open-nomad/client/allocrunner/task_hook_coordinator_test.go

233 lines
7.2 KiB
Go

package allocrunner
import (
"testing"
"time"
"github.com/stretchr/testify/require"
"github.com/hashicorp/nomad/nomad/structs"
"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
task := tasks[0]
logger := testlog.HCLogger(t)
coord := newTaskHookCoordinator(logger, tasks)
ch := coord.startConditionForTask(task)
require.Truef(t, isChannelClosed(ch), "%s channel was open, should be closed", task.Name)
}
func TestTaskHookCoordinator_PrestartRunsBeforeMain(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)
}
func TestTaskHookCoordinator_MainRunsAfterPrestart(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.TaskStateRunning,
Failed: false,
StartedAt: time.Now(),
},
}
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.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.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: false,
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.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 {
select {
case <-ch:
return true
default:
return false
}
}