func TestReconciler_TaintedNode_MultiGroups(t *testing.T) {
	// Create a job with two task groups
	job := mock.Job()
	job.TaskGroups[0].Update = noCanaryUpdate
	job.TaskGroups = append(job.TaskGroups, job.TaskGroups[0].Copy())
	job.TaskGroups[1].Name = "two"
	job.TaskGroups[1].Update.Stagger = 100 * time.Second

	// Create the allocations
	var allocs []*structs.Allocation
	for j := 0; j < 2; j++ {
		for i := 0; i < 10; i++ {
			alloc := mock.Alloc()
			alloc.Job = job
			alloc.JobID = job.ID
			alloc.NodeID = structs.GenerateUUID()
			alloc.Name = structs.AllocName(job.ID, job.TaskGroups[j].Name, uint(i))
			alloc.TaskGroup = job.TaskGroups[j].Name
			allocs = append(allocs, alloc)
		}
	}

	// Build a map of tainted nodes
	tainted := make(map[string]*structs.Node, 15)
	for i := 0; i < 15; i++ {
		n := mock.Node()
		n.ID = allocs[i].NodeID
		n.Drain = true
		tainted[n.ID] = n
	}

	reconciler := NewAllocReconciler(testLogger(), allocUpdateFnIgnore, false, job.ID, job, nil, allocs, tainted)
	r := reconciler.Compute()

	// Assert the correct results
	assertResults(t, r, &resultExpectation{
		createDeployment:  nil,
		deploymentUpdates: nil,
		place:             8,
		inplace:           0,
		stop:              8,
		followupEvalWait:  100 * time.Second,
		desiredTGUpdates: map[string]*structs.DesiredUpdates{
			job.TaskGroups[0].Name: {
				Place:             0,
				Stop:              0,
				Migrate:           4,
				DestructiveUpdate: 0,
				Ignore:            6,
			},
			job.TaskGroups[1].Name: {
				Place:             0,
				Stop:              0,
				Migrate:           4,
				DestructiveUpdate: 0,
				Ignore:            6,
			},
		},
	})

	assertNamesHaveIndexes(t, intRange(0, 3, 0, 3), placeResultsToNames(r.place))
	assertNamesHaveIndexes(t, intRange(0, 3, 0, 3), stopResultsToNames(r.stop))
}
// Tests the reconciler picks the maximum of the staggers when multiple task
// groups are under going node drains.
Tests the reconciler picks the maximum of the staggers when multiple task
groups are under going node drains.
// Tests the reconciler picks the maximum of the staggers when multiple task // groups are under going node drains .
func TestReconciler_TaintedNode_MultiGroups(t *testing.T) {
	job := mock.Job()
	job.TaskGroups[0].Update = noCanaryUpdate
	job.TaskGroups = append(job.TaskGroups, job.TaskGroups[0].Copy())
	job.TaskGroups[1].Name = "two"
	job.TaskGroups[1].Update.Stagger = 100 * time.Second
	var allocs []*structs.Allocation
	for j := 0; j < 2; j++ {
		for i := 0; i < 10; i++ {
			alloc := mock.Alloc()
			alloc.Job = job
			alloc.JobID = job.ID
			alloc.NodeID = structs.GenerateUUID()
			alloc.Name = structs.AllocName(job.ID, job.TaskGroups[j].Name, uint(i))
			alloc.TaskGroup = job.TaskGroups[j].Name
			allocs = append(allocs, alloc)
		}
	}
	tainted := make(map[string]*structs.Node, 15)
	for i := 0; i < 15; i++ {
		n := mock.Node()
		n.ID = allocs[i].NodeID
		n.Drain = true
		tainted[n.ID] = n
	}
	reconciler := NewAllocReconciler(testLogger(), allocUpdateFnIgnore, false, job.ID, job, nil, allocs, tainted)
	r := reconciler.Compute()
	assertResults(t, r, &resultExpectation{
		createDeployment:  nil,
		deploymentUpdates: nil,
		place:             8,
		inplace:           0,
		stop:              8,
		followupEvalWait:  100 * time.Second,
		desiredTGUpdates: map[string]*structs.DesiredUpdates{
			job.TaskGroups[0].Name: {
				Place:             0,
				Stop:              0,
				Migrate:           4,
				DestructiveUpdate: 0,
				Ignore:            6,
			},
			job.TaskGroups[1].Name: {
				Place:             0,
				Stop:              0,
				Migrate:           4,
				DestructiveUpdate: 0,
				Ignore:            6,
			},
		},
	})
	assertNamesHaveIndexes(t, intRange(0, 3, 0, 3), placeResultsToNames(r.place))
	assertNamesHaveIndexes(t, intRange(0, 3, 0, 3), stopResultsToNames(r.stop))
}
func TestReconciler_TaintedNode_MultiGroups ( t * testing . T ) { job := mock . Job ( ) job . TaskGroups [ 0 ] . Update = noCanaryUpdate job . TaskGroups = append ( job . TaskGroups , job . TaskGroups [ 0 ] . Copy ( ) ) job . TaskGroups [ 1 ] . Name = " " job . TaskGroups [ 1 ] . Update . Stagger = 100 * time . Second var allocs [ ] * structs . Allocation for j := 0 ; j < 2 ; j ++ { for i := 0 ; i < 10 ; i ++ { alloc := mock . Alloc ( ) alloc . Job = job alloc . JobID = job . ID alloc . NodeID = structs . GenerateUUID ( ) alloc . Name = structs . AllocName ( job . ID , job . TaskGroups [ j ] . Name , uint ( i ) ) alloc . TaskGroup = job . TaskGroups [ j ] . Name allocs = append ( allocs , alloc ) } } tainted := make ( map [ string ] * structs . Node , 15 ) for i := 0 ; i < 15 ; i ++ { n := mock . Node ( ) n . ID = allocs [ i ] . NodeID n . Drain = true tainted [ n . ID ] = n } reconciler := NewAllocReconciler ( testLogger ( ) , allocUpdateFnIgnore , false , job . ID , job , nil , allocs , tainted ) r := reconciler . Compute ( ) assertResults ( t , r , & resultExpectation { createDeployment : nil , deploymentUpdates : nil , place : 8 , inplace : 0 , stop : 8 , followupEvalWait : 100 * time . Second , desiredTGUpdates : map [ string ] * structs . DesiredUpdates { job . TaskGroups [ 0 ] . Name : { Place : 0 , Stop : 0 , Migrate : 4 , DestructiveUpdate : 0 , Ignore : 6 , } , job . TaskGroups [ 1 ] . Name : { Place : 0 , Stop : 0 , Migrate : 4 , DestructiveUpdate : 0 , Ignore : 6 , } , } , } ) assertNamesHaveIndexes ( t , intRange ( 0 , 3 , 0 , 3 ) , placeResultsToNames ( r . place ) ) assertNamesHaveIndexes ( t , intRange ( 0 , 3 , 0 , 3 ) , stopResultsToNames ( r . stop ) ) }
Tests the reconciler picks the maximum of the staggers when multiple task
groups are under going node drains.
Tests the reconciler picks the maximum of the staggers when multiple task groups are under going node drains .
// Create a job with two task groups // Create the allocations // Build a map of tainted nodes // Assert the correct results