From d73215358267543f9097a47c66abe2db2404ddb6 Mon Sep 17 00:00:00 2001 From: Aleksandr Rybolovlev Date: Tue, 26 Jul 2022 15:53:15 +0200 Subject: [PATCH 1/5] Update resource and data of 'kubernetes_(default_)service_account' to handle deprecated 'default_secret_name' in Kubernetes 1.24.0+ --- .../data_source_kubernetes_service_account.go | 5 +- ..._source_kubernetes_service_account_test.go | 13 ++--- kubernetes/provider.go | 24 +++++++++ ...urce_kubernetes_default_service_account.go | 1 - kubernetes/resource_kubernetes_service.go | 2 +- .../resource_kubernetes_service_account.go | 47 ++++++++++++++-- ...esource_kubernetes_service_account_test.go | 53 ++++++++++++++++++- kubernetes/structure_service_spec.go | 11 ++-- 8 files changed, 132 insertions(+), 24 deletions(-) diff --git a/kubernetes/data_source_kubernetes_service_account.go b/kubernetes/data_source_kubernetes_service_account.go index 45f92ac1c7..77ee53f616 100644 --- a/kubernetes/data_source_kubernetes_service_account.go +++ b/kubernetes/data_source_kubernetes_service_account.go @@ -48,8 +48,9 @@ func dataSourceKubernetesServiceAccount() *schema.Resource { Computed: true, }, "default_secret_name": { - Type: schema.TypeString, - Computed: true, + Type: schema.TypeString, + Computed: true, + Deprecated: "Starting from version 1.24.0 Kubernetes does not automatically generate a token for service accounts, in this case, `default_secret_name` will be empty and deprecated in future", }, }, } diff --git a/kubernetes/data_source_kubernetes_service_account_test.go b/kubernetes/data_source_kubernetes_service_account_test.go index ce6f4f05a6..02743c08ff 100644 --- a/kubernetes/data_source_kubernetes_service_account_test.go +++ b/kubernetes/data_source_kubernetes_service_account_test.go @@ -25,7 +25,6 @@ func TestAccKubernetesDataSourceServiceAccount_basic(t *testing.T) { resource.TestCheckResourceAttr("kubernetes_service_account.test", "secret.0.name", name+"-secret"), resource.TestCheckResourceAttr("kubernetes_service_account.test", "image_pull_secret.0.name", name+"-image-pull-secret"), resource.TestCheckResourceAttr("kubernetes_service_account.test", "automount_service_account_token", "true"), - resource.TestCheckResourceAttrSet("kubernetes_service_account.test", "default_secret_name"), ), }, { @@ -38,7 +37,6 @@ func TestAccKubernetesDataSourceServiceAccount_basic(t *testing.T) { resource.TestCheckResourceAttr("data.kubernetes_service_account.test", "secret.0.name", name+"-secret"), resource.TestCheckResourceAttr("data.kubernetes_service_account.test", "image_pull_secret.0.name", name+"-image-pull-secret"), resource.TestCheckResourceAttr("data.kubernetes_service_account.test", "automount_service_account_token", "true"), - resource.TestCheckResourceAttrSet("data.kubernetes_service_account.test", "default_secret_name"), ), }, }, @@ -49,18 +47,21 @@ func TestAccKubernetesDataSourceServiceAccount_default_secret(t *testing.T) { name := fmt.Sprintf("tf-acc-test-%s", acctest.RandStringFromCharSet(10, acctest.CharSetAlphaNum)) resource.Test(t, resource.TestCase{ - PreCheck: func() { testAccPreCheck(t) }, + PreCheck: func() { + testAccPreCheck(t) + skipIfClusterVersionGreaterThanOrEqual(t, "1.24.0") + }, ProviderFactories: testAccProviderFactories, Steps: []resource.TestStep{ { - Config: testAccKubernetesServiceAccountConfig_default_secret(name), + Config: testAccKubernetesDataSourceServiceAccountConfig_default_secret(name), Check: resource.ComposeAggregateTestCheckFunc( resource.TestCheckResourceAttr("kubernetes_service_account.test", "metadata.0.name", name), resource.TestCheckResourceAttr("kubernetes_service_account.test", "secret.#", "1"), ), }, { - Config: testAccKubernetesServiceAccountConfig_default_secret(name) + + Config: testAccKubernetesDataSourceServiceAccountConfig_default_secret(name) + testAccKubernetesDataSourceServiceAccountConfig_default_secret_read(name), Check: resource.ComposeAggregateTestCheckFunc( resource.TestCheckResourceAttr("data.kubernetes_service_account.test", "metadata.0.name", name), @@ -117,7 +118,7 @@ func testAccKubernetesDataSourceServiceAccountConfig_read() string { `) } -func testAccKubernetesServiceAccountConfig_default_secret(name string) string { +func testAccKubernetesDataSourceServiceAccountConfig_default_secret(name string) string { return fmt.Sprintf(` variable "token_name" { default = "%s-token-test0" diff --git a/kubernetes/provider.go b/kubernetes/provider.go index 1ab078094e..912262c4de 100644 --- a/kubernetes/provider.go +++ b/kubernetes/provider.go @@ -11,6 +11,7 @@ import ( "strconv" "github.com/hashicorp/go-cty/cty" + gversion "github.com/hashicorp/go-version" "github.com/mitchellh/go-homedir" "github.com/hashicorp/terraform-plugin-sdk/v2/diag" @@ -633,3 +634,26 @@ func useAdmissionregistrationV1beta1(conn *kubernetes.Clientset) (bool, error) { useadmissionregistrationv1beta1 = ptrToBool(true) return true, nil } + +func getServerVersion(connection *kubernetes.Clientset) (*gversion.Version, error) { + sv, err := connection.ServerVersion() + if err != nil { + return nil, err + } + + return gversion.NewVersion(sv.String()) +} + +func serverVersionGreaterThanOrEqual(connection *kubernetes.Clientset, version string) (bool, error) { + sv, err := getServerVersion(connection) + if err != nil { + return false, err + } + // server version that we need to compare with + cv, err := gversion.NewVersion(version) + if err != nil { + return false, err + } + + return sv.GreaterThanOrEqual(cv), nil +} diff --git a/kubernetes/resource_kubernetes_default_service_account.go b/kubernetes/resource_kubernetes_default_service_account.go index 5f6f98acb0..ce80196fb5 100644 --- a/kubernetes/resource_kubernetes_default_service_account.go +++ b/kubernetes/resource_kubernetes_default_service_account.go @@ -55,7 +55,6 @@ func resourceKubernetesDefaultServiceAccountCreate(ctx context.Context, d *schem log.Printf("[INFO] Default service account exists: %s", metadata.Namespace) return nil }) - if err != nil { return diag.FromErr(err) } diff --git a/kubernetes/resource_kubernetes_service.go b/kubernetes/resource_kubernetes_service.go index f870ba34c3..e5ba21db4e 100644 --- a/kubernetes/resource_kubernetes_service.go +++ b/kubernetes/resource_kubernetes_service.go @@ -442,7 +442,7 @@ func resourceKubernetesServiceUpdate(ctx context.Context, d *schema.ResourceData ops := patchMetadata("metadata.0.", "/metadata/", d) if d.HasChange("spec") { - serverVersion, err := conn.ServerVersion() + serverVersion, err := getServerVersion(conn) if err != nil { return diag.FromErr(err) } diff --git a/kubernetes/resource_kubernetes_service_account.go b/kubernetes/resource_kubernetes_service_account.go index 8463061578..647ad450ca 100644 --- a/kubernetes/resource_kubernetes_service_account.go +++ b/kubernetes/resource_kubernetes_service_account.go @@ -69,8 +69,9 @@ func resourceKubernetesServiceAccount() *schema.Resource { Default: true, }, "default_secret_name": { - Type: schema.TypeString, - Computed: true, + Type: schema.TypeString, + Computed: true, + Deprecated: "Starting from version 1.24.0 Kubernetes does not automatically generate a token for service accounts, in this case, `default_secret_name` will be empty and deprecated in future", }, }, } @@ -106,12 +107,21 @@ func resourceKubernetesServiceAccountCreate(ctx context.Context, d *schema.Resou if err != nil { return diag.FromErr(err) } + return resourceKubernetesServiceAccountRead(ctx, d, meta) } func getServiceAccountDefaultSecret(ctx context.Context, name string, config api.ServiceAccount, timeout time.Duration, conn *kubernetes.Clientset) (*api.Secret, error) { + b, err := serverVersionGreaterThanOrEqual(conn, "1.24.0") + if err != nil { + return &api.Secret{}, err + } + if b { + return &api.Secret{}, nil + } + var svcAccTokens []api.Secret - err := resource.RetryContext(ctx, timeout, func() *resource.RetryError { + err = resource.RetryContext(ctx, timeout, func() *resource.RetryError { resp, err := conn.CoreV1().ServiceAccounts(config.Namespace).Get(ctx, name, metav1.GetOptions{}) if err != nil { return resource.NonRetryableError(err) @@ -167,6 +177,20 @@ func findDefaultServiceAccount(ctx context.Context, sa *api.ServiceAccount, conn */ ds := make([]string, 0) + b, err := serverVersionGreaterThanOrEqual(conn, "1.24.0") + if err != nil { + return "", diag.FromErr(err) + } + if b { + return "", diag.Diagnostics{ + diag.Diagnostic{ + Severity: diag.Warning, + Summary: "'default_secret_name' is no longer applicable for Kubernetes 'v1.24.0' and above", + Detail: "Starting from version 1.24.0 Kubernetes does not automatically generate a token for service accounts, in this case, `default_secret_name` will be empty", + }, + } + } + for _, saSecret := range sa.Secrets { if !strings.HasPrefix(saSecret.Name, fmt.Sprintf("%s-token-", sa.Name)) { log.Printf("[DEBUG] Skipping %s as it doesn't have the right name", saSecret.Name) @@ -237,6 +261,9 @@ func diffObjectReferences(origOrs []api.ObjectReference, ors []api.ObjectReferen } func resourceKubernetesServiceAccountRead(ctx context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics { + + var diagMessages []diag.Diagnostic + exists, err := resourceKubernetesServiceAccountExists(ctx, d, meta) if err != nil { return diag.FromErr(err) @@ -284,6 +311,17 @@ func resourceKubernetesServiceAccountRead(ctx context.Context, d *schema.Resourc } defaultSecretName := d.Get("default_secret_name").(string) + b, err := serverVersionGreaterThanOrEqual(conn, "1.24.0") + if err != nil { + return diag.FromErr(err) + } + if b { + diagMessages = append(diagMessages, diag.Diagnostic{ + Severity: diag.Warning, + Summary: "'default_secret_name' is no longer applicable for Kubernetes 'v1.24.0' and above", + Detail: "Starting from version 1.24.0 Kubernetes does not automatically generate a token for service accounts, in this case, `default_secret_name` will be empty", + }) + } log.Printf("[DEBUG] Default secret name is %q", defaultSecretName) secrets := flattenServiceAccountSecrets(svcAcc.Secrets, defaultSecretName) log.Printf("[DEBUG] Flattened secrets: %#v", secrets) @@ -292,7 +330,7 @@ func resourceKubernetesServiceAccountRead(ctx context.Context, d *schema.Resourc return diag.FromErr(err) } - return nil + return diagMessages } func resourceKubernetesServiceAccountUpdate(ctx context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics { @@ -415,6 +453,7 @@ func resourceKubernetesServiceAccountImportState(ctx context.Context, d *schema. if err != nil { return nil, fmt.Errorf("Unable to set default_secret_name: %s", err) } + d.SetId(buildId(sa.ObjectMeta)) return []*schema.ResourceData{d}, nil diff --git a/kubernetes/resource_kubernetes_service_account_test.go b/kubernetes/resource_kubernetes_service_account_test.go index fb6105c207..c4a57a0e4e 100644 --- a/kubernetes/resource_kubernetes_service_account_test.go +++ b/kubernetes/resource_kubernetes_service_account_test.go @@ -63,6 +63,38 @@ func TestAccKubernetesServiceAccount_basic(t *testing.T) { }) } +func TestAccKubernetesServiceAccount_default_secret(t *testing.T) { + var conf api.ServiceAccount + name := fmt.Sprintf("tf-acc-test-%s", acctest.RandStringFromCharSet(10, acctest.CharSetAlphaNum)) + resourceName := "kubernetes_service_account_v1.test" + + resource.Test(t, resource.TestCase{ + PreCheck: func() { + testAccPreCheck(t) + skipIfClusterVersionGreaterThanOrEqual(t, "1.24.0") + }, + IDRefreshName: resourceName, + ProviderFactories: testAccProviderFactories, + CheckDestroy: testAccCheckKubernetesServiceAccountDestroy, + Steps: []resource.TestStep{ + { + Config: testAccKubernetesServiceAccountConfig_default_secret(name), + Check: resource.ComposeAggregateTestCheckFunc( + testAccCheckKubernetesServiceAccountExists(resourceName, &conf), + resource.TestCheckResourceAttr(resourceName, "metadata.0.name", name), + resource.TestCheckResourceAttrSet(resourceName, "default_secret_name"), + ), + }, + { + ResourceName: resourceName, + ImportState: true, + ImportStateVerify: true, + ImportStateVerifyIgnore: []string{"metadata.0.resource_version", "automount_service_account_token"}, + }, + }, + }) +} + func TestAccKubernetesServiceAccount_automount(t *testing.T) { var conf api.ServiceAccount name := fmt.Sprintf("tf-acc-test-%s", acctest.RandStringFromCharSet(10, acctest.CharSetAlphaNum)) @@ -187,7 +219,7 @@ func TestAccKubernetesServiceAccount_update(t *testing.T) { resource.TestCheckResourceAttr("kubernetes_service_account.test", "image_pull_secret.#", "0"), resource.TestCheckResourceAttr("kubernetes_service_account.test", "automount_service_account_token", "true"), testAccCheckServiceAccountImagePullSecrets(&conf, []*regexp.Regexp{}), - testAccCheckServiceAccountSecrets(&conf, []*regexp.Regexp{ + testAccCheckServiceAccountDefaultSecrets(&conf, []*regexp.Regexp{ regexp.MustCompile("^" + name + "-token-[a-z0-9]+$"), }), ), @@ -219,7 +251,7 @@ func TestAccKubernetesServiceAccount_generatedName(t *testing.T) { resource.TestCheckResourceAttrSet("kubernetes_service_account.test", "metadata.0.uid"), resource.TestCheckResourceAttr("kubernetes_service_account.test", "automount_service_account_token", "true"), testAccCheckServiceAccountImagePullSecrets(&conf, []*regexp.Regexp{}), - testAccCheckServiceAccountSecrets(&conf, []*regexp.Regexp{ + testAccCheckServiceAccountDefaultSecrets(&conf, []*regexp.Regexp{ regexp.MustCompile("^" + prefix + "[a-z0-9]+-token-[a-z0-9]+$"), }), ), @@ -255,6 +287,15 @@ func matchLocalObjectReferenceName(lor []api.LocalObjectReference, expected []*r return false } +func testAccCheckServiceAccountDefaultSecrets(m *api.ServiceAccount, expected []*regexp.Regexp) resource.TestCheckFunc { + if clusterVersionGreaterThanOrEqual("1.24.0") { + return func(s *terraform.State) error { + return nil + } + } + return testAccCheckServiceAccountSecrets(m, expected) +} + func testAccCheckServiceAccountSecrets(m *api.ServiceAccount, expected []*regexp.Regexp) resource.TestCheckFunc { return func(s *terraform.State) error { if len(expected) == 0 && len(m.Secrets) == 0 { @@ -397,6 +438,14 @@ resource "kubernetes_secret" "four" { `, name, name, name, name, name) } +func testAccKubernetesServiceAccountConfig_default_secret(name string) string { + return fmt.Sprintf(`resource "kubernetes_service_account_v1" "test" { + metadata { + name = "%s" + } +}`, name) +} + func testAccKubernetesServiceAccountConfig_modified(name string) string { return fmt.Sprintf(`resource "kubernetes_service_account" "test" { metadata { diff --git a/kubernetes/structure_service_spec.go b/kubernetes/structure_service_spec.go index a35449ce31..8dbcd1c3e3 100644 --- a/kubernetes/structure_service_spec.go +++ b/kubernetes/structure_service_spec.go @@ -5,7 +5,6 @@ import ( "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" v1 "k8s.io/api/core/v1" "k8s.io/apimachinery/pkg/util/intstr" - "k8s.io/apimachinery/pkg/version" ) // Flatteners @@ -284,7 +283,7 @@ func expandServiceSpec(l []interface{}) v1.ServiceSpec { // Patch Ops -func patchServiceSpec(keyPrefix, pathPrefix string, d *schema.ResourceData, v *version.Info) (PatchOperations, error) { +func patchServiceSpec(keyPrefix, pathPrefix string, d *schema.ResourceData, kv *gversion.Version) (PatchOperations, error) { ops := make([]PatchOperation, 0, 0) if d.HasChange(keyPrefix + "allocate_load_balancer_node_ports") { @@ -360,12 +359,8 @@ func patchServiceSpec(keyPrefix, pathPrefix string, d *schema.ResourceData, v *v }) } if d.HasChange(keyPrefix + "external_ips") { - k8sVersion, err := gversion.NewVersion(v.String()) - if err != nil { - return nil, err - } - v1_8_0, _ := gversion.NewVersion("1.8.0") - if k8sVersion.LessThan(v1_8_0) { + version, _ := gversion.NewVersion("1.8.0") + if kv.LessThan(version) { // If we haven't done this the deprecated field would have priority ops = append(ops, &ReplaceOperation{ Path: pathPrefix + "deprecatedPublicIPs", From 25d0def8d0741613381157aae2f66d395717401d Mon Sep 17 00:00:00 2001 From: Aleksandr Rybolovlev Date: Wed, 27 Jul 2022 09:47:49 +0200 Subject: [PATCH 2/5] Update service account related documentation --- kubernetes/data_source_kubernetes_service_account.go | 2 +- kubernetes/resource_kubernetes_service_account.go | 2 +- website/docs/d/service_account.html.markdown | 2 +- website/docs/d/service_account_v1.html.markdown | 2 +- website/docs/r/default_service_account.html.markdown | 2 +- website/docs/r/default_service_account_v1.html.markdown | 2 +- website/docs/r/service_account.html.markdown | 2 +- website/docs/r/service_account_v1.html.markdown | 2 +- 8 files changed, 8 insertions(+), 8 deletions(-) diff --git a/kubernetes/data_source_kubernetes_service_account.go b/kubernetes/data_source_kubernetes_service_account.go index 77ee53f616..beff26017b 100644 --- a/kubernetes/data_source_kubernetes_service_account.go +++ b/kubernetes/data_source_kubernetes_service_account.go @@ -50,7 +50,7 @@ func dataSourceKubernetesServiceAccount() *schema.Resource { "default_secret_name": { Type: schema.TypeString, Computed: true, - Deprecated: "Starting from version 1.24.0 Kubernetes does not automatically generate a token for service accounts, in this case, `default_secret_name` will be empty and deprecated in future", + Deprecated: "Starting from version 1.24.0 Kubernetes does not automatically generate a token for service accounts, in this case, `default_secret_name` will be empty", }, }, } diff --git a/kubernetes/resource_kubernetes_service_account.go b/kubernetes/resource_kubernetes_service_account.go index 647ad450ca..addd5b39b3 100644 --- a/kubernetes/resource_kubernetes_service_account.go +++ b/kubernetes/resource_kubernetes_service_account.go @@ -71,7 +71,7 @@ func resourceKubernetesServiceAccount() *schema.Resource { "default_secret_name": { Type: schema.TypeString, Computed: true, - Deprecated: "Starting from version 1.24.0 Kubernetes does not automatically generate a token for service accounts, in this case, `default_secret_name` will be empty and deprecated in future", + Deprecated: "Starting from version 1.24.0 Kubernetes does not automatically generate a token for service accounts, in this case, `default_secret_name` will be empty", }, }, } diff --git a/website/docs/d/service_account.html.markdown b/website/docs/d/service_account.html.markdown index 431f371323..2637e64355 100644 --- a/website/docs/d/service_account.html.markdown +++ b/website/docs/d/service_account.html.markdown @@ -53,7 +53,7 @@ The following arguments are supported: * `image_pull_secret` - A list of image pull secrets associated with the service account. * `secret` - A list of secrets associated with the service account. -* `default_secret_name` - Name of the default secret, containing service account token, created & managed by the service. By default, the provider will try to find the secret containing the service account token that Kubernetes automatically created for the service account. Where there are multiple tokens and the provider cannot determine which was created by Kubernetes, this attribute will be empty. When only one token is associated with the service account, the provider will return this single token secret. +* `default_secret_name` - Name of the default secret, containing service account token, created & managed by the service. By default, the provider will try to find the secret containing the service account token that Kubernetes automatically created for the service account. Where there are multiple tokens and the provider cannot determine which was created by Kubernetes, this attribute will be empty. When only one token is associated with the service account, the provider will return this single token secret. Starting from version 1.24.0 Kubernetes does not automatically generate a token for service accounts, in this case, `default_secret_name` will be empty. ### `image_pull_secret` diff --git a/website/docs/d/service_account_v1.html.markdown b/website/docs/d/service_account_v1.html.markdown index 8227ad84cf..629dda01e2 100644 --- a/website/docs/d/service_account_v1.html.markdown +++ b/website/docs/d/service_account_v1.html.markdown @@ -53,7 +53,7 @@ The following arguments are supported: * `image_pull_secret` - A list of image pull secrets associated with the service account. * `secret` - A list of secrets associated with the service account. -* `default_secret_name` - Name of the default secret, containing service account token, created & managed by the service. By default, the provider will try to find the secret containing the service account token that Kubernetes automatically created for the service account. Where there are multiple tokens and the provider cannot determine which was created by Kubernetes, this attribute will be empty. When only one token is associated with the service account, the provider will return this single token secret. +* `default_secret_name` - Name of the default secret, containing service account token, created & managed by the service. By default, the provider will try to find the secret containing the service account token that Kubernetes automatically created for the service account. Where there are multiple tokens and the provider cannot determine which was created by Kubernetes, this attribute will be empty. When only one token is associated with the service account, the provider will return this single token secret. Starting from version 1.24.0 Kubernetes does not automatically generate a token for service accounts, in this case, `default_secret_name` will be empty. ### `image_pull_secret` diff --git a/website/docs/r/default_service_account.html.markdown b/website/docs/r/default_service_account.html.markdown index dfb2fd75db..c489a6eb04 100644 --- a/website/docs/r/default_service_account.html.markdown +++ b/website/docs/r/default_service_account.html.markdown @@ -79,7 +79,7 @@ The following arguments are supported: In addition to the arguments listed above, the following computed attributes are exported: -* `default_secret_name` - Name of the default secret, containing service account token, created & managed by the service. By default, the provider will try to find the secret containing the service account token that Kubernetes automatically created for the service account. Where there are multiple tokens and the provider cannot determine which was created by Kubernetes, this attribute will be empty. When only one token is associated with the service account, the provider will return this single token secret. +* `default_secret_name` - Name of the default secret, containing service account token, created & managed by the service. By default, the provider will try to find the secret containing the service account token that Kubernetes automatically created for the service account. Where there are multiple tokens and the provider cannot determine which was created by Kubernetes, this attribute will be empty. When only one token is associated with the service account, the provider will return this single token secret. Starting from version 1.24.0 Kubernetes does not automatically generate a token for service accounts, in this case, `default_secret_name` will be empty. ## Destroying diff --git a/website/docs/r/default_service_account_v1.html.markdown b/website/docs/r/default_service_account_v1.html.markdown index aad5723263..94548e4457 100644 --- a/website/docs/r/default_service_account_v1.html.markdown +++ b/website/docs/r/default_service_account_v1.html.markdown @@ -79,7 +79,7 @@ The following arguments are supported: In addition to the arguments listed above, the following computed attributes are exported: -* `default_secret_name` - Name of the default secret, containing service account token, created & managed by the service. By default, the provider will try to find the secret containing the service account token that Kubernetes automatically created for the service account. Where there are multiple tokens and the provider cannot determine which was created by Kubernetes, this attribute will be empty. When only one token is associated with the service account, the provider will return this single token secret. +* `default_secret_name` - Name of the default secret, containing service account token, created & managed by the service. By default, the provider will try to find the secret containing the service account token that Kubernetes automatically created for the service account. Where there are multiple tokens and the provider cannot determine which was created by Kubernetes, this attribute will be empty. When only one token is associated with the service account, the provider will return this single token secret. Starting from version 1.24.0 Kubernetes does not automatically generate a token for service accounts, in this case, `default_secret_name` will be empty. ## Destroying diff --git a/website/docs/r/service_account.html.markdown b/website/docs/r/service_account.html.markdown index 8b4f3b2dc6..6fa686f3d1 100644 --- a/website/docs/r/service_account.html.markdown +++ b/website/docs/r/service_account.html.markdown @@ -81,7 +81,7 @@ The following arguments are supported: In addition to the arguments listed above, the following computed attributes are exported: -* `default_secret_name` - Name of the default secret, containing service account token, created & managed by the service. By default, the provider will try to find the secret containing the service account token that Kubernetes automatically created for the service account. Where there are multiple tokens and the provider cannot determine which was created by Kubernetes, this attribute will be empty. When only one token is associated with the service account, the provider will return this single token secret. +* `default_secret_name` - Name of the default secret, containing service account token, created & managed by the service. By default, the provider will try to find the secret containing the service account token that Kubernetes automatically created for the service account. Where there are multiple tokens and the provider cannot determine which was created by Kubernetes, this attribute will be empty. When only one token is associated with the service account, the provider will return this single token secret. Starting from version 1.24.0 Kubernetes does not automatically generate a token for service accounts, in this case, `default_secret_name` will be empty. ## Import diff --git a/website/docs/r/service_account_v1.html.markdown b/website/docs/r/service_account_v1.html.markdown index 757ee49fe9..59e398b15f 100644 --- a/website/docs/r/service_account_v1.html.markdown +++ b/website/docs/r/service_account_v1.html.markdown @@ -81,7 +81,7 @@ The following arguments are supported: In addition to the arguments listed above, the following computed attributes are exported: -* `default_secret_name` - Name of the default secret, containing service account token, created & managed by the service. By default, the provider will try to find the secret containing the service account token that Kubernetes automatically created for the service account. Where there are multiple tokens and the provider cannot determine which was created by Kubernetes, this attribute will be empty. When only one token is associated with the service account, the provider will return this single token secret. +* `default_secret_name` - Name of the default secret, containing service account token, created & managed by the service. By default, the provider will try to find the secret containing the service account token that Kubernetes automatically created for the service account. Where there are multiple tokens and the provider cannot determine which was created by Kubernetes, this attribute will be empty. When only one token is associated with the service account, the provider will return this single token secret. Starting from version 1.24.0 Kubernetes does not automatically generate a token for service accounts, in this case, `default_secret_name` will be empty. ## Import From 04140ea649a2dcdaffb2da3f85dde35320fd97c8 Mon Sep 17 00:00:00 2001 From: Aleksandr Rybolovlev Date: Thu, 11 Aug 2022 11:13:44 +0200 Subject: [PATCH 3/5] Update tests so they can detect version of the cluster correctly --- .../resource_kubernetes_service_account_test.go | 16 +++++----------- 1 file changed, 5 insertions(+), 11 deletions(-) diff --git a/kubernetes/resource_kubernetes_service_account_test.go b/kubernetes/resource_kubernetes_service_account_test.go index c4a57a0e4e..8ae4990839 100644 --- a/kubernetes/resource_kubernetes_service_account_test.go +++ b/kubernetes/resource_kubernetes_service_account_test.go @@ -219,7 +219,7 @@ func TestAccKubernetesServiceAccount_update(t *testing.T) { resource.TestCheckResourceAttr("kubernetes_service_account.test", "image_pull_secret.#", "0"), resource.TestCheckResourceAttr("kubernetes_service_account.test", "automount_service_account_token", "true"), testAccCheckServiceAccountImagePullSecrets(&conf, []*regexp.Regexp{}), - testAccCheckServiceAccountDefaultSecrets(&conf, []*regexp.Regexp{ + testAccCheckServiceAccountSecrets(&conf, []*regexp.Regexp{ regexp.MustCompile("^" + name + "-token-[a-z0-9]+$"), }), ), @@ -251,7 +251,7 @@ func TestAccKubernetesServiceAccount_generatedName(t *testing.T) { resource.TestCheckResourceAttrSet("kubernetes_service_account.test", "metadata.0.uid"), resource.TestCheckResourceAttr("kubernetes_service_account.test", "automount_service_account_token", "true"), testAccCheckServiceAccountImagePullSecrets(&conf, []*regexp.Regexp{}), - testAccCheckServiceAccountDefaultSecrets(&conf, []*regexp.Regexp{ + testAccCheckServiceAccountSecrets(&conf, []*regexp.Regexp{ regexp.MustCompile("^" + prefix + "[a-z0-9]+-token-[a-z0-9]+$"), }), ), @@ -287,17 +287,11 @@ func matchLocalObjectReferenceName(lor []api.LocalObjectReference, expected []*r return false } -func testAccCheckServiceAccountDefaultSecrets(m *api.ServiceAccount, expected []*regexp.Regexp) resource.TestCheckFunc { - if clusterVersionGreaterThanOrEqual("1.24.0") { - return func(s *terraform.State) error { - return nil - } - } - return testAccCheckServiceAccountSecrets(m, expected) -} - func testAccCheckServiceAccountSecrets(m *api.ServiceAccount, expected []*regexp.Regexp) resource.TestCheckFunc { return func(s *terraform.State) error { + if clusterVersionGreaterThanOrEqual("1.24.0") { + return nil + } if len(expected) == 0 && len(m.Secrets) == 0 { return nil } From 8c6ceb2f5cc98831142ae1799111d13eb92c076c Mon Sep 17 00:00:00 2001 From: Aleksandr Rybolovlev Date: Tue, 16 Aug 2022 10:15:34 +0200 Subject: [PATCH 4/5] Update diag messages and rename variables for clarity --- .../resource_kubernetes_service_account.go | 20 +++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/kubernetes/resource_kubernetes_service_account.go b/kubernetes/resource_kubernetes_service_account.go index addd5b39b3..f7d8b1f282 100644 --- a/kubernetes/resource_kubernetes_service_account.go +++ b/kubernetes/resource_kubernetes_service_account.go @@ -112,11 +112,11 @@ func resourceKubernetesServiceAccountCreate(ctx context.Context, d *schema.Resou } func getServiceAccountDefaultSecret(ctx context.Context, name string, config api.ServiceAccount, timeout time.Duration, conn *kubernetes.Clientset) (*api.Secret, error) { - b, err := serverVersionGreaterThanOrEqual(conn, "1.24.0") + sv, err := serverVersionGreaterThanOrEqual(conn, "1.24.0") if err != nil { return &api.Secret{}, err } - if b { + if sv { return &api.Secret{}, nil } @@ -177,16 +177,16 @@ func findDefaultServiceAccount(ctx context.Context, sa *api.ServiceAccount, conn */ ds := make([]string, 0) - b, err := serverVersionGreaterThanOrEqual(conn, "1.24.0") + sv, err := serverVersionGreaterThanOrEqual(conn, "1.24.0") if err != nil { return "", diag.FromErr(err) } - if b { + if sv { return "", diag.Diagnostics{ diag.Diagnostic{ Severity: diag.Warning, - Summary: "'default_secret_name' is no longer applicable for Kubernetes 'v1.24.0' and above", - Detail: "Starting from version 1.24.0 Kubernetes does not automatically generate a token for service accounts, in this case, `default_secret_name` will be empty", + Summary: `"default_secret_name" is no longer applicable for Kubernetes v1.24.0 and above`, + Detail: `Starting from version 1.24.0 Kubernetes does not automatically generate a token for service accounts, in this case, "default_secret_name" will be empty`, }, } } @@ -311,15 +311,15 @@ func resourceKubernetesServiceAccountRead(ctx context.Context, d *schema.Resourc } defaultSecretName := d.Get("default_secret_name").(string) - b, err := serverVersionGreaterThanOrEqual(conn, "1.24.0") + sv, err := serverVersionGreaterThanOrEqual(conn, "1.24.0") if err != nil { return diag.FromErr(err) } - if b { + if sv { diagMessages = append(diagMessages, diag.Diagnostic{ Severity: diag.Warning, - Summary: "'default_secret_name' is no longer applicable for Kubernetes 'v1.24.0' and above", - Detail: "Starting from version 1.24.0 Kubernetes does not automatically generate a token for service accounts, in this case, `default_secret_name` will be empty", + Summary: `"default_secret_name" is no longer applicable for Kubernetes v1.24.0 and above`, + Detail: `Starting from version 1.24.0 Kubernetes does not automatically generate a token for service accounts, in this case, "default_secret_name" will be empty`, }) } log.Printf("[DEBUG] Default secret name is %q", defaultSecretName) From 8caf26c39d4b1d285c09df576ebaccd236414a55 Mon Sep 17 00:00:00 2001 From: Aleksandr Rybolovlev Date: Tue, 16 Aug 2022 16:02:55 +0200 Subject: [PATCH 5/5] Move cluster version verification to the end of function resourceKubernetesServiceAccountRead --- .../resource_kubernetes_service_account.go | 30 +++++++++---------- 1 file changed, 15 insertions(+), 15 deletions(-) diff --git a/kubernetes/resource_kubernetes_service_account.go b/kubernetes/resource_kubernetes_service_account.go index f7d8b1f282..19198ffd1d 100644 --- a/kubernetes/resource_kubernetes_service_account.go +++ b/kubernetes/resource_kubernetes_service_account.go @@ -261,9 +261,6 @@ func diffObjectReferences(origOrs []api.ObjectReference, ors []api.ObjectReferen } func resourceKubernetesServiceAccountRead(ctx context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics { - - var diagMessages []diag.Diagnostic - exists, err := resourceKubernetesServiceAccountExists(ctx, d, meta) if err != nil { return diag.FromErr(err) @@ -311,17 +308,6 @@ func resourceKubernetesServiceAccountRead(ctx context.Context, d *schema.Resourc } defaultSecretName := d.Get("default_secret_name").(string) - sv, err := serverVersionGreaterThanOrEqual(conn, "1.24.0") - if err != nil { - return diag.FromErr(err) - } - if sv { - diagMessages = append(diagMessages, diag.Diagnostic{ - Severity: diag.Warning, - Summary: `"default_secret_name" is no longer applicable for Kubernetes v1.24.0 and above`, - Detail: `Starting from version 1.24.0 Kubernetes does not automatically generate a token for service accounts, in this case, "default_secret_name" will be empty`, - }) - } log.Printf("[DEBUG] Default secret name is %q", defaultSecretName) secrets := flattenServiceAccountSecrets(svcAcc.Secrets, defaultSecretName) log.Printf("[DEBUG] Flattened secrets: %#v", secrets) @@ -330,7 +316,21 @@ func resourceKubernetesServiceAccountRead(ctx context.Context, d *schema.Resourc return diag.FromErr(err) } - return diagMessages + sv, err := serverVersionGreaterThanOrEqual(conn, "1.24.0") + if err != nil { + return diag.FromErr(err) + } + if sv { + return diag.Diagnostics{ + diag.Diagnostic{ + Severity: diag.Warning, + Summary: `"default_secret_name" is no longer applicable for Kubernetes v1.24.0 and above`, + Detail: `Starting from version 1.24.0 Kubernetes does not automatically generate a token for service accounts, in this case, "default_secret_name" will be empty`, + }, + } + } + + return nil } func resourceKubernetesServiceAccountUpdate(ctx context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics {