Skip to content

Commit 550e917

Browse files
authored
Change replicas to TypeString for statefulset and deployment (#1079)
* Change replicas to TypeString for statefulset and deployment * Fix metadata bug in statefulset
1 parent 647bf73 commit 550e917

10 files changed

+109
-61
lines changed

kubernetes/resource_kubernetes_deployment.go

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -68,10 +68,11 @@ func resourceKubernetesDeployment() *schema.Resource {
6868
Default: 600,
6969
},
7070
"replicas": {
71-
Type: schema.TypeInt,
72-
Description: "The number of desired replicas. Defaults to 1. More info: http://kubernetes.io/docs/user-guide/replication-controller#what-is-a-replication-controller",
73-
Optional: true,
74-
Default: 1,
71+
Type: schema.TypeString,
72+
Description: "Number of desired pods. This is a string to be able to distinguish between explicit zero and not specified.",
73+
Optional: true,
74+
Computed: true,
75+
ValidateFunc: validateTypeStringNullableInt,
7576
},
7677
"revision_history_limit": {
7778
Type: schema.TypeInt,

kubernetes/resource_kubernetes_deployment_test.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -989,7 +989,7 @@ func TestAccKubernetesDeployment_with_resource_field_selector(t *testing.T) {
989989
Check: resource.ComposeAggregateTestCheckFunc(
990990
testAccCheckKubernetesDeploymentExists("kubernetes_deployment.test", &conf),
991991
resource.TestCheckResourceAttr("kubernetes_deployment.test", "spec.0.template.0.spec.0.container.0.image", imageName),
992-
resource.TestCheckResourceAttr("kubernetes_deployment.test", "spec.0.template.0.spec.0.container.0.resources.0.limits.0.memory", "512Mi"),
992+
resource.TestCheckResourceAttr("kubernetes_deployment.test", "spec.0.template.0.spec.0.container.0.resources.0.limits.memory", "512Mi"),
993993
resource.TestCheckResourceAttr("kubernetes_deployment.test", "spec.0.template.0.spec.0.container.0.env.#", "1"),
994994
resource.TestCheckResourceAttr("kubernetes_deployment.test", "spec.0.template.0.spec.0.container.0.env.0.name", "K8S_LIMITS_CPU"),
995995
resource.TestCheckResourceAttr("kubernetes_deployment.test", "spec.0.template.0.spec.0.container.0.env.0.value_from.0.resource_field_ref.0.container_name", "containername"),
@@ -2528,7 +2528,7 @@ func testAccKubernetesDeploymentConfigWithResourceFieldSelector(rcName, imageNam
25282528
image = "%s"
25292529
name = "containername"
25302530
resources {
2531-
limits {
2531+
limits = {
25322532
memory = "512Mi"
25332533
}
25342534
}

kubernetes/resource_kubernetes_stateful_set.go

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -98,7 +98,6 @@ func resourceKubernetesStatefulSetCreate(ctx context.Context, d *schema.Resource
9898
if err != nil {
9999
return diag.FromErr(err)
100100
}
101-
return diag.Diagnostics{}
102101
}
103102

104103
return resourceKubernetesStatefulSetRead(ctx, d, meta)

kubernetes/resource_kubernetes_stateful_set_test.go

Lines changed: 68 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -28,8 +28,8 @@ func TestAccKubernetesStatefulSet_basic(t *testing.T) {
2828
Config: testAccKubernetesStatefulSetConfigBasic(name),
2929
Check: resource.ComposeAggregateTestCheckFunc(
3030
testAccCheckKubernetesStatefulSetExists("kubernetes_stateful_set.test", &conf),
31-
testAccCheckKubernetesStatefulSetRollingOut("kubernetes_stateful_set.test"),
32-
resource.TestCheckResourceAttr("kubernetes_stateful_set.test", "wait_for_rollout", "false"),
31+
testAccCheckKubernetesStatefulSetRolledOut("kubernetes_stateful_set.test"),
32+
resource.TestCheckResourceAttr("kubernetes_stateful_set.test", "wait_for_rollout", "true"),
3333
resource.TestCheckResourceAttrSet("kubernetes_stateful_set.test", "metadata.0.generation"),
3434
resource.TestCheckResourceAttrSet("kubernetes_stateful_set.test", "metadata.0.resource_version"),
3535
resource.TestCheckResourceAttrSet("kubernetes_stateful_set.test", "metadata.0.self_link"),
@@ -51,10 +51,10 @@ func TestAccKubernetesStatefulSet_basic(t *testing.T) {
5151
resource.TestCheckResourceAttr("kubernetes_stateful_set.test", "spec.0.template.0.metadata.0.labels.%", "1"),
5252
resource.TestCheckResourceAttr("kubernetes_stateful_set.test", "spec.0.template.0.metadata.0.labels.app", "ss-test"),
5353
resource.TestCheckResourceAttr("kubernetes_stateful_set.test", "spec.0.template.0.spec.0.container.0.name", "ss-test"),
54-
resource.TestCheckResourceAttr("kubernetes_stateful_set.test", "spec.0.template.0.spec.0.container.0.image", "k8s.gcr.io/pause:latest"),
54+
resource.TestCheckResourceAttr("kubernetes_stateful_set.test", "spec.0.template.0.spec.0.container.0.image", "nginx:1.19"),
5555
resource.TestCheckResourceAttr("kubernetes_stateful_set.test", "spec.0.template.0.spec.0.container.0.port.0.container_port", "80"),
5656
resource.TestCheckResourceAttr("kubernetes_stateful_set.test", "spec.0.template.0.spec.0.container.0.port.0.name", "web"),
57-
resource.TestCheckResourceAttr("kubernetes_stateful_set.test", "spec.0.template.0.spec.0.container.0.volume_mount.0.name", "workdir"),
57+
resource.TestCheckResourceAttr("kubernetes_stateful_set.test", "spec.0.template.0.spec.0.container.0.volume_mount.0.name", "ss-test"),
5858
resource.TestCheckResourceAttr("kubernetes_stateful_set.test", "spec.0.template.0.spec.0.container.0.volume_mount.0.mount_path", "/work-dir"),
5959
resource.TestCheckResourceAttr("kubernetes_stateful_set.test", "spec.0.update_strategy.0.type", "RollingUpdate"),
6060
resource.TestCheckResourceAttr("kubernetes_stateful_set.test", "spec.0.update_strategy.0.rolling_update.#", "1"),
@@ -110,6 +110,7 @@ func TestAccKubernetesStatefulSet_Update(t *testing.T) {
110110
resource.Test(t, resource.TestCase{
111111
PreCheck: func() { testAccPreCheck(t) },
112112
IDRefreshName: "kubernetes_stateful_set.test",
113+
IDRefreshIgnore: []string{"metadata.0.resource_version"},
113114
ProviderFactories: testAccProviderFactories,
114115
CheckDestroy: testAccCheckKubernetesStatefulSetDestroy,
115116
Steps: []resource.TestStep{
@@ -139,15 +140,24 @@ func TestAccKubernetesStatefulSet_Update(t *testing.T) {
139140
),
140141
},
141142
{
142-
Config: testAccKubernetesStatefulSetConfigUpdateReplicas(name, 5),
143+
Config: testAccKubernetesStatefulSetConfigUpdateReplicas(name, "5"),
144+
Check: resource.ComposeAggregateTestCheckFunc(
145+
testAccCheckKubernetesStatefulSetExists("kubernetes_stateful_set.test", &conf),
146+
resource.TestCheckResourceAttr("kubernetes_stateful_set.test", "metadata.0.name", name),
147+
resource.TestCheckResourceAttr("kubernetes_stateful_set.test", "spec.0.replicas", "5"),
148+
),
149+
},
150+
{
151+
Config: testAccKubernetesStatefulSetConfigUpdateReplicas(name, ""),
143152
Check: resource.ComposeAggregateTestCheckFunc(
144153
testAccCheckKubernetesStatefulSetExists("kubernetes_stateful_set.test", &conf),
145154
resource.TestCheckResourceAttr("kubernetes_stateful_set.test", "metadata.0.name", name),
155+
// NOTE setting to empty should preserve the current replica count
146156
resource.TestCheckResourceAttr("kubernetes_stateful_set.test", "spec.0.replicas", "5"),
147157
),
148158
},
149159
{
150-
Config: testAccKubernetesStatefulSetConfigUpdateReplicas(name, 0),
160+
Config: testAccKubernetesStatefulSetConfigUpdateReplicas(name, "0"),
151161
Check: resource.ComposeAggregateTestCheckFunc(
152162
testAccCheckKubernetesStatefulSetExists("kubernetes_stateful_set.test", &conf),
153163
resource.TestCheckResourceAttr("kubernetes_stateful_set.test", "metadata.0.name", name),
@@ -213,7 +223,7 @@ func TestAccKubernetesStatefulSet_Update(t *testing.T) {
213223
})
214224
}
215225

216-
func TestAccKubernetesStatefulSet_waitForRollout(t *testing.T) {
226+
func TestAccKubernetesStatefulSet_waitForRollout_true(t *testing.T) {
217227
var conf api.StatefulSet
218228
name := fmt.Sprintf("tf-acc-test-%s", acctest.RandStringFromCharSet(10, acctest.CharSetAlphaNum))
219229
resource.Test(t, resource.TestCase{
@@ -223,7 +233,7 @@ func TestAccKubernetesStatefulSet_waitForRollout(t *testing.T) {
223233
CheckDestroy: testAccCheckKubernetesStatefulSetDestroy,
224234
Steps: []resource.TestStep{
225235
{
226-
Config: testAccKubernetesStatefulSetConfigWaitForRollout(name),
236+
Config: testAccKubernetesStatefulSetConfigWaitForRollout(name, true),
227237
Check: resource.ComposeAggregateTestCheckFunc(
228238
testAccCheckKubernetesStatefulSetExists("kubernetes_stateful_set.test", &conf),
229239
testAccCheckKubernetesStatefulSetRolledOut("kubernetes_stateful_set.test"),
@@ -233,6 +243,26 @@ func TestAccKubernetesStatefulSet_waitForRollout(t *testing.T) {
233243
})
234244
}
235245

246+
func TestAccKubernetesStatefulSet_waitForRollout_false(t *testing.T) {
247+
var conf api.StatefulSet
248+
name := fmt.Sprintf("tf-acc-test-%s", acctest.RandStringFromCharSet(10, acctest.CharSetAlphaNum))
249+
resource.Test(t, resource.TestCase{
250+
PreCheck: func() { testAccPreCheck(t) },
251+
IDRefreshName: "kubernetes_stateful_set.test",
252+
ProviderFactories: testAccProviderFactories,
253+
CheckDestroy: testAccCheckKubernetesStatefulSetDestroy,
254+
Steps: []resource.TestStep{
255+
{
256+
Config: testAccKubernetesStatefulSetConfigWaitForRollout(name, false),
257+
Check: resource.ComposeAggregateTestCheckFunc(
258+
testAccCheckKubernetesStatefulSetExists("kubernetes_stateful_set.test", &conf),
259+
testAccCheckKubernetesStatefulSetRollingOut("kubernetes_stateful_set.test"),
260+
),
261+
},
262+
},
263+
})
264+
}
265+
236266
func TestAccKubernetesStatefulSet_regression(t *testing.T) {
237267
var conf1, conf2 api.StatefulSet
238268
name := fmt.Sprintf("tf-acc-test-%s", acctest.RandStringFromCharSet(10, acctest.CharSetAlphaNum))
@@ -272,7 +302,7 @@ func TestAccKubernetesStatefulSet_regression(t *testing.T) {
272302
resource.TestCheckResourceAttr("kubernetes_stateful_set.test", "spec.0.template.0.spec.0.container.0.image", "k8s.gcr.io/pause:latest"),
273303
resource.TestCheckResourceAttr("kubernetes_stateful_set.test", "spec.0.template.0.spec.0.container.0.port.0.container_port", "80"),
274304
resource.TestCheckResourceAttr("kubernetes_stateful_set.test", "spec.0.template.0.spec.0.container.0.port.0.name", "web"),
275-
resource.TestCheckResourceAttr("kubernetes_stateful_set.test", "spec.0.template.0.spec.0.container.0.volume_mount.0.name", "workdir"),
305+
resource.TestCheckResourceAttr("kubernetes_stateful_set.test", "spec.0.template.0.spec.0.container.0.volume_mount.0.name", "ss-test"),
276306
resource.TestCheckResourceAttr("kubernetes_stateful_set.test", "spec.0.template.0.spec.0.container.0.volume_mount.0.mount_path", "/work-dir"),
277307
resource.TestCheckResourceAttr("kubernetes_stateful_set.test", "spec.0.update_strategy.0.type", "RollingUpdate"),
278308
resource.TestCheckResourceAttr("kubernetes_stateful_set.test", "spec.0.update_strategy.0.rolling_update.#", "1"),
@@ -315,7 +345,7 @@ func TestAccKubernetesStatefulSet_regression(t *testing.T) {
315345
resource.TestCheckResourceAttr("kubernetes_stateful_set.test", "spec.0.template.0.spec.0.container.0.image", "k8s.gcr.io/pause:latest"),
316346
resource.TestCheckResourceAttr("kubernetes_stateful_set.test", "spec.0.template.0.spec.0.container.0.port.0.container_port", "80"),
317347
resource.TestCheckResourceAttr("kubernetes_stateful_set.test", "spec.0.template.0.spec.0.container.0.port.0.name", "web"),
318-
resource.TestCheckResourceAttr("kubernetes_stateful_set.test", "spec.0.template.0.spec.0.container.0.volume_mount.0.name", "workdir"),
348+
resource.TestCheckResourceAttr("kubernetes_stateful_set.test", "spec.0.template.0.spec.0.container.0.volume_mount.0.name", "ss-test"),
319349
resource.TestCheckResourceAttr("kubernetes_stateful_set.test", "spec.0.template.0.spec.0.container.0.volume_mount.0.mount_path", "/work-dir"),
320350
resource.TestCheckResourceAttr("kubernetes_stateful_set.test", "spec.0.update_strategy.0.type", "RollingUpdate"),
321351
resource.TestCheckResourceAttr("kubernetes_stateful_set.test", "spec.0.update_strategy.0.rolling_update.#", "1"),
@@ -421,7 +451,7 @@ func testAccCheckKubernetesStatefulSetRollingOut(n string) resource.TestCheckFun
421451
return err
422452
}
423453

424-
if d.Status.Replicas == *d.Spec.Replicas {
454+
if d.Status.ReadyReplicas == *d.Spec.Replicas {
425455
return fmt.Errorf("StatefulSet has already rolled out")
426456
}
427457

@@ -436,7 +466,7 @@ func testAccCheckKubernetesStatefulSetRolledOut(n string) resource.TestCheckFunc
436466
return err
437467
}
438468

439-
if d.Status.Replicas != *d.Spec.Replicas {
469+
if d.Status.ReadyReplicas != *d.Spec.Replicas {
440470
return fmt.Errorf("StatefulSet is still rolling out")
441471
}
442472

@@ -483,16 +513,24 @@ func testAccKubernetesStatefulSetConfigBasic(name string) string {
483513
484514
spec {
485515
container {
486-
name = "ss-test"
487-
image = "k8s.gcr.io/pause:latest"
516+
name = "ss-test"
517+
image = "nginx:1.19"
488518
489519
port {
490-
container_port = "80"
491520
name = "web"
521+
container_port = 80
522+
}
523+
524+
readiness_probe {
525+
initial_delay_seconds = 5
526+
http_get {
527+
path = "/"
528+
port = 80
529+
}
492530
}
493531
494532
volume_mount {
495-
name = "workdir"
533+
name = "ss-test"
496534
mount_path = "/work-dir"
497535
}
498536
}
@@ -575,7 +613,7 @@ func testAccKubernetesStatefulSetConfigUpdateImage(name string) string {
575613
}
576614
577615
volume_mount {
578-
name = "workdir"
616+
name = "ss-test"
579617
mount_path = "/work-dir"
580618
}
581619
}
@@ -660,7 +698,7 @@ func testAccKubernetesStatefulSetConfigUpdatedSelectorLabels(name string) string
660698
}
661699
662700
volume_mount {
663-
name = "workdir"
701+
name = "ss-test"
664702
mount_path = "/work-dir"
665703
}
666704
}
@@ -695,7 +733,7 @@ func testAccKubernetesStatefulSetConfigUpdatedSelectorLabels(name string) string
695733
`, name)
696734
}
697735

698-
func testAccKubernetesStatefulSetConfigUpdateReplicas(name string, replicas int) string {
736+
func testAccKubernetesStatefulSetConfigUpdateReplicas(name string, replicas string) string {
699737
return fmt.Sprintf(`resource "kubernetes_stateful_set" "test" {
700738
metadata {
701739
annotations = {
@@ -714,7 +752,7 @@ func testAccKubernetesStatefulSetConfigUpdateReplicas(name string, replicas int)
714752
715753
spec {
716754
pod_management_policy = "OrderedReady"
717-
replicas = %d
755+
replicas = %q
718756
revision_history_limit = 11
719757
720758
selector {
@@ -743,7 +781,7 @@ func testAccKubernetesStatefulSetConfigUpdateReplicas(name string, replicas int)
743781
}
744782
745783
volume_mount {
746-
name = "workdir"
784+
name = "ss-test"
747785
mount_path = "/work-dir"
748786
}
749787
}
@@ -831,7 +869,7 @@ func testAccKubernetesStatefulSetConfigUpdateTemplate(name string) string {
831869
}
832870
833871
volume_mount {
834-
name = "workdir"
872+
name = "ss-test"
835873
mount_path = "/work-dir"
836874
}
837875
}
@@ -930,7 +968,7 @@ func testAccKubernetesStatefulSetConfigRollingUpdatePartition(name string) strin
930968
}
931969
932970
volume_mount {
933-
name = "workdir"
971+
name = "ss-test"
934972
mount_path = "/work-dir"
935973
}
936974
}
@@ -1013,7 +1051,7 @@ func testAccKubernetesStatefulSetConfigUpdateStrategyOnDelete(name string) strin
10131051
}
10141052
10151053
volume_mount {
1016-
name = "workdir"
1054+
name = "ss-test"
10171055
mount_path = "/work-dir"
10181056
}
10191057
}
@@ -1040,11 +1078,13 @@ func testAccKubernetesStatefulSetConfigUpdateStrategyOnDelete(name string) strin
10401078
}
10411079
}
10421080
}
1081+
1082+
wait_for_rollout = false
10431083
}
10441084
`, name)
10451085
}
10461086

1047-
func testAccKubernetesStatefulSetConfigWaitForRollout(name string) string {
1087+
func testAccKubernetesStatefulSetConfigWaitForRollout(name string, v bool) string {
10481088
return fmt.Sprintf(`resource "kubernetes_service" "test" {
10491089
metadata {
10501090
name = "ss-test"
@@ -1111,9 +1151,9 @@ resource "kubernetes_stateful_set" "test" {
11111151
}
11121152
}
11131153
1114-
wait_for_rollout = true
1154+
wait_for_rollout = %t
11151155
}
1116-
`, name)
1156+
`, name, v)
11171157
}
11181158

11191159
func testAccKubernetesStatefulSet_regression(provider, name string) string {
@@ -1165,7 +1205,7 @@ func testAccKubernetesStatefulSet_regression(provider, name string) string {
11651205
}
11661206
11671207
volume_mount {
1168-
name = "workdir"
1208+
name = "ss-test"
11691209
mount_path = "/work-dir"
11701210
}
11711211
}

kubernetes/schema_job_spec.go

Lines changed: 5 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,6 @@
11
package kubernetes
22

33
import (
4-
"fmt"
5-
"strconv"
6-
74
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema"
85
)
96

@@ -131,17 +128,11 @@ func jobSpecFields() map[string]*schema.Schema {
131128
},
132129
},
133130
"ttl_seconds_after_finished": {
134-
Type: schema.TypeString,
135-
Optional: true,
136-
ForceNew: true,
137-
ValidateFunc: func(value interface{}, key string) ([]string, []error) {
138-
v, err := strconv.Atoi(value.(string))
139-
if err != nil {
140-
return []string{}, []error{fmt.Errorf("%s is not a valid integer", key)}
141-
}
142-
return validateNonNegativeInteger(v, key)
143-
},
144-
Description: "ttlSecondsAfterFinished limits the lifetime of a Job that has finished execution (either Complete or Failed). If this field is set, ttlSecondsAfterFinished after the Job finishes, it is eligible to be automatically deleted. When the Job is being deleted, its lifecycle guarantees (e.g. finalizers) will be honored. If this field is unset, the Job won't be automatically deleted. If this field is set to zero, the Job becomes eligible to be deleted immediately after it finishes.",
131+
Type: schema.TypeString,
132+
Optional: true,
133+
ForceNew: true,
134+
ValidateFunc: validateTypeStringNullableInt,
135+
Description: "ttlSecondsAfterFinished limits the lifetime of a Job that has finished execution (either Complete or Failed). If this field is set, ttlSecondsAfterFinished after the Job finishes, it is eligible to be automatically deleted. When the Job is being deleted, its lifecycle guarantees (e.g. finalizers) will be honored. If this field is unset, the Job won't be automatically deleted. If this field is set to zero, the Job becomes eligible to be deleted immediately after it finishes.",
145136
},
146137
}
147138

kubernetes/schema_stateful_set_spec.go

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -19,11 +19,11 @@ func statefulSetSpecFields(isUpdatable bool) map[string]*schema.Schema {
1919
}, false),
2020
},
2121
"replicas": {
22-
Type: schema.TypeInt,
22+
Type: schema.TypeString,
2323
Optional: true,
24-
Default: 1,
24+
Computed: true,
2525
Description: "The desired number of replicas of the given Template, in the sense that they are instantiations of the same Template. Value must be a positive integer.",
26-
ValidateFunc: validateNonNegativeInteger,
26+
ValidateFunc: validateTypeStringNullableInt,
2727
},
2828
"revision_history_limit": {
2929
Type: schema.TypeInt,

kubernetes/structures_deployment.go

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
11
package kubernetes
22

33
import (
4+
"strconv"
5+
46
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema"
57
appsv1 "k8s.io/api/apps/v1"
68
corev1 "k8s.io/api/core/v1"
@@ -12,7 +14,7 @@ func flattenDeploymentSpec(in appsv1.DeploymentSpec, d *schema.ResourceData) ([]
1214
att["min_ready_seconds"] = in.MinReadySeconds
1315

1416
if in.Replicas != nil {
15-
att["replicas"] = *in.Replicas
17+
att["replicas"] = strconv.Itoa(int(*in.Replicas))
1618
}
1719

1820
if in.ProgressDeadlineSeconds != nil {
@@ -75,7 +77,13 @@ func expandDeploymentSpec(deployment []interface{}) (*appsv1.DeploymentSpec, err
7577
obj.MinReadySeconds = int32(in["min_ready_seconds"].(int))
7678
obj.Paused = in["paused"].(bool)
7779
obj.ProgressDeadlineSeconds = ptrToInt32(int32(in["progress_deadline_seconds"].(int)))
78-
obj.Replicas = ptrToInt32(int32(in["replicas"].(int)))
80+
if v, ok := in["replicas"].(string); ok && v != "" {
81+
i, err := strconv.ParseInt(v, 10, 32)
82+
if err != nil {
83+
return obj, err
84+
}
85+
obj.Replicas = ptrToInt32(int32(i))
86+
}
7987
obj.RevisionHistoryLimit = ptrToInt32(int32(in["revision_history_limit"].(int)))
8088

8189
if v, ok := in["selector"].([]interface{}); ok && len(v) > 0 {

0 commit comments

Comments
 (0)