From 1039c8fd40a480c3176a23cfb0473ffa264f6677 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Luka=20Zakraj=C5=A1ek?= Date: Tue, 30 Mar 2021 01:55:27 +0200 Subject: [PATCH] Add secret_namespace to volume_source azure_file (#1204) * Add secret_namespace to volume_source azure_file * Update kubernetes/schema_volume_source.go Co-authored-by: Stef Forrester --- ...ource_kubernetes_persistent_volume_test.go | 137 ++++++++++++++++++ kubernetes/schema_volume_source.go | 7 + .../structure_persistent_volume_spec.go | 6 + kubernetes/test-infra/aks/README.md | 2 +- .../docs/guides/getting-started.html.markdown | 7 +- .../docs/r/persistent_volume.html.markdown | 7 +- 6 files changed, 159 insertions(+), 7 deletions(-) diff --git a/kubernetes/resource_kubernetes_persistent_volume_test.go b/kubernetes/resource_kubernetes_persistent_volume_test.go index 69c8e686bc..244ffbb874 100644 --- a/kubernetes/resource_kubernetes_persistent_volume_test.go +++ b/kubernetes/resource_kubernetes_persistent_volume_test.go @@ -137,6 +137,50 @@ func TestAccKubernetesPersistentVolume_azure_blobStorageDisk(t *testing.T) { }) } +func TestAccKubernetesPersistentVolume_azure_file(t *testing.T) { + var conf1, conf2 api.PersistentVolume + // name must not contain dashes, due to the Azure API requirements for storage accounts. + name := fmt.Sprintf("tfacctest%s", acctest.RandStringFromCharSet(10, acctest.CharSetAlphaNum)) + namespace := fmt.Sprintf("tfacctest%s", acctest.RandStringFromCharSet(10, acctest.CharSetAlphaNum)) + secretName := fmt.Sprintf("tfacctest%s", acctest.RandStringFromCharSet(10, acctest.CharSetAlphaNum)) + location := os.Getenv("TF_VAR_location") + + resource.Test(t, resource.TestCase{ + PreCheck: func() { testAccPreCheck(t); skipIfNotRunningInAks(t) }, + IDRefreshName: "kubernetes_persistent_volume.test", + ProviderFactories: testAccProviderFactories, + ExternalProviders: testAccExternalProviders, + CheckDestroy: testAccCheckKubernetesPersistentVolumeDestroy, + Steps: []resource.TestStep{ + { // Create a PV using the existing Azure storage share (without secret_namespace). + Config: testAccKubernetesPersistentVolumeConfig_azure_file(name, location) + + testAccKubernetesPersistentVolumeConfig_azure_PersistentVolumeAzureFile(name, secretName), + Check: resource.ComposeAggregateTestCheckFunc( + testAccCheckKubernetesPersistentVolumeExists("kubernetes_persistent_volume.test", &conf1), + resource.TestCheckResourceAttr("kubernetes_persistent_volume.test", "metadata.0.name", name), + resource.TestCheckResourceAttr("kubernetes_persistent_volume.test", "spec.0.persistent_volume_source.0.azure_file.#", "1"), + resource.TestCheckResourceAttr("kubernetes_persistent_volume.test", "spec.0.persistent_volume_source.0.azure_file.0.share_name", name), + resource.TestCheckResourceAttr("kubernetes_persistent_volume.test", "spec.0.persistent_volume_source.0.azure_file.0.secret_name", secretName), + resource.TestCheckResourceAttr("kubernetes_persistent_volume.test", "spec.0.persistent_volume_source.0.azure_file.0.secret_namespace", ""), + ), + }, + { // Create a PV using the existing Azure storage share (with secret_namespace). + Config: testAccKubernetesPersistentVolumeConfig_azure_file(name, location) + + testAccKubernetesPersistentVolumeConfig_azure_PersistentVolumeAzureFileNamespace(name, namespace, secretName), + Check: resource.ComposeAggregateTestCheckFunc( + testAccCheckKubernetesPersistentVolumeExists("kubernetes_persistent_volume.test", &conf2), + resource.TestCheckResourceAttr("kubernetes_persistent_volume.test", "metadata.0.name", name), + resource.TestCheckResourceAttr("kubernetes_persistent_volume.test", "spec.0.persistent_volume_source.0.azure_file.#", "1"), + resource.TestCheckResourceAttr("kubernetes_persistent_volume.test", "spec.0.persistent_volume_source.0.azure_file.0.share_name", name), + resource.TestCheckResourceAttr("kubernetes_persistent_volume.test", "spec.0.persistent_volume_source.0.azure_file.0.secret_name", secretName), + resource.TestCheckResourceAttr("kubernetes_persistent_volume.test", "spec.0.persistent_volume_source.0.azure_file.0.secret_namespace", namespace), + testAccCheckKubernetesPersistentVolumeForceNew(&conf1, &conf2, true), + ), + }, + }, + }) +} + func TestAccKubernetesPersistentVolume_googleCloud_basic(t *testing.T) { var conf api.PersistentVolume randString := acctest.RandStringFromCharSet(10, acctest.CharSetAlphaNum) @@ -1357,6 +1401,99 @@ resource "azurerm_storage_container" "test" { `, name, location) } +func testAccKubernetesPersistentVolumeConfig_azure_PersistentVolumeAzureFile(name, secretName string) string { + return fmt.Sprintf(`resource "kubernetes_persistent_volume" "test" { + metadata { + name = %[1]q + } + spec { + capacity = { + storage = "1Gi" + } + access_modes = ["ReadWriteOnce"] + persistent_volume_source { + azure_file { + secret_name = %[2]q + share_name = %[1]q + read_only = false + } + } + } +}`, name, secretName) +} + +func testAccKubernetesPersistentVolumeConfig_azure_PersistentVolumeAzureFileNamespace(name, namespace, secretName string) string { + return fmt.Sprintf(`resource "kubernetes_namespace" "test" { + metadata { + name = %[2]q + } +} + +resource "kubernetes_secret" "test" { + metadata { + name = %[3]q + namespace = %[2]q + } + + data = { + azurestorageaccountname = azurerm_storage_account.test.name + azurestorageaccountkey = azurerm_storage_account.test.primary_access_key + } +} + +resource "kubernetes_persistent_volume" "test" { + metadata { + name = %[1]q + } + spec { + capacity = { + storage = "1Gi" + } + access_modes = ["ReadWriteOnce"] + persistent_volume_source { + azure_file { + secret_name = %[3]q + secret_namespace = %[2]q + share_name = %[1]q + read_only = false + } + } + } +}`, name, namespace, secretName) +} + +func testAccKubernetesPersistentVolumeConfig_azure_file(name, location string) string { + return fmt.Sprintf(`provider "azurerm" { + features {} +} +resource "azurerm_resource_group" "test" { + name = "%s" + location = "%s" + tags = { + environment = "terraform-provider-kubernetes-test" + } +} +resource "azurerm_storage_account" "test" { + name = %[1]q + resource_group_name = azurerm_resource_group.test.name + location = azurerm_resource_group.test.location + account_tier = "Standard" + account_replication_type = "LRS" + account_kind = "StorageV2" + # needed for Azure File kubernetes cifs mount + enable_https_traffic_only = false + tags = { + environment = "terraform-provider-kubernetes-test" + } +} +resource "azurerm_storage_share" "test" { + name = %[1]q + storage_account_name = azurerm_storage_account.test.name + quota = 1 +} +`, name, location) +} + func testAccKubernetesPersistentVolumeConfig_csi_basic(name string) string { return fmt.Sprintf(`resource "kubernetes_persistent_volume" "test" { metadata { diff --git a/kubernetes/schema_volume_source.go b/kubernetes/schema_volume_source.go index d1529664fb..5e31af9dbd 100644 --- a/kubernetes/schema_volume_source.go +++ b/kubernetes/schema_volume_source.go @@ -139,6 +139,13 @@ func commonVolumeSources() map[string]*schema.Schema { Description: "The name of secret that contains Azure Storage Account Name and Key", Required: true, }, + "secret_namespace": { + Type: schema.TypeString, + Description: "The namespace of the secret that contains Azure Storage Account Name and Key. For Kubernetes up to 1.18.x the default is the same as the Pod. For Kubernetes 1.19.x and later the default is \"default\" namespace.", + Optional: true, + Computed: false, + ForceNew: true, + }, "share_name": { Type: schema.TypeString, Description: "Share Name", diff --git a/kubernetes/structure_persistent_volume_spec.go b/kubernetes/structure_persistent_volume_spec.go index ff5d89ed53..0b22b4148a 100644 --- a/kubernetes/structure_persistent_volume_spec.go +++ b/kubernetes/structure_persistent_volume_spec.go @@ -57,6 +57,9 @@ func flattenAzureFilePersistentVolumeSource(in *v1.AzureFilePersistentVolumeSour if in.ReadOnly != false { att["read_only"] = in.ReadOnly } + if in.SecretNamespace != nil { + att["secret_namespace"] = *in.SecretNamespace + } return []interface{}{att} } @@ -583,6 +586,9 @@ func expandAzureFilePersistentVolumeSource(l []interface{}) *v1.AzureFilePersist if v, ok := in["read_only"].(bool); ok { obj.ReadOnly = v } + if v, ok := in["secret_namespace"].(string); ok && v != "" { + obj.SecretNamespace = &v + } return obj } diff --git a/kubernetes/test-infra/aks/README.md b/kubernetes/test-infra/aks/README.md index 789770fff8..3fdcf66d49 100644 --- a/kubernetes/test-infra/aks/README.md +++ b/kubernetes/test-infra/aks/README.md @@ -9,7 +9,7 @@ In addition, you will need the following environment variables to be set. - `TF_VAR_aks_client_secret` - `TF_VAR_location` -Obtaining the values for ***client id*** and ***client secret*** is detailed in the documentation linked above. +Obtaining the values for ***client id*** and ***client secret*** is detailed in the documentation linked above. ## Versions diff --git a/website/docs/guides/getting-started.html.markdown b/website/docs/guides/getting-started.html.markdown index 688a92293a..c847ae30ad 100644 --- a/website/docs/guides/getting-started.html.markdown +++ b/website/docs/guides/getting-started.html.markdown @@ -350,9 +350,10 @@ Terraform will perform the following actions: } + azure_file { - + read_only = (known after apply) - + secret_name = (known after apply) - + share_name = (known after apply) + + read_only = (known after apply) + + secret_name = (known after apply) + + share_name = (known after apply) + + secret_namespace = (known after apply) } + ceph_fs { diff --git a/website/docs/r/persistent_volume.html.markdown b/website/docs/r/persistent_volume.html.markdown index 5adcda6e9d..92c681d56b 100644 --- a/website/docs/r/persistent_volume.html.markdown +++ b/website/docs/r/persistent_volume.html.markdown @@ -180,7 +180,8 @@ The following arguments are supported: #### Arguments * `read_only` - (Optional) Whether to force the read-only setting in VolumeMounts. Defaults to false (read/write). -* `secret_name` - (Required) The name of secret that contains Azure Storage Account Name and Key +* `secret_name` - (Required) The name of secret that contains Azure Storage Account Name and Key. +* `secret_namespace` - (Optional) The namespace of the secret that contains Azure Storage Account Name and Key. For Kubernetes up to 1.18.x the default is the same as the Pod. For Kubernetes 1.19.x and later the default is \"default\" namespace. * `share_name` - (Required) Share Name ### `ceph_fs` @@ -287,11 +288,11 @@ The following arguments are supported: #### Arguments -* `annotations` - (Optional) An unstructured key value map stored with the persistent volume that may be used to store arbitrary metadata. +* `annotations` - (Optional) An unstructured key value map stored with the persistent volume that may be used to store arbitrary metadata. ~> By default, the provider ignores any annotations whose key names end with *kubernetes.io*. This is necessary because such annotations can be mutated by server-side components and consequently cause a perpetual diff in the Terraform plan output. If you explicitly specify any such annotations in the configuration template then Terraform will consider these as normal resource attributes and manage them as expected (while still avoiding the perpetual diff problem). For more info info see [Kubernetes reference](http://kubernetes.io/docs/user-guide/annotations) -* `labels` - (Optional) Map of string keys and values that can be used to organize and categorize (scope and select) the persistent volume. May match selectors of replication controllers and services. +* `labels` - (Optional) Map of string keys and values that can be used to organize and categorize (scope and select) the persistent volume. May match selectors of replication controllers and services. ~> By default, the provider ignores any labels whose key names end with *kubernetes.io*. This is necessary because such labels can be mutated by server-side components and consequently cause a perpetual diff in the Terraform plan output. If you explicitly specify any such labels in the configuration template then Terraform will consider these as normal resource attributes and manage them as expected (while still avoiding the perpetual diff problem). For more info info see [Kubernetes reference](http://kubernetes.io/docs/user-guide/labels)