Change:
[X] Test approval issue: [X] Test PR: 7 July 2022 [x] Two weeks soak end date: 21 Jul 2022 [x] Test promotion According to this APIsnoop query, there are still some remaining APIService endpoints which are untested. replaceApiregistrationV1APIServiceStatuspatchApiregistrationV1APIServiceStatusreplaceApiregistrationV1APIServicedeleteApiregistrationV1CollectionAPIService Using a number of existing e2e test practices a new has been created for 4 APIService endpoints. The e2e logs for this test are listed below. This query shows the following endpoints are hit within a short period of running this e2e test If a test with these calls gets merged, test coverage will go up by 4 points This test is also created with the goal of conformance promotion. /sig testing /sig architecture /area conformance
/triage accepted
/reopen
Reopened this issue. <detailsIn response to : /reopen 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:
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/apis/meta/v1/unstructured" unstructuredv1 "k8s.io/apimachinery/pkg/apis/meta/v1/unstructured" <ins> "k8s.io/apimachinery/pkg/labels" </ins> "k8s.io/apimachinery/pkg/runtime/schema" "k8s.io/apimachinery/pkg/types" "k8s.io/apimachinery/pkg/util/intstr" <ins> utilrand "k8s.io/apimachinery/pkg/util/rand" </ins> "k8s.io/apimachinery/pkg/util/wait" "k8s.io/client-go/discovery" clientset "k8s.io/client-go/kubernetes" <ins> "k8s.io/client-go/util/retry" </ins> apiregistrationv1 "k8s.io/kube-aggregator/pkg/apis/apiregistration/v1" aggregatorclient "k8s.io/kube-aggregator/pkg/client/clientset_generated/clientset" rbacv1helpers "k8s.io/kubernetes/pkg/apis/rbac/v1"

const ( aggregatorServicePort = 7443 <ins> apiServiceRetryPeriod  = 1 * time.Second apiServiceRetryTimeout = 1 * time.Minute </ins> ) var _ = SIGDescribe("Aggregator", func() {

TestSampleAPIServer(f, aggrclient, imageutils.GetE2EImage(imageutils.APIServer)) }) <ins> ginkgo.It("should manage the lifecycle of an APIService", func() { ns := f.Namespace.Name framework.Logf("ns: %v", ns) subDomain := "e2e-" + utilrand.String(5) apiServiceGroup := subDomain + ".example.com" label := map[string]string{"e2e": subDomain} labelSelector := labels.SelectorFromSet(label).String() apiServiceName := "v1alpha1." + apiServiceGroup apiServiceClient := aggrclient.ApiregistrationV1().APIServices() certCtx := setupServerCert(ns, "e2e-api") ginkgo.By(fmt.Sprintf("Create APIService %s", apiServiceName)) _, err := apiServiceClient.Create(context.TODO(), &apiregistrationv1.APIService{ ObjectMeta: metav1.ObjectMeta{ Name:   apiServiceName, Labels: label, }, Spec: apiregistrationv1.APIServiceSpec{ Service: &apiregistrationv1.ServiceReference{ Namespace: ns, Name:      "e2e-api", Port:      pointer.Int32Ptr(aggregatorServicePort), }, Group:                apiServiceGroup, Version:              "v1alpha1", CABundle:             certCtx.signingCert, GroupPriorityMinimum: 2000, VersionPriority:      200, }, }, metav1.CreateOptions{}) framework.ExpectNoError(err, "creating apiService %s, namespace %s", apiServiceName, ns) _, err = apiServiceClient.List(context.TODO(), metav1.ListOptions{LabelSelector: labelSelector}) framework.ExpectNoError(err, "failed to list API Services") ginkgo.By("Confirm that the generated APIService has been created") err = wait.PollImmediate(apiServiceRetryPeriod, apiServiceRetryTimeout, checkApiServiceListQuantity(aggrclient, labelSelector, 1)) framework.ExpectNoError(err, "failed to count the required APIServices") ginkgo.By(fmt.Sprintf("Update status for APIService %s", apiServiceName)) var statusToUpdate, updatedStatus *apiregistrationv1.APIService updatedStatusConditions := apiregistrationv1.APIServiceCondition{ Type:    "StatusUpdate", Status:  "True", Reason:  "E2E", Message: "Set from e2e test", } err = retry.RetryOnConflict(retry.DefaultRetry, func() error { statusToUpdate, err = apiServiceClient.Get(context.TODO(), apiServiceName, metav1.GetOptions{}) framework.ExpectNoError(err, "Unable to retrieve api service %s", apiServiceName) statusToUpdate.Status.Conditions = append(statusToUpdate.Status.Conditions, updatedStatusConditions) updatedStatus, err = apiServiceClient.UpdateStatus(context.TODO(), statusToUpdate, metav1.UpdateOptions{}) return err }) framework.ExpectNoError(err, "Failed to update status. %v", err) framework.Logf("updatedStatus.Conditions: %#v", updatedStatus.Status.Conditions) ginkgo.By("Confirm that the generated APIService has an updated status") err = wait.PollImmediate(apiServiceRetryPeriod, apiServiceRetryTimeout, checkApiServiceStatus(aggrclient, apiServiceName, updatedStatusConditions)) framework.ExpectNoError(err, "failed to locate the required APIService status") ginkgo.By(fmt.Sprintf("Patching status for APIService %s", apiServiceName)) patchedStatusConditions := apiregistrationv1.APIServiceCondition{ Type:    "StatusPatched", Status:  "True", Reason:  "E2E", Message: "Set from e2e test", } payload := []byte(`{"status":{"conditions":[{"type":"StatusPatched","status":"True","reason":"E2E","message":"Set from e2e test"}]}}`) patchedApiService, err := apiServiceClient.Patch(context.TODO(), apiServiceName, types.MergePatchType, payload, metav1.PatchOptions{}, "status") framework.ExpectNoError(err, "Failed to patch status. %v", err) framework.Logf("Patched status conditions: %#v", patchedApiService.Status.Conditions) ginkgo.By("Confirm that the generated APIService has a patched status") err = wait.PollImmediate(apiServiceRetryPeriod, apiServiceRetryTimeout, checkApiServiceStatus(aggrclient, apiServiceName, patchedStatusConditions)) framework.ExpectNoError(err, "failed to locate the required APIService status") ginkgo.By(fmt.Sprintf("Replace APIService %s", apiServiceName)) var updatedApiService *apiregistrationv1.APIService err = retry.RetryOnConflict(retry.DefaultRetry, func() error { patchedApiService, err = apiServiceClient.Get(context.TODO(), apiServiceName, metav1.GetOptions{}) framework.ExpectNoError(err, "Unable to get APIService %s", apiServiceName) patchedApiService.Labels = map[string]string{ apiServiceGroup: "updated", } updatedApiService, err = apiServiceClient.Update(context.TODO(), patchedApiService, metav1.UpdateOptions{}) return err }) framework.ExpectNoError(err) framework.ExpectEqual(updatedApiService.Labels[apiServiceGroup], "updated", "updated object should have the applied label") framework.Logf("Found updated apiService label for %q", apiServiceName) ginkgo.By(fmt.Sprintf("DeleteCollection APIService %s via labelSelector: %s", apiServiceName, labelSelector)) err = aggrclient.ApiregistrationV1().APIServices().DeleteCollection(context.TODO(), metav1.DeleteOptions{GracePeriodSeconds: pointer.Int64(1)}, metav1.ListOptions{LabelSelector: labelSelector}) framework.ExpectNoError(err, "Unable to delete apiservice %s", apiServiceName) ginkgo.By("Confirm that the generated APIService has been deleted") err = wait.PollImmediate(apiServiceRetryPeriod, apiServiceRetryTimeout, checkApiServiceListQuantity(aggrclient, labelSelector, 0)) framework.ExpectNoError(err, "failed to count the required APIServices") framework.Logf("APIService %s has been deleted.", apiServiceName) }) </ins> }) func cleanTest(client clientset.Interface, aggrclient *aggregatorclient.Clientset, namespace string) {

} return fmt.Sprintf("%s-%d", base, id) } <ins> func checkApiServiceListQuantity(aggrclient *aggregatorclient.Clientset, label string, quantity int) func() (bool, error) { return func() (bool, error) { var err error framework.Logf("Requesting list of APIServices to confirm quantity") list, err := aggrclient.ApiregistrationV1().APIServices().List(context.TODO(), metav1.ListOptions{LabelSelector: label}) if err != nil { return false, err } if len(list.Items) != quantity { return false, err } framework.Logf("Found %d APIService with label %q", quantity, label) return true, nil } } func checkApiServiceStatus(aggrclient *aggregatorclient.Clientset, apiServiceName string, statusConditions apiregistrationv1.APIServiceCondition) func() (bool, error) { return func() (bool, error) { framework.Logf("Get APIService %q to confirm status", apiServiceName) currentApiService, err := aggrclient.ApiregistrationV1().APIServices().Get(context.TODO(), apiServiceName, metav1.GetOptions{}) if err != nil { return false, err } for _, cond := range currentApiService.Status.Conditions { if cond.Type == statusConditions.Type && cond.Reason == statusConditions.Reason && cond.Message == statusConditions.Message { framework.Logf("APIService %q has the required status conditions", apiServiceName) return true, nil } } return false, err } } </ins>