Skip to content

feat: add agent exec pkg #15577

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 17 commits into from
Nov 25, 2024
Prev Previous commit
Next Next commit
fixup some test stuff
  • Loading branch information
sreya committed Nov 18, 2024
commit 196c8a90797324439de3d5d8368130fc49d18077
6 changes: 6 additions & 0 deletions agent/agentexec/cli.go
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,12 @@
return xerrors.Errorf("agent-exec is only supported on Linux")
}

if len(args) < 2 {
return xerrors.Errorf("malformed command %q", args)
}

args = args[2:]

pid := os.Getpid()

oomScore, ok := envVal(environ, EnvProcOOMScore)
Expand All @@ -41,7 +47,7 @@
return xerrors.Errorf("invalid nice score: %w", err)
}

err = syscall.Setpriority(syscall.PRIO_PROCESS, pid, score)

Check failure on line 50 in agent/agentexec/cli.go

View workflow job for this annotation

GitHub Actions / test-go (windows-2022)

undefined: syscall.Setpriority

Check failure on line 50 in agent/agentexec/cli.go

View workflow job for this annotation

GitHub Actions / test-go (windows-2022)

undefined: syscall.PRIO_PROCESS

Check failure on line 50 in agent/agentexec/cli.go

View workflow job for this annotation

GitHub Actions / test-go (windows-2022)

undefined: syscall.Setpriority

Check failure on line 50 in agent/agentexec/cli.go

View workflow job for this annotation

GitHub Actions / test-go (windows-2022)

undefined: syscall.PRIO_PROCESS
if err != nil {
return xerrors.Errorf("set nice score: %w", err)
}
Expand Down
46 changes: 33 additions & 13 deletions agent/agentexec/cli_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,10 +6,12 @@
"fmt"
"os"
"os/exec"
"path/filepath"
"strconv"
"strings"
"syscall"
"testing"
"time"

"github.com/stretchr/testify/require"
"golang.org/x/sys/unix"
Expand All @@ -23,13 +25,14 @@
t.Parallel()

ctx := testutil.Context(t, testutil.WaitMedium)
cmd, dir := cmd(t, ctx)
cmd, path := cmd(ctx, t)
cmd.Env = append(cmd.Env, "CODER_PROC_NICE_SCORE=10")
cmd.Env = append(cmd.Env, "CODER_PROC_OOM_SCORE=123")
err := cmd.Start()
require.NoError(t, err)
go cmd.Wait()

waitForSentinel(t, ctx, cmd, dir)
waitForSentinel(t, ctx, cmd, path)
requireOOMScore(t, cmd.Process.Pid, 123)
requireNiceScore(t, cmd.Process.Pid, 10)
})
Expand All @@ -38,7 +41,7 @@
func requireNiceScore(t *testing.T, pid int, score int) {
t.Helper()

nice, err := unix.Getpriority(0, pid)

Check failure on line 44 in agent/agentexec/cli_test.go

View workflow job for this annotation

GitHub Actions / test-go (windows-2022)

undefined: unix.Getpriority

Check failure on line 44 in agent/agentexec/cli_test.go

View workflow job for this annotation

GitHub Actions / test-go (windows-2022)

undefined: unix.Getpriority
require.NoError(t, err)
require.Equal(t, score, nice)
}
Expand All @@ -52,27 +55,40 @@
require.Equal(t, strconv.Itoa(expected), score)
}

func waitForSentinel(t *testing.T, ctx context.Context, cmd *exec.Cmd, dir string) {
func waitForSentinel(t *testing.T, ctx context.Context, cmd *exec.Cmd, path string) {
t.Helper()

require.Eventually(t, func() bool {
// Check if the process is still running.
ticker := time.NewTicker(testutil.IntervalFast)
defer ticker.Stop()

// RequireEventually doesn't work well with require.NoError or similar require functions.
for {
err := cmd.Process.Signal(syscall.Signal(0))
require.NoError(t, err)

_, err = os.Stat(dir)
return err == nil && ctx.Err() == nil
}, testutil.WaitLong, testutil.IntervalFast)
_, err = os.Stat(path)
if err == nil {
return
}

select {
case <-ticker.C:
case <-ctx.Done():
return
}
}
}

func cmd(t *testing.T, ctx context.Context, args ...string) (*exec.Cmd, string) {
dir := ""
func cmd(ctx context.Context, t *testing.T, args ...string) (*exec.Cmd, string) {
file := ""
cmd := exec.Command(TestBin, args...)
if len(args) == 0 {
dir = t.TempDir()
dir := t.TempDir()
file = filepath.Join(dir, uniqueFile(t))
//nolint:gosec
cmd = exec.CommandContext(ctx, TestBin, "sh", "-c", fmt.Sprintf("touch %s && sleep 10m", dir))
cmd = exec.CommandContext(ctx, TestBin, "agent-exec", "sh", "-c", fmt.Sprintf("touch %s && sleep 10m", file))
}
cmd.Env = os.Environ()
var buf bytes.Buffer
cmd.Stdout = &buf
cmd.Stderr = &buf
Expand All @@ -86,5 +102,9 @@
_ = cmd.Process.Kill()
}
})
return cmd, dir
return cmd, file
}

func uniqueFile(t *testing.T) string {
return fmt.Sprintf("%s-%d", strings.ReplaceAll(t.Name(), "/", "_"), time.Now().UnixNano())
}
Loading