Skip to content

Commit 9d6074c

Browse files
Support JobBackoffLimitPerIndex feature gate fields (#2421)
* update job spec * fix tests by adding in extra checks and DiffSuppressFuncs for both new attributes * add changelog * add docs * add new fields into TestAccKubernetesCronJobV1_minimalWithPodFailurePolicy test * insert field checks for new fields * make tests * add flatteners * lint fix * add new test - TestAccKubernetesCronJobV1_minimalWithBackoffLimitPerIndex * remove fields from other test --------- Co-authored-by: Mauricio Alvarez Leon <[email protected]> Co-authored-by: BBBmau <[email protected]>
1 parent 507da66 commit 9d6074c

File tree

7 files changed

+144
-0
lines changed

7 files changed

+144
-0
lines changed

.changelog/2421.txt

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
```release-note:enhancement
2+
Add `backoff_per_limit_index` and `max_failed_indexes` fields in `structure_job.go`
3+
```

docs/resources/cron_job.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -102,6 +102,8 @@ Optional:
102102

103103
- `active_deadline_seconds` (Number) Optional duration in seconds the pod may be active on the node relative to StartTime before the system will actively try to mark it failed and kill associated containers. Value must be a positive integer.
104104
- `backoff_limit` (Number) Specifies the number of retries before marking this job failed. Defaults to 6
105+
- `backoff_limit_per_index` - (Number) Specifies the limit for the number of retries within an index before marking this index as failed. When enabled the number of failures per index is kept in the pod's batch.kubernetes.io/job-index-failure-count annotation. It can only be set when Job's completionMode=Indexed, and the Pod's restart policy is Never. The field is immutable.
106+
- `max_failed_indexes` - (Number) Controls generation of pod labels and pod selectors. Leave unset unless you are certain what you are doing. When false or unset, the system pick labels unique to this job and appends those labels to the pod template. When true, the user is responsible for picking unique labels and specifying the selector. Failure to pick a unique label may cause this and other jobs to not function correctly. More info: https://git.k8s.io/community/contributors/design-proposals/selector-generation.md
105107
- `completion_mode` (String) Specifies how Pod completions are tracked. It can be `NonIndexed` (default) or `Indexed`. More info: https://kubernetes.io/docs/concepts/workloads/controllers/job/#completion-mode
106108
- `completions` (Number) Specifies the desired number of successfully finished pods the job should be run with. Setting to nil means that the success of any pod signals the success of all pods, and allows parallelism to have any positive value. Setting to 1 means that parallelism is limited to 1 and the success of that pod signals the success of the job. More info: https://kubernetes.io/docs/concepts/workloads/controllers/jobs-run-to-completion/
107109
- `manual_selector` (Boolean) Controls generation of pod labels and pod selectors. Leave unset unless you are certain what you are doing. When false or unset, the system pick labels unique to this job and appends those labels to the pod template. When true, the user is responsible for picking unique labels and specifying the selector. Failure to pick a unique label may cause this and other jobs to not function correctly. More info: https://git.k8s.io/community/contributors/design-proposals/selector-generation.md

docs/resources/cron_job_v1.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -97,6 +97,8 @@ Optional:
9797

9898
- `active_deadline_seconds` (Number) Optional duration in seconds the pod may be active on the node relative to StartTime before the system will actively try to mark it failed and kill associated containers. Value must be a positive integer.
9999
- `backoff_limit` (Number) Specifies the number of retries before marking this job failed. Defaults to 6
100+
- `backoff_limit_per_index` - (Number) Specifies the limit for the number of retries within an index before marking this index as failed. When enabled the number of failures per index is kept in the pod's batch.kubernetes.io/job-index-failure-count annotation. It can only be set when Job's completionMode=Indexed, and the Pod's restart policy is Never. The field is immutable.
101+
- `max_failed_indexes` - (Number) Controls generation of pod labels and pod selectors. Leave unset unless you are certain what you are doing. When false or unset, the system pick labels unique to this job and appends those labels to the pod template. When true, the user is responsible for picking unique labels and specifying the selector. Failure to pick a unique label may cause this and other jobs to not function correctly. More info: https://git.k8s.io/community/contributors/design-proposals/selector-generation.md
100102
- `completion_mode` (String) Specifies how Pod completions are tracked. It can be `NonIndexed` (default) or `Indexed`. More info: https://kubernetes.io/docs/concepts/workloads/controllers/job/#completion-mode
101103
- `completions` (Number) Specifies the desired number of successfully finished pods the job should be run with. Setting to nil means that the success of any pod signals the success of all pods, and allows parallelism to have any positive value. Setting to 1 means that parallelism is limited to 1 and the success of that pod signals the success of the job. More info: https://kubernetes.io/docs/concepts/workloads/controllers/jobs-run-to-completion/
102104
- `manual_selector` (Boolean) Controls generation of pod labels and pod selectors. Leave unset unless you are certain what you are doing. When false or unset, the system pick labels unique to this job and appends those labels to the pod template. When true, the user is responsible for picking unique labels and specifying the selector. Failure to pick a unique label may cause this and other jobs to not function correctly. More info: https://git.k8s.io/community/contributors/design-proposals/selector-generation.md

docs/resources/job_v1.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,8 @@ Optional:
5555

5656
- `active_deadline_seconds` (Number) Optional duration in seconds the pod may be active on the node relative to StartTime before the system will actively try to mark it failed and kill associated containers. Value must be a positive integer.
5757
- `backoff_limit` (Number) Specifies the number of retries before marking this job failed. Defaults to 6
58+
- `backoff_limit_per_index` - (Number) Specifies the limit for the number of retries within an index before marking this index as failed. When enabled the number of failures per index is kept in the pod's batch.kubernetes.io/job-index-failure-count annotation. It can only be set when Job's completionMode=Indexed, and the Pod's restart policy is Never. The field is immutable.
59+
- `max_failed_indexes` - (Number) Controls generation of pod labels and pod selectors. Leave unset unless you are certain what you are doing. When false or unset, the system pick labels unique to this job and appends those labels to the pod template. When true, the user is responsible for picking unique labels and specifying the selector. Failure to pick a unique label may cause this and other jobs to not function correctly. More info: https://git.k8s.io/community/contributors/design-proposals/selector-generation.md
5860
- `completion_mode` (String) Specifies how Pod completions are tracked. It can be `NonIndexed` (default) or `Indexed`. More info: https://kubernetes.io/docs/concepts/workloads/controllers/job/#completion-mode
5961
- `completions` (Number) Specifies the desired number of successfully finished pods the job should be run with. Setting to nil means that the success of any pod signals the success of all pods, and allows parallelism to have any positive value. Setting to 1 means that parallelism is limited to 1 and the success of that pod signals the success of the job. More info: https://kubernetes.io/docs/concepts/workloads/controllers/jobs-run-to-completion/
6062
- `manual_selector` (Boolean) Controls generation of pod labels and pod selectors. Leave unset unless you are certain what you are doing. When false or unset, the system pick labels unique to this job and appends those labels to the pod template. When true, the user is responsible for picking unique labels and specifying the selector. Failure to pick a unique label may cause this and other jobs to not function correctly. More info: https://git.k8s.io/community/contributors/design-proposals/selector-generation.md

kubernetes/resource_kubernetes_cron_job_v1_test.go

Lines changed: 105 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -222,6 +222,61 @@ func TestAccKubernetesCronJobV1_minimalWithPodFailurePolicy(t *testing.T) {
222222
})
223223
}
224224

225+
func TestAccKubernetesCronJobV1_minimalWithBackoffLimitPerIndex(t *testing.T) {
226+
var conf1, conf2 batchv1.CronJob
227+
228+
name := fmt.Sprintf("tf-acc-test-%s", acctest.RandStringFromCharSet(10, acctest.CharSetAlphaNum))
229+
resourceName := "kubernetes_cron_job_v1.test"
230+
imageName := busyboxImage
231+
232+
resource.ParallelTest(t, resource.TestCase{
233+
PreCheck: func() {
234+
testAccPreCheck(t)
235+
skipIfClusterVersionLessThan(t, "1.29.0")
236+
},
237+
IDRefreshName: resourceName,
238+
IDRefreshIgnore: []string{"metadata.0.resource_version"},
239+
ProviderFactories: testAccProviderFactories,
240+
CheckDestroy: testAccCheckKubernetesCronJobV1Destroy,
241+
Steps: []resource.TestStep{
242+
{
243+
Config: testAccKubernetesCronJobV1ConfigMinimal(name, imageName),
244+
Check: resource.ComposeAggregateTestCheckFunc(
245+
testAccCheckKubernetesCronJobV1Exists(resourceName, &conf1),
246+
resource.TestCheckResourceAttrSet(resourceName, "metadata.0.generation"),
247+
resource.TestCheckResourceAttrSet(resourceName, "metadata.0.resource_version"),
248+
resource.TestCheckResourceAttrSet(resourceName, "metadata.0.uid"),
249+
resource.TestCheckResourceAttrSet(resourceName, "metadata.0.namespace"),
250+
resource.TestCheckResourceAttr(resourceName, "spec.0.job_template.0.metadata.0.namespace", ""),
251+
),
252+
},
253+
{
254+
Config: testAccKubernetesCronJobV1ConfigMinimalWithBackoffLimitPerIndex(name, imageName),
255+
Check: resource.ComposeAggregateTestCheckFunc(
256+
testAccCheckKubernetesCronJobV1Exists(resourceName, &conf2),
257+
resource.TestCheckResourceAttrSet(resourceName, "metadata.0.generation"),
258+
resource.TestCheckResourceAttrSet(resourceName, "metadata.0.resource_version"),
259+
resource.TestCheckResourceAttrSet(resourceName, "metadata.0.uid"),
260+
resource.TestCheckResourceAttrSet(resourceName, "metadata.0.namespace"),
261+
resource.TestCheckResourceAttr(resourceName, "spec.0.job_template.0.spec.0.backoff_limit_per_index", "3"),
262+
resource.TestCheckResourceAttr(resourceName, "spec.0.job_template.0.spec.0.max_failed_indexes", "4"),
263+
resource.TestCheckResourceAttr(resourceName, "spec.0.job_template.0.spec.0.pod_failure_policy.0.rule.#", "2"),
264+
resource.TestCheckResourceAttr(resourceName, "spec.0.job_template.0.spec.0.pod_failure_policy.0.rule.0.action", "FailJob"),
265+
resource.TestCheckResourceAttr(resourceName, "spec.0.job_template.0.spec.0.pod_failure_policy.0.rule.0.on_exit_codes.0.container_name", "test"),
266+
resource.TestCheckResourceAttr(resourceName, "spec.0.job_template.0.spec.0.pod_failure_policy.0.rule.0.on_exit_codes.0.values.#", "3"),
267+
resource.TestCheckResourceAttr(resourceName, "spec.0.job_template.0.spec.0.pod_failure_policy.0.rule.0.on_exit_codes.0.values.0", "1"),
268+
resource.TestCheckResourceAttr(resourceName, "spec.0.job_template.0.spec.0.pod_failure_policy.0.rule.0.on_exit_codes.0.values.1", "2"),
269+
resource.TestCheckResourceAttr(resourceName, "spec.0.job_template.0.spec.0.pod_failure_policy.0.rule.0.on_exit_codes.0.values.2", "42"),
270+
resource.TestCheckResourceAttr(resourceName, "spec.0.job_template.0.spec.0.pod_failure_policy.0.rule.1.action", "Ignore"),
271+
resource.TestCheckResourceAttr(resourceName, "spec.0.job_template.0.spec.0.pod_failure_policy.0.rule.1.on_pod_condition.0.type", "DisruptionTarget"),
272+
resource.TestCheckResourceAttr(resourceName, "spec.0.job_template.0.spec.0.pod_failure_policy.0.rule.1.on_pod_condition.0.status", "False"),
273+
testAccCheckKubernetesCronJobV1ForceNew(&conf1, &conf2, true),
274+
),
275+
},
276+
},
277+
})
278+
}
279+
225280
func testAccCheckKubernetesCronJobV1Destroy(s *terraform.State) error {
226281
conn, err := testAccProvider.Meta().(KubeClientsets).MainClientset()
227282

@@ -461,6 +516,56 @@ func testAccKubernetesCronJobV1ConfigMinimal(name, imageName string) string {
461516
`, name, imageName)
462517
}
463518

519+
func testAccKubernetesCronJobV1ConfigMinimalWithBackoffLimitPerIndex(name, imageName string) string {
520+
return fmt.Sprintf(`resource "kubernetes_cron_job_v1" "test" {
521+
metadata {
522+
name = "%s"
523+
}
524+
spec {
525+
schedule = "*/1 * * * *"
526+
job_template {
527+
metadata {}
528+
spec {
529+
backoff_limit_per_index = 3
530+
max_failed_indexes = 4
531+
completions = 4
532+
completion_mode = "Indexed"
533+
pod_failure_policy {
534+
rule {
535+
action = "FailJob"
536+
on_exit_codes {
537+
container_name = "test"
538+
operator = "In"
539+
values = [1, 2, 42]
540+
}
541+
}
542+
rule {
543+
action = "Ignore"
544+
on_pod_condition {
545+
status = "False"
546+
type = "DisruptionTarget"
547+
}
548+
}
549+
}
550+
template {
551+
metadata {}
552+
spec {
553+
554+
container {
555+
name = "test"
556+
image = "%s"
557+
command = ["sleep", "5"]
558+
}
559+
termination_grace_period_seconds = 1
560+
}
561+
}
562+
}
563+
}
564+
}
565+
}
566+
`, name, imageName)
567+
}
568+
464569
func testAccKubernetesCronJobV1ConfigMinimalWithPodFailurePolicy(name, imageName string) string {
465570
return fmt.Sprintf(`resource "kubernetes_cron_job_v1" "test" {
466571
metadata {

kubernetes/schema_job_spec.go

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -57,6 +57,13 @@ func jobSpecFields(specUpdatable bool) map[string]*schema.Schema {
5757
ValidateFunc: validateNonNegativeInteger,
5858
Description: "Specifies the number of retries before marking this job failed. Defaults to 6",
5959
},
60+
"backoff_limit_per_index": {
61+
Type: schema.TypeInt,
62+
Optional: true,
63+
ForceNew: true,
64+
ValidateFunc: validateNonNegativeInteger,
65+
Description: "Specifies the limit for the number of retries within an index before marking this index as failed. When enabled the number of failures per index is kept in the pod's batch.kubernetes.io/job-index-failure-count annotation. It can only be set when Job's completionMode=Indexed, and the Pod's restart policy is Never. The field is immutable.",
66+
},
6067
// This field is immutable in Jobs.
6168
"completions": {
6269
Type: schema.TypeInt,
@@ -83,6 +90,13 @@ func jobSpecFields(specUpdatable bool) map[string]*schema.Schema {
8390
ForceNew: false,
8491
Description: "Controls generation of pod labels and pod selectors. Leave unset unless you are certain what you are doing. When false or unset, the system pick labels unique to this job and appends those labels to the pod template. When true, the user is responsible for picking unique labels and specifying the selector. Failure to pick a unique label may cause this and other jobs to not function correctly. More info: https://git.k8s.io/community/contributors/design-proposals/selector-generation.md",
8592
},
93+
"max_failed_indexes": {
94+
Type: schema.TypeInt,
95+
Optional: true,
96+
ForceNew: false,
97+
ValidateFunc: validateNonNegativeInteger,
98+
Description: "Controls generation of pod labels and pod selectors. Leave unset unless you are certain what you are doing. When false or unset, the system pick labels unique to this job and appends those labels to the pod template. When true, the user is responsible for picking unique labels and specifying the selector. Failure to pick a unique label may cause this and other jobs to not function correctly. More info: https://git.k8s.io/community/contributors/design-proposals/selector-generation.md",
99+
},
86100
"parallelism": {
87101
Type: schema.TypeInt,
88102
Optional: true,

kubernetes/structure_job.go

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,14 @@ func flattenJobV1Spec(in batchv1.JobSpec, d *schema.ResourceData, meta interface
2323
att["backoff_limit"] = *in.BackoffLimit
2424
}
2525

26+
if in.BackoffLimitPerIndex != nil {
27+
att["backoff_limit_per_index"] = *in.BackoffLimitPerIndex
28+
}
29+
30+
if in.MaxFailedIndexes != nil {
31+
att["max_failed_indexes"] = *in.MaxFailedIndexes
32+
}
33+
2634
if in.Completions != nil {
2735
att["completions"] = *in.Completions
2836
}
@@ -79,6 +87,10 @@ func expandJobV1Spec(j []interface{}) (batchv1.JobSpec, error) {
7987
obj.BackoffLimit = ptr.To(int32(v))
8088
}
8189

90+
if v, ok := in["backoff_limit_per_index"].(int); in["completion_mode"] == "Indexed" && ok && v >= 0 {
91+
obj.BackoffLimitPerIndex = ptr.To(int32(v))
92+
}
93+
8294
if v, ok := in["completions"].(int); ok && v > 0 {
8395
obj.Completions = ptr.To(int32(v))
8496
}
@@ -92,6 +104,10 @@ func expandJobV1Spec(j []interface{}) (batchv1.JobSpec, error) {
92104
obj.ManualSelector = ptr.To(v.(bool))
93105
}
94106

107+
if v, ok := in["max_failed_indexes"].(int); in["completion_mode"] == "Indexed" && ok && v >= 0 {
108+
obj.MaxFailedIndexes = ptr.To(int32(v))
109+
}
110+
95111
if v, ok := in["parallelism"].(int); ok && v >= 0 {
96112
obj.Parallelism = ptr.To(int32(v))
97113
}

0 commit comments

Comments
 (0)