@@ -61,17 +61,19 @@ func (c *DeploymentController) Handle(deployment *kapi.ReplicationController) er
6161 switch currentStatus {
6262 case deployapi .DeploymentStatusNew :
6363 // If the deployment has been cancelled, don't create a deployer pod.
64- // Transition the deployment to Pending so that re-syncs will check
65- // up on the deployer pods and so that the deployment config controller
66- // continues to see the deployment as in-flight (which it is until we
67- // have deployer pod outcomes).
64+ // Instead try to delete any deployer pods found and transition the
65+ // deployment to Pending so that the deployment config controller
66+ // continues to see the deployment as in-flight. Eventually the deletion
67+ // of the deployer pod should cause a requeue of this deployment and
68+ // then it can be transitioned to Failed by this controller.
6869 if deployutil .IsDeploymentCancelled (deployment ) {
6970 nextStatus = deployapi .DeploymentStatusPending
70- if err := c .cancelDeployerPods (deployment ); err != nil {
71+ if err := c .cleanupDeployerPods (deployment ); err != nil {
7172 return err
7273 }
7374 break
7475 }
76+
7577 // If the pod already exists, it's possible that a previous CreatePod
7678 // succeeded but the deployment state update failed and now we're re-
7779 // entering. Ensure that the pod is the one we created by verifying the
@@ -126,29 +128,34 @@ func (c *DeploymentController) Handle(deployment *kapi.ReplicationController) er
126128 case deployapi .DeploymentStatusPending , deployapi .DeploymentStatusRunning :
127129 // If the deployer pod has vanished, consider the deployment a failure.
128130 deployerPodName := deployutil .DeployerPodNameForDeployment (deployment .Name )
129- if _ , err := c .podClient .getPod (deployment .Namespace , deployerPodName ); err != nil {
130- if kerrors .IsNotFound (err ) {
131- nextStatus = deployapi .DeploymentStatusFailed
131+ _ , err := c .podClient .getPod (deployment .Namespace , deployerPodName )
132+ switch {
133+ case kerrors .IsNotFound (err ):
134+ nextStatus = deployapi .DeploymentStatusFailed
135+ // If the deployment is cancelled here then we deleted the deployer in a previous
136+ // resync of the deployment.
137+ if ! deployutil .IsDeploymentCancelled (deployment ) {
132138 deployment .Annotations [deployapi .DeploymentStatusAnnotation ] = string (nextStatus )
133139 deployment .Annotations [deployapi .DeploymentStatusReasonAnnotation ] = deployapi .DeploymentFailedDeployerPodNoLongerExists
134140 c .emitDeploymentEvent (deployment , kapi .EventTypeWarning , "Failed" , fmt .Sprintf ("Deployer pod %q has gone missing" , deployerPodName ))
135141 glog .V (4 ).Infof ("Failing deployment %q because its deployer pod %q disappeared" , deployutil .LabelForDeployment (deployment ), deployerPodName )
136- break
137- } else {
138- // We'll try again later on resync. Continue to process cancellations.
139- glog .V (2 ).Infof ("Error getting deployer pod %s for deployment %s: %#v" , deployerPodName , deployutil .LabelForDeployment (deployment ), err )
140142 }
141- }
142143
143- // If the deployment is cancelled, terminate any deployer/hook pods.
144- // NOTE: Do not mark the deployment as Failed just yet.
145- // The deployment will be marked as Failed by the deployer pod controller
146- // when the deployer pod failure state is picked up.
147- // Then, the deployment config controller will scale down the failed deployment
148- // and scale back up the last successful completed deployment.
149- if deployutil .IsDeploymentCancelled (deployment ) {
150- if err := c .cancelDeployerPods (deployment ); err != nil {
151- return err
144+ case err != nil :
145+ // We'll try again later on resync. Continue to process cancellations.
146+ glog .V (4 ).Infof ("Error getting deployer pod %s for deployment %s: %#v" , deployerPodName , deployutil .LabelForDeployment (deployment ), err )
147+
148+ default : /* err == nil */
149+ // If the deployment has been cancelled, delete any deployer pods
150+ // found and transition the deployment to Pending so that the
151+ // deployment config controller continues to see the deployment
152+ // as in-flight. Eventually the deletion of the deployer pod should
153+ // cause a requeue of this deployment and then it can be transitioned
154+ // to Failed by this controller.
155+ if deployutil .IsDeploymentCancelled (deployment ) {
156+ if err := c .cleanupDeployerPods (deployment ); err != nil {
157+ return err
158+ }
152159 }
153160 }
154161 case deployapi .DeploymentStatusFailed :
@@ -157,38 +164,22 @@ func (c *DeploymentController) Handle(deployment *kapi.ReplicationController) er
157164 deploymentScaled = deployment .Spec .Replicas != 0
158165 deployment .Spec .Replicas = 0
159166 }
167+ // Try to cleanup once more a cancelled deployment in case hook pods
168+ // were created just after we issued the first cleanup request.
169+ if deployutil .IsDeploymentCancelled (deployment ) {
170+ if err := c .cleanupDeployerPods (deployment ); err != nil {
171+ return err
172+ }
173+ }
160174 case deployapi .DeploymentStatusComplete :
161175 // Check for test deployment and ensure the deployment scale matches
162176 if config , err := c .decodeConfig (deployment ); err == nil && config .Spec .Test {
163177 deploymentScaled = deployment .Spec .Replicas != 0
164178 deployment .Spec .Replicas = 0
165179 }
166180
167- // now list any pods in the namespace that have the specified label
168- deployerPods , err := c .podClient .getDeployerPodsFor (deployment .Namespace , deployment .Name )
169- if err != nil {
170- return fmt .Errorf ("couldn't fetch deployer pods for %s after successful completion: %v" , deployutil .LabelForDeployment (deployment ), err )
171- }
172- if len (deployerPods ) > 0 {
173- glog .V (4 ).Infof ("Deleting %d deployer pods for deployment %s" , len (deployerPods ), deployutil .LabelForDeployment (deployment ))
174- }
175- cleanedAll := true
176- for _ , deployerPod := range deployerPods {
177- if err := c .podClient .deletePod (deployerPod .Namespace , deployerPod .Name ); err != nil {
178- if ! kerrors .IsNotFound (err ) {
179- // if the pod deletion failed, then log the error and continue
180- // we will try to delete any remaining deployer pods and return an error later
181- utilruntime .HandleError (fmt .Errorf ("couldn't delete completed deployer pod %s/%s for deployment %s: %v" , deployment .Namespace , deployerPod .Name , deployutil .LabelForDeployment (deployment ), err ))
182- cleanedAll = false
183- }
184- // Already deleted
185- } else {
186- glog .V (4 ).Infof ("Deleted completed deployer pod %s/%s for deployment %s" , deployment .Namespace , deployerPod .Name , deployutil .LabelForDeployment (deployment ))
187- }
188- }
189-
190- if ! cleanedAll {
191- return actionableError (fmt .Sprintf ("couldn't clean up all deployer pods for %s" , deployment .Name ))
181+ if err := c .cleanupDeployerPods (deployment ); err != nil {
182+ return err
192183 }
193184 }
194185
@@ -264,27 +255,24 @@ func (c *DeploymentController) makeDeployerPod(deployment *kapi.ReplicationContr
264255 return pod , nil
265256}
266257
267- func (c * DeploymentController ) cancelDeployerPods (deployment * kapi.ReplicationController ) error {
258+ func (c * DeploymentController ) cleanupDeployerPods (deployment * kapi.ReplicationController ) error {
268259 deployerPods , err := c .podClient .getDeployerPodsFor (deployment .Namespace , deployment .Name )
269260 if err != nil {
270- return fmt .Errorf ("couldn't fetch deployer pods for %s while trying to cancel deployment : %v" , deployutil .LabelForDeployment (deployment ), err )
261+ return fmt .Errorf ("couldn't fetch deployer pods for %q : %v" , deployutil .LabelForDeployment (deployment ), err )
271262 }
272- glog .V (4 ).Infof ("Cancelling %d deployer pods for deployment %s" , len (deployerPods ), deployutil .LabelForDeployment (deployment ))
273- zeroDelay := int64 (1 )
274- cleanedAll := len (deployerPods ) > 0
263+
264+ cleanedAll := true
275265 for _ , deployerPod := range deployerPods {
276- // Set the ActiveDeadlineSeconds on the pod so it's terminated very soon.
277- if deployerPod .Spec .ActiveDeadlineSeconds == nil || * deployerPod .Spec .ActiveDeadlineSeconds != zeroDelay {
278- deployerPod .Spec .ActiveDeadlineSeconds = & zeroDelay
279- if _ , err := c .podClient .updatePod (deployerPod .Namespace , & deployerPod ); err != nil {
280- cleanedAll = false
281- utilruntime .HandleError (fmt .Errorf ("couldn't cancel deployer pod %s for deployment %s: %v" , deployerPod .Name , deployutil .LabelForDeployment (deployment ), err ))
282- }
283- glog .V (4 ).Infof ("Cancelled deployer pod %s for deployment %s" , deployerPod .Name , deployutil .LabelForDeployment (deployment ))
266+ if err := c .podClient .deletePod (deployerPod .Namespace , deployerPod .Name ); err != nil && ! kerrors .IsNotFound (err ) {
267+ // if the pod deletion failed, then log the error and continue
268+ // we will try to delete any remaining deployer pods and return an error later
269+ utilruntime .HandleError (fmt .Errorf ("couldn't delete completed deployer pod %q for deployment %q: %v" , deployerPod .Name , deployutil .LabelForDeployment (deployment ), err ))
270+ cleanedAll = false
284271 }
285272 }
286- if cleanedAll {
287- c .emitDeploymentEvent (deployment , kapi .EventTypeNormal , "Cancelled" , "Cancelled all deployer pods" )
273+
274+ if ! cleanedAll {
275+ return actionableError (fmt .Sprintf ("couldn't clean up all deployer pods for %s" , deployment .Name ))
288276 }
289277 return nil
290278}
0 commit comments