// testRollbackDeploymentRSNoRevision tests that deployment supports rollback even when there's old replica set without revision. // An old replica set without revision is created, and then a deployment is created (v1). The deployment shouldn't add revision // annotation to the old replica set. Then rollback the deployment to last revision, and it should fail. // Then update the deployment to v2 and rollback it to v1 should succeed, now the deployment // becomes v3. Then rollback the deployment to v10 (doesn't exist in history) should fail. // Finally, rollback the deployment (v3) to v3 should be no-op. // TODO: When we finished reporting rollback status in deployment status, check the rollback status here in each case. func testRollbackDeploymentRSNoRevision(f *framework.Framework) { ns := f.Namespace.Name c := adapter.FromUnversionedClient(f.Client) podName := "nginx" deploymentPodLabels := map[string]string{"name": podName} rsPodLabels := map[string]string{ "name": podName, "pod": nginxImageName, } // Create an old RS without revision rsName := "test-rollback-no-revision-controller" rsReplicas := 0 rs := newRS(rsName, rsReplicas, rsPodLabels, nginxImageName, nginxImage) rs.Annotations = make(map[string]string) rs.Annotations["make"] = "difference" _, err := c.Extensions().ReplicaSets(ns).Create(rs) Expect(err).NotTo(HaveOccurred()) // 1. Create a deployment to create nginx pods, which have different template than the replica set created above. deploymentName, deploymentImageName := "test-rollback-no-revision-deployment", nginxImageName deploymentReplicas := 1 deploymentImage := nginxImage deploymentStrategyType := extensions.RollingUpdateDeploymentStrategyType framework.Logf("Creating deployment %s", deploymentName) d := newDeployment(deploymentName, deploymentReplicas, deploymentPodLabels, deploymentImageName, deploymentImage, deploymentStrategyType, nil) _, err = c.Extensions().Deployments(ns).Create(d) Expect(err).NotTo(HaveOccurred()) defer stopDeployment(c, f.Client, ns, deploymentName) // Wait for it to be updated to revision 1 err = framework.WaitForDeploymentRevisionAndImage(c, ns, deploymentName, "1", deploymentImage) Expect(err).NotTo(HaveOccurred()) err = framework.WaitForDeploymentStatus(c, ns, deploymentName, deploymentReplicas, deploymentReplicas-1, deploymentReplicas+1, 0) Expect(err).NotTo(HaveOccurred()) // Check that the replica set we created still doesn't contain revision information rs, err = c.Extensions().ReplicaSets(ns).Get(rsName) Expect(err).NotTo(HaveOccurred()) Expect(rs.Annotations[deploymentutil.RevisionAnnotation]).Should(Equal("")) // 2. Update the deploymentRollback to rollback to last revision // Since there's only 1 revision in history, it should stay as revision 1 revision := int64(0) framework.Logf("rolling back deployment %s to last revision", deploymentName) rollback := newDeploymentRollback(deploymentName, nil, revision) err = c.Extensions().Deployments(ns).Rollback(rollback) Expect(err).NotTo(HaveOccurred()) // Wait for the deployment to start rolling back err = framework.WaitForDeploymentRollbackCleared(c, ns, deploymentName) Expect(err).NotTo(HaveOccurred()) // TODO: report RollbackRevisionNotFound in deployment status and check it here // The pod template shouldn't change since there's no last revision // Check if the deployment is still revision 1 and still has the old pod template checkDeploymentRevision(c, ns, deploymentName, "1", deploymentImageName, deploymentImage) // 3. Update the deployment to create redis pods. updatedDeploymentImage := redisImage updatedDeploymentImageName := redisImageName deployment, err := framework.UpdateDeploymentWithRetries(c, ns, d.Name, func(update *extensions.Deployment) { update.Spec.Template.Spec.Containers[0].Name = updatedDeploymentImageName update.Spec.Template.Spec.Containers[0].Image = updatedDeploymentImage }) Expect(err).NotTo(HaveOccurred()) // Use observedGeneration to determine if the controller noticed the pod template update. err = framework.WaitForObservedDeployment(c, ns, deploymentName, deployment.Generation) Expect(err).NotTo(HaveOccurred()) // Wait for it to be updated to revision 2 err = framework.WaitForDeploymentRevisionAndImage(c, ns, deploymentName, "2", updatedDeploymentImage) Expect(err).NotTo(HaveOccurred()) err = framework.WaitForDeploymentStatus(c, ns, deploymentName, deploymentReplicas, deploymentReplicas-1, deploymentReplicas+1, 0) Expect(err).NotTo(HaveOccurred()) // 4. Update the deploymentRollback to rollback to revision 1 revision = 1 framework.Logf("rolling back deployment %s to revision %d", deploymentName, revision) rollback = newDeploymentRollback(deploymentName, nil, revision) err = c.Extensions().Deployments(ns).Rollback(rollback) Expect(err).NotTo(HaveOccurred()) // Wait for the deployment to start rolling back err = framework.WaitForDeploymentRollbackCleared(c, ns, deploymentName) Expect(err).NotTo(HaveOccurred()) // TODO: report RollbackDone in deployment status and check it here // The pod template should be updated to the one in revision 1 // Wait for it to be updated to revision 3 err = framework.WaitForDeploymentRevisionAndImage(c, ns, deploymentName, "3", deploymentImage) Expect(err).NotTo(HaveOccurred()) err = framework.WaitForDeploymentStatus(c, ns, deploymentName, deploymentReplicas, deploymentReplicas-1, deploymentReplicas+1, 0) Expect(err).NotTo(HaveOccurred()) // 5. Update the deploymentRollback to rollback to revision 10 // Since there's no revision 10 in history, it should stay as revision 3 revision = 10 framework.Logf("rolling back deployment %s to revision %d", deploymentName, revision) rollback = newDeploymentRollback(deploymentName, nil, revision) err = c.Extensions().Deployments(ns).Rollback(rollback) Expect(err).NotTo(HaveOccurred()) // Wait for the deployment to start rolling back err = framework.WaitForDeploymentRollbackCleared(c, ns, deploymentName) Expect(err).NotTo(HaveOccurred()) // TODO: report RollbackRevisionNotFound in deployment status and check it here // The pod template shouldn't change since there's no revision 10 // Check if it's still revision 3 and still has the old pod template checkDeploymentRevision(c, ns, deploymentName, "3", deploymentImageName, deploymentImage) // 6. Update the deploymentRollback to rollback to revision 3 // Since it's already revision 3, it should be no-op revision = 3 framework.Logf("rolling back deployment %s to revision %d", deploymentName, revision) rollback = newDeploymentRollback(deploymentName, nil, revision) err = c.Extensions().Deployments(ns).Rollback(rollback) Expect(err).NotTo(HaveOccurred()) // Wait for the deployment to start rolling back err = framework.WaitForDeploymentRollbackCleared(c, ns, deploymentName) Expect(err).NotTo(HaveOccurred()) // TODO: report RollbackTemplateUnchanged in deployment status and check it here // The pod template shouldn't change since it's already revision 3 // Check if it's still revision 3 and still has the old pod template checkDeploymentRevision(c, ns, deploymentName, "3", deploymentImageName, deploymentImage) }
// testRollbackDeployment tests that a deployment is created (revision 1) and updated (revision 2), and // then rollback to revision 1 (should update template to revision 1, and then update revision 1 to 3), // and then rollback to last revision. func testRollbackDeployment(f *framework.Framework) { ns := f.Namespace.Name unversionedClient := f.Client c := adapter.FromUnversionedClient(unversionedClient) podName := "nginx" deploymentPodLabels := map[string]string{"name": podName} // 1. Create a deployment to create nginx pods. deploymentName, deploymentImageName := "test-rollback-deployment", nginxImageName deploymentReplicas := 1 deploymentImage := nginxImage deploymentStrategyType := extensions.RollingUpdateDeploymentStrategyType framework.Logf("Creating deployment %s", deploymentName) d := newDeployment(deploymentName, deploymentReplicas, deploymentPodLabels, deploymentImageName, deploymentImage, deploymentStrategyType, nil) createAnnotation := map[string]string{"action": "create", "author": "minion"} d.Annotations = createAnnotation _, err := c.Extensions().Deployments(ns).Create(d) Expect(err).NotTo(HaveOccurred()) defer stopDeployment(c, f.Client, ns, deploymentName) // Wait for it to be updated to revision 1 err = framework.WaitForDeploymentRevisionAndImage(c, ns, deploymentName, "1", deploymentImage) Expect(err).NotTo(HaveOccurred()) err = framework.WaitForDeploymentStatus(c, ns, deploymentName, deploymentReplicas, deploymentReplicas-1, deploymentReplicas+1, 0) Expect(err).NotTo(HaveOccurred()) // Current newRS annotation should be "create" err = framework.CheckNewRSAnnotations(c, ns, deploymentName, createAnnotation) Expect(err).NotTo(HaveOccurred()) // 2. Update the deployment to create redis pods. updatedDeploymentImage := redisImage updatedDeploymentImageName := redisImageName updateAnnotation := map[string]string{"action": "update", "log": "I need to update it"} deployment, err := framework.UpdateDeploymentWithRetries(c, ns, d.Name, func(update *extensions.Deployment) { update.Spec.Template.Spec.Containers[0].Name = updatedDeploymentImageName update.Spec.Template.Spec.Containers[0].Image = updatedDeploymentImage update.Annotations = updateAnnotation }) Expect(err).NotTo(HaveOccurred()) // Use observedGeneration to determine if the controller noticed the pod template update. err = framework.WaitForObservedDeployment(c, ns, deploymentName, deployment.Generation) Expect(err).NotTo(HaveOccurred()) // Wait for it to be updated to revision 2 err = framework.WaitForDeploymentRevisionAndImage(c, ns, deploymentName, "2", updatedDeploymentImage) Expect(err).NotTo(HaveOccurred()) err = framework.WaitForDeploymentStatus(c, ns, deploymentName, deploymentReplicas, deploymentReplicas-1, deploymentReplicas+1, 0) Expect(err).NotTo(HaveOccurred()) // Current newRS annotation should be "update" err = framework.CheckNewRSAnnotations(c, ns, deploymentName, updateAnnotation) Expect(err).NotTo(HaveOccurred()) // 3. Update the deploymentRollback to rollback to revision 1 revision := int64(1) framework.Logf("rolling back deployment %s to revision %d", deploymentName, revision) rollback := newDeploymentRollback(deploymentName, nil, revision) err = c.Extensions().Deployments(ns).Rollback(rollback) Expect(err).NotTo(HaveOccurred()) // Wait for the deployment to start rolling back err = framework.WaitForDeploymentRollbackCleared(c, ns, deploymentName) Expect(err).NotTo(HaveOccurred()) // TODO: report RollbackDone in deployment status and check it here // Wait for it to be updated to revision 3 err = framework.WaitForDeploymentRevisionAndImage(c, ns, deploymentName, "3", deploymentImage) Expect(err).NotTo(HaveOccurred()) err = framework.WaitForDeploymentStatus(c, ns, deploymentName, deploymentReplicas, deploymentReplicas-1, deploymentReplicas+1, 0) Expect(err).NotTo(HaveOccurred()) // Current newRS annotation should be "create", after the rollback err = framework.CheckNewRSAnnotations(c, ns, deploymentName, createAnnotation) Expect(err).NotTo(HaveOccurred()) // 4. Update the deploymentRollback to rollback to last revision revision = 0 framework.Logf("rolling back deployment %s to last revision", deploymentName) rollback = newDeploymentRollback(deploymentName, nil, revision) err = c.Extensions().Deployments(ns).Rollback(rollback) Expect(err).NotTo(HaveOccurred()) err = framework.WaitForDeploymentRollbackCleared(c, ns, deploymentName) Expect(err).NotTo(HaveOccurred()) // Wait for it to be updated to revision 4 err = framework.WaitForDeploymentRevisionAndImage(c, ns, deploymentName, "4", updatedDeploymentImage) Expect(err).NotTo(HaveOccurred()) err = framework.WaitForDeploymentStatus(c, ns, deploymentName, deploymentReplicas, deploymentReplicas-1, deploymentReplicas+1, 0) Expect(err).NotTo(HaveOccurred()) // Current newRS annotation should be "update", after the rollback err = framework.CheckNewRSAnnotations(c, ns, deploymentName, updateAnnotation) Expect(err).NotTo(HaveOccurred()) }