mirror of
https://github.com/k3s-io/kubernetes.git
synced 2025-07-22 11:21:47 +00:00
Fix validation for Job with suspend=true,completions=0 to set Complete condition
This commit is contained in:
parent
f208b6c73d
commit
3851253305
@ -379,6 +379,7 @@ func getStatusValidationOptions(newJob, oldJob *batch.Job) batchvalidation.JobSt
|
|||||||
isUncountedTerminatedPodsChanged := !apiequality.Semantic.DeepEqual(oldJob.Status.UncountedTerminatedPods, newJob.Status.UncountedTerminatedPods)
|
isUncountedTerminatedPodsChanged := !apiequality.Semantic.DeepEqual(oldJob.Status.UncountedTerminatedPods, newJob.Status.UncountedTerminatedPods)
|
||||||
isReadyChanged := !ptr.Equal(oldJob.Status.Ready, newJob.Status.Ready)
|
isReadyChanged := !ptr.Equal(oldJob.Status.Ready, newJob.Status.Ready)
|
||||||
isTerminatingChanged := !ptr.Equal(oldJob.Status.Terminating, newJob.Status.Terminating)
|
isTerminatingChanged := !ptr.Equal(oldJob.Status.Terminating, newJob.Status.Terminating)
|
||||||
|
isSuspendedWithZeroCompletions := newJob.Spec.Completions != nil && *newJob.Spec.Completions == 0 && newJob.Spec.Suspend != nil && *newJob.Spec.Suspend
|
||||||
|
|
||||||
return batchvalidation.JobStatusValidationOptions{
|
return batchvalidation.JobStatusValidationOptions{
|
||||||
// We allow to decrease the counter for succeeded pods for jobs which
|
// We allow to decrease the counter for succeeded pods for jobs which
|
||||||
@ -394,7 +395,7 @@ func getStatusValidationOptions(newJob, oldJob *batch.Job) batchvalidation.JobSt
|
|||||||
RejectFailedJobWithoutFailureTarget: isJobFailedChanged || isFailedIndexesChanged,
|
RejectFailedJobWithoutFailureTarget: isJobFailedChanged || isFailedIndexesChanged,
|
||||||
RejectCompleteJobWithoutSuccessCriteriaMet: isJobCompleteChanged || isJobSuccessCriteriaMetChanged,
|
RejectCompleteJobWithoutSuccessCriteriaMet: isJobCompleteChanged || isJobSuccessCriteriaMetChanged,
|
||||||
RejectFinishedJobWithActivePods: isJobFinishedChanged || isActiveChanged,
|
RejectFinishedJobWithActivePods: isJobFinishedChanged || isActiveChanged,
|
||||||
RejectFinishedJobWithoutStartTime: isJobFinishedChanged || isStartTimeChanged,
|
RejectFinishedJobWithoutStartTime: (isJobFinishedChanged || isStartTimeChanged) && !isSuspendedWithZeroCompletions,
|
||||||
RejectFinishedJobWithUncountedTerminatedPods: isJobFinishedChanged || isUncountedTerminatedPodsChanged,
|
RejectFinishedJobWithUncountedTerminatedPods: isJobFinishedChanged || isUncountedTerminatedPodsChanged,
|
||||||
RejectStartTimeUpdateForUnsuspendedJob: isStartTimeChanged,
|
RejectStartTimeUpdateForUnsuspendedJob: isStartTimeChanged,
|
||||||
RejectCompletionTimeBeforeStartTime: isStartTimeChanged || isCompletionTimeChanged,
|
RejectCompletionTimeBeforeStartTime: isStartTimeChanged || isCompletionTimeChanged,
|
||||||
|
@ -3535,6 +3535,36 @@ func TestStatusStrategy_ValidateUpdate(t *testing.T) {
|
|||||||
{Type: field.ErrorTypeInvalid, Field: "status.ready"},
|
{Type: field.ErrorTypeInvalid, Field: "status.ready"},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
"valid transition to Complete for suspended Job with completions=0; without startTime": {
|
||||||
|
enableJobManagedBy: true,
|
||||||
|
job: &batch.Job{
|
||||||
|
ObjectMeta: validObjectMeta,
|
||||||
|
Spec: batch.JobSpec{
|
||||||
|
Completions: ptr.To[int32](0),
|
||||||
|
Suspend: ptr.To(true),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
newJob: &batch.Job{
|
||||||
|
ObjectMeta: validObjectMeta,
|
||||||
|
Spec: batch.JobSpec{
|
||||||
|
Completions: ptr.To[int32](0),
|
||||||
|
Suspend: ptr.To(true),
|
||||||
|
},
|
||||||
|
Status: batch.JobStatus{
|
||||||
|
CompletionTime: &now,
|
||||||
|
Conditions: []batch.JobCondition{
|
||||||
|
{
|
||||||
|
Type: batch.JobSuccessCriteriaMet,
|
||||||
|
Status: api.ConditionTrue,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Type: batch.JobComplete,
|
||||||
|
Status: api.ConditionTrue,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
}
|
}
|
||||||
for name, tc := range cases {
|
for name, tc := range cases {
|
||||||
t.Run(name, func(t *testing.T) {
|
t.Run(name, func(t *testing.T) {
|
||||||
|
@ -2801,6 +2801,29 @@ func TestParallelJobWithCompletions(t *testing.T) {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// TestSuspendedJobWithZeroCompletions verifies the suspended Job with
|
||||||
|
// completions=0 is marked as Complete.
|
||||||
|
func TestSuspendedJobWithZeroCompletions(t *testing.T) {
|
||||||
|
closeFn, restConfig, clientSet, ns := setup(t, "suspended-with-zero-completions")
|
||||||
|
t.Cleanup(closeFn)
|
||||||
|
ctx, cancel := startJobControllerAndWaitForCaches(t, restConfig)
|
||||||
|
t.Cleanup(func() {
|
||||||
|
cancel()
|
||||||
|
})
|
||||||
|
jobObj, err := createJobWithDefaults(ctx, clientSet, ns.Name, &batchv1.Job{
|
||||||
|
Spec: batchv1.JobSpec{
|
||||||
|
Completions: ptr.To[int32](0),
|
||||||
|
Suspend: ptr.To(true),
|
||||||
|
},
|
||||||
|
})
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("Failed to create Job: %v", err)
|
||||||
|
}
|
||||||
|
for _, condition := range []batchv1.JobConditionType{batchv1.JobSuccessCriteriaMet, batchv1.JobComplete} {
|
||||||
|
validateJobCondition(ctx, t, clientSet, jobObj, condition)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
func TestIndexedJob(t *testing.T) {
|
func TestIndexedJob(t *testing.T) {
|
||||||
t.Cleanup(setDurationDuringTest(&jobcontroller.DefaultJobPodFailureBackOff, fastPodFailureBackoff))
|
t.Cleanup(setDurationDuringTest(&jobcontroller.DefaultJobPodFailureBackOff, fastPodFailureBackoff))
|
||||||
closeFn, restConfig, clientSet, ns := setup(t, "indexed")
|
closeFn, restConfig, clientSet, ns := setup(t, "indexed")
|
||||||
|
Loading…
Reference in New Issue
Block a user