Skip to content

Commit 71d80ca

Browse files
Ensure the test deployment invariant is maintained
Update scale for deployment while also setting next phase.
1 parent 2b8ea77 commit 71d80ca

File tree

2 files changed

+55
-0
lines changed

2 files changed

+55
-0
lines changed

pkg/deploy/controller/deployment/controller.go

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -209,6 +209,17 @@ func (c *DeploymentController) Handle(deployment *kapi.ReplicationController) er
209209
}
210210

211211
if deployutil.CanTransitionPhase(currentStatus, nextStatus) || deploymentScaled {
212+
// if we are going to transition to failed or complete and scale is non-zero, we'll check one more
213+
// time to see if we are a test deployment to guarantee that we maintain the test invariant.
214+
if deployment.Spec.Replicas != 0 {
215+
switch nextStatus {
216+
case deployapi.DeploymentStatusComplete, deployapi.DeploymentStatusFailed:
217+
if config, err := deployutil.DecodeDeploymentConfig(deployment, c.codec); err == nil && config.Spec.Test {
218+
deployment.Spec.Replicas = 0
219+
}
220+
}
221+
}
222+
212223
deployment.Annotations[deployapi.DeploymentStatusAnnotation] = string(nextStatus)
213224
if _, err := c.rn.ReplicationControllers(deployment.Namespace).Update(deployment); err != nil {
214225
return fmt.Errorf("couldn't update deployment %s to status %s: %v", deployutil.LabelForDeployment(deployment), nextStatus, err)

pkg/deploy/controller/deployment/controller_test.go

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -334,6 +334,50 @@ func TestHandle_unrelatedPodAlreadyExists(t *testing.T) {
334334
}
335335
}
336336

337+
// TestHandle_unrelatedPodAlreadyExists ensures that attempts to create a
338+
// deployer pod, when a pod with the same name but missing annotations results
339+
// a transition to failed.
340+
func TestHandle_unrelatedPodAlreadyExistsTestScaled(t *testing.T) {
341+
var updatedDeployment *kapi.ReplicationController
342+
343+
config := deploytest.TestDeploymentConfig(deploytest.OkDeploymentConfig(1))
344+
deployment, _ := deployutil.MakeDeployment(config, codec)
345+
deployment.Annotations[deployapi.DeploymentStatusAnnotation] = string(deployapi.DeploymentStatusNew)
346+
deployment.Spec.Replicas = 1
347+
348+
fake := &ktestclient.Fake{}
349+
fake.AddReactor("create", "pods", func(action ktestclient.Action) (handled bool, ret runtime.Object, err error) {
350+
name := action.(ktestclient.CreateAction).GetObject().(*kapi.Pod).Name
351+
return true, nil, kerrors.NewAlreadyExists(kapi.Resource("Pod"), name)
352+
})
353+
fake.AddReactor("update", "replicationcontrollers", func(action ktestclient.Action) (handled bool, ret runtime.Object, err error) {
354+
rc := action.(ktestclient.UpdateAction).GetObject().(*kapi.ReplicationController)
355+
updatedDeployment = rc
356+
return true, rc, nil
357+
})
358+
359+
controller := okDeploymentController(fake, deployment, nil, false, kapi.PodRunning)
360+
361+
if err := controller.Handle(deployment); err != nil {
362+
t.Fatalf("unexpected error: %v", err)
363+
}
364+
365+
if _, exists := updatedDeployment.Annotations[deployapi.DeploymentPodAnnotation]; exists {
366+
t.Fatalf("deployment updated with pod name annotation")
367+
}
368+
369+
if e, a := deployapi.DeploymentFailedUnrelatedDeploymentExists, deployment.Annotations[deployapi.DeploymentStatusReasonAnnotation]; e != a {
370+
t.Errorf("expected reason annotation %s, got %s", e, a)
371+
}
372+
373+
if e, a := deployapi.DeploymentStatusFailed, deployutil.DeploymentStatusFor(updatedDeployment); e != a {
374+
t.Errorf("expected deployment status %s, got %s", e, a)
375+
}
376+
if e, a := int32(0), updatedDeployment.Spec.Replicas; e != a {
377+
t.Errorf("expected failed deployment to be scaled to zero: %d", a)
378+
}
379+
}
380+
337381
// TestHandle_noop ensures that pending, running, and failed states result in
338382
// no action by the controller (as long as the deployment hasn't been cancelled
339383
// and the deployer pod status is synced with the deployment status).

0 commit comments

Comments
 (0)