diff --git a/client/allocrunner/task_hook_coordinator_test.go b/client/allocrunner/task_hook_coordinator_test.go index b6e57ef54..91802f102 100644 --- a/client/allocrunner/task_hook_coordinator_test.go +++ b/client/allocrunner/task_hook_coordinator_test.go @@ -28,58 +28,54 @@ func TestTaskHookCoordinator_OnlyMainApp(t *testing.T) { func TestTaskHookCoordinator_PrestartRunsBeforeMain(t *testing.T) { logger := testlog.HCLogger(t) - alloc := mock.Alloc() + alloc := mock.LifecycleAlloc() tasks := alloc.Job.TaskGroups[0].Tasks - tasks = append(tasks, initTask()) - tasks = append(tasks, sidecarTask()) mainTask := tasks[0] - initTask := tasks[1] - sideTask := tasks[2] + sideTask := tasks[1] + initTask := tasks[2] coord := newTaskHookCoordinator(logger, tasks) - mainCh := coord.startConditionForTask(mainTask) initCh := coord.startConditionForTask(initTask) sideCh := coord.startConditionForTask(sideTask) + mainCh := coord.startConditionForTask(mainTask) - require.Falsef(t, isChannelClosed(mainCh), "%s channel was closed, should be open", mainTask.Name) require.Truef(t, isChannelClosed(initCh), "%s channel was open, should be closed", initTask.Name) require.Truef(t, isChannelClosed(sideCh), "%s channel was open, should be closed", sideTask.Name) + require.Falsef(t, isChannelClosed(mainCh), "%s channel was closed, should be open", mainTask.Name) } func TestTaskHookCoordinator_MainRunsAfterPrestart(t *testing.T) { logger := testlog.HCLogger(t) - alloc := mock.Alloc() + alloc := mock.LifecycleAlloc() tasks := alloc.Job.TaskGroups[0].Tasks - tasks = append(tasks, initTask()) - tasks = append(tasks, sidecarTask()) + + mainTask := tasks[0] + sideTask := tasks[1] + initTask := tasks[2] coord := newTaskHookCoordinator(logger, tasks) - mainCh := coord.startConditionForTask(tasks[0]) - initCh := coord.startConditionForTask(tasks[1]) - sideCh := coord.startConditionForTask(tasks[2]) + initCh := coord.startConditionForTask(initTask) + sideCh := coord.startConditionForTask(sideTask) + mainCh := coord.startConditionForTask(mainTask) - mainTaskName := tasks[0].Name - initTaskName := tasks[1].Name - sideTaskName := tasks[2].Name - - require.Falsef(t, isChannelClosed(mainCh), "%s channel was closed, should be open", mainTaskName) - require.Truef(t, isChannelClosed(initCh), "%s channel was open, should be closed", initTaskName) - require.Truef(t, isChannelClosed(sideCh), "%s channel was open, should be closed", sideTaskName) + require.Truef(t, isChannelClosed(initCh), "%s channel was open, should be closed", initTask.Name) + require.Truef(t, isChannelClosed(sideCh), "%s channel was open, should be closed", sideTask.Name) + require.Falsef(t, isChannelClosed(mainCh), "%s channel was closed, should be open", mainTask.Name) states := map[string]*structs.TaskState{ - mainTaskName: { + mainTask.Name: { State: structs.TaskStatePending, Failed: false, }, - initTaskName: { + initTask.Name: { State: structs.TaskStateDead, Failed: false, StartedAt: time.Now(), FinishedAt: time.Now(), }, - sideTaskName: { + sideTask.Name: { State: structs.TaskStateRunning, Failed: false, StartedAt: time.Now(), @@ -88,45 +84,43 @@ func TestTaskHookCoordinator_MainRunsAfterPrestart(t *testing.T) { coord.taskStateUpdated(states) - require.Truef(t, isChannelClosed(initCh), "%s channel was open, should be closed", mainTaskName) - require.Truef(t, isChannelClosed(initCh), "%s channel was open, should be closed", initTaskName) - require.Truef(t, isChannelClosed(sideCh), "%s channel was open, should be closed", sideTaskName) + require.Truef(t, isChannelClosed(initCh), "%s channel was open, should be closed", initTask.Name) + require.Truef(t, isChannelClosed(sideCh), "%s channel was open, should be closed", sideTask.Name) + require.Truef(t, isChannelClosed(mainCh), "%s channel was open, should be closed", mainTask.Name) } func TestTaskHookCoordinator_MainRunsAfterManyInitTasks(t *testing.T) { logger := testlog.HCLogger(t) - alloc := mock.Alloc() + alloc := mock.LifecycleAlloc() + alloc.Job = mock.VariableLifecycleJob(structs.Resources{CPU: 100, MemoryMB: 256}, 1, 2, 0) tasks := alloc.Job.TaskGroups[0].Tasks - init1 := initTask() - init1.Name = "init-1" - init2 := initTask() - init2.Name = "init-2" - tasks = append(tasks, init1) - tasks = append(tasks, init2) + mainTask := tasks[0] + init1Task := tasks[1] + init2Task := tasks[2] coord := newTaskHookCoordinator(logger, tasks) - mainCh := coord.startConditionForTask(tasks[0]) - init1Ch := coord.startConditionForTask(tasks[1]) - init2Ch := coord.startConditionForTask(tasks[2]) + mainCh := coord.startConditionForTask(mainTask) + init1Ch := coord.startConditionForTask(init1Task) + init2Ch := coord.startConditionForTask(init2Task) - require.Falsef(t, isChannelClosed(mainCh), "%s channel was closed, should be open", tasks[0].Name) - require.Truef(t, isChannelClosed(init1Ch), "%s channel was open, should be closed", tasks[1].Name) - require.Truef(t, isChannelClosed(init2Ch), "%s channel was open, should be closed", tasks[2].Name) + require.Truef(t, isChannelClosed(init1Ch), "%s channel was open, should be closed", init1Task.Name) + require.Truef(t, isChannelClosed(init2Ch), "%s channel was open, should be closed", init2Task.Name) + require.Falsef(t, isChannelClosed(mainCh), "%s channel was closed, should be open", mainTask.Name) states := map[string]*structs.TaskState{ - tasks[0].Name: { + mainTask.Name: { State: structs.TaskStatePending, Failed: false, }, - tasks[1].Name: { + init1Task.Name: { State: structs.TaskStateDead, Failed: false, StartedAt: time.Now(), FinishedAt: time.Now(), }, - tasks[2].Name: { + init2Task.Name: { State: structs.TaskStateDead, Failed: false, StartedAt: time.Now(), @@ -135,9 +129,97 @@ func TestTaskHookCoordinator_MainRunsAfterManyInitTasks(t *testing.T) { coord.taskStateUpdated(states) - require.Truef(t, isChannelClosed(init1Ch), "%s channel was open, should be closed", tasks[0].Name) - require.Truef(t, isChannelClosed(init2Ch), "%s channel was open, should be closed", tasks[1].Name) - require.Truef(t, isChannelClosed(mainCh), "%s channel was open, should be closed", tasks[2].Name) + require.Truef(t, isChannelClosed(init1Ch), "%s channel was open, should be closed", init1Task.Name) + require.Truef(t, isChannelClosed(init2Ch), "%s channel was open, should be closed", init2Task.Name) + require.Truef(t, isChannelClosed(mainCh), "%s channel was open, should be closed", mainTask.Name) +} + +func TestTaskHookCoordinator_FailedInitTask(t *testing.T) { + logger := testlog.HCLogger(t) + + alloc := mock.LifecycleAlloc() + alloc.Job = mock.VariableLifecycleJob(structs.Resources{CPU: 100, MemoryMB: 256}, 1, 2, 0) + tasks := alloc.Job.TaskGroups[0].Tasks + + mainTask := tasks[0] + init1Task := tasks[1] + init2Task := tasks[2] + + coord := newTaskHookCoordinator(logger, tasks) + mainCh := coord.startConditionForTask(mainTask) + init1Ch := coord.startConditionForTask(init1Task) + init2Ch := coord.startConditionForTask(init2Task) + + require.Truef(t, isChannelClosed(init1Ch), "%s channel was open, should be closed", init1Task.Name) + require.Truef(t, isChannelClosed(init2Ch), "%s channel was open, should be closed", init2Task.Name) + require.Falsef(t, isChannelClosed(mainCh), "%s channel was closed, should be open", mainTask.Name) + + states := map[string]*structs.TaskState{ + mainTask.Name: { + State: structs.TaskStatePending, + Failed: false, + }, + init1Task.Name: { + State: structs.TaskStateDead, + Failed: false, + StartedAt: time.Now(), + FinishedAt: time.Now(), + }, + init2Task.Name: { + State: structs.TaskStateDead, + Failed: true, + StartedAt: time.Now(), + }, + } + + coord.taskStateUpdated(states) + + require.Truef(t, isChannelClosed(init1Ch), "%s channel was open, should be closed", init1Task.Name) + require.Truef(t, isChannelClosed(init2Ch), "%s channel was open, should be closed", init2Task.Name) + require.Falsef(t, isChannelClosed(mainCh), "%s channel was closed, should be open", mainTask.Name) +} + +func TestTaskHookCoordinator_SidecarNeverStarts(t *testing.T) { + logger := testlog.HCLogger(t) + + alloc := mock.LifecycleAlloc() + tasks := alloc.Job.TaskGroups[0].Tasks + + mainTask := tasks[0] + sideTask := tasks[1] + initTask := tasks[2] + + coord := newTaskHookCoordinator(logger, tasks) + initCh := coord.startConditionForTask(initTask) + sideCh := coord.startConditionForTask(sideTask) + mainCh := coord.startConditionForTask(mainTask) + + require.Truef(t, isChannelClosed(initCh), "%s channel was open, should be closed", initTask.Name) + require.Truef(t, isChannelClosed(sideCh), "%s channel was open, should be closed", sideTask.Name) + require.Falsef(t, isChannelClosed(mainCh), "%s channel was closed, should be open", mainTask.Name) + + states := map[string]*structs.TaskState{ + mainTask.Name: { + State: structs.TaskStatePending, + Failed: false, + }, + initTask.Name: { + State: structs.TaskStateDead, + Failed: false, + StartedAt: time.Now(), + FinishedAt: time.Now(), + }, + sideTask.Name: { + State: structs.TaskStatePending, + Failed: false, + }, + } + + coord.taskStateUpdated(states) + + require.Truef(t, isChannelClosed(initCh), "%s channel was open, should be closed", initTask.Name) + require.Truef(t, isChannelClosed(sideCh), "%s channel was open, should be closed", sideTask.Name) + require.Falsef(t, isChannelClosed(mainCh), "%s channel was closed, should be open", mainTask.Name) } func isChannelClosed(ch <-chan struct{}) bool { @@ -148,23 +230,3 @@ func isChannelClosed(ch <-chan struct{}) bool { return false } } - -func sidecarTask() *structs.Task { - return &structs.Task{ - Name: "sidecar", - Lifecycle: &structs.TaskLifecycleConfig{ - Hook: structs.TaskLifecycleHookPrestart, - BlockUntil: structs.TaskLifecycleBlockUntilRunning, - }, - } -} - -func initTask() *structs.Task { - return &structs.Task{ - Name: "init", - Lifecycle: &structs.TaskLifecycleConfig{ - Hook: structs.TaskLifecycleHookPrestart, - BlockUntil: structs.TaskLifecycleBlockUntilCompleted, - }, - } -}