From e00cdd3ffb8cc7a183a672cabff9c7b04ea3de0a Mon Sep 17 00:00:00 2001 From: benjah1 Date: Tue, 21 Jul 2020 23:43:59 +0000 Subject: [PATCH] add sub_path_expr to volume_mount --- .../resource_kubernetes_deployment_test.go | 1 + kubernetes/resource_kubernetes_pod_test.go | 90 +++++++++++++++++++ ..._kubernetes_replication_controller_test.go | 1 + kubernetes/schema_container.go | 5 ++ kubernetes/structures_container.go | 6 ++ website/docs/d/pod.html.markdown | 1 + .../docs/guides/getting-started.html.markdown | 9 +- website/docs/r/daemonset.html.markdown | 1 + website/docs/r/deployment.html.markdown | 1 + website/docs/r/pod.html.markdown | 1 + 10 files changed, 112 insertions(+), 4 deletions(-) diff --git a/kubernetes/resource_kubernetes_deployment_test.go b/kubernetes/resource_kubernetes_deployment_test.go index e208e32d07..4b1c322548 100644 --- a/kubernetes/resource_kubernetes_deployment_test.go +++ b/kubernetes/resource_kubernetes_deployment_test.go @@ -495,6 +495,7 @@ func TestAccKubernetesDeployment_with_volume_mount(t *testing.T) { resource.TestCheckResourceAttr(deploymentTestResourceName, "spec.0.template.0.spec.0.container.0.volume_mount.0.name", "db"), resource.TestCheckResourceAttr(deploymentTestResourceName, "spec.0.template.0.spec.0.container.0.volume_mount.0.read_only", "false"), resource.TestCheckResourceAttr(deploymentTestResourceName, "spec.0.template.0.spec.0.container.0.volume_mount.0.sub_path", ""), + resource.TestCheckResourceAttr(deploymentTestResourceName, "spec.0.template.0.spec.0.container.0.volume_mount.0.sub_path_expr", ""), ), }, }, diff --git a/kubernetes/resource_kubernetes_pod_test.go b/kubernetes/resource_kubernetes_pod_test.go index 02a8024c1a..138a5b82b0 100644 --- a/kubernetes/resource_kubernetes_pod_test.go +++ b/kubernetes/resource_kubernetes_pod_test.go @@ -490,6 +490,38 @@ func TestAccKubernetesPod_with_volume_mount(t *testing.T) { resource.TestCheckResourceAttr("kubernetes_pod.test", "spec.0.container.0.volume_mount.0.name", "db"), resource.TestCheckResourceAttr("kubernetes_pod.test", "spec.0.container.0.volume_mount.0.read_only", "false"), resource.TestCheckResourceAttr("kubernetes_pod.test", "spec.0.container.0.volume_mount.0.sub_path", ""), + resource.TestCheckResourceAttr("kubernetes_pod.test", "spec.0.container.0.volume_mount.0.sub_path_expr", ""), + resource.TestCheckResourceAttr("kubernetes_pod.test", "spec.0.container.0.volume_mount.0.mount_propagation", "HostToContainer"), + ), + }, + }, + }) +} + +func TestAccKubernetesPod_with_volume_mount_sub_path_expr(t *testing.T) { + var conf api.Pod + + podName := fmt.Sprintf("tf-acc-test-%s", acctest.RandStringFromCharSet(10, acctest.CharSetAlphaNum)) + secretName := fmt.Sprintf("tf-acc-test-%s", acctest.RandStringFromCharSet(10, acctest.CharSetAlphaNum)) + + imageName := "nginx:1.7.9" + + resource.Test(t, resource.TestCase{ + PreCheck: func() { testAccPreCheck(t) }, + Providers: testAccProviders, + CheckDestroy: testAccCheckKubernetesPodDestroy, + Steps: []resource.TestStep{ + { + Config: testAccKubernetesPodConfigWithVolumeMountsSubPathExpr(secretName, podName, imageName), + Check: resource.ComposeAggregateTestCheckFunc( + testAccCheckKubernetesPodExists("kubernetes_pod.test", &conf), + resource.TestCheckResourceAttr("kubernetes_pod.test", "spec.0.container.0.image", imageName), + resource.TestCheckResourceAttr("kubernetes_pod.test", "spec.0.container.0.volume_mount.#", "1"), + resource.TestCheckResourceAttr("kubernetes_pod.test", "spec.0.container.0.volume_mount.0.mount_path", "/tmp/my_path"), + resource.TestCheckResourceAttr("kubernetes_pod.test", "spec.0.container.0.volume_mount.0.name", "db"), + resource.TestCheckResourceAttr("kubernetes_pod.test", "spec.0.container.0.volume_mount.0.read_only", "false"), + resource.TestCheckResourceAttr("kubernetes_pod.test", "spec.0.container.0.volume_mount.0.sub_path", ""), + resource.TestCheckResourceAttr("kubernetes_pod.test", "spec.0.container.0.volume_mount.0.sub_path_expr", "$(POD_NAME)"), resource.TestCheckResourceAttr("kubernetes_pod.test", "spec.0.container.0.volume_mount.0.mount_propagation", "HostToContainer"), ), }, @@ -520,11 +552,13 @@ func TestAccKubernetesPod_with_cfg_map_volume_mount(t *testing.T) { resource.TestCheckResourceAttr("kubernetes_pod.test", "spec.0.container.0.volume_mount.0.name", "cfg"), resource.TestCheckResourceAttr("kubernetes_pod.test", "spec.0.container.0.volume_mount.0.read_only", "false"), resource.TestCheckResourceAttr("kubernetes_pod.test", "spec.0.container.0.volume_mount.0.sub_path", ""), + resource.TestCheckResourceAttr("kubernetes_pod.test", "spec.0.container.0.volume_mount.0.sub_path_expr", ""), resource.TestCheckResourceAttr("kubernetes_pod.test", "spec.0.container.0.volume_mount.0.mount_propagation", "None"), resource.TestCheckResourceAttr("kubernetes_pod.test", "spec.0.container.0.volume_mount.1.mount_path", "/tmp/my_raw_path"), resource.TestCheckResourceAttr("kubernetes_pod.test", "spec.0.container.0.volume_mount.1.name", "cfg-binary"), resource.TestCheckResourceAttr("kubernetes_pod.test", "spec.0.container.0.volume_mount.1.read_only", "false"), resource.TestCheckResourceAttr("kubernetes_pod.test", "spec.0.container.0.volume_mount.1.sub_path", ""), + resource.TestCheckResourceAttr("kubernetes_pod.test", "spec.0.container.0.volume_mount.1.sub_path_expr", ""), resource.TestCheckResourceAttr("kubernetes_pod.test", "spec.0.volume.0.name", "cfg"), resource.TestCheckResourceAttr("kubernetes_pod.test", "spec.0.volume.0.config_map.0.name", cfgMap), resource.TestCheckResourceAttr("kubernetes_pod.test", "spec.0.volume.0.config_map.0.default_mode", "0777")), @@ -1235,6 +1269,62 @@ resource "kubernetes_pod" "test" { `, secretName, podName, imageName) } +func testAccKubernetesPodConfigWithVolumeMountsSubPathExpr(secretName, podName, imageName string) string { + return fmt.Sprintf(` +resource "kubernetes_secret" "test" { + metadata { + name = "%s" + } + + data = { + one = "first" + } +} + +resource "kubernetes_pod" "test" { + metadata { + labels = { + app = "pod_label" + } + + name = "%s" + } + + spec { + container { + image = "%s" + name = "containername" + + env { + name = "POD_NAME" + value_from { + field_ref { + api_version = "v1" + field_path = "metadata.name" + } + } + } + + volume_mount { + mount_path = "/tmp/my_path" + name = "db" + mount_propagation = "HostToContainer" + sub_path_expr = "$(POD_NAME)" + } + } + + volume { + name = "db" + + secret { + secret_name = "${kubernetes_secret.test.metadata.0.name}" + } + } + } +} +`, secretName, podName, imageName) +} + func testAccKubernetesPodConfigWithSecretItemsVolume(secretName, podName, imageName string) string { return fmt.Sprintf(` resource "kubernetes_secret" "test" { diff --git a/kubernetes/resource_kubernetes_replication_controller_test.go b/kubernetes/resource_kubernetes_replication_controller_test.go index 3cf8350549..6149e6fb80 100644 --- a/kubernetes/resource_kubernetes_replication_controller_test.go +++ b/kubernetes/resource_kubernetes_replication_controller_test.go @@ -401,6 +401,7 @@ func TestAccKubernetesReplicationController_with_volume_mount(t *testing.T) { resource.TestCheckResourceAttr("kubernetes_replication_controller.test", "spec.0.template.0.spec.0.container.0.volume_mount.0.name", "db"), resource.TestCheckResourceAttr("kubernetes_replication_controller.test", "spec.0.template.0.spec.0.container.0.volume_mount.0.read_only", "false"), resource.TestCheckResourceAttr("kubernetes_replication_controller.test", "spec.0.template.0.spec.0.container.0.volume_mount.0.sub_path", ""), + resource.TestCheckResourceAttr("kubernetes_replication_controller.test", "spec.0.template.0.spec.0.container.0.volume_mount.0.sub_path_expr", ""), ), }, }, diff --git a/kubernetes/schema_container.go b/kubernetes/schema_container.go index b8356b86e9..443561138e 100644 --- a/kubernetes/schema_container.go +++ b/kubernetes/schema_container.go @@ -194,6 +194,11 @@ func volumeMountFields() map[string]*schema.Schema { Optional: true, Description: `Path within the volume from which the container's volume should be mounted. Defaults to "" (volume's root).`, }, + "sub_path_expr": { + Type: schema.TypeString, + Optional: true, + Description: `Expanded path within the volume from which the container's volume should be mounted. Behaves similarly to SubPath but environment variable references $(VAR_NAME) are expanded using the container's environment. Defaults to "" (volume's root). SubPathExpr and SubPath are mutually exclusive.`, + }, "mount_propagation": { Type: schema.TypeString, Description: "Mount propagation mode. mount_propagation determines how mounts are propagated from the host to container and the other way around. Valid values are None (default), HostToContainer and Bidirectional.", diff --git a/kubernetes/structures_container.go b/kubernetes/structures_container.go index c21e3710e7..b3925e22ac 100644 --- a/kubernetes/structures_container.go +++ b/kubernetes/structures_container.go @@ -270,6 +270,9 @@ func flattenContainerVolumeMounts(in []v1.VolumeMount) ([]interface{}, error) { if v.SubPath != "" { m["sub_path"] = v.SubPath } + if v.SubPathExpr != "" { + m["sub_path_expr"] = v.SubPathExpr + } if v.MountPropagation != nil { m["mount_propagation"] = string(*v.MountPropagation) } @@ -723,6 +726,9 @@ func expandContainerVolumeMounts(in []interface{}) ([]v1.VolumeMount, error) { if subPath, ok := p["sub_path"]; ok { vmp[i].SubPath = subPath.(string) } + if subPathExpr, ok := p["sub_path_expr"]; ok { + vmp[i].SubPathExpr = subPathExpr.(string) + } if mountPropagation, ok := p["mount_propagation"]; ok { mp := v1.MountPropagationMode(mountPropagation.(string)) vmp[i].MountPropagation = &mp diff --git a/website/docs/d/pod.html.markdown b/website/docs/d/pod.html.markdown index 0a0ae4e762..e1fd88a062 100644 --- a/website/docs/d/pod.html.markdown +++ b/website/docs/d/pod.html.markdown @@ -416,6 +416,7 @@ The `items` block supports the following: * `name` - This must match the Name of a Volume. * `read_only` - Mounted read-only if true, read-write otherwise (false or unspecified). Defaults to false. * `sub_path` - Path within the volume from which the container's volume should be mounted. Defaults to "" (volume's root). +* `sub_path_expr` - Expanded path within the volume from which the container's volume should be mounted. Behaves similarly to SubPath but environment variable references $(VAR_NAME) are expanded using the container's environment. Defaults to "" (volume's root). SubPathExpr and SubPath are mutually exclusive. * `mount_propagation` - Mount propagation mode. Defaults to "None". For more info see [Kubernetes reference](https://kubernetes.io/docs/concepts/storage/volumes/#mount-propagation) ## Argument Reference diff --git a/website/docs/guides/getting-started.html.markdown b/website/docs/guides/getting-started.html.markdown index 11fbcdbab8..9424d2be77 100644 --- a/website/docs/guides/getting-started.html.markdown +++ b/website/docs/guides/getting-started.html.markdown @@ -288,10 +288,11 @@ Terraform will perform the following actions: } + volume_mount { - + mount_path = (known after apply) - + name = (known after apply) - + read_only = (known after apply) - + sub_path = (known after apply) + + mount_path = (known after apply) + + name = (known after apply) + + read_only = (known after apply) + + sub_path = (known after apply) + + sub_path_expr = (known after apply) } } diff --git a/website/docs/r/daemonset.html.markdown b/website/docs/r/daemonset.html.markdown index 63a3d66232..2a8180d38f 100644 --- a/website/docs/r/daemonset.html.markdown +++ b/website/docs/r/daemonset.html.markdown @@ -793,6 +793,7 @@ The `items` block supports the following: * `name` - (Required) This must match the Name of a Volume. * `read_only` - (Optional) Mounted read-only if true, read-write otherwise (false or unspecified). Defaults to false. * `sub_path` - (Optional) Path within the volume from which the container's volume should be mounted. Defaults to "" (volume's root). +* `sub_path_expr` - (Optional) Expanded path within the volume from which the container's volume should be mounted. Behaves similarly to SubPath but environment variable references $(VAR_NAME) are expanded using the container's environment. Defaults to "" (volume's root). SubPathExpr and SubPath are mutually exclusive. * `mount_propagation` - (Optional) Mount propagation mode. Defaults to "None". For more info see [Kubernetes reference](https://kubernetes.io/docs/concepts/storage/volumes/#mount-propagation) ### `vsphere_volume` diff --git a/website/docs/r/deployment.html.markdown b/website/docs/r/deployment.html.markdown index 4a401b9098..83a9f8528c 100644 --- a/website/docs/r/deployment.html.markdown +++ b/website/docs/r/deployment.html.markdown @@ -799,6 +799,7 @@ The `items` block supports the following: * `name` - (Required) This must match the Name of a Volume. * `read_only` - (Optional) Mounted read-only if true, read-write otherwise (false or unspecified). Defaults to false. * `sub_path` - (Optional) Path within the volume from which the container's volume should be mounted. Defaults to "" (volume's root). +* `sub_path_expr` - (Optional) Expanded path within the volume from which the container's volume should be mounted. Behaves similarly to SubPath but environment variable references $(VAR_NAME) are expanded using the container's environment. Defaults to "" (volume's root). SubPathExpr and SubPath are mutually exclusive. * `mount_propagation` - (Optional) Mount propagation mode. Defaults to "None". For more info see [Kubernetes reference](https://kubernetes.io/docs/concepts/storage/volumes/#mount-propagation) ### `vsphere_volume` diff --git a/website/docs/r/pod.html.markdown b/website/docs/r/pod.html.markdown index b7c031e659..0c77235495 100644 --- a/website/docs/r/pod.html.markdown +++ b/website/docs/r/pod.html.markdown @@ -853,6 +853,7 @@ The `items` block supports the following: * `name` - (Required) This must match the Name of a Volume. * `read_only` - (Optional) Mounted read-only if true, read-write otherwise (false or unspecified). Defaults to false. * `sub_path` - (Optional) Path within the volume from which the container's volume should be mounted. Defaults to "" (volume's root). +* `sub_path_expr` - (Optional) Expanded path within the volume from which the container's volume should be mounted. Behaves similarly to SubPath but environment variable references $(VAR_NAME) are expanded using the container's environment. Defaults to "" (volume's root). SubPathExpr and SubPath are mutually exclusive. * `mount_propagation` - (Optional) Mount propagation mode. Defaults to "None". For more info see [Kubernetes reference](https://kubernetes.io/docs/concepts/storage/volumes/#mount-propagation) ### `vsphere_volume`