diff --git a/scheduler/util.go b/scheduler/util.go index 37a5b729db46..1069b5a331f5 100644 --- a/scheduler/util.go +++ b/scheduler/util.go @@ -341,6 +341,15 @@ func tasksUpdated(jobA, jobB *structs.Job, taskGroup string) bool { a := jobA.LookupTaskGroup(taskGroup) b := jobB.LookupTaskGroup(taskGroup) + // Check Job level Affinities and Constraints + if !reflect.DeepEqual(jobA.Affinities, jobB.Affinities) { + return true + } + + if !reflect.DeepEqual(jobA.Constraints, jobB.Constraints) { + return true + } + // If the number of tasks do not match, clearly there is an update if len(a.Tasks) != len(b.Tasks) { return true @@ -356,6 +365,16 @@ func tasksUpdated(jobA, jobB *structs.Job, taskGroup string) bool { return true } + // Check that the task group affinities haven't changed + if !reflect.DeepEqual(a.Affinities, b.Affinities) { + return true + } + + // Check that the task group constraints haven't changed + if !reflect.DeepEqual(a.Constraints, b.Constraints) { + return true + } + // Check each task for _, at := range a.Tasks { bt := b.LookupTask(at.Name) @@ -384,6 +403,14 @@ func tasksUpdated(jobA, jobB *structs.Job, taskGroup string) bool { return true } + if !reflect.DeepEqual(at.Affinities, bt.Affinities) { + return true + } + + if !reflect.DeepEqual(at.Constraints, bt.Constraints) { + return true + } + // Check the metadata if !reflect.DeepEqual( jobA.CombinedTaskMeta(taskGroup, at.Name), diff --git a/scheduler/util_test.go b/scheduler/util_test.go index 4983e592b63d..ab214d4f1caa 100644 --- a/scheduler/util_test.go +++ b/scheduler/util_test.go @@ -384,6 +384,89 @@ func TestShuffleNodes(t *testing.T) { require.False(t, reflect.DeepEqual(nodes, orig)) } +func TestTaskUpdatedAffinity(t *testing.T) { + j1 := mock.Job() + j2 := mock.Job() + name := j1.TaskGroups[0].Name + + require.False(t, tasksUpdated(j1, j2, name)) + + // TaskGroup Affinity + j2.TaskGroups[0].Affinities = []*structs.Affinity{ + { + LTarget: "", + RTarget: "", + Operand: "", + Weight: 100, + }, + } + require.True(t, tasksUpdated(j1, j2, name)) + + // TaskGroup Task Affinity + j3 := mock.Job() + j3.TaskGroups[0].Tasks[0].Affinities = []*structs.Affinity{ + { + LTarget: "", + RTarget: "", + Operand: "", + Weight: 100, + }, + } + + require.True(t, tasksUpdated(j1, j3, name)) + + j4 := mock.Job() + j4.TaskGroups[0].Tasks[0].Affinities = []*structs.Affinity{ + { + LTarget: "", + RTarget: "", + Operand: "", + Weight: 100, + }, + } + + require.True(t, tasksUpdated(j1, j4, name)) +} + +func TestTaskUpdated_Constraint(t *testing.T) { + j1 := mock.Job() + j2 := mock.Job() + name := j1.TaskGroups[0].Name + require.False(t, tasksUpdated(j1, j2, name)) + + // TaskGroup Constraint + j2.TaskGroups[0].Constraints = []*structs.Constraint{ + { + LTarget: "kernel", + RTarget: "linux", + Operand: "=", + }, + } + + // TaskGroup Task Constraint + j3 := mock.Job() + j3.TaskGroups[0].Tasks[0].Constraints = []*structs.Constraint{ + { + LTarget: "kernel", + RTarget: "linux", + Operand: "=", + }, + } + + require.True(t, tasksUpdated(j1, j3, name)) + + j4 := mock.Job() + j4.TaskGroups[0].Tasks[0].Constraints = []*structs.Constraint{ + { + LTarget: "kernel", + RTarget: "linux", + Operand: "=", + }, + } + + require.True(t, tasksUpdated(j1, j4, name)) +} + func TestTasksUpdated(t *testing.T) { j1 := mock.Job() j2 := mock.Job()