mirror of
https://github.com/kemko/nomad.git
synced 2026-01-01 16:05:42 +03:00
testing: migrate nomad/scheduler off of testify (#25968)
In the spirit of #25909, this PR removes testify dependencies from the scheduler package, along with reflect.DeepEqual removal. This is again a combination of semgrep and hx editing magic. --------- Co-authored-by: Tim Gross <tgross@hashicorp.com>
This commit is contained in:
committed by
GitHub
parent
34e96932a1
commit
648bacda77
@@ -29,3 +29,4 @@ rules:
|
|||||||
paths:
|
paths:
|
||||||
include:
|
include:
|
||||||
- "nomad/state/*_test.go"
|
- "nomad/state/*_test.go"
|
||||||
|
- "nomad/scheduler/*_test.go"
|
||||||
|
|||||||
@@ -4,11 +4,11 @@
|
|||||||
package scheduler
|
package scheduler
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"reflect"
|
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"github.com/hashicorp/nomad/ci"
|
"github.com/hashicorp/nomad/ci"
|
||||||
"github.com/hashicorp/nomad/nomad/structs"
|
"github.com/hashicorp/nomad/nomad/structs"
|
||||||
|
"github.com/shoenig/test/must"
|
||||||
)
|
)
|
||||||
|
|
||||||
func TestAnnotateTaskGroup_Updates(t *testing.T) {
|
func TestAnnotateTaskGroup_Updates(t *testing.T) {
|
||||||
@@ -50,9 +50,8 @@ func TestAnnotateTaskGroup_Updates(t *testing.T) {
|
|||||||
t.Fatalf("annotateTaskGroup(%#v, %#v) failed: %#v", tgDiff, annotations, err)
|
t.Fatalf("annotateTaskGroup(%#v, %#v) failed: %#v", tgDiff, annotations, err)
|
||||||
}
|
}
|
||||||
|
|
||||||
if !reflect.DeepEqual(tgDiff, expected) {
|
must.Eq(t, expected, tgDiff)
|
||||||
t.Fatalf("got %#v, want %#v", tgDiff, expected)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestAnnotateCountChange_NonEdited(t *testing.T) {
|
func TestAnnotateCountChange_NonEdited(t *testing.T) {
|
||||||
@@ -61,9 +60,8 @@ func TestAnnotateCountChange_NonEdited(t *testing.T) {
|
|||||||
tg := &structs.TaskGroupDiff{}
|
tg := &structs.TaskGroupDiff{}
|
||||||
tgOrig := &structs.TaskGroupDiff{}
|
tgOrig := &structs.TaskGroupDiff{}
|
||||||
annotateCountChange(tg)
|
annotateCountChange(tg)
|
||||||
if !reflect.DeepEqual(tgOrig, tg) {
|
must.Eq(t, tgOrig, tg)
|
||||||
t.Fatalf("annotateCountChange(%#v) should not have caused any annotation: %#v", tgOrig, tg)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestAnnotateCountChange(t *testing.T) {
|
func TestAnnotateCountChange(t *testing.T) {
|
||||||
@@ -116,9 +114,8 @@ func TestAnnotateTask_NonEdited(t *testing.T) {
|
|||||||
td := &structs.TaskDiff{Type: structs.DiffTypeNone}
|
td := &structs.TaskDiff{Type: structs.DiffTypeNone}
|
||||||
tdOrig := &structs.TaskDiff{Type: structs.DiffTypeNone}
|
tdOrig := &structs.TaskDiff{Type: structs.DiffTypeNone}
|
||||||
annotateTask(td, tgd)
|
annotateTask(td, tgd)
|
||||||
if !reflect.DeepEqual(tdOrig, td) {
|
must.Eq(t, tdOrig, td)
|
||||||
t.Fatalf("annotateTask(%#v) should not have caused any annotation: %#v", tdOrig, td)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestAnnotateTask(t *testing.T) {
|
func TestAnnotateTask(t *testing.T) {
|
||||||
|
|||||||
@@ -16,7 +16,7 @@ import (
|
|||||||
|
|
||||||
"github.com/hashicorp/nomad/helper/raftutil"
|
"github.com/hashicorp/nomad/helper/raftutil"
|
||||||
"github.com/hashicorp/nomad/scheduler"
|
"github.com/hashicorp/nomad/scheduler"
|
||||||
"github.com/stretchr/testify/require"
|
"github.com/shoenig/test/must"
|
||||||
)
|
)
|
||||||
|
|
||||||
// NewBenchmarkingHarness creates a starting test harness with state
|
// NewBenchmarkingHarness creates a starting test harness with state
|
||||||
@@ -30,13 +30,13 @@ func NewBenchmarkingHarness(t testing.TB) *scheduler.Harness {
|
|||||||
datadir := os.Getenv("NOMAD_BENCHMARK_DATADIR")
|
datadir := os.Getenv("NOMAD_BENCHMARK_DATADIR")
|
||||||
if datadir != "" {
|
if datadir != "" {
|
||||||
h, err := NewHarnessFromDataDir(t, datadir)
|
h, err := NewHarnessFromDataDir(t, datadir)
|
||||||
require.NoError(t, err)
|
must.NoError(t, err)
|
||||||
return h
|
return h
|
||||||
} else {
|
} else {
|
||||||
snapshotPath := os.Getenv("NOMAD_BENCHMARK_SNAPSHOT")
|
snapshotPath := os.Getenv("NOMAD_BENCHMARK_SNAPSHOT")
|
||||||
if snapshotPath != "" {
|
if snapshotPath != "" {
|
||||||
h, err := NewHarnessFromSnapshot(t, snapshotPath)
|
h, err := NewHarnessFromSnapshot(t, snapshotPath)
|
||||||
require.NoError(t, err)
|
must.NoError(t, err)
|
||||||
return h
|
return h
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -16,7 +16,6 @@ import (
|
|||||||
"github.com/hashicorp/nomad/nomad/state"
|
"github.com/hashicorp/nomad/nomad/state"
|
||||||
"github.com/hashicorp/nomad/nomad/structs"
|
"github.com/hashicorp/nomad/nomad/structs"
|
||||||
"github.com/shoenig/test/must"
|
"github.com/shoenig/test/must"
|
||||||
"github.com/stretchr/testify/require"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
func testContext(t testing.TB) (*state.StateStore, *EvalContext) {
|
func testContext(t testing.TB) (*state.StateStore, *EvalContext) {
|
||||||
@@ -160,9 +159,9 @@ func TestEvalContext_ProposedAlloc(t *testing.T) {
|
|||||||
ClientStatus: structs.AllocClientStatusPending,
|
ClientStatus: structs.AllocClientStatusPending,
|
||||||
TaskGroup: "web",
|
TaskGroup: "web",
|
||||||
}
|
}
|
||||||
require.NoError(t, state.UpsertJobSummary(998, mock.JobSummary(alloc1.JobID)))
|
must.NoError(t, state.UpsertJobSummary(998, mock.JobSummary(alloc1.JobID)))
|
||||||
require.NoError(t, state.UpsertJobSummary(999, mock.JobSummary(alloc2.JobID)))
|
must.NoError(t, state.UpsertJobSummary(999, mock.JobSummary(alloc2.JobID)))
|
||||||
require.NoError(t, state.UpsertAllocs(structs.MsgTypeTestSetup, 1000, []*structs.Allocation{alloc1, alloc2}))
|
must.NoError(t, state.UpsertAllocs(structs.MsgTypeTestSetup, 1000, []*structs.Allocation{alloc1, alloc2}))
|
||||||
|
|
||||||
// Add a planned eviction to alloc1
|
// Add a planned eviction to alloc1
|
||||||
plan := ctx.Plan()
|
plan := ctx.Plan()
|
||||||
@@ -299,10 +298,10 @@ func TestEvalContext_ProposedAlloc_EvictPreempt(t *testing.T) {
|
|||||||
ClientStatus: structs.AllocClientStatusPending,
|
ClientStatus: structs.AllocClientStatusPending,
|
||||||
TaskGroup: "web",
|
TaskGroup: "web",
|
||||||
}
|
}
|
||||||
require.NoError(t, state.UpsertJobSummary(998, mock.JobSummary(allocEvict.JobID)))
|
must.NoError(t, state.UpsertJobSummary(998, mock.JobSummary(allocEvict.JobID)))
|
||||||
require.NoError(t, state.UpsertJobSummary(999, mock.JobSummary(allocPreempt.JobID)))
|
must.NoError(t, state.UpsertJobSummary(999, mock.JobSummary(allocPreempt.JobID)))
|
||||||
require.NoError(t, state.UpsertJobSummary(999, mock.JobSummary(allocPropose.JobID)))
|
must.NoError(t, state.UpsertJobSummary(999, mock.JobSummary(allocPropose.JobID)))
|
||||||
require.NoError(t, state.UpsertAllocs(structs.MsgTypeTestSetup, 1000, []*structs.Allocation{allocEvict, allocPreempt, allocPropose}))
|
must.NoError(t, state.UpsertAllocs(structs.MsgTypeTestSetup, 1000, []*structs.Allocation{allocEvict, allocPreempt, allocPropose}))
|
||||||
|
|
||||||
// Plan to evict one alloc and preempt another
|
// Plan to evict one alloc and preempt another
|
||||||
plan := ctx.Plan()
|
plan := ctx.Plan()
|
||||||
@@ -310,8 +309,8 @@ func TestEvalContext_ProposedAlloc_EvictPreempt(t *testing.T) {
|
|||||||
plan.NodeUpdate[nodes[0].Node.ID] = []*structs.Allocation{allocPreempt}
|
plan.NodeUpdate[nodes[0].Node.ID] = []*structs.Allocation{allocPreempt}
|
||||||
|
|
||||||
proposed, err := ctx.ProposedAllocs(nodes[0].Node.ID)
|
proposed, err := ctx.ProposedAllocs(nodes[0].Node.ID)
|
||||||
require.NoError(t, err)
|
must.NoError(t, err)
|
||||||
require.Len(t, proposed, 1)
|
must.SliceLen(t, 1, proposed)
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestEvalEligibility_JobStatus(t *testing.T) {
|
func TestEvalEligibility_JobStatus(t *testing.T) {
|
||||||
@@ -431,7 +430,7 @@ func TestEvalEligibility_GetClasses(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
actClasses := e.GetClasses()
|
actClasses := e.GetClasses()
|
||||||
require.Equal(t, expClasses, actClasses)
|
must.Eq(t, expClasses, actClasses)
|
||||||
}
|
}
|
||||||
func TestEvalEligibility_GetClasses_JobEligible_TaskGroupIneligible(t *testing.T) {
|
func TestEvalEligibility_GetClasses_JobEligible_TaskGroupIneligible(t *testing.T) {
|
||||||
ci.Parallel(t)
|
ci.Parallel(t)
|
||||||
@@ -455,7 +454,7 @@ func TestEvalEligibility_GetClasses_JobEligible_TaskGroupIneligible(t *testing.T
|
|||||||
}
|
}
|
||||||
|
|
||||||
actClasses := e.GetClasses()
|
actClasses := e.GetClasses()
|
||||||
require.Equal(t, expClasses, actClasses)
|
must.Eq(t, expClasses, actClasses)
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestPortCollisionEvent_Copy(t *testing.T) {
|
func TestPortCollisionEvent_Copy(t *testing.T) {
|
||||||
@@ -503,6 +502,6 @@ func TestPortCollisionEvent_Sanitize(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
cleanEv := ev.Sanitize()
|
cleanEv := ev.Sanitize()
|
||||||
require.Empty(t, cleanEv.Node.SecretID)
|
must.Eq(t, "", cleanEv.Node.SecretID)
|
||||||
require.Nil(t, cleanEv.Allocations[0].Job)
|
must.Nil(t, cleanEv.Allocations[0].Job)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -14,7 +14,6 @@ import (
|
|||||||
"github.com/hashicorp/nomad/nomad/structs"
|
"github.com/hashicorp/nomad/nomad/structs"
|
||||||
psstructs "github.com/hashicorp/nomad/plugins/shared/structs"
|
psstructs "github.com/hashicorp/nomad/plugins/shared/structs"
|
||||||
"github.com/shoenig/test/must"
|
"github.com/shoenig/test/must"
|
||||||
"github.com/stretchr/testify/require"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
func anyMemoryNodeMatcher() *memoryNodeMatcher {
|
func anyMemoryNodeMatcher() *memoryNodeMatcher {
|
||||||
@@ -103,68 +102,64 @@ func collectInstanceIDs(devices ...*structs.NodeDeviceResource) []string {
|
|||||||
func TestDeviceAllocator_Allocate_GenericRequest(t *testing.T) {
|
func TestDeviceAllocator_Allocate_GenericRequest(t *testing.T) {
|
||||||
ci.Parallel(t)
|
ci.Parallel(t)
|
||||||
|
|
||||||
require := require.New(t)
|
|
||||||
_, ctx := testContext(t)
|
_, ctx := testContext(t)
|
||||||
n := devNode()
|
n := devNode()
|
||||||
d := newDeviceAllocator(ctx, n)
|
d := newDeviceAllocator(ctx, n)
|
||||||
require.NotNil(d)
|
must.NotNil(t, d)
|
||||||
|
|
||||||
// Build the request
|
// Build the request
|
||||||
ask := deviceRequest("gpu", 1, nil, nil)
|
ask := deviceRequest("gpu", 1, nil, nil)
|
||||||
|
|
||||||
mem := anyMemoryNodeMatcher()
|
mem := anyMemoryNodeMatcher()
|
||||||
out, score, err := d.createOffer(mem, ask)
|
out, score, err := d.createOffer(mem, ask)
|
||||||
require.NotNil(out)
|
must.NotNil(t, out)
|
||||||
require.Zero(score)
|
must.Zero(t, score)
|
||||||
require.NoError(err)
|
must.NoError(t, err)
|
||||||
|
|
||||||
// Check that we got the nvidia device
|
// Check that we got the nvidia device
|
||||||
require.Len(out.DeviceIDs, 1)
|
must.SliceLen(t, 1, out.DeviceIDs)
|
||||||
require.Contains(collectInstanceIDs(n.NodeResources.Devices[0]), out.DeviceIDs[0])
|
must.SliceContains(t, collectInstanceIDs(n.NodeResources.Devices[0]), out.DeviceIDs[0])
|
||||||
}
|
}
|
||||||
|
|
||||||
// Test that asking for a device that is fully specified works.
|
// Test that asking for a device that is fully specified works.
|
||||||
func TestDeviceAllocator_Allocate_FullyQualifiedRequest(t *testing.T) {
|
func TestDeviceAllocator_Allocate_FullyQualifiedRequest(t *testing.T) {
|
||||||
ci.Parallel(t)
|
ci.Parallel(t)
|
||||||
|
|
||||||
require := require.New(t)
|
|
||||||
_, ctx := testContext(t)
|
_, ctx := testContext(t)
|
||||||
n := devNode()
|
n := devNode()
|
||||||
d := newDeviceAllocator(ctx, n)
|
d := newDeviceAllocator(ctx, n)
|
||||||
require.NotNil(d)
|
must.NotNil(t, d)
|
||||||
|
|
||||||
// Build the request
|
// Build the request
|
||||||
ask := deviceRequest("intel/fpga/F100", 1, nil, nil)
|
ask := deviceRequest("intel/fpga/F100", 1, nil, nil)
|
||||||
|
|
||||||
mem := anyMemoryNodeMatcher()
|
mem := anyMemoryNodeMatcher()
|
||||||
out, score, err := d.createOffer(mem, ask)
|
out, score, err := d.createOffer(mem, ask)
|
||||||
require.NotNil(out)
|
must.NotNil(t, out)
|
||||||
require.Zero(score)
|
must.Zero(t, score)
|
||||||
require.NoError(err)
|
must.NoError(t, err)
|
||||||
|
|
||||||
// Check that we got the nvidia device
|
// Check that we got the nvidia device
|
||||||
require.Len(out.DeviceIDs, 1)
|
must.SliceLen(t, 1, out.DeviceIDs)
|
||||||
require.Contains(collectInstanceIDs(n.NodeResources.Devices[1]), out.DeviceIDs[0])
|
must.SliceContains(t, collectInstanceIDs(n.NodeResources.Devices[1]), out.DeviceIDs[0])
|
||||||
}
|
}
|
||||||
|
|
||||||
// Test that asking for a device with too much count doesn't place
|
// Test that asking for a device with too much count doesn't place
|
||||||
func TestDeviceAllocator_Allocate_NotEnoughInstances(t *testing.T) {
|
func TestDeviceAllocator_Allocate_NotEnoughInstances(t *testing.T) {
|
||||||
ci.Parallel(t)
|
ci.Parallel(t)
|
||||||
|
|
||||||
require := require.New(t)
|
|
||||||
_, ctx := testContext(t)
|
_, ctx := testContext(t)
|
||||||
n := devNode()
|
n := devNode()
|
||||||
d := newDeviceAllocator(ctx, n)
|
d := newDeviceAllocator(ctx, n)
|
||||||
require.NotNil(d)
|
must.NotNil(t, d)
|
||||||
|
|
||||||
// Build the request
|
// Build the request
|
||||||
ask := deviceRequest("gpu", 4, nil, nil)
|
ask := deviceRequest("gpu", 4, nil, nil)
|
||||||
|
|
||||||
mem := anyMemoryNodeMatcher()
|
mem := anyMemoryNodeMatcher()
|
||||||
out, _, err := d.createOffer(mem, ask)
|
out, _, err := d.createOffer(mem, ask)
|
||||||
require.Nil(out)
|
must.Nil(t, out)
|
||||||
require.Error(err)
|
must.ErrorContains(t, err, "no devices match request")
|
||||||
require.Contains(err.Error(), "no devices match request")
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestDeviceAllocator_Allocate_NUMA_available(t *testing.T) {
|
func TestDeviceAllocator_Allocate_NUMA_available(t *testing.T) {
|
||||||
@@ -338,14 +333,14 @@ func TestDeviceAllocator_Allocate_Constraints(t *testing.T) {
|
|||||||
mem := anyMemoryNodeMatcher()
|
mem := anyMemoryNodeMatcher()
|
||||||
out, score, err := d.createOffer(mem, ask)
|
out, score, err := d.createOffer(mem, ask)
|
||||||
if c.NoPlacement {
|
if c.NoPlacement {
|
||||||
require.Nil(t, out)
|
must.Nil(t, out)
|
||||||
} else {
|
} else {
|
||||||
must.NotNil(t, out)
|
must.NotNil(t, out)
|
||||||
must.Zero(t, score)
|
must.Zero(t, score)
|
||||||
must.NoError(t, err)
|
must.NoError(t, err)
|
||||||
|
|
||||||
// Check that we got the right nvidia device instance, and
|
// Check that we got the right nvidia device instance, and
|
||||||
// specific device instance IDs if required
|
// specific device instance IDs if mustd
|
||||||
must.Len(t, 1, out.DeviceIDs)
|
must.Len(t, 1, out.DeviceIDs)
|
||||||
must.SliceContains(t, collectInstanceIDs(c.ExpectedDevice), out.DeviceIDs[0])
|
must.SliceContains(t, collectInstanceIDs(c.ExpectedDevice), out.DeviceIDs[0])
|
||||||
must.SliceContainsSubset(t, c.ExpectedDeviceIDs, out.DeviceIDs)
|
must.SliceContainsSubset(t, c.ExpectedDeviceIDs, out.DeviceIDs)
|
||||||
@@ -434,27 +429,26 @@ func TestDeviceAllocator_Allocate_Affinities(t *testing.T) {
|
|||||||
|
|
||||||
for _, c := range cases {
|
for _, c := range cases {
|
||||||
t.Run(c.Name, func(t *testing.T) {
|
t.Run(c.Name, func(t *testing.T) {
|
||||||
require := require.New(t)
|
|
||||||
_, ctx := testContext(t)
|
_, ctx := testContext(t)
|
||||||
d := newDeviceAllocator(ctx, n)
|
d := newDeviceAllocator(ctx, n)
|
||||||
require.NotNil(d)
|
must.NotNil(t, d)
|
||||||
|
|
||||||
// Build the request
|
// Build the request
|
||||||
ask := deviceRequest(c.Name, 1, nil, c.Affinities)
|
ask := deviceRequest(c.Name, 1, nil, c.Affinities)
|
||||||
|
|
||||||
mem := anyMemoryNodeMatcher()
|
mem := anyMemoryNodeMatcher()
|
||||||
out, score, err := d.createOffer(mem, ask)
|
out, score, err := d.createOffer(mem, ask)
|
||||||
require.NotNil(out)
|
must.NotNil(t, out)
|
||||||
require.NoError(err)
|
must.NoError(t, err)
|
||||||
if c.ZeroScore {
|
if c.ZeroScore {
|
||||||
require.Zero(score)
|
must.Zero(t, score)
|
||||||
} else {
|
} else {
|
||||||
require.NotZero(score)
|
must.NonZero(t, score)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Check that we got the nvidia device
|
// Check that we got the nvidia device
|
||||||
require.Len(out.DeviceIDs, 1)
|
must.SliceLen(t, 1, out.DeviceIDs)
|
||||||
require.Contains(collectInstanceIDs(c.ExpectedDevice), out.DeviceIDs[0])
|
must.SliceContains(t, collectInstanceIDs(c.ExpectedDevice), out.DeviceIDs[0])
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -5,7 +5,6 @@ package scheduler
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"reflect"
|
|
||||||
"testing"
|
"testing"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
@@ -64,9 +63,8 @@ func TestStaticIterator_SetNodes(t *testing.T) {
|
|||||||
static.SetNodes(newNodes)
|
static.SetNodes(newNodes)
|
||||||
|
|
||||||
out := collectFeasible(static)
|
out := collectFeasible(static)
|
||||||
if !reflect.DeepEqual(out, newNodes) {
|
must.Eq(t, newNodes, out)
|
||||||
t.Fatalf("bad: %#v", out)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestRandomIterator(t *testing.T) {
|
func TestRandomIterator(t *testing.T) {
|
||||||
@@ -86,9 +84,8 @@ func TestRandomIterator(t *testing.T) {
|
|||||||
if len(out) != len(nodes) {
|
if len(out) != len(nodes) {
|
||||||
t.Fatalf("missing nodes")
|
t.Fatalf("missing nodes")
|
||||||
}
|
}
|
||||||
if reflect.DeepEqual(out, nodes) {
|
must.NotEq(t, nodes, out)
|
||||||
t.Fatalf("same order")
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestHostVolumeChecker_Static(t *testing.T) {
|
func TestHostVolumeChecker_Static(t *testing.T) {
|
||||||
@@ -1360,7 +1357,7 @@ func TestResolveConstraintTarget(t *testing.T) {
|
|||||||
type tcase struct {
|
type tcase struct {
|
||||||
target string
|
target string
|
||||||
node *structs.Node
|
node *structs.Node
|
||||||
val interface{}
|
val string
|
||||||
result bool
|
result bool
|
||||||
}
|
}
|
||||||
node := mock.Node()
|
node := mock.Node()
|
||||||
@@ -1422,11 +1419,9 @@ func TestResolveConstraintTarget(t *testing.T) {
|
|||||||
|
|
||||||
for _, tc := range cases {
|
for _, tc := range cases {
|
||||||
res, ok := resolveTarget(tc.target, tc.node)
|
res, ok := resolveTarget(tc.target, tc.node)
|
||||||
if ok != tc.result {
|
must.Eq(t, ok, tc.result)
|
||||||
t.Fatalf("TC: %#v, Result: %v %v", tc, res, ok)
|
if ok {
|
||||||
}
|
must.Eq(t, res, tc.val)
|
||||||
if ok && !reflect.DeepEqual(res, tc.val) {
|
|
||||||
t.Fatalf("TC: %#v, Result: %v %v", tc, res, ok)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
File diff suppressed because it is too large
Load Diff
@@ -10,7 +10,7 @@ import (
|
|||||||
"github.com/hashicorp/nomad/client/lib/numalib"
|
"github.com/hashicorp/nomad/client/lib/numalib"
|
||||||
"github.com/hashicorp/nomad/client/lib/numalib/hw"
|
"github.com/hashicorp/nomad/client/lib/numalib/hw"
|
||||||
"github.com/hashicorp/nomad/nomad/structs"
|
"github.com/hashicorp/nomad/nomad/structs"
|
||||||
"github.com/stretchr/testify/require"
|
"github.com/shoenig/test/must"
|
||||||
)
|
)
|
||||||
|
|
||||||
func TestCoreSelectorSelect(t *testing.T) {
|
func TestCoreSelectorSelect(t *testing.T) {
|
||||||
@@ -46,7 +46,7 @@ func TestCoreSelectorSelect(t *testing.T) {
|
|||||||
GuessSpeed: 0,
|
GuessSpeed: 0,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
require.Equal(t, coreIds, []uint16{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47})
|
must.Eq(t, []uint16{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47}, coreIds)
|
||||||
|
|
||||||
selector := &coreSelector{
|
selector := &coreSelector{
|
||||||
topology: &numalib.Topology{
|
topology: &numalib.Topology{
|
||||||
@@ -88,8 +88,8 @@ func TestCoreSelectorSelect(t *testing.T) {
|
|||||||
} {
|
} {
|
||||||
t.Run(test.name, func(t *testing.T) {
|
t.Run(test.name, func(t *testing.T) {
|
||||||
ids, mhz := selector.Select(test.resources)
|
ids, mhz := selector.Select(test.resources)
|
||||||
require.Equal(t, test.expectedIds, ids)
|
must.Eq(t, test.expectedIds, ids)
|
||||||
require.Equal(t, test.expectedMhz, mhz)
|
must.Eq(t, test.expectedMhz, mhz)
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -5,18 +5,15 @@ package scheduler
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"maps"
|
|
||||||
"strconv"
|
"strconv"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"github.com/hashicorp/nomad/ci"
|
"github.com/hashicorp/nomad/ci"
|
||||||
"github.com/hashicorp/nomad/client/lib/numalib"
|
|
||||||
"github.com/hashicorp/nomad/client/lib/numalib/hw"
|
|
||||||
"github.com/hashicorp/nomad/helper/uuid"
|
"github.com/hashicorp/nomad/helper/uuid"
|
||||||
"github.com/hashicorp/nomad/nomad/mock"
|
"github.com/hashicorp/nomad/nomad/mock"
|
||||||
"github.com/hashicorp/nomad/nomad/structs"
|
"github.com/hashicorp/nomad/nomad/structs"
|
||||||
psstructs "github.com/hashicorp/nomad/plugins/shared/structs"
|
psstructs "github.com/hashicorp/nomad/plugins/shared/structs"
|
||||||
"github.com/stretchr/testify/require"
|
"github.com/shoenig/test/must"
|
||||||
)
|
)
|
||||||
|
|
||||||
func TestResourceDistance(t *testing.T) {
|
func TestResourceDistance(t *testing.T) {
|
||||||
@@ -140,80 +137,14 @@ func TestResourceDistance(t *testing.T) {
|
|||||||
|
|
||||||
for _, tc := range testCases {
|
for _, tc := range testCases {
|
||||||
t.Run("", func(t *testing.T) {
|
t.Run("", func(t *testing.T) {
|
||||||
require := require.New(t)
|
|
||||||
actualDistance := fmt.Sprintf("%3.3f", basicResourceDistance(resourceAsk, tc.allocResource))
|
actualDistance := fmt.Sprintf("%3.3f", basicResourceDistance(resourceAsk, tc.allocResource))
|
||||||
require.Equal(tc.expectedDistance, actualDistance)
|
must.Eq(t, tc.expectedDistance, actualDistance)
|
||||||
})
|
})
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func makeNodeResources(devices []*structs.NodeDeviceResource, busAssociativity map[string]hw.NodeID) *structs.NodeResources {
|
|
||||||
makeCore := func(node hw.NodeID, id hw.CoreID) numalib.Core {
|
|
||||||
sockets := map[hw.NodeID]hw.SocketID{
|
|
||||||
0: 0,
|
|
||||||
1: 0,
|
|
||||||
2: 1,
|
|
||||||
3: 1,
|
|
||||||
}
|
|
||||||
return numalib.Core{
|
|
||||||
NodeID: node,
|
|
||||||
SocketID: sockets[node],
|
|
||||||
ID: id,
|
|
||||||
Grade: numalib.Performance,
|
|
||||||
BaseSpeed: 4000,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// 2 socket, 4 numa node system, 2 cores per node
|
|
||||||
processors := structs.NodeProcessorResources{
|
|
||||||
Topology: &numalib.Topology{
|
|
||||||
Nodes: []uint8{0, 1, 2, 3},
|
|
||||||
Distances: numalib.SLIT{
|
|
||||||
[]numalib.Cost{10, 12, 32, 32},
|
|
||||||
[]numalib.Cost{12, 10, 32, 32},
|
|
||||||
[]numalib.Cost{32, 32, 10, 12},
|
|
||||||
[]numalib.Cost{32, 32, 12, 10},
|
|
||||||
},
|
|
||||||
Cores: []numalib.Core{
|
|
||||||
makeCore(0, 0),
|
|
||||||
makeCore(0, 1),
|
|
||||||
makeCore(1, 2),
|
|
||||||
makeCore(1, 3),
|
|
||||||
makeCore(2, 4),
|
|
||||||
makeCore(2, 5),
|
|
||||||
makeCore(3, 6),
|
|
||||||
makeCore(3, 7),
|
|
||||||
},
|
|
||||||
},
|
|
||||||
}
|
|
||||||
|
|
||||||
defaultNodeResources := &structs.NodeResources{
|
|
||||||
Processors: processors,
|
|
||||||
Memory: structs.NodeMemoryResources{
|
|
||||||
MemoryMB: 8192,
|
|
||||||
},
|
|
||||||
Disk: structs.NodeDiskResources{
|
|
||||||
DiskMB: 100 * 1024,
|
|
||||||
},
|
|
||||||
Networks: []*structs.NetworkResource{
|
|
||||||
{
|
|
||||||
Device: "eth0",
|
|
||||||
CIDR: "192.168.0.100/32",
|
|
||||||
MBits: 1000,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
Devices: devices,
|
|
||||||
}
|
|
||||||
|
|
||||||
defaultNodeResources.Compatibility()
|
|
||||||
|
|
||||||
defaultNodeResources.Processors.Topology.BusAssociativity = maps.Clone(busAssociativity)
|
|
||||||
|
|
||||||
return defaultNodeResources
|
|
||||||
}
|
|
||||||
|
|
||||||
func makeDeviceInstance(instanceID, busID string) *structs.NodeDevice {
|
func makeDeviceInstance(instanceID, busID string) *structs.NodeDevice {
|
||||||
return &structs.NodeDevice{
|
return &structs.NodeDevice{
|
||||||
ID: instanceID,
|
ID: instanceID,
|
||||||
@@ -1395,10 +1326,9 @@ func TestPreemption_Normal(t *testing.T) {
|
|||||||
for _, alloc := range tc.currentAllocations {
|
for _, alloc := range tc.currentAllocations {
|
||||||
alloc.NodeID = node.ID
|
alloc.NodeID = node.ID
|
||||||
}
|
}
|
||||||
require := require.New(t)
|
|
||||||
err := state.UpsertAllocs(structs.MsgTypeTestSetup, 1001, tc.currentAllocations)
|
err := state.UpsertAllocs(structs.MsgTypeTestSetup, 1001, tc.currentAllocations)
|
||||||
|
|
||||||
require.Nil(err)
|
must.NoError(t, err)
|
||||||
if tc.currentPreemptions != nil {
|
if tc.currentPreemptions != nil {
|
||||||
ctx.plan.NodePreemptions[node.ID] = tc.currentPreemptions
|
ctx.plan.NodePreemptions[node.ID] = tc.currentPreemptions
|
||||||
}
|
}
|
||||||
@@ -1422,14 +1352,14 @@ func TestPreemption_Normal(t *testing.T) {
|
|||||||
binPackIter.SetTaskGroup(taskGroup)
|
binPackIter.SetTaskGroup(taskGroup)
|
||||||
option := binPackIter.Next()
|
option := binPackIter.Next()
|
||||||
if tc.preemptedAllocIDs == nil {
|
if tc.preemptedAllocIDs == nil {
|
||||||
require.Nil(option)
|
must.Nil(t, option)
|
||||||
} else {
|
} else {
|
||||||
require.NotNil(option)
|
must.NotNil(t, option)
|
||||||
preemptedAllocs := option.PreemptedAllocs
|
preemptedAllocs := option.PreemptedAllocs
|
||||||
require.Equal(len(tc.preemptedAllocIDs), len(preemptedAllocs))
|
must.Eq(t, len(tc.preemptedAllocIDs), len(preemptedAllocs))
|
||||||
for _, alloc := range preemptedAllocs {
|
for _, alloc := range preemptedAllocs {
|
||||||
_, ok := tc.preemptedAllocIDs[alloc.ID]
|
_, ok := tc.preemptedAllocIDs[alloc.ID]
|
||||||
require.Truef(ok, "alloc %s was preempted unexpectedly", alloc.ID)
|
must.True(t, ok, must.Sprintf("alloc %s was preempted unexpectedly", alloc.ID))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
@@ -1502,7 +1432,7 @@ func TestPreemptionMultiple(t *testing.T) {
|
|||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
require.NoError(t, h.State.UpsertNode(structs.MsgTypeTestSetup, h.NextIndex(), node))
|
must.NoError(t, h.State.UpsertNode(structs.MsgTypeTestSetup, h.NextIndex(), node))
|
||||||
|
|
||||||
// low priority job with 4 allocs using all 4 GPUs
|
// low priority job with 4 allocs using all 4 GPUs
|
||||||
lowPrioJob := mock.Job()
|
lowPrioJob := mock.Job()
|
||||||
@@ -1515,7 +1445,7 @@ func TestPreemptionMultiple(t *testing.T) {
|
|||||||
Name: "gpu",
|
Name: "gpu",
|
||||||
Count: 1,
|
Count: 1,
|
||||||
}}
|
}}
|
||||||
require.NoError(t, h.State.UpsertJob(structs.MsgTypeTestSetup, h.NextIndex(), nil, lowPrioJob))
|
must.NoError(t, h.State.UpsertJob(structs.MsgTypeTestSetup, h.NextIndex(), nil, lowPrioJob))
|
||||||
|
|
||||||
allocs := []*structs.Allocation{}
|
allocs := []*structs.Allocation{}
|
||||||
allocIDs := map[string]struct{}{}
|
allocIDs := map[string]struct{}{}
|
||||||
@@ -1531,7 +1461,7 @@ func TestPreemptionMultiple(t *testing.T) {
|
|||||||
allocs = append(allocs, alloc)
|
allocs = append(allocs, alloc)
|
||||||
allocIDs[alloc.ID] = struct{}{}
|
allocIDs[alloc.ID] = struct{}{}
|
||||||
}
|
}
|
||||||
require.NoError(t, h.State.UpsertAllocs(structs.MsgTypeTestSetup, h.NextIndex(), allocs))
|
must.NoError(t, h.State.UpsertAllocs(structs.MsgTypeTestSetup, h.NextIndex(), allocs))
|
||||||
|
|
||||||
// new high priority job with 2 allocs, each using 2 GPUs
|
// new high priority job with 2 allocs, each using 2 GPUs
|
||||||
highPrioJob := mock.Job()
|
highPrioJob := mock.Job()
|
||||||
@@ -1544,7 +1474,7 @@ func TestPreemptionMultiple(t *testing.T) {
|
|||||||
Name: "gpu",
|
Name: "gpu",
|
||||||
Count: 2,
|
Count: 2,
|
||||||
}}
|
}}
|
||||||
require.NoError(t, h.State.UpsertJob(structs.MsgTypeTestSetup, h.NextIndex(), nil, highPrioJob))
|
must.NoError(t, h.State.UpsertJob(structs.MsgTypeTestSetup, h.NextIndex(), nil, highPrioJob))
|
||||||
|
|
||||||
// schedule
|
// schedule
|
||||||
eval := &structs.Evaluation{
|
eval := &structs.Evaluation{
|
||||||
@@ -1555,18 +1485,18 @@ func TestPreemptionMultiple(t *testing.T) {
|
|||||||
JobID: highPrioJob.ID,
|
JobID: highPrioJob.ID,
|
||||||
Status: structs.EvalStatusPending,
|
Status: structs.EvalStatusPending,
|
||||||
}
|
}
|
||||||
require.NoError(t, h.State.UpsertEvals(structs.MsgTypeTestSetup, h.NextIndex(), []*structs.Evaluation{eval}))
|
must.NoError(t, h.State.UpsertEvals(structs.MsgTypeTestSetup, h.NextIndex(), []*structs.Evaluation{eval}))
|
||||||
|
|
||||||
// Process the evaluation
|
// Process the evaluation
|
||||||
require.NoError(t, h.Process(NewServiceScheduler, eval))
|
must.NoError(t, h.Process(NewServiceScheduler, eval))
|
||||||
require.Len(t, h.Plans, 1)
|
must.Len(t, 1, h.Plans)
|
||||||
require.Contains(t, h.Plans[0].NodePreemptions, node.ID)
|
must.MapContainsKey(t, h.Plans[0].NodePreemptions, node.ID)
|
||||||
|
|
||||||
preempted := map[string]struct{}{}
|
preempted := map[string]struct{}{}
|
||||||
for _, alloc := range h.Plans[0].NodePreemptions[node.ID] {
|
for _, alloc := range h.Plans[0].NodePreemptions[node.ID] {
|
||||||
preempted[alloc.ID] = struct{}{}
|
preempted[alloc.ID] = struct{}{}
|
||||||
}
|
}
|
||||||
require.Equal(t, allocIDs, preempted)
|
must.Eq(t, allocIDs, preempted)
|
||||||
}
|
}
|
||||||
|
|
||||||
// helper method to create allocations with given jobs and resources
|
// helper method to create allocations with given jobs and resources
|
||||||
|
|||||||
@@ -16,7 +16,6 @@ import (
|
|||||||
"github.com/hashicorp/nomad/nomad/structs"
|
"github.com/hashicorp/nomad/nomad/structs"
|
||||||
"github.com/shoenig/test"
|
"github.com/shoenig/test"
|
||||||
"github.com/shoenig/test/must"
|
"github.com/shoenig/test/must"
|
||||||
"github.com/stretchr/testify/require"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
var testSchedulerConfig = &structs.SchedulerConfiguration{
|
var testSchedulerConfig = &structs.SchedulerConfiguration{
|
||||||
@@ -255,15 +254,15 @@ func TestBinPackIterator_NoExistingAlloc_MixedReserve(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// 3 nodes should be feasible
|
// 3 nodes should be feasible
|
||||||
require.Len(t, out, 3)
|
must.Len(t, 3, out)
|
||||||
|
|
||||||
// Node without reservations is the best fit
|
// Node without reservations is the best fit
|
||||||
require.Equal(t, nodes[0].Node.Name, out[0].Node.Name)
|
must.Eq(t, nodes[0].Node.Name, out[0].Node.Name)
|
||||||
|
|
||||||
// Node with smallest remaining resources ("best fit") should get a
|
// Node with smallest remaining resources ("best fit") should get a
|
||||||
// higher score than node with more remaining resources ("worse fit")
|
// higher score than node with more remaining resources ("worse fit")
|
||||||
require.Equal(t, nodes[1].Node.Name, out[1].Node.Name)
|
must.Eq(t, nodes[1].Node.Name, out[1].Node.Name)
|
||||||
require.Equal(t, nodes[2].Node.Name, out[2].Node.Name)
|
must.Eq(t, nodes[2].Node.Name, out[2].Node.Name)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Tests bin packing iterator with network resources at task and task group level
|
// Tests bin packing iterator with network resources at task and task group level
|
||||||
@@ -367,27 +366,26 @@ func TestBinPackIterator_Network_Success(t *testing.T) {
|
|||||||
scoreNorm := NewScoreNormalizationIterator(ctx, binp)
|
scoreNorm := NewScoreNormalizationIterator(ctx, binp)
|
||||||
|
|
||||||
out := collectRanked(scoreNorm)
|
out := collectRanked(scoreNorm)
|
||||||
require := require.New(t)
|
|
||||||
|
|
||||||
// We expect both nodes to be eligible to place
|
// We expect both nodes to be eligible to place
|
||||||
require.Len(out, 2)
|
must.Len(t, 2, out)
|
||||||
require.Equal(out[0], nodes[0])
|
must.Eq(t, nodes[0], out[0])
|
||||||
require.Equal(out[1], nodes[1])
|
must.Eq(t, nodes[1], out[1])
|
||||||
|
|
||||||
// First node should have a perfect score
|
// First node should have a perfect score
|
||||||
require.Equal(1.0, out[0].FinalScore)
|
must.Eq(t, 1.0, out[0].FinalScore)
|
||||||
|
|
||||||
if out[1].FinalScore < 0.50 || out[1].FinalScore > 0.60 {
|
if out[1].FinalScore < 0.50 || out[1].FinalScore > 0.60 {
|
||||||
t.Fatalf("Bad Score: %v", out[1].FinalScore)
|
t.Fatalf("Bad Score: %v", out[1].FinalScore)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Verify network information at taskgroup level
|
// Verify network information at taskgroup level
|
||||||
require.Equal(500, out[0].AllocResources.Networks[0].MBits)
|
must.Eq(t, 500, out[0].AllocResources.Networks[0].MBits)
|
||||||
require.Equal(500, out[1].AllocResources.Networks[0].MBits)
|
must.Eq(t, 500, out[1].AllocResources.Networks[0].MBits)
|
||||||
|
|
||||||
// Verify network information at task level
|
// Verify network information at task level
|
||||||
require.Equal(300, out[0].TaskResources["web"].Networks[0].MBits)
|
must.Eq(t, 300, out[0].TaskResources["web"].Networks[0].MBits)
|
||||||
require.Equal(300, out[1].TaskResources["web"].Networks[0].MBits)
|
must.Eq(t, 300, out[1].TaskResources["web"].Networks[0].MBits)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Tests that bin packing iterator fails due to overprovisioning of network
|
// Tests that bin packing iterator fails due to overprovisioning of network
|
||||||
@@ -499,12 +497,11 @@ func TestBinPackIterator_Network_Failure(t *testing.T) {
|
|||||||
scoreNorm := NewScoreNormalizationIterator(ctx, binp)
|
scoreNorm := NewScoreNormalizationIterator(ctx, binp)
|
||||||
|
|
||||||
out := collectRanked(scoreNorm)
|
out := collectRanked(scoreNorm)
|
||||||
require := require.New(t)
|
|
||||||
|
|
||||||
// We expect a placement failure because we need 800 mbits of network
|
// We expect a placement failure because we need 800 mbits of network
|
||||||
// and only 300 is free
|
// and only 300 is free
|
||||||
require.Len(out, 0)
|
must.Len(t, 0, out)
|
||||||
require.Equal(1, ctx.metrics.DimensionExhausted["network: bandwidth exceeded"])
|
must.Eq(t, 1, ctx.metrics.DimensionExhausted["network: bandwidth exceeded"])
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestBinPackIterator_Network_NoCollision_Node(t *testing.T) {
|
func TestBinPackIterator_Network_NoCollision_Node(t *testing.T) {
|
||||||
@@ -595,7 +592,7 @@ func TestBinPackIterator_Network_NoCollision_Node(t *testing.T) {
|
|||||||
|
|
||||||
// Placement should succeed since reserved ports are merged instead of
|
// Placement should succeed since reserved ports are merged instead of
|
||||||
// treating them as a collision
|
// treating them as a collision
|
||||||
require.Len(t, out, 1)
|
must.Len(t, 1, out)
|
||||||
}
|
}
|
||||||
|
|
||||||
// TestBinPackIterator_Network_NodeError asserts that NetworkIndex.SetNode can
|
// TestBinPackIterator_Network_NodeError asserts that NetworkIndex.SetNode can
|
||||||
@@ -694,9 +691,9 @@ func TestBinPackIterator_Network_NodeError(t *testing.T) {
|
|||||||
|
|
||||||
// We expect a placement failure because the node has invalid reserved
|
// We expect a placement failure because the node has invalid reserved
|
||||||
// ports
|
// ports
|
||||||
require.Len(t, out, 0)
|
must.Len(t, 0, out)
|
||||||
require.Equal(t, 1, ctx.metrics.DimensionExhausted["network: invalid node"],
|
must.Eq(t, 1, ctx.metrics.DimensionExhausted["network: invalid node"],
|
||||||
ctx.metrics.DimensionExhausted)
|
must.Sprint(ctx.metrics.DimensionExhausted))
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestBinPackIterator_Network_PortCollision_Alloc(t *testing.T) {
|
func TestBinPackIterator_Network_PortCollision_Alloc(t *testing.T) {
|
||||||
@@ -786,9 +783,9 @@ func TestBinPackIterator_Network_PortCollision_Alloc(t *testing.T) {
|
|||||||
ClientStatus: structs.AllocClientStatusPending,
|
ClientStatus: structs.AllocClientStatusPending,
|
||||||
TaskGroup: "web",
|
TaskGroup: "web",
|
||||||
}
|
}
|
||||||
require.NoError(t, state.UpsertJobSummary(998, mock.JobSummary(alloc1.JobID)))
|
must.NoError(t, state.UpsertJobSummary(998, mock.JobSummary(alloc1.JobID)))
|
||||||
require.NoError(t, state.UpsertJobSummary(999, mock.JobSummary(alloc2.JobID)))
|
must.NoError(t, state.UpsertJobSummary(999, mock.JobSummary(alloc2.JobID)))
|
||||||
require.NoError(t, state.UpsertAllocs(structs.MsgTypeTestSetup, 1000, []*structs.Allocation{alloc1, alloc2}))
|
must.NoError(t, state.UpsertAllocs(structs.MsgTypeTestSetup, 1000, []*structs.Allocation{alloc1, alloc2}))
|
||||||
|
|
||||||
taskGroup := &structs.TaskGroup{
|
taskGroup := &structs.TaskGroup{
|
||||||
EphemeralDisk: &structs.EphemeralDisk{},
|
EphemeralDisk: &structs.EphemeralDisk{},
|
||||||
@@ -820,8 +817,8 @@ func TestBinPackIterator_Network_PortCollision_Alloc(t *testing.T) {
|
|||||||
out := collectRanked(scoreNorm)
|
out := collectRanked(scoreNorm)
|
||||||
|
|
||||||
// We expect a placement failure due to port collision.
|
// We expect a placement failure due to port collision.
|
||||||
require.Len(t, out, 0)
|
must.Len(t, 0, out)
|
||||||
require.Equal(t, 1, ctx.metrics.DimensionExhausted["network: port collision"])
|
must.Eq(t, 1, ctx.metrics.DimensionExhausted["network: port collision"])
|
||||||
}
|
}
|
||||||
|
|
||||||
// Tests bin packing iterator with host network interpolation of task group level ports configuration
|
// Tests bin packing iterator with host network interpolation of task group level ports configuration
|
||||||
@@ -961,18 +958,17 @@ func TestBinPackIterator_Network_Interpolation_Success(t *testing.T) {
|
|||||||
scoreNorm := NewScoreNormalizationIterator(ctx, binp)
|
scoreNorm := NewScoreNormalizationIterator(ctx, binp)
|
||||||
|
|
||||||
out := collectRanked(scoreNorm)
|
out := collectRanked(scoreNorm)
|
||||||
require := require.New(t)
|
|
||||||
|
|
||||||
// We expect both nodes to be eligible to place
|
// We expect both nodes to be eligible to place
|
||||||
require.Len(out, 2)
|
must.Len(t, 2, out)
|
||||||
require.Equal(out[0], nodes[0])
|
must.Eq(t, out[0], nodes[0])
|
||||||
require.Equal(out[1], nodes[1])
|
must.Eq(t, out[1], nodes[1])
|
||||||
|
|
||||||
// Verify network information at taskgroup level
|
// Verify network information at taskgroup level
|
||||||
require.Contains([]string{"public", "private"}, out[0].AllocResources.Networks[0].DynamicPorts[0].HostNetwork)
|
must.SliceContains(t, []string{"public", "private"}, out[0].AllocResources.Networks[0].DynamicPorts[0].HostNetwork)
|
||||||
require.Contains([]string{"public", "private"}, out[0].AllocResources.Networks[0].DynamicPorts[1].HostNetwork)
|
must.SliceContains(t, []string{"public", "private"}, out[0].AllocResources.Networks[0].DynamicPorts[1].HostNetwork)
|
||||||
require.Contains([]string{"first", "second"}, out[1].AllocResources.Networks[0].DynamicPorts[0].HostNetwork)
|
must.SliceContains(t, []string{"first", "second"}, out[1].AllocResources.Networks[0].DynamicPorts[0].HostNetwork)
|
||||||
require.Contains([]string{"first", "second"}, out[1].AllocResources.Networks[0].DynamicPorts[1].HostNetwork)
|
must.SliceContains(t, []string{"first", "second"}, out[1].AllocResources.Networks[0].DynamicPorts[1].HostNetwork)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Tests that bin packing iterator fails due to absence of meta value
|
// Tests that bin packing iterator fails due to absence of meta value
|
||||||
@@ -1072,8 +1068,7 @@ func TestBinPackIterator_Host_Network_Interpolation_Absent_Value(t *testing.T) {
|
|||||||
scoreNorm := NewScoreNormalizationIterator(ctx, binp)
|
scoreNorm := NewScoreNormalizationIterator(ctx, binp)
|
||||||
|
|
||||||
out := collectRanked(scoreNorm)
|
out := collectRanked(scoreNorm)
|
||||||
require := require.New(t)
|
must.Len(t, 0, out)
|
||||||
require.Len(out, 0)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Tests that bin packing iterator fails due to absence of meta value
|
// Tests that bin packing iterator fails due to absence of meta value
|
||||||
@@ -1173,8 +1168,7 @@ func TestBinPackIterator_Host_Network_Interpolation_Interface_Not_Exists(t *test
|
|||||||
scoreNorm := NewScoreNormalizationIterator(ctx, binp)
|
scoreNorm := NewScoreNormalizationIterator(ctx, binp)
|
||||||
|
|
||||||
out := collectRanked(scoreNorm)
|
out := collectRanked(scoreNorm)
|
||||||
require := require.New(t)
|
must.Len(t, 0, out)
|
||||||
require.Len(out, 0)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestBinPackIterator_PlannedAlloc(t *testing.T) {
|
func TestBinPackIterator_PlannedAlloc(t *testing.T) {
|
||||||
@@ -1377,9 +1371,9 @@ func TestBinPackIterator_ReservedCores(t *testing.T) {
|
|||||||
ClientStatus: structs.AllocClientStatusPending,
|
ClientStatus: structs.AllocClientStatusPending,
|
||||||
TaskGroup: "web",
|
TaskGroup: "web",
|
||||||
}
|
}
|
||||||
require.NoError(t, state.UpsertJobSummary(998, mock.JobSummary(alloc1.JobID)))
|
must.NoError(t, state.UpsertJobSummary(998, mock.JobSummary(alloc1.JobID)))
|
||||||
require.NoError(t, state.UpsertJobSummary(999, mock.JobSummary(alloc2.JobID)))
|
must.NoError(t, state.UpsertJobSummary(999, mock.JobSummary(alloc2.JobID)))
|
||||||
require.NoError(t, state.UpsertAllocs(structs.MsgTypeTestSetup, 1000, []*structs.Allocation{alloc1, alloc2}))
|
must.NoError(t, state.UpsertAllocs(structs.MsgTypeTestSetup, 1000, []*structs.Allocation{alloc1, alloc2}))
|
||||||
|
|
||||||
taskGroup := &structs.TaskGroup{
|
taskGroup := &structs.TaskGroup{
|
||||||
EphemeralDisk: &structs.EphemeralDisk{},
|
EphemeralDisk: &structs.EphemeralDisk{},
|
||||||
@@ -1403,10 +1397,9 @@ func TestBinPackIterator_ReservedCores(t *testing.T) {
|
|||||||
scoreNorm := NewScoreNormalizationIterator(ctx, binp)
|
scoreNorm := NewScoreNormalizationIterator(ctx, binp)
|
||||||
|
|
||||||
out := collectRanked(scoreNorm)
|
out := collectRanked(scoreNorm)
|
||||||
require := require.New(t)
|
must.Len(t, 1, out)
|
||||||
require.Len(out, 1)
|
must.Eq(t, nodes[1].Node.ID, out[0].Node.ID)
|
||||||
require.Equal(nodes[1].Node.ID, out[0].Node.ID)
|
must.Eq(t, []uint16{1}, out[0].TaskResources["web"].Cpu.ReservedCores)
|
||||||
require.Equal([]uint16{1}, out[0].TaskResources["web"].Cpu.ReservedCores)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestBinPackIterator_ExistingAlloc(t *testing.T) {
|
func TestBinPackIterator_ExistingAlloc(t *testing.T) {
|
||||||
@@ -1489,9 +1482,9 @@ func TestBinPackIterator_ExistingAlloc(t *testing.T) {
|
|||||||
ClientStatus: structs.AllocClientStatusPending,
|
ClientStatus: structs.AllocClientStatusPending,
|
||||||
TaskGroup: "web",
|
TaskGroup: "web",
|
||||||
}
|
}
|
||||||
require.NoError(t, state.UpsertJobSummary(998, mock.JobSummary(alloc1.JobID)))
|
must.NoError(t, state.UpsertJobSummary(998, mock.JobSummary(alloc1.JobID)))
|
||||||
require.NoError(t, state.UpsertJobSummary(999, mock.JobSummary(alloc2.JobID)))
|
must.NoError(t, state.UpsertJobSummary(999, mock.JobSummary(alloc2.JobID)))
|
||||||
require.NoError(t, state.UpsertAllocs(structs.MsgTypeTestSetup, 1000, []*structs.Allocation{alloc1, alloc2}))
|
must.NoError(t, state.UpsertAllocs(structs.MsgTypeTestSetup, 1000, []*structs.Allocation{alloc1, alloc2}))
|
||||||
|
|
||||||
taskGroup := &structs.TaskGroup{
|
taskGroup := &structs.TaskGroup{
|
||||||
EphemeralDisk: &structs.EphemeralDisk{},
|
EphemeralDisk: &structs.EphemeralDisk{},
|
||||||
@@ -1603,9 +1596,9 @@ func TestBinPackIterator_ExistingAlloc_PlannedEvict(t *testing.T) {
|
|||||||
ClientStatus: structs.AllocClientStatusPending,
|
ClientStatus: structs.AllocClientStatusPending,
|
||||||
TaskGroup: "web",
|
TaskGroup: "web",
|
||||||
}
|
}
|
||||||
require.NoError(t, state.UpsertJobSummary(998, mock.JobSummary(alloc1.JobID)))
|
must.NoError(t, state.UpsertJobSummary(998, mock.JobSummary(alloc1.JobID)))
|
||||||
require.NoError(t, state.UpsertJobSummary(999, mock.JobSummary(alloc2.JobID)))
|
must.NoError(t, state.UpsertJobSummary(999, mock.JobSummary(alloc2.JobID)))
|
||||||
require.NoError(t, state.UpsertAllocs(structs.MsgTypeTestSetup, 1000, []*structs.Allocation{alloc1, alloc2}))
|
must.NoError(t, state.UpsertAllocs(structs.MsgTypeTestSetup, 1000, []*structs.Allocation{alloc1, alloc2}))
|
||||||
|
|
||||||
// Add a planned eviction to alloc1
|
// Add a planned eviction to alloc1
|
||||||
plan := ctx.Plan()
|
plan := ctx.Plan()
|
||||||
@@ -2319,13 +2312,12 @@ func TestNodeAntiAffinity_PenaltyNodes(t *testing.T) {
|
|||||||
|
|
||||||
out := collectRanked(scoreNorm)
|
out := collectRanked(scoreNorm)
|
||||||
|
|
||||||
require := require.New(t)
|
must.Eq(t, 2, len(out))
|
||||||
require.Equal(2, len(out))
|
must.Eq(t, node1.ID, out[0].Node.ID)
|
||||||
require.Equal(node1.ID, out[0].Node.ID)
|
must.Eq(t, -1.0, out[0].FinalScore)
|
||||||
require.Equal(-1.0, out[0].FinalScore)
|
|
||||||
|
|
||||||
require.Equal(node2.ID, out[1].Node.ID)
|
must.Eq(t, node2.ID, out[1].Node.ID)
|
||||||
require.Equal(0.0, out[1].FinalScore)
|
must.Eq(t, 0.0, out[1].FinalScore)
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -2383,15 +2375,14 @@ func TestScoreNormalizationIterator(t *testing.T) {
|
|||||||
scoreNorm := NewScoreNormalizationIterator(ctx, nodeReschedulePenaltyIter)
|
scoreNorm := NewScoreNormalizationIterator(ctx, nodeReschedulePenaltyIter)
|
||||||
|
|
||||||
out := collectRanked(scoreNorm)
|
out := collectRanked(scoreNorm)
|
||||||
require := require.New(t)
|
|
||||||
|
|
||||||
require.Equal(2, len(out))
|
must.Eq(t, 2, len(out))
|
||||||
require.Equal(out[0], nodes[0])
|
must.Eq(t, nodes[0], out[0])
|
||||||
// Score should be averaged between both scorers
|
// Score should be averaged between both scorers
|
||||||
// -0.75 from job anti affinity and -1 from node rescheduling penalty
|
// -0.75 from job anti affinity and -1 from node rescheduling penalty
|
||||||
require.Equal(-0.875, out[0].FinalScore)
|
must.Eq(t, -0.875, out[0].FinalScore)
|
||||||
require.Equal(out[1], nodes[1])
|
must.Eq(t, nodes[1], out[1])
|
||||||
require.Equal(out[1].FinalScore, 0.0)
|
must.Eq(t, 0.0, out[1].FinalScore)
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestNodeAffinityIterator(t *testing.T) {
|
func TestNodeAffinityIterator(t *testing.T) {
|
||||||
|
|||||||
@@ -5,7 +5,6 @@ package scheduler
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"reflect"
|
|
||||||
"regexp"
|
"regexp"
|
||||||
"strconv"
|
"strconv"
|
||||||
"testing"
|
"testing"
|
||||||
@@ -277,10 +276,9 @@ func assertResults(t *testing.T, r *reconcileResults, exp *resultExpectation) {
|
|||||||
} else if exp.createDeployment != nil && r.deployment != nil {
|
} else if exp.createDeployment != nil && r.deployment != nil {
|
||||||
// Clear the deployment ID
|
// Clear the deployment ID
|
||||||
r.deployment.ID, exp.createDeployment.ID = "", ""
|
r.deployment.ID, exp.createDeployment.ID = "", ""
|
||||||
if !reflect.DeepEqual(r.deployment, exp.createDeployment) {
|
must.Eq(t, exp.createDeployment, r.deployment, must.Sprintf(
|
||||||
t.Errorf("Unexpected createdDeployment; got\n %#v\nwant\n%#v\nDiff: %v",
|
"Unexpected createdDeployment; got\n %#v\nwant\n%#v\nDiff: %v",
|
||||||
r.deployment, exp.createDeployment, pretty.Diff(r.deployment, exp.createDeployment))
|
r.deployment, exp.createDeployment, pretty.Diff(r.deployment, exp.createDeployment)))
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
test.Eq(t, exp.deploymentUpdates, r.deploymentUpdates, test.Sprint("Expected Deployment Updates"))
|
test.Eq(t, exp.deploymentUpdates, r.deploymentUpdates, test.Sprint("Expected Deployment Updates"))
|
||||||
|
|||||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@@ -9,7 +9,7 @@ import (
|
|||||||
"github.com/hashicorp/nomad/ci"
|
"github.com/hashicorp/nomad/ci"
|
||||||
"github.com/hashicorp/nomad/nomad/mock"
|
"github.com/hashicorp/nomad/nomad/mock"
|
||||||
"github.com/hashicorp/nomad/nomad/structs"
|
"github.com/hashicorp/nomad/nomad/structs"
|
||||||
"github.com/stretchr/testify/require"
|
"github.com/shoenig/test/must"
|
||||||
)
|
)
|
||||||
|
|
||||||
func TestLimitIterator(t *testing.T) {
|
func TestLimitIterator(t *testing.T) {
|
||||||
@@ -313,12 +313,11 @@ func TestLimitIterator_ScoreThreshold(t *testing.T) {
|
|||||||
limit := NewLimitIterator(ctx, static, 1, 0, 2)
|
limit := NewLimitIterator(ctx, static, 1, 0, 2)
|
||||||
limit.SetLimit(2)
|
limit.SetLimit(2)
|
||||||
out := collectRanked(limit)
|
out := collectRanked(limit)
|
||||||
require := require.New(t)
|
must.Eq(t, tc.expectedOut, out)
|
||||||
require.Equal(tc.expectedOut, out)
|
|
||||||
|
|
||||||
limit.Reset()
|
limit.Reset()
|
||||||
require.Equal(0, limit.skippedNodeIndex)
|
must.Eq(t, 0, limit.skippedNodeIndex)
|
||||||
require.Equal(0, len(limit.skippedNodes))
|
must.Eq(t, 0, len(limit.skippedNodes))
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -13,7 +13,6 @@ import (
|
|||||||
|
|
||||||
"github.com/shoenig/test"
|
"github.com/shoenig/test"
|
||||||
"github.com/shoenig/test/must"
|
"github.com/shoenig/test/must"
|
||||||
"github.com/stretchr/testify/require"
|
|
||||||
|
|
||||||
"github.com/hashicorp/go-set/v3"
|
"github.com/hashicorp/go-set/v3"
|
||||||
"github.com/hashicorp/nomad/ci"
|
"github.com/hashicorp/nomad/ci"
|
||||||
@@ -100,7 +99,7 @@ func TestSpreadIterator_SingleAttribute(t *testing.T) {
|
|||||||
"dc2": 0.5,
|
"dc2": 0.5,
|
||||||
}
|
}
|
||||||
for _, rn := range out {
|
for _, rn := range out {
|
||||||
require.Equal(t, expectedScores[rn.Node.Datacenter], rn.FinalScore)
|
must.Eq(t, expectedScores[rn.Node.Datacenter], rn.FinalScore)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Update the plan to add more allocs to nodes in dc1
|
// Update the plan to add more allocs to nodes in dc1
|
||||||
@@ -179,7 +178,7 @@ func TestSpreadIterator_SingleAttribute(t *testing.T) {
|
|||||||
"dc2": 0.5,
|
"dc2": 0.5,
|
||||||
}
|
}
|
||||||
for _, rn := range out {
|
for _, rn := range out {
|
||||||
require.Equal(t, expectedScores[rn.Node.Datacenter], rn.FinalScore)
|
must.Eq(t, expectedScores[rn.Node.Datacenter], rn.FinalScore)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -281,7 +280,7 @@ func TestSpreadIterator_MultipleAttributes(t *testing.T) {
|
|||||||
nodes[3].Node.ID: 0.556,
|
nodes[3].Node.ID: 0.556,
|
||||||
}
|
}
|
||||||
for _, rn := range out {
|
for _, rn := range out {
|
||||||
require.Equal(t, fmt.Sprintf("%.3f", expectedScores[rn.Node.ID]), fmt.Sprintf("%.3f", rn.FinalScore))
|
must.Eq(t, fmt.Sprintf("%.3f", expectedScores[rn.Node.ID]), fmt.Sprintf("%.3f", rn.FinalScore))
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
@@ -328,7 +327,7 @@ func TestSpreadIterator_EvenSpread(t *testing.T) {
|
|||||||
"dc2": 0,
|
"dc2": 0,
|
||||||
}
|
}
|
||||||
for _, rn := range out {
|
for _, rn := range out {
|
||||||
require.Equal(t, fmt.Sprintf("%.3f", expectedScores[rn.Node.Datacenter]), fmt.Sprintf("%.3f", rn.FinalScore))
|
must.Eq(t, fmt.Sprintf("%.3f", expectedScores[rn.Node.Datacenter]), fmt.Sprintf("%.3f", rn.FinalScore))
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -374,7 +373,7 @@ func TestSpreadIterator_EvenSpread(t *testing.T) {
|
|||||||
"dc2": 1,
|
"dc2": 1,
|
||||||
}
|
}
|
||||||
for _, rn := range out {
|
for _, rn := range out {
|
||||||
require.Equal(t, expectedScores[rn.Node.Datacenter], rn.FinalScore)
|
must.Eq(t, expectedScores[rn.Node.Datacenter], rn.FinalScore)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Update the plan to add more allocs to nodes in dc2
|
// Update the plan to add more allocs to nodes in dc2
|
||||||
@@ -427,7 +426,7 @@ func TestSpreadIterator_EvenSpread(t *testing.T) {
|
|||||||
"dc2": -0.5,
|
"dc2": -0.5,
|
||||||
}
|
}
|
||||||
for _, rn := range out {
|
for _, rn := range out {
|
||||||
require.Equal(t, fmt.Sprintf("%3.3f", expectedScores[rn.Node.Datacenter]), fmt.Sprintf("%3.3f", rn.FinalScore))
|
must.Eq(t, fmt.Sprintf("%3.3f", expectedScores[rn.Node.Datacenter]), fmt.Sprintf("%3.3f", rn.FinalScore))
|
||||||
}
|
}
|
||||||
|
|
||||||
// Add another node in dc3
|
// Add another node in dc3
|
||||||
@@ -470,7 +469,7 @@ func TestSpreadIterator_EvenSpread(t *testing.T) {
|
|||||||
"dc3": 1,
|
"dc3": 1,
|
||||||
}
|
}
|
||||||
for _, rn := range out {
|
for _, rn := range out {
|
||||||
require.Equal(t, fmt.Sprintf("%.3f", expectedScores[rn.Node.Datacenter]), fmt.Sprintf("%.3f", rn.FinalScore))
|
must.Eq(t, fmt.Sprintf("%.3f", expectedScores[rn.Node.Datacenter]), fmt.Sprintf("%.3f", rn.FinalScore))
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
@@ -525,7 +524,7 @@ func TestSpreadIterator_MaxPenalty(t *testing.T) {
|
|||||||
|
|
||||||
// All nodes are in dc3 so score should be -1
|
// All nodes are in dc3 so score should be -1
|
||||||
for _, rn := range out {
|
for _, rn := range out {
|
||||||
require.Equal(t, -1.0, rn.FinalScore)
|
must.Eq(t, -1.0, rn.FinalScore)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Reset scores
|
// Reset scores
|
||||||
@@ -560,7 +559,7 @@ func TestSpreadIterator_MaxPenalty(t *testing.T) {
|
|||||||
|
|
||||||
// All nodes don't have the spread attribute so score should be -1
|
// All nodes don't have the spread attribute so score should be -1
|
||||||
for _, rn := range out {
|
for _, rn := range out {
|
||||||
require.Equal(t, -1.0, rn.FinalScore)
|
must.Eq(t, -1.0, rn.FinalScore)
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
@@ -685,8 +684,8 @@ func Test_evenSpreadScoreBoost(t *testing.T) {
|
|||||||
Datacenter: "dc2",
|
Datacenter: "dc2",
|
||||||
}
|
}
|
||||||
boost := evenSpreadScoreBoost(pset, opt)
|
boost := evenSpreadScoreBoost(pset, opt)
|
||||||
require.False(t, math.IsInf(boost, 1))
|
must.False(t, math.IsInf(boost, 1))
|
||||||
require.Equal(t, 1.0, boost)
|
must.Eq(t, 1.0, boost)
|
||||||
}
|
}
|
||||||
|
|
||||||
// TestSpreadOnLargeCluster exercises potentially quadratic
|
// TestSpreadOnLargeCluster exercises potentially quadratic
|
||||||
@@ -759,20 +758,20 @@ func TestSpreadOnLargeCluster(t *testing.T) {
|
|||||||
ci.Parallel(t)
|
ci.Parallel(t)
|
||||||
h := NewHarness(t)
|
h := NewHarness(t)
|
||||||
err := upsertNodes(h, tc.nodeCount, tc.racks)
|
err := upsertNodes(h, tc.nodeCount, tc.racks)
|
||||||
require.NoError(t, err)
|
must.NoError(t, err)
|
||||||
job := generateJob(tc.allocs)
|
job := generateJob(tc.allocs)
|
||||||
eval, err := upsertJob(h, job)
|
eval, err := upsertJob(h, job)
|
||||||
require.NoError(t, err)
|
must.NoError(t, err)
|
||||||
|
|
||||||
start := time.Now()
|
start := time.Now()
|
||||||
err = h.Process(NewServiceScheduler, eval)
|
err = h.Process(NewServiceScheduler, eval)
|
||||||
require.NoError(t, err)
|
must.NoError(t, err)
|
||||||
require.LessOrEqual(t, time.Since(start), time.Duration(60*time.Second),
|
must.LessEq(t, time.Duration(60*time.Second), time.Since(start),
|
||||||
"time to evaluate exceeded EvalNackTimeout")
|
must.Sprint("time to evaluate exceeded EvalNackTimeout"))
|
||||||
|
|
||||||
require.Len(t, h.Plans, 1)
|
must.Len(t, 1, h.Plans)
|
||||||
require.False(t, h.Plans[0].IsNoOp())
|
must.False(t, h.Plans[0].IsNoOp())
|
||||||
require.NoError(t, validateEqualSpread(h))
|
must.NoError(t, validateEqualSpread(h))
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -940,7 +939,7 @@ func TestSpreadPanicDowngrade(t *testing.T) {
|
|||||||
nodes = append(nodes, node)
|
nodes = append(nodes, node)
|
||||||
err := h.State.UpsertNode(structs.MsgTypeTestSetup,
|
err := h.State.UpsertNode(structs.MsgTypeTestSetup,
|
||||||
h.NextIndex(), node)
|
h.NextIndex(), node)
|
||||||
require.NoError(t, err)
|
must.NoError(t, err)
|
||||||
}
|
}
|
||||||
|
|
||||||
// job version 1
|
// job version 1
|
||||||
@@ -974,7 +973,7 @@ func TestSpreadPanicDowngrade(t *testing.T) {
|
|||||||
job1.Version = 1
|
job1.Version = 1
|
||||||
job1.TaskGroups[0].Count = 5
|
job1.TaskGroups[0].Count = 5
|
||||||
err := h.State.UpsertJob(structs.MsgTypeTestSetup, h.NextIndex(), nil, job1)
|
err := h.State.UpsertJob(structs.MsgTypeTestSetup, h.NextIndex(), nil, job1)
|
||||||
require.NoError(t, err)
|
must.NoError(t, err)
|
||||||
|
|
||||||
allocs := []*structs.Allocation{}
|
allocs := []*structs.Allocation{}
|
||||||
for i := 0; i < 4; i++ {
|
for i := 0; i < 4; i++ {
|
||||||
@@ -997,7 +996,7 @@ func TestSpreadPanicDowngrade(t *testing.T) {
|
|||||||
allocs = append(allocs, alloc)
|
allocs = append(allocs, alloc)
|
||||||
}
|
}
|
||||||
err = h.State.UpsertAllocs(structs.MsgTypeTestSetup, h.NextIndex(), allocs)
|
err = h.State.UpsertAllocs(structs.MsgTypeTestSetup, h.NextIndex(), allocs)
|
||||||
require.NoError(t, err)
|
must.NoError(t, err)
|
||||||
|
|
||||||
// job version 2
|
// job version 2
|
||||||
// max_parallel = 0, canary = 1, spread == nil
|
// max_parallel = 0, canary = 1, spread == nil
|
||||||
@@ -1006,7 +1005,7 @@ func TestSpreadPanicDowngrade(t *testing.T) {
|
|||||||
job2.Version = 2
|
job2.Version = 2
|
||||||
job2.Spreads = nil
|
job2.Spreads = nil
|
||||||
err = h.State.UpsertJob(structs.MsgTypeTestSetup, h.NextIndex(), nil, job2)
|
err = h.State.UpsertJob(structs.MsgTypeTestSetup, h.NextIndex(), nil, job2)
|
||||||
require.NoError(t, err)
|
must.NoError(t, err)
|
||||||
|
|
||||||
eval := &structs.Evaluation{
|
eval := &structs.Evaluation{
|
||||||
Namespace: job2.Namespace,
|
Namespace: job2.Namespace,
|
||||||
@@ -1018,11 +1017,11 @@ func TestSpreadPanicDowngrade(t *testing.T) {
|
|||||||
}
|
}
|
||||||
err = h.State.UpsertEvals(structs.MsgTypeTestSetup,
|
err = h.State.UpsertEvals(structs.MsgTypeTestSetup,
|
||||||
h.NextIndex(), []*structs.Evaluation{eval})
|
h.NextIndex(), []*structs.Evaluation{eval})
|
||||||
require.NoError(t, err)
|
must.NoError(t, err)
|
||||||
|
|
||||||
processErr := h.Process(NewServiceScheduler, eval)
|
processErr := h.Process(NewServiceScheduler, eval)
|
||||||
require.NoError(t, processErr, "failed to process eval")
|
must.NoError(t, processErr, must.Sprintf("..."))
|
||||||
require.Len(t, h.Plans, 1)
|
must.Len(t, 1, h.Plans)
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestSpread_ImplicitTargets(t *testing.T) {
|
func TestSpread_ImplicitTargets(t *testing.T) {
|
||||||
|
|||||||
@@ -5,7 +5,6 @@ package scheduler
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"reflect"
|
|
||||||
"runtime"
|
"runtime"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
@@ -82,9 +81,8 @@ func TestServiceStack_SetNodes(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
out := collectFeasible(stack.source)
|
out := collectFeasible(stack.source)
|
||||||
if !reflect.DeepEqual(out, nodes) {
|
must.Eq(t, nodes, out)
|
||||||
t.Fatalf("bad: %#v", out)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestServiceStack_SetJob(t *testing.T) {
|
func TestServiceStack_SetJob(t *testing.T) {
|
||||||
@@ -99,9 +97,7 @@ func TestServiceStack_SetJob(t *testing.T) {
|
|||||||
if stack.binPack.priority != job.Priority {
|
if stack.binPack.priority != job.Priority {
|
||||||
t.Fatalf("bad")
|
t.Fatalf("bad")
|
||||||
}
|
}
|
||||||
if !reflect.DeepEqual(stack.jobConstraint.constraints, job.Constraints) {
|
must.Eq(t, stack.jobConstraint.constraints, job.Constraints)
|
||||||
t.Fatalf("bad")
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestServiceStack_Select_Size(t *testing.T) {
|
func TestServiceStack_Select_Size(t *testing.T) {
|
||||||
|
|||||||
@@ -9,13 +9,12 @@ import (
|
|||||||
"testing"
|
"testing"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/stretchr/testify/require"
|
|
||||||
|
|
||||||
"github.com/hashicorp/go-memdb"
|
"github.com/hashicorp/go-memdb"
|
||||||
"github.com/hashicorp/go-version"
|
"github.com/hashicorp/go-version"
|
||||||
"github.com/hashicorp/nomad/helper/testlog"
|
"github.com/hashicorp/nomad/helper/testlog"
|
||||||
"github.com/hashicorp/nomad/nomad/state"
|
"github.com/hashicorp/nomad/nomad/state"
|
||||||
"github.com/hashicorp/nomad/nomad/structs"
|
"github.com/hashicorp/nomad/nomad/structs"
|
||||||
|
"github.com/shoenig/test/must"
|
||||||
)
|
)
|
||||||
|
|
||||||
// RejectPlan is used to always reject the entire plan and force a state refresh
|
// RejectPlan is used to always reject the entire plan and force a state refresh
|
||||||
@@ -306,9 +305,9 @@ func (h *Harness) Process(factory Factory, eval *structs.Evaluation) error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (h *Harness) AssertEvalStatus(t testing.TB, state string) {
|
func (h *Harness) AssertEvalStatus(t testing.TB, state string) {
|
||||||
require.Len(t, h.Evals, 1)
|
must.Len(t, 1, h.Evals)
|
||||||
update := h.Evals[0]
|
update := h.Evals[0]
|
||||||
require.Equal(t, state, update.Status)
|
must.Eq(t, state, update.Status)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (h *Harness) SetNoSubmit() {
|
func (h *Harness) SetNoSubmit() {
|
||||||
|
|||||||
@@ -4,7 +4,6 @@
|
|||||||
package scheduler
|
package scheduler
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"reflect"
|
|
||||||
"testing"
|
"testing"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
@@ -16,7 +15,6 @@ import (
|
|||||||
"github.com/hashicorp/nomad/nomad/state"
|
"github.com/hashicorp/nomad/nomad/state"
|
||||||
"github.com/hashicorp/nomad/nomad/structs"
|
"github.com/hashicorp/nomad/nomad/structs"
|
||||||
"github.com/shoenig/test/must"
|
"github.com/shoenig/test/must"
|
||||||
"github.com/stretchr/testify/require"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
func BenchmarkTasksUpdated(b *testing.B) {
|
func BenchmarkTasksUpdated(b *testing.B) {
|
||||||
@@ -136,8 +134,8 @@ func TestRetryMax(t *testing.T) {
|
|||||||
return false, nil
|
return false, nil
|
||||||
}
|
}
|
||||||
err := retryMax(3, bad, nil)
|
err := retryMax(3, bad, nil)
|
||||||
require.Error(t, err)
|
must.Error(t, err)
|
||||||
require.Equal(t, 3, calls, "mis match")
|
must.Eq(t, 3, calls)
|
||||||
|
|
||||||
calls = 0
|
calls = 0
|
||||||
first := true
|
first := true
|
||||||
@@ -149,8 +147,8 @@ func TestRetryMax(t *testing.T) {
|
|||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
err = retryMax(3, bad, reset)
|
err = retryMax(3, bad, reset)
|
||||||
require.Error(t, err)
|
must.Error(t, err)
|
||||||
require.Equal(t, 6, calls, "mis match")
|
must.Eq(t, 6, calls)
|
||||||
|
|
||||||
calls = 0
|
calls = 0
|
||||||
good := func() (bool, error) {
|
good := func() (bool, error) {
|
||||||
@@ -158,8 +156,8 @@ func TestRetryMax(t *testing.T) {
|
|||||||
return true, nil
|
return true, nil
|
||||||
}
|
}
|
||||||
err = retryMax(3, good, nil)
|
err = retryMax(3, good, nil)
|
||||||
require.NoError(t, err)
|
must.NoError(t, err)
|
||||||
require.Equal(t, 1, calls, "mis match")
|
must.Eq(t, 1, calls)
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestTaintedNodes(t *testing.T) {
|
func TestTaintedNodes(t *testing.T) {
|
||||||
@@ -173,10 +171,10 @@ func TestTaintedNodes(t *testing.T) {
|
|||||||
node3.Datacenter = "dc2"
|
node3.Datacenter = "dc2"
|
||||||
node3.Status = structs.NodeStatusDown
|
node3.Status = structs.NodeStatusDown
|
||||||
node4 := mock.DrainNode()
|
node4 := mock.DrainNode()
|
||||||
require.NoError(t, state.UpsertNode(structs.MsgTypeTestSetup, 1000, node1))
|
must.NoError(t, state.UpsertNode(structs.MsgTypeTestSetup, 1000, node1))
|
||||||
require.NoError(t, state.UpsertNode(structs.MsgTypeTestSetup, 1001, node2))
|
must.NoError(t, state.UpsertNode(structs.MsgTypeTestSetup, 1001, node2))
|
||||||
require.NoError(t, state.UpsertNode(structs.MsgTypeTestSetup, 1002, node3))
|
must.NoError(t, state.UpsertNode(structs.MsgTypeTestSetup, 1002, node3))
|
||||||
require.NoError(t, state.UpsertNode(structs.MsgTypeTestSetup, 1003, node4))
|
must.NoError(t, state.UpsertNode(structs.MsgTypeTestSetup, 1003, node4))
|
||||||
|
|
||||||
allocs := []*structs.Allocation{
|
allocs := []*structs.Allocation{
|
||||||
{NodeID: node1.ID},
|
{NodeID: node1.ID},
|
||||||
@@ -186,19 +184,19 @@ func TestTaintedNodes(t *testing.T) {
|
|||||||
{NodeID: "12345678-abcd-efab-cdef-123456789abc"},
|
{NodeID: "12345678-abcd-efab-cdef-123456789abc"},
|
||||||
}
|
}
|
||||||
tainted, err := taintedNodes(state, allocs)
|
tainted, err := taintedNodes(state, allocs)
|
||||||
require.NoError(t, err)
|
must.NoError(t, err)
|
||||||
require.Equal(t, 3, len(tainted))
|
must.Eq(t, 3, len(tainted))
|
||||||
require.NotContains(t, tainted, node1.ID)
|
must.MapNotContainsKey(t, tainted, node1.ID)
|
||||||
require.NotContains(t, tainted, node2.ID)
|
must.MapNotContainsKey(t, tainted, node2.ID)
|
||||||
|
|
||||||
require.Contains(t, tainted, node3.ID)
|
must.MapContainsKey(t, tainted, node3.ID)
|
||||||
require.NotNil(t, tainted[node3.ID])
|
must.NotNil(t, tainted[node3.ID])
|
||||||
|
|
||||||
require.Contains(t, tainted, node4.ID)
|
must.MapContainsKey(t, tainted, node4.ID)
|
||||||
require.NotNil(t, tainted[node4.ID])
|
must.NotNil(t, tainted[node4.ID])
|
||||||
|
|
||||||
require.Contains(t, tainted, "12345678-abcd-efab-cdef-123456789abc")
|
must.MapContainsKey(t, tainted, "12345678-abcd-efab-cdef-123456789abc")
|
||||||
require.Nil(t, tainted["12345678-abcd-efab-cdef-123456789abc"])
|
must.Nil(t, tainted["12345678-abcd-efab-cdef-123456789abc"])
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestShuffleNodes(t *testing.T) {
|
func TestShuffleNodes(t *testing.T) {
|
||||||
@@ -223,13 +221,13 @@ func TestShuffleNodes(t *testing.T) {
|
|||||||
eval := mock.Eval() // will have random EvalID
|
eval := mock.Eval() // will have random EvalID
|
||||||
plan := eval.MakePlan(mock.Job())
|
plan := eval.MakePlan(mock.Job())
|
||||||
shuffleNodes(plan, 1000, nodes)
|
shuffleNodes(plan, 1000, nodes)
|
||||||
require.False(t, reflect.DeepEqual(nodes, orig))
|
must.NotEq(t, nodes, orig)
|
||||||
|
|
||||||
nodes2 := make([]*structs.Node, len(nodes))
|
nodes2 := make([]*structs.Node, len(nodes))
|
||||||
copy(nodes2, orig)
|
copy(nodes2, orig)
|
||||||
shuffleNodes(plan, 1000, nodes2)
|
shuffleNodes(plan, 1000, nodes2)
|
||||||
|
|
||||||
require.True(t, reflect.DeepEqual(nodes, nodes2))
|
must.Eq(t, nodes, nodes2)
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -602,58 +600,58 @@ func TestSetStatus(t *testing.T) {
|
|||||||
eval := mock.Eval()
|
eval := mock.Eval()
|
||||||
status := "a"
|
status := "a"
|
||||||
desc := "b"
|
desc := "b"
|
||||||
require.NoError(t, setStatus(logger, h, eval, nil, nil, nil, status, desc, nil, ""))
|
must.NoError(t, setStatus(logger, h, eval, nil, nil, nil, status, desc, nil, ""))
|
||||||
require.Equal(t, 1, len(h.Evals), "setStatus() didn't update plan: %v", h.Evals)
|
must.Eq(t, 1, len(h.Evals), must.Sprintf("setStatus() didn't update plan: %v", h.Evals))
|
||||||
|
|
||||||
newEval := h.Evals[0]
|
newEval := h.Evals[0]
|
||||||
require.True(t, newEval.ID == eval.ID && newEval.Status == status && newEval.StatusDescription == desc,
|
must.True(t, newEval.ID == eval.ID && newEval.Status == status && newEval.StatusDescription == desc,
|
||||||
"setStatus() submited invalid eval: %v", newEval)
|
must.Sprintf("setStatus() submited invalid eval: %v", newEval))
|
||||||
|
|
||||||
// Test next evals
|
// Test next evals
|
||||||
h = NewHarness(t)
|
h = NewHarness(t)
|
||||||
next := mock.Eval()
|
next := mock.Eval()
|
||||||
require.NoError(t, setStatus(logger, h, eval, next, nil, nil, status, desc, nil, ""))
|
must.NoError(t, setStatus(logger, h, eval, next, nil, nil, status, desc, nil, ""))
|
||||||
require.Equal(t, 1, len(h.Evals), "setStatus() didn't update plan: %v", h.Evals)
|
must.Eq(t, 1, len(h.Evals), must.Sprintf("setStatus() didn't update plan: %v", h.Evals))
|
||||||
|
|
||||||
newEval = h.Evals[0]
|
newEval = h.Evals[0]
|
||||||
require.Equal(t, next.ID, newEval.NextEval, "setStatus() didn't set nextEval correctly: %v", newEval)
|
must.Eq(t, next.ID, newEval.NextEval, must.Sprintf("setStatus() didn't set nextEval correctly: %v", newEval))
|
||||||
|
|
||||||
// Test blocked evals
|
// Test blocked evals
|
||||||
h = NewHarness(t)
|
h = NewHarness(t)
|
||||||
blocked := mock.Eval()
|
blocked := mock.Eval()
|
||||||
require.NoError(t, setStatus(logger, h, eval, nil, blocked, nil, status, desc, nil, ""))
|
must.NoError(t, setStatus(logger, h, eval, nil, blocked, nil, status, desc, nil, ""))
|
||||||
require.Equal(t, 1, len(h.Evals), "setStatus() didn't update plan: %v", h.Evals)
|
must.Eq(t, 1, len(h.Evals), must.Sprintf("setStatus() didn't update plan: %v", h.Evals))
|
||||||
|
|
||||||
newEval = h.Evals[0]
|
newEval = h.Evals[0]
|
||||||
require.Equal(t, blocked.ID, newEval.BlockedEval, "setStatus() didn't set BlockedEval correctly: %v", newEval)
|
must.Eq(t, blocked.ID, newEval.BlockedEval, must.Sprintf("setStatus() didn't set BlockedEval correctly: %v", newEval))
|
||||||
|
|
||||||
// Test metrics
|
// Test metrics
|
||||||
h = NewHarness(t)
|
h = NewHarness(t)
|
||||||
metrics := map[string]*structs.AllocMetric{"foo": nil}
|
metrics := map[string]*structs.AllocMetric{"foo": nil}
|
||||||
require.NoError(t, setStatus(logger, h, eval, nil, nil, metrics, status, desc, nil, ""))
|
must.NoError(t, setStatus(logger, h, eval, nil, nil, metrics, status, desc, nil, ""))
|
||||||
require.Equal(t, 1, len(h.Evals), "setStatus() didn't update plan: %v", h.Evals)
|
must.Eq(t, 1, len(h.Evals), must.Sprintf("setStatus() didn't update plan: %v", h.Evals))
|
||||||
|
|
||||||
newEval = h.Evals[0]
|
newEval = h.Evals[0]
|
||||||
require.True(t, reflect.DeepEqual(newEval.FailedTGAllocs, metrics),
|
must.Eq(t, newEval.FailedTGAllocs, metrics,
|
||||||
"setStatus() didn't set failed task group metrics correctly: %v", newEval)
|
must.Sprintf("setStatus() didn't set failed task group metrics correctly: %v", newEval))
|
||||||
|
|
||||||
// Test queued allocations
|
// Test queued allocations
|
||||||
h = NewHarness(t)
|
h = NewHarness(t)
|
||||||
queuedAllocs := map[string]int{"web": 1}
|
queuedAllocs := map[string]int{"web": 1}
|
||||||
|
|
||||||
require.NoError(t, setStatus(logger, h, eval, nil, nil, metrics, status, desc, queuedAllocs, ""))
|
must.NoError(t, setStatus(logger, h, eval, nil, nil, metrics, status, desc, queuedAllocs, ""))
|
||||||
require.Equal(t, 1, len(h.Evals), "setStatus() didn't update plan: %v", h.Evals)
|
must.Eq(t, 1, len(h.Evals), must.Sprintf("setStatus() didn't update plan: %v", h.Evals))
|
||||||
|
|
||||||
newEval = h.Evals[0]
|
newEval = h.Evals[0]
|
||||||
require.True(t, reflect.DeepEqual(newEval.QueuedAllocations, queuedAllocs), "setStatus() didn't set failed task group metrics correctly: %v", newEval)
|
must.Eq(t, newEval.QueuedAllocations, queuedAllocs, must.Sprintf("setStatus() didn't set failed task group metrics correctly: %v", newEval))
|
||||||
|
|
||||||
h = NewHarness(t)
|
h = NewHarness(t)
|
||||||
dID := uuid.Generate()
|
dID := uuid.Generate()
|
||||||
require.NoError(t, setStatus(logger, h, eval, nil, nil, metrics, status, desc, queuedAllocs, dID))
|
must.NoError(t, setStatus(logger, h, eval, nil, nil, metrics, status, desc, queuedAllocs, dID))
|
||||||
require.Equal(t, 1, len(h.Evals), "setStatus() didn't update plan: %v", h.Evals)
|
must.Eq(t, 1, len(h.Evals), must.Sprintf("setStatus() didn't update plan: %v", h.Evals))
|
||||||
|
|
||||||
newEval = h.Evals[0]
|
newEval = h.Evals[0]
|
||||||
require.Equal(t, dID, newEval.DeploymentID, "setStatus() didn't set deployment id correctly: %v", newEval)
|
must.Eq(t, dID, newEval.DeploymentID, must.Sprintf("setStatus() didn't set deployment id correctly: %v", newEval))
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestInplaceUpdate_ChangedTaskGroup(t *testing.T) {
|
func TestInplaceUpdate_ChangedTaskGroup(t *testing.T) {
|
||||||
@@ -664,7 +662,7 @@ func TestInplaceUpdate_ChangedTaskGroup(t *testing.T) {
|
|||||||
job := mock.Job()
|
job := mock.Job()
|
||||||
|
|
||||||
node := mock.Node()
|
node := mock.Node()
|
||||||
require.NoError(t, state.UpsertNode(structs.MsgTypeTestSetup, 900, node))
|
must.NoError(t, state.UpsertNode(structs.MsgTypeTestSetup, 900, node))
|
||||||
|
|
||||||
// Register an alloc
|
// Register an alloc
|
||||||
alloc := &structs.Allocation{
|
alloc := &structs.Allocation{
|
||||||
@@ -690,8 +688,8 @@ func TestInplaceUpdate_ChangedTaskGroup(t *testing.T) {
|
|||||||
TaskGroup: "web",
|
TaskGroup: "web",
|
||||||
}
|
}
|
||||||
alloc.TaskResources = map[string]*structs.Resources{"web": alloc.Resources}
|
alloc.TaskResources = map[string]*structs.Resources{"web": alloc.Resources}
|
||||||
require.NoError(t, state.UpsertJobSummary(1000, mock.JobSummary(alloc.JobID)))
|
must.NoError(t, state.UpsertJobSummary(1000, mock.JobSummary(alloc.JobID)))
|
||||||
require.NoError(t, state.UpsertAllocs(structs.MsgTypeTestSetup, 1001, []*structs.Allocation{alloc}))
|
must.NoError(t, state.UpsertAllocs(structs.MsgTypeTestSetup, 1001, []*structs.Allocation{alloc}))
|
||||||
|
|
||||||
// Create a new task group that prevents in-place updates.
|
// Create a new task group that prevents in-place updates.
|
||||||
tg := &structs.TaskGroup{}
|
tg := &structs.TaskGroup{}
|
||||||
@@ -709,8 +707,8 @@ func TestInplaceUpdate_ChangedTaskGroup(t *testing.T) {
|
|||||||
// Do the inplace update.
|
// Do the inplace update.
|
||||||
unplaced, inplace := inplaceUpdate(ctx, eval, job, stack, updates)
|
unplaced, inplace := inplaceUpdate(ctx, eval, job, stack, updates)
|
||||||
|
|
||||||
require.True(t, len(unplaced) == 1 && len(inplace) == 0, "inplaceUpdate incorrectly did an inplace update")
|
must.True(t, len(unplaced) == 1 && len(inplace) == 0, must.Sprint("inplaceUpdate incorrectly did an inplace update"))
|
||||||
require.Empty(t, ctx.plan.NodeAllocation, "inplaceUpdate incorrectly did an inplace update")
|
must.MapEmpty(t, ctx.plan.NodeAllocation, must.Sprint("inplaceUpdate incorrectly did an inplace update"))
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestInplaceUpdate_AllocatedResources(t *testing.T) {
|
func TestInplaceUpdate_AllocatedResources(t *testing.T) {
|
||||||
@@ -721,7 +719,7 @@ func TestInplaceUpdate_AllocatedResources(t *testing.T) {
|
|||||||
job := mock.Job()
|
job := mock.Job()
|
||||||
|
|
||||||
node := mock.Node()
|
node := mock.Node()
|
||||||
require.NoError(t, state.UpsertNode(structs.MsgTypeTestSetup, 900, node))
|
must.NoError(t, state.UpsertNode(structs.MsgTypeTestSetup, 900, node))
|
||||||
|
|
||||||
// Register an alloc
|
// Register an alloc
|
||||||
alloc := &structs.Allocation{
|
alloc := &structs.Allocation{
|
||||||
@@ -746,8 +744,8 @@ func TestInplaceUpdate_AllocatedResources(t *testing.T) {
|
|||||||
TaskGroup: "web",
|
TaskGroup: "web",
|
||||||
}
|
}
|
||||||
alloc.TaskResources = map[string]*structs.Resources{"web": alloc.Resources}
|
alloc.TaskResources = map[string]*structs.Resources{"web": alloc.Resources}
|
||||||
require.NoError(t, state.UpsertJobSummary(1000, mock.JobSummary(alloc.JobID)))
|
must.NoError(t, state.UpsertJobSummary(1000, mock.JobSummary(alloc.JobID)))
|
||||||
require.NoError(t, state.UpsertAllocs(structs.MsgTypeTestSetup, 1001, []*structs.Allocation{alloc}))
|
must.NoError(t, state.UpsertAllocs(structs.MsgTypeTestSetup, 1001, []*structs.Allocation{alloc}))
|
||||||
|
|
||||||
// Update TG to add a new service (inplace)
|
// Update TG to add a new service (inplace)
|
||||||
tg := job.TaskGroups[0]
|
tg := job.TaskGroups[0]
|
||||||
@@ -763,13 +761,13 @@ func TestInplaceUpdate_AllocatedResources(t *testing.T) {
|
|||||||
// Do the inplace update.
|
// Do the inplace update.
|
||||||
unplaced, inplace := inplaceUpdate(ctx, eval, job, stack, updates)
|
unplaced, inplace := inplaceUpdate(ctx, eval, job, stack, updates)
|
||||||
|
|
||||||
require.True(t, len(unplaced) == 0 && len(inplace) == 1, "inplaceUpdate incorrectly did not perform an inplace update")
|
must.True(t, len(unplaced) == 0 && len(inplace) == 1, must.Sprint("inplaceUpdate incorrectly did not perform an inplace update"))
|
||||||
require.NotEmpty(t, ctx.plan.NodeAllocation, "inplaceUpdate incorrectly did an inplace update")
|
must.MapNotEmpty(t, ctx.plan.NodeAllocation, must.Sprint("inplaceUpdate incorrectly did an inplace update"))
|
||||||
require.NotEmpty(t, ctx.plan.NodeAllocation[node.ID][0].AllocatedResources.Shared.Ports)
|
must.SliceNotEmpty(t, ctx.plan.NodeAllocation[node.ID][0].AllocatedResources.Shared.Ports)
|
||||||
|
|
||||||
port, ok := ctx.plan.NodeAllocation[node.ID][0].AllocatedResources.Shared.Ports.Get("api-port")
|
port, ok := ctx.plan.NodeAllocation[node.ID][0].AllocatedResources.Shared.Ports.Get("api-port")
|
||||||
require.True(t, ok)
|
must.True(t, ok)
|
||||||
require.Equal(t, 19910, port.Value)
|
must.Eq(t, 19910, port.Value)
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestInplaceUpdate_NoMatch(t *testing.T) {
|
func TestInplaceUpdate_NoMatch(t *testing.T) {
|
||||||
@@ -780,7 +778,7 @@ func TestInplaceUpdate_NoMatch(t *testing.T) {
|
|||||||
job := mock.Job()
|
job := mock.Job()
|
||||||
|
|
||||||
node := mock.Node()
|
node := mock.Node()
|
||||||
require.NoError(t, state.UpsertNode(structs.MsgTypeTestSetup, 900, node))
|
must.NoError(t, state.UpsertNode(structs.MsgTypeTestSetup, 900, node))
|
||||||
|
|
||||||
// Register an alloc
|
// Register an alloc
|
||||||
alloc := &structs.Allocation{
|
alloc := &structs.Allocation{
|
||||||
@@ -806,8 +804,8 @@ func TestInplaceUpdate_NoMatch(t *testing.T) {
|
|||||||
TaskGroup: "web",
|
TaskGroup: "web",
|
||||||
}
|
}
|
||||||
alloc.TaskResources = map[string]*structs.Resources{"web": alloc.Resources}
|
alloc.TaskResources = map[string]*structs.Resources{"web": alloc.Resources}
|
||||||
require.NoError(t, state.UpsertJobSummary(1000, mock.JobSummary(alloc.JobID)))
|
must.NoError(t, state.UpsertJobSummary(1000, mock.JobSummary(alloc.JobID)))
|
||||||
require.NoError(t, state.UpsertAllocs(structs.MsgTypeTestSetup, 1001, []*structs.Allocation{alloc}))
|
must.NoError(t, state.UpsertAllocs(structs.MsgTypeTestSetup, 1001, []*structs.Allocation{alloc}))
|
||||||
|
|
||||||
// Create a new task group that requires too much resources.
|
// Create a new task group that requires too much resources.
|
||||||
tg := &structs.TaskGroup{}
|
tg := &structs.TaskGroup{}
|
||||||
@@ -821,8 +819,8 @@ func TestInplaceUpdate_NoMatch(t *testing.T) {
|
|||||||
// Do the inplace update.
|
// Do the inplace update.
|
||||||
unplaced, inplace := inplaceUpdate(ctx, eval, job, stack, updates)
|
unplaced, inplace := inplaceUpdate(ctx, eval, job, stack, updates)
|
||||||
|
|
||||||
require.True(t, len(unplaced) == 1 && len(inplace) == 0, "inplaceUpdate incorrectly did an inplace update")
|
must.True(t, len(unplaced) == 1 && len(inplace) == 0, must.Sprint("inplaceUpdate incorrectly did an inplace update"))
|
||||||
require.Empty(t, ctx.plan.NodeAllocation, "inplaceUpdate incorrectly did an inplace update")
|
must.MapEmpty(t, ctx.plan.NodeAllocation, must.Sprint("inplaceUpdate incorrectly did an inplace update"))
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestInplaceUpdate_Success(t *testing.T) {
|
func TestInplaceUpdate_Success(t *testing.T) {
|
||||||
@@ -833,7 +831,7 @@ func TestInplaceUpdate_Success(t *testing.T) {
|
|||||||
job := mock.Job()
|
job := mock.Job()
|
||||||
|
|
||||||
node := mock.Node()
|
node := mock.Node()
|
||||||
require.NoError(t, state.UpsertNode(structs.MsgTypeTestSetup, 900, node))
|
must.NoError(t, state.UpsertNode(structs.MsgTypeTestSetup, 900, node))
|
||||||
|
|
||||||
// Register an alloc
|
// Register an alloc
|
||||||
alloc := &structs.Allocation{
|
alloc := &structs.Allocation{
|
||||||
@@ -859,8 +857,8 @@ func TestInplaceUpdate_Success(t *testing.T) {
|
|||||||
DesiredStatus: structs.AllocDesiredStatusRun,
|
DesiredStatus: structs.AllocDesiredStatusRun,
|
||||||
}
|
}
|
||||||
alloc.TaskResources = map[string]*structs.Resources{"web": alloc.Resources}
|
alloc.TaskResources = map[string]*structs.Resources{"web": alloc.Resources}
|
||||||
require.NoError(t, state.UpsertJobSummary(999, mock.JobSummary(alloc.JobID)))
|
must.NoError(t, state.UpsertJobSummary(999, mock.JobSummary(alloc.JobID)))
|
||||||
require.NoError(t, state.UpsertAllocs(structs.MsgTypeTestSetup, 1001, []*structs.Allocation{alloc}))
|
must.NoError(t, state.UpsertAllocs(structs.MsgTypeTestSetup, 1001, []*structs.Allocation{alloc}))
|
||||||
|
|
||||||
// Create a new task group that updates the resources.
|
// Create a new task group that updates the resources.
|
||||||
tg := &structs.TaskGroup{}
|
tg := &structs.TaskGroup{}
|
||||||
@@ -891,23 +889,23 @@ func TestInplaceUpdate_Success(t *testing.T) {
|
|||||||
// Do the inplace update.
|
// Do the inplace update.
|
||||||
unplaced, inplace := inplaceUpdate(ctx, eval, job, stack, updates)
|
unplaced, inplace := inplaceUpdate(ctx, eval, job, stack, updates)
|
||||||
|
|
||||||
require.True(t, len(unplaced) == 0 && len(inplace) == 1, "inplaceUpdate did not do an inplace update")
|
must.True(t, len(unplaced) == 0 && len(inplace) == 1, must.Sprint("inplaceUpdate did not do an inplace update"))
|
||||||
require.Equal(t, 1, len(ctx.plan.NodeAllocation), "inplaceUpdate did not do an inplace update")
|
must.Eq(t, 1, len(ctx.plan.NodeAllocation), must.Sprint("inplaceUpdate did not do an inplace update"))
|
||||||
require.Equal(t, alloc.ID, inplace[0].Alloc.ID, "inplaceUpdate returned the wrong, inplace updated alloc: %#v", inplace)
|
must.Eq(t, alloc.ID, inplace[0].Alloc.ID, must.Sprintf("inplaceUpdate returned the wrong, inplace updated alloc: %#v", inplace))
|
||||||
|
|
||||||
// Get the alloc we inserted.
|
// Get the alloc we inserted.
|
||||||
a := inplace[0].Alloc // TODO(sean@): Verify this is correct vs: ctx.plan.NodeAllocation[alloc.NodeID][0]
|
a := inplace[0].Alloc // TODO(sean@): Verify this is correct vs: ctx.plan.NodeAllocation[alloc.NodeID][0]
|
||||||
require.NotNil(t, a.Job)
|
must.NotNil(t, a.Job)
|
||||||
require.Equal(t, 1, len(a.Job.TaskGroups))
|
must.Eq(t, 1, len(a.Job.TaskGroups))
|
||||||
require.Equal(t, 1, len(a.Job.TaskGroups[0].Tasks))
|
must.Eq(t, 1, len(a.Job.TaskGroups[0].Tasks))
|
||||||
require.Equal(t, 3, len(a.Job.TaskGroups[0].Tasks[0].Services),
|
must.Eq(t, 3, len(a.Job.TaskGroups[0].Tasks[0].Services), must.Sprintf(
|
||||||
"Expected number of services: %v, Actual: %v", 3, len(a.Job.TaskGroups[0].Tasks[0].Services))
|
"Expected number of services: %v, Actual: %v", 3, len(a.Job.TaskGroups[0].Tasks[0].Services)))
|
||||||
|
|
||||||
serviceNames := make(map[string]struct{}, 3)
|
serviceNames := make(map[string]struct{}, 3)
|
||||||
for _, consulService := range a.Job.TaskGroups[0].Tasks[0].Services {
|
for _, consulService := range a.Job.TaskGroups[0].Tasks[0].Services {
|
||||||
serviceNames[consulService.Name] = struct{}{}
|
serviceNames[consulService.Name] = struct{}{}
|
||||||
}
|
}
|
||||||
require.Equal(t, 3, len(serviceNames))
|
must.Eq(t, 3, len(serviceNames))
|
||||||
|
|
||||||
for _, name := range []string{"dummy-service", "dummy-service2", "web-frontend"} {
|
for _, name := range []string{"dummy-service", "dummy-service2", "web-frontend"} {
|
||||||
if _, found := serviceNames[name]; !found {
|
if _, found := serviceNames[name]; !found {
|
||||||
@@ -1051,23 +1049,23 @@ func TestUtil_connectSidecarServiceUpdated(t *testing.T) {
|
|||||||
ci.Parallel(t)
|
ci.Parallel(t)
|
||||||
|
|
||||||
t.Run("both nil", func(t *testing.T) {
|
t.Run("both nil", func(t *testing.T) {
|
||||||
require.False(t, connectSidecarServiceUpdated(nil, nil).modified)
|
must.False(t, connectSidecarServiceUpdated(nil, nil).modified)
|
||||||
})
|
})
|
||||||
|
|
||||||
t.Run("one nil", func(t *testing.T) {
|
t.Run("one nil", func(t *testing.T) {
|
||||||
require.True(t, connectSidecarServiceUpdated(nil, new(structs.ConsulSidecarService)).modified)
|
must.True(t, connectSidecarServiceUpdated(nil, new(structs.ConsulSidecarService)).modified)
|
||||||
})
|
})
|
||||||
|
|
||||||
t.Run("ports differ", func(t *testing.T) {
|
t.Run("ports differ", func(t *testing.T) {
|
||||||
a := &structs.ConsulSidecarService{Port: "1111"}
|
a := &structs.ConsulSidecarService{Port: "1111"}
|
||||||
b := &structs.ConsulSidecarService{Port: "2222"}
|
b := &structs.ConsulSidecarService{Port: "2222"}
|
||||||
require.True(t, connectSidecarServiceUpdated(a, b).modified)
|
must.True(t, connectSidecarServiceUpdated(a, b).modified)
|
||||||
})
|
})
|
||||||
|
|
||||||
t.Run("same", func(t *testing.T) {
|
t.Run("same", func(t *testing.T) {
|
||||||
a := &structs.ConsulSidecarService{Port: "1111"}
|
a := &structs.ConsulSidecarService{Port: "1111"}
|
||||||
b := &structs.ConsulSidecarService{Port: "1111"}
|
b := &structs.ConsulSidecarService{Port: "1111"}
|
||||||
require.False(t, connectSidecarServiceUpdated(a, b).modified)
|
must.False(t, connectSidecarServiceUpdated(a, b).modified)
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1144,17 +1142,17 @@ func TestTaskGroupConstraints(t *testing.T) {
|
|||||||
expDrivers := map[string]struct{}{"exec": {}, "docker": {}}
|
expDrivers := map[string]struct{}{"exec": {}, "docker": {}}
|
||||||
|
|
||||||
actConstrains := taskGroupConstraints(tg)
|
actConstrains := taskGroupConstraints(tg)
|
||||||
require.True(t, reflect.DeepEqual(actConstrains.constraints, expConstr),
|
must.Eq(t, actConstrains.constraints, expConstr, must.Sprintf(
|
||||||
"taskGroupConstraints(%v) returned %v; want %v", tg, actConstrains.constraints, expConstr)
|
"taskGroupConstraints(%v) returned %v; want %v", tg, actConstrains.constraints, expConstr))
|
||||||
require.True(t, reflect.DeepEqual(actConstrains.drivers, expDrivers),
|
must.Eq(t, actConstrains.drivers, expDrivers, must.Sprintf(
|
||||||
"taskGroupConstraints(%v) returned %v; want %v", tg, actConstrains.drivers, expDrivers)
|
"taskGroupConstraints(%v) returned %v; want %v", tg, actConstrains.drivers, expDrivers))
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestProgressMade(t *testing.T) {
|
func TestProgressMade(t *testing.T) {
|
||||||
ci.Parallel(t)
|
ci.Parallel(t)
|
||||||
|
|
||||||
noopPlan := &structs.PlanResult{}
|
noopPlan := &structs.PlanResult{}
|
||||||
require.False(t, progressMade(nil) || progressMade(noopPlan), "no progress plan marked as making progress")
|
must.False(t, progressMade(nil) || progressMade(noopPlan), must.Sprint("no progress plan marked as making progress"))
|
||||||
|
|
||||||
m := map[string][]*structs.Allocation{
|
m := map[string][]*structs.Allocation{
|
||||||
"foo": {mock.Alloc()},
|
"foo": {mock.Alloc()},
|
||||||
@@ -1172,7 +1170,7 @@ func TestProgressMade(t *testing.T) {
|
|||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
require.True(t, progressMade(both) && progressMade(update) && progressMade(alloc) &&
|
must.True(t, progressMade(both) && progressMade(update) && progressMade(alloc) &&
|
||||||
progressMade(deployment) && progressMade(deploymentUpdates))
|
progressMade(deployment) && progressMade(deploymentUpdates))
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1231,7 +1229,7 @@ func TestDesiredUpdates(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
desired := desiredUpdates(diff, inplace, destructive)
|
desired := desiredUpdates(diff, inplace, destructive)
|
||||||
require.True(t, reflect.DeepEqual(desired, expected), "desiredUpdates() returned %#v; want %#v", desired, expected)
|
must.Eq(t, desired, expected, must.Sprintf("desiredUpdates() returned %#v; want %#v", desired, expected))
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestUtil_AdjustQueuedAllocations(t *testing.T) {
|
func TestUtil_AdjustQueuedAllocations(t *testing.T) {
|
||||||
@@ -1268,7 +1266,7 @@ func TestUtil_AdjustQueuedAllocations(t *testing.T) {
|
|||||||
queuedAllocs := map[string]int{"web": 2}
|
queuedAllocs := map[string]int{"web": 2}
|
||||||
adjustQueuedAllocations(logger, &planResult, queuedAllocs)
|
adjustQueuedAllocations(logger, &planResult, queuedAllocs)
|
||||||
|
|
||||||
require.Equal(t, 1, queuedAllocs["web"])
|
must.Eq(t, 1, queuedAllocs["web"])
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestUtil_UpdateNonTerminalAllocsToLost(t *testing.T) {
|
func TestUtil_UpdateNonTerminalAllocsToLost(t *testing.T) {
|
||||||
@@ -1308,7 +1306,7 @@ func TestUtil_UpdateNonTerminalAllocsToLost(t *testing.T) {
|
|||||||
allocsLost = append(allocsLost, alloc.ID)
|
allocsLost = append(allocsLost, alloc.ID)
|
||||||
}
|
}
|
||||||
expected := []string{alloc1.ID, alloc2.ID}
|
expected := []string{alloc1.ID, alloc2.ID}
|
||||||
require.True(t, reflect.DeepEqual(allocsLost, expected), "actual: %v, expected: %v", allocsLost, expected)
|
must.Eq(t, allocsLost, expected, must.Sprintf("actual: %v, expected: %v", allocsLost, expected))
|
||||||
|
|
||||||
// Update the node status to ready and try again
|
// Update the node status to ready and try again
|
||||||
plan = structs.Plan{
|
plan = structs.Plan{
|
||||||
@@ -1322,7 +1320,7 @@ func TestUtil_UpdateNonTerminalAllocsToLost(t *testing.T) {
|
|||||||
allocsLost = append(allocsLost, alloc.ID)
|
allocsLost = append(allocsLost, alloc.ID)
|
||||||
}
|
}
|
||||||
expected = []string{}
|
expected = []string{}
|
||||||
require.True(t, reflect.DeepEqual(allocsLost, expected), "actual: %v, expected: %v", allocsLost, expected)
|
must.Eq(t, allocsLost, expected, must.Sprintf("actual: %v, expected: %v", allocsLost, expected))
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestTaskGroupUpdated_Restart(t *testing.T) {
|
func TestTaskGroupUpdated_Restart(t *testing.T) {
|
||||||
|
|||||||
Reference in New Issue
Block a user