Code change:
_, err = f.ClientSet.CoreV1().Endpoints(testNamespaceName).Get(context.TODO(), testEndpointName, metav1.GetOptions{}) framework.ExpectError(err, "should not be able to fetch Endpoint") }) <ins> ginkgo.It("should complete a service status lifecycle", func() { ns := f.Namespace.Name svcResource := schema.GroupVersionResource{Group: "", Version: "v1", Resource: "services"} svcClient := f.ClientSet.CoreV1().Services(ns) testSvcName := "test-service-" + utilrand.String(5) testSvcLabels := map[string]string{"test-service-static": "true"} testSvcLabelsFlat := "test-service-static=true" w := &cache.ListWatch{ WatchFunc: func(options metav1.ListOptions) (watch.Interface, error) { options.LabelSelector = testSvcLabelsFlat return cs.CoreV1().Services(ns).Watch(context.TODO(), options) }, } svcList, err := cs.CoreV1().Services("").List(context.TODO(), metav1.ListOptions{LabelSelector: testSvcLabelsFlat}) framework.ExpectNoError(err, "failed to list Services") ginkgo.By("creating a Service") testService := v1.Service{ ObjectMeta: metav1.ObjectMeta{ Name:   testSvcName, Labels: testSvcLabels, }, Spec: v1.ServiceSpec{ Type: "ClusterIP", Ports: []v1.ServicePort{{ Name:       "http", Protocol:   v1.ProtocolTCP, Port:       int32(80), TargetPort: intstr.FromInt(80), }}, }, } _, err = cs.CoreV1().Services(ns).Create(context.TODO(), &testService, metav1.CreateOptions{}) framework.ExpectNoError(err, "failed to create Service") ginkgo.By("watching for the Service to be added") ctx, cancel := context.WithTimeout(context.Background(), svcReadyTimeout) defer cancel() _, err = watchtools.Until(ctx, svcList.ResourceVersion, w, func(event watch.Event) (bool, error) { if svc, ok := event.Object.(*v1.Service); ok { found := svc.ObjectMeta.Name == testService.ObjectMeta.Name && svc.ObjectMeta.Namespace == ns && svc.Labels["test-service-static"] == "true" if !found { framework.Logf("observed Service %v in namespace %v with labels: %v & ports %v", svc.ObjectMeta.Name, svc.ObjectMeta.Namespace, svc.Labels, svc.Spec.Ports) return false, nil } framework.Logf("Found Service %v in namespace %v with labels: %v & ports %v", svc.ObjectMeta.Name, svc.ObjectMeta.Namespace, svc.Labels, svc.Spec.Ports) return found, nil } framework.Logf("Observed event: %+v", event.Object) return false, nil }) framework.ExpectNoError(err, "Failed to locate Service %v in namespace %v", testService.ObjectMeta.Name, ns) framework.Logf("Service %s created", testSvcName) ginkgo.By("Getting /status") svcStatusUnstructured, err := f.DynamicClient.Resource(svcResource).Namespace(ns).Get(context.TODO(), testSvcName, metav1.GetOptions{}, "status") framework.ExpectNoError(err, "Failed to fetch ServiceStatus of Service %s in namespace %s", testSvcName, ns) svcStatusBytes, err := json.Marshal(svcStatusUnstructured) framework.ExpectNoError(err, "Failed to marshal unstructured response. %v", err) var svcStatus v1.Service err = json.Unmarshal(svcStatusBytes, &svcStatus) framework.ExpectNoError(err, "Failed to unmarshal JSON bytes to a Service object type") framework.Logf("Service %s has LoadBalancer: %v", testSvcName, svcStatus.Status.LoadBalancer) ginkgo.By("patching the ServiceStatus") lbStatus := v1.LoadBalancerStatus{ Ingress: []v1.LoadBalancerIngress{{IP: "203.0.113.1"}}, } lbStatusJSON, err := json.Marshal(lbStatus) framework.ExpectNoError(err, "Failed to marshal JSON. %v", err) _, err = svcClient.Patch(context.TODO(), testSvcName, types.MergePatchType, []byte(`{"metadata":{"annotations":{"patchedstatus":"true"}},"status":{"loadBalancer":`+string(lbStatusJSON)+`}}`), metav1.PatchOptions{}, "status") framework.ExpectNoError(err, "Could not patch service status", err) ginkgo.By("watching for the Service to be patched") ctx, cancel = context.WithTimeout(context.Background(), svcReadyTimeout) defer cancel() _, err = watchtools.Until(ctx, svcList.ResourceVersion, w, func(event watch.Event) (bool, error) { if svc, ok := event.Object.(*v1.Service); ok { found := svc.ObjectMeta.Name == testService.ObjectMeta.Name && svc.ObjectMeta.Namespace == ns && svc.Annotations["patchedstatus"] == "true" if !found { framework.Logf("observed Service %v in namespace %v with annotations: %v & LoadBalancer: %v", svc.ObjectMeta.Name, svc.ObjectMeta.Namespace, svc.Annotations, svc.Status.LoadBalancer) return false, nil } framework.Logf("Found Service %v in namespace %v with annotations: %v & LoadBalancer: %v", svc.ObjectMeta.Name, svc.ObjectMeta.Namespace, svc.Annotations, svc.Status.LoadBalancer) return found, nil } framework.Logf("Observed event: %+v", event.Object) return false, nil }) framework.ExpectNoError(err, "failed to locate Service %v in namespace %v", testService.ObjectMeta.Name, ns) framework.Logf("Service %s has service status patched", testSvcName) ginkgo.By("updating the ServiceStatus") var statusToUpdate, updatedStatus *v1.Service err = retry.RetryOnConflict(retry.DefaultRetry, func() error { statusToUpdate, err = svcClient.Get(context.TODO(), testSvcName, metav1.GetOptions{}) framework.ExpectNoError(err, "Unable to retrieve service %s", testSvcName) statusToUpdate.Status.Conditions = append(statusToUpdate.Status.Conditions, metav1.Condition{ Type:    "StatusUpdate", Status:  metav1.ConditionTrue, Reason:  "E2E", Message: "Set from e2e test", }) updatedStatus, err = svcClient.UpdateStatus(context.TODO(), statusToUpdate, metav1.UpdateOptions{}) return err }) framework.ExpectNoError(err, "nn Failed to UpdateStatus. %vnn", err) framework.Logf("updatedStatus.Conditions: %#v", updatedStatus.Status.Conditions) ginkgo.By("watching for the Service to be updated") ctx, cancel = context.WithTimeout(context.Background(), svcReadyTimeout) defer cancel() _, err = watchtools.Until(ctx, svcList.ResourceVersion, w, func(event watch.Event) (bool, error) { if svc, ok := event.Object.(*v1.Service); ok { found := svc.ObjectMeta.Name == testService.ObjectMeta.Name && svc.ObjectMeta.Namespace == ns && svc.Annotations["patchedstatus"] == "true" if !found { framework.Logf("Observed Service %v in namespace %v with annotations: %v & Conditions: %v", svc.ObjectMeta.Name, svc.ObjectMeta.Namespace, svc.Annotations, svc.Status.LoadBalancer) return false, nil } for _, cond := range svc.Status.Conditions { if cond.Type == "StatusUpdate" && cond.Reason == "E2E" && cond.Message == "Set from e2e test" { framework.Logf("Found Service %v in namespace %v with annotations: %v & Conditions: %v", svc.ObjectMeta.Name, svc.ObjectMeta.Namespace, svc.Annotations, svc.Status.Conditions) return found, nil } else { framework.Logf("Observed Service %v in namespace %v with annotations: %v & Conditions: %v", svc.ObjectMeta.Name, svc.ObjectMeta.Namespace, svc.Annotations, svc.Status.LoadBalancer) return false, nil } } } framework.Logf("Observed event: %+v", event.Object) return false, nil }) framework.ExpectNoError(err, "failed to locate Service %v in namespace %v", testService.ObjectMeta.Name, ns) framework.Logf("Service %s has service status updated", testSvcName) ginkgo.By("patching the service") servicePatchPayload, err := json.Marshal(v1.Service{ ObjectMeta: metav1.ObjectMeta{ Labels: map[string]string{ "test-service": "patched", }, }, }) _, err = svcClient.Patch(context.TODO(), testSvcName, types.StrategicMergePatchType, []byte(servicePatchPayload), metav1.PatchOptions{}) framework.ExpectNoError(err, "failed to patch service. %v", err) ginkgo.By("watching for the Service to be patched") ctx, cancel = context.WithTimeout(context.Background(), svcReadyTimeout) defer cancel() _, err = watchtools.Until(ctx, svcList.ResourceVersion, w, func(event watch.Event) (bool, error) { if svc, ok := event.Object.(*v1.Service); ok { found := svc.ObjectMeta.Name == testService.ObjectMeta.Name && svc.ObjectMeta.Namespace == ns && svc.Labels["test-service"] == "patched" if !found { framework.Logf("observed Service %v in namespace %v with labels: %v", svc.ObjectMeta.Name, svc.ObjectMeta.Namespace, svc.Labels) return false, nil } framework.Logf("Found Service %v in namespace %v with labels: %v", svc.ObjectMeta.Name, svc.ObjectMeta.Namespace, svc.Labels) return found, nil } framework.Logf("Observed event: %+v", event.Object) return false, nil }) framework.ExpectNoError(err, "failed to locate Service %v in namespace %v", testService.ObjectMeta.Name, ns) framework.Logf("Service %s patched", testSvcName) ginkgo.By("deleting the service") err = cs.CoreV1().Services(ns).Delete(context.TODO(), testSvcName, metav1.DeleteOptions{}) framework.ExpectNoError(err, "failed to delete the Service. %v", err) ginkgo.By("watching for the Service to be deleted") ctx, cancel = context.WithTimeout(context.Background(), svcReadyTimeout) defer cancel() _, err = watchtools.Until(ctx, svcList.ResourceVersion, w, func(event watch.Event) (bool, error) { switch event.Type { case watch.Deleted: if svc, ok := event.Object.(*v1.Service); ok { found := svc.ObjectMeta.Name == testService.ObjectMeta.Name && svc.ObjectMeta.Namespace == ns && svc.Labels["test-service-static"] == "true" if !found { framework.Logf("observed Service %v in namespace %v with labels: %v & annotations: %v", svc.ObjectMeta.Name, svc.ObjectMeta.Namespace, svc.Labels, svc.Annotations) return false, nil } framework.Logf("Found Service %v in namespace %v with labels: %v & annotations: %v", svc.ObjectMeta.Name, svc.ObjectMeta.Namespace, svc.Labels, svc.Annotations) return found, nil } default: framework.Logf("Observed event: %+v", event.Type) } return false, nil }) framework.ExpectNoError(err, "failed to delete Service %v in namespace %v", testService.ObjectMeta.Name, ns) framework.Logf("Service %s deleted", testSvcName) }) </ins> }) // execAffinityTestForSessionAffinityTimeout is a helper function that wrap the logic of

Related discussion:
text: Using the following code before the patch request Gives this response Then after running the patch ServiceStatus Then running The response shows the patched changes.
During the Conformance Meeting on 12th of January 2021, reviewed approach with Clayton, and we will start on the test PR this week!
/reopen
Reopened this issue. <detailsIn response to : /reopen </details
/triage accepted