mirror of
				https://github.com/optim-enterprises-bv/kubernetes.git
				synced 2025-11-04 04:08:16 +00:00 
			
		
		
		
	Add more test cases for SuccessCriteriaMet
Cleanup error messages in the new code Add validation for the Job controller fields
This commit is contained in:
		@@ -518,6 +518,16 @@ func validateJobStatus(job *batch.Job, fldPath *field.Path, opts JobStatusValida
 | 
				
			|||||||
			allErrs = append(allErrs, field.Invalid(fldPath.Child("completionTime"), status.CompletionTime, "completionTime cannot be set before startTime"))
 | 
								allErrs = append(allErrs, field.Invalid(fldPath.Child("completionTime"), status.CompletionTime, "completionTime cannot be set before startTime"))
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
						if opts.RejectFailedJobWithoutFailureTarget {
 | 
				
			||||||
 | 
							if IsJobFailed(job) && !isJobFailureTarget(job) {
 | 
				
			||||||
 | 
								allErrs = append(allErrs, field.Invalid(fldPath.Child("conditions"), field.OmitValueType{}, "cannot set Failed=True condition without the FailureTarget=true condition"))
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						if opts.RejectCompleteJobWithoutSuccessCriteriaMet {
 | 
				
			||||||
 | 
							if IsJobComplete(job) && !isJobSuccessCriteriaMet(job) {
 | 
				
			||||||
 | 
								allErrs = append(allErrs, field.Invalid(fldPath.Child("conditions"), field.OmitValueType{}, "cannot set Complete=True condition without the SuccessCriteriaMet=true condition"))
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
	isJobFinished := IsJobFinished(job)
 | 
						isJobFinished := IsJobFinished(job)
 | 
				
			||||||
	if opts.RejectFinishedJobWithActivePods {
 | 
						if opts.RejectFinishedJobWithActivePods {
 | 
				
			||||||
		if status.Active > 0 && isJobFinished {
 | 
							if status.Active > 0 && isJobFinished {
 | 
				
			||||||
@@ -568,6 +578,16 @@ func validateJobStatus(job *batch.Job, fldPath *field.Path, opts JobStatusValida
 | 
				
			|||||||
			}
 | 
								}
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
						if opts.RejectFinishedJobWithTerminatingPods {
 | 
				
			||||||
 | 
							if status.Terminating != nil && *status.Terminating > 0 && isJobFinished {
 | 
				
			||||||
 | 
								allErrs = append(allErrs, field.Invalid(fldPath.Child("terminating"), status.Terminating, "terminating>0 is invalid for finished job"))
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						if opts.RejectMoreReadyThanActivePods {
 | 
				
			||||||
 | 
							if status.Ready != nil && *status.Ready > status.Active {
 | 
				
			||||||
 | 
								allErrs = append(allErrs, field.Invalid(fldPath.Child("ready"), *status.Ready, "cannot set more ready pods than active"))
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
	if !opts.AllowForSuccessCriteriaMetInExtendedScope && ptr.Deref(job.Spec.CompletionMode, batch.NonIndexedCompletion) != batch.IndexedCompletion && isJobSuccessCriteriaMet(job) {
 | 
						if !opts.AllowForSuccessCriteriaMetInExtendedScope && ptr.Deref(job.Spec.CompletionMode, batch.NonIndexedCompletion) != batch.IndexedCompletion && isJobSuccessCriteriaMet(job) {
 | 
				
			||||||
		allErrs = append(allErrs, field.Invalid(fldPath.Child("conditions"), field.OmitValueType{}, "cannot set SuccessCriteriaMet to NonIndexed Job"))
 | 
							allErrs = append(allErrs, field.Invalid(fldPath.Child("conditions"), field.OmitValueType{}, "cannot set SuccessCriteriaMet to NonIndexed Job"))
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
@@ -1005,6 +1025,8 @@ type JobStatusValidationOptions struct {
 | 
				
			|||||||
	RejectFailedIndexesOverlappingCompleted      bool
 | 
						RejectFailedIndexesOverlappingCompleted      bool
 | 
				
			||||||
	RejectCompletedIndexesForNonIndexedJob       bool
 | 
						RejectCompletedIndexesForNonIndexedJob       bool
 | 
				
			||||||
	RejectFailedIndexesForNoBackoffLimitPerIndex bool
 | 
						RejectFailedIndexesForNoBackoffLimitPerIndex bool
 | 
				
			||||||
 | 
						RejectFailedJobWithoutFailureTarget          bool
 | 
				
			||||||
 | 
						RejectCompleteJobWithoutSuccessCriteriaMet   bool
 | 
				
			||||||
	RejectFinishedJobWithActivePods              bool
 | 
						RejectFinishedJobWithActivePods              bool
 | 
				
			||||||
	RejectFinishedJobWithoutStartTime            bool
 | 
						RejectFinishedJobWithoutStartTime            bool
 | 
				
			||||||
	RejectFinishedJobWithUncountedTerminatedPods bool
 | 
						RejectFinishedJobWithUncountedTerminatedPods bool
 | 
				
			||||||
@@ -1016,4 +1038,6 @@ type JobStatusValidationOptions struct {
 | 
				
			|||||||
	RejectCompleteJobWithFailedCondition         bool
 | 
						RejectCompleteJobWithFailedCondition         bool
 | 
				
			||||||
	RejectCompleteJobWithFailureTargetCondition  bool
 | 
						RejectCompleteJobWithFailureTargetCondition  bool
 | 
				
			||||||
	AllowForSuccessCriteriaMetInExtendedScope    bool
 | 
						AllowForSuccessCriteriaMetInExtendedScope    bool
 | 
				
			||||||
 | 
						RejectMoreReadyThanActivePods                bool
 | 
				
			||||||
 | 
						RejectFinishedJobWithTerminatingPods         bool
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -376,12 +376,15 @@ func getStatusValidationOptions(newJob, oldJob *batch.Job) batchvalidation.JobSt
 | 
				
			|||||||
		isJobCompleteChanged := batchvalidation.IsJobComplete(oldJob) != batchvalidation.IsJobComplete(newJob)
 | 
							isJobCompleteChanged := batchvalidation.IsJobComplete(oldJob) != batchvalidation.IsJobComplete(newJob)
 | 
				
			||||||
		isJobFailedChanged := batchvalidation.IsJobFailed(oldJob) != batchvalidation.IsJobFailed(newJob)
 | 
							isJobFailedChanged := batchvalidation.IsJobFailed(oldJob) != batchvalidation.IsJobFailed(newJob)
 | 
				
			||||||
		isJobFailureTargetChanged := batchvalidation.IsConditionTrue(oldJob.Status.Conditions, batch.JobFailureTarget) != batchvalidation.IsConditionTrue(newJob.Status.Conditions, batch.JobFailureTarget)
 | 
							isJobFailureTargetChanged := batchvalidation.IsConditionTrue(oldJob.Status.Conditions, batch.JobFailureTarget) != batchvalidation.IsConditionTrue(newJob.Status.Conditions, batch.JobFailureTarget)
 | 
				
			||||||
 | 
							isJobSuccessCriteriaMetChanged := batchvalidation.IsConditionTrue(oldJob.Status.Conditions, batch.JobSuccessCriteriaMet) != batchvalidation.IsConditionTrue(newJob.Status.Conditions, batch.JobSuccessCriteriaMet)
 | 
				
			||||||
		isCompletedIndexesChanged := oldJob.Status.CompletedIndexes != newJob.Status.CompletedIndexes
 | 
							isCompletedIndexesChanged := oldJob.Status.CompletedIndexes != newJob.Status.CompletedIndexes
 | 
				
			||||||
		isFailedIndexesChanged := !ptr.Equal(oldJob.Status.FailedIndexes, newJob.Status.FailedIndexes)
 | 
							isFailedIndexesChanged := !ptr.Equal(oldJob.Status.FailedIndexes, newJob.Status.FailedIndexes)
 | 
				
			||||||
		isActiveChanged := oldJob.Status.Active != newJob.Status.Active
 | 
							isActiveChanged := oldJob.Status.Active != newJob.Status.Active
 | 
				
			||||||
		isStartTimeChanged := !ptr.Equal(oldJob.Status.StartTime, newJob.Status.StartTime)
 | 
							isStartTimeChanged := !ptr.Equal(oldJob.Status.StartTime, newJob.Status.StartTime)
 | 
				
			||||||
		isCompletionTimeChanged := !ptr.Equal(oldJob.Status.CompletionTime, newJob.Status.CompletionTime)
 | 
							isCompletionTimeChanged := !ptr.Equal(oldJob.Status.CompletionTime, newJob.Status.CompletionTime)
 | 
				
			||||||
		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)
 | 
				
			||||||
 | 
							isTerminatingChanged := !ptr.Equal(oldJob.Status.Terminating, newJob.Status.Terminating)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		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,6 +397,8 @@ func getStatusValidationOptions(newJob, oldJob *batch.Job) batchvalidation.JobSt
 | 
				
			|||||||
			RejectCompletedIndexesForNonIndexedJob:       isCompletedIndexesChanged,
 | 
								RejectCompletedIndexesForNonIndexedJob:       isCompletedIndexesChanged,
 | 
				
			||||||
			RejectFailedIndexesForNoBackoffLimitPerIndex: isFailedIndexesChanged,
 | 
								RejectFailedIndexesForNoBackoffLimitPerIndex: isFailedIndexesChanged,
 | 
				
			||||||
			RejectFailedIndexesOverlappingCompleted:      isFailedIndexesChanged || isCompletedIndexesChanged,
 | 
								RejectFailedIndexesOverlappingCompleted:      isFailedIndexesChanged || isCompletedIndexesChanged,
 | 
				
			||||||
 | 
								RejectFailedJobWithoutFailureTarget:          isJobFailedChanged || isFailedIndexesChanged,
 | 
				
			||||||
 | 
								RejectCompleteJobWithoutSuccessCriteriaMet:   isJobCompleteChanged || isJobSuccessCriteriaMetChanged,
 | 
				
			||||||
			RejectFinishedJobWithActivePods:              isJobFinishedChanged || isActiveChanged,
 | 
								RejectFinishedJobWithActivePods:              isJobFinishedChanged || isActiveChanged,
 | 
				
			||||||
			RejectFinishedJobWithoutStartTime:            isJobFinishedChanged || isStartTimeChanged,
 | 
								RejectFinishedJobWithoutStartTime:            isJobFinishedChanged || isStartTimeChanged,
 | 
				
			||||||
			RejectFinishedJobWithUncountedTerminatedPods: isJobFinishedChanged || isUncountedTerminatedPodsChanged,
 | 
								RejectFinishedJobWithUncountedTerminatedPods: isJobFinishedChanged || isUncountedTerminatedPodsChanged,
 | 
				
			||||||
@@ -405,6 +410,8 @@ func getStatusValidationOptions(newJob, oldJob *batch.Job) batchvalidation.JobSt
 | 
				
			|||||||
			RejectCompleteJobWithFailedCondition:         isJobCompleteChanged || isJobFailedChanged,
 | 
								RejectCompleteJobWithFailedCondition:         isJobCompleteChanged || isJobFailedChanged,
 | 
				
			||||||
			RejectCompleteJobWithFailureTargetCondition:  isJobCompleteChanged || isJobFailureTargetChanged,
 | 
								RejectCompleteJobWithFailureTargetCondition:  isJobCompleteChanged || isJobFailureTargetChanged,
 | 
				
			||||||
			AllowForSuccessCriteriaMetInExtendedScope:    true,
 | 
								AllowForSuccessCriteriaMetInExtendedScope:    true,
 | 
				
			||||||
 | 
								RejectMoreReadyThanActivePods:                isReadyChanged || isActiveChanged,
 | 
				
			||||||
 | 
								RejectFinishedJobWithTerminatingPods:         isJobFinishedChanged || isTerminatingChanged,
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	if utilfeature.DefaultFeatureGate.Enabled(features.JobPodReplacementPolicy) {
 | 
						if utilfeature.DefaultFeatureGate.Enabled(features.JobPodReplacementPolicy) {
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -2155,6 +2155,51 @@ func TestStatusStrategy_ValidateUpdate(t *testing.T) {
 | 
				
			|||||||
					},
 | 
										},
 | 
				
			||||||
				},
 | 
									},
 | 
				
			||||||
			},
 | 
								},
 | 
				
			||||||
 | 
								wantErrs: field.ErrorList{
 | 
				
			||||||
 | 
									{Type: field.ErrorTypeInvalid, Field: "status.conditions"},
 | 
				
			||||||
 | 
									{Type: field.ErrorTypeInvalid, Field: "status.conditions"},
 | 
				
			||||||
 | 
									{Type: field.ErrorTypeInvalid, Field: "status.conditions"},
 | 
				
			||||||
 | 
								},
 | 
				
			||||||
 | 
							},
 | 
				
			||||||
 | 
							"invalid addition of Complete=True without SuccessCriteriaMet=True": {
 | 
				
			||||||
 | 
								enableJobManagedBy: true,
 | 
				
			||||||
 | 
								job: &batch.Job{
 | 
				
			||||||
 | 
									ObjectMeta: validObjectMeta,
 | 
				
			||||||
 | 
								},
 | 
				
			||||||
 | 
								newJob: &batch.Job{
 | 
				
			||||||
 | 
									ObjectMeta: validObjectMeta,
 | 
				
			||||||
 | 
									Status: batch.JobStatus{
 | 
				
			||||||
 | 
										StartTime:      &now,
 | 
				
			||||||
 | 
										CompletionTime: &now,
 | 
				
			||||||
 | 
										Conditions: []batch.JobCondition{
 | 
				
			||||||
 | 
											{
 | 
				
			||||||
 | 
												Type:   batch.JobComplete,
 | 
				
			||||||
 | 
												Status: api.ConditionTrue,
 | 
				
			||||||
 | 
											},
 | 
				
			||||||
 | 
										},
 | 
				
			||||||
 | 
									},
 | 
				
			||||||
 | 
								},
 | 
				
			||||||
 | 
								wantErrs: field.ErrorList{
 | 
				
			||||||
 | 
									{Type: field.ErrorTypeInvalid, Field: "status.conditions"},
 | 
				
			||||||
 | 
								},
 | 
				
			||||||
 | 
							},
 | 
				
			||||||
 | 
							"invalid addition of Failed=True without FailureTarget=True": {
 | 
				
			||||||
 | 
								enableJobManagedBy: true,
 | 
				
			||||||
 | 
								job: &batch.Job{
 | 
				
			||||||
 | 
									ObjectMeta: validObjectMeta,
 | 
				
			||||||
 | 
								},
 | 
				
			||||||
 | 
								newJob: &batch.Job{
 | 
				
			||||||
 | 
									ObjectMeta: validObjectMeta,
 | 
				
			||||||
 | 
									Status: batch.JobStatus{
 | 
				
			||||||
 | 
										StartTime: &now,
 | 
				
			||||||
 | 
										Conditions: []batch.JobCondition{
 | 
				
			||||||
 | 
											{
 | 
				
			||||||
 | 
												Type:   batch.JobFailed,
 | 
				
			||||||
 | 
												Status: api.ConditionTrue,
 | 
				
			||||||
 | 
											},
 | 
				
			||||||
 | 
										},
 | 
				
			||||||
 | 
									},
 | 
				
			||||||
 | 
								},
 | 
				
			||||||
			wantErrs: field.ErrorList{
 | 
								wantErrs: field.ErrorList{
 | 
				
			||||||
				{Type: field.ErrorTypeInvalid, Field: "status.conditions"},
 | 
									{Type: field.ErrorTypeInvalid, Field: "status.conditions"},
 | 
				
			||||||
			},
 | 
								},
 | 
				
			||||||
@@ -2179,11 +2224,23 @@ func TestStatusStrategy_ValidateUpdate(t *testing.T) {
 | 
				
			|||||||
			enableJobManagedBy: true,
 | 
								enableJobManagedBy: true,
 | 
				
			||||||
			job: &batch.Job{
 | 
								job: &batch.Job{
 | 
				
			||||||
				ObjectMeta: validObjectMeta,
 | 
									ObjectMeta: validObjectMeta,
 | 
				
			||||||
 | 
									Status: batch.JobStatus{
 | 
				
			||||||
 | 
										Conditions: []batch.JobCondition{
 | 
				
			||||||
 | 
											{
 | 
				
			||||||
 | 
												Type:   batch.JobFailureTarget,
 | 
				
			||||||
 | 
												Status: api.ConditionTrue,
 | 
				
			||||||
 | 
											},
 | 
				
			||||||
 | 
										},
 | 
				
			||||||
 | 
									},
 | 
				
			||||||
			},
 | 
								},
 | 
				
			||||||
			newJob: &batch.Job{
 | 
								newJob: &batch.Job{
 | 
				
			||||||
				ObjectMeta: validObjectMeta,
 | 
									ObjectMeta: validObjectMeta,
 | 
				
			||||||
				Status: batch.JobStatus{
 | 
									Status: batch.JobStatus{
 | 
				
			||||||
					Conditions: []batch.JobCondition{
 | 
										Conditions: []batch.JobCondition{
 | 
				
			||||||
 | 
											{
 | 
				
			||||||
 | 
												Type:   batch.JobFailureTarget,
 | 
				
			||||||
 | 
												Status: api.ConditionTrue,
 | 
				
			||||||
 | 
											},
 | 
				
			||||||
						{
 | 
											{
 | 
				
			||||||
							Type:   batch.JobFailed,
 | 
												Type:   batch.JobFailed,
 | 
				
			||||||
							Status: api.ConditionTrue,
 | 
												Status: api.ConditionTrue,
 | 
				
			||||||
@@ -2199,12 +2256,24 @@ func TestStatusStrategy_ValidateUpdate(t *testing.T) {
 | 
				
			|||||||
			enableJobManagedBy: true,
 | 
								enableJobManagedBy: true,
 | 
				
			||||||
			job: &batch.Job{
 | 
								job: &batch.Job{
 | 
				
			||||||
				ObjectMeta: validObjectMeta,
 | 
									ObjectMeta: validObjectMeta,
 | 
				
			||||||
 | 
									Status: batch.JobStatus{
 | 
				
			||||||
 | 
										Conditions: []batch.JobCondition{
 | 
				
			||||||
 | 
											{
 | 
				
			||||||
 | 
												Type:   batch.JobSuccessCriteriaMet,
 | 
				
			||||||
 | 
												Status: api.ConditionTrue,
 | 
				
			||||||
 | 
											},
 | 
				
			||||||
 | 
										},
 | 
				
			||||||
 | 
									},
 | 
				
			||||||
			},
 | 
								},
 | 
				
			||||||
			newJob: &batch.Job{
 | 
								newJob: &batch.Job{
 | 
				
			||||||
				ObjectMeta: validObjectMeta,
 | 
									ObjectMeta: validObjectMeta,
 | 
				
			||||||
				Status: batch.JobStatus{
 | 
									Status: batch.JobStatus{
 | 
				
			||||||
					CompletionTime: &now,
 | 
										CompletionTime: &now,
 | 
				
			||||||
					Conditions: []batch.JobCondition{
 | 
										Conditions: []batch.JobCondition{
 | 
				
			||||||
 | 
											{
 | 
				
			||||||
 | 
												Type:   batch.JobSuccessCriteriaMet,
 | 
				
			||||||
 | 
												Status: api.ConditionTrue,
 | 
				
			||||||
 | 
											},
 | 
				
			||||||
						{
 | 
											{
 | 
				
			||||||
							Type:   batch.JobComplete,
 | 
												Type:   batch.JobComplete,
 | 
				
			||||||
							Status: api.ConditionTrue,
 | 
												Status: api.ConditionTrue,
 | 
				
			||||||
@@ -2220,6 +2289,16 @@ func TestStatusStrategy_ValidateUpdate(t *testing.T) {
 | 
				
			|||||||
			enableJobManagedBy: true,
 | 
								enableJobManagedBy: true,
 | 
				
			||||||
			job: &batch.Job{
 | 
								job: &batch.Job{
 | 
				
			||||||
				ObjectMeta: validObjectMeta,
 | 
									ObjectMeta: validObjectMeta,
 | 
				
			||||||
 | 
									Status: batch.JobStatus{
 | 
				
			||||||
 | 
										StartTime: &now,
 | 
				
			||||||
 | 
										Active:    1,
 | 
				
			||||||
 | 
										Conditions: []batch.JobCondition{
 | 
				
			||||||
 | 
											{
 | 
				
			||||||
 | 
												Type:   batch.JobSuccessCriteriaMet,
 | 
				
			||||||
 | 
												Status: api.ConditionTrue,
 | 
				
			||||||
 | 
											},
 | 
				
			||||||
 | 
										},
 | 
				
			||||||
 | 
									},
 | 
				
			||||||
			},
 | 
								},
 | 
				
			||||||
			newJob: &batch.Job{
 | 
								newJob: &batch.Job{
 | 
				
			||||||
				ObjectMeta: validObjectMeta,
 | 
									ObjectMeta: validObjectMeta,
 | 
				
			||||||
@@ -2228,6 +2307,10 @@ func TestStatusStrategy_ValidateUpdate(t *testing.T) {
 | 
				
			|||||||
					CompletionTime: &now,
 | 
										CompletionTime: &now,
 | 
				
			||||||
					Active:         1,
 | 
										Active:         1,
 | 
				
			||||||
					Conditions: []batch.JobCondition{
 | 
										Conditions: []batch.JobCondition{
 | 
				
			||||||
 | 
											{
 | 
				
			||||||
 | 
												Type:   batch.JobSuccessCriteriaMet,
 | 
				
			||||||
 | 
												Status: api.ConditionTrue,
 | 
				
			||||||
 | 
											},
 | 
				
			||||||
						{
 | 
											{
 | 
				
			||||||
							Type:   batch.JobComplete,
 | 
												Type:   batch.JobComplete,
 | 
				
			||||||
							Status: api.ConditionTrue,
 | 
												Status: api.ConditionTrue,
 | 
				
			||||||
@@ -2239,30 +2322,94 @@ func TestStatusStrategy_ValidateUpdate(t *testing.T) {
 | 
				
			|||||||
				{Type: field.ErrorTypeInvalid, Field: "status.active"},
 | 
									{Type: field.ErrorTypeInvalid, Field: "status.active"},
 | 
				
			||||||
			},
 | 
								},
 | 
				
			||||||
		},
 | 
							},
 | 
				
			||||||
		"transition to Failed condition with terminating>0 and ready>0": {
 | 
							"invalid attempt to transition to Failed=True with terminating > 0": {
 | 
				
			||||||
			enableJobManagedBy: true,
 | 
								enableJobManagedBy: true,
 | 
				
			||||||
			job: &batch.Job{
 | 
								job: &batch.Job{
 | 
				
			||||||
				ObjectMeta: validObjectMeta,
 | 
									ObjectMeta: validObjectMeta,
 | 
				
			||||||
 | 
									Status: batch.JobStatus{
 | 
				
			||||||
 | 
										StartTime: &now,
 | 
				
			||||||
 | 
										Conditions: []batch.JobCondition{
 | 
				
			||||||
 | 
											{
 | 
				
			||||||
 | 
												Type:   batch.JobFailureTarget,
 | 
				
			||||||
 | 
												Status: api.ConditionTrue,
 | 
				
			||||||
 | 
											},
 | 
				
			||||||
 | 
										},
 | 
				
			||||||
 | 
										Terminating: ptr.To[int32](1),
 | 
				
			||||||
 | 
									},
 | 
				
			||||||
			},
 | 
								},
 | 
				
			||||||
			newJob: &batch.Job{
 | 
								newJob: &batch.Job{
 | 
				
			||||||
				ObjectMeta: validObjectMeta,
 | 
									ObjectMeta: validObjectMeta,
 | 
				
			||||||
				Status: batch.JobStatus{
 | 
									Status: batch.JobStatus{
 | 
				
			||||||
					StartTime: &now,
 | 
										StartTime: &now,
 | 
				
			||||||
					Conditions: []batch.JobCondition{
 | 
										Conditions: []batch.JobCondition{
 | 
				
			||||||
 | 
											{
 | 
				
			||||||
 | 
												Type:   batch.JobFailureTarget,
 | 
				
			||||||
 | 
												Status: api.ConditionTrue,
 | 
				
			||||||
 | 
											},
 | 
				
			||||||
						{
 | 
											{
 | 
				
			||||||
							Type:   batch.JobFailed,
 | 
												Type:   batch.JobFailed,
 | 
				
			||||||
							Status: api.ConditionTrue,
 | 
												Status: api.ConditionTrue,
 | 
				
			||||||
						},
 | 
											},
 | 
				
			||||||
					},
 | 
										},
 | 
				
			||||||
					Terminating: ptr.To[int32](1),
 | 
										Terminating: ptr.To[int32](1),
 | 
				
			||||||
					Ready:       ptr.To[int32](1),
 | 
					 | 
				
			||||||
				},
 | 
									},
 | 
				
			||||||
			},
 | 
								},
 | 
				
			||||||
 | 
								wantErrs: field.ErrorList{
 | 
				
			||||||
 | 
									{Type: field.ErrorTypeInvalid, Field: "status.terminating"},
 | 
				
			||||||
 | 
								},
 | 
				
			||||||
 | 
							},
 | 
				
			||||||
 | 
							"invalid attempt to transition to Failed=True with active > 0": {
 | 
				
			||||||
 | 
								enableJobManagedBy: true,
 | 
				
			||||||
 | 
								job: &batch.Job{
 | 
				
			||||||
 | 
									ObjectMeta: validObjectMeta,
 | 
				
			||||||
 | 
									Status: batch.JobStatus{
 | 
				
			||||||
 | 
										StartTime: &now,
 | 
				
			||||||
 | 
										Conditions: []batch.JobCondition{
 | 
				
			||||||
 | 
											{
 | 
				
			||||||
 | 
												Type:   batch.JobFailureTarget,
 | 
				
			||||||
 | 
												Status: api.ConditionTrue,
 | 
				
			||||||
 | 
											},
 | 
				
			||||||
 | 
										},
 | 
				
			||||||
 | 
										Active: 1,
 | 
				
			||||||
 | 
									},
 | 
				
			||||||
 | 
								},
 | 
				
			||||||
 | 
								newJob: &batch.Job{
 | 
				
			||||||
 | 
									ObjectMeta: validObjectMeta,
 | 
				
			||||||
 | 
									Status: batch.JobStatus{
 | 
				
			||||||
 | 
										StartTime: &now,
 | 
				
			||||||
 | 
										Conditions: []batch.JobCondition{
 | 
				
			||||||
 | 
											{
 | 
				
			||||||
 | 
												Type:   batch.JobFailureTarget,
 | 
				
			||||||
 | 
												Status: api.ConditionTrue,
 | 
				
			||||||
 | 
											},
 | 
				
			||||||
 | 
											{
 | 
				
			||||||
 | 
												Type:   batch.JobFailed,
 | 
				
			||||||
 | 
												Status: api.ConditionTrue,
 | 
				
			||||||
 | 
											},
 | 
				
			||||||
 | 
										},
 | 
				
			||||||
 | 
										Active: 1,
 | 
				
			||||||
 | 
									},
 | 
				
			||||||
 | 
								},
 | 
				
			||||||
 | 
								wantErrs: field.ErrorList{
 | 
				
			||||||
 | 
									{Type: field.ErrorTypeInvalid, Field: "status.active"},
 | 
				
			||||||
 | 
								},
 | 
				
			||||||
		},
 | 
							},
 | 
				
			||||||
		"invalid attempt to transition to Failed=True with uncountedTerminatedPods.Failed>0": {
 | 
							"invalid attempt to transition to Failed=True with uncountedTerminatedPods.Failed>0": {
 | 
				
			||||||
			enableJobManagedBy: true,
 | 
								enableJobManagedBy: true,
 | 
				
			||||||
			job: &batch.Job{
 | 
								job: &batch.Job{
 | 
				
			||||||
				ObjectMeta: validObjectMeta,
 | 
									ObjectMeta: validObjectMeta,
 | 
				
			||||||
 | 
									Status: batch.JobStatus{
 | 
				
			||||||
 | 
										StartTime: &now,
 | 
				
			||||||
 | 
										UncountedTerminatedPods: &batch.UncountedTerminatedPods{
 | 
				
			||||||
 | 
											Failed: []types.UID{"a"},
 | 
				
			||||||
 | 
										},
 | 
				
			||||||
 | 
										Conditions: []batch.JobCondition{
 | 
				
			||||||
 | 
											{
 | 
				
			||||||
 | 
												Type:   batch.JobFailureTarget,
 | 
				
			||||||
 | 
												Status: api.ConditionTrue,
 | 
				
			||||||
 | 
											},
 | 
				
			||||||
 | 
										},
 | 
				
			||||||
 | 
									},
 | 
				
			||||||
			},
 | 
								},
 | 
				
			||||||
			newJob: &batch.Job{
 | 
								newJob: &batch.Job{
 | 
				
			||||||
				ObjectMeta: validObjectMeta,
 | 
									ObjectMeta: validObjectMeta,
 | 
				
			||||||
@@ -2272,6 +2419,10 @@ func TestStatusStrategy_ValidateUpdate(t *testing.T) {
 | 
				
			|||||||
						Failed: []types.UID{"a"},
 | 
											Failed: []types.UID{"a"},
 | 
				
			||||||
					},
 | 
										},
 | 
				
			||||||
					Conditions: []batch.JobCondition{
 | 
										Conditions: []batch.JobCondition{
 | 
				
			||||||
 | 
											{
 | 
				
			||||||
 | 
												Type:   batch.JobFailureTarget,
 | 
				
			||||||
 | 
												Status: api.ConditionTrue,
 | 
				
			||||||
 | 
											},
 | 
				
			||||||
						{
 | 
											{
 | 
				
			||||||
							Type:   batch.JobFailed,
 | 
												Type:   batch.JobFailed,
 | 
				
			||||||
							Status: api.ConditionTrue,
 | 
												Status: api.ConditionTrue,
 | 
				
			||||||
@@ -2364,6 +2515,18 @@ func TestStatusStrategy_ValidateUpdate(t *testing.T) {
 | 
				
			|||||||
			enableJobManagedBy: true,
 | 
								enableJobManagedBy: true,
 | 
				
			||||||
			job: &batch.Job{
 | 
								job: &batch.Job{
 | 
				
			||||||
				ObjectMeta: validObjectMeta,
 | 
									ObjectMeta: validObjectMeta,
 | 
				
			||||||
 | 
									Status: batch.JobStatus{
 | 
				
			||||||
 | 
										StartTime: &now,
 | 
				
			||||||
 | 
										UncountedTerminatedPods: &batch.UncountedTerminatedPods{
 | 
				
			||||||
 | 
											Succeeded: []types.UID{"a"},
 | 
				
			||||||
 | 
										},
 | 
				
			||||||
 | 
										Conditions: []batch.JobCondition{
 | 
				
			||||||
 | 
											{
 | 
				
			||||||
 | 
												Type:   batch.JobSuccessCriteriaMet,
 | 
				
			||||||
 | 
												Status: api.ConditionTrue,
 | 
				
			||||||
 | 
											},
 | 
				
			||||||
 | 
										},
 | 
				
			||||||
 | 
									},
 | 
				
			||||||
			},
 | 
								},
 | 
				
			||||||
			newJob: &batch.Job{
 | 
								newJob: &batch.Job{
 | 
				
			||||||
				ObjectMeta: validObjectMeta,
 | 
									ObjectMeta: validObjectMeta,
 | 
				
			||||||
@@ -2374,6 +2537,10 @@ func TestStatusStrategy_ValidateUpdate(t *testing.T) {
 | 
				
			|||||||
						Succeeded: []types.UID{"a"},
 | 
											Succeeded: []types.UID{"a"},
 | 
				
			||||||
					},
 | 
										},
 | 
				
			||||||
					Conditions: []batch.JobCondition{
 | 
										Conditions: []batch.JobCondition{
 | 
				
			||||||
 | 
											{
 | 
				
			||||||
 | 
												Type:   batch.JobSuccessCriteriaMet,
 | 
				
			||||||
 | 
												Status: api.ConditionTrue,
 | 
				
			||||||
 | 
											},
 | 
				
			||||||
						{
 | 
											{
 | 
				
			||||||
							Type:   batch.JobComplete,
 | 
												Type:   batch.JobComplete,
 | 
				
			||||||
							Status: api.ConditionTrue,
 | 
												Status: api.ConditionTrue,
 | 
				
			||||||
@@ -2389,12 +2556,25 @@ func TestStatusStrategy_ValidateUpdate(t *testing.T) {
 | 
				
			|||||||
			enableJobManagedBy: true,
 | 
								enableJobManagedBy: true,
 | 
				
			||||||
			job: &batch.Job{
 | 
								job: &batch.Job{
 | 
				
			||||||
				ObjectMeta: validObjectMeta,
 | 
									ObjectMeta: validObjectMeta,
 | 
				
			||||||
 | 
									Status: batch.JobStatus{
 | 
				
			||||||
 | 
										StartTime: &now,
 | 
				
			||||||
 | 
										Conditions: []batch.JobCondition{
 | 
				
			||||||
 | 
											{
 | 
				
			||||||
 | 
												Type:   batch.JobSuccessCriteriaMet,
 | 
				
			||||||
 | 
												Status: api.ConditionTrue,
 | 
				
			||||||
 | 
											},
 | 
				
			||||||
 | 
										},
 | 
				
			||||||
 | 
									},
 | 
				
			||||||
			},
 | 
								},
 | 
				
			||||||
			newJob: &batch.Job{
 | 
								newJob: &batch.Job{
 | 
				
			||||||
				ObjectMeta: validObjectMeta,
 | 
									ObjectMeta: validObjectMeta,
 | 
				
			||||||
				Status: batch.JobStatus{
 | 
									Status: batch.JobStatus{
 | 
				
			||||||
					StartTime: &now,
 | 
										StartTime: &now,
 | 
				
			||||||
					Conditions: []batch.JobCondition{
 | 
										Conditions: []batch.JobCondition{
 | 
				
			||||||
 | 
											{
 | 
				
			||||||
 | 
												Type:   batch.JobSuccessCriteriaMet,
 | 
				
			||||||
 | 
												Status: api.ConditionTrue,
 | 
				
			||||||
 | 
											},
 | 
				
			||||||
						{
 | 
											{
 | 
				
			||||||
							Type:   batch.JobComplete,
 | 
												Type:   batch.JobComplete,
 | 
				
			||||||
							Status: api.ConditionTrue,
 | 
												Status: api.ConditionTrue,
 | 
				
			||||||
@@ -2500,6 +2680,12 @@ func TestStatusStrategy_ValidateUpdate(t *testing.T) {
 | 
				
			|||||||
				ObjectMeta: validObjectMeta,
 | 
									ObjectMeta: validObjectMeta,
 | 
				
			||||||
				Status: batch.JobStatus{
 | 
									Status: batch.JobStatus{
 | 
				
			||||||
					StartTime: &nowPlusMinute,
 | 
										StartTime: &nowPlusMinute,
 | 
				
			||||||
 | 
										Conditions: []batch.JobCondition{
 | 
				
			||||||
 | 
											{
 | 
				
			||||||
 | 
												Type:   batch.JobSuccessCriteriaMet,
 | 
				
			||||||
 | 
												Status: api.ConditionTrue,
 | 
				
			||||||
 | 
											},
 | 
				
			||||||
 | 
										},
 | 
				
			||||||
				},
 | 
									},
 | 
				
			||||||
			},
 | 
								},
 | 
				
			||||||
			newJob: &batch.Job{
 | 
								newJob: &batch.Job{
 | 
				
			||||||
@@ -2508,6 +2694,10 @@ func TestStatusStrategy_ValidateUpdate(t *testing.T) {
 | 
				
			|||||||
					StartTime:      &nowPlusMinute,
 | 
										StartTime:      &nowPlusMinute,
 | 
				
			||||||
					CompletionTime: &now,
 | 
										CompletionTime: &now,
 | 
				
			||||||
					Conditions: []batch.JobCondition{
 | 
										Conditions: []batch.JobCondition{
 | 
				
			||||||
 | 
											{
 | 
				
			||||||
 | 
												Type:   batch.JobSuccessCriteriaMet,
 | 
				
			||||||
 | 
												Status: api.ConditionTrue,
 | 
				
			||||||
 | 
											},
 | 
				
			||||||
						{
 | 
											{
 | 
				
			||||||
							Type:   batch.JobComplete,
 | 
												Type:   batch.JobComplete,
 | 
				
			||||||
							Status: api.ConditionTrue,
 | 
												Status: api.ConditionTrue,
 | 
				
			||||||
@@ -2942,6 +3132,7 @@ func TestStatusStrategy_ValidateUpdate(t *testing.T) {
 | 
				
			|||||||
			},
 | 
								},
 | 
				
			||||||
			wantErrs: field.ErrorList{
 | 
								wantErrs: field.ErrorList{
 | 
				
			||||||
				{Type: field.ErrorTypeInvalid, Field: "status.conditions"},
 | 
									{Type: field.ErrorTypeInvalid, Field: "status.conditions"},
 | 
				
			||||||
 | 
									{Type: field.ErrorTypeInvalid, Field: "status.conditions"},
 | 
				
			||||||
			},
 | 
								},
 | 
				
			||||||
		},
 | 
							},
 | 
				
			||||||
		"invalid failedIndexes, which overlap with completedIndexes": {
 | 
							"invalid failedIndexes, which overlap with completedIndexes": {
 | 
				
			||||||
@@ -3440,6 +3631,28 @@ func TestStatusStrategy_ValidateUpdate(t *testing.T) {
 | 
				
			|||||||
				},
 | 
									},
 | 
				
			||||||
			},
 | 
								},
 | 
				
			||||||
		},
 | 
							},
 | 
				
			||||||
 | 
							"invalid attempt to set more ready pods than active": {
 | 
				
			||||||
 | 
								enableJobManagedBy: true,
 | 
				
			||||||
 | 
								job: &batch.Job{
 | 
				
			||||||
 | 
									ObjectMeta: validObjectMeta,
 | 
				
			||||||
 | 
									Spec: batch.JobSpec{
 | 
				
			||||||
 | 
										Completions: ptr.To[int32](5),
 | 
				
			||||||
 | 
									},
 | 
				
			||||||
 | 
								},
 | 
				
			||||||
 | 
								newJob: &batch.Job{
 | 
				
			||||||
 | 
									ObjectMeta: validObjectMeta,
 | 
				
			||||||
 | 
									Spec: batch.JobSpec{
 | 
				
			||||||
 | 
										Completions: ptr.To[int32](5),
 | 
				
			||||||
 | 
									},
 | 
				
			||||||
 | 
									Status: batch.JobStatus{
 | 
				
			||||||
 | 
										Active: 1,
 | 
				
			||||||
 | 
										Ready:  ptr.To[int32](2),
 | 
				
			||||||
 | 
									},
 | 
				
			||||||
 | 
								},
 | 
				
			||||||
 | 
								wantErrs: field.ErrorList{
 | 
				
			||||||
 | 
									{Type: field.ErrorTypeInvalid, Field: "status.ready"},
 | 
				
			||||||
 | 
								},
 | 
				
			||||||
 | 
							},
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	for name, tc := range cases {
 | 
						for name, tc := range cases {
 | 
				
			||||||
		t.Run(name, func(t *testing.T) {
 | 
							t.Run(name, func(t *testing.T) {
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -2262,16 +2262,14 @@ func TestManagedBy_UsingReservedJobFinalizers(t *testing.T) {
 | 
				
			|||||||
		t.Fatalf("Error %v when marking the %q pod as succeeded", err, klog.KObj(podObj))
 | 
							t.Fatalf("Error %v when marking the %q pod as succeeded", err, klog.KObj(podObj))
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	// Mark the job as finished so that the built-in controller receives the
 | 
						// Trigger termination for the Job so that the built-in controller receives the
 | 
				
			||||||
	// UpdateJob event in reaction to each it would remove the pod's finalizer,
 | 
						// UpdateJob event in reaction to each it would remove the pod's finalizer,
 | 
				
			||||||
	// if not for the custom managedBy field.
 | 
						// if not for the custom managedBy field.
 | 
				
			||||||
	jobObj.Status.Conditions = append(jobObj.Status.Conditions, batchv1.JobCondition{
 | 
						jobObj.Status.Conditions = append(jobObj.Status.Conditions, batchv1.JobCondition{
 | 
				
			||||||
		Type:   batchv1.JobComplete,
 | 
							Type:   batchv1.JobSuccessCriteriaMet,
 | 
				
			||||||
		Status: v1.ConditionTrue,
 | 
							Status: v1.ConditionTrue,
 | 
				
			||||||
	})
 | 
						})
 | 
				
			||||||
	jobObj.Status.StartTime = ptr.To(metav1.Now())
 | 
						jobObj.Status.StartTime = ptr.To(metav1.Now())
 | 
				
			||||||
	jobObj.Status.CompletionTime = ptr.To(metav1.Now())
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	if jobObj, err = clientSet.BatchV1().Jobs(jobObj.Namespace).UpdateStatus(ctx, jobObj, metav1.UpdateOptions{}); err != nil {
 | 
						if jobObj, err = clientSet.BatchV1().Jobs(jobObj.Namespace).UpdateStatus(ctx, jobObj, metav1.UpdateOptions{}); err != nil {
 | 
				
			||||||
		t.Fatalf("Error %v when updating the job as finished %v", err, klog.KObj(jobObj))
 | 
							t.Fatalf("Error %v when updating the job as finished %v", err, klog.KObj(jobObj))
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 
 | 
				
			|||||||
		Reference in New Issue
	
	Block a user