diff --git a/api/openapi-spec/swagger.json b/api/openapi-spec/swagger.json index 681cc77ae7c31..c3a74d96db75d 100644 --- a/api/openapi-spec/swagger.json +++ b/api/openapi-spec/swagger.json @@ -4380,7 +4380,7 @@ "type": "string" }, "ready": { - "description": "The number of pods which have a Ready condition. The value is zero (or nil) for finished jobs.", + "description": "The number of pods which have a Ready condition. The value is zero (or null) for finished jobs.", "format": "int32", "type": "integer" }, @@ -4394,7 +4394,7 @@ "type": "integer" }, "terminating": { - "description": "The number of pods which are terminating (in phase Pending or Running and have a deletionTimestamp). The value is zero (or nil) for finished jobs.\n\nThis field is beta-level. The job controller populates the field when the feature gate JobPodReplacementPolicy is enabled (enabled by default).", + "description": "The number of pods which are terminating (in phase Pending or Running and have a deletionTimestamp). The value is zero (or null) for finished jobs.\n\nThis field is beta-level. The job controller populates the field when the feature gate JobPodReplacementPolicy is enabled (enabled by default).", "format": "int32", "type": "integer" }, diff --git a/api/openapi-spec/v3/apis__batch__v1_openapi.json b/api/openapi-spec/v3/apis__batch__v1_openapi.json index e95ea608bc1cd..8d97a538ef562 100644 --- a/api/openapi-spec/v3/apis__batch__v1_openapi.json +++ b/api/openapi-spec/v3/apis__batch__v1_openapi.json @@ -451,7 +451,7 @@ "type": "string" }, "ready": { - "description": "The number of pods which have a Ready condition. The value is zero (or nil) for finished jobs.", + "description": "The number of pods which have a Ready condition. The value is zero (or null) for finished jobs.", "format": "int32", "type": "integer" }, @@ -469,7 +469,7 @@ "type": "integer" }, "terminating": { - "description": "The number of pods which are terminating (in phase Pending or Running and have a deletionTimestamp). The value is zero (or nil) for finished jobs.\n\nThis field is beta-level. The job controller populates the field when the feature gate JobPodReplacementPolicy is enabled (enabled by default).", + "description": "The number of pods which are terminating (in phase Pending or Running and have a deletionTimestamp). The value is zero (or null) for finished jobs.\n\nThis field is beta-level. The job controller populates the field when the feature gate JobPodReplacementPolicy is enabled (enabled by default).", "format": "int32", "type": "integer" }, diff --git a/pkg/apis/batch/types.go b/pkg/apis/batch/types.go index 25be976c12d0e..879d6f4f6a252 100644 --- a/pkg/apis/batch/types.go +++ b/pkg/apis/batch/types.go @@ -475,7 +475,7 @@ type JobStatus struct { // The number of pods which are terminating (in phase Pending or Running // and have a deletionTimestamp). - // The value is zero (or nil) for finished jobs. + // The value is zero (or null) for finished jobs. // // This field is beta-level. The job controller populates the field when // the feature gate JobPodReplacementPolicy is enabled (enabled by default). @@ -483,7 +483,7 @@ type JobStatus struct { Terminating *int32 // The number of active pods which have a Ready condition. - // The value is zero (or nil) for finished jobs. + // The value is zero (or null) for finished jobs. // +optional Ready *int32 diff --git a/pkg/apis/batch/validation/validation.go b/pkg/apis/batch/validation/validation.go index cfa7793dea389..56b44bcba0412 100644 --- a/pkg/apis/batch/validation/validation.go +++ b/pkg/apis/batch/validation/validation.go @@ -605,11 +605,16 @@ func ValidateJobStatusUpdate(job, oldJob *batch.Job, opts JobStatusValidationOpt } } if opts.RejectMutatingCompletionTime { + // Note that we check the condition only when `job.Status.CompletionTime != nil`, this is because + // we don't want to block transitions to completionTime = nil when the job is not finished yet. + // Setting completionTime = nil for finished jobs is prevented in RejectCompleteJobWithoutCompletionTime. if job.Status.CompletionTime != nil && oldJob.Status.CompletionTime != nil && !ptr.Equal(job.Status.CompletionTime, oldJob.Status.CompletionTime) { allErrs = append(allErrs, field.Invalid(statusFld.Child("completionTime"), job.Status.CompletionTime, "completionTime cannot be mutated")) } } if opts.RejectStartTimeUpdateForUnsuspendedJob { + // Note that we check `oldJob.Status.StartTime != nil` to allow transitioning from + // startTime = nil to startTime != nil for unsuspended jobs, which is a desired transition. if oldJob.Status.StartTime != nil && !ptr.Equal(oldJob.Status.StartTime, job.Status.StartTime) && !ptr.Deref(job.Spec.Suspend, false) { allErrs = append(allErrs, field.Required(statusFld.Child("startTime"), "startTime cannot be removed for unsuspended job")) } diff --git a/pkg/generated/openapi/zz_generated.openapi.go b/pkg/generated/openapi/zz_generated.openapi.go index cb9001bb9aa7e..153aaefe41ca2 100644 --- a/pkg/generated/openapi/zz_generated.openapi.go +++ b/pkg/generated/openapi/zz_generated.openapi.go @@ -16314,7 +16314,7 @@ func schema_k8sio_api_batch_v1_JobStatus(ref common.ReferenceCallback) common.Op }, "terminating": { SchemaProps: spec.SchemaProps{ - Description: "The number of pods which are terminating (in phase Pending or Running and have a deletionTimestamp). The value is zero (or nil) for finished jobs.\n\nThis field is beta-level. The job controller populates the field when the feature gate JobPodReplacementPolicy is enabled (enabled by default).", + Description: "The number of pods which are terminating (in phase Pending or Running and have a deletionTimestamp). The value is zero (or null) for finished jobs.\n\nThis field is beta-level. The job controller populates the field when the feature gate JobPodReplacementPolicy is enabled (enabled by default).", Type: []string{"integer"}, Format: "int32", }, @@ -16341,7 +16341,7 @@ func schema_k8sio_api_batch_v1_JobStatus(ref common.ReferenceCallback) common.Op }, "ready": { SchemaProps: spec.SchemaProps{ - Description: "The number of pods which have a Ready condition. The value is zero (or nil) for finished jobs.", + Description: "The number of pods which have a Ready condition. The value is zero (or null) for finished jobs.", Type: []string{"integer"}, Format: "int32", }, diff --git a/staging/src/k8s.io/api/batch/v1/generated.proto b/staging/src/k8s.io/api/batch/v1/generated.proto index 24d7a7993e810..1a9facaadac8a 100644 --- a/staging/src/k8s.io/api/batch/v1/generated.proto +++ b/staging/src/k8s.io/api/batch/v1/generated.proto @@ -407,7 +407,7 @@ message JobStatus { // The number of pods which are terminating (in phase Pending or Running // and have a deletionTimestamp). - // The value is zero (or nil) for finished jobs. + // The value is zero (or null) for finished jobs. // // This field is beta-level. The job controller populates the field when // the feature gate JobPodReplacementPolicy is enabled (enabled by default). @@ -458,7 +458,7 @@ message JobStatus { optional UncountedTerminatedPods uncountedTerminatedPods = 8; // The number of pods which have a Ready condition. - // The value is zero (or nil) for finished jobs. + // The value is zero (or null) for finished jobs. // +optional optional int32 ready = 9; } diff --git a/staging/src/k8s.io/api/batch/v1/types.go b/staging/src/k8s.io/api/batch/v1/types.go index 2847b55005664..1209331394c87 100644 --- a/staging/src/k8s.io/api/batch/v1/types.go +++ b/staging/src/k8s.io/api/batch/v1/types.go @@ -490,7 +490,7 @@ type JobStatus struct { // The number of pods which are terminating (in phase Pending or Running // and have a deletionTimestamp). - // The value is zero (or nil) for finished jobs. + // The value is zero (or null) for finished jobs. // // This field is beta-level. The job controller populates the field when // the feature gate JobPodReplacementPolicy is enabled (enabled by default). @@ -541,7 +541,7 @@ type JobStatus struct { UncountedTerminatedPods *UncountedTerminatedPods `json:"uncountedTerminatedPods,omitempty" protobuf:"bytes,8,opt,name=uncountedTerminatedPods"` // The number of pods which have a Ready condition. - // The value is zero (or nil) for finished jobs. + // The value is zero (or null) for finished jobs. // +optional Ready *int32 `json:"ready,omitempty" protobuf:"varint,9,opt,name=ready"` } diff --git a/staging/src/k8s.io/api/batch/v1/types_swagger_doc_generated.go b/staging/src/k8s.io/api/batch/v1/types_swagger_doc_generated.go index b3398ff8af958..c2f9fe0f8ce17 100644 --- a/staging/src/k8s.io/api/batch/v1/types_swagger_doc_generated.go +++ b/staging/src/k8s.io/api/batch/v1/types_swagger_doc_generated.go @@ -141,11 +141,11 @@ var map_JobStatus = map[string]string{ "active": "The number of pending and running pods which are not terminating (without a deletionTimestamp). The value is zero for finished jobs.", "succeeded": "The number of pods which reached phase Succeeded. The value increases monotonically for a given spec. However, it may decrease in reaction to scale down of elastic indexed jobs.", "failed": "The number of pods which reached phase Failed. The value increases monotonically.", - "terminating": "The number of pods which are terminating (in phase Pending or Running and have a deletionTimestamp). The value is zero (or nil) for finished jobs.\n\nThis field is beta-level. The job controller populates the field when the feature gate JobPodReplacementPolicy is enabled (enabled by default).", + "terminating": "The number of pods which are terminating (in phase Pending or Running and have a deletionTimestamp). The value is zero (or null) for finished jobs.\n\nThis field is beta-level. The job controller populates the field when the feature gate JobPodReplacementPolicy is enabled (enabled by default).", "completedIndexes": "completedIndexes holds the completed indexes when .spec.completionMode = \"Indexed\" in a text format. The indexes are represented as decimal integers separated by commas. The numbers are listed in increasing order. Three or more consecutive numbers are compressed and represented by the first and last element of the series, separated by a hyphen. For example, if the completed indexes are 1, 3, 4, 5 and 7, they are represented as \"1,3-5,7\".", "failedIndexes": "FailedIndexes holds the failed indexes when spec.backoffLimitPerIndex is set. The indexes are represented in the text format analogous as for the `completedIndexes` field, ie. they are kept as decimal integers separated by commas. The numbers are listed in increasing order. Three or more consecutive numbers are compressed and represented by the first and last element of the series, separated by a hyphen. For example, if the failed indexes are 1, 3, 4, 5 and 7, they are represented as \"1,3-5,7\". The set of failed indexes cannot overlap with the set of completed indexes.\n\nThis field is beta-level. It can be used when the `JobBackoffLimitPerIndex` feature gate is enabled (enabled by default).", "uncountedTerminatedPods": "uncountedTerminatedPods holds the UIDs of Pods that have terminated but the job controller hasn't yet accounted for in the status counters.\n\nThe job controller creates pods with a finalizer. When a pod terminates (succeeded or failed), the controller does three steps to account for it in the job status:\n\n1. Add the pod UID to the arrays in this field. 2. Remove the pod finalizer. 3. Remove the pod UID from the arrays while increasing the corresponding\n counter.\n\nOld jobs might not be tracked using this field, in which case the field remains null. The structure is empty for finished jobs.", - "ready": "The number of pods which have a Ready condition. The value is zero (or nil) for finished jobs.", + "ready": "The number of pods which have a Ready condition. The value is zero (or null) for finished jobs.", } func (JobStatus) SwaggerDoc() map[string]string {