Skip to content

Commit

Permalink
Merge pull request #110237 from ii/create-apiservice-lifecycle-test
Browse files Browse the repository at this point in the history
Write APIService lifecycle test + 4 Endpoints
  • Loading branch information
k8s-ci-robot committed Jul 7, 2022
2 parents f74aa47 + e35ea85 commit 2a017f9
Showing 1 changed file with 160 additions and 0 deletions.
160 changes: 160 additions & 0 deletions test/e2e/apimachinery/aggregator.go
Expand Up @@ -33,12 +33,15 @@ import (
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"
"k8s.io/apimachinery/pkg/labels"
"k8s.io/apimachinery/pkg/runtime/schema"
"k8s.io/apimachinery/pkg/types"
"k8s.io/apimachinery/pkg/util/intstr"
utilrand "k8s.io/apimachinery/pkg/util/rand"
"k8s.io/apimachinery/pkg/util/wait"
"k8s.io/client-go/discovery"
clientset "k8s.io/client-go/kubernetes"
"k8s.io/client-go/util/retry"
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"
Expand All @@ -55,6 +58,9 @@ import (

const (
aggregatorServicePort = 7443

apiServiceRetryPeriod = 1 * time.Second
apiServiceRetryTimeout = 1 * time.Minute
)

var _ = SIGDescribe("Aggregator", func() {
Expand Down Expand Up @@ -103,6 +109,121 @@ var _ = SIGDescribe("Aggregator", func() {
TestSampleAPIServer(f, aggrclient, imageutils.GetE2EImage(imageutils.APIServer))
})

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)
})
})

func cleanTest(client clientset.Interface, aggrclient *aggregatorclient.Clientset, namespace string) {
Expand Down Expand Up @@ -583,3 +704,42 @@ func generateFlunderName(base string) string {
}
return fmt.Sprintf("%s-%d", base, id)
}

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
}
}

0 comments on commit 2a017f9

Please sign in to comment.