From 658c429d75e405b5a30880b6a8d90b80196cc2a5 Mon Sep 17 00:00:00 2001 From: Michael Smithhisler Date: Fri, 1 Nov 2024 11:04:40 -0400 Subject: [PATCH] Drivers: add work_dir config to exec/raw_exec/java drivers (#24249) --------- Co-authored-by: wurosh Co-authored-by: Michael Schurter Co-authored-by: Tim Gross --- .changelog/24249.txt | 3 + drivers/exec/driver.go | 9 + drivers/exec/driver_test.go | 61 +++++++ drivers/java/driver.go | 8 + drivers/java/driver_test.go | 58 +++++++ drivers/java/test-resources/Hello.class | Bin 728 -> 1256 bytes drivers/java/test-resources/Hello.java | 2 +- drivers/java/test-resources/demoapp.jar | Bin 952 -> 1174 bytes drivers/rawexec/driver.go | 36 ++-- drivers/rawexec/driver_test.go | 98 ++++++++++- drivers/rawexec/driver_unix_test.go | 33 ---- drivers/shared/executor/executor.go | 12 +- drivers/shared/executor/executor_linux.go | 4 +- .../shared/executor/executor_linux_test.go | 29 ++++ drivers/shared/executor/grpc_client.go | 1 + drivers/shared/executor/grpc_server.go | 1 + drivers/shared/executor/proto/executor.pb.go | 161 +++++++++--------- drivers/shared/executor/proto/executor.proto | 1 + website/content/docs/drivers/exec.mdx | 5 + website/content/docs/drivers/java.mdx | 7 + website/content/docs/drivers/raw_exec.mdx | 4 + 21 files changed, 408 insertions(+), 125 deletions(-) create mode 100644 .changelog/24249.txt diff --git a/.changelog/24249.txt b/.changelog/24249.txt new file mode 100644 index 00000000000..419bd8bb33b --- /dev/null +++ b/.changelog/24249.txt @@ -0,0 +1,3 @@ +```release-note:improvement +drivers: Add work_dir config to exec/rawexec/java drivers for setting the working directory of processes in a task +``` diff --git a/drivers/exec/driver.go b/drivers/exec/driver.go index caad707d9ad..70d2b43c2c2 100644 --- a/drivers/exec/driver.go +++ b/drivers/exec/driver.go @@ -97,6 +97,7 @@ var ( "ipc_mode": hclspec.NewAttr("ipc_mode", "string", false), "cap_add": hclspec.NewAttr("cap_add", "list(string)", false), "cap_drop": hclspec.NewAttr("cap_drop", "list(string)", false), + "work_dir": hclspec.NewAttr("work_dir", "string", false), }) // driverCapabilities represents the RPC response for what features are @@ -211,6 +212,9 @@ type TaskConfig struct { // CapDrop is a set of linux capabilities to disable. CapDrop []string `codec:"cap_drop"` + + // WorkDir is the working directory inside the chroot + WorkDir string `codec:"work_dir"` } func (tc *TaskConfig) validate() error { @@ -237,6 +241,10 @@ func (tc *TaskConfig) validate() error { return fmt.Errorf("cap_drop configured with capabilities not supported by system: %s", badDrops) } + if tc.WorkDir != "" && !filepath.IsAbs(tc.WorkDir) { + return fmt.Errorf("work_dir must be absolute but got relative path %q", tc.WorkDir) + } + return nil } @@ -517,6 +525,7 @@ func (d *Driver) StartTask(cfg *drivers.TaskConfig) (*drivers.TaskHandle, *drive NoPivotRoot: d.config.NoPivotRoot, Resources: cfg.Resources, TaskDir: cfg.TaskDir().Dir, + WorkDir: driverConfig.WorkDir, StdoutPath: cfg.StdoutPath, StderrPath: cfg.StderrPath, Mounts: cfg.Mounts, diff --git a/drivers/exec/driver_test.go b/drivers/exec/driver_test.go index cd275bc87f2..9b1d86bb41d 100644 --- a/drivers/exec/driver_test.go +++ b/drivers/exec/driver_test.go @@ -19,6 +19,7 @@ import ( "time" "github.com/hashicorp/nomad/ci" + "github.com/hashicorp/nomad/client/allocdir" "github.com/hashicorp/nomad/client/lib/cgroupslib" "github.com/hashicorp/nomad/client/lib/numalib" ctestutils "github.com/hashicorp/nomad/client/testutil" @@ -127,6 +128,50 @@ func TestExecDriver_Fingerprint(t *testing.T) { } } +func TestExecDriver_WorkDir(t *testing.T) { + ci.Parallel(t) + + ctestutils.ExecCompatible(t) + + ctx, cancel := context.WithCancel(context.Background()) + defer cancel() + + d := newExecDriverTest(t, ctx) + harness := dtestutil.NewDriverHarness(t, d) + allocID := uuid.Generate() + task := &drivers.TaskConfig{ + AllocID: allocID, + ID: uuid.Generate(), + Name: "test", + Resources: testResources(allocID, "test"), + } + + workDir := filepath.Join("/", allocdir.TaskLocal) + tc := &TaskConfig{ + Command: "/bin/cat", + Args: []string{"foo.txt"}, + WorkDir: workDir, + } + must.NoError(t, task.EncodeConcreteDriverConfig(&tc)) + + cleanup := harness.MkAllocDir(task, false) + defer cleanup() + + must.NoError(t, os.WriteFile(filepath.Join(task.TaskDir().Dir, allocdir.TaskLocal, "foo.txt"), []byte("foo"), 660)) + + handle, _, err := harness.StartTask(task) + must.NoError(t, err) + + ch, err := harness.WaitTask(context.Background(), handle.Config.ID) + must.NoError(t, err) + + // Task will fail if cat cannot find the file, which would only happen + // if the task's WorkDir was setup incorrectly + result := <-ch + must.Zero(t, result.ExitCode) + must.NoError(t, harness.DestroyTask(task.ID, true)) +} + func TestExecDriver_StartWait(t *testing.T) { ci.Parallel(t) ctestutils.ExecCompatible(t) @@ -735,11 +780,13 @@ func TestConfig_ParseAllHCL(t *testing.T) { config { command = "/bin/bash" args = ["-c", "echo hello"] + work_dir = "/root" }` expected := &TaskConfig{ Command: "/bin/bash", Args: []string{"-c", "echo hello"}, + WorkDir: "/root", } var tc *TaskConfig @@ -1013,4 +1060,18 @@ func TestDriver_TaskConfig_validate(t *testing.T) { }).validate()) } }) + + t.Run("work_dir", func(t *testing.T) { + for _, tc := range []struct { + workDir string + exp error + }{ + {workDir: "/foo", exp: nil}, + {workDir: "foo", exp: errors.New(`work_dir must be absolute but got relative path "foo"`)}, + } { + must.Eq(t, tc.exp, (&TaskConfig{ + WorkDir: tc.workDir, + }).validate()) + } + }) } diff --git a/drivers/java/driver.go b/drivers/java/driver.go index 829f59f6565..99575d77853 100644 --- a/drivers/java/driver.go +++ b/drivers/java/driver.go @@ -98,6 +98,7 @@ var ( "ipc_mode": hclspec.NewAttr("ipc_mode", "string", false), "cap_add": hclspec.NewAttr("cap_add", "list(string)", false), "cap_drop": hclspec.NewAttr("cap_drop", "list(string)", false), + "work_dir": hclspec.NewAttr("work_dir", "string", false), }) // driverCapabilities is returned by the Capabilities RPC and indicates what @@ -189,6 +190,9 @@ type TaskConfig struct { // CapDrop is a set of linux capabilities to disable. CapDrop []string `codec:"cap_drop"` + + // WorkDir is the working directory for the task + WorkDir string `coded:"work_dir"` } func (tc *TaskConfig) validate() error { @@ -215,6 +219,9 @@ func (tc *TaskConfig) validate() error { return fmt.Errorf("cap_drop configured with capabilities not supported by system: %s", badDrops) } + if tc.WorkDir != "" && !filepath.IsAbs(tc.WorkDir) { + return fmt.Errorf("work_dir must be an absolute path: %s", tc.WorkDir) + } return nil } @@ -496,6 +503,7 @@ func (d *Driver) StartTask(cfg *drivers.TaskConfig) (*drivers.TaskHandle, *drive ResourceLimits: true, Resources: cfg.Resources, TaskDir: cfg.TaskDir().Dir, + WorkDir: driverConfig.WorkDir, StdoutPath: cfg.StdoutPath, StderrPath: cfg.StderrPath, Mounts: cfg.Mounts, diff --git a/drivers/java/driver_test.go b/drivers/java/driver_test.go index bc050755d0c..35c467f9418 100644 --- a/drivers/java/driver_test.go +++ b/drivers/java/driver_test.go @@ -25,6 +25,7 @@ import ( "github.com/hashicorp/nomad/plugins/drivers" dtestutil "github.com/hashicorp/nomad/plugins/drivers/testutils" "github.com/hashicorp/nomad/testutil" + "github.com/shoenig/test/must" "github.com/stretchr/testify/require" ) @@ -209,6 +210,49 @@ func TestJavaDriver_Class_Start_Wait(t *testing.T) { require.NoError(t, harness.DestroyTask(task.ID, true)) } +func TestJavaDriver_WorkDir(t *testing.T) { + ci.Parallel(t) + javaCompatible(t) + + ctx, cancel := context.WithCancel(context.Background()) + defer cancel() + + d := newJavaDriverTest(t, ctx) + + harness := dtestutil.NewDriverHarness(t, d) + + tc := &TaskConfig{ + JarPath: "../demoapp.jar", + Args: []string{"1"}, + JvmOpts: []string{"-Xmx64m", "-Xms32m"}, + WorkDir: "/local", + } + + task := basicTask(t, "demo-app", tc) + + cleanup := harness.MkAllocDir(task, true) + defer cleanup() + + copyFile("./test-resources/demoapp.jar", filepath.Join(task.TaskDir().Dir, "demoapp.jar"), t) + + handle, _, err := harness.StartTask(task) + must.NoError(t, err) + + ch, err := harness.WaitTask(context.Background(), handle.Config.ID) + must.NoError(t, err) + result := <-ch + must.Nil(t, result.Err) + + must.Zero(t, result.ExitCode) + + // Get the stdout of the process and assert that it's not empty + stdout, err := os.ReadFile(filepath.Join(task.TaskDir().LogDir, "demo-app.stdout.0")) + must.NoError(t, err) + must.Eq(t, string(stdout), "Hello, the current working directory is: /local\n") + + must.NoError(t, harness.DestroyTask(task.ID, true)) +} + func TestJavaCmdArgs(t *testing.T) { ci.Parallel(t) @@ -521,4 +565,18 @@ func TestDriver_TaskConfig_validate(t *testing.T) { }).validate()) } }) + + t.Run("work_dir", func(t *testing.T) { + for _, tc := range []struct { + workDir string + exp error + }{ + {workDir: "/goodpath", exp: nil}, + {workDir: "badpath", exp: errors.New("work_dir must be an absolute path: badpath")}, + } { + require.Equal(t, tc.exp, (&TaskConfig{ + WorkDir: tc.workDir, + }).validate()) + } + }) } diff --git a/drivers/java/test-resources/Hello.class b/drivers/java/test-resources/Hello.class index d55f78e76eee1a200cdc812e4a0ae41b5a3f9874..448f71b564a36967ec9ce42c77003971b56041e8 100644 GIT binary patch literal 1256 zcmZ`&+foxj5IvJXHrXtMJ0glfxrBg3@J`~52oeRQDwIC>G$d2WlFjbc>;&c6@*ngI ze8vZ)c;Ey45$ss~3ey^9d^_teDGhTP(hQNDX`AXXLpU|}mZ2-}lm$a#)3n9wMtxVv9lmRk zr>o9Qn_(pNeshoS^NhvqN~Wl!X;-p-Voy==Qf-U7t$4lYG-OGvn|`vsAuP*T^b-yA zBB5d4zyfYEL>r!vi)B+9SVV@QZ`E;>rzCf`gsM7aFA>45D3%N?BctKAfjhXX;hsUX zA82@JUq_L40`bX7XtI&6RmypcaG1L~v|NAq*Ld~wF{0m~ZyiHFLi~^_Okfsisuv3C&(IEt zQeFQB9ixa-L@&kkQ&a-;bh1PzLlhN9_%|llD-E#-0T?D%2qSn-R;R+NSVtaXxDpg( H0i%h(YVAN2 delta 324 zcmWlTJx;?w5JsQ9vDe;g0tsLU353KDh{JE7L2`$LkPtl=K%$7m0Vt?AK;#N>0BR_r zh$00gC*TM<1VYTNG&7oS-+VLk_$N63{`;H(XPg?!Br&V3MKlcSGz~2_44bqyTdsCo z>S`LAbbN8EL>|Ak29}Cu+proo`PZ5toRP><>f>g@}c*LK#xZZTfOdU9d9hm&Ci) MEV+A@Me`P*wXP+#GF^x(s6{K?aQp9j#qrPY{rmd;2g?EHoEI;Sd8n^TFlkzC zb#h~!(VYu|$9MG2-mx^9X|mL^8q2r;g{0Cd*ZUaXMF2tCt7?=ES@j_Van0Bdqey@FW>Y2-FMgW=;x)n@60|_om+Wg zPlR#v>0KLi((jdkHe?1N-Gkbd&A32wGYs1tDn;vNeM*N*3zRpPYwnIIeKaY;` zsSAQvoMxVjx%ci}_nxevr>o`(r6wI+IU#Yyz0EI|Y+IS=n#&!xY)fplQ?B=M(V$St zWkR|ucCNVeQRKYDBuCle!cdWqHLhNXtADt=Pva0$w_Bm$9`<NRGC#~UYCJ6$q}(X(~D?tRB>mc}j3pmj`w zuOgjxY*FkCKd59f%hHrz?Obudb)nL^&tA?kvH8Ay_bG$IHsiO<%T=UizV2QBu|bGe zKQr50c6rFcCCA!wxo2+O@tia1@#~+PqzzwnZ#nn2Np(->uH;`y<@k$I7p!JS*$O50BUU$r)KcJxC7zGk^S|F<^&eBb$RZ^>@INfY0A{A00R z!rVLa-$MsUH}zkJ7aHo+t_z$zDxdM1|LTRh9=-=04?WZ>Kk-%>ZHZ`}_LBRroOazx z#ZR)o!gzlP?&8yQ;<@Y*v}c>bKasf&97n$zzmRYgSM;yqxa__{BkklShiQ&ZrHWtJ z4ZlS>r_bP$;Hr{1#y!c3HSVC)CW)h46%@Fwy8beQ^1+Vi-@8vTF)+Mf0p$ZmCJ_ci y)|&i>$($FIx8Rv&vIDcJGbocFYXfBx1ULa?B4wEXZ&o&tBr_0h1Jb9MK|BD(Oq7@a delta 760 zcmbQnxr3cAz?+#xgn@&DgW-1HH?N6&mMmb}+pV56;)Uc9X(=hqj345vYR{KwSv(gP zeIl+pjp1tcr=p)~Y0q9-Jy#JEkJhYM^6bfz&qW`L7#RY***WCihnj{nFfc>_F~az4 zpz%NfIN%1dJW_LV^7WE)5{rvVgAN8=4iK^J-%|ThIh1QlS3L)Z#*)C5P1aU(A7mRYL6b-Qd-~CbobLaJLigP&p3{TUHxTP{~@#Gl6c2m z!8gKF`a2_!3xyr%%zn1+qRRylX;z_-B~hIMsfR3Dgd$WY@(P*zuJDYo4@}p$OzW9* zGp72jIVfdRJGoxJ%gDfRg9(%}7@0&E5J?Y|Fo42fz{$YEF!>d;Ixi?K!jscvITllA hP%=U`29%5t;2MyLl&Au{S=m66%s{veNWTGF00162H01yQ diff --git a/drivers/rawexec/driver.go b/drivers/rawexec/driver.go index 39493e16948..b98f0bf767e 100644 --- a/drivers/rawexec/driver.go +++ b/drivers/rawexec/driver.go @@ -94,6 +94,7 @@ var ( "cgroup_v2_override": hclspec.NewAttr("cgroup_v2_override", "string", false), "cgroup_v1_override": hclspec.NewAttr("cgroup_v1_override", "list(map(string))", false), "oom_score_adj": hclspec.NewAttr("oom_score_adj", "number", false), + "work_dir": hclspec.NewAttr("work_dir", "string", false), }) // capabilities is returned by the Capabilities RPC and indicates what @@ -172,6 +173,25 @@ type TaskConfig struct { // OOMScoreAdj sets the oom_score_adj on Linux systems OOMScoreAdj int `codec:"oom_score_adj"` + + // WorkDir sets the working directory of the task + WorkDir string `codec:"work_dir"` +} + +func (t *TaskConfig) validate() error { + // ensure only one of cgroups_v1_override and cgroups_v2_override have been + // configured; must check here because task config validation cannot happen + // on the server. + if len(t.OverrideCgroupV1) > 0 && t.OverrideCgroupV2 != "" { + return errors.New("only one of cgroups_v1_override and cgroups_v2_override may be set") + } + if t.OOMScoreAdj < 0 { + return errors.New("oom_score_adj must not be negative") + } + if t.WorkDir != "" && !filepath.IsAbs(t.WorkDir) { + return errors.New("work_dir must be an absolute path") + } + return nil } // TaskState is the state which is encoded in the handle returned in @@ -352,8 +372,10 @@ func (d *Driver) StartTask(cfg *drivers.TaskConfig) (*drivers.TaskHandle, *drive return nil, nil, fmt.Errorf("failed to decode driver config: %v", err) } - if driverConfig.OOMScoreAdj < 0 { - return nil, nil, fmt.Errorf("oom_score_adj must not be negative") + driverConfig.OverrideCgroupV2 = cgroupslib.CustomPathCG2(driverConfig.OverrideCgroupV2) + + if err := driverConfig.validate(); err != nil { + return nil, nil, fmt.Errorf("failed driver config validation: %v", err) } if err := d.Validate(*cfg); err != nil { @@ -383,22 +405,16 @@ func (d *Driver) StartTask(cfg *drivers.TaskConfig) (*drivers.TaskHandle, *drive Env: cfg.EnvList(), User: cfg.User, TaskDir: cfg.TaskDir().Dir, + WorkDir: driverConfig.WorkDir, StdoutPath: cfg.StdoutPath, StderrPath: cfg.StderrPath, NetworkIsolation: cfg.NetworkIsolation, Resources: cfg.Resources.Copy(), - OverrideCgroupV2: cgroupslib.CustomPathCG2(driverConfig.OverrideCgroupV2), + OverrideCgroupV2: driverConfig.OverrideCgroupV2, OverrideCgroupV1: driverConfig.OverrideCgroupV1, OOMScoreAdj: int32(driverConfig.OOMScoreAdj), } - // ensure only one of cgroups_v1_override and cgroups_v2_override have been - // configured; must check here because task config validation cannot happen - // on the server. - if len(execCmd.OverrideCgroupV1) > 0 && execCmd.OverrideCgroupV2 != "" { - return nil, nil, errors.New("only one of cgroups_v1_override and cgroups_v2_override may be set") - } - ps, err := exec.Launch(execCmd) if err != nil { pluginClient.Kill() diff --git a/drivers/rawexec/driver_test.go b/drivers/rawexec/driver_test.go index 693eac2d3dd..887367ae772 100644 --- a/drivers/rawexec/driver_test.go +++ b/drivers/rawexec/driver_test.go @@ -462,7 +462,6 @@ func TestRawExecDriver_ParentCgroup(t *testing.T) { func TestRawExecDriver_Exec(t *testing.T) { ci.Parallel(t) - ctestutil.ExecCompatible(t) require := require.New(t) @@ -506,7 +505,7 @@ func TestRawExecDriver_Exec(t *testing.T) { res, err = harness.ExecTask(task.ID, []string{"cmd.exe", "/c", "stat", "notarealfile123abc"}, 1*time.Second) require.NoError(err) require.False(res.ExitResult.Successful()) - require.Contains(string(res.Stdout), "not recognized") + require.Contains(string(res.Stdout), "No such file or directory") } else { // Exec a command that should work res, err := harness.ExecTask(task.ID, []string{"/usr/bin/stat", "/tmp"}, 1*time.Second) @@ -524,6 +523,59 @@ func TestRawExecDriver_Exec(t *testing.T) { require.NoError(harness.DestroyTask(task.ID, true)) } +func TestRawExecDriver_WorkDir(t *testing.T) { + ci.Parallel(t) + + d := newEnabledRawExecDriver(t) + harness := dtestutil.NewDriverHarness(t, d) + defer harness.Kill() + + allocID := uuid.Generate() + taskName := "test" + task := &drivers.TaskConfig{ + AllocID: allocID, + ID: uuid.Generate(), + Name: taskName, + Env: defaultEnv(), + Resources: testResources(allocID, taskName), + } + + workDir := t.TempDir() + + tc := &TaskConfig{ + WorkDir: workDir, + } + if runtime.GOOS == "windows" { + tc.Command = "cmd.exe" + tc.Args = []string{"/c", "stat", "foo.txt"} + } else { + tc.Command = "/usr/bin/stat" + tc.Args = []string{"foo.txt"} + } + + must.NoError(t, task.EncodeConcreteDriverConfig(&tc)) + testtask.SetTaskConfigEnv(task) + + cleanup := harness.MkAllocDir(task, false) + defer cleanup() + + harness.MakeTaskCgroup(allocID, taskName) + + must.NoError(t, os.WriteFile(filepath.Join(workDir, "foo.txt"), []byte("foo"), 770)) + + handle, _, err := harness.StartTask(task) + must.NoError(t, err) + + ch, err := harness.WaitTask(context.Background(), handle.Config.ID) + must.NoError(t, err) + + // Task will fail if cat cannot find the file, which would only happen + // if the task's WorkDir was setup incorrectly + result := <-ch + must.Zero(t, result.ExitCode) + must.NoError(t, harness.DestroyTask(task.ID, true)) +} + func TestConfig_ParseAllHCL(t *testing.T) { ci.Parallel(t) @@ -568,3 +620,45 @@ func TestRawExecDriver_Disabled(t *testing.T) { require.Contains(err.Error(), errDisabledDriver.Error()) require.Nil(handle) } + +func TestRawExecDriver_validate(t *testing.T) { + ci.Parallel(t) + + testCases := []struct { + name string + config *TaskConfig + exp error + }{ + { + name: "validates CGroup overrides", + config: &TaskConfig{ + OverrideCgroupV2: "custom.slice/app.scope", + OverrideCgroupV1: map[string]string{ + "pids": "custom/path", + }, + }, + exp: errors.New("only one of cgroups_v1_override and cgroups_v2_override may be set"), + }, + { + name: "validates OOM score adj", + config: &TaskConfig{ + OOMScoreAdj: -1, + }, + exp: errors.New("oom_score_adj must not be negative"), + }, + { + name: "validates work_dir is abolute path", + config: &TaskConfig{ + WorkDir: "bad/path", + }, + exp: errors.New("work_dir must be an absolute path"), + }, + } + + for _, i := range testCases { + t.Run(i.name, func(t *testing.T) { + err := i.config.validate() + must.Eq(t, i.exp, err) + }) + } +} diff --git a/drivers/rawexec/driver_unix_test.go b/drivers/rawexec/driver_unix_test.go index 6912590a3cc..8512f5562c3 100644 --- a/drivers/rawexec/driver_unix_test.go +++ b/drivers/rawexec/driver_unix_test.go @@ -30,7 +30,6 @@ import ( "github.com/hashicorp/nomad/plugins/drivers" dtestutil "github.com/hashicorp/nomad/plugins/drivers/testutils" "github.com/hashicorp/nomad/testutil" - "github.com/shoenig/test/must" "github.com/stretchr/testify/require" "golang.org/x/sys/unix" ) @@ -65,38 +64,6 @@ func TestRawExecDriver_User(t *testing.T) { require.Contains(err.Error(), msg) } -func TestRawExecDriver_ValidateCgroupOverrides(t *testing.T) { - ci.Parallel(t) - clienttestutil.RequireLinux(t) - - d := newEnabledRawExecDriver(t) - harness := dtestutil.NewDriverHarness(t, d) - - task := &drivers.TaskConfig{ - ID: uuid.Generate(), - Name: "sleep", - User: "nobody", - } - - cleanup := harness.MkAllocDir(task, false) - defer cleanup() - - tc := &TaskConfig{ - Command: "sleep", - Args: []string{"infinity"}, - OverrideCgroupV2: "custom.slice/app.scope", - OverrideCgroupV1: map[string]string{ - "pids": "custom/path", - }, - } - - must.NoError(t, task.EncodeConcreteDriverConfig(&tc)) - testtask.SetTaskConfigEnv(task) - - _, _, err := harness.StartTask(task) - must.ErrorContains(t, err, "only one of cgroups_v1_override and cgroups_v2_override may be set") -} - func TestRawExecDriver_Signal(t *testing.T) { ci.Parallel(t) clienttestutil.RequireLinux(t) diff --git a/drivers/shared/executor/executor.go b/drivers/shared/executor/executor.go index 6f24226607c..c537d9de52f 100644 --- a/drivers/shared/executor/executor.go +++ b/drivers/shared/executor/executor.go @@ -125,6 +125,10 @@ type ExecCommand struct { // TaskDir is the directory path on the host where for the task TaskDir string + // WorkDir is the working directory of the task inside of a chroot + // which defaults to the chroot directory (TaskDir) itself + WorkDir string + // ResourceLimits determines whether resource limits are enforced by the // executor. ResourceLimits bool @@ -363,7 +367,11 @@ func (e *UniversalExecutor) Launch(command *ExecCommand) (*ProcessState, error) } // set the task dir as the working directory for the command - e.childCmd.Dir = e.command.TaskDir + if e.command.WorkDir != "" { + e.childCmd.Dir = e.command.WorkDir + } else { + e.childCmd.Dir = e.command.TaskDir + } // start command in separate process group if err := e.setNewProcessGroup(); err != nil { @@ -482,7 +490,7 @@ func (e *UniversalExecutor) ExecStreaming(ctx context.Context, command []string, cmd := exec.CommandContext(ctx, command[0], command[1:]...) - cmd.Dir = "/" + cmd.Dir = e.childCmd.Dir cmd.Env = e.childCmd.Env execHelper := &execHelper{ diff --git a/drivers/shared/executor/executor_linux.go b/drivers/shared/executor/executor_linux.go index 6baef44ca5e..d5fe3e64608 100644 --- a/drivers/shared/executor/executor_linux.go +++ b/drivers/shared/executor/executor_linux.go @@ -214,6 +214,7 @@ func (l *LibcontainerExecutor) Launch(command *ExecCommand) (*ProcessState, erro process := &libcontainer.Process{ Args: combined, Env: command.Env, + Cwd: command.WorkDir, Stdout: stdout, Stderr: stderr, Init: true, @@ -497,6 +498,7 @@ func (l *LibcontainerExecutor) Exec(deadline time.Time, cmd string, args []strin process := &libcontainer.Process{ Args: combined, Env: l.command.Env, + Cwd: l.command.WorkDir, Stdout: buf, Stderr: buf, } @@ -552,7 +554,7 @@ func (l *LibcontainerExecutor) ExecStreaming(ctx context.Context, cmd []string, Env: l.userProc.Env, User: l.userProc.User, Init: false, - Cwd: "/", + Cwd: l.command.WorkDir, } execHelper := &execHelper{ diff --git a/drivers/shared/executor/executor_linux_test.go b/drivers/shared/executor/executor_linux_test.go index 60eb4b481ee..a203975e2fd 100644 --- a/drivers/shared/executor/executor_linux_test.go +++ b/drivers/shared/executor/executor_linux_test.go @@ -62,6 +62,7 @@ func testExecutorCommandWithChroot(t *testing.T) *testExecCmd { "/lib64": "/lib64", "/usr/lib": "/usr/lib", "/bin/ls": "/bin/ls", + "/bin/pwd": "/bin/pwd", "/bin/cat": "/bin/cat", "/bin/echo": "/bin/echo", "/bin/bash": "/bin/bash", @@ -798,6 +799,34 @@ func TestExecutor_cmdMounts(t *testing.T) { require.EqualValues(t, expected, cmdMounts(input)) } +func TestExecutor_WorkDir(t *testing.T) { + t.Parallel() + testutil.ExecCompatible(t) + + testExecCmd := testExecutorCommandWithChroot(t) + execCmd, allocDir := testExecCmd.command, testExecCmd.allocDir + defer allocDir.Destroy() + + execCmd.ResourceLimits = true + workDir := "/etc" + execCmd.WorkDir = workDir + execCmd.Cmd = "/bin/pwd" + + executor := NewExecutorWithIsolation(testlog.HCLogger(t), compute) + defer executor.Shutdown("SIGKILL", 0) + + ps, err := executor.Launch(execCmd) + must.NoError(t, err) + must.NonZero(t, ps.Pid) + + state, err := executor.Wait(context.Background()) + must.NoError(t, err) + must.Zero(t, state.ExitCode) + + output := strings.TrimSpace(testExecCmd.stdout.String()) + must.Eq(t, output, workDir) +} + func TestExecCommand_getCgroupOr_off(t *testing.T) { ci.Parallel(t) diff --git a/drivers/shared/executor/grpc_client.go b/drivers/shared/executor/grpc_client.go index 2f55bc65a7a..0deeb2603c4 100644 --- a/drivers/shared/executor/grpc_client.go +++ b/drivers/shared/executor/grpc_client.go @@ -55,6 +55,7 @@ func (c *grpcExecutorClient) Launch(cmd *ExecCommand) (*ProcessState, error) { CgroupV2Override: cmd.OverrideCgroupV2, CgroupV1Override: cmd.OverrideCgroupV1, OomScoreAdj: cmd.OOMScoreAdj, + WorkDir: cmd.WorkDir, } resp, err := c.client.Launch(ctx, req) if err != nil { diff --git a/drivers/shared/executor/grpc_server.go b/drivers/shared/executor/grpc_server.go index 7811e7bbd60..af9758a4522 100644 --- a/drivers/shared/executor/grpc_server.go +++ b/drivers/shared/executor/grpc_server.go @@ -44,6 +44,7 @@ func (s *grpcExecutorServer) Launch(ctx context.Context, req *proto.LaunchReques OverrideCgroupV2: req.CgroupV2Override, OverrideCgroupV1: req.CgroupV1Override, OOMScoreAdj: req.OomScoreAdj, + WorkDir: req.WorkDir, }) if err != nil { diff --git a/drivers/shared/executor/proto/executor.pb.go b/drivers/shared/executor/proto/executor.pb.go index 7515b8c65ea..71e54ff573f 100644 --- a/drivers/shared/executor/proto/executor.pb.go +++ b/drivers/shared/executor/proto/executor.pb.go @@ -49,6 +49,7 @@ type LaunchRequest struct { CgroupV2Override string `protobuf:"bytes,20,opt,name=cgroup_v2_override,json=cgroupV2Override,proto3" json:"cgroup_v2_override,omitempty"` CgroupV1Override map[string]string `protobuf:"bytes,21,rep,name=cgroup_v1_override,json=cgroupV1Override,proto3" json:"cgroup_v1_override,omitempty" protobuf_key:"bytes,1,opt,name=key,proto3" protobuf_val:"bytes,2,opt,name=value,proto3"` OomScoreAdj int32 `protobuf:"varint,22,opt,name=oom_score_adj,json=oomScoreAdj,proto3" json:"oom_score_adj,omitempty"` + WorkDir string `protobuf:"bytes,23,opt,name=work_dir,json=workDir,proto3" json:"work_dir,omitempty"` XXX_NoUnkeyedLiteral struct{} `json:"-"` XXX_unrecognized []byte `json:"-"` XXX_sizecache int32 `json:"-"` @@ -234,6 +235,13 @@ func (m *LaunchRequest) GetOomScoreAdj() int32 { return 0 } +func (m *LaunchRequest) GetWorkDir() string { + if m != nil { + return m.WorkDir + } + return "" +} + type LaunchResponse struct { Process *ProcessState `protobuf:"bytes,1,opt,name=process,proto3" json:"process,omitempty"` XXX_NoUnkeyedLiteral struct{} `json:"-"` @@ -908,82 +916,83 @@ func init() { } var fileDescriptor_66b85426380683f3 = []byte{ - // 1187 bytes of a gzipped FileDescriptorProto - 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xb4, 0x56, 0x7d, 0x6f, 0xdb, 0x44, - 0x1c, 0x9e, 0x9b, 0xa6, 0x49, 0x7e, 0x49, 0xda, 0xec, 0xd8, 0x8a, 0x17, 0x84, 0x56, 0x8c, 0xc4, - 0x22, 0x18, 0xee, 0xd6, 0xbd, 0x0a, 0x24, 0x06, 0xeb, 0x06, 0x9a, 0xf6, 0x42, 0xe5, 0x8e, 0x4d, - 0xe2, 0x0f, 0xcc, 0xcd, 0xbe, 0x25, 0xb7, 0x38, 0x3e, 0x73, 0x77, 0xce, 0x5a, 0x09, 0x89, 0x2f, - 0x01, 0x12, 0x1f, 0x80, 0x4f, 0xc4, 0x27, 0x42, 0xf7, 0xe6, 0x26, 0xdd, 0x98, 0xdc, 0x22, 0xfe, - 0xca, 0xdd, 0xe3, 0xe7, 0xf7, 0x7e, 0xf7, 0x5c, 0xe0, 0x72, 0xca, 0xe9, 0x9c, 0x70, 0xb1, 0x2d, - 0x26, 0x98, 0x93, 0x74, 0x9b, 0x1c, 0x90, 0xa4, 0x94, 0x8c, 0x6f, 0x17, 0x9c, 0x49, 0x56, 0x6d, - 0x43, 0xbd, 0x45, 0x9f, 0x4c, 0xb0, 0x98, 0xd0, 0x84, 0xf1, 0x22, 0xcc, 0xd9, 0x0c, 0xa7, 0x61, - 0x91, 0x95, 0x63, 0x9a, 0x8b, 0x70, 0x99, 0x37, 0xbc, 0x38, 0x66, 0x6c, 0x9c, 0x11, 0xe3, 0xe4, - 0x45, 0xf9, 0x72, 0x5b, 0xd2, 0x19, 0x11, 0x12, 0xcf, 0x0a, 0x4b, 0x08, 0xac, 0xe1, 0xb6, 0x0b, - 0x6f, 0xc2, 0x99, 0x9d, 0xe1, 0x04, 0x7f, 0xb7, 0xa1, 0xff, 0x08, 0x97, 0x79, 0x32, 0x89, 0xc8, - 0x2f, 0x25, 0x11, 0x12, 0x0d, 0xa0, 0x91, 0xcc, 0x52, 0xdf, 0xdb, 0xf2, 0x46, 0x9d, 0x48, 0x2d, - 0x11, 0x82, 0x55, 0xcc, 0xc7, 0xc2, 0x5f, 0xd9, 0x6a, 0x8c, 0x3a, 0x91, 0x5e, 0xa3, 0x27, 0xd0, - 0xe1, 0x44, 0xb0, 0x92, 0x27, 0x44, 0xf8, 0x8d, 0x2d, 0x6f, 0xd4, 0xdd, 0xb9, 0x12, 0xfe, 0x5b, - 0xe2, 0x36, 0xbe, 0x09, 0x19, 0x46, 0xce, 0x2e, 0x3a, 0x72, 0x81, 0x2e, 0x42, 0x57, 0xc8, 0x94, - 0x95, 0x32, 0x2e, 0xb0, 0x9c, 0xf8, 0xab, 0x3a, 0x3a, 0x18, 0x68, 0x0f, 0xcb, 0x89, 0x25, 0x10, - 0xce, 0x0d, 0xa1, 0x59, 0x11, 0x08, 0xe7, 0x9a, 0x30, 0x80, 0x06, 0xc9, 0xe7, 0xfe, 0x9a, 0x4e, - 0x52, 0x2d, 0x55, 0xde, 0xa5, 0x20, 0xdc, 0x6f, 0x69, 0xae, 0x5e, 0xa3, 0x0b, 0xd0, 0x96, 0x58, - 0x4c, 0xe3, 0x94, 0x72, 0xbf, 0xad, 0xf1, 0x96, 0xda, 0xdf, 0xa3, 0x1c, 0x5d, 0x82, 0x0d, 0x97, - 0x4f, 0x9c, 0xd1, 0x19, 0x95, 0xc2, 0xef, 0x6c, 0x79, 0xa3, 0x76, 0xb4, 0xee, 0xe0, 0x47, 0x1a, - 0x45, 0xd7, 0xe1, 0xdc, 0x0b, 0x2c, 0x68, 0x12, 0x17, 0x9c, 0x25, 0x44, 0x88, 0x38, 0x19, 0x73, - 0x56, 0x16, 0x3e, 0x28, 0xf6, 0xdd, 0x15, 0xdf, 0x8b, 0x90, 0xfe, 0xbe, 0x67, 0x3e, 0xef, 0xea, - 0xaf, 0xe8, 0x1e, 0xac, 0xcd, 0x58, 0x99, 0x4b, 0xe1, 0x77, 0xb7, 0x1a, 0xa3, 0xee, 0xce, 0xe5, - 0x9a, 0xed, 0x7a, 0xac, 0x8c, 0x22, 0x6b, 0x8b, 0xbe, 0x83, 0x56, 0x4a, 0xe6, 0x54, 0x75, 0xbd, - 0xa7, 0xdd, 0x7c, 0x5e, 0xd3, 0xcd, 0x3d, 0x6d, 0x15, 0x39, 0x6b, 0x34, 0x81, 0xb3, 0x39, 0x91, - 0xaf, 0x19, 0x9f, 0xc6, 0x54, 0xb0, 0x0c, 0x4b, 0xca, 0x72, 0xbf, 0xaf, 0x07, 0xf9, 0x65, 0x4d, - 0x97, 0x4f, 0x8c, 0xfd, 0x03, 0x67, 0xbe, 0x5f, 0x90, 0x24, 0x1a, 0xe4, 0xc7, 0x50, 0x14, 0x40, - 0x3f, 0x67, 0x71, 0x41, 0xe7, 0x4c, 0xc6, 0x9c, 0x31, 0xe9, 0xaf, 0xeb, 0xae, 0x76, 0x73, 0xb6, - 0xa7, 0xb0, 0x88, 0x31, 0x89, 0x46, 0x30, 0x48, 0xc9, 0x4b, 0x5c, 0x66, 0x32, 0x2e, 0x68, 0x1a, - 0xcf, 0x58, 0x4a, 0xfc, 0x0d, 0x3d, 0x9e, 0x75, 0x8b, 0xef, 0xd1, 0xf4, 0x31, 0x4b, 0xc9, 0x22, - 0x93, 0x16, 0x89, 0x61, 0x0e, 0x96, 0x98, 0x0f, 0x8a, 0x44, 0x33, 0x3f, 0x86, 0x7e, 0x52, 0x94, - 0x82, 0x48, 0x37, 0x9f, 0xb3, 0x9a, 0xd6, 0x33, 0xa0, 0x9d, 0xca, 0x87, 0x00, 0x38, 0xcb, 0xd8, - 0xeb, 0x38, 0xc1, 0x85, 0xf0, 0x91, 0x3e, 0x3c, 0x1d, 0x8d, 0xec, 0xe2, 0x42, 0xa0, 0x00, 0x7a, - 0x09, 0x2e, 0xf0, 0x0b, 0x9a, 0x51, 0x49, 0x89, 0xf0, 0xdf, 0xd3, 0x84, 0x25, 0x0c, 0x5d, 0x06, - 0x64, 0x02, 0xc4, 0xf3, 0x9d, 0x98, 0xcd, 0x09, 0xe7, 0x34, 0x25, 0xfe, 0x39, 0x1d, 0x6c, 0x60, - 0xbe, 0x3c, 0xdb, 0xf9, 0xde, 0xe2, 0xe8, 0xf0, 0x88, 0x7d, 0xf5, 0x88, 0x7d, 0x5e, 0xcf, 0xf2, - 0x61, 0x58, 0xef, 0xea, 0x87, 0x4b, 0x37, 0x36, 0x34, 0xa5, 0x3c, 0xbb, 0xea, 0x62, 0xdc, 0xcf, - 0x25, 0x3f, 0xac, 0x42, 0x57, 0xb0, 0x1a, 0x04, 0x63, 0xb3, 0x58, 0x24, 0x8c, 0x93, 0x18, 0xa7, - 0xaf, 0xfc, 0xcd, 0x2d, 0x6f, 0xd4, 0x8c, 0xba, 0x8c, 0xcd, 0xf6, 0x15, 0xf6, 0x4d, 0xfa, 0x6a, - 0xb8, 0x0b, 0xe7, 0xdf, 0xea, 0x4e, 0x5d, 0xaf, 0x29, 0x39, 0x74, 0xb2, 0x30, 0x25, 0x87, 0xe8, - 0x1c, 0x34, 0xe7, 0x38, 0x2b, 0x89, 0xbf, 0xa2, 0x31, 0xb3, 0xf9, 0x62, 0xe5, 0xb6, 0x17, 0xfc, - 0x0c, 0xeb, 0x2e, 0x43, 0x51, 0xb0, 0x5c, 0x10, 0xf4, 0x04, 0x5a, 0xf6, 0xb2, 0x68, 0x0f, 0xdd, - 0x9d, 0xeb, 0x75, 0x4b, 0xb5, 0x97, 0x68, 0x5f, 0x62, 0x49, 0x22, 0xe7, 0x24, 0xe8, 0x43, 0xf7, - 0x39, 0xa6, 0xd2, 0x76, 0x20, 0xf8, 0x09, 0x7a, 0x66, 0xfb, 0x3f, 0x85, 0x7b, 0x04, 0x1b, 0xfb, - 0x93, 0x52, 0xa6, 0xec, 0x75, 0xee, 0x64, 0x72, 0x13, 0xd6, 0x04, 0x1d, 0xe7, 0x38, 0xb3, 0x2d, - 0xb1, 0x3b, 0xf4, 0x11, 0xf4, 0xc6, 0x1c, 0x27, 0x24, 0x2e, 0x08, 0xa7, 0x2c, 0xd5, 0xcd, 0x69, - 0x44, 0x5d, 0x8d, 0xed, 0x69, 0x28, 0x40, 0x30, 0x38, 0xf2, 0x66, 0x32, 0x0e, 0x26, 0xb0, 0xf9, - 0x43, 0x91, 0xaa, 0xa0, 0x95, 0x3a, 0xda, 0x40, 0x4b, 0x4a, 0xeb, 0xfd, 0x67, 0xa5, 0x0d, 0x2e, - 0xc0, 0xfb, 0x6f, 0x44, 0xb2, 0x49, 0x0c, 0x60, 0xfd, 0x19, 0xe1, 0x82, 0x32, 0x57, 0x65, 0xf0, - 0x19, 0x6c, 0x54, 0x88, 0xed, 0xad, 0x0f, 0xad, 0xb9, 0x81, 0x6c, 0xe5, 0x6e, 0x1b, 0x7c, 0x0a, - 0x3d, 0xd5, 0xb7, 0x2a, 0xf3, 0x21, 0xb4, 0x69, 0x2e, 0x09, 0x9f, 0xdb, 0x26, 0x35, 0xa2, 0x6a, - 0x1f, 0x3c, 0x87, 0xbe, 0xe5, 0x5a, 0xb7, 0xdf, 0x42, 0x53, 0x28, 0xe0, 0x84, 0x25, 0x3e, 0xc5, - 0x62, 0x6a, 0x1c, 0x19, 0xf3, 0xe0, 0x12, 0xf4, 0xf7, 0xf5, 0x24, 0xde, 0x3e, 0xa8, 0xa6, 0x1b, - 0x94, 0x2a, 0xd6, 0x11, 0x6d, 0xf9, 0x53, 0xe8, 0xde, 0x3f, 0x20, 0x89, 0x33, 0xbc, 0x09, 0xed, - 0x94, 0xe0, 0x34, 0xa3, 0x39, 0xb1, 0x49, 0x0d, 0x43, 0xf3, 0xe4, 0x86, 0xee, 0xc9, 0x0d, 0x9f, - 0xba, 0x27, 0x37, 0xaa, 0xb8, 0xee, 0x01, 0x5d, 0x79, 0xf3, 0x01, 0x6d, 0x1c, 0x3d, 0xa0, 0xc1, - 0x2e, 0xf4, 0x4c, 0x30, 0x5b, 0xff, 0x26, 0xac, 0xb1, 0x52, 0x16, 0xa5, 0xd4, 0xb1, 0x7a, 0x91, - 0xdd, 0xa1, 0x0f, 0xa0, 0x43, 0x0e, 0xa8, 0x8c, 0x13, 0x25, 0x74, 0x2b, 0xba, 0x82, 0xb6, 0x02, - 0x76, 0x59, 0x4a, 0x82, 0xbf, 0x3c, 0xe8, 0x2d, 0x9e, 0x58, 0x15, 0xbb, 0xa0, 0xa9, 0xad, 0x54, - 0x2d, 0xdf, 0x69, 0xbf, 0xd0, 0x9b, 0xc6, 0x62, 0x6f, 0x50, 0x08, 0xab, 0xea, 0xcf, 0x84, 0x7e, - 0x86, 0xdf, 0x5d, 0xb6, 0xe6, 0x29, 0x15, 0x55, 0xca, 0x32, 0xa5, 0x59, 0x46, 0x52, 0xfd, 0x36, - 0xb7, 0xa3, 0x0e, 0x63, 0xb3, 0x87, 0x1a, 0xd8, 0xf9, 0xa3, 0x03, 0xed, 0xfb, 0xf6, 0x9e, 0xa1, - 0x43, 0x58, 0x33, 0xe2, 0x80, 0x6e, 0x9c, 0x4a, 0xee, 0x86, 0x37, 0x4f, 0x6a, 0x66, 0xc7, 0x7b, - 0x06, 0x09, 0x58, 0x55, 0x32, 0x81, 0xae, 0xd5, 0xf5, 0xb0, 0xa0, 0x31, 0xc3, 0xeb, 0x27, 0x33, - 0xaa, 0x82, 0xfe, 0x06, 0x6d, 0x77, 0xdb, 0xd1, 0xad, 0xba, 0x3e, 0x8e, 0xa9, 0xcd, 0xf0, 0xf6, - 0xc9, 0x0d, 0xab, 0x04, 0x7e, 0xf7, 0x60, 0xe3, 0xd8, 0x8d, 0x47, 0x5f, 0xd5, 0xf5, 0xf7, 0x76, - 0x51, 0x1a, 0xde, 0x39, 0xb5, 0x7d, 0x95, 0xd6, 0xaf, 0xd0, 0xb2, 0xd2, 0x82, 0x6a, 0x4f, 0x74, - 0x59, 0x9d, 0x86, 0xb7, 0x4e, 0x6c, 0x57, 0x45, 0x3f, 0x80, 0xa6, 0x96, 0x0d, 0x54, 0x7b, 0xac, - 0x8b, 0xd2, 0x36, 0xbc, 0x71, 0x42, 0x2b, 0x17, 0xf7, 0x8a, 0xa7, 0xce, 0xbf, 0xd1, 0x9d, 0xfa, - 0xe7, 0x7f, 0x49, 0xd0, 0xea, 0x9f, 0xff, 0x63, 0xf2, 0xa6, 0xcf, 0xbf, 0xba, 0x86, 0xf5, 0xcf, - 0xff, 0x82, 0x1c, 0xd6, 0x3f, 0xff, 0x8b, 0xb2, 0x16, 0x9c, 0x41, 0x7f, 0x7a, 0xd0, 0x57, 0xd0, - 0xbe, 0xe4, 0x04, 0xcf, 0x68, 0x3e, 0x46, 0x77, 0x6a, 0x6a, 0xbb, 0xb2, 0x32, 0xfa, 0x6e, 0x2d, - 0x5d, 0x2a, 0x5f, 0x9f, 0xde, 0x81, 0x4b, 0x6b, 0xe4, 0x5d, 0xf1, 0xee, 0xb6, 0x7e, 0x6c, 0x1a, - 0x49, 0x5b, 0xd3, 0x3f, 0xd7, 0xfe, 0x09, 0x00, 0x00, 0xff, 0xff, 0xd2, 0x85, 0x8d, 0xe6, 0xa9, - 0x0d, 0x00, 0x00, + // 1205 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xb4, 0x56, 0xfb, 0x6e, 0x1b, 0xc5, + 0x17, 0xee, 0xc6, 0x71, 0x6c, 0x1f, 0xdb, 0x89, 0x3b, 0xbf, 0x36, 0xdd, 0xfa, 0x27, 0xd4, 0xb0, + 0x48, 0xd4, 0x82, 0xb2, 0x69, 0xd3, 0xab, 0x40, 0xa2, 0xd0, 0xa4, 0xa0, 0xaa, 0x17, 0xa2, 0x4d, + 0x69, 0x25, 0xfe, 0x60, 0x99, 0xee, 0x4e, 0xed, 0xa9, 0xd7, 0x3b, 0xcb, 0xcc, 0xac, 0x9b, 0x48, + 0x48, 0xbc, 0x04, 0x48, 0x3c, 0x00, 0xaf, 0xc7, 0x3b, 0xa0, 0xb9, 0x6d, 0xec, 0xb4, 0x54, 0x9b, + 0x22, 0xfe, 0xca, 0x9e, 0xcf, 0xdf, 0xb9, 0xcc, 0x39, 0x73, 0xbe, 0x09, 0x5c, 0x49, 0x39, 0x9d, + 0x13, 0x2e, 0xb6, 0xc5, 0x04, 0x73, 0x92, 0x6e, 0x93, 0x43, 0x92, 0x94, 0x92, 0xf1, 0xed, 0x82, + 0x33, 0xc9, 0x2a, 0x33, 0xd4, 0x26, 0xfa, 0x78, 0x82, 0xc5, 0x84, 0x26, 0x8c, 0x17, 0x61, 0xce, + 0x66, 0x38, 0x0d, 0x8b, 0xac, 0x1c, 0xd3, 0x5c, 0x84, 0xcb, 0xbc, 0xe1, 0xa5, 0x31, 0x63, 0xe3, + 0x8c, 0x98, 0x20, 0x2f, 0xca, 0x97, 0xdb, 0x92, 0xce, 0x88, 0x90, 0x78, 0x56, 0x58, 0x42, 0x60, + 0x1d, 0xb7, 0x5d, 0x7a, 0x93, 0xce, 0x58, 0x86, 0x13, 0xfc, 0xd5, 0x86, 0xfe, 0x23, 0x5c, 0xe6, + 0xc9, 0x24, 0x22, 0x3f, 0x97, 0x44, 0x48, 0x34, 0x80, 0x46, 0x32, 0x4b, 0x7d, 0x6f, 0xcb, 0x1b, + 0x75, 0x22, 0xf5, 0x89, 0x10, 0xac, 0x62, 0x3e, 0x16, 0xfe, 0xca, 0x56, 0x63, 0xd4, 0x89, 0xf4, + 0x37, 0x7a, 0x02, 0x1d, 0x4e, 0x04, 0x2b, 0x79, 0x42, 0x84, 0xdf, 0xd8, 0xf2, 0x46, 0xdd, 0x9d, + 0xab, 0xe1, 0x3f, 0x15, 0x6e, 0xf3, 0x9b, 0x94, 0x61, 0xe4, 0xfc, 0xa2, 0xe3, 0x10, 0xe8, 0x12, + 0x74, 0x85, 0x4c, 0x59, 0x29, 0xe3, 0x02, 0xcb, 0x89, 0xbf, 0xaa, 0xb3, 0x83, 0x81, 0xf6, 0xb1, + 0x9c, 0x58, 0x02, 0xe1, 0xdc, 0x10, 0x9a, 0x15, 0x81, 0x70, 0xae, 0x09, 0x03, 0x68, 0x90, 0x7c, + 0xee, 0xaf, 0xe9, 0x22, 0xd5, 0xa7, 0xaa, 0xbb, 0x14, 0x84, 0xfb, 0x2d, 0xcd, 0xd5, 0xdf, 0xe8, + 0x22, 0xb4, 0x25, 0x16, 0xd3, 0x38, 0xa5, 0xdc, 0x6f, 0x6b, 0xbc, 0xa5, 0xec, 0x3d, 0xca, 0xd1, + 0x65, 0xd8, 0x70, 0xf5, 0xc4, 0x19, 0x9d, 0x51, 0x29, 0xfc, 0xce, 0x96, 0x37, 0x6a, 0x47, 0xeb, + 0x0e, 0x7e, 0xa4, 0x51, 0x74, 0x03, 0xce, 0xbd, 0xc0, 0x82, 0x26, 0x71, 0xc1, 0x59, 0x42, 0x84, + 0x88, 0x93, 0x31, 0x67, 0x65, 0xe1, 0x83, 0x62, 0xdf, 0x5b, 0xf1, 0xbd, 0x08, 0xe9, 0xdf, 0xf7, + 0xcd, 0xcf, 0xbb, 0xfa, 0x57, 0xb4, 0x07, 0x6b, 0x33, 0x56, 0xe6, 0x52, 0xf8, 0xdd, 0xad, 0xc6, + 0xa8, 0xbb, 0x73, 0xa5, 0x66, 0xbb, 0x1e, 0x2b, 0xa7, 0xc8, 0xfa, 0xa2, 0x6f, 0xa1, 0x95, 0x92, + 0x39, 0x55, 0x5d, 0xef, 0xe9, 0x30, 0x9f, 0xd5, 0x0c, 0xb3, 0xa7, 0xbd, 0x22, 0xe7, 0x8d, 0x26, + 0x70, 0x36, 0x27, 0xf2, 0x35, 0xe3, 0xd3, 0x98, 0x0a, 0x96, 0x61, 0x49, 0x59, 0xee, 0xf7, 0xf5, + 0x20, 0xbf, 0xa8, 0x19, 0xf2, 0x89, 0xf1, 0x7f, 0xe0, 0xdc, 0x0f, 0x0a, 0x92, 0x44, 0x83, 0xfc, + 0x04, 0x8a, 0x02, 0xe8, 0xe7, 0x2c, 0x2e, 0xe8, 0x9c, 0xc9, 0x98, 0x33, 0x26, 0xfd, 0x75, 0xdd, + 0xd5, 0x6e, 0xce, 0xf6, 0x15, 0x16, 0x31, 0x26, 0xd1, 0x08, 0x06, 0x29, 0x79, 0x89, 0xcb, 0x4c, + 0xc6, 0x05, 0x4d, 0xe3, 0x19, 0x4b, 0x89, 0xbf, 0xa1, 0xc7, 0xb3, 0x6e, 0xf1, 0x7d, 0x9a, 0x3e, + 0x66, 0x29, 0x59, 0x64, 0xd2, 0x22, 0x31, 0xcc, 0xc1, 0x12, 0xf3, 0x41, 0x91, 0x68, 0xe6, 0x47, + 0xd0, 0x4f, 0x8a, 0x52, 0x10, 0xe9, 0xe6, 0x73, 0x56, 0xd3, 0x7a, 0x06, 0xb4, 0x53, 0xf9, 0x00, + 0x00, 0x67, 0x19, 0x7b, 0x1d, 0x27, 0xb8, 0x10, 0x3e, 0xd2, 0x97, 0xa7, 0xa3, 0x91, 0x5d, 0x5c, + 0x08, 0x14, 0x40, 0x2f, 0xc1, 0x05, 0x7e, 0x41, 0x33, 0x2a, 0x29, 0x11, 0xfe, 0xff, 0x34, 0x61, + 0x09, 0x43, 0x57, 0x00, 0x99, 0x04, 0xf1, 0x7c, 0x27, 0x66, 0x73, 0xc2, 0x39, 0x4d, 0x89, 0x7f, + 0x4e, 0x27, 0x1b, 0x98, 0x5f, 0x9e, 0xed, 0x7c, 0x67, 0x71, 0x74, 0x74, 0xcc, 0xbe, 0x76, 0xcc, + 0x3e, 0xaf, 0x67, 0xf9, 0x30, 0xac, 0xb7, 0xfa, 0xe1, 0xd2, 0xc6, 0x86, 0xe6, 0x28, 0xcf, 0xae, + 0xb9, 0x1c, 0xf7, 0x73, 0xc9, 0x8f, 0xaa, 0xd4, 0x15, 0xac, 0x06, 0xc1, 0xd8, 0x2c, 0x16, 0x09, + 0xe3, 0x24, 0xc6, 0xe9, 0x2b, 0x7f, 0x73, 0xcb, 0x1b, 0x35, 0xa3, 0x2e, 0x63, 0xb3, 0x03, 0x85, + 0x7d, 0x9d, 0xbe, 0x52, 0xfb, 0xa1, 0xef, 0x84, 0xda, 0x8f, 0x0b, 0x66, 0x3f, 0x94, 0xbd, 0x47, + 0xf9, 0x70, 0x17, 0xce, 0xbf, 0x35, 0x93, 0xda, 0xbc, 0x29, 0x39, 0x72, 0x8a, 0x31, 0x25, 0x47, + 0xe8, 0x1c, 0x34, 0xe7, 0x38, 0x2b, 0x89, 0xbf, 0xa2, 0x31, 0x63, 0x7c, 0xbe, 0x72, 0xc7, 0x0b, + 0x7e, 0x82, 0x75, 0x57, 0xbc, 0x28, 0x58, 0x2e, 0x08, 0x7a, 0x02, 0x2d, 0xbb, 0x47, 0x3a, 0x42, + 0x77, 0xe7, 0x46, 0xdd, 0x2e, 0xd8, 0xfd, 0x3a, 0x90, 0x58, 0x92, 0xc8, 0x05, 0x09, 0xfa, 0xd0, + 0x7d, 0x8e, 0xa9, 0xb4, 0xcd, 0x09, 0x7e, 0x84, 0x9e, 0x31, 0xff, 0xa3, 0x74, 0x8f, 0x60, 0xe3, + 0x60, 0x52, 0xca, 0x94, 0xbd, 0xce, 0x9d, 0x82, 0x6e, 0xc2, 0x9a, 0xa0, 0xe3, 0x1c, 0x67, 0xb6, + 0x25, 0xd6, 0x42, 0x1f, 0x42, 0x6f, 0xcc, 0x71, 0x42, 0xe2, 0x82, 0x70, 0xca, 0x52, 0xdd, 0x9c, + 0x46, 0xd4, 0xd5, 0xd8, 0xbe, 0x86, 0x02, 0x04, 0x83, 0xe3, 0x68, 0xa6, 0xe2, 0x60, 0x02, 0x9b, + 0xdf, 0x17, 0xa9, 0x4a, 0x5a, 0x09, 0xa7, 0x4d, 0xb4, 0x24, 0xc2, 0xde, 0xbf, 0x16, 0xe1, 0xe0, + 0x22, 0x5c, 0x78, 0x23, 0x93, 0x2d, 0x62, 0x00, 0xeb, 0xcf, 0x08, 0x17, 0x94, 0xb9, 0x53, 0x06, + 0x9f, 0xc2, 0x46, 0x85, 0xd8, 0xde, 0xfa, 0xd0, 0x9a, 0x1b, 0xc8, 0x9e, 0xdc, 0x99, 0xc1, 0x27, + 0xd0, 0x53, 0x7d, 0xab, 0x2a, 0x1f, 0x42, 0x9b, 0xe6, 0x92, 0xf0, 0xb9, 0x6d, 0x52, 0x23, 0xaa, + 0xec, 0xe0, 0x39, 0xf4, 0x2d, 0xd7, 0x86, 0xfd, 0x06, 0x9a, 0x42, 0x01, 0xa7, 0x3c, 0xe2, 0x53, + 0x2c, 0xa6, 0x26, 0x90, 0x71, 0x0f, 0x2e, 0x43, 0xff, 0x40, 0x4f, 0xe2, 0xed, 0x83, 0x6a, 0xba, + 0x41, 0xa9, 0xc3, 0x3a, 0xa2, 0x3d, 0xfe, 0x14, 0xba, 0xf7, 0x0f, 0x49, 0xe2, 0x1c, 0x6f, 0x41, + 0x3b, 0x25, 0x38, 0xcd, 0x68, 0x4e, 0x6c, 0x51, 0xc3, 0xd0, 0xbc, 0xc6, 0xa1, 0x7b, 0x8d, 0xc3, + 0xa7, 0xee, 0x35, 0x8e, 0x2a, 0xae, 0x7b, 0x5b, 0x57, 0xde, 0x7c, 0x5b, 0x1b, 0xc7, 0x6f, 0x6b, + 0xb0, 0x0b, 0x3d, 0x93, 0xcc, 0x9e, 0x7f, 0x13, 0xd6, 0x58, 0x29, 0x8b, 0x52, 0xea, 0x5c, 0xbd, + 0xc8, 0x5a, 0xe8, 0xff, 0xd0, 0x21, 0x87, 0x54, 0xc6, 0x89, 0xd2, 0xc0, 0x15, 0x7d, 0x82, 0xb6, + 0x02, 0x76, 0x59, 0x4a, 0x82, 0x3f, 0x3d, 0xe8, 0x2d, 0xde, 0x58, 0x95, 0xbb, 0xa0, 0xa9, 0x3d, + 0xa9, 0xfa, 0x7c, 0xa7, 0xff, 0x42, 0x6f, 0x1a, 0x8b, 0xbd, 0x41, 0x21, 0xac, 0xaa, 0xff, 0x33, + 0xf4, 0x0b, 0xfd, 0xee, 0x63, 0x6b, 0x9e, 0x12, 0x58, 0x25, 0x3a, 0x53, 0x9a, 0x65, 0x24, 0xd5, + 0xcf, 0x76, 0x3b, 0xea, 0x30, 0x36, 0x7b, 0xa8, 0x81, 0x9d, 0xdf, 0x3b, 0xd0, 0xbe, 0x6f, 0xf7, + 0x0c, 0x1d, 0xc1, 0x9a, 0x11, 0x07, 0x74, 0xf3, 0xbd, 0x94, 0x70, 0x78, 0xeb, 0xb4, 0x6e, 0x76, + 0xbc, 0x67, 0x90, 0x80, 0x55, 0x25, 0x13, 0xe8, 0x7a, 0xdd, 0x08, 0x0b, 0x1a, 0x33, 0xbc, 0x71, + 0x3a, 0xa7, 0x2a, 0xe9, 0xaf, 0xd0, 0x76, 0xdb, 0x8e, 0x6e, 0xd7, 0x8d, 0x71, 0x42, 0x6d, 0x86, + 0x77, 0x4e, 0xef, 0x58, 0x15, 0xf0, 0x9b, 0x07, 0x1b, 0x27, 0x36, 0x1e, 0x7d, 0x59, 0x37, 0xde, + 0xdb, 0x45, 0x69, 0x78, 0xf7, 0xbd, 0xfd, 0xab, 0xb2, 0x7e, 0x81, 0x96, 0x95, 0x16, 0x54, 0x7b, + 0xa2, 0xcb, 0xea, 0x34, 0xbc, 0x7d, 0x6a, 0xbf, 0x2a, 0xfb, 0x21, 0x34, 0xb5, 0x6c, 0xa0, 0xda, + 0x63, 0x5d, 0x94, 0xb6, 0xe1, 0xcd, 0x53, 0x7a, 0xb9, 0xbc, 0x57, 0x3d, 0x75, 0xff, 0x8d, 0xee, + 0xd4, 0xbf, 0xff, 0x4b, 0x82, 0x56, 0xff, 0xfe, 0x9f, 0x90, 0x37, 0x7d, 0xff, 0xd5, 0x1a, 0xd6, + 0xbf, 0xff, 0x0b, 0x72, 0x58, 0xff, 0xfe, 0x2f, 0xca, 0x5a, 0x70, 0x06, 0xfd, 0xe1, 0x41, 0x5f, + 0x41, 0x07, 0x92, 0x13, 0x3c, 0xa3, 0xf9, 0x18, 0xdd, 0xad, 0xa9, 0xed, 0xca, 0xcb, 0xe8, 0xbb, + 0xf5, 0x74, 0xa5, 0x7c, 0xf5, 0xfe, 0x01, 0x5c, 0x59, 0x23, 0xef, 0xaa, 0x77, 0xaf, 0xf5, 0x43, + 0xd3, 0x48, 0xda, 0x9a, 0xfe, 0x73, 0xfd, 0xef, 0x00, 0x00, 0x00, 0xff, 0xff, 0x5b, 0xc0, 0xa1, + 0x7e, 0xc4, 0x0d, 0x00, 0x00, } // Reference imports to suppress errors if they are not otherwise used. diff --git a/drivers/shared/executor/proto/executor.proto b/drivers/shared/executor/proto/executor.proto index 55863968f84..7233837e0a4 100644 --- a/drivers/shared/executor/proto/executor.proto +++ b/drivers/shared/executor/proto/executor.proto @@ -53,6 +53,7 @@ message LaunchRequest { string cgroup_v2_override = 20; map cgroup_v1_override = 21; int32 oom_score_adj = 22; + string work_dir = 23; } message LaunchResponse { diff --git a/website/content/docs/drivers/exec.mdx b/website/content/docs/drivers/exec.mdx index 7ddd240d373..d399ee69b15 100644 --- a/website/content/docs/drivers/exec.mdx +++ b/website/content/docs/drivers/exec.mdx @@ -87,6 +87,11 @@ config { } ``` +- `work_dir` - (Optional) Sets a custom working directory for the task. This path must be + absolute and within the task's [chroot](#chroot) or in a [host volume][] mounted + with a [`volume_mount`][volume_mount] block. This will also change the working + directory when using `nomad alloc exec`. + ## Examples To run a binary present on the Node: diff --git a/website/content/docs/drivers/java.mdx b/website/content/docs/drivers/java.mdx index 88066fa7873..58d8f3aae21 100644 --- a/website/content/docs/drivers/java.mdx +++ b/website/content/docs/drivers/java.mdx @@ -85,6 +85,11 @@ config { } ``` +- `work_dir` - (Optional) Sets a custom working directory for the task. This path must be + absolute and within the task's [chroot](#chroot) or in a [host volume][] mounted + with a [`volume_mount`][volume_mount] block. This will also change the working + directory when using `nomad alloc exec`. + ## Examples A simple config block to run a Java Jar: @@ -260,3 +265,5 @@ This list is configurable through the agent client [allow_caps]: /nomad/docs/drivers/java#allow_caps [docker_caps]: https://docs.docker.com/engine/reference/run/#runtime-privilege-and-linux-capabilities [cgroup controller requirements]: /nomad/docs/install/production/requirements#hardening-nomad +[volume_mount]: /nomad/docs/job-specification/volume_mount +[host volume]: /nomad/docs/configuration/client#host_volume-block diff --git a/website/content/docs/drivers/raw_exec.mdx b/website/content/docs/drivers/raw_exec.mdx index 0bdc73ae942..1e01a1e4e2e 100644 --- a/website/content/docs/drivers/raw_exec.mdx +++ b/website/content/docs/drivers/raw_exec.mdx @@ -53,6 +53,10 @@ the Nomad client has been hardened according to the [production][hardening] guid - `oom_score_adj` - (Optional) A positive integer to indicate the likelihood of the task being OOM killed (valid only for Linux). Defaults to 0. +- `work_dir` - (Optional) Sets a custom working directory for the task. This must be an + absolute path. This will also change the working directory when using `nomad alloc exec`. + + ## Examples To run a binary present on the Node: