Extend the Job API for BackoffLimitPerIndex
This commit is contained in:
@@ -160,6 +160,28 @@ func TestValidateJob(t *testing.T) {
|
||||
},
|
||||
},
|
||||
},
|
||||
"valid pod failure policy with FailIndex": {
|
||||
job: batch.Job{
|
||||
ObjectMeta: validJobObjectMeta,
|
||||
Spec: batch.JobSpec{
|
||||
CompletionMode: completionModePtr(batch.IndexedCompletion),
|
||||
Completions: pointer.Int32(2),
|
||||
BackoffLimitPerIndex: pointer.Int32(1),
|
||||
Selector: validGeneratedSelector,
|
||||
ManualSelector: pointer.Bool(true),
|
||||
Template: validPodTemplateSpecForGeneratedRestartPolicyNever,
|
||||
PodFailurePolicy: &batch.PodFailurePolicy{
|
||||
Rules: []batch.PodFailurePolicyRule{{
|
||||
Action: batch.PodFailurePolicyActionFailIndex,
|
||||
OnExitCodes: &batch.PodFailurePolicyOnExitCodesRequirement{
|
||||
Operator: batch.PodFailurePolicyOnExitCodesOpIn,
|
||||
Values: []int32{10},
|
||||
},
|
||||
}},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
"valid manual selector": {
|
||||
opts: JobValidationOptions{RequirePrefixedLabels: true},
|
||||
job: batch.Job{
|
||||
@@ -236,6 +258,36 @@ func TestValidateJob(t *testing.T) {
|
||||
},
|
||||
},
|
||||
},
|
||||
"valid parallelism and maxFailedIndexes for high completions when backoffLimitPerIndex is used": {
|
||||
job: batch.Job{
|
||||
ObjectMeta: validJobObjectMeta,
|
||||
Spec: batch.JobSpec{
|
||||
Completions: pointer.Int32(100_000),
|
||||
Parallelism: pointer.Int32(100_000),
|
||||
MaxFailedIndexes: pointer.Int32(100_000),
|
||||
BackoffLimitPerIndex: pointer.Int32(1),
|
||||
CompletionMode: completionModePtr(batch.IndexedCompletion),
|
||||
Selector: validGeneratedSelector,
|
||||
Template: validPodTemplateSpecForGenerated,
|
||||
},
|
||||
},
|
||||
opts: JobValidationOptions{RequirePrefixedLabels: true},
|
||||
},
|
||||
"valid parallelism and maxFailedIndexes for unlimited completions when backoffLimitPerIndex is used": {
|
||||
job: batch.Job{
|
||||
ObjectMeta: validJobObjectMeta,
|
||||
Spec: batch.JobSpec{
|
||||
Completions: pointer.Int32(1_000_000_000),
|
||||
Parallelism: pointer.Int32(10_000),
|
||||
MaxFailedIndexes: pointer.Int32(10_000),
|
||||
BackoffLimitPerIndex: pointer.Int32(1),
|
||||
CompletionMode: completionModePtr(batch.IndexedCompletion),
|
||||
Selector: validGeneratedSelector,
|
||||
Template: validPodTemplateSpecForGenerated,
|
||||
},
|
||||
},
|
||||
opts: JobValidationOptions{RequirePrefixedLabels: true},
|
||||
},
|
||||
"valid job tracking annotation": {
|
||||
opts: JobValidationOptions{
|
||||
RequirePrefixedLabels: true,
|
||||
@@ -476,7 +528,7 @@ func TestValidateJob(t *testing.T) {
|
||||
},
|
||||
opts: JobValidationOptions{RequirePrefixedLabels: true},
|
||||
},
|
||||
`spec.podFailurePolicy.rules[0].action: Required value: valid values: ["Count" "FailJob" "Ignore"]`: {
|
||||
`spec.podFailurePolicy.rules[0].action: Required value: valid values: ["Count" "FailIndex" "FailJob" "Ignore"]`: {
|
||||
job: batch.Job{
|
||||
ObjectMeta: validJobObjectMeta,
|
||||
Spec: batch.JobSpec{
|
||||
@@ -584,7 +636,7 @@ func TestValidateJob(t *testing.T) {
|
||||
},
|
||||
opts: JobValidationOptions{RequirePrefixedLabels: true},
|
||||
},
|
||||
`spec.podFailurePolicy.rules[0].action: Unsupported value: "UnknownAction": supported values: "Count", "FailJob", "Ignore"`: {
|
||||
`spec.podFailurePolicy.rules[0].action: Unsupported value: "UnknownAction": supported values: "Count", "FailIndex", "FailJob", "Ignore"`: {
|
||||
job: batch.Job{
|
||||
ObjectMeta: validJobObjectMeta,
|
||||
Spec: batch.JobSpec{
|
||||
@@ -749,6 +801,124 @@ func TestValidateJob(t *testing.T) {
|
||||
},
|
||||
opts: JobValidationOptions{RequirePrefixedLabels: true},
|
||||
},
|
||||
"spec.backoffLimitPerIndex: Invalid value: 1: requires indexed completion mode": {
|
||||
job: batch.Job{
|
||||
ObjectMeta: validJobObjectMeta,
|
||||
Spec: batch.JobSpec{
|
||||
BackoffLimitPerIndex: pointer.Int32(1),
|
||||
Selector: validGeneratedSelector,
|
||||
Template: validPodTemplateSpecForGenerated,
|
||||
},
|
||||
},
|
||||
opts: JobValidationOptions{RequirePrefixedLabels: true},
|
||||
},
|
||||
"spec.backoffLimitPerIndex:must be greater than or equal to 0": {
|
||||
job: batch.Job{
|
||||
ObjectMeta: validJobObjectMeta,
|
||||
Spec: batch.JobSpec{
|
||||
BackoffLimitPerIndex: pointer.Int32(-1),
|
||||
CompletionMode: completionModePtr(batch.IndexedCompletion),
|
||||
Selector: validGeneratedSelector,
|
||||
Template: validPodTemplateSpecForGenerated,
|
||||
},
|
||||
},
|
||||
opts: JobValidationOptions{RequirePrefixedLabels: true},
|
||||
},
|
||||
"spec.maxFailedIndexes: Invalid value: 11: must be less than or equal to completions": {
|
||||
job: batch.Job{
|
||||
ObjectMeta: validJobObjectMeta,
|
||||
Spec: batch.JobSpec{
|
||||
Completions: pointer.Int32(10),
|
||||
MaxFailedIndexes: pointer.Int32(11),
|
||||
BackoffLimitPerIndex: pointer.Int32(1),
|
||||
CompletionMode: completionModePtr(batch.IndexedCompletion),
|
||||
Selector: validGeneratedSelector,
|
||||
Template: validPodTemplateSpecForGenerated,
|
||||
},
|
||||
},
|
||||
opts: JobValidationOptions{RequirePrefixedLabels: true},
|
||||
},
|
||||
"spec.maxFailedIndexes: Required value: must be specified when completions is above 100000": {
|
||||
job: batch.Job{
|
||||
ObjectMeta: validJobObjectMeta,
|
||||
Spec: batch.JobSpec{
|
||||
Completions: pointer.Int32(100_001),
|
||||
BackoffLimitPerIndex: pointer.Int32(1),
|
||||
CompletionMode: completionModePtr(batch.IndexedCompletion),
|
||||
Selector: validGeneratedSelector,
|
||||
Template: validPodTemplateSpecForGenerated,
|
||||
},
|
||||
},
|
||||
opts: JobValidationOptions{RequirePrefixedLabels: true},
|
||||
},
|
||||
"spec.parallelism: Invalid value: 50000: must be less than or equal to 10000 when completions are above 100000 and used with backoff limit per index": {
|
||||
job: batch.Job{
|
||||
ObjectMeta: validJobObjectMeta,
|
||||
Spec: batch.JobSpec{
|
||||
Completions: pointer.Int32(100_001),
|
||||
Parallelism: pointer.Int32(50_000),
|
||||
BackoffLimitPerIndex: pointer.Int32(1),
|
||||
MaxFailedIndexes: pointer.Int32(1),
|
||||
CompletionMode: completionModePtr(batch.IndexedCompletion),
|
||||
Selector: validGeneratedSelector,
|
||||
Template: validPodTemplateSpecForGenerated,
|
||||
},
|
||||
},
|
||||
opts: JobValidationOptions{RequirePrefixedLabels: true},
|
||||
},
|
||||
"spec.maxFailedIndexes: Invalid value: 100001: must be less than or equal to 100000": {
|
||||
job: batch.Job{
|
||||
ObjectMeta: validJobObjectMeta,
|
||||
Spec: batch.JobSpec{
|
||||
Completions: pointer.Int32(100_001),
|
||||
BackoffLimitPerIndex: pointer.Int32(1),
|
||||
MaxFailedIndexes: pointer.Int32(100_001),
|
||||
CompletionMode: completionModePtr(batch.IndexedCompletion),
|
||||
Selector: validGeneratedSelector,
|
||||
Template: validPodTemplateSpecForGenerated,
|
||||
},
|
||||
},
|
||||
opts: JobValidationOptions{RequirePrefixedLabels: true},
|
||||
},
|
||||
"spec.maxFailedIndexes: Invalid value: 50000: must be less than or equal to 10000 when completions are above 100000 and used with backoff limit per index": {
|
||||
job: batch.Job{
|
||||
ObjectMeta: validJobObjectMeta,
|
||||
Spec: batch.JobSpec{
|
||||
Completions: pointer.Int32(100_001),
|
||||
BackoffLimitPerIndex: pointer.Int32(1),
|
||||
MaxFailedIndexes: pointer.Int32(50_000),
|
||||
CompletionMode: completionModePtr(batch.IndexedCompletion),
|
||||
Selector: validGeneratedSelector,
|
||||
Template: validPodTemplateSpecForGenerated,
|
||||
},
|
||||
},
|
||||
opts: JobValidationOptions{RequirePrefixedLabels: true},
|
||||
},
|
||||
"spec.maxFailedIndexes:must be greater than or equal to 0": {
|
||||
job: batch.Job{
|
||||
ObjectMeta: validJobObjectMeta,
|
||||
Spec: batch.JobSpec{
|
||||
BackoffLimitPerIndex: pointer.Int32(1),
|
||||
MaxFailedIndexes: pointer.Int32(-1),
|
||||
CompletionMode: completionModePtr(batch.IndexedCompletion),
|
||||
Selector: validGeneratedSelector,
|
||||
Template: validPodTemplateSpecForGenerated,
|
||||
},
|
||||
},
|
||||
opts: JobValidationOptions{RequirePrefixedLabels: true},
|
||||
},
|
||||
"spec.backoffLimitPerIndex: Required value: when maxFailedIndexes is specified": {
|
||||
job: batch.Job{
|
||||
ObjectMeta: validJobObjectMeta,
|
||||
Spec: batch.JobSpec{
|
||||
MaxFailedIndexes: pointer.Int32(1),
|
||||
CompletionMode: completionModePtr(batch.IndexedCompletion),
|
||||
Selector: validGeneratedSelector,
|
||||
Template: validPodTemplateSpecForGenerated,
|
||||
},
|
||||
},
|
||||
opts: JobValidationOptions{RequirePrefixedLabels: true},
|
||||
},
|
||||
"spec.completions:must be greater than or equal to 0": {
|
||||
job: batch.Job{
|
||||
ObjectMeta: metav1.ObjectMeta{
|
||||
@@ -1243,12 +1413,117 @@ func TestValidateJobUpdate(t *testing.T) {
|
||||
Field: "spec.podFailurePolicy",
|
||||
},
|
||||
},
|
||||
"set backoff limit per index": {
|
||||
old: batch.Job{
|
||||
ObjectMeta: metav1.ObjectMeta{Name: "abc", Namespace: metav1.NamespaceDefault},
|
||||
Spec: batch.JobSpec{
|
||||
Selector: validGeneratedSelector,
|
||||
Template: validPodTemplateSpecForGeneratedRestartPolicyNever,
|
||||
Completions: pointer.Int32(3),
|
||||
CompletionMode: completionModePtr(batch.IndexedCompletion),
|
||||
},
|
||||
},
|
||||
update: func(job *batch.Job) {
|
||||
job.Spec.BackoffLimitPerIndex = pointer.Int32(1)
|
||||
},
|
||||
err: &field.Error{
|
||||
Type: field.ErrorTypeInvalid,
|
||||
Field: "spec.backoffLimitPerIndex",
|
||||
},
|
||||
},
|
||||
"unset backoff limit per index": {
|
||||
old: batch.Job{
|
||||
ObjectMeta: metav1.ObjectMeta{Name: "abc", Namespace: metav1.NamespaceDefault},
|
||||
Spec: batch.JobSpec{
|
||||
Selector: validGeneratedSelector,
|
||||
Template: validPodTemplateSpecForGeneratedRestartPolicyNever,
|
||||
Completions: pointer.Int32(3),
|
||||
CompletionMode: completionModePtr(batch.IndexedCompletion),
|
||||
BackoffLimitPerIndex: pointer.Int32(1),
|
||||
},
|
||||
},
|
||||
update: func(job *batch.Job) {
|
||||
job.Spec.BackoffLimitPerIndex = nil
|
||||
},
|
||||
err: &field.Error{
|
||||
Type: field.ErrorTypeInvalid,
|
||||
Field: "spec.backoffLimitPerIndex",
|
||||
},
|
||||
},
|
||||
"update backoff limit per index": {
|
||||
old: batch.Job{
|
||||
ObjectMeta: metav1.ObjectMeta{Name: "abc", Namespace: metav1.NamespaceDefault},
|
||||
Spec: batch.JobSpec{
|
||||
Selector: validGeneratedSelector,
|
||||
Template: validPodTemplateSpecForGeneratedRestartPolicyNever,
|
||||
Completions: pointer.Int32(3),
|
||||
CompletionMode: completionModePtr(batch.IndexedCompletion),
|
||||
BackoffLimitPerIndex: pointer.Int32(1),
|
||||
},
|
||||
},
|
||||
update: func(job *batch.Job) {
|
||||
job.Spec.BackoffLimitPerIndex = pointer.Int32(2)
|
||||
},
|
||||
err: &field.Error{
|
||||
Type: field.ErrorTypeInvalid,
|
||||
Field: "spec.backoffLimitPerIndex",
|
||||
},
|
||||
},
|
||||
"set max failed indexes": {
|
||||
old: batch.Job{
|
||||
ObjectMeta: metav1.ObjectMeta{Name: "abc", Namespace: metav1.NamespaceDefault},
|
||||
Spec: batch.JobSpec{
|
||||
Selector: validGeneratedSelector,
|
||||
Template: validPodTemplateSpecForGeneratedRestartPolicyNever,
|
||||
Completions: pointer.Int32(3),
|
||||
CompletionMode: completionModePtr(batch.IndexedCompletion),
|
||||
BackoffLimitPerIndex: pointer.Int32(1),
|
||||
},
|
||||
},
|
||||
update: func(job *batch.Job) {
|
||||
job.Spec.MaxFailedIndexes = pointer.Int32(1)
|
||||
},
|
||||
},
|
||||
"unset max failed indexes": {
|
||||
old: batch.Job{
|
||||
ObjectMeta: metav1.ObjectMeta{Name: "abc", Namespace: metav1.NamespaceDefault},
|
||||
Spec: batch.JobSpec{
|
||||
Selector: validGeneratedSelector,
|
||||
Template: validPodTemplateSpecForGeneratedRestartPolicyNever,
|
||||
Completions: pointer.Int32(3),
|
||||
CompletionMode: completionModePtr(batch.IndexedCompletion),
|
||||
BackoffLimitPerIndex: pointer.Int32(1),
|
||||
MaxFailedIndexes: pointer.Int32(1),
|
||||
},
|
||||
},
|
||||
update: func(job *batch.Job) {
|
||||
job.Spec.MaxFailedIndexes = nil
|
||||
},
|
||||
},
|
||||
"update max failed indexes": {
|
||||
old: batch.Job{
|
||||
ObjectMeta: metav1.ObjectMeta{Name: "abc", Namespace: metav1.NamespaceDefault},
|
||||
Spec: batch.JobSpec{
|
||||
Selector: validGeneratedSelector,
|
||||
Template: validPodTemplateSpecForGeneratedRestartPolicyNever,
|
||||
Completions: pointer.Int32(3),
|
||||
CompletionMode: completionModePtr(batch.IndexedCompletion),
|
||||
BackoffLimitPerIndex: pointer.Int32(1),
|
||||
MaxFailedIndexes: pointer.Int32(1),
|
||||
},
|
||||
},
|
||||
update: func(job *batch.Job) {
|
||||
job.Spec.MaxFailedIndexes = pointer.Int32(2)
|
||||
},
|
||||
},
|
||||
"immutable pod template": {
|
||||
old: batch.Job{
|
||||
ObjectMeta: metav1.ObjectMeta{Name: "abc", Namespace: metav1.NamespaceDefault},
|
||||
Spec: batch.JobSpec{
|
||||
Selector: validGeneratedSelector,
|
||||
Template: validPodTemplateSpecForGenerated,
|
||||
Selector: validGeneratedSelector,
|
||||
Template: validPodTemplateSpecForGenerated,
|
||||
Completions: pointer.Int32(3),
|
||||
CompletionMode: completionModePtr(batch.IndexedCompletion),
|
||||
},
|
||||
},
|
||||
update: func(job *batch.Job) {
|
||||
|
Reference in New Issue
Block a user