Change:
[x] Original approval issue: [x] Two weeks soak end date: This issue is created to allow edit by /wip /hold This issue proposes the writing of a new test for the API endponts , , , with the intention of promoting it to Conformance. This issue contains a very basic mock test in order to start the conversation about what a good e2e test would look like for this endpoint. The code below is verified to be hitting the intended endpoint, show as per the queries in APIsnoop's live view of the cluster's audit logs. According to this APIsnoop query, there are still some remaining Endpoints endpoints which are untested. a Service in a namespace all Endpoints in all Namespaces find the created Service(1) /update the Namespaced Endpoint for the Service(1) the Namespaced Endpoint for the Service(1) the Namespaced Endpoint for the Service(1) Namespaced Endpoint(1) via a Collection with a LabelSelector Discover useragents: If a test with these calls gets merged, Conformance coverage will go up by 4 points* /sig testing /sig architecture /area conformance
/reopen Wait for Promotion PR to Merge.
Reopened this issue. <detailsIn response to : /reopen Wait for Promotion PR to Merge. Instructions for interacting with me using PR comments are available . If you have questions or suggestions related to my behavior, please file an issue against the repository. </details

Discussion:
"//staging/src/k8s.io/apiserver/pkg/authentication/serviceaccount:go_default_library", "//staging/src/k8s.io/client-go/kubernetes:go_default_library", "//staging/src/k8s.io/client-go/tools/cache:go_default_library", <ins> "//staging/src/k8s.io/client-go/tools/watch:go_default_library", </ins> "//staging/src/k8s.io/client-go/util/flowcontrol:go_default_library", "//staging/src/k8s.io/client-go/util/retry:go_default_library", "//staging/src/k8s.io/client-go/util/workqueue:go_default_library",

compute "google.golang.org/api/compute/v1" <ins> "k8s.io/client-go/tools/cache" </ins> appsv1 "k8s.io/api/apps/v1" v1 "k8s.io/api/core/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"

"k8s.io/apimachinery/pkg/util/intstr" "k8s.io/apimachinery/pkg/util/sets" "k8s.io/apimachinery/pkg/util/wait" <ins> watch "k8s.io/apimachinery/pkg/watch" </ins> clientset "k8s.io/client-go/kubernetes" <ins> watchtools "k8s.io/client-go/tools/watch" </ins> cloudprovider "k8s.io/cloud-provider" "k8s.io/kubernetes/test/e2e/framework" e2edeployment "k8s.io/kubernetes/test/e2e/framework/deployment"

}) ginkgo.It("should test the lifecycle of an Endpoint", func() { <del> ns := f.Namespace.Name </del> <ins> testNamespaceName := f.Namespace.Name </ins> testEndpointName := "testservice" <del> ginkgo.By("creating an Endpoint") _, err := f.ClientSet.CoreV1().Endpoints(ns).Create(context.TODO(), &v1.Endpoints{ </del> <ins> testEndpoints := v1.Endpoints{ </ins> ObjectMeta: metav1.ObjectMeta{ <del> Name:      testEndpointName, Namespace: ns, </del> <ins> Name: testEndpointName, </ins> Labels: map[string]string{ <del> "testendpoint-static": "true", </del> <ins> "test-endpoint-static": "true", </ins> }, }, Subsets: []v1.EndpointSubset{{

Protocol: v1.ProtocolTCP, }}, }}, <del> }, metav1.CreateOptions{}) framework.ExpectNoError(err, "failed to create Endpoint") </del> <ins> } w := &cache.ListWatch{ WatchFunc: func(options metav1.ListOptions) (watch.Interface, error) { options.LabelSelector = "test-endpoint-static=true" return f.ClientSet.CoreV1().Endpoints(testNamespaceName).Watch(context.TODO(), options) }, } endpointsList, err := f.ClientSet.CoreV1().Endpoints("").List(context.TODO(), metav1.ListOptions{LabelSelector: "test-endpoint-static=true"}) framework.ExpectNoError(err, "failed to list Endpoints") </ins> <del> // set up a watch for the Endpoint // this timeout was chosen as there was timeout failure from the CI endpointWatchTimeoutSeconds := int64(180) endpointWatch, err := f.ClientSet.CoreV1().Endpoints(ns).Watch(context.TODO(), metav1.ListOptions{LabelSelector: "testendpoint-static=true", TimeoutSeconds: &endpointWatchTimeoutSeconds}) framework.ExpectNoError(err, "failed to setup watch on newly created Endpoint") endpointWatchChan := endpointWatch.ResultChan() </del> <ins> ginkgo.By("creating an Endpoint") _, err = f.ClientSet.CoreV1().Endpoints(testNamespaceName).Create(context.TODO(), &testEndpoints, metav1.CreateOptions{}) framework.ExpectNoError(err, "failed to create Endpoint") </ins> ginkgo.By("waiting for available Endpoint") <del> for watchEvent := range endpointWatchChan { if watchEvent.Type == "ADDED" { break </del> <ins> ctx, cancel := context.WithTimeout(context.Background(), 30*time.Second) defer cancel() _, err = watchtools.Until(ctx, endpointsList.ResourceVersion, w, func(event watch.Event) (bool, error) { switch event.Type { case watch.Added: if endpoints, ok := event.Object.(*v1.Endpoints); ok { found := endpoints.ObjectMeta.Name == endpoints.Name && endpoints.Labels["test-endpoint-static"] == "true" return found, nil } default: framework.Logf("observed event type %v", event.Type) </ins> } <del> } </del> <ins> return false, nil }) framework.ExpectNoError(err, "failed to see %v event", watch.Added) </ins> ginkgo.By("listing all Endpoints") <del> endpointsList, err := f.ClientSet.CoreV1().Endpoints("").List(context.TODO(), metav1.ListOptions{LabelSelector: "testendpoint-static=true"}) </del> <ins> endpointsList, err = f.ClientSet.CoreV1().Endpoints("").List(context.TODO(), metav1.ListOptions{LabelSelector: "test-endpoint-static=true"}) </ins> framework.ExpectNoError(err, "failed to list Endpoints") <del> foundEndpointService := false </del> <ins> eventFound := false </ins> var foundEndpoint v1.Endpoints for _, endpoint := range endpointsList.Items { <del> if endpoint.ObjectMeta.Name == testEndpointName && endpoint.ObjectMeta.Namespace == ns { foundEndpointService = true </del> <ins> if endpoint.ObjectMeta.Name == testEndpointName && endpoint.ObjectMeta.Namespace == testNamespaceName { eventFound = true </ins> foundEndpoint = endpoint break } } <del> framework.ExpectEqual(foundEndpointService, true, "unable to find Endpoint Service in list of Endpoints") </del> <ins> framework.ExpectEqual(eventFound, true, "unable to find Endpoint Service in list of Endpoints") </ins> ginkgo.By("updating the Endpoint") <del> foundEndpoint.ObjectMeta.Labels["testservice"] = "first-modification" _, err = f.ClientSet.CoreV1().Endpoints(ns).Update(context.TODO(), &foundEndpoint, metav1.UpdateOptions{}) </del> <ins> foundEndpoint.ObjectMeta.Labels["test-service"] = "updated" _, err = f.ClientSet.CoreV1().Endpoints(testNamespaceName).Update(context.TODO(), &foundEndpoint, metav1.UpdateOptions{}) </ins> framework.ExpectNoError(err, "failed to update Endpoint with new label") <ins> ctx, cancel = context.WithTimeout(context.Background(), 30*time.Second) defer cancel() _, err = watchtools.Until(ctx, endpointsList.ResourceVersion, w, func(event watch.Event) (bool, error) { switch event.Type { case watch.Modified: if endpoints, ok := event.Object.(*v1.Endpoints); ok { found := endpoints.ObjectMeta.Name == endpoints.Name && endpoints.Labels["test-endpoint-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) </ins> ginkgo.By("fetching the Endpoint") <del> _, err = f.ClientSet.CoreV1().Endpoints(ns).Get(context.TODO(), testEndpointName, metav1.GetOptions{}) </del> <ins> endpoints, err := f.ClientSet.CoreV1().Endpoints(testNamespaceName).Get(context.TODO(), testEndpointName, metav1.GetOptions{}) </ins> framework.ExpectNoError(err, "failed to fetch Endpoint") <del> framework.ExpectEqual(foundEndpoint.ObjectMeta.Labels["testservice"], "first-modification", "label not patched") </del> <ins> framework.ExpectEqual(foundEndpoint.ObjectMeta.Labels["test-service"], "updated", "failed to update Endpoint %v in namespace %v label not updated", testEndpointName, testNamespaceName) </ins> endpointPatch, err := json.Marshal(map[string]interface{}{ "metadata": map[string]interface{}{ "labels": map[string]string{ <del> "testservice": "second-modification", </del> <ins> "test-service": "patched", </ins> }, }, "subsets": []map[string]interface{}{

}) framework.ExpectNoError(err, "failed to marshal JSON for WatchEvent patch") ginkgo.By("patching the Endpoint") <del> _, err = f.ClientSet.CoreV1().Endpoints(ns).Patch(context.TODO(), testEndpointName, types.StrategicMergePatchType, []byte(endpointPatch), metav1.PatchOptions{}) </del> <ins> _, err = f.ClientSet.CoreV1().Endpoints(testNamespaceName).Patch(context.TODO(), testEndpointName, types.StrategicMergePatchType, []byte(endpointPatch), metav1.PatchOptions{}) </ins> framework.ExpectNoError(err, "failed to patch Endpoint") <ins> ctx, cancel = context.WithTimeout(context.Background(), 30*time.Second) defer cancel() _, err = watchtools.Until(ctx, endpoints.ResourceVersion, w, func(event watch.Event) (bool, error) { switch event.Type { case watch.Modified: if endpoints, ok := event.Object.(*v1.Endpoints); ok { found := endpoints.ObjectMeta.Name == endpoints.Name && endpoints.Labels["test-endpoint-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) </ins> ginkgo.By("fetching the Endpoint") <del> endpoint, err := f.ClientSet.CoreV1().Endpoints(ns).Get(context.TODO(), testEndpointName, metav1.GetOptions{}) </del> <ins> endpoints, err = f.ClientSet.CoreV1().Endpoints(testNamespaceName).Get(context.TODO(), testEndpointName, metav1.GetOptions{}) </ins> framework.ExpectNoError(err, "failed to fetch Endpoint") <del> framework.ExpectEqual(endpoint.ObjectMeta.Labels["testservice"], "second-modification", "failed to patch Endpoint with Label") endpointSubsetOne := endpoint.Subsets[0] </del> <ins> framework.ExpectEqual(endpoints.ObjectMeta.Labels["test-service"], "patched", "failed to patch Endpoint with Label") endpointSubsetOne := endpoints.Subsets[0] </ins> endpointSubsetOneAddresses := endpointSubsetOne.Addresses[0] endpointSubsetOnePorts := endpointSubsetOne.Ports[0] framework.ExpectEqual(endpointSubsetOneAddresses.IP, "10.0.0.25", "failed to patch Endpoint")

framework.ExpectEqual(endpointSubsetOnePorts.Port, int32(8080), "failed to patch Endpoint") ginkgo.By("deleting the Endpoint by Collection") <del> err = f.ClientSet.CoreV1().Endpoints(ns).DeleteCollection(context.TODO(), metav1.DeleteOptions{}, metav1.ListOptions{LabelSelector: "testendpoint-static=true"}) </del> <ins> err = f.ClientSet.CoreV1().Endpoints(testNamespaceName).DeleteCollection(context.TODO(), metav1.DeleteOptions{}, metav1.ListOptions{LabelSelector: "test-endpoint-static=true"}) </ins> framework.ExpectNoError(err, "failed to delete Endpoint by Collection") ginkgo.By("waiting for Endpoint deletion") <del> for watchEvent := range endpointWatchChan { if watchEvent.Type == "DELETED" { break </del> <ins> ctx, cancel = context.WithTimeout(context.Background(), 30*time.Second) defer cancel() _, err = watchtools.Until(ctx, endpoints.ResourceVersion, w, func(event watch.Event) (bool, error) { switch event.Type { case watch.Deleted: if endpoints, ok := event.Object.(*v1.Endpoints); ok { found := endpoints.ObjectMeta.Name == endpoints.Name && endpoints.Labels["test-endpoint-static"] == "true" return found, nil } default: framework.Logf("observed event type %v", event.Type) </ins> } <del> } </del> <ins> return false, nil }) framework.ExpectNoError(err, "failed to see %v event", watch.Deleted) ginkgo.By("fetching the Endpoint") _, err = f.ClientSet.CoreV1().Endpoints(testNamespaceName).Get(context.TODO(), testEndpointName, metav1.GetOptions{}) framework.ExpectError(err, "should not be able to fetch Endpoint") </ins> }) })