Repository: hashicorp/nomad
File: e2e/scheduler_system/systemsched_test.go (Go)

Code before:
		must.NoError(t, err)
		for _, d := range deployments {
			for _, tg := range d.TaskGroups { // this job has 1 tg
				if d.JobVersion == 1 && tg.HealthyAllocs >= tg.DesiredCanaries {
					break CANARYWAIT
				}
			}
		}
	}

	// filter allocation from v1 version of the job, they should all be canaries
	// and there should be exactly 2
	canaryAllocs := []*api.AllocationListStub{}
	for _, a := range allocs {
		if a.JobVersion == 1 {
			must.True(t, a.DeploymentStatus.Canary)
			canaryAllocs = append(canaryAllocs, a)
		}
	}
	must.SliceLen(t, 2, canaryAllocs, must.Sprint("expected 2 canary allocs"))

	// promote canaries
	deployments, _, err := deploymentsApi.List(nil)
	must.NoError(t, err)
	must.SliceLen(t, 2, deployments)
	_, _, err = deploymentsApi.PromoteAll(deployments[0].ID, nil)
	must.NoError(t, err)

	// wait for the promotions to become healthy
PROMOTIONWAIT:
	for {
		select {
		case <-timeout:
			must.Unreachable(t, must.Sprint("timeout reached waiting for healthy status of promoted allocs"))
		default:
		}

		deploymentsApi := job2.DeploymentsApi()
		deployments, _, err := deploymentsApi.List(nil)
		must.NoError(t, err)
		for _, d := range deployments {
			for _, tg := range d.TaskGroups { // this job has 1 tg
				if d.JobVersion == 1 && tg.HealthyAllocs >= tg.DesiredTotal {
					break PROMOTIONWAIT
				}
			}
		}
	}

	// expect 4 allocations for job version 1, none of them canary
	newAllocs := job2.Allocs()

Review comment (bug):
This check uses a hardcoded two, does that mean it would fail if we change the number of clients available to the cluster or some fail to deploy properly? If so, I wonder if we can use an API call to determine how many we expect?

Same comment for line 157 and 197.

Code after:
	defer cancel()

	job2.WaitForDeploymentFunc(timeout, deployment.ID, func(d *api.Deployment) bool {
		for _, tg := range d.TaskGroups { // we only have 1 tg in this job
			if d.JobVersion == 1 && tg.HealthyAllocs >= tg.DesiredCanaries {
				return true
			}
		}
		return false
	})

	// find allocations from v1 version of the job, they should all be canaries
	// and there should be exactly 2
	count := 0
	for _, a := range allocs {
		if a.JobVersion == 1 {
			must.True(t, a.DeploymentStatus.Canary)
			count += 1
		}
	}
	must.Eq(t, numberOfEligibleNodes/2, count, must.Sprint("expected canaries to be placed on 50% of eligible nodes"))

	// promote canaries
	deployments, _, err := deploymentsApi.List(nil)
	must.NoError(t, err)
	must.SliceLen(t, 2, deployments)
	_, _, err = deploymentsApi.PromoteAll(deployments[0].ID, nil)
	must.NoError(t, err)

	// promoting canaries on a system job should result in a new deployment
	deploymentsList, _, err = deploymentsApi.List(nil)
	must.NoError(t, err)

	for _, d := range deploymentsList {
		if d.JobID == job2.JobID() && d.Status == api.DeploymentStatusRunning {
			deployment = d
			break
		}
	}
	must.NotNil(t, deployment)

	// wait for the promotions to become healthy
	job2.WaitForDeploymentFunc(timeout, deployment.ID, func(d *api.Deployment) bool {
		for _, tg := range d.TaskGroups { // we only have 1 tg in this job
			if d.JobVersion == 1 && tg.HealthyAllocs >= tg.DesiredTotal {
				return true
			}
		}
		return false
	})