From e528512d38d961c8d304585b1a155d2ab986123f Mon Sep 17 00:00:00 2001 From: Daniel Helfand Date: Tue, 24 May 2022 10:15:44 -0500 Subject: [PATCH 1/2] fix: create serviceaccount token for v1.24 clusters Signed-off-by: Daniel Helfand --- cmd/argocd/commands/admin/cluster.go | 2 +- cmd/argocd/commands/cluster.go | 4 +- common/common.go | 6 ++ go.mod | 2 +- test/e2e/cluster_test.go | 2 - test/e2e/fixture/cluster/actions.go | 3 +- util/clusterauth/clusterauth.go | 138 +++++++++++++++++++++------ util/clusterauth/clusterauth_test.go | 122 +++++++++++++++++++++-- 8 files changed, 236 insertions(+), 43 deletions(-) diff --git a/cmd/argocd/commands/admin/cluster.go b/cmd/argocd/commands/admin/cluster.go index 69b5988f167d9..1ecdb62eb8721 100644 --- a/cmd/argocd/commands/admin/cluster.go +++ b/cmd/argocd/commands/admin/cluster.go @@ -609,7 +609,7 @@ func GenerateToken(clusterOpts cmdutil.ClusterOptions, conf *rest.Config) (strin clientset, err := kubernetes.NewForConfig(conf) errors.CheckError(err) - bearerToken, err := clusterauth.GetServiceAccountBearerToken(clientset, clusterOpts.SystemNamespace, clusterOpts.ServiceAccount) + bearerToken, err := clusterauth.GetServiceAccountBearerToken(clientset, clusterOpts.SystemNamespace, clusterOpts.ServiceAccount, common.BearerTokenTimeout) if err != nil { return "", err } diff --git a/cmd/argocd/commands/cluster.go b/cmd/argocd/commands/cluster.go index 8d8177632a17b..ff0a3c6678e37 100644 --- a/cmd/argocd/commands/cluster.go +++ b/cmd/argocd/commands/cluster.go @@ -101,7 +101,7 @@ func NewClusterAddCommand(clientOpts *argocdclient.ClientOptions, pathOpts *clie clientset, err := kubernetes.NewForConfig(conf) errors.CheckError(err) if clusterOpts.ServiceAccount != "" { - managerBearerToken, err = clusterauth.GetServiceAccountBearerToken(clientset, clusterOpts.SystemNamespace, clusterOpts.ServiceAccount) + managerBearerToken, err = clusterauth.GetServiceAccountBearerToken(clientset, clusterOpts.SystemNamespace, clusterOpts.ServiceAccount, common.BearerTokenTimeout) } else { isTerminal := isatty.IsTerminal(os.Stdout.Fd()) || isatty.IsCygwinTerminal(os.Stdout.Fd()) @@ -115,7 +115,7 @@ func NewClusterAddCommand(clientOpts *argocdclient.ClientOptions, pathOpts *clie os.Exit(1) } } - managerBearerToken, err = clusterauth.InstallClusterManagerRBAC(clientset, clusterOpts.SystemNamespace, clusterOpts.Namespaces) + managerBearerToken, err = clusterauth.InstallClusterManagerRBAC(clientset, clusterOpts.SystemNamespace, clusterOpts.Namespaces, common.BearerTokenTimeout) } errors.CheckError(err) } diff --git a/common/common.go b/common/common.go index ae23f9d86fc96..4d92f1fb7193a 100644 --- a/common/common.go +++ b/common/common.go @@ -229,6 +229,12 @@ const ( CacheVersion = "1.8.3" ) +// Constants used by util/clusterauth package +const ( + ClusterAuthRequestTimeout = 10 * time.Second + BearerTokenTimeout = 30 * time.Second +) + const ( DefaultGitRetryMaxDuration time.Duration = time.Second * 5 // 5s DefaultGitRetryDuration time.Duration = time.Millisecond * 250 // 0.25s diff --git a/go.mod b/go.mod index d277ef6e31085..bb621c796df3f 100644 --- a/go.mod +++ b/go.mod @@ -217,7 +217,7 @@ require ( gopkg.in/square/go-jose.v2 v2.2.2 // indirect gopkg.in/warnings.v0 v0.1.2 // indirect gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b // indirect - k8s.io/apiserver v0.23.1 // indirect + k8s.io/apiserver v0.23.1 k8s.io/cli-runtime v0.23.1 // indirect k8s.io/component-base v0.23.1 // indirect k8s.io/component-helpers v0.23.1 // indirect diff --git a/test/e2e/cluster_test.go b/test/e2e/cluster_test.go index 00c089dedcf3b..b29e069a648ab 100644 --- a/test/e2e/cluster_test.go +++ b/test/e2e/cluster_test.go @@ -184,8 +184,6 @@ func TestClusterURLInRestAPI(t *testing.T) { } func TestClusterDeleteDenied(t *testing.T) { - EnsureCleanState(t) - accountFixture.Given(t). Name("test"). When(). diff --git a/test/e2e/fixture/cluster/actions.go b/test/e2e/fixture/cluster/actions.go index ef5980e2ebc72..c55e82fba091c 100644 --- a/test/e2e/fixture/cluster/actions.go +++ b/test/e2e/fixture/cluster/actions.go @@ -6,6 +6,7 @@ import ( "fmt" "log" + "github.com/argoproj/argo-cd/v2/common" "github.com/argoproj/argo-cd/v2/pkg/apis/application/v1alpha1" "github.com/argoproj/argo-cd/v2/util/clusterauth" "k8s.io/client-go/kubernetes" @@ -81,7 +82,7 @@ func (a *Actions) CreateWithRBAC(args ...string) *Actions { } client := kubernetes.NewForConfigOrDie(conf) - _, err = clusterauth.InstallClusterManagerRBAC(client, "kube-system", []string{}) + _, err = clusterauth.InstallClusterManagerRBAC(client, "kube-system", []string{}, common.BearerTokenTimeout) if err != nil { a.lastError = err return a diff --git a/util/clusterauth/clusterauth.go b/util/clusterauth/clusterauth.go index 48efe8b17b720..ea93d72f05a19 100644 --- a/util/clusterauth/clusterauth.go +++ b/util/clusterauth/clusterauth.go @@ -2,16 +2,19 @@ package clusterauth import ( "context" + "encoding/json" "fmt" "strings" "time" + "github.com/argoproj/argo-cd/v2/common" jwt "github.com/golang-jwt/jwt/v4" log "github.com/sirupsen/logrus" corev1 "k8s.io/api/core/v1" rbacv1 "k8s.io/api/rbac/v1" apierr "k8s.io/apimachinery/pkg/api/errors" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/apimachinery/pkg/types" "k8s.io/apimachinery/pkg/util/wait" "k8s.io/client-go/kubernetes" ) @@ -173,7 +176,7 @@ func upsertRoleBinding(clientset kubernetes.Interface, name string, roleName str } // InstallClusterManagerRBAC installs RBAC resources for a cluster manager to operate a cluster. Returns a token -func InstallClusterManagerRBAC(clientset kubernetes.Interface, ns string, namespaces []string) (string, error) { +func InstallClusterManagerRBAC(clientset kubernetes.Interface, ns string, namespaces []string, bearerTokenTimeout time.Duration) (string, error) { err := CreateServiceAccount(clientset, ArgoCDManagerServiceAccount, ns) if err != nil { @@ -212,42 +215,123 @@ func InstallClusterManagerRBAC(clientset kubernetes.Interface, ns string, namesp } } - return GetServiceAccountBearerToken(clientset, ns, ArgoCDManagerServiceAccount) + return GetServiceAccountBearerToken(clientset, ns, ArgoCDManagerServiceAccount, bearerTokenTimeout) } -// GetServiceAccountBearerToken will attempt to get the provided service account until it -// exists, iterate the secrets associated with it looking for one of type -// kubernetes.io/service-account-token, and return it's token if found. -func GetServiceAccountBearerToken(clientset kubernetes.Interface, ns string, sa string) (string, error) { - var serviceAccount *corev1.ServiceAccount +// GetServiceAccountBearerToken determines if a ServiceAccount has a +// bearer token secret to use or if a secret should be created. It then +// waits for the secret to have a bearer token if a secret needs to +// be created and returns the token in encoded base64. +func GetServiceAccountBearerToken(clientset kubernetes.Interface, ns string, sa string, timeout time.Duration) (string, error) { + secretName, err := getOrCreateServiceAccountTokenSecret(clientset, sa, ns) + if err != nil { + return "", err + } + var secret *corev1.Secret - var err error - err = wait.Poll(500*time.Millisecond, 30*time.Second, func() (bool, error) { - serviceAccount, err = clientset.CoreV1().ServiceAccounts(ns).Get(context.Background(), sa, metav1.GetOptions{}) + err = wait.PollImmediate(500*time.Millisecond, timeout, func() (bool, error) { + ctx, cancel := context.WithTimeout(context.Background(), common.ClusterAuthRequestTimeout) + defer cancel() + secret, err = clientset.CoreV1().Secrets(ns).Get(ctx, secretName, metav1.GetOptions{}) if err != nil { - return false, err + return false, fmt.Errorf("failed to get secret %q for serviceaccount %q: %w", secretName, sa, err) } - // Scan all secrets looking for one of the correct type: - for _, oRef := range serviceAccount.Secrets { - var getErr error - secret, err = clientset.CoreV1().Secrets(ns).Get(context.Background(), oRef.Name, metav1.GetOptions{}) - if err != nil { - return false, fmt.Errorf("Failed to retrieve secret %q: %v", oRef.Name, getErr) - } - if secret.Type == corev1.SecretTypeServiceAccountToken { - return true, nil - } + + _, ok := secret.Data["token"] + if !ok { + return false, nil } - return false, nil + + return true, nil }) if err != nil { - return "", fmt.Errorf("Failed to wait for service account secret: %v", err) + return "", fmt.Errorf("failed to get token for serviceaccount %q: %w", sa, err) } - token, ok := secret.Data["token"] - if !ok { - return "", fmt.Errorf("Secret %q for service account %q did not have a token", secret.Name, serviceAccount) + + return string(secret.Data["token"]), nil +} + +// getOrCreateServiceAccountTokenSecret will check if a ServiceAccount +// already has a kubernetes.io/service-account-token secret associated +// with it or creates one if the ServiceAccount doesn't have one. This +// was added to help add k8s v1.24+ clusters. +func getOrCreateServiceAccountTokenSecret(clientset kubernetes.Interface, sa, ns string) (string, error) { + // Wait for sa to have secret, but don't wait too + // long for 1.24+ clusters + var serviceAccount *corev1.ServiceAccount + err := wait.PollImmediate(500*time.Millisecond, 5*time.Second, func() (bool, error) { + ctx, cancel := context.WithTimeout(context.Background(), common.ClusterAuthRequestTimeout) + defer cancel() + var getErr error + serviceAccount, getErr = clientset.CoreV1().ServiceAccounts(ns).Get(ctx, sa, metav1.GetOptions{}) + if getErr != nil { + return false, fmt.Errorf("failed to get serviceaccount %q: %w", sa, getErr) + } + if len(serviceAccount.Secrets) == 0 { + return false, nil + } + return true, nil + }) + if err != nil && err != wait.ErrWaitTimeout { + return "", fmt.Errorf("failed to create serviceaccount token secret: %w", err) } - return string(token), nil + if serviceAccount == nil { + log.Errorf("Unexpected nil serviceaccount '%s/%s' with no error returned", ns, sa) + return "", fmt.Errorf("failed to create serviceaccount token secret: nil serviceaccount returned for '%s/%s' with no error", ns, sa) + } + + outerCtx, cancel := context.WithTimeout(context.Background(), 30*time.Second) + defer cancel() + for _, s := range serviceAccount.Secrets { + innerCtx, cancel := context.WithTimeout(outerCtx, common.ClusterAuthRequestTimeout) + defer cancel() + existingSecret, err := clientset.CoreV1().Secrets(ns).Get(innerCtx, s.Name, metav1.GetOptions{}) + if err != nil { + return "", fmt.Errorf("failed to retrieve secret %q: %w", s.Name, err) + } + if existingSecret.Type == corev1.SecretTypeServiceAccountToken { + return existingSecret.Name, nil + } + } + + return createServiceAccountToken(clientset, serviceAccount) +} + +func createServiceAccountToken(clientset kubernetes.Interface, sa *corev1.ServiceAccount) (string, error) { + secret := &corev1.Secret{ + ObjectMeta: metav1.ObjectMeta{ + GenerateName: sa.Name + "-token-", + Namespace: sa.Namespace, + Annotations: map[string]string{ + corev1.ServiceAccountNameKey: sa.Name, + }, + }, + Type: corev1.SecretTypeServiceAccountToken, + } + + ctx, cancel := context.WithTimeout(context.Background(), common.ClusterAuthRequestTimeout) + defer cancel() + secret, err := clientset.CoreV1().Secrets(sa.Namespace).Create(ctx, secret, metav1.CreateOptions{}) + if err != nil { + return "", fmt.Errorf("failed to create secret for serviceaccount %q: %w", sa, err) + } + + log.Infof("Created bearer token secret for ServiceAccount %q", sa) + sa.Secrets = []corev1.ObjectReference{{ + Name: secret.Name, + Namespace: secret.Namespace, + }} + patch, err := json.Marshal(sa) + if err != nil { + return "", fmt.Errorf("failed marshaling patch for serviceaccount %q: %w", sa, err) + } + + _, err = clientset.CoreV1().ServiceAccounts(sa.Namespace).Patch(ctx, sa.Name, types.StrategicMergePatchType, patch, metav1.PatchOptions{}) + if err != nil { + return "", fmt.Errorf("failed to patch serviceaccount %q with bearer token secret: %w", sa, err) + } + + return secret.Name, nil } // UninstallClusterManagerRBAC removes RBAC resources for a cluster manager to operate a cluster diff --git a/util/clusterauth/clusterauth_test.go b/util/clusterauth/clusterauth_test.go index 88c6e9946391e..cb1699c765541 100644 --- a/util/clusterauth/clusterauth_test.go +++ b/util/clusterauth/clusterauth_test.go @@ -4,21 +4,24 @@ import ( "context" "io/ioutil" "testing" + "time" + "github.com/argoproj/argo-cd/v2/util/errors" "github.com/ghodss/yaml" "github.com/stretchr/testify/assert" corev1 "k8s.io/api/core/v1" apierr "k8s.io/apimachinery/pkg/api/errors" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/runtime" + "k8s.io/apimachinery/pkg/runtime/schema" + "k8s.io/apiserver/pkg/storage/names" "k8s.io/client-go/kubernetes/fake" kubetesting "k8s.io/client-go/testing" - - "github.com/argoproj/argo-cd/v2/util/errors" ) const ( - testToken = "eyJhbGciOiJSUzI1NiIsImtpZCI6IiJ9.eyJpc3MiOiJrdWJlcm5ldGVzL3NlcnZpY2VhY2NvdW50Iiwia3ViZXJuZXRlcy5pby9zZXJ2aWNlYWNjb3VudC9uYW1lc3BhY2UiOiJrdWJlLXN5c3RlbSIsImt1YmVybmV0ZXMuaW8vc2VydmljZWFjY291bnQvc2VjcmV0Lm5hbWUiOiJhcmdvY2QtbWFuYWdlci10b2tlbi10ajc5ciIsImt1YmVybmV0ZXMuaW8vc2VydmljZWFjY291bnQvc2VydmljZS1hY2NvdW50Lm5hbWUiOiJhcmdvY2QtbWFuYWdlciIsImt1YmVybmV0ZXMuaW8vc2VydmljZWFjY291bnQvc2VydmljZS1hY2NvdW50LnVpZCI6IjkxZGQzN2NmLThkOTItMTFlOS1hMDkxLWQ2NWYyYWU3ZmE4ZCIsInN1YiI6InN5c3RlbTpzZXJ2aWNlYWNjb3VudDprdWJlLXN5c3RlbTphcmdvY2QtbWFuYWdlciJ9.ytZjt2pDV8-A7DBMR06zQ3wt9cuVEfq262TQw7sdra-KRpDpMPnziMhc8bkwvgW-LGhTWUh5iu1y-1QhEx6mtbCt7vQArlBRxfvM5ys6ClFkplzq5c2TtZ7EzGSD0Up7tdxuG9dvR6TGXYdfFcG779yCdZo2H48sz5OSJfdEriduMEY1iL5suZd3ebOoVi1fGflmqFEkZX6SvxkoArl5mtNP6TvZ1eTcn64xh4ws152hxio42E-eSnl_CET4tpB5vgP5BVlSKW2xB7w2GJxqdETA5LJRI_OilY77dTOp8cMr_Ck3EOeda3zHfh4Okflg8rZFEeAuJYahQNeAILLkcA" + testToken = "eyJhbGciOiJSUzI1NiIsImtpZCI6IiJ9.eyJpc3MiOiJrdWJlcm5ldGVzL3NlcnZpY2VhY2NvdW50Iiwia3ViZXJuZXRlcy5pby9zZXJ2aWNlYWNjb3VudC9uYW1lc3BhY2UiOiJrdWJlLXN5c3RlbSIsImt1YmVybmV0ZXMuaW8vc2VydmljZWFjY291bnQvc2VjcmV0Lm5hbWUiOiJhcmdvY2QtbWFuYWdlci10b2tlbi10ajc5ciIsImt1YmVybmV0ZXMuaW8vc2VydmljZWFjY291bnQvc2VydmljZS1hY2NvdW50Lm5hbWUiOiJhcmdvY2QtbWFuYWdlciIsImt1YmVybmV0ZXMuaW8vc2VydmljZWFjY291bnQvc2VydmljZS1hY2NvdW50LnVpZCI6IjkxZGQzN2NmLThkOTItMTFlOS1hMDkxLWQ2NWYyYWU3ZmE4ZCIsInN1YiI6InN5c3RlbTpzZXJ2aWNlYWNjb3VudDprdWJlLXN5c3RlbTphcmdvY2QtbWFuYWdlciJ9.ytZjt2pDV8-A7DBMR06zQ3wt9cuVEfq262TQw7sdra-KRpDpMPnziMhc8bkwvgW-LGhTWUh5iu1y-1QhEx6mtbCt7vQArlBRxfvM5ys6ClFkplzq5c2TtZ7EzGSD0Up7tdxuG9dvR6TGXYdfFcG779yCdZo2H48sz5OSJfdEriduMEY1iL5suZd3ebOoVi1fGflmqFEkZX6SvxkoArl5mtNP6TvZ1eTcn64xh4ws152hxio42E-eSnl_CET4tpB5vgP5BVlSKW2xB7w2GJxqdETA5LJRI_OilY77dTOp8cMr_Ck3EOeda3zHfh4Okflg8rZFEeAuJYahQNeAILLkcA" + testBearerTokenTimeout = 5 * time.Second ) var ( @@ -132,7 +135,7 @@ func TestInstallClusterManagerRBAC(t *testing.T) { Namespace: "test", }, Secrets: []corev1.ObjectReference{ - corev1.ObjectReference{ + { Kind: secret.GetObjectKind().GroupVersionKind().Kind, APIVersion: secret.APIVersion, Name: secret.GetName(), @@ -145,7 +148,7 @@ func TestInstallClusterManagerRBAC(t *testing.T) { t.Run("Cluster Scope - Success", func(t *testing.T) { cs := fake.NewSimpleClientset(ns, secret, sa) - token, err := InstallClusterManagerRBAC(cs, "test", nil) + token, err := InstallClusterManagerRBAC(cs, "test", nil, testBearerTokenTimeout) assert.NoError(t, err) assert.Equal(t, "foobar", token) }) @@ -154,14 +157,14 @@ func TestInstallClusterManagerRBAC(t *testing.T) { nsecret := secret.DeepCopy() nsecret.Data = make(map[string][]byte) cs := fake.NewSimpleClientset(ns, nsecret, sa) - token, err := InstallClusterManagerRBAC(cs, "test", nil) + token, err := InstallClusterManagerRBAC(cs, "test", nil, testBearerTokenTimeout) assert.Error(t, err) assert.Empty(t, token) }) t.Run("Namespace Scope - Success", func(t *testing.T) { cs := fake.NewSimpleClientset(ns, secret, sa) - token, err := InstallClusterManagerRBAC(cs, "test", []string{"nsa"}) + token, err := InstallClusterManagerRBAC(cs, "test", []string{"nsa"}, testBearerTokenTimeout) assert.NoError(t, err) assert.Equal(t, "foobar", token) }) @@ -170,7 +173,7 @@ func TestInstallClusterManagerRBAC(t *testing.T) { nsecret := secret.DeepCopy() nsecret.Data = make(map[string][]byte) cs := fake.NewSimpleClientset(ns, nsecret, sa) - token, err := InstallClusterManagerRBAC(cs, "test", []string{"nsa"}) + token, err := InstallClusterManagerRBAC(cs, "test", []string{"nsa"}, testBearerTokenTimeout) assert.Error(t, err) assert.Empty(t, token) }) @@ -254,7 +257,108 @@ func TestGetServiceAccountBearerToken(t *testing.T) { } kubeclientset := fake.NewSimpleClientset(sa, dockercfgSecret, tokenSecret) - token, err := GetServiceAccountBearerToken(kubeclientset, "kube-system", sa.Name) + token, err := GetServiceAccountBearerToken(kubeclientset, "kube-system", sa.Name, testBearerTokenTimeout) assert.NoError(t, err) assert.Equal(t, testToken, token) } + +func Test_getOrCreateServiceAccountTokenSecret_NoSecretForSA(t *testing.T) { + ns := &corev1.Namespace{ + ObjectMeta: metav1.ObjectMeta{ + Name: "kube-system", + }, + } + saWithoutSecret := &corev1.ServiceAccount{ + ObjectMeta: metav1.ObjectMeta{ + Name: ArgoCDManagerServiceAccount, + Namespace: ns.Name, + }, + } + cs := fake.NewSimpleClientset(ns, saWithoutSecret) + cs.PrependReactor("create", "secrets", + func(a kubetesting.Action) (handled bool, ret runtime.Object, err error) { + s, ok := a.(kubetesting.CreateAction).GetObject().(*corev1.Secret) + if !ok { + return + } + + if s.Name == "" && s.GenerateName != "" { + s.SetName(names.SimpleNameGenerator.GenerateName(s.GenerateName)) + } + + s.Data = make(map[string][]byte) + s.Data["token"] = []byte("fake-token") + + return + }) + + got, err := getOrCreateServiceAccountTokenSecret(cs, ArgoCDManagerServiceAccount, ns.Name) + assert.NoError(t, err) + assert.Contains(t, got, "argocd-manager-token-") + + obj, err := cs.Tracker().Get(schema.GroupVersionResource{Version: "v1", Resource: "serviceaccounts"}, + ns.Name, ArgoCDManagerServiceAccount) + if err != nil { + t.Errorf("ServiceAccount %s not found but was expected to be found: %s", ArgoCDManagerServiceAccount, err.Error()) + } + + sa := obj.(*corev1.ServiceAccount) + assert.Equal(t, 1, len(sa.Secrets)) +} + +func Test_getOrCreateServiceAccountTokenSecret_SAHasSecret(t *testing.T) { + ns := &corev1.Namespace{ + ObjectMeta: metav1.ObjectMeta{ + Name: "kube-system", + }, + } + + secret := &corev1.Secret{ + ObjectMeta: metav1.ObjectMeta{ + Name: "sa-secret", + Namespace: ns.Name, + }, + Type: corev1.SecretTypeServiceAccountToken, + Data: map[string][]byte{ + "token": []byte("foobar"), + }, + } + + saWithSecret := &corev1.ServiceAccount{ + ObjectMeta: metav1.ObjectMeta{ + Name: ArgoCDManagerServiceAccount, + Namespace: ns.Name, + }, + Secrets: []corev1.ObjectReference{ + { + Kind: secret.GetObjectKind().GroupVersionKind().Kind, + APIVersion: secret.APIVersion, + Name: secret.GetName(), + Namespace: secret.GetNamespace(), + UID: secret.GetUID(), + ResourceVersion: secret.GetResourceVersion(), + }, + }, + } + + cs := fake.NewSimpleClientset(ns, saWithSecret, secret) + + got, err := getOrCreateServiceAccountTokenSecret(cs, ArgoCDManagerServiceAccount, ns.Name) + assert.NoError(t, err) + assert.Equal(t, "sa-secret", got) + + obj, err := cs.Tracker().Get(schema.GroupVersionResource{Version: "v1", Resource: "serviceaccounts"}, + ns.Name, ArgoCDManagerServiceAccount) + if err != nil { + t.Errorf("ServiceAccount %s not found but was expected to be found: %s", ArgoCDManagerServiceAccount, err.Error()) + } + + sa := obj.(*corev1.ServiceAccount) + assert.Equal(t, 1, len(sa.Secrets)) + + // Adding if statement to prevent case where secret not found + // since accessing name by first index. + if len(sa.Secrets) != 0 { + assert.Equal(t, "sa-secret", sa.Secrets[0].Name) + } +} From 4e1db7d9b2d7d861f9012eb810d4dc941a75d07d Mon Sep 17 00:00:00 2001 From: Daniel Helfand Date: Wed, 8 Jun 2022 09:32:13 -0500 Subject: [PATCH 2/2] change create to get in err Signed-off-by: Daniel Helfand --- util/clusterauth/clusterauth.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/util/clusterauth/clusterauth.go b/util/clusterauth/clusterauth.go index ea93d72f05a19..ca216bf9bf5ae 100644 --- a/util/clusterauth/clusterauth.go +++ b/util/clusterauth/clusterauth.go @@ -273,7 +273,7 @@ func getOrCreateServiceAccountTokenSecret(clientset kubernetes.Interface, sa, ns return true, nil }) if err != nil && err != wait.ErrWaitTimeout { - return "", fmt.Errorf("failed to create serviceaccount token secret: %w", err) + return "", fmt.Errorf("failed to get serviceaccount token secret: %w", err) } if serviceAccount == nil { log.Errorf("Unexpected nil serviceaccount '%s/%s' with no error returned", ns, sa)