From 01f6171db64bf3b57f61f6942b6a910905fd1b8a Mon Sep 17 00:00:00 2001 From: Alex Somesan Date: Thu, 17 Oct 2024 13:56:56 +0200 Subject: [PATCH] Fix restart_policy validation in Deployment (#2595) Fix validation of restart_policy in Deployment's pod template --- .changelog/2595.txt | 3 + .github/workflows/documentation-check.yaml | 2 +- docs/resources/deployment_v1.md | 2 +- .../resource_kubernetes_deployment_v1.go | 13 +++- .../resource_kubernetes_deployment_v1_test.go | 63 +++++++++++++++++++ 5 files changed, 80 insertions(+), 3 deletions(-) create mode 100644 .changelog/2595.txt diff --git a/.changelog/2595.txt b/.changelog/2595.txt new file mode 100644 index 0000000000..2f31c97a50 --- /dev/null +++ b/.changelog/2595.txt @@ -0,0 +1,3 @@ +```release-note:improvement +resource/kubernetes_deployment_v1: Fix validation of `restart_policy` values +``` \ No newline at end of file diff --git a/.github/workflows/documentation-check.yaml b/.github/workflows/documentation-check.yaml index bdc29395f1..b3476f61e1 100644 --- a/.github/workflows/documentation-check.yaml +++ b/.github/workflows/documentation-check.yaml @@ -37,6 +37,6 @@ jobs: - name: Undocumented changes run: | - echo "Documentation is not up to date. Please refer to the `Making Changes` in the Contribution Guide on how to properly update documentation." + echo 'Documentation is not up to date. Please refer to the `Making Changes` in the Contribution Guide on how to properly update documentation.' exit 1 if: failure() \ No newline at end of file diff --git a/docs/resources/deployment_v1.md b/docs/resources/deployment_v1.md index 1ba1ae283c..049de98022 100644 --- a/docs/resources/deployment_v1.md +++ b/docs/resources/deployment_v1.md @@ -111,7 +111,7 @@ Optional: - `os` (Block List, Max: 1) Specifies the OS of the containers in the pod. (see [below for nested schema](#nestedblock--spec--template--spec--os)) - `priority_class_name` (String) If specified, indicates the pod's priority. "system-node-critical" and "system-cluster-critical" are two special keywords which indicate the highest priorities with the former being the highest priority. Any other name must be defined by creating a PriorityClass object with that name. If not specified, the pod priority will be default or zero if there is no default. - `readiness_gate` (Block List) If specified, all readiness gates will be evaluated for pod readiness. A pod is ready when all its containers are ready AND all conditions specified in the readiness gates have status equal to "True" More info: https://git.k8s.io/enhancements/keps/sig-network/0007-pod-ready%2B%2B.md (see [below for nested schema](#nestedblock--spec--template--spec--readiness_gate)) -- `restart_policy` (String) Restart policy for all containers within the pod. One of Always, OnFailure, Never. More info: https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle/#restart-policy. +- `restart_policy` (String) Restart policy for all containers within the pod. Defaults to Always as the only option. More info: https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle/#restart-policy. - `runtime_class_name` (String) RuntimeClassName is a feature for selecting the container runtime configuration. The container runtime configuration is used to run a Pod's containers. More info: https://kubernetes.io/docs/concepts/containers/runtime-class - `scheduler_name` (String) If specified, the pod will be dispatched by specified scheduler. If not specified, the pod will be dispatched by default scheduler. - `security_context` (Block List, Max: 1) SecurityContext holds pod-level security attributes and common container settings. Optional: Defaults to empty (see [below for nested schema](#nestedblock--spec--template--spec--security_context)) diff --git a/kubernetes/resource_kubernetes_deployment_v1.go b/kubernetes/resource_kubernetes_deployment_v1.go index a28338ff22..22749666be 100644 --- a/kubernetes/resource_kubernetes_deployment_v1.go +++ b/kubernetes/resource_kubernetes_deployment_v1.go @@ -16,6 +16,7 @@ import ( "github.com/hashicorp/terraform-plugin-sdk/v2/helper/validation" appsv1 "k8s.io/api/apps/v1" + corev1 "k8s.io/api/core/v1" "k8s.io/apimachinery/pkg/api/errors" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/types" @@ -199,7 +200,7 @@ func resourceKubernetesDeploymentSchemaV1() map[string]*schema.Schema { Required: true, MaxItems: 1, Elem: &schema.Resource{ - Schema: podSpecFields(true, false), + Schema: deploymentPodTemplateSpecFields(), }, }, }, @@ -217,6 +218,16 @@ func resourceKubernetesDeploymentSchemaV1() map[string]*schema.Schema { } } +func deploymentPodTemplateSpecFields() map[string]*schema.Schema { + psf := podSpecFields(true, false) + rp := psf["restart_policy"] + rp.ValidateFunc = validation.StringInSlice([]string{ + string(corev1.RestartPolicyAlways), + }, false) + rp.Description = "Restart policy for all containers within the pod. Defaults to Always as the only option. More info: https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle/#restart-policy." + return psf +} + func resourceKubernetesDeploymentV1Create(ctx context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics { conn, err := meta.(KubeClientsets).MainClientset() if err != nil { diff --git a/kubernetes/resource_kubernetes_deployment_v1_test.go b/kubernetes/resource_kubernetes_deployment_v1_test.go index d93c716420..85872dec7e 100644 --- a/kubernetes/resource_kubernetes_deployment_v1_test.go +++ b/kubernetes/resource_kubernetes_deployment_v1_test.go @@ -1225,6 +1225,36 @@ func TestAccKubernetesDeploymentV1_config_with_automount_service_account_token(t }) } +func TestAccKubernetesDeploymentV1_with_restart_policy(t *testing.T) { + var conf appsv1.Deployment + name := fmt.Sprintf("tf-acc-test-%s", acctest.RandStringFromCharSet(10, acctest.CharSetAlphaNum)) + resourceName := "kubernetes_deployment_v1.test" + imageName := busyboxImage + + resource.ParallelTest(t, resource.TestCase{ + PreCheck: func() { testAccPreCheck(t) }, + IDRefreshName: resourceName, + IDRefreshIgnore: []string{"metadata.0.resource_version"}, + ProviderFactories: testAccProviderFactories, + CheckDestroy: testAccCheckKubernetesDeploymentV1Destroy, + Steps: []resource.TestStep{ + { + Config: testAccKubernetesDeploymentV1Config_with_restart_policy(name, imageName, "Never"), + ExpectError: regexp.MustCompile("expected spec\\.0\\.template\\.0\\.spec\\.0\\.restart_policy to be one of \\[\"Always\"\\], got Never"), + }, + { + Config: testAccKubernetesDeploymentV1Config_with_restart_policy(name, imageName, "Always"), + Check: resource.ComposeAggregateTestCheckFunc( + testAccCheckKubernetesDeploymentV1Exists(resourceName, &conf), + resource.TestCheckResourceAttrSet(resourceName, "metadata.0.generation"), + resource.TestCheckResourceAttrSet(resourceName, "metadata.0.resource_version"), + resource.TestCheckResourceAttrSet(resourceName, "metadata.0.uid"), + ), + }, + }, + }) +} + func testAccCheckKubernetesDeploymentForceNew(old, new *appsv1.Deployment, wantNew bool) resource.TestCheckFunc { return func(s *terraform.State) error { if wantNew { @@ -1409,6 +1439,39 @@ func testAccKubernetesDeploymentV1Config_basic(name, imageName string) string { `, name, imageName) } +func testAccKubernetesDeploymentV1Config_with_restart_policy(name, imageName, restartPolicy string) string { + return fmt.Sprintf(`resource "kubernetes_deployment_v1" "test" { + metadata { + name = "%s" + } + spec { + replicas = 2 + selector { + match_labels = { + TestLabelOne = "one" + } + } + template { + metadata { + labels = { + TestLabelOne = "one" + } + } + spec { + container { + image = "%s" + name = "tf-acc-test" + command = ["sleep", "300"] + } + restart_policy = "%s" + termination_grace_period_seconds = 1 + } + } + } +} +`, name, imageName, restartPolicy) +} + func testAccKubernetesDeploymentV1Config_initContainer(namespace, name, imageName, imageName1, memory, envName, initName, initCommand, pullPolicy string) string { return fmt.Sprintf(`resource "kubernetes_namespace_v1" "test" { metadata {