Skip to content

Commit 06d0a07

Browse files
authored
Fix namespace requirement in template metadata (#2387)
1 parent 865f137 commit 06d0a07

14 files changed

+468
-13
lines changed

.changelog/2387.txt

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
```release-note:bug
2+
`resource/kubernetes_stateful_set_v1`: fix an issue when the provider forces a resource recreation after upgrading to `2.25.0` and `2.25.1` due to changes in the resource schema.
3+
```
4+
5+
```release-note:bug
6+
`resource/kubernetes_stateful_set`: fix an issue when the provider forces a resource recreation after upgrading to `2.25.0` and `2.25.1` due to changes in the resource schema.
7+
```
8+
9+
```release-note:bug
10+
`resource/kubernetes_daemon_set_v1`: fix an issue when the provider forces a resource recreation after upgrading to `2.25.0` and `2.25.1` due to changes in the resource schema.
11+
```
12+
13+
```release-note:bug
14+
`resource/kubernetes_daemonset`: fix an issue when the provider forces a resource recreation after upgrading to `2.25.0` and `2.25.1` due to changes in the resource schema.
15+
```
16+
17+
```release-note:bug
18+
`resource/kubernetes_cron_job_v1`: fix an issue when the provider forces a resource recreation after upgrading to `2.25.0` and `2.25.1` due to changes in the resource schema.
19+
```
20+
21+
```release-note:bug
22+
`resource/kubernetes_cron_job`: fix an issue when the provider forces a resource recreation after upgrading to `2.25.0` and `2.25.1` due to changes in the resource schema.
23+
```
24+
25+
```release-note:note
26+
Resources `kubernetes_stateful_set_v1`, `kubernetes_stateful_set`, `kubernetes_daemon_set_v1`, and `kubernetes_daemonset` got a new attribute `spec.template.metadata.namespace`. It is a stub attribute that does not affect the namespace in which the Pod will be created. The Pod will be created in the same namespace as the main resource. However, modifying this field will force the resource recreation.
27+
```
28+
29+
```release-note:note
30+
Resources `kubernetes_cron_job_v1` and `kubernetes_cron_job` got a new attribute `spec.job_template.metadata.namespace`. It is a stub attribute that does not affect the namespace in which the Pod will be created. The Pod will be created in the same namespace as the main resource. However, modifying this field will force the resource recreation.
31+
```

kubernetes/resource_kubernetes_cron_job_v1_test.go

Lines changed: 103 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -52,7 +52,6 @@ func TestAccKubernetesCronJobV1_basic(t *testing.T) {
5252
resource.TestCheckResourceAttr(resourceName, "spec.0.successful_jobs_history_limit", "10"),
5353
resource.TestCheckResourceAttr(resourceName, "spec.0.suspend", "true"),
5454
resource.TestCheckResourceAttr(resourceName, "spec.0.job_template.0.metadata.0.annotations.cluster-autoscaler.kubernetes.io/safe-to-evict", "false"),
55-
resource.TestCheckResourceAttr(resourceName, "spec.0.job_template.0.metadata.0.namespace", "ns-test"),
5655
resource.TestCheckResourceAttr(resourceName, "spec.0.job_template.0.spec.0.parallelism", "1"),
5756
resource.TestCheckResourceAttr(resourceName, "spec.0.job_template.0.spec.0.backoff_limit", "2"),
5857
resource.TestCheckResourceAttr(resourceName, "spec.0.job_template.0.spec.0.template.0.metadata.0.annotations.controller.kubernetes.io/pod-deletion-cost", "10000"),
@@ -134,6 +133,47 @@ func TestAccKubernetesCronJobV1_extra(t *testing.T) {
134133
})
135134
}
136135

136+
func TestAccKubernetesCronJobV1_minimalWithTemplateNamespace(t *testing.T) {
137+
var conf1, conf2 batchv1.CronJob
138+
139+
name := fmt.Sprintf("tf-acc-test-%s", acctest.RandStringFromCharSet(10, acctest.CharSetAlphaNum))
140+
resourceName := "kubernetes_cron_job_v1.test"
141+
imageName := busyboxImage
142+
143+
resource.ParallelTest(t, resource.TestCase{
144+
PreCheck: func() { testAccPreCheck(t) },
145+
IDRefreshName: resourceName,
146+
IDRefreshIgnore: []string{"metadata.0.resource_version"},
147+
ProviderFactories: testAccProviderFactories,
148+
CheckDestroy: testAccCheckKubernetesCronJobV1Destroy,
149+
Steps: []resource.TestStep{
150+
{
151+
Config: testAccKubernetesCronJobV1ConfigMinimal(name, imageName),
152+
Check: resource.ComposeAggregateTestCheckFunc(
153+
testAccCheckKubernetesCronJobV1Exists(resourceName, &conf1),
154+
resource.TestCheckResourceAttrSet(resourceName, "metadata.0.generation"),
155+
resource.TestCheckResourceAttrSet(resourceName, "metadata.0.resource_version"),
156+
resource.TestCheckResourceAttrSet(resourceName, "metadata.0.uid"),
157+
resource.TestCheckResourceAttrSet(resourceName, "metadata.0.namespace"),
158+
resource.TestCheckResourceAttr(resourceName, "spec.0.job_template.0.metadata.0.namespace", ""),
159+
),
160+
},
161+
{
162+
Config: testAccKubernetesCronJobV1ConfigMinimalWithJobTemplateNamespace(name, imageName),
163+
Check: resource.ComposeAggregateTestCheckFunc(
164+
testAccCheckKubernetesCronJobV1Exists(resourceName, &conf2),
165+
resource.TestCheckResourceAttrSet(resourceName, "metadata.0.generation"),
166+
resource.TestCheckResourceAttrSet(resourceName, "metadata.0.resource_version"),
167+
resource.TestCheckResourceAttrSet(resourceName, "metadata.0.uid"),
168+
resource.TestCheckResourceAttrSet(resourceName, "metadata.0.namespace"),
169+
resource.TestCheckResourceAttrSet(resourceName, "spec.0.job_template.0.metadata.0.namespace"),
170+
testAccCheckKubernetesCronJobV1ForceNew(&conf1, &conf2, true),
171+
),
172+
},
173+
},
174+
})
175+
}
176+
137177
func testAccCheckKubernetesCronJobV1Destroy(s *terraform.State) error {
138178
conn, err := testAccProvider.Meta().(KubeClientsets).MainClientset()
139179

@@ -212,7 +252,6 @@ func testAccKubernetesCronJobV1Config_basic(name, imageName string) string {
212252
annotations = {
213253
"cluster-autoscaler.kubernetes.io/safe-to-evict" = "false"
214254
}
215-
namespace = "ns-test"
216255
}
217256
spec {
218257
backoff_limit = 2
@@ -244,9 +283,7 @@ func testAccKubernetesCronJobV1Config_modified(name, imageName string) string {
244283
spec {
245284
schedule = "1 0 * * *"
246285
job_template {
247-
metadata {
248-
namespace = "ns-test"
249-
}
286+
metadata {}
250287
spec {
251288
parallelism = 2
252289
template {
@@ -336,7 +373,7 @@ func testAccKubernetesCronJobV1Config_extraModified(name, imageName string) stri
336373
func testAccCheckKubernetesCronJobV1ForceNew(old, new *batchv1.CronJob, wantNew bool) resource.TestCheckFunc {
337374
return func(s *terraform.State) error {
338375
if wantNew {
339-
if old.ObjectMeta.UID != new.ObjectMeta.UID {
376+
if old.ObjectMeta.UID == new.ObjectMeta.UID {
340377
return fmt.Errorf("Expecting forced replacement")
341378
}
342379
} else {
@@ -347,3 +384,63 @@ func testAccCheckKubernetesCronJobV1ForceNew(old, new *batchv1.CronJob, wantNew
347384
return nil
348385
}
349386
}
387+
388+
func testAccKubernetesCronJobV1ConfigMinimal(name, imageName string) string {
389+
return fmt.Sprintf(`resource "kubernetes_cron_job_v1" "test" {
390+
metadata {
391+
name = "%s"
392+
}
393+
spec {
394+
schedule = "*/1 * * * *"
395+
job_template {
396+
metadata {}
397+
spec {
398+
template {
399+
metadata {}
400+
spec {
401+
container {
402+
name = "test"
403+
image = "%s"
404+
command = ["sleep", "5"]
405+
}
406+
termination_grace_period_seconds = 1
407+
}
408+
}
409+
}
410+
}
411+
}
412+
}
413+
`, name, imageName)
414+
}
415+
416+
func testAccKubernetesCronJobV1ConfigMinimalWithJobTemplateNamespace(name, imageName string) string {
417+
return fmt.Sprintf(`resource "kubernetes_cron_job_v1" "test" {
418+
metadata {
419+
name = "%s"
420+
}
421+
spec {
422+
schedule = "*/1 * * * *"
423+
job_template {
424+
metadata {
425+
// The namespace field is just a stub and does not influence where the Pod will be created.
426+
// The Pod will be created within the same Namespace as the Cron Job resource.
427+
namespace = "fake" // Doesn't have to exist.
428+
}
429+
spec {
430+
template {
431+
metadata {}
432+
spec {
433+
container {
434+
name = "test"
435+
image = "%s"
436+
command = ["sleep", "1"]
437+
}
438+
termination_grace_period_seconds = 1
439+
}
440+
}
441+
}
442+
}
443+
}
444+
}
445+
`, name, imageName)
446+
}

kubernetes/resource_kubernetes_cron_job_v1beta1_test.go

Lines changed: 104 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -126,6 +126,50 @@ func TestAccKubernetesCronJobV1Beta1_extra(t *testing.T) {
126126
})
127127
}
128128

129+
func TestAccKubernetesCronJobV1Beta1_minimalWithTemplateNamespace(t *testing.T) {
130+
var conf1, conf2 batchv1beta1.CronJob
131+
132+
name := fmt.Sprintf("tf-acc-test-%s", acctest.RandStringFromCharSet(10, acctest.CharSetAlphaNum))
133+
resourceName := "kubernetes_cron_job.test"
134+
imageName := busyboxImage
135+
136+
resource.ParallelTest(t, resource.TestCase{
137+
PreCheck: func() {
138+
testAccPreCheck(t)
139+
skipIfClusterVersionGreaterThanOrEqual(t, "1.25.0")
140+
},
141+
IDRefreshName: resourceName,
142+
IDRefreshIgnore: []string{"metadata.0.resource_version"},
143+
ProviderFactories: testAccProviderFactories,
144+
CheckDestroy: testAccCheckKubernetesCronJobV1Beta1Destroy,
145+
Steps: []resource.TestStep{
146+
{
147+
Config: testAccKubernetesCronJobV1Beta1ConfigMinimal(name, imageName),
148+
Check: resource.ComposeAggregateTestCheckFunc(
149+
testAccCheckKubernetesCronJobV1Beta1Exists(resourceName, &conf1),
150+
resource.TestCheckResourceAttrSet(resourceName, "metadata.0.generation"),
151+
resource.TestCheckResourceAttrSet(resourceName, "metadata.0.resource_version"),
152+
resource.TestCheckResourceAttrSet(resourceName, "metadata.0.uid"),
153+
resource.TestCheckResourceAttrSet(resourceName, "metadata.0.namespace"),
154+
resource.TestCheckResourceAttr(resourceName, "spec.0.job_template.0.metadata.0.namespace", ""),
155+
),
156+
},
157+
{
158+
Config: testAccKubernetesCronJobV1Beta1ConfigMinimalWithJobTemplateNamespace(name, imageName),
159+
Check: resource.ComposeAggregateTestCheckFunc(
160+
testAccCheckKubernetesCronJobV1Beta1Exists(resourceName, &conf2),
161+
resource.TestCheckResourceAttrSet(resourceName, "metadata.0.generation"),
162+
resource.TestCheckResourceAttrSet(resourceName, "metadata.0.resource_version"),
163+
resource.TestCheckResourceAttrSet(resourceName, "metadata.0.uid"),
164+
resource.TestCheckResourceAttrSet(resourceName, "metadata.0.namespace"),
165+
resource.TestCheckResourceAttrSet(resourceName, "spec.0.job_template.0.metadata.0.namespace"),
166+
testAccCheckKubernetesCronJobV1Beta1ForceNew(&conf1, &conf2, true),
167+
),
168+
},
169+
},
170+
})
171+
}
172+
129173
func testAccCheckKubernetesCronJobV1Beta1Destroy(s *terraform.State) error {
130174
conn, err := testAccProvider.Meta().(KubeClientsets).MainClientset()
131175

@@ -322,3 +366,63 @@ func testAccCheckKubernetesCronJobV1Beta1ForceNew(old, new *batchv1beta1.CronJob
322366
return nil
323367
}
324368
}
369+
370+
func testAccKubernetesCronJobV1Beta1ConfigMinimal(name, imageName string) string {
371+
return fmt.Sprintf(`resource "kubernetes_cron_job" "test" {
372+
metadata {
373+
name = "%s"
374+
}
375+
spec {
376+
schedule = "*/1 * * * *"
377+
job_template {
378+
metadata {}
379+
spec {
380+
template {
381+
metadata {}
382+
spec {
383+
container {
384+
name = "test"
385+
image = "%s"
386+
command = ["sleep", "5"]
387+
}
388+
}
389+
}
390+
}
391+
}
392+
}
393+
}
394+
`, name, imageName)
395+
}
396+
397+
func testAccKubernetesCronJobV1Beta1ConfigMinimalWithJobTemplateNamespace(name, imageName string) string {
398+
return fmt.Sprintf(`resource "kubernetes_cron_job" "test" {
399+
metadata {
400+
name = "%s"
401+
}
402+
403+
spec {
404+
schedule = "*/1 * * * *"
405+
406+
job_template {
407+
metadata {
408+
// The namespace field is just a stub and does not influence where the Pod will be created.
409+
// The Pod will be created within the same Namespace as the Cron Job resource.
410+
namespace = "fake" // Doesn't have to exist.
411+
}
412+
spec {
413+
template {
414+
metadata {}
415+
spec {
416+
container {
417+
name = "test"
418+
image = "%s"
419+
command = ["sleep", "5"]
420+
}
421+
}
422+
}
423+
}
424+
}
425+
}
426+
}
427+
`, name, imageName)
428+
}

0 commit comments

Comments
 (0)