Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions go/action_kit_commons/CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,9 @@
# Changelog

## 1.5.15

- Add filldisk helpers to validate target directory

## 1.5.14

- Set OOM score adjustment in disc fill command
Expand Down
19 changes: 17 additions & 2 deletions go/action_kit_commons/diskfill/diskfill_process.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,13 +7,14 @@ package diskfill
import (
"context"
"fmt"
"github.com/rs/zerolog/log"
"github.com/steadybit/action-kit/go/action_kit_commons/utils"
"os/exec"
"path/filepath"
"strconv"
"strings"
"time"

"github.com/rs/zerolog/log"
"github.com/steadybit/action-kit/go/action_kit_commons/utils"
)

type diskfillProcess struct {
Expand Down Expand Up @@ -92,3 +93,17 @@ func (df *diskfillProcess) Args() []string {
func (df *diskfillProcess) Noop() bool {
return df.cmd.Args[0] == "echo" && df.cmd.Args[1] == "noop"
}

func CheckPathWritableProcess(ctx context.Context, targetPath string) error {
if out, err := utils.RootCommandContext(ctx, "test", "-d", targetPath).CombinedOutput(); err != nil {
return fmt.Errorf("target path %q does not exist: %w: %s", targetPath, err, string(out))
}

checkFile := filepath.Join(targetPath, ".steadybit-diskfill-check")
if out, err := utils.RootCommandContext(ctx, "touch", checkFile).CombinedOutput(); err != nil {
return fmt.Errorf("target path %q is not writable: %w: %s", targetPath, err, string(out))
}

_ = utils.RootCommandContext(ctx, "rm", "-f", checkFile).Run()
return nil
}
27 changes: 26 additions & 1 deletion go/action_kit_commons/diskfill/diskfill_runc.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
package diskfill

import (
"bytes"
"context"
"fmt"
"path/filepath"
Expand Down Expand Up @@ -142,7 +143,7 @@ func createBundle(ctx context.Context, r ociruntime.OciRuntime, sidecar SidecarO

if targetPath != "" {
if err := bundle.MountFromProcess(ctx, sidecar.TargetProcess.Pid, targetPath, mountpointInContainer); err != nil {
log.Warn().Err(err).Msgf("failed to mount %s", targetPath)
return nil, err
}
}

Expand Down Expand Up @@ -183,6 +184,30 @@ func createBundle(ctx context.Context, r ociruntime.OciRuntime, sidecar SidecarO
return bundle, nil
}

func CheckPathWritableRunc(ctx context.Context, r ociruntime.OciRuntime, sidecar SidecarOpts, targetPath string) error {
bundle, err := createBundle(ctx, r, sidecar, targetPath, "sh", "-c", fmt.Sprintf("test -d %s && touch %s/.steadybit-diskfill-check && rm -f %s/.steadybit-diskfill-check", mountpointInContainer, mountpointInContainer, mountpointInContainer))
if err != nil {
return fmt.Errorf("target path %q is not accessible: %w", targetPath, err)
}
defer func() {
if err := bundle.Remove(); err != nil {
log.Warn().Str("id", bundle.ContainerId()).Err(err).Msg("failed to remove bundle")
}
}()

var errb bytes.Buffer
err = r.Run(ctx, bundle, ociruntime.IoOpts{Stderr: &errb})
defer func() {
if err := r.Delete(context.Background(), bundle.ContainerId(), true); err != nil {
log.Debug().Str("id", bundle.ContainerId()).Err(err).Msg("failed to delete check container")
}
}()
if err != nil {
return fmt.Errorf("target path %q does not exist or is not writable: %w: %s", targetPath, err, errb.String())
}
return nil
}

func getNextContainerId(executionId uuid.UUID, suffix string) string {
return fmt.Sprintf("sb-diskfill-%d-%s-%s", time.Now().UnixMilli(), utils.ShortenUUID(executionId), suffix)
}
Expand Down
4 changes: 1 addition & 3 deletions go/action_kit_commons/diskfill/read_diskspace.go
Original file line number Diff line number Diff line change
Expand Up @@ -68,9 +68,7 @@ func readDiskUsageProcess(ctx context.Context, path string) (*DiskUsage, error)
var outb, errb bytes.Buffer
cmd.Stdout = &outb
cmd.Stderr = &errb

err := cmd.Run()
if err != nil {
if err := cmd.Run(); err != nil {
return nil, fmt.Errorf("failed to read disk usage: %w: %s", err, errb.String())
}

Expand Down
2 changes: 0 additions & 2 deletions go/action_kit_commons/network/dig_runner.go
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,6 @@ import (
"github.com/steadybit/action-kit/go/action_kit_commons/utils"
"io"
"os/exec"
"runtime/trace"
)

type DigRunner interface {
Expand Down Expand Up @@ -50,7 +49,6 @@ type RuncDigRunner struct {
var _ DigRunner = (*RuncDigRunner)(nil)

func (r *RuncDigRunner) Run(ctx context.Context, arg []string, stdin io.Reader) ([]byte, error) {
defer trace.StartRegion(ctx, "RuncDigRunner.Run").End()
id := getNextContainerId(r.Sidecar.ExecutionId, "dig", r.Sidecar.IdSuffix)

bundle, err := r.Runc.Create(ctx, "/", id)
Expand Down
33 changes: 11 additions & 22 deletions go/action_kit_commons/ociruntime/container_bundle.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,16 +5,15 @@
package ociruntime

import (
"bytes"
"context"
"errors"
"fmt"
"github.com/rs/zerolog/log"
"github.com/steadybit/action-kit/go/action_kit_commons/utils"
"os"
"path/filepath"
"runtime/trace"
"strconv"

"github.com/rs/zerolog/log"
"github.com/steadybit/action-kit/go/action_kit_commons/utils"
)

type containerBundle struct {
Expand Down Expand Up @@ -86,38 +85,28 @@ func (b *containerBundle) mountRootfsOverlay(ctx context.Context, image string)
}

func (b *containerBundle) CopyFileFromProcess(ctx context.Context, pid int, fromPath, toPath string) error {
defer trace.StartRegion(ctx, "utils.CopyFileFromProcessToBundle").End()
var out bytes.Buffer
cmd := utils.RootCommandContext(ctx, "cat", filepath.Join("/proc", strconv.Itoa(pid), "root", fromPath))
cmd.Stdout = &out
cmd.Stderr = &out
if err := cmd.Run(); err != nil {
return fmt.Errorf("%w: %s", err, out.String())
out, err := utils.RootCommandContext(ctx, "cat", filepath.Join("/proc", strconv.Itoa(pid), "root", fromPath)).CombinedOutput()
if err != nil {
return fmt.Errorf("failed to mount %s (%w): %s", fromPath, err, out)
}

return os.WriteFile(filepath.Join(b.path, "rootfs", toPath), out.Bytes(), 0644)
return os.WriteFile(filepath.Join(b.path, "rootfs", toPath), out, 0644)
}

func (b *containerBundle) MountFromProcess(ctx context.Context, fromPid int, fromPath, toPath string) error {
defer trace.StartRegion(ctx, "utils.MountFromProcessToBundle").End()

mountpoint := filepath.Join(b.path, "rootfs", toPath)
log.Trace().
Int("fromPid", fromPid).
Str("fromPath", fromPath).
Str("mountpoint", mountpoint).
Str("mount-point", mountpoint).
Msg("mount from process to bundle")

if err := os.Mkdir(mountpoint, 0755); err != nil && !os.IsExist(err) {
return fmt.Errorf("failed to create mountpoint %s: %w", mountpoint, err)
return fmt.Errorf("failed to create mount point %s: %w", mountpoint, err)
}

var out bytes.Buffer
cmd := utils.RootCommandContext(ctx, nsmountPath, strconv.Itoa(fromPid), fromPath, strconv.Itoa(os.Getpid()), mountpoint)
cmd.Stdout = &out
cmd.Stderr = &out
if err := cmd.Run(); err != nil {
return fmt.Errorf("%w: %s", err, out.String())
if out, err := utils.RootCommandContext(ctx, nsmountPath, strconv.Itoa(fromPid), fromPath, strconv.Itoa(os.Getpid()), mountpoint).CombinedOutput(); err != nil {
return fmt.Errorf("failed to mount %s (%w): %s", fromPath, err, out)
}
b.addFinalizer(func() error {
return unmount(context.Background(), mountpoint)
Expand Down
15 changes: 6 additions & 9 deletions go/action_kit_commons/ociruntime/utils.go
Original file line number Diff line number Diff line change
Expand Up @@ -515,19 +515,16 @@ func searchNamespacePathInProcess(ctx context.Context, inode uint64, nsType spec
}

func readCgroupPath(ctx context.Context, pid int) (string, error) {
var out bytes.Buffer
cmd := utils.RootCommandContext(ctx, nsenterPath, "-t", "1", "-C", "--", "cat", filepath.Join("/proc", strconv.Itoa(pid), "cgroup"))
cmd.Stdout = &out
cmd.Stderr = &out
if err := cmd.Run(); err != nil {
return "", fmt.Errorf("%w: %s", err, out.String())
out, err := utils.RootCommandContext(ctx, nsenterPath, "-t", "1", "-C", "--", "cat", filepath.Join("/proc", strconv.Itoa(pid), "cgroup")).CombinedOutput()
if err != nil {
return "", fmt.Errorf("%w: %s", err, out)
}

if cgroup := parseProcCgroupFile(out.String()); cgroup != "" {
if cgroup := parseProcCgroupFile(string(out)); cgroup != "" {
return cgroup, nil
} else {
return "", fmt.Errorf("failed to read cgroup for pid %d\n%s", pid, out.String())
}

return "", fmt.Errorf("failed to read cgroup for pid %d\n%s", pid, out)
}

func parseProcCgroupFile(s string) string {
Expand Down
Loading