Repository: hashicorp/nomad
File: scheduler/generic_sched_test.go (Go)

Code before:
			t.Fatalf("bad: %#v", plan)
		}

		// Update the job to force a rolling upgrade
		updated := job.Copy()
		updated.TaskGroups[0].Tasks[0].Resources.CPU += 10
		must.NoError(t, h.State.UpsertJob(structs.MsgTypeTestSetup, h.NextIndex(), nil, updated))

		// Create a mock evaluation to handle the update
		eval = &structs.Evaluation{
			Namespace:   structs.DefaultNamespace,
			ID:          uuid.Generate(),
			Priority:    job.Priority,
			TriggeredBy: structs.EvalTriggerNodeUpdate,
			JobID:       job.ID,
			Status:      structs.EvalStatusPending,
		}
		must.NoError(t, h.State.UpsertEvals(structs.MsgTypeTestSetup, h.NextIndex(), []*structs.Evaluation{eval}))
		h1 := tests.NewHarnessWithState(t, h.State)
		must.NoError(t, h1.Process(NewServiceScheduler, eval))

		// Ensure we have created only one new allocation
		// Ensure a single plan
		if len(h1.Plans) != 1 {
			t.Fatalf("bad: %#v", h1.Plans)
		}
		plan = h1.Plans[0]
		var newPlanned []*structs.Allocation
		for _, allocList := range plan.NodeAllocation {
			newPlanned = append(newPlanned, allocList...)
		}
		if len(newPlanned) != 10 {
			t.Fatalf("bad plan: %#v", plan)
		}
		// Ensure that the new allocations were placed on the same node as the older
		// ones
		for _, new := range newPlanned {
			// new alloc should have a previous allocation
			must.NotEq(t, new.PreviousAllocation, "")

			// new allocs PreviousAllocation must be a valid previously placed alloc
			old, ok := planned[new.PreviousAllocation]
			must.True(t, ok)

			// new alloc should be placed in the same node
			must.Eq(t, new.NodeID, old.NodeID)
		}
	})

	t.Run("ephemeral alloc should change node if node pool changes", func(t *testing.T) {
		h := tests.NewHarness(t)

Review comment (suggestion):
Let's use `shoenig/test` in this test, instead of mixing in `testify`.

Code after:
		for _, allocList := range plan.NodeAllocation {
			for _, alloc := range allocList {
				planned[alloc.ID] = alloc
			}
		}
		must.MapLen(t, 10, planned)

		// Update the job to force a rolling upgrade
		updated := job.Copy()
		updated.TaskGroups[0].Tasks[0].Resources.CPU += 10
		must.NoError(t, h.State.UpsertJob(structs.MsgTypeTestSetup, h.NextIndex(), nil, updated))

		// Create a mock evaluation to handle the update
		eval := &structs.Evaluation{
			Namespace:   structs.DefaultNamespace,
			ID:          uuid.Generate(),
			Priority:    job.Priority,
			TriggeredBy: structs.EvalTriggerNodeUpdate,
			JobID:       job.ID,
			Status:      structs.EvalStatusPending,
		}
		must.NoError(t, h.State.UpsertEvals(structs.MsgTypeTestSetup, h.NextIndex(), []*structs.Evaluation{eval}))
		h1 := tests.NewHarnessWithState(t, h.State)
		must.NoError(t, h1.Process(NewServiceScheduler, eval))

		// Ensure we have created only one new allocation
		// Ensure a single plan
		must.SliceLen(t, 1, h1.Plans)

		plan = h1.Plans[0]
		var newPlanned []*structs.Allocation
		for _, allocList := range plan.NodeAllocation {
			newPlanned = append(newPlanned, allocList...)
		}
		must.SliceLen(t, 10, newPlanned)
		// Ensure that the new allocations were placed on the same node as the older
		// ones
		for _, new := range newPlanned {
			// new alloc should have a previous allocation
			must.NotEq(t, new.PreviousAllocation, "")

			// new allocs PreviousAllocation must be a valid previously placed alloc
			old, ok := planned[new.PreviousAllocation]
			must.True(t, ok)

			// new alloc should be placed in the same node
			must.Eq(t, new.NodeID, old.NodeID)
		}
	})

	t.Run("ephemeral alloc should migrate if node pool changes", func(t *testing.T) {