2019-12-04 20:44:21 +00:00
|
|
|
package allocrunner
|
|
|
|
|
|
|
|
import (
|
|
|
|
"testing"
|
2019-12-19 17:45:39 +00:00
|
|
|
"time"
|
|
|
|
|
2020-01-27 18:47:56 +00:00
|
|
|
"github.com/stretchr/testify/require"
|
|
|
|
|
2019-12-19 17:45:39 +00:00
|
|
|
"github.com/hashicorp/nomad/nomad/structs"
|
2019-12-04 20:44:21 +00:00
|
|
|
|
|
|
|
"github.com/hashicorp/nomad/helper/testlog"
|
|
|
|
"github.com/hashicorp/nomad/nomad/mock"
|
|
|
|
)
|
|
|
|
|
|
|
|
func TestTaskHookCoordinator_OnlyMainApp(t *testing.T) {
|
|
|
|
alloc := mock.Alloc()
|
|
|
|
tasks := alloc.Job.TaskGroups[0].Tasks
|
2020-01-27 18:47:56 +00:00
|
|
|
task := tasks[0]
|
2019-12-04 20:44:21 +00:00
|
|
|
logger := testlog.HCLogger(t)
|
|
|
|
|
|
|
|
coord := newTaskHookCoordinator(logger, tasks)
|
|
|
|
|
2020-01-27 18:47:56 +00:00
|
|
|
ch := coord.startConditionForTask(task)
|
2019-12-04 20:44:21 +00:00
|
|
|
|
2020-01-27 18:47:56 +00:00
|
|
|
require.Truef(t, isChannelClosed(ch), "%s channel was open, should be closed", task.Name)
|
2019-12-04 20:44:21 +00:00
|
|
|
}
|
2019-12-16 19:08:36 +00:00
|
|
|
|
2019-12-19 17:45:39 +00:00
|
|
|
func TestTaskHookCoordinator_PrestartRunsBeforeMain(t *testing.T) {
|
|
|
|
logger := testlog.HCLogger(t)
|
|
|
|
|
2020-01-30 19:44:18 +00:00
|
|
|
alloc := mock.LifecycleAlloc()
|
2019-12-16 19:08:36 +00:00
|
|
|
tasks := alloc.Job.TaskGroups[0].Tasks
|
|
|
|
|
2020-01-27 18:47:56 +00:00
|
|
|
mainTask := tasks[0]
|
2020-01-30 19:44:18 +00:00
|
|
|
sideTask := tasks[1]
|
|
|
|
initTask := tasks[2]
|
2019-12-19 17:45:39 +00:00
|
|
|
|
2020-01-27 18:47:56 +00:00
|
|
|
coord := newTaskHookCoordinator(logger, tasks)
|
|
|
|
initCh := coord.startConditionForTask(initTask)
|
|
|
|
sideCh := coord.startConditionForTask(sideTask)
|
2020-01-30 19:44:18 +00:00
|
|
|
mainCh := coord.startConditionForTask(mainTask)
|
2019-12-19 17:45:39 +00:00
|
|
|
|
2020-01-27 18:47:56 +00:00
|
|
|
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)
|
2020-01-30 19:44:18 +00:00
|
|
|
require.Falsef(t, isChannelClosed(mainCh), "%s channel was closed, should be open", mainTask.Name)
|
2019-12-19 17:45:39 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
func TestTaskHookCoordinator_MainRunsAfterPrestart(t *testing.T) {
|
|
|
|
logger := testlog.HCLogger(t)
|
|
|
|
|
2020-01-30 19:44:18 +00:00
|
|
|
alloc := mock.LifecycleAlloc()
|
2019-12-19 17:45:39 +00:00
|
|
|
tasks := alloc.Job.TaskGroups[0].Tasks
|
2019-12-16 19:08:36 +00:00
|
|
|
|
2020-01-30 19:44:18 +00:00
|
|
|
mainTask := tasks[0]
|
|
|
|
sideTask := tasks[1]
|
|
|
|
initTask := tasks[2]
|
2019-12-16 19:08:36 +00:00
|
|
|
|
2020-01-30 19:44:18 +00:00
|
|
|
coord := newTaskHookCoordinator(logger, tasks)
|
|
|
|
initCh := coord.startConditionForTask(initTask)
|
|
|
|
sideCh := coord.startConditionForTask(sideTask)
|
|
|
|
mainCh := coord.startConditionForTask(mainTask)
|
2019-12-19 17:45:39 +00:00
|
|
|
|
2020-01-30 19:44:18 +00:00
|
|
|
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)
|
2019-12-19 17:45:39 +00:00
|
|
|
|
|
|
|
states := map[string]*structs.TaskState{
|
2020-01-30 19:44:18 +00:00
|
|
|
mainTask.Name: {
|
2019-12-19 17:45:39 +00:00
|
|
|
State: structs.TaskStatePending,
|
|
|
|
Failed: false,
|
|
|
|
},
|
2020-01-30 19:44:18 +00:00
|
|
|
initTask.Name: {
|
2019-12-19 17:45:39 +00:00
|
|
|
State: structs.TaskStateDead,
|
|
|
|
Failed: false,
|
|
|
|
StartedAt: time.Now(),
|
|
|
|
FinishedAt: time.Now(),
|
|
|
|
},
|
2020-01-30 19:44:18 +00:00
|
|
|
sideTask.Name: {
|
2019-12-19 17:45:39 +00:00
|
|
|
State: structs.TaskStateRunning,
|
|
|
|
Failed: false,
|
|
|
|
StartedAt: time.Now(),
|
|
|
|
},
|
|
|
|
}
|
|
|
|
|
|
|
|
coord.taskStateUpdated(states)
|
|
|
|
|
2020-01-30 19:44:18 +00:00
|
|
|
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)
|
2019-12-19 17:45:39 +00:00
|
|
|
}
|
|
|
|
|
2020-01-29 01:47:21 +00:00
|
|
|
func TestTaskHookCoordinator_MainRunsAfterManyInitTasks(t *testing.T) {
|
|
|
|
logger := testlog.HCLogger(t)
|
|
|
|
|
2020-01-30 19:44:18 +00:00
|
|
|
alloc := mock.LifecycleAlloc()
|
|
|
|
alloc.Job = mock.VariableLifecycleJob(structs.Resources{CPU: 100, MemoryMB: 256}, 1, 2, 0)
|
2020-01-29 01:47:21 +00:00
|
|
|
tasks := alloc.Job.TaskGroups[0].Tasks
|
|
|
|
|
2020-01-30 19:44:18 +00:00
|
|
|
mainTask := tasks[0]
|
|
|
|
init1Task := tasks[1]
|
|
|
|
init2Task := tasks[2]
|
2020-01-29 01:47:21 +00:00
|
|
|
|
|
|
|
coord := newTaskHookCoordinator(logger, tasks)
|
2020-01-30 19:44:18 +00:00
|
|
|
mainCh := coord.startConditionForTask(mainTask)
|
|
|
|
init1Ch := coord.startConditionForTask(init1Task)
|
|
|
|
init2Ch := coord.startConditionForTask(init2Task)
|
2020-01-29 01:47:21 +00:00
|
|
|
|
2020-01-30 19:44:18 +00:00
|
|
|
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)
|
2020-01-29 01:47:21 +00:00
|
|
|
|
|
|
|
states := map[string]*structs.TaskState{
|
2020-01-30 19:44:18 +00:00
|
|
|
mainTask.Name: {
|
2020-01-29 01:47:21 +00:00
|
|
|
State: structs.TaskStatePending,
|
|
|
|
Failed: false,
|
|
|
|
},
|
2020-01-30 19:44:18 +00:00
|
|
|
init1Task.Name: {
|
2020-01-29 01:47:21 +00:00
|
|
|
State: structs.TaskStateDead,
|
|
|
|
Failed: false,
|
|
|
|
StartedAt: time.Now(),
|
|
|
|
FinishedAt: time.Now(),
|
|
|
|
},
|
2020-01-30 19:44:18 +00:00
|
|
|
init2Task.Name: {
|
2020-01-29 01:47:21 +00:00
|
|
|
State: structs.TaskStateDead,
|
|
|
|
Failed: false,
|
|
|
|
StartedAt: time.Now(),
|
|
|
|
},
|
|
|
|
}
|
|
|
|
|
|
|
|
coord.taskStateUpdated(states)
|
|
|
|
|
2020-01-30 19:44:18 +00:00
|
|
|
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)
|
2020-01-29 01:47:21 +00:00
|
|
|
}
|
|
|
|
|
2020-01-30 19:44:18 +00:00
|
|
|
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(),
|
|
|
|
},
|
2019-12-19 17:45:39 +00:00
|
|
|
}
|
2020-01-30 19:44:18 +00:00
|
|
|
|
|
|
|
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)
|
2019-12-19 17:45:39 +00:00
|
|
|
}
|
|
|
|
|
2020-01-30 19:44:18 +00:00
|
|
|
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,
|
2019-12-19 17:45:39 +00:00
|
|
|
},
|
|
|
|
}
|
2020-01-30 19:44:18 +00:00
|
|
|
|
|
|
|
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)
|
2019-12-19 17:45:39 +00:00
|
|
|
}
|
|
|
|
|
2020-01-30 19:44:18 +00:00
|
|
|
func isChannelClosed(ch <-chan struct{}) bool {
|
|
|
|
select {
|
|
|
|
case <-ch:
|
|
|
|
return true
|
|
|
|
default:
|
|
|
|
return false
|
2019-12-16 19:08:36 +00:00
|
|
|
}
|
|
|
|
}
|