From 3149247932b2545065ac0b1b290576bfe7c901a9 Mon Sep 17 00:00:00 2001 From: Caleb Woodbine Date: Thu, 25 Jun 2020 10:29:53 +1200 Subject: [PATCH 1/9] Add Deployment resource lifecycle test as-is --- test/e2e/apps/deployment.go | 272 +++++++++++++++++++++++++++++++++++- 1 file changed, 271 insertions(+), 1 deletion(-) diff --git a/test/e2e/apps/deployment.go b/test/e2e/apps/deployment.go index eb7726dbd0d..49949dfcc19 100644 --- a/test/e2e/apps/deployment.go +++ b/test/e2e/apps/deployment.go @@ -21,6 +21,7 @@ import ( "fmt" "math/rand" "time" + "encoding/json" "github.com/davecgh/go-spew/spew" "github.com/onsi/ginkgo" @@ -28,6 +29,10 @@ import ( "k8s.io/apimachinery/pkg/fields" "k8s.io/client-go/tools/cache" + unstructuredv1 "k8s.io/apimachinery/pkg/apis/meta/v1/unstructured" + "k8s.io/apimachinery/pkg/runtime" + "k8s.io/apimachinery/pkg/runtime/schema" + "k8s.io/client-go/dynamic" appsv1 "k8s.io/api/apps/v1" v1 "k8s.io/api/core/v1" apierrors "k8s.io/apimachinery/pkg/api/errors" @@ -67,6 +72,7 @@ var ( var _ = SIGDescribe("Deployment", func() { var ns string var c clientset.Interface + var dc dynamic.Interface ginkgo.AfterEach(func() { failureTrap(c, ns) @@ -77,6 +83,7 @@ var _ = SIGDescribe("Deployment", func() { ginkgo.BeforeEach(func() { c = f.ClientSet ns = f.Namespace.Name + dc = f.DynamicClient }) ginkgo.It("deployment reaping should cascade to its replica sets and pods", func() { @@ -134,6 +141,270 @@ var _ = SIGDescribe("Deployment", func() { }) // TODO: add tests that cover deployment.Spec.MinReadySeconds once we solved clock-skew issues // See https://github.com/kubernetes/kubernetes/issues/29229 + + ginkgo.It("should run the lifecycle of a Deployment", func() { + deploymentResource := schema.GroupVersionResource{Group: "apps", Version: "v1", Resource: "deployments"} + testDeploymentName := "test-deployment" + testDeploymentInitialImage := "nginx" + testDeploymentPatchImage := "alpine" + testDeploymentUpdateImage := "httpd" + testDeploymentDefaultReplicas := int32(3) + testDeploymentMinimumReplicas := int32(1) + testDeploymentNoReplicas := int32(0) + // TODO labels + // TODO flat labels + testDeploymentLabelSelectors := metav1.LabelSelector{ + MatchLabels: map[string]string{"app": "test-deployment"}, + } + testNamespaceName := "default" + + fmt.Println("creating a Deployment") + testDeployment := appsv1.Deployment{ + ObjectMeta: metav1.ObjectMeta{ + Name: testDeploymentName, + Labels: map[string]string{"test-deployment-static": "true"}, + }, + Spec: appsv1.DeploymentSpec{ + Replicas: &testDeploymentDefaultReplicas, + Selector: &testDeploymentLabelSelectors, + Template: v1.PodTemplateSpec{ + ObjectMeta: metav1.ObjectMeta{ + Labels: testDeploymentLabelSelectors.MatchLabels, + }, + Spec: v1.PodSpec{ + Containers: []v1.Container{{ + Name: testDeploymentName, + Image: testDeploymentInitialImage, + }}, + }, + }, + }, + } + _, err := f.ClientSet.AppsV1().Deployments(testNamespaceName).Create(context.TODO(), &testDeployment, metav1.CreateOptions{}) + if err != nil { + fmt.Println(err) + return + } + + fmt.Println("watching for the Deployment to be added") + dplmtWatchTimeoutSeconds := int64(180) + dplmtWatch, err := f.ClientSet.AppsV1().Deployments(testNamespaceName).Watch(context.TODO(), metav1.ListOptions{LabelSelector: "test-deployment-static=true", TimeoutSeconds: &dplmtWatchTimeoutSeconds}) + if err != nil { + fmt.Println(err, "Failed to setup watch on newly created Deployment") + return + } + + dplmtWatchChan := dplmtWatch.ResultChan() + for event := range dplmtWatchChan { + if event.Type == watch.Added { + break + } + } + defer func() { + fmt.Println("deleting the Deployment") + err = f.ClientSet.AppsV1().Deployments(testNamespaceName).DeleteCollection(context.TODO(), metav1.DeleteOptions{}, metav1.ListOptions{LabelSelector: "test-deployment-static=true"}) + if err != nil { + fmt.Println(err) + return + } + for event := range dplmtWatchChan { + deployment, ok := event.Object.(*appsv1.Deployment) + if ok != true { + fmt.Println("unable to convert event.Object type") + return + } + if event.Type == watch.Deleted && deployment.ObjectMeta.Name == testDeploymentName { + break + } + } + }() + fmt.Println("waiting for all Replicas to be Ready") + for event := range dplmtWatchChan { + deployment, ok := event.Object.(*appsv1.Deployment) + if ok != true { + fmt.Println("unable to convert event.Object type") + return + } + if deployment.Status.AvailableReplicas == testDeploymentDefaultReplicas && + deployment.Status.ReadyReplicas == testDeploymentDefaultReplicas { + break + } + } + + fmt.Println("patching the Deployment") + deploymentPatch, err := json.Marshal(map[string]interface{}{ + "metadata": map[string]interface{}{ + "labels": map[string]string{"test-deployment": "patched"}, + }, + "spec": map[string]interface{}{ + "replicas": testDeploymentMinimumReplicas, + "template": map[string]interface{}{ + "spec": map[string]interface{}{ + "containers": []map[string]interface{}{{ + "name": testDeploymentName, + "image": testDeploymentPatchImage, + "command": []string{"/bin/sleep", "100000"}, + }}, + }, + }, + }, + }) + if err != nil { + fmt.Println(err, "failed to Marshal Deployment JSON patch") + return + } + _, err = f.ClientSet.AppsV1().Deployments(testNamespaceName).Patch(context.TODO(), testDeploymentName, types.StrategicMergePatchType, []byte(deploymentPatch), metav1.PatchOptions{}) + if err != nil { + fmt.Println(err, "failed to patch Deployment") + return + } + + for event := range dplmtWatchChan { + if event.Type == watch.Modified { + break + } + } + fmt.Println("waiting for Replicas to scale") + for event := range dplmtWatchChan { + deployment, ok := event.Object.(*appsv1.Deployment) + if ok != true { + fmt.Println("unable to convert event.Object type") + return + } + if deployment.Status.AvailableReplicas == testDeploymentMinimumReplicas && + deployment.Status.ReadyReplicas == testDeploymentMinimumReplicas { + break + } + } + + fmt.Println("listing Deployments") + deploymentsList, err := f.ClientSet.AppsV1().Deployments("").List(context.TODO(), metav1.ListOptions{LabelSelector: "test-deployment-static=true"}) + if err != nil { + fmt.Println(err, "failed to list Deployments") + return + } + foundDeployment := false + for _, deploymentItem := range deploymentsList.Items { + if deploymentItem.ObjectMeta.Name == testDeploymentName && + deploymentItem.ObjectMeta.Namespace == testNamespaceName && + deploymentItem.ObjectMeta.Labels["test-deployment-static"] == "true" && + *deploymentItem.Spec.Replicas == testDeploymentMinimumReplicas && + deploymentItem.Spec.Template.Spec.Containers[0].Image == testDeploymentPatchImage { + foundDeployment = true + break + } + } + if foundDeployment != true { + fmt.Println("unable to find the Deployment in list") + return + } + + fmt.Println("updating the DeploymentStatus") + testDeploymentUpdate := testDeployment + testDeploymentUpdate.ObjectMeta.Labels["test-deployment"] = "updated" + testDeploymentUpdate.Spec.Template.Spec.Containers[0].Image = testDeploymentUpdateImage + testDeploymentDefaultReplicasPointer := &testDeploymentDefaultReplicas + testDeploymentUpdate.Spec.Replicas = testDeploymentDefaultReplicasPointer + testDeploymentUpdate.Status.ReadyReplicas = testDeploymentNoReplicas + testDeploymentUpdateUnstructuredMap, err := runtime.DefaultUnstructuredConverter.ToUnstructured(&testDeploymentUpdate) + if err != nil { + fmt.Println(err, "failed to convert to unstructured") + } + testDeploymentUpdateUnstructured := unstructuredv1.Unstructured{ + Object: testDeploymentUpdateUnstructuredMap, + } + // currently this hasn't been able to hit the endpoint replaceAppsV1NamespacedDeploymentStatus + _, err = dc.Resource(deploymentResource).Namespace(testNamespaceName).Update(context.TODO(), &testDeploymentUpdateUnstructured, metav1.UpdateOptions{}) //, "status") + if err != nil { + fmt.Println(err, "failed to update the DeploymentStatus") + return + } + for event := range dplmtWatchChan { + if event.Type == watch.Modified { + break + } + } + + fmt.Println("fetching the DeploymentStatus") + deploymentGetUnstructured, err := dc.Resource(deploymentResource).Namespace(testNamespaceName).Get(context.TODO(), testDeploymentName, metav1.GetOptions{}, "status") + if err != nil { + fmt.Println(err, "failed to fetch the Deployment") + return + } + deploymentGet := appsv1.Deployment{} + err = runtime.DefaultUnstructuredConverter.FromUnstructured(deploymentGetUnstructured.Object, &deploymentGet) + if err != nil { + fmt.Println(err, "failed to convert the unstructured response to a Deployment") + return + } + if !(deploymentGet.Spec.Template.Spec.Containers[0].Image == testDeploymentUpdateImage || deploymentGet.Status.ReadyReplicas == testDeploymentNoReplicas || deploymentGet.ObjectMeta.Labels["test-deployment"] == "updated") { + fmt.Println("failed to update the Deployment (did not return correct values)") + return + } + for event := range dplmtWatchChan { + if event.Type == watch.Modified { + break + } + } + for event := range dplmtWatchChan { + deployment, ok := event.Object.(*appsv1.Deployment) + if ok != true { + fmt.Println("failed to convert event Object to a Deployment") + return + } + if deployment.Status.ReadyReplicas == testDeploymentDefaultReplicas { + break + } + } + + fmt.Println("patching the DeploymentStatus") + deploymentStatusPatch, err := json.Marshal(map[string]interface{}{ + "metadata": map[string]interface{}{ + "labels": map[string]string{"test-deployment": "patched-status"}, + }, + "status": map[string]interface{}{ + "readyReplicas": testDeploymentNoReplicas, + }, + }) + if err != nil { + fmt.Println(err, "failed to Marshal Deployment JSON patch") + return + } + dc.Resource(deploymentResource).Namespace(testNamespaceName).Patch(context.TODO(), testDeploymentName, types.StrategicMergePatchType, []byte(deploymentStatusPatch), metav1.PatchOptions{}, "status") + + fmt.Println("fetching the DeploymentStatus") + deploymentGetUnstructured, err = dc.Resource(deploymentResource).Namespace(testNamespaceName).Get(context.TODO(), testDeploymentName, metav1.GetOptions{}, "status") + + if err != nil { + fmt.Println(err, "failed to fetch the DeploymentStatus") + return + } + deploymentGet = appsv1.Deployment{} + err = runtime.DefaultUnstructuredConverter.FromUnstructured(deploymentGetUnstructured.Object, &deploymentGet) + if err != nil { + fmt.Println(err, "failed to convert the unstructured response to a Deployment") + return + } + if !(deploymentGet.Spec.Template.Spec.Containers[0].Image == testDeploymentUpdateImage || deploymentGet.Status.ReadyReplicas == 0 || deploymentGet.ObjectMeta.Labels["test-deployment"] == "patched-status") { + fmt.Println("failed to update the Deployment (did not return correct values)") + return + } + for event := range dplmtWatchChan { + if event.Type == watch.Modified { + break + } + } + for event := range dplmtWatchChan { + deployment, ok := event.Object.(*appsv1.Deployment) + if ok != true { + fmt.Println("failed to convert event Object to a Deployment") + return + } + if deployment.Status.ReadyReplicas == testDeploymentDefaultReplicas { + break + } + } + }) }) func failureTrap(c clientset.Interface, ns string) { @@ -372,7 +643,6 @@ func testDeploymentCleanUpPolicy(f *framework.Framework) { w, err := c.CoreV1().Pods(ns).Watch(context.TODO(), options) framework.ExpectNoError(err) go func() { - defer ginkgo.GinkgoRecover() // There should be only one pod being created, which is the pod with the agnhost image. // The old RS shouldn't create new pod when deployment controller adding pod template hash label to its selector. numPodCreation := 1 From e719b723f7a4267d70b4872d18b4dd3064f827ce Mon Sep 17 00:00:00 2001 From: Caleb Woodbine Date: Mon, 29 Jun 2020 11:08:45 +1200 Subject: [PATCH 2/9] Update checks and status messages; Remove asserting of status values --- test/e2e/apps/deployment.go | 162 +++++++++++------------------------- 1 file changed, 50 insertions(+), 112 deletions(-) diff --git a/test/e2e/apps/deployment.go b/test/e2e/apps/deployment.go index 49949dfcc19..b6a4ecf6697 100644 --- a/test/e2e/apps/deployment.go +++ b/test/e2e/apps/deployment.go @@ -144,6 +144,7 @@ var _ = SIGDescribe("Deployment", func() { ginkgo.It("should run the lifecycle of a Deployment", func() { deploymentResource := schema.GroupVersionResource{Group: "apps", Version: "v1", Resource: "deployments"} + testNamespaceName := f.Namespace.Name testDeploymentName := "test-deployment" testDeploymentInitialImage := "nginx" testDeploymentPatchImage := "alpine" @@ -151,14 +152,13 @@ var _ = SIGDescribe("Deployment", func() { testDeploymentDefaultReplicas := int32(3) testDeploymentMinimumReplicas := int32(1) testDeploymentNoReplicas := int32(0) - // TODO labels - // TODO flat labels + testDeploymentLabels := map[string]string{"test-deployment-static": "true"} + testDeploymentLabelsFlat := "test-deployment-static=true" testDeploymentLabelSelectors := metav1.LabelSelector{ - MatchLabels: map[string]string{"app": "test-deployment"}, + MatchLabels: testDeploymentLabels, } - testNamespaceName := "default" - fmt.Println("creating a Deployment") + ginkgo.By("creating a Deployment") testDeployment := appsv1.Deployment{ ObjectMeta: metav1.ObjectMeta{ Name: testDeploymentName, @@ -180,19 +180,14 @@ var _ = SIGDescribe("Deployment", func() { }, }, } + // TODO add watch tooling _, err := f.ClientSet.AppsV1().Deployments(testNamespaceName).Create(context.TODO(), &testDeployment, metav1.CreateOptions{}) - if err != nil { - fmt.Println(err) - return - } + framework.ExpectNoError(err, "failed to create Deployment %v in namespace %v", testDeploymentName, testNamespaceName) - fmt.Println("watching for the Deployment to be added") + ginkgo.By("watching for the Deployment to be added") dplmtWatchTimeoutSeconds := int64(180) - dplmtWatch, err := f.ClientSet.AppsV1().Deployments(testNamespaceName).Watch(context.TODO(), metav1.ListOptions{LabelSelector: "test-deployment-static=true", TimeoutSeconds: &dplmtWatchTimeoutSeconds}) - if err != nil { - fmt.Println(err, "Failed to setup watch on newly created Deployment") - return - } + dplmtWatch, err := f.ClientSet.AppsV1().Deployments(testNamespaceName).Watch(context.TODO(), metav1.ListOptions{LabelSelector: testDeploymentLabelsFlat, TimeoutSeconds: &dplmtWatchTimeoutSeconds}) + framework.ExpectNoError(err, "Failed to setup watch on newly created Deployment") dplmtWatchChan := dplmtWatch.ResultChan() for event := range dplmtWatchChan { @@ -200,38 +195,17 @@ var _ = SIGDescribe("Deployment", func() { break } } - defer func() { - fmt.Println("deleting the Deployment") - err = f.ClientSet.AppsV1().Deployments(testNamespaceName).DeleteCollection(context.TODO(), metav1.DeleteOptions{}, metav1.ListOptions{LabelSelector: "test-deployment-static=true"}) - if err != nil { - fmt.Println(err) - return - } - for event := range dplmtWatchChan { - deployment, ok := event.Object.(*appsv1.Deployment) - if ok != true { - fmt.Println("unable to convert event.Object type") - return - } - if event.Type == watch.Deleted && deployment.ObjectMeta.Name == testDeploymentName { - break - } - } - }() - fmt.Println("waiting for all Replicas to be Ready") + ginkgo.By("waiting for all Replicas to be Ready") for event := range dplmtWatchChan { deployment, ok := event.Object.(*appsv1.Deployment) - if ok != true { - fmt.Println("unable to convert event.Object type") - return - } + framework.ExpectEqual(ok, true, "unable to convert event.Object type") if deployment.Status.AvailableReplicas == testDeploymentDefaultReplicas && deployment.Status.ReadyReplicas == testDeploymentDefaultReplicas { break } } - fmt.Println("patching the Deployment") + ginkgo.By("patching the Deployment") deploymentPatch, err := json.Marshal(map[string]interface{}{ "metadata": map[string]interface{}{ "labels": map[string]string{"test-deployment": "patched"}, @@ -240,7 +214,7 @@ var _ = SIGDescribe("Deployment", func() { "replicas": testDeploymentMinimumReplicas, "template": map[string]interface{}{ "spec": map[string]interface{}{ - "containers": []map[string]interface{}{{ + "containers": [1]map[string]interface{}{{ "name": testDeploymentName, "image": testDeploymentPatchImage, "command": []string{"/bin/sleep", "100000"}, @@ -249,40 +223,28 @@ var _ = SIGDescribe("Deployment", func() { }, }, }) - if err != nil { - fmt.Println(err, "failed to Marshal Deployment JSON patch") - return - } + framework.ExpectNoError(err, "failed to Marshal Deployment JSON patch") _, err = f.ClientSet.AppsV1().Deployments(testNamespaceName).Patch(context.TODO(), testDeploymentName, types.StrategicMergePatchType, []byte(deploymentPatch), metav1.PatchOptions{}) - if err != nil { - fmt.Println(err, "failed to patch Deployment") - return - } + framework.ExpectNoError(err, "failed to patch Deployment") for event := range dplmtWatchChan { if event.Type == watch.Modified { break } } - fmt.Println("waiting for Replicas to scale") + ginkgo.By("waiting for Replicas to scale") for event := range dplmtWatchChan { deployment, ok := event.Object.(*appsv1.Deployment) - if ok != true { - fmt.Println("unable to convert event.Object type") - return - } + framework.ExpectEqual(ok, true, "unable to convert event.Object type") if deployment.Status.AvailableReplicas == testDeploymentMinimumReplicas && deployment.Status.ReadyReplicas == testDeploymentMinimumReplicas { break } } - fmt.Println("listing Deployments") - deploymentsList, err := f.ClientSet.AppsV1().Deployments("").List(context.TODO(), metav1.ListOptions{LabelSelector: "test-deployment-static=true"}) - if err != nil { - fmt.Println(err, "failed to list Deployments") - return - } + ginkgo.By("listing Deployments") + deploymentsList, err := f.ClientSet.AppsV1().Deployments("").List(context.TODO(), metav1.ListOptions{LabelSelector: testDeploymentLabelsFlat}) + framework.ExpectNoError(err, "failed to list Deployments") foundDeployment := false for _, deploymentItem := range deploymentsList.Items { if deploymentItem.ObjectMeta.Name == testDeploymentName && @@ -294,53 +256,36 @@ var _ = SIGDescribe("Deployment", func() { break } } - if foundDeployment != true { - fmt.Println("unable to find the Deployment in list") - return - } + framework.ExpectEqual(foundDeployment, true, "unable to find the Deployment in list", deploymentsList) - fmt.Println("updating the DeploymentStatus") + ginkgo.By("updating the DeploymentStatus") testDeploymentUpdate := testDeployment testDeploymentUpdate.ObjectMeta.Labels["test-deployment"] = "updated" testDeploymentUpdate.Spec.Template.Spec.Containers[0].Image = testDeploymentUpdateImage testDeploymentDefaultReplicasPointer := &testDeploymentDefaultReplicas testDeploymentUpdate.Spec.Replicas = testDeploymentDefaultReplicasPointer - testDeploymentUpdate.Status.ReadyReplicas = testDeploymentNoReplicas testDeploymentUpdateUnstructuredMap, err := runtime.DefaultUnstructuredConverter.ToUnstructured(&testDeploymentUpdate) - if err != nil { - fmt.Println(err, "failed to convert to unstructured") - } + framework.ExpectNoError(err, "failed to convert to unstructured") testDeploymentUpdateUnstructured := unstructuredv1.Unstructured{ Object: testDeploymentUpdateUnstructuredMap, } // currently this hasn't been able to hit the endpoint replaceAppsV1NamespacedDeploymentStatus _, err = dc.Resource(deploymentResource).Namespace(testNamespaceName).Update(context.TODO(), &testDeploymentUpdateUnstructured, metav1.UpdateOptions{}) //, "status") - if err != nil { - fmt.Println(err, "failed to update the DeploymentStatus") - return - } + framework.ExpectNoError(err, "failed to update the DeploymentStatus") for event := range dplmtWatchChan { if event.Type == watch.Modified { break } } - fmt.Println("fetching the DeploymentStatus") + ginkgo.By("fetching the DeploymentStatus") deploymentGetUnstructured, err := dc.Resource(deploymentResource).Namespace(testNamespaceName).Get(context.TODO(), testDeploymentName, metav1.GetOptions{}, "status") - if err != nil { - fmt.Println(err, "failed to fetch the Deployment") - return - } + framework.ExpectNoError(err, "failed to fetch the Deployment") deploymentGet := appsv1.Deployment{} err = runtime.DefaultUnstructuredConverter.FromUnstructured(deploymentGetUnstructured.Object, &deploymentGet) - if err != nil { - fmt.Println(err, "failed to convert the unstructured response to a Deployment") - return - } - if !(deploymentGet.Spec.Template.Spec.Containers[0].Image == testDeploymentUpdateImage || deploymentGet.Status.ReadyReplicas == testDeploymentNoReplicas || deploymentGet.ObjectMeta.Labels["test-deployment"] == "updated") { - fmt.Println("failed to update the Deployment (did not return correct values)") - return - } + framework.ExpectNoError(err, "failed to convert the unstructured response to a Deployment") + framework.ExpectEqual(deploymentGet.Spec.Template.Spec.Containers[0].Image, testDeploymentUpdateImage, "failed to update image") + framework.ExpectEqual(deploymentGet.ObjectMeta.Labels["test-deployment"], "updated", "failed to update labels") for event := range dplmtWatchChan { if event.Type == watch.Modified { break @@ -348,16 +293,13 @@ var _ = SIGDescribe("Deployment", func() { } for event := range dplmtWatchChan { deployment, ok := event.Object.(*appsv1.Deployment) - if ok != true { - fmt.Println("failed to convert event Object to a Deployment") - return - } + framework.ExpectEqual(ok, true, "unable to convert event.Object type") if deployment.Status.ReadyReplicas == testDeploymentDefaultReplicas { break } } - fmt.Println("patching the DeploymentStatus") + ginkgo.By("patching the DeploymentStatus") deploymentStatusPatch, err := json.Marshal(map[string]interface{}{ "metadata": map[string]interface{}{ "labels": map[string]string{"test-deployment": "patched-status"}, @@ -366,29 +308,17 @@ var _ = SIGDescribe("Deployment", func() { "readyReplicas": testDeploymentNoReplicas, }, }) - if err != nil { - fmt.Println(err, "failed to Marshal Deployment JSON patch") - return - } + framework.ExpectNoError(err, "failed to Marshal Deployment JSON patch") dc.Resource(deploymentResource).Namespace(testNamespaceName).Patch(context.TODO(), testDeploymentName, types.StrategicMergePatchType, []byte(deploymentStatusPatch), metav1.PatchOptions{}, "status") - fmt.Println("fetching the DeploymentStatus") + ginkgo.By("fetching the DeploymentStatus") deploymentGetUnstructured, err = dc.Resource(deploymentResource).Namespace(testNamespaceName).Get(context.TODO(), testDeploymentName, metav1.GetOptions{}, "status") - - if err != nil { - fmt.Println(err, "failed to fetch the DeploymentStatus") - return - } + framework.ExpectNoError(err, "failed to fetch the DeploymentStatus") deploymentGet = appsv1.Deployment{} err = runtime.DefaultUnstructuredConverter.FromUnstructured(deploymentGetUnstructured.Object, &deploymentGet) - if err != nil { - fmt.Println(err, "failed to convert the unstructured response to a Deployment") - return - } - if !(deploymentGet.Spec.Template.Spec.Containers[0].Image == testDeploymentUpdateImage || deploymentGet.Status.ReadyReplicas == 0 || deploymentGet.ObjectMeta.Labels["test-deployment"] == "patched-status") { - fmt.Println("failed to update the Deployment (did not return correct values)") - return - } + framework.ExpectNoError(err, "failed to convert the unstructured response to a Deployment") + framework.ExpectEqual(deploymentGet.Spec.Template.Spec.Containers[0].Image, testDeploymentUpdateImage, "failed to update image") + framework.ExpectEqual(deploymentGet.ObjectMeta.Labels["test-deployment"], "updated", "failed to update labels") for event := range dplmtWatchChan { if event.Type == watch.Modified { break @@ -396,14 +326,22 @@ var _ = SIGDescribe("Deployment", func() { } for event := range dplmtWatchChan { deployment, ok := event.Object.(*appsv1.Deployment) - if ok != true { - fmt.Println("failed to convert event Object to a Deployment") - return - } + framework.ExpectEqual(ok, true, "unable to convert event.Object type") if deployment.Status.ReadyReplicas == testDeploymentDefaultReplicas { break } } + + ginkgo.By("deleting the Deployment") + err = f.ClientSet.AppsV1().Deployments(testNamespaceName).DeleteCollection(context.TODO(), metav1.DeleteOptions{}, metav1.ListOptions{LabelSelector: testDeploymentLabelsFlat}) + framework.ExpectNoError(err, "failed to delete Deployment via collection") + for event := range dplmtWatchChan { + deployment, ok := event.Object.(*appsv1.Deployment) + framework.ExpectEqual(ok, true, "unable to convert event.Object type") + if event.Type == watch.Deleted && deployment.ObjectMeta.Name == testDeploymentName { + break + } + } }) }) From b38d7f25fefa035f97c7cd911645d9a98f1e6f86 Mon Sep 17 00:00:00 2001 From: Caleb Woodbine Date: Mon, 20 Jul 2020 11:00:37 +1200 Subject: [PATCH 3/9] Remove watch tooling --- test/e2e/apps/deployment.go | 32 +++++++++++++++++++++++++++++++- 1 file changed, 31 insertions(+), 1 deletion(-) diff --git a/test/e2e/apps/deployment.go b/test/e2e/apps/deployment.go index b6a4ecf6697..cebea339e62 100644 --- a/test/e2e/apps/deployment.go +++ b/test/e2e/apps/deployment.go @@ -180,7 +180,6 @@ var _ = SIGDescribe("Deployment", func() { }, }, } - // TODO add watch tooling _, err := f.ClientSet.AppsV1().Deployments(testNamespaceName).Create(context.TODO(), &testDeployment, metav1.CreateOptions{}) framework.ExpectNoError(err, "failed to create Deployment %v in namespace %v", testDeploymentName, testNamespaceName) @@ -189,21 +188,28 @@ var _ = SIGDescribe("Deployment", func() { dplmtWatch, err := f.ClientSet.AppsV1().Deployments(testNamespaceName).Watch(context.TODO(), metav1.ListOptions{LabelSelector: testDeploymentLabelsFlat, TimeoutSeconds: &dplmtWatchTimeoutSeconds}) framework.ExpectNoError(err, "Failed to setup watch on newly created Deployment") + foundEvent := false dplmtWatchChan := dplmtWatch.ResultChan() for event := range dplmtWatchChan { if event.Type == watch.Added { + foundEvent = true break } } + framework.ExpectEqual(foundEvent, true, "failed to find watch event %v", watch.Added) + ginkgo.By("waiting for all Replicas to be Ready") + foundEvent = false for event := range dplmtWatchChan { deployment, ok := event.Object.(*appsv1.Deployment) framework.ExpectEqual(ok, true, "unable to convert event.Object type") if deployment.Status.AvailableReplicas == testDeploymentDefaultReplicas && deployment.Status.ReadyReplicas == testDeploymentDefaultReplicas { + foundEvent = true break } } + framework.ExpectEqual(foundEvent, true, "failed to see scale of replicas") ginkgo.By("patching the Deployment") deploymentPatch, err := json.Marshal(map[string]interface{}{ @@ -227,20 +233,27 @@ var _ = SIGDescribe("Deployment", func() { _, err = f.ClientSet.AppsV1().Deployments(testNamespaceName).Patch(context.TODO(), testDeploymentName, types.StrategicMergePatchType, []byte(deploymentPatch), metav1.PatchOptions{}) framework.ExpectNoError(err, "failed to patch Deployment") + foundEvent = false for event := range dplmtWatchChan { if event.Type == watch.Modified { + foundEvent = true break } } + framework.ExpectEqual(foundEvent, true, "failed to see scale of replicas") + ginkgo.By("waiting for Replicas to scale") + foundEvent = false for event := range dplmtWatchChan { deployment, ok := event.Object.(*appsv1.Deployment) framework.ExpectEqual(ok, true, "unable to convert event.Object type") if deployment.Status.AvailableReplicas == testDeploymentMinimumReplicas && deployment.Status.ReadyReplicas == testDeploymentMinimumReplicas { + foundEvent = true break } } + framework.ExpectEqual(foundEvent, true, "failed to see scale of replicas") ginkgo.By("listing Deployments") deploymentsList, err := f.ClientSet.AppsV1().Deployments("").List(context.TODO(), metav1.ListOptions{LabelSelector: testDeploymentLabelsFlat}) @@ -272,11 +285,14 @@ var _ = SIGDescribe("Deployment", func() { // currently this hasn't been able to hit the endpoint replaceAppsV1NamespacedDeploymentStatus _, err = dc.Resource(deploymentResource).Namespace(testNamespaceName).Update(context.TODO(), &testDeploymentUpdateUnstructured, metav1.UpdateOptions{}) //, "status") framework.ExpectNoError(err, "failed to update the DeploymentStatus") + foundEvent = false for event := range dplmtWatchChan { if event.Type == watch.Modified { + foundEvent = true break } } + framework.ExpectEqual(foundEvent, true, "failed to find watch event %v", watch.Modified) ginkgo.By("fetching the DeploymentStatus") deploymentGetUnstructured, err := dc.Resource(deploymentResource).Namespace(testNamespaceName).Get(context.TODO(), testDeploymentName, metav1.GetOptions{}, "status") @@ -286,18 +302,25 @@ var _ = SIGDescribe("Deployment", func() { framework.ExpectNoError(err, "failed to convert the unstructured response to a Deployment") framework.ExpectEqual(deploymentGet.Spec.Template.Spec.Containers[0].Image, testDeploymentUpdateImage, "failed to update image") framework.ExpectEqual(deploymentGet.ObjectMeta.Labels["test-deployment"], "updated", "failed to update labels") + foundEvent = false for event := range dplmtWatchChan { if event.Type == watch.Modified { + foundEvent = true break } } + framework.ExpectEqual(foundEvent, true, "failed to find watch event %v", watch.Modified) + + foundEvent = false for event := range dplmtWatchChan { deployment, ok := event.Object.(*appsv1.Deployment) framework.ExpectEqual(ok, true, "unable to convert event.Object type") if deployment.Status.ReadyReplicas == testDeploymentDefaultReplicas { + foundEvent = true break } } + framework.ExpectEqual(foundEvent, true, "failed to see scale of replicas") ginkgo.By("patching the DeploymentStatus") deploymentStatusPatch, err := json.Marshal(map[string]interface{}{ @@ -319,11 +342,14 @@ var _ = SIGDescribe("Deployment", func() { framework.ExpectNoError(err, "failed to convert the unstructured response to a Deployment") framework.ExpectEqual(deploymentGet.Spec.Template.Spec.Containers[0].Image, testDeploymentUpdateImage, "failed to update image") framework.ExpectEqual(deploymentGet.ObjectMeta.Labels["test-deployment"], "updated", "failed to update labels") + foundEvent = false for event := range dplmtWatchChan { if event.Type == watch.Modified { + foundEvent = true break } } + framework.ExpectEqual(foundEvent, true, "failed to find watch event %v", watch.Modified) for event := range dplmtWatchChan { deployment, ok := event.Object.(*appsv1.Deployment) framework.ExpectEqual(ok, true, "unable to convert event.Object type") @@ -335,13 +361,17 @@ var _ = SIGDescribe("Deployment", func() { ginkgo.By("deleting the Deployment") err = f.ClientSet.AppsV1().Deployments(testNamespaceName).DeleteCollection(context.TODO(), metav1.DeleteOptions{}, metav1.ListOptions{LabelSelector: testDeploymentLabelsFlat}) framework.ExpectNoError(err, "failed to delete Deployment via collection") + + foundEvent = false for event := range dplmtWatchChan { deployment, ok := event.Object.(*appsv1.Deployment) framework.ExpectEqual(ok, true, "unable to convert event.Object type") if event.Type == watch.Deleted && deployment.ObjectMeta.Name == testDeploymentName { + foundEvent = true break } } + framework.ExpectEqual(foundEvent, true, "failed to find watch event %v", watch.Deleted) }) }) From 125e839d7744e895559ab3c6571fe464e6704c56 Mon Sep 17 00:00:00 2001 From: Caleb Woodbine Date: Mon, 20 Jul 2020 13:16:35 +1200 Subject: [PATCH 4/9] Fix formatting --- test/e2e/apps/deployment.go | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/test/e2e/apps/deployment.go b/test/e2e/apps/deployment.go index cebea339e62..a78ce6804e6 100644 --- a/test/e2e/apps/deployment.go +++ b/test/e2e/apps/deployment.go @@ -18,10 +18,10 @@ package apps import ( "context" + "encoding/json" "fmt" "math/rand" "time" - "encoding/json" "github.com/davecgh/go-spew/spew" "github.com/onsi/ginkgo" @@ -29,19 +29,19 @@ import ( "k8s.io/apimachinery/pkg/fields" "k8s.io/client-go/tools/cache" - unstructuredv1 "k8s.io/apimachinery/pkg/apis/meta/v1/unstructured" - "k8s.io/apimachinery/pkg/runtime" - "k8s.io/apimachinery/pkg/runtime/schema" - "k8s.io/client-go/dynamic" appsv1 "k8s.io/api/apps/v1" v1 "k8s.io/api/core/v1" apierrors "k8s.io/apimachinery/pkg/api/errors" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + unstructuredv1 "k8s.io/apimachinery/pkg/apis/meta/v1/unstructured" "k8s.io/apimachinery/pkg/labels" + "k8s.io/apimachinery/pkg/runtime" + "k8s.io/apimachinery/pkg/runtime/schema" "k8s.io/apimachinery/pkg/types" "k8s.io/apimachinery/pkg/util/intstr" "k8s.io/apimachinery/pkg/util/wait" "k8s.io/apimachinery/pkg/watch" + "k8s.io/client-go/dynamic" clientset "k8s.io/client-go/kubernetes" appsclient "k8s.io/client-go/kubernetes/typed/apps/v1" watchtools "k8s.io/client-go/tools/watch" From 9c2330db4c2a7d2daee9de643d25f6aa30e69050 Mon Sep 17 00:00:00 2001 From: Caleb Woodbine Date: Wed, 22 Jul 2020 08:48:28 +1200 Subject: [PATCH 5/9] Revert ginkgoRecover --- test/e2e/apps/deployment.go | 1 + 1 file changed, 1 insertion(+) diff --git a/test/e2e/apps/deployment.go b/test/e2e/apps/deployment.go index a78ce6804e6..886ec8787fe 100644 --- a/test/e2e/apps/deployment.go +++ b/test/e2e/apps/deployment.go @@ -611,6 +611,7 @@ func testDeploymentCleanUpPolicy(f *framework.Framework) { w, err := c.CoreV1().Pods(ns).Watch(context.TODO(), options) framework.ExpectNoError(err) go func() { + defer ginkgo.GinkgoRecover() // There should be only one pod being created, which is the pod with the agnhost image. // The old RS shouldn't create new pod when deployment controller adding pod template hash label to its selector. numPodCreation := 1 From fc8e24c6869a0a137f8c5bd4d8de2a0616d97d58 Mon Sep 17 00:00:00 2001 From: Caleb Woodbine Date: Wed, 22 Jul 2020 09:29:09 +1200 Subject: [PATCH 6/9] Add watchtools.Until for fetching watch events; Remove plain watch --- test/e2e/apps/deployment.go | 212 ++++++++++++++++++++---------------- 1 file changed, 121 insertions(+), 91 deletions(-) diff --git a/test/e2e/apps/deployment.go b/test/e2e/apps/deployment.go index 886ec8787fe..0e3d5b94740 100644 --- a/test/e2e/apps/deployment.go +++ b/test/e2e/apps/deployment.go @@ -157,6 +157,14 @@ var _ = SIGDescribe("Deployment", func() { testDeploymentLabelSelectors := metav1.LabelSelector{ MatchLabels: testDeploymentLabels, } + w := &cache.ListWatch{ + WatchFunc: func(options metav1.ListOptions) (watch.Interface, error) { + options.LabelSelector = testDeploymentLabelsFlat + return f.ClientSet.AppsV1().Deployments(testNamespaceName).Watch(context.TODO(), options) + }, + } + deploymentsList, err := f.ClientSet.AppsV1().Deployments("").List(context.TODO(), metav1.ListOptions{LabelSelector: testDeploymentLabelsFlat}) + framework.ExpectNoError(err, "failed to list Endpoints") ginkgo.By("creating a Deployment") testDeployment := appsv1.Deployment{ @@ -180,36 +188,41 @@ var _ = SIGDescribe("Deployment", func() { }, }, } - _, err := f.ClientSet.AppsV1().Deployments(testNamespaceName).Create(context.TODO(), &testDeployment, metav1.CreateOptions{}) + _, err = f.ClientSet.AppsV1().Deployments(testNamespaceName).Create(context.TODO(), &testDeployment, metav1.CreateOptions{}) framework.ExpectNoError(err, "failed to create Deployment %v in namespace %v", testDeploymentName, testNamespaceName) - ginkgo.By("watching for the Deployment to be added") - dplmtWatchTimeoutSeconds := int64(180) - dplmtWatch, err := f.ClientSet.AppsV1().Deployments(testNamespaceName).Watch(context.TODO(), metav1.ListOptions{LabelSelector: testDeploymentLabelsFlat, TimeoutSeconds: &dplmtWatchTimeoutSeconds}) - framework.ExpectNoError(err, "Failed to setup watch on newly created Deployment") - - foundEvent := false - dplmtWatchChan := dplmtWatch.ResultChan() - for event := range dplmtWatchChan { - if event.Type == watch.Added { - foundEvent = true - break + ginkgo.By("waiting for Deployment to be created") + ctx, cancel := context.WithTimeout(context.Background(), 30*time.Second) + defer cancel() + _, err = watchtools.Until(ctx, deploymentsList.ResourceVersion, w, func(event watch.Event) (bool, error) { + switch event.Type { + case watch.Added: + if deployment, ok := event.Object.(*appsv1.Deployment); ok { + found := deployment.ObjectMeta.Name == testDeployment.Name && + deployment.Labels["test-deployment-static"] == "true" + return found, nil + } + default: + framework.Logf("observed event type %v", event.Type) } - } - framework.ExpectEqual(foundEvent, true, "failed to find watch event %v", watch.Added) + return false, nil + }) + framework.ExpectNoError(err, "failed to see %v event", watch.Added) ginkgo.By("waiting for all Replicas to be Ready") - foundEvent = false - for event := range dplmtWatchChan { - deployment, ok := event.Object.(*appsv1.Deployment) - framework.ExpectEqual(ok, true, "unable to convert event.Object type") - if deployment.Status.AvailableReplicas == testDeploymentDefaultReplicas && - deployment.Status.ReadyReplicas == testDeploymentDefaultReplicas { - foundEvent = true - break + ctx, cancel = context.WithTimeout(context.Background(), 30*time.Second) + defer cancel() + _, err = watchtools.Until(ctx, deploymentsList.ResourceVersion, w, func(event watch.Event) (bool, error) { + if deployment, ok := event.Object.(*appsv1.Deployment); ok { + found := deployment.ObjectMeta.Name == testDeployment.Name && + deployment.Labels["test-deployment-static"] == "true" && + deployment.Status.AvailableReplicas == testDeploymentDefaultReplicas && + deployment.Status.ReadyReplicas == testDeploymentDefaultReplicas + return found, nil } - } - framework.ExpectEqual(foundEvent, true, "failed to see scale of replicas") + return false, nil + }) + framework.ExpectNoError(err, "failed to see replicas of %v in namespace %v scale to requested amount of %v", testDeployment.Name, testNamespaceName, testDeploymentDefaultReplicas) ginkgo.By("patching the Deployment") deploymentPatch, err := json.Marshal(map[string]interface{}{ @@ -233,30 +246,23 @@ var _ = SIGDescribe("Deployment", func() { _, err = f.ClientSet.AppsV1().Deployments(testNamespaceName).Patch(context.TODO(), testDeploymentName, types.StrategicMergePatchType, []byte(deploymentPatch), metav1.PatchOptions{}) framework.ExpectNoError(err, "failed to patch Deployment") - foundEvent = false - for event := range dplmtWatchChan { - if event.Type == watch.Modified { - foundEvent = true - break - } - } - framework.ExpectEqual(foundEvent, true, "failed to see scale of replicas") - ginkgo.By("waiting for Replicas to scale") - foundEvent = false - for event := range dplmtWatchChan { - deployment, ok := event.Object.(*appsv1.Deployment) - framework.ExpectEqual(ok, true, "unable to convert event.Object type") - if deployment.Status.AvailableReplicas == testDeploymentMinimumReplicas && - deployment.Status.ReadyReplicas == testDeploymentMinimumReplicas { - foundEvent = true - break + ctx, cancel = context.WithTimeout(context.Background(), 30*time.Second) + defer cancel() + _, err = watchtools.Until(ctx, deploymentsList.ResourceVersion, w, func(event watch.Event) (bool, error) { + if deployment, ok := event.Object.(*appsv1.Deployment); ok { + found := deployment.ObjectMeta.Name == testDeployment.Name && + deployment.Labels["test-deployment-static"] == "true" && + deployment.Status.AvailableReplicas == testDeploymentMinimumReplicas && + deployment.Status.ReadyReplicas == testDeploymentMinimumReplicas + return found, nil } - } - framework.ExpectEqual(foundEvent, true, "failed to see scale of replicas") + return false, nil + }) + framework.ExpectNoError(err, "failed to see replicas of %v in namespace %v scale to requested amount of %v", testDeployment.Name, testNamespaceName, testDeploymentMinimumReplicas) ginkgo.By("listing Deployments") - deploymentsList, err := f.ClientSet.AppsV1().Deployments("").List(context.TODO(), metav1.ListOptions{LabelSelector: testDeploymentLabelsFlat}) + deploymentsList, err = f.ClientSet.AppsV1().Deployments("").List(context.TODO(), metav1.ListOptions{LabelSelector: testDeploymentLabelsFlat}) framework.ExpectNoError(err, "failed to list Deployments") foundDeployment := false for _, deploymentItem := range deploymentsList.Items { @@ -285,14 +291,22 @@ var _ = SIGDescribe("Deployment", func() { // currently this hasn't been able to hit the endpoint replaceAppsV1NamespacedDeploymentStatus _, err = dc.Resource(deploymentResource).Namespace(testNamespaceName).Update(context.TODO(), &testDeploymentUpdateUnstructured, metav1.UpdateOptions{}) //, "status") framework.ExpectNoError(err, "failed to update the DeploymentStatus") - foundEvent = false - for event := range dplmtWatchChan { - if event.Type == watch.Modified { - foundEvent = true - break + ctx, cancel = context.WithTimeout(context.Background(), 30*time.Second) + defer cancel() + _, err = watchtools.Until(ctx, deploymentsList.ResourceVersion, w, func(event watch.Event) (bool, error) { + switch event.Type { + case watch.Modified: + if deployment, ok := event.Object.(*appsv1.Deployment); ok { + found := deployment.ObjectMeta.Name == testDeployment.Name && + deployment.Labels["test-deployment-static"] == "true" + return found, nil + } + default: + framework.Logf("observed event type %v", event.Type) } - } - framework.ExpectEqual(foundEvent, true, "failed to find watch event %v", watch.Modified) + return false, nil + }) + framework.ExpectNoError(err, "failed to see %v event", watch.Modified) ginkgo.By("fetching the DeploymentStatus") deploymentGetUnstructured, err := dc.Resource(deploymentResource).Namespace(testNamespaceName).Get(context.TODO(), testDeploymentName, metav1.GetOptions{}, "status") @@ -302,25 +316,20 @@ var _ = SIGDescribe("Deployment", func() { framework.ExpectNoError(err, "failed to convert the unstructured response to a Deployment") framework.ExpectEqual(deploymentGet.Spec.Template.Spec.Containers[0].Image, testDeploymentUpdateImage, "failed to update image") framework.ExpectEqual(deploymentGet.ObjectMeta.Labels["test-deployment"], "updated", "failed to update labels") - foundEvent = false - for event := range dplmtWatchChan { - if event.Type == watch.Modified { - foundEvent = true - break - } - } - framework.ExpectEqual(foundEvent, true, "failed to find watch event %v", watch.Modified) - foundEvent = false - for event := range dplmtWatchChan { - deployment, ok := event.Object.(*appsv1.Deployment) - framework.ExpectEqual(ok, true, "unable to convert event.Object type") - if deployment.Status.ReadyReplicas == testDeploymentDefaultReplicas { - foundEvent = true - break + ctx, cancel = context.WithTimeout(context.Background(), 30*time.Second) + defer cancel() + _, err = watchtools.Until(ctx, deploymentsList.ResourceVersion, w, func(event watch.Event) (bool, error) { + if deployment, ok := event.Object.(*appsv1.Deployment); ok { + found := deployment.ObjectMeta.Name == testDeployment.Name && + deployment.Labels["test-deployment-static"] == "true" && + deployment.Status.AvailableReplicas == testDeploymentDefaultReplicas && + deployment.Status.ReadyReplicas == testDeploymentDefaultReplicas + return found, nil } - } - framework.ExpectEqual(foundEvent, true, "failed to see scale of replicas") + return false, nil + }) + framework.ExpectNoError(err, "failed to see replicas of %v in namespace %v scale to requested amount of %v", testDeployment.Name, testNamespaceName, testDeploymentDefaultReplicas) ginkgo.By("patching the DeploymentStatus") deploymentStatusPatch, err := json.Marshal(map[string]interface{}{ @@ -333,6 +342,22 @@ var _ = SIGDescribe("Deployment", func() { }) framework.ExpectNoError(err, "failed to Marshal Deployment JSON patch") dc.Resource(deploymentResource).Namespace(testNamespaceName).Patch(context.TODO(), testDeploymentName, types.StrategicMergePatchType, []byte(deploymentStatusPatch), metav1.PatchOptions{}, "status") + ctx, cancel = context.WithTimeout(context.Background(), 30*time.Second) + defer cancel() + _, err = watchtools.Until(ctx, deploymentsList.ResourceVersion, w, func(event watch.Event) (bool, error) { + switch event.Type { + case watch.Modified: + if deployment, ok := event.Object.(*appsv1.Deployment); ok { + found := deployment.ObjectMeta.Name == testDeployment.Name && + deployment.Labels["test-deployment-static"] == "true" + return found, nil + } + default: + framework.Logf("observed event type %v", event.Type) + } + return false, nil + }) + framework.ExpectNoError(err, "failed to see %v event", watch.Modified) ginkgo.By("fetching the DeploymentStatus") deploymentGetUnstructured, err = dc.Resource(deploymentResource).Namespace(testNamespaceName).Get(context.TODO(), testDeploymentName, metav1.GetOptions{}, "status") @@ -342,36 +367,41 @@ var _ = SIGDescribe("Deployment", func() { framework.ExpectNoError(err, "failed to convert the unstructured response to a Deployment") framework.ExpectEqual(deploymentGet.Spec.Template.Spec.Containers[0].Image, testDeploymentUpdateImage, "failed to update image") framework.ExpectEqual(deploymentGet.ObjectMeta.Labels["test-deployment"], "updated", "failed to update labels") - foundEvent = false - for event := range dplmtWatchChan { - if event.Type == watch.Modified { - foundEvent = true - break + ctx, cancel = context.WithTimeout(context.Background(), 30*time.Second) + defer cancel() + _, err = watchtools.Until(ctx, deploymentsList.ResourceVersion, w, func(event watch.Event) (bool, error) { + if deployment, ok := event.Object.(*appsv1.Deployment); ok { + found := deployment.ObjectMeta.Name == testDeployment.Name && + deployment.Labels["test-deployment-static"] == "true" && + deployment.Status.AvailableReplicas == testDeploymentDefaultReplicas && + deployment.Status.ReadyReplicas == testDeploymentDefaultReplicas && + deployment.Spec.Template.Spec.Containers[0].Image == testDeploymentUpdateImage + return found, nil } - } - framework.ExpectEqual(foundEvent, true, "failed to find watch event %v", watch.Modified) - for event := range dplmtWatchChan { - deployment, ok := event.Object.(*appsv1.Deployment) - framework.ExpectEqual(ok, true, "unable to convert event.Object type") - if deployment.Status.ReadyReplicas == testDeploymentDefaultReplicas { - break - } - } + return false, nil + }) + framework.ExpectNoError(err, "failed to see replicas of %v in namespace %v scale to requested amount of %v", testDeployment.Name, testNamespaceName, testDeploymentDefaultReplicas) ginkgo.By("deleting the Deployment") err = f.ClientSet.AppsV1().Deployments(testNamespaceName).DeleteCollection(context.TODO(), metav1.DeleteOptions{}, metav1.ListOptions{LabelSelector: testDeploymentLabelsFlat}) framework.ExpectNoError(err, "failed to delete Deployment via collection") - foundEvent = false - for event := range dplmtWatchChan { - deployment, ok := event.Object.(*appsv1.Deployment) - framework.ExpectEqual(ok, true, "unable to convert event.Object type") - if event.Type == watch.Deleted && deployment.ObjectMeta.Name == testDeploymentName { - foundEvent = true - break + ctx, cancel = context.WithTimeout(context.Background(), 30*time.Second) + defer cancel() + _, err = watchtools.Until(ctx, deploymentsList.ResourceVersion, w, func(event watch.Event) (bool, error) { + switch event.Type { + case watch.Deleted: + if deployment, ok := event.Object.(*appsv1.Deployment); ok { + found := deployment.ObjectMeta.Name == testDeployment.Name && + deployment.Labels["test-deployment-static"] == "true" + return found, nil + } + default: + framework.Logf("observed event type %v", event.Type) } - } - framework.ExpectEqual(foundEvent, true, "failed to find watch event %v", watch.Deleted) + return false, nil + }) + framework.ExpectNoError(err, "failed to see %v event", watch.Deleted) }) }) From 11492f7b91c68b0d5b4b3c7e30b5e39880dc1043 Mon Sep 17 00:00:00 2001 From: Caleb Woodbine Date: Wed, 22 Jul 2020 09:57:11 +1200 Subject: [PATCH 7/9] Add check for Modified after patch; Update checks for scale --- test/e2e/apps/deployment.go | 25 ++++++++++++++++++++----- 1 file changed, 20 insertions(+), 5 deletions(-) diff --git a/test/e2e/apps/deployment.go b/test/e2e/apps/deployment.go index 0e3d5b94740..15e9e16894e 100644 --- a/test/e2e/apps/deployment.go +++ b/test/e2e/apps/deployment.go @@ -245,6 +245,22 @@ var _ = SIGDescribe("Deployment", func() { framework.ExpectNoError(err, "failed to Marshal Deployment JSON patch") _, err = f.ClientSet.AppsV1().Deployments(testNamespaceName).Patch(context.TODO(), testDeploymentName, types.StrategicMergePatchType, []byte(deploymentPatch), metav1.PatchOptions{}) framework.ExpectNoError(err, "failed to patch Deployment") + ctx, cancel = context.WithTimeout(context.Background(), 30*time.Second) + defer cancel() + _, err = watchtools.Until(ctx, deploymentsList.ResourceVersion, w, func(event watch.Event) (bool, error) { + switch event.Type { + case watch.Modified: + if deployment, ok := event.Object.(*appsv1.Deployment); ok { + found := deployment.ObjectMeta.Name == testDeployment.Name && + deployment.Labels["test-deployment-static"] == "true" + return found, nil + } + default: + framework.Logf("observed event type %v", event.Type) + } + return false, nil + }) + framework.ExpectNoError(err, "failed to see %v event", watch.Modified) ginkgo.By("waiting for Replicas to scale") ctx, cancel = context.WithTimeout(context.Background(), 30*time.Second) @@ -254,7 +270,8 @@ var _ = SIGDescribe("Deployment", func() { found := deployment.ObjectMeta.Name == testDeployment.Name && deployment.Labels["test-deployment-static"] == "true" && deployment.Status.AvailableReplicas == testDeploymentMinimumReplicas && - deployment.Status.ReadyReplicas == testDeploymentMinimumReplicas + deployment.Status.ReadyReplicas == testDeploymentMinimumReplicas && + deployment.Spec.Template.Spec.Containers[0].Image == testDeploymentPatchImage return found, nil } return false, nil @@ -268,16 +285,14 @@ var _ = SIGDescribe("Deployment", func() { for _, deploymentItem := range deploymentsList.Items { if deploymentItem.ObjectMeta.Name == testDeploymentName && deploymentItem.ObjectMeta.Namespace == testNamespaceName && - deploymentItem.ObjectMeta.Labels["test-deployment-static"] == "true" && - *deploymentItem.Spec.Replicas == testDeploymentMinimumReplicas && - deploymentItem.Spec.Template.Spec.Containers[0].Image == testDeploymentPatchImage { + deploymentItem.ObjectMeta.Labels["test-deployment-static"] == "true" { foundDeployment = true break } } framework.ExpectEqual(foundDeployment, true, "unable to find the Deployment in list", deploymentsList) - ginkgo.By("updating the DeploymentStatus") + ginkgo.By("updating the Deployment") testDeploymentUpdate := testDeployment testDeploymentUpdate.ObjectMeta.Labels["test-deployment"] = "updated" testDeploymentUpdate.Spec.Template.Spec.Containers[0].Image = testDeploymentUpdateImage From 84de375921d180fe4656a30bc53b18218d77be66 Mon Sep 17 00:00:00 2001 From: Caleb Woodbine Date: Wed, 22 Jul 2020 11:17:37 +1200 Subject: [PATCH 8/9] Fix error message --- test/e2e/apps/deployment.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/e2e/apps/deployment.go b/test/e2e/apps/deployment.go index 15e9e16894e..819910c1677 100644 --- a/test/e2e/apps/deployment.go +++ b/test/e2e/apps/deployment.go @@ -164,7 +164,7 @@ var _ = SIGDescribe("Deployment", func() { }, } deploymentsList, err := f.ClientSet.AppsV1().Deployments("").List(context.TODO(), metav1.ListOptions{LabelSelector: testDeploymentLabelsFlat}) - framework.ExpectNoError(err, "failed to list Endpoints") + framework.ExpectNoError(err, "failed to list Deployments") ginkgo.By("creating a Deployment") testDeployment := appsv1.Deployment{ From ee29022ac8a28fef9839a70e0be3c0f2b082364f Mon Sep 17 00:00:00 2001 From: Caleb Woodbine Date: Thu, 23 Jul 2020 14:07:01 +1200 Subject: [PATCH 9/9] Update test images to use conformance images --- test/e2e/apps/deployment.go | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/test/e2e/apps/deployment.go b/test/e2e/apps/deployment.go index 819910c1677..2608fab2fb2 100644 --- a/test/e2e/apps/deployment.go +++ b/test/e2e/apps/deployment.go @@ -55,6 +55,7 @@ import ( e2eservice "k8s.io/kubernetes/test/e2e/framework/service" e2eskipper "k8s.io/kubernetes/test/e2e/framework/skipper" testutil "k8s.io/kubernetes/test/utils" + imageutils "k8s.io/kubernetes/test/utils/image" utilpointer "k8s.io/utils/pointer" ) @@ -146,9 +147,9 @@ var _ = SIGDescribe("Deployment", func() { deploymentResource := schema.GroupVersionResource{Group: "apps", Version: "v1", Resource: "deployments"} testNamespaceName := f.Namespace.Name testDeploymentName := "test-deployment" - testDeploymentInitialImage := "nginx" - testDeploymentPatchImage := "alpine" - testDeploymentUpdateImage := "httpd" + testDeploymentInitialImage := imageutils.GetE2EImage(imageutils.Agnhost) + testDeploymentPatchImage := imageutils.GetE2EImage(imageutils.Pause) + testDeploymentUpdateImage := imageutils.GetE2EImage(imageutils.Httpd) testDeploymentDefaultReplicas := int32(3) testDeploymentMinimumReplicas := int32(1) testDeploymentNoReplicas := int32(0)