From 61520b44dea2d086e8025521fdb7d312d72e0632 Mon Sep 17 00:00:00 2001 From: gram-signal <84339875+gram-signal@users.noreply.github.com> Date: Fri, 12 Jan 2024 17:13:20 -0700 Subject: [PATCH] Allow HugePages in emptyDir.medium. (#2395) * Allow HugePages in emptyDir.medium. * Add acceptance test for HugePages-1Gi. * Reformat. * add changelog-entry --------- Co-authored-by: BBBmau --- .changelog/2395.txt | 3 + .../resource_kubernetes_deployment_v1_test.go | 80 +++++++++++++++++++ kubernetes/schema_pod_spec.go | 26 +++--- 3 files changed, 100 insertions(+), 9 deletions(-) create mode 100644 .changelog/2395.txt diff --git a/.changelog/2395.txt b/.changelog/2395.txt new file mode 100644 index 0000000000..0a26cf26a6 --- /dev/null +++ b/.changelog/2395.txt @@ -0,0 +1,3 @@ +```release-note:enhancement +`kubernetes/kubernetes_deployment_v1`: Add support for `HugePages` in `emptyDir.medium` +``` \ No newline at end of file diff --git a/kubernetes/resource_kubernetes_deployment_v1_test.go b/kubernetes/resource_kubernetes_deployment_v1_test.go index 41786efb83..d93c716420 100644 --- a/kubernetes/resource_kubernetes_deployment_v1_test.go +++ b/kubernetes/resource_kubernetes_deployment_v1_test.go @@ -820,6 +820,33 @@ func TestAccKubernetesDeploymentV1_with_empty_dir_volume(t *testing.T) { }) } +func TestAccKubernetesDeploymentV1_with_empty_dir_huge_page(t *testing.T) { + var conf appsv1.Deployment + + imageName := busyboxImage + deploymentName := fmt.Sprintf("tf-acc-test-%s", acctest.RandStringFromCharSet(10, acctest.CharSetAlphaNum)) + resourceName := "kubernetes_deployment_v1.test" + + resource.ParallelTest(t, resource.TestCase{ + PreCheck: func() { testAccPreCheck(t) }, + ProviderFactories: testAccProviderFactories, + CheckDestroy: testAccCheckKubernetesDeploymentV1Destroy, + Steps: []resource.TestStep{ + { + Config: testAccKubernetesDeploymentV1ConfigWithEmptyDirHugePage(deploymentName, imageName), + Check: resource.ComposeAggregateTestCheckFunc( + testAccCheckKubernetesDeploymentV1Exists(resourceName, &conf), + resource.TestCheckResourceAttr(resourceName, "spec.0.template.0.spec.0.container.0.image", imageName), + resource.TestCheckResourceAttr(resourceName, "spec.0.template.0.spec.0.container.0.volume_mount.#", "1"), + resource.TestCheckResourceAttr(resourceName, "spec.0.template.0.spec.0.container.0.volume_mount.0.mount_path", "/cache"), + resource.TestCheckResourceAttr(resourceName, "spec.0.template.0.spec.0.container.0.volume_mount.0.name", "cache-volume"), + resource.TestCheckResourceAttr(resourceName, "spec.0.template.0.spec.0.volume.0.empty_dir.0.medium", "HugePages-1Gi"), + ), + }, + }, + }) +} + func TestAccKubernetesDeploymentV1Update_basic(t *testing.T) { var conf1, conf2 appsv1.Deployment resourceName := "kubernetes_deployment_v1.test" @@ -2608,6 +2635,59 @@ func testAccKubernetesDeploymentV1ConfigWithEmptyDirVolumes(deploymentName, imag `, deploymentName, imageName) } +func testAccKubernetesDeploymentV1ConfigWithEmptyDirHugePage(deploymentName, imageName string) string { + return fmt.Sprintf(`resource "kubernetes_deployment_v1" "test" { + metadata { + name = "%s" + + labels = { + Test = "TfAcceptanceTest" + } + } + + spec { + replicas = 0 # We request zero replicas, since the K8S backing this test may not have huge pages available. + selector { + match_labels = { + Test = "TfAcceptanceTest" + } + } + + template { + metadata { + labels = { + Test = "TfAcceptanceTest" + } + } + + spec { + container { + image = "%s" + name = "containername" + command = ["sleep", "300"] + + volume_mount { + mount_path = "/cache" + name = "cache-volume" + } + } + + volume { + name = "cache-volume" + + empty_dir { + medium = "HugePages-1Gi" + } + } + + termination_grace_period_seconds = 1 + } + } + } +} +`, deploymentName, imageName) +} + func testAccKubernetesDeploymentV1ConfigWithEmptyDirVolumesModified(deploymentName, imageName string) string { return fmt.Sprintf(`resource "kubernetes_deployment_v1" "test" { metadata { diff --git a/kubernetes/schema_pod_spec.go b/kubernetes/schema_pod_spec.go index 50103582df..2feade4525 100644 --- a/kubernetes/schema_pod_spec.go +++ b/kubernetes/schema_pod_spec.go @@ -4,6 +4,8 @@ package kubernetes import ( + "fmt" + corev1 "k8s.io/api/core/v1" "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" @@ -707,6 +709,15 @@ func volumeSchema(isUpdatable bool) *schema.Resource { }, } + validEmptyDirMediums := []string{ + string(corev1.StorageMediumDefault), + string(corev1.StorageMediumMemory), + string(corev1.StorageMediumHugePages), + // This is possibly not an exhaustive list, but it does cover the + // common cases from x86_64 architectures. + string(corev1.StorageMediumHugePagesPrefix) + "2Mi", + string(corev1.StorageMediumHugePagesPrefix) + "1Gi", + } v["empty_dir"] = &schema.Schema{ Type: schema.TypeList, Description: "EmptyDir represents a temporary directory that shares a pod's lifetime. More info: https://kubernetes.io/docs/concepts/storage/volumes#emptydir", @@ -715,15 +726,12 @@ func volumeSchema(isUpdatable bool) *schema.Resource { Elem: &schema.Resource{ Schema: map[string]*schema.Schema{ "medium": { - Type: schema.TypeString, - Description: `What type of storage medium should back this directory. The default is "" which means to use the node's default medium. Must be an empty string (default) or Memory. More info: https://kubernetes.io/docs/concepts/storage/volumes#emptydir`, - Optional: true, - Default: "", - ForceNew: !isUpdatable, - ValidateFunc: validation.StringInSlice([]string{ - string(corev1.StorageMediumDefault), - string(corev1.StorageMediumMemory), - }, false), + Type: schema.TypeString, + Description: fmt.Sprintf(`What type of storage medium should back this directory. The default is "" which means to use the node's default medium. Must be one of %q. More info: https://kubernetes.io/docs/concepts/storage/volumes#emptydir`, validEmptyDirMediums), + Optional: true, + Default: "", + ForceNew: !isUpdatable, + ValidateFunc: validation.StringInSlice(validEmptyDirMediums, false), }, "size_limit": { Type: schema.TypeString,