diff --git a/test/e2e/auth/service_accounts.go b/test/e2e/auth/service_accounts.go index 926f63241e9..52200122d12 100644 --- a/test/e2e/auth/service_accounts.go +++ b/test/e2e/auth/service_accounts.go @@ -18,6 +18,7 @@ package auth import ( "context" + "encoding/json" "fmt" "path" "regexp" @@ -29,9 +30,11 @@ import ( rbacv1 "k8s.io/api/rbac/v1" apierrors "k8s.io/apimachinery/pkg/api/errors" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/apimachinery/pkg/types" "k8s.io/apimachinery/pkg/util/sets" "k8s.io/apimachinery/pkg/util/uuid" "k8s.io/apimachinery/pkg/util/wait" + watch "k8s.io/apimachinery/pkg/watch" "k8s.io/kubernetes/plugin/pkg/admission/serviceaccount" "k8s.io/kubernetes/test/e2e/framework" e2ekubectl "k8s.io/kubernetes/test/e2e/framework/kubectl" @@ -621,6 +624,92 @@ var _ = SIGDescribe("ServiceAccounts", func() { framework.ExpectNoError(podErr) framework.Logf("completed pod") }) + + ginkgo.It("should run through the lifecycle of a ServiceAccount", func() { + testNamespaceName := f.Namespace.Name + testServiceAccountName := "testserviceaccount" + testSecretName := "testsecret" + testServiceAccountStaticLabels := map[string]string{"test-serviceaccount-static": "true"} + testServiceAccountStaticLabelsFlat := "test-serviceaccount-static=true" + + ginkgo.By("creating a ServiceAccount") + testServiceAccount := v1.ServiceAccount{ + ObjectMeta: metav1.ObjectMeta{ + Name: testServiceAccountName, + Labels: testServiceAccountStaticLabels, + }, + } + _, err := f.ClientSet.CoreV1().ServiceAccounts(testNamespaceName).Create(context.TODO(), &testServiceAccount, metav1.CreateOptions{}) + framework.ExpectNoError(err, "failed to create a ServiceAccount") + ginkgo.By("creating a Secret") + testSecret := v1.Secret{ + ObjectMeta: metav1.ObjectMeta{ + Name: testSecretName, + }, + Data: map[string][]byte{ + "test-field": []byte("test-value"), + }, + Type: "Opaque", + } + _, err = f.ClientSet.CoreV1().Secrets(testNamespaceName).Create(context.TODO(), &testSecret, metav1.CreateOptions{}) + framework.ExpectNoError(err, "failed to create a Secret") + + fmt.Println("watching for the ServiceAccount to be added") + resourceWatchTimeoutSeconds := int64(180) + resourceWatch, err := f.ClientSet.CoreV1().ServiceAccounts(testNamespaceName).Watch(context.TODO(), metav1.ListOptions{LabelSelector: testServiceAccountStaticLabelsFlat, TimeoutSeconds: &resourceWatchTimeoutSeconds}) + if err != nil { + fmt.Println(err, "failed to setup watch on newly created ServiceAccount") + return + } + + resourceWatchChan := resourceWatch.ResultChan() + for watchEvent := range resourceWatchChan { + if watchEvent.Type == watch.Added { + break + } + } + + defer func() { + ginkgo.By("deleting the ServiceAccount") + err = f.ClientSet.CoreV1().ServiceAccounts(testNamespaceName).DeleteCollection(context.TODO(), metav1.DeleteOptions{}, metav1.ListOptions{}) + framework.ExpectNoError(err, "failed to delete the ServiceAccount by Collection") + for watchEvent := range resourceWatchChan { + if watchEvent.Type == watch.Deleted { + break + } + } + + ginkgo.By("deleting the Secret") + err = f.ClientSet.CoreV1().Secrets(testNamespaceName).Delete(context.TODO(), testSecretName, metav1.DeleteOptions{}) + framework.ExpectNoError(err, "failed to delete the Secret") + }() + + ginkgo.By("patching the ServiceAccount") + testServiceAccountPatchData, err := json.Marshal(map[string]interface{}{ + "secrets": []map[string]interface{}{{ + "name": testSecretName, + }}, + }) + framework.ExpectNoError(err, "failed to marshal JSON patch for the ServiceAccount") + _, err = f.ClientSet.CoreV1().ServiceAccounts(testNamespaceName).Patch(context.TODO(), testServiceAccountName, types.StrategicMergePatchType, []byte(testServiceAccountPatchData), metav1.PatchOptions{}) + framework.ExpectNoError(err, "failed to patch the ServiceAccount") + for watchEvent := range resourceWatchChan { + if watchEvent.Type == watch.Modified { + break + } + } + + ginkgo.By("finding ServiceAccount in list of all ServiceAccounts (by LabelSelector)") + serviceAccountList, err := f.ClientSet.CoreV1().ServiceAccounts("").List(context.TODO(), metav1.ListOptions{LabelSelector: testServiceAccountStaticLabelsFlat}) + foundServiceAccount := false + for _, serviceAccountItem := range serviceAccountList.Items { + if serviceAccountItem.ObjectMeta.Name == testServiceAccountName && serviceAccountItem.ObjectMeta.Namespace == testNamespaceName && serviceAccountItem.Secrets[0].Name == testSecretName { + foundServiceAccount = true + break + } + } + framework.ExpectEqual(foundServiceAccount, true, "failed to find the created ServiceAccount") + }) }) var reportLogsParser = regexp.MustCompile("([a-zA-Z0-9-_]*)=([a-zA-Z0-9-_]*)$")