Skip to content

Commit

Permalink
feat: Support spec.persistentVolumeClaimRetentionPolicy in kubernetes…
Browse files Browse the repository at this point in the history
…_stateful_set (hashicorp#2333)

* feat: Support spec.persistentVolumeClaimRetentionPolicy in kubernetes_stateful_set

Signed-off-by: adinhodovic <[email protected]>

* add changelog-entry

---------

Signed-off-by: adinhodovic <[email protected]>
Co-authored-by: Mauricio Alvarez Leon <[email protected]>
Co-authored-by: BBBmau <[email protected]>
  • Loading branch information
3 people authored Dec 5, 2023
1 parent a7809cd commit 256472a
Show file tree
Hide file tree
Showing 6 changed files with 240 additions and 0 deletions.
3 changes: 3 additions & 0 deletions .changelog/2333.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
```release-note:enhancement
`kubernetes/schema_stateful_set_spec.go`: Add `spec.persistentVolumeClaimRetentionPolicy` in `kubernetes_stateful_set`
```
112 changes: 112 additions & 0 deletions kubernetes/resource_kubernetes_stateful_set_v1_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -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"),
Expand Down Expand Up @@ -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"),
),
},
},
})
}
Expand Down Expand Up @@ -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 = {
Expand Down Expand Up @@ -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)
}
30 changes: 30 additions & 0 deletions kubernetes/schema_stateful_set_spec.go
Original file line number Diff line number Diff line change
Expand Up @@ -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
}
65 changes: 65 additions & 0 deletions kubernetes/structures_stateful_set.go
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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{})

Expand Down Expand Up @@ -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
}

Expand Down Expand Up @@ -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) {
Expand Down Expand Up @@ -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
}

Expand Down
15 changes: 15 additions & 0 deletions website/docs/r/stateful_set.html.markdown
Original file line number Diff line number Diff line change
Expand Up @@ -204,6 +204,11 @@ resource "kubernetes_stateful_set" "prometheus" {
}
}
}
persistent_volume_claim_retention_policy {
when_deleted = "Delete"
when_scaled = "Delete"
}
}
}
```
Expand Down Expand Up @@ -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`
Expand Down Expand Up @@ -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:
Expand Down
15 changes: 15 additions & 0 deletions website/docs/r/stateful_set_v1.html.markdown
Original file line number Diff line number Diff line change
Expand Up @@ -204,6 +204,11 @@ resource "kubernetes_stateful_set_v1" "prometheus" {
}
}
}
persistent_volume_claim_retention_policy {
when_deleted = "Delete"
when_scaled = "Delete"
}
}
}
```
Expand Down Expand Up @@ -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`
Expand Down Expand Up @@ -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:
Expand Down

0 comments on commit 256472a

Please sign in to comment.