From 256472ab67278a5e1b64b0a0f7cca95d88498d36 Mon Sep 17 00:00:00 2001 From: Adin Hodovic Date: Tue, 5 Dec 2023 13:35:02 +0100 Subject: [PATCH] feat: Support spec.persistentVolumeClaimRetentionPolicy in kubernetes_stateful_set (#2333) * feat: Support spec.persistentVolumeClaimRetentionPolicy in kubernetes_stateful_set Signed-off-by: adinhodovic * add changelog-entry --------- Signed-off-by: adinhodovic Co-authored-by: Mauricio Alvarez Leon <65101411+BBBmau@users.noreply.github.com> Co-authored-by: BBBmau --- .changelog/2333.txt | 3 + ...esource_kubernetes_stateful_set_v1_test.go | 112 ++++++++++++++++++ kubernetes/schema_stateful_set_spec.go | 30 +++++ kubernetes/structures_stateful_set.go | 65 ++++++++++ website/docs/r/stateful_set.html.markdown | 15 +++ website/docs/r/stateful_set_v1.html.markdown | 15 +++ 6 files changed, 240 insertions(+) create mode 100644 .changelog/2333.txt diff --git a/.changelog/2333.txt b/.changelog/2333.txt new file mode 100644 index 0000000000..38595ba14e --- /dev/null +++ b/.changelog/2333.txt @@ -0,0 +1,3 @@ +```release-note:enhancement +`kubernetes/schema_stateful_set_spec.go`: Add `spec.persistentVolumeClaimRetentionPolicy` in `kubernetes_stateful_set` +``` \ No newline at end of file diff --git a/kubernetes/resource_kubernetes_stateful_set_v1_test.go b/kubernetes/resource_kubernetes_stateful_set_v1_test.go index 9c8e6c19c5..5e185d0b13 100644 --- a/kubernetes/resource_kubernetes_stateful_set_v1_test.go +++ b/kubernetes/resource_kubernetes_stateful_set_v1_test.go @@ -78,6 +78,8 @@ func TestAccKubernetesStatefulSetV1_basic(t *testing.T) { resource.TestCheckResourceAttr(resourceName, "spec.0.replicas", "1"), resource.TestCheckResourceAttr(resourceName, "spec.0.revision_history_limit", "11"), resource.TestCheckResourceAttr(resourceName, "spec.0.service_name", "ss-test-service"), + resource.TestCheckResourceAttr(resourceName, "spec.0.persistent_volume_claim_retention_policy.0.when_deleted", "Delete"), + resource.TestCheckResourceAttr(resourceName, "spec.0.persistent_volume_claim_retention_policy.0.when_scaled", "Delete"), resource.TestCheckResourceAttr(resourceName, "spec.0.selector.0.match_labels.%", "1"), resource.TestCheckResourceAttr(resourceName, "spec.0.selector.0.match_labels.app", "ss-test"), resource.TestCheckResourceAttr(resourceName, "spec.0.template.0.metadata.#", "1"), @@ -273,6 +275,15 @@ func TestAccKubernetesStatefulSetV1_Update(t *testing.T) { resource.TestCheckResourceAttr(resourceName, "spec.0.template.0.spec.0.dns_policy", "Default"), ), }, + { + Config: testAccKubernetesStatefulSetV1ConfigUpdatePersistentVolumeClaimRetentionPolicy(name, imageName), + Check: resource.ComposeAggregateTestCheckFunc( + testAccCheckKubernetesStatefulSetV1Exists(resourceName, &conf), + resource.TestCheckResourceAttr(resourceName, "metadata.0.name", name), + resource.TestCheckResourceAttr(resourceName, "spec.0.persistent_volume_claim_retention_policy.0.when_deleted", "Retain"), + resource.TestCheckResourceAttr(resourceName, "spec.0.persistent_volume_claim_retention_policy.0.when_scaled", "Retain"), + ), + }, }, }) } @@ -482,6 +493,11 @@ func testAccKubernetesStatefulSetV1ConfigBasic(name, imageName string) string { service_name = "ss-test-service" + persistent_volume_claim_retention_policy { + when_deleted = "Delete" + when_scaled = "Delete" + } + template { metadata { labels = { @@ -1132,3 +1148,99 @@ func testAccKubernetesStatefulSetV1ConfigWaitForRollout(name, imageName, waitFor } `, name, imageName, waitForRollout) } + +func testAccKubernetesStatefulSetV1ConfigUpdatePersistentVolumeClaimRetentionPolicy(name, imageName string) string { + return fmt.Sprintf(`resource "kubernetes_stateful_set_v1" "test" { + metadata { + annotations = { + TestAnnotationOne = "one" + TestAnnotationTwo = "two" + } + + labels = { + TestLabelOne = "one" + TestLabelTwo = "two" + TestLabelThree = "three" + } + + name = "%s" + } + + spec { + pod_management_policy = "OrderedReady" + replicas = 1 + revision_history_limit = 11 + + selector { + match_labels = { + app = "ss-test" + } + } + + service_name = "ss-test-service" + + persistent_volume_claim_retention_policy { + when_deleted = "Retain" + when_scaled = "Retain" + } + + template { + metadata { + labels = { + app = "ss-test" + } + } + + spec { + container { + name = "ss-test" + image = %q + args = ["test-webserver"] + + port { + name = "web" + container_port = 80 + } + + readiness_probe { + initial_delay_seconds = 5 + http_get { + path = "/" + port = 80 + } + } + + volume_mount { + name = "ss-test" + mount_path = "/work-dir" + } + } + } + } + + update_strategy { + type = "RollingUpdate" + + rolling_update { + partition = 1 + } + } + + volume_claim_template { + metadata { + name = "ss-test" + } + + spec { + access_modes = ["ReadWriteOnce"] + resources { + requests = { + storage = "1Gi" + } + } + } + } + } +} +`, name, imageName) +} diff --git a/kubernetes/schema_stateful_set_spec.go b/kubernetes/schema_stateful_set_spec.go index ba6856a6be..81b6ce8a5b 100644 --- a/kubernetes/schema_stateful_set_spec.go +++ b/kubernetes/schema_stateful_set_spec.go @@ -104,6 +104,36 @@ func statefulSetSpecFields() map[string]*schema.Schema { Schema: persistentVolumeClaimFields(), }, }, + "persistent_volume_claim_retention_policy": { + Type: schema.TypeList, + Optional: true, + Computed: true, + Description: "The field controls if and how PVCs are deleted during the lifecycle of a StatefulSet.", + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "when_deleted": { + Type: schema.TypeString, + Description: "This field controls what happens when a Statefulset is deleted. Default is Retain.", + Optional: true, + Default: "Retain", + ValidateFunc: validation.StringInSlice([]string{ + "Retain", + "Delete", + }, false), + }, + "when_scaled": { + Type: schema.TypeString, + Description: "This field controls what happens when a Statefulset is scaled. Default is Retain.", + Optional: true, + Default: "Retain", + ValidateFunc: validation.StringInSlice([]string{ + "Retain", + "Delete", + }, false), + }, + }, + }, + }, } return s } diff --git a/kubernetes/structures_stateful_set.go b/kubernetes/structures_stateful_set.go index af72e7dafc..61f5923e0b 100644 --- a/kubernetes/structures_stateful_set.go +++ b/kubernetes/structures_stateful_set.go @@ -55,6 +55,14 @@ func expandStatefulSetSpec(s []interface{}) (*v1.StatefulSetSpec, error) { obj.UpdateStrategy = *us } + if v, ok := in["persistent_volume_claim_retention_policy"].([]interface{}); ok { + ret, err := expandStatefulSetSpecPersistentVolumeClaimRetentionPolicy(v) + if err != nil { + return obj, err + } + obj.PersistentVolumeClaimRetentionPolicy = ret + } + template, err := expandPodTemplate(in["template"].([]interface{})) if err != nil { return obj, err @@ -111,6 +119,31 @@ func expandStatefulSetSpecUpdateStrategy(s []interface{}) (*v1.StatefulSetUpdate return ust, nil } +func expandStatefulSetSpecPersistentVolumeClaimRetentionPolicy(s []interface{}) (*v1.StatefulSetPersistentVolumeClaimRetentionPolicy, error) { + retPolicySpec := &v1.StatefulSetPersistentVolumeClaimRetentionPolicy{} + if len(s) == 0 { + return retPolicySpec, nil + } + retPolicy, ok := s[0].(map[string]interface{}) + if !ok { + return retPolicySpec, errors.New("failed to expand 'spec.persistent_volume_claim_retention_policy'") + } + retWd, ok := retPolicy["when_deleted"].(string) + if !ok { + return retPolicySpec, errors.New("failed to expand 'spec.persistent_volume_claim_retention_policy.when_deleted'") + } + retPolicySpec.WhenDeleted = v1.PersistentVolumeClaimRetentionPolicyType(retWd) + + retWs, ok := retPolicy["when_scaled"].(string) + if !ok { + return retPolicySpec, errors.New("failed to expand 'spec.persistent_volume_claim_retention_policy.when_scaled'") + } + retPolicySpec.WhenScaled = v1.PersistentVolumeClaimRetentionPolicyType(retWs) + + log.Printf("[DEBUG] Expanded StatefulSet.Spec.PersistentVolumeClaimRetentionPolicy: %#v", retPolicySpec) + return retPolicySpec, nil +} + func flattenStatefulSetSpec(spec v1.StatefulSetSpec, d *schema.ResourceData, meta interface{}) ([]interface{}, error) { att := make(map[string]interface{}) @@ -143,6 +176,10 @@ func flattenStatefulSetSpec(spec v1.StatefulSetSpec, d *schema.ResourceData, met att["update_strategy"] = flattenStatefulSetSpecUpdateStrategy(spec.UpdateStrategy) } + if spec.PersistentVolumeClaimRetentionPolicy != nil { + att["persistent_volume_claim_retention_policy"] = flattenStatefulSetSpecPersistentVolumeClaimRetentionPolicy(*spec.PersistentVolumeClaimRetentionPolicy) + } + return []interface{}{att}, nil } @@ -185,6 +222,18 @@ func flattenStatefulSetSpecUpdateStrategy(s v1.StatefulSetUpdateStrategy) []inte return []interface{}{att} } +func flattenStatefulSetSpecPersistentVolumeClaimRetentionPolicy(s v1.StatefulSetPersistentVolumeClaimRetentionPolicy) []interface{} { + ret := make(map[string]interface{}) + + if s.WhenDeleted != "" { + ret["when_deleted"] = s.WhenDeleted + } + if s.WhenScaled != "" { + ret["when_scaled"] = s.WhenScaled + } + return []interface{}{ret} +} + // Patchers func patchStatefulSetSpec(d *schema.ResourceData) (PatchOperations, error) { @@ -224,6 +273,22 @@ func patchStatefulSetSpec(d *schema.ResourceData) (PatchOperations, error) { } ops = append(ops, u...) } + + if d.HasChange("spec.0.persistent_volume_claim_retention_policy") { + log.Printf("[TRACE] StatefulSet.Spec.PersistentVolumeClaimRetentionPolicy has changes") + if wd, ok := d.Get("spec.0.persistent_volume_claim_retention_policy.0.when_deleted").(string); ok && wd != "" { + ops = append(ops, &ReplaceOperation{ + Path: "/spec/persistentVolumeClaimRetentionPolicy/whenDeleted", + Value: wd, + }) + } + if ws, ok := d.Get("spec.0.persistent_volume_claim_retention_policy.0.when_scaled").(string); ok && ws != "" { + ops = append(ops, &ReplaceOperation{ + Path: "/spec/persistentVolumeClaimRetentionPolicy/whenScaled", + Value: ws, + }) + } + } return ops, nil } diff --git a/website/docs/r/stateful_set.html.markdown b/website/docs/r/stateful_set.html.markdown index a5766ebfb3..cc5a06fcb0 100644 --- a/website/docs/r/stateful_set.html.markdown +++ b/website/docs/r/stateful_set.html.markdown @@ -204,6 +204,11 @@ resource "kubernetes_stateful_set" "prometheus" { } } } + + persistent_volume_claim_retention_policy { + when_deleted = "Delete" + when_scaled = "Delete" + } } } ``` @@ -260,6 +265,8 @@ The following arguments are supported: * `volume_claim_template` - (Optional) A list of volume claims that pods are allowed to reference. A claim in this list takes precedence over any volumes in the template, with the same name. *Changing this forces a new resource to be created.* +* `persistent_volume_claim_retention_policy` - (Optional) The object controls if and how PVCs are deleted during the lifecycle of a StatefulSet. + ## Nested Blocks ### `spec.template` @@ -309,6 +316,14 @@ Each takes the same attibutes as a `kubernetes_persistent_volume_claim` resource Please see its [documentation](persistent_volume_claim.html#argument-reference) for reference. +### `spec.persistent_volume_claim_retention_policy` + +#### Arguments + +* `when_deleted` - (Optional) This field controls what happens when a Statefulset is deleted. Default is Retain. + +* `when_scaled` - (Optional) This field controls what happens when a Statefulset is scaled. Default is Retain. + ## Timeouts The following [Timeout](/docs/configuration/resources.html#operation-timeouts) configuration options are available for the `kubernetes_stateful_set` resource: diff --git a/website/docs/r/stateful_set_v1.html.markdown b/website/docs/r/stateful_set_v1.html.markdown index 1fbcc495c2..ab832c96c0 100644 --- a/website/docs/r/stateful_set_v1.html.markdown +++ b/website/docs/r/stateful_set_v1.html.markdown @@ -204,6 +204,11 @@ resource "kubernetes_stateful_set_v1" "prometheus" { } } } + + persistent_volume_claim_retention_policy { + when_deleted = "Delete" + when_scaled = "Delete" + } } } ``` @@ -260,6 +265,8 @@ The following arguments are supported: * `volume_claim_template` - (Optional) A list of volume claims that pods are allowed to reference. A claim in this list takes precedence over any volumes in the template, with the same name. *Changing this forces a new resource to be created.* +* `persistent_volume_claim_retention_policy` - (Optional) The object controls if and how PVCs are deleted during the lifecycle of a StatefulSet. + ## Nested Blocks ### `spec.template` @@ -309,6 +316,14 @@ Each takes the same attibutes as a `kubernetes_persistent_volume_claim_v1` resou Please see its [documentation](persistent_volume_claim_v1.html#argument-reference) for reference. +### `spec.persistent_volume_claim_retention_policy` + +#### Arguments + +* `when_deleted` - (Optional) This field controls what happens when a Statefulset is deleted. Default is Retain. + +* `when_scaled` - (Optional) This field controls what happens when a Statefulset is scaled. Default is Retain. + ## Timeouts The following [Timeout](/docs/configuration/resources.html#operation-timeouts) configuration options are available for the `kubernetes_stateful_set_v1` resource: