diff --git a/client/driver/exec.go b/client/driver/exec.go index b346f387a..728ed3f5f 100644 --- a/client/driver/exec.go +++ b/client/driver/exec.go @@ -121,18 +121,18 @@ func (d *ExecDriver) Start(ctx *ExecContext, task *structs.Task) (DriverHandle, return nil, err } executorCtx := &executor.ExecutorContext{ - TaskEnv: d.taskEnv, - Driver: "exec", - AllocDir: ctx.AllocDir, - AllocID: ctx.AllocID, - Task: task, + TaskEnv: d.taskEnv, + Driver: "exec", + AllocDir: ctx.AllocDir, + AllocID: ctx.AllocID, + ChrootEnv: d.config.ChrootEnv, + Task: task, } ps, err := exec.LaunchCmd(&executor.ExecCommand{ Cmd: command, Args: driverConfig.Args, FSIsolation: true, - ChrootEnv: d.config.ChrootEnv, ResourceLimits: true, User: getExecutorUser(task), }, executorCtx) diff --git a/client/driver/executor/executor.go b/client/driver/executor/executor.go index 17984b226..7fc973e63 100644 --- a/client/driver/executor/executor.go +++ b/client/driver/executor/executor.go @@ -102,6 +102,10 @@ type ExecutorContext struct { // AllocID is the allocation id to which the task belongs AllocID string + // A mapping of directories on the host OS to attempt to embed inside each + // task's chroot. + ChrootEnv map[string]string + // Driver is the name of the driver that invoked the executor Driver string @@ -126,10 +130,6 @@ type ExecCommand struct { // FSIsolation determines whether the command would be run in a chroot. FSIsolation bool - // A mapping of directories on the host OS to attempt to embed inside each - // task's chroot. - ChrootEnv map[string]string - // User is the user which the executor uses to run the command. User string diff --git a/client/driver/executor/executor_linux.go b/client/driver/executor/executor_linux.go index 6b1d1b445..c673555cc 100644 --- a/client/driver/executor/executor_linux.go +++ b/client/driver/executor/executor_linux.go @@ -228,8 +228,8 @@ func (e *UniversalExecutor) configureChroot() error { } chroot := chrootEnv - if e.command.ChrootEnv != nil && len(e.command.ChrootEnv) > 0 { - chroot = e.command.ChrootEnv + if len(e.ctx.ChrootEnv) > 0 { + chroot = e.ctx.ChrootEnv } if err := allocDir.Embed(e.ctx.Task.Name, chroot); err != nil { diff --git a/client/driver/executor/executor_linux_test.go b/client/driver/executor/executor_linux_test.go index 9af75dec5..fcc0e088a 100644 --- a/client/driver/executor/executor_linux_test.go +++ b/client/driver/executor/executor_linux_test.go @@ -9,15 +9,38 @@ import ( "strings" "testing" + "github.com/hashicorp/nomad/client/driver/env" cstructs "github.com/hashicorp/nomad/client/driver/structs" "github.com/hashicorp/nomad/client/testutil" + "github.com/hashicorp/nomad/nomad/mock" ) +func testExecutorContextWithChroot(t *testing.T) *ExecutorContext { + taskEnv := env.NewTaskEnvironment(mock.Node()) + task, allocDir := mockAllocDir(t) + ctx := &ExecutorContext{ + TaskEnv: taskEnv, + Task: task, + AllocDir: allocDir, + ChrootEnv: map[string]string{ + "/etc/ld.so.cache": "/etc/ld.so.cache", + "/etc/ld.so.conf": "/etc/ld.so.conf", + "/etc/ld.so.conf.d": "/etc/ld.so.conf.d", + "/lib": "/lib", + "/lib64": "/lib64", + "/usr/lib": "/usr/lib", + "/bin/ls": "/bin/ls", + "/foobar": "/does/not/exist", + }, + } + return ctx +} + func TestExecutor_IsolationAndConstraints(t *testing.T) { testutil.ExecCompatible(t) - execCmd := ExecCommand{Cmd: "/bin/echo", Args: []string{"hello world"}} - ctx := testExecutorContext(t) + execCmd := ExecCommand{Cmd: "/bin/ls", Args: []string{"-F", "/"}} + ctx := testExecutorContextWithChroot(t) defer ctx.AllocDir.Destroy() execCmd.FSIsolation = true @@ -58,7 +81,7 @@ func TestExecutor_IsolationAndConstraints(t *testing.T) { t.Fatalf("file %v hasn't been removed", memLimits) } - expected := "hello world" + expected := "bin/\netc/\nlib/\nlib64/\nusr/" file := filepath.Join(ctx.AllocDir.LogDir(), "web.stdout.0") output, err := ioutil.ReadFile(file) if err != nil { diff --git a/client/driver/java.go b/client/driver/java.go index 4488a5e33..24e6ce6a8 100644 --- a/client/driver/java.go +++ b/client/driver/java.go @@ -203,11 +203,12 @@ func (d *JavaDriver) Start(ctx *ExecContext, task *structs.Task) (DriverHandle, return nil, err } executorCtx := &executor.ExecutorContext{ - TaskEnv: d.taskEnv, - Driver: "java", - AllocDir: ctx.AllocDir, - AllocID: ctx.AllocID, - Task: task, + TaskEnv: d.taskEnv, + Driver: "java", + AllocDir: ctx.AllocDir, + AllocID: ctx.AllocID, + ChrootEnv: d.config.ChrootEnv, + Task: task, } absPath, err := GetAbsolutePath("java") @@ -219,7 +220,6 @@ func (d *JavaDriver) Start(ctx *ExecContext, task *structs.Task) (DriverHandle, Cmd: absPath, Args: args, FSIsolation: true, - ChrootEnv: d.config.ChrootEnv, ResourceLimits: true, User: getExecutorUser(task), }, executorCtx) diff --git a/command/agent/config-test-fixtures/basic.hcl b/command/agent/config-test-fixtures/basic.hcl index 1663d7d70..61d9577a9 100644 --- a/command/agent/config-test-fixtures/basic.hcl +++ b/command/agent/config-test-fixtures/basic.hcl @@ -33,6 +33,10 @@ client { foo = "bar" baz = "zip" } + chroot_env { + "/opt/myapp/etc" = "/etc" + "/opt/myapp/bin" = "/bin" + } network_interface = "eth0" network_speed = 100 reserved { diff --git a/command/agent/config_parse_test.go b/command/agent/config_parse_test.go index 04d00c43c..9dd7593e5 100644 --- a/command/agent/config_parse_test.go +++ b/command/agent/config_parse_test.go @@ -53,6 +53,10 @@ func TestConfig_Parse(t *testing.T) { "foo": "bar", "baz": "zip", }, + ChrootEnv: map[string]string{ + "/opt/myapp/etc": "/etc", + "/opt/myapp/bin": "/bin", + }, NetworkInterface: "eth0", NetworkSpeed: 100, MaxKillTimeout: "10s",