func TestReconciler_StopOldCanaries(t *testing.T) {
	job := mock.Job()
	job.TaskGroups[0].Update = canaryUpdate

	// Create an old deployment that has placed some canaries
	d := structs.NewDeployment(job)
	s := &structs.DeploymentState{
		Promoted:        false,
		DesiredTotal:    10,
		DesiredCanaries: 2,
		PlacedAllocs:    2,
	}
	d.TaskGroups[job.TaskGroups[0].Name] = s

	// Update the job
	job.Version += 10

	// Create 10 allocations from the old job
	var allocs []*structs.Allocation
	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[0].Name, uint(i))
		alloc.TaskGroup = job.TaskGroups[0].Name
		allocs = append(allocs, alloc)
	}

	// Create canaries
	for i := 0; i < 2; i++ {
		// Create one canary
		canary := mock.Alloc()
		canary.Job = job
		canary.JobID = job.ID
		canary.NodeID = structs.GenerateUUID()
		canary.Name = structs.AllocName(job.ID, job.TaskGroups[0].Name, uint(i))
		canary.TaskGroup = job.TaskGroups[0].Name
		s.PlacedCanaries = append(s.PlacedCanaries, canary.ID)
		canary.DeploymentID = d.ID
		allocs = append(allocs, canary)
	}

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

	newD := structs.NewDeployment(job)
	newD.StatusDescription = structs.DeploymentStatusDescriptionRunningNeedsPromotion
	newD.TaskGroups[job.TaskGroups[0].Name] = &structs.DeploymentState{
		DesiredCanaries: 2,
		DesiredTotal:    10,
	}

	// Assert the correct results
	assertResults(t, r, &resultExpectation{
		createDeployment: newD,
		deploymentUpdates: []*structs.DeploymentStatusUpdate{
			{
				DeploymentID:      d.ID,
				Status:            structs.DeploymentStatusCancelled,
				StatusDescription: structs.DeploymentStatusDescriptionNewerJob,
			},
		},
		place:   2,
		inplace: 0,
		stop:    2,
		desiredTGUpdates: map[string]*structs.DesiredUpdates{
			job.TaskGroups[0].Name: {
				Canary: 2,
				Stop:   2,
				Ignore: 10,
			},
		},
	})

	assertNamesHaveIndexes(t, intRange(0, 1), stopResultsToNames(r.stop))
	assertNamesHaveIndexes(t, intRange(0, 1), placeResultsToNames(r.place))
}
// Tests the reconciler handles stopping canaries from older deployments
Tests the reconciler handles stopping canaries from older deployments
// Tests the reconciler handles stopping canaries from older deployments
func TestReconciler_StopOldCanaries(t *testing.T) {
	job := mock.Job()
	job.TaskGroups[0].Update = canaryUpdate
	d := structs.NewDeployment(job)
	s := &structs.DeploymentState{
		Promoted:        false,
		DesiredTotal:    10,
		DesiredCanaries: 2,
		PlacedAllocs:    2,
	}
	d.TaskGroups[job.TaskGroups[0].Name] = s
	job.Version += 10
	var allocs []*structs.Allocation
	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[0].Name, uint(i))
		alloc.TaskGroup = job.TaskGroups[0].Name
		allocs = append(allocs, alloc)
	}
	for i := 0; i < 2; i++ {
		canary := mock.Alloc()
		canary.Job = job
		canary.JobID = job.ID
		canary.NodeID = structs.GenerateUUID()
		canary.Name = structs.AllocName(job.ID, job.TaskGroups[0].Name, uint(i))
		canary.TaskGroup = job.TaskGroups[0].Name
		s.PlacedCanaries = append(s.PlacedCanaries, canary.ID)
		canary.DeploymentID = d.ID
		allocs = append(allocs, canary)
	}
	reconciler := NewAllocReconciler(testLogger(), allocUpdateFnDestructive, false, job.ID, job, d, allocs, nil)
	r := reconciler.Compute()
	newD := structs.NewDeployment(job)
	newD.StatusDescription = structs.DeploymentStatusDescriptionRunningNeedsPromotion
	newD.TaskGroups[job.TaskGroups[0].Name] = &structs.DeploymentState{
		DesiredCanaries: 2,
		DesiredTotal:    10,
	}
	assertResults(t, r, &resultExpectation{
		createDeployment: newD,
		deploymentUpdates: []*structs.DeploymentStatusUpdate{
			{
				DeploymentID:      d.ID,
				Status:            structs.DeploymentStatusCancelled,
				StatusDescription: structs.DeploymentStatusDescriptionNewerJob,
			},
		},
		place:   2,
		inplace: 0,
		stop:    2,
		desiredTGUpdates: map[string]*structs.DesiredUpdates{
			job.TaskGroups[0].Name: {
				Canary: 2,
				Stop:   2,
				Ignore: 10,
			},
		},
	})
	assertNamesHaveIndexes(t, intRange(0, 1), stopResultsToNames(r.stop))
	assertNamesHaveIndexes(t, intRange(0, 1), placeResultsToNames(r.place))
}
func TestReconciler_StopOldCanaries ( t * testing . T ) { job := mock . Job ( ) job . TaskGroups [ 0 ] . Update = canaryUpdate d := structs . NewDeployment ( job ) s := & structs . DeploymentState { Promoted : false , DesiredTotal : 10 , DesiredCanaries : 2 , PlacedAllocs : 2 , } d . TaskGroups [ job . TaskGroups [ 0 ] . Name ] = s job . Version += 10 var allocs [ ] * structs . Allocation 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 [ 0 ] . Name , uint ( i ) ) alloc . TaskGroup = job . TaskGroups [ 0 ] . Name allocs = append ( allocs , alloc ) } for i := 0 ; i < 2 ; i ++ { canary := mock . Alloc ( ) canary . Job = job canary . JobID = job . ID canary . NodeID = structs . GenerateUUID ( ) canary . Name = structs . AllocName ( job . ID , job . TaskGroups [ 0 ] . Name , uint ( i ) ) canary . TaskGroup = job . TaskGroups [ 0 ] . Name s . PlacedCanaries = append ( s . PlacedCanaries , canary . ID ) canary . DeploymentID = d . ID allocs = append ( allocs , canary ) } reconciler := NewAllocReconciler ( testLogger ( ) , allocUpdateFnDestructive , false , job . ID , job , d , allocs , nil ) r := reconciler . Compute ( ) newD := structs . NewDeployment ( job ) newD . StatusDescription = structs . DeploymentStatusDescriptionRunningNeedsPromotion newD . TaskGroups [ job . TaskGroups [ 0 ] . Name ] = & structs . DeploymentState { DesiredCanaries : 2 , DesiredTotal : 10 , } assertResults ( t , r , & resultExpectation { createDeployment : newD , deploymentUpdates : [ ] * structs . DeploymentStatusUpdate { { DeploymentID : d . ID , Status : structs . DeploymentStatusCancelled , StatusDescription : structs . DeploymentStatusDescriptionNewerJob , } , } , place : 2 , inplace : 0 , stop : 2 , desiredTGUpdates : map [ string ] * structs . DesiredUpdates { job . TaskGroups [ 0 ] . Name : { Canary : 2 , Stop : 2 , Ignore : 10 , } , } , } ) assertNamesHaveIndexes ( t , intRange ( 0 , 1 ) , stopResultsToNames ( r . stop ) ) assertNamesHaveIndexes ( t , intRange ( 0 , 1 ) , placeResultsToNames ( r . place ) ) }
Tests the reconciler handles stopping canaries from older deployments
Tests the reconciler handles stopping canaries from older deployments
// Create an old deployment that has placed some canaries // Update the job // Create 10 allocations from the old job // Create canaries // Create one canary // Assert the correct results