@@ -277,7 +277,7 @@ func (a *AllocReconciler) Compute() *ReconcileResults {
277277 // Create the allocation matrix
278278 m := newAllocMatrix (a .jobState .Job , a .jobState .ExistingAllocs )
279279
280- a .jobState .DeploymentOld , a .jobState .DeploymentCurrent , result .DeploymentUpdates = cancelUnneededDeployments (a .jobState .Job , a .jobState .DeploymentCurrent )
280+ a .jobState .DeploymentOld , a .jobState .DeploymentCurrent , result .DeploymentUpdates = cancelUnneededServiceDeployments (a .jobState .Job , a .jobState .DeploymentCurrent )
281281
282282 // If we are just stopping a job we do not need to do anything more than
283283 // stopping all running allocs
@@ -569,6 +569,57 @@ func (a *AllocReconciler) computeGroup(group string, all allocSet) (*ReconcileRe
569569 return result , deploymentComplete
570570}
571571
572+ // cancelUnneededServiceDeployments cancels any deployment that is not needed.
573+ // A deployment update will be staged for jobs that should stop or have the
574+ // wrong version. Unneeded deployments include:
575+ // 1. Jobs that are marked for stop, but there is a non-terminal deployment.
576+ // 2. Deployments that are active, but referencing a different job version.
577+ // 3. Deployments that are already successful.
578+ //
579+ // returns: old deployment, current deployment and a slice of deployment status
580+ // updates.
581+ func cancelUnneededServiceDeployments (j * structs.Job , d * structs.Deployment ) (* structs.Deployment , * structs.Deployment , []* structs.DeploymentStatusUpdate ) {
582+ var updates []* structs.DeploymentStatusUpdate
583+
584+ // If the job is stopped and there is a non-terminal deployment, cancel it
585+ if j .Stopped () {
586+ if d != nil && d .Active () {
587+ updates = append (updates , & structs.DeploymentStatusUpdate {
588+ DeploymentID : d .ID ,
589+ Status : structs .DeploymentStatusCancelled ,
590+ StatusDescription : structs .DeploymentStatusDescriptionStoppedJob ,
591+ })
592+ }
593+
594+ // Nothing else to do
595+ return d , nil , updates
596+ }
597+
598+ if d == nil {
599+ return nil , nil , nil
600+ }
601+
602+ // Check if the deployment is active and referencing an older job and cancel it
603+ if d .JobCreateIndex != j .CreateIndex || d .JobVersion != j .Version {
604+ if d .Active () {
605+ updates = append (updates , & structs.DeploymentStatusUpdate {
606+ DeploymentID : d .ID ,
607+ Status : structs .DeploymentStatusCancelled ,
608+ StatusDescription : structs .DeploymentStatusDescriptionNewerJob ,
609+ })
610+ }
611+
612+ return d , nil , updates
613+ }
614+
615+ // Clear it as the current deployment if it is successful
616+ if d .Status == structs .DeploymentStatusSuccessful {
617+ return d , nil , updates
618+ }
619+
620+ return nil , d , updates
621+ }
622+
572623// setDeploymentStatusAndUpdates sets status for a.deployment if necessary and
573624// returns an array of DeploymentStatusUpdates.
574625func (a * AllocReconciler ) setDeploymentStatusAndUpdates (deploymentComplete bool , createdDeployment * structs.Deployment ) []* structs.DeploymentStatusUpdate {
0 commit comments