diff --git a/client/allocrunner/taskrunner/task_runner_test.go b/client/allocrunner/taskrunner/task_runner_test.go index 935c810a5..78870b04f 100644 --- a/client/allocrunner/taskrunner/task_runner_test.go +++ b/client/allocrunner/taskrunner/task_runner_test.go @@ -1716,44 +1716,6 @@ func TestTaskRunner_DeriveToken_Unrecoverable(t *testing.T) { require.True(t, state.Events[2].FailsTask) } -// TestTaskRunner_Download_ChrootExec asserts that downloaded artifacts may be -// executed in a chroot. -func TestTaskRunner_Download_ChrootExec(t *testing.T) { - ci.Parallel(t) - ctestutil.ExecCompatible(t) - - ts := httptest.NewServer(http.FileServer(http.Dir(filepath.Dir(".")))) - defer ts.Close() - - // Create a task that downloads a script and executes it. - alloc := mock.BatchAlloc() - alloc.Job.TaskGroups[0].RestartPolicy = &structs.RestartPolicy{} - task := alloc.Job.TaskGroups[0].Tasks[0] - task.RestartPolicy = &structs.RestartPolicy{} - task.Driver = "exec" - task.Config = map[string]interface{}{ - "command": "noop.sh", - } - - task.Artifacts = []*structs.TaskArtifact{ - { - GetterSource: fmt.Sprintf("%s/testdata/noop.sh", ts.URL), - GetterMode: "file", - RelativeDest: "noop.sh", - }, - } - - tr, _, cleanup := runTestTaskRunner(t, alloc, task.Name) - defer cleanup() - - // Wait for task to run and exit - testWaitForTaskToDie(t, tr) - - state := tr.TaskState() - require.Equal(t, structs.TaskStateDead, state.State) - require.False(t, state.Failed) -} - // TestTaskRunner_Download_Exec asserts that downloaded artifacts may be // executed in a driver without filesystem isolation. func TestTaskRunner_Download_RawExec(t *testing.T) { diff --git a/e2e/isolation/chroot_test.go b/e2e/isolation/chroot_test.go index 9f710adc4..89c72deb4 100644 --- a/e2e/isolation/chroot_test.go +++ b/e2e/isolation/chroot_test.go @@ -17,6 +17,7 @@ func TestChrootFS(t *testing.T) { t.Run("testTaskEnvChroot", testExecUsesChroot) t.Run("testTaskImageChroot", testImageUsesChroot) + t.Run("testDownloadChrootExec", testDownloadChrootExec) } func testExecUsesChroot(t *testing.T) { @@ -74,3 +75,28 @@ func testImageUsesChroot(t *testing.T) { must.RegexMatch(t, regexp.MustCompile(`(?m:^/secrets\b)`), logs) must.StrContains(t, logs, "/bin") } + +func testDownloadChrootExec(t *testing.T) { + nomad := e2eutil.NomadClient(t) + + jobID := "dl-chroot-exec" + uuid.Short() + jobIDs := []string{jobID} + t.Cleanup(e2eutil.CleanupJobsAndGC(t, &jobIDs)) + + // start job + e2eutil.RegisterAndWaitForAllocs(t, nomad, "./input/chroot_dl_exec.nomad", jobID, "") + + // get allocation + allocations, err := e2eutil.AllocsForJob(jobID, "") + must.NoError(t, err) + must.Len(t, 1, allocations) + allocID := allocations[0]["ID"] + + // wait for allocation stopped + e2eutil.WaitForAllocsStopped(t, nomad, []string{allocID}) + + // assert log contents + logs, err := e2eutil.AllocTaskLogs(allocID, "run-script", e2eutil.LogsStdOut) + must.NoError(t, err) + must.StrContains(t, logs, "this output is from a script") +} diff --git a/e2e/isolation/input/chroot_dl_exec.nomad b/e2e/isolation/input/chroot_dl_exec.nomad new file mode 100644 index 000000000..6edee70c8 --- /dev/null +++ b/e2e/isolation/input/chroot_dl_exec.nomad @@ -0,0 +1,67 @@ +job "chroot_dl_exec" { + datacenters = ["dc1"] + type = "batch" + constraint { + attribute = "${attr.kernel.name}" + value = "linux" + } + group "group" { + network { + mode = "host" + port "http" {} + } + task "script-writer" { + driver = "raw_exec" + config { + command = "/bin/bash" + args = [ + "-c", + "cd ${NOMAD_ALLOC_DIR} && chmod +x script.sh && tar -czf script.tar.gz script.sh" + ] + } + resources { + cpu = 10 + memory = 12 + } + template { + data = <