mirror of
https://github.com/k3s-io/kubernetes.git
synced 2025-07-21 02:41:25 +00:00
Merge pull request #104915 from alculquicondor/job-ready
Track ready pods in Job status
This commit is contained in:
commit
6edcb60d9f
7
api/openapi-spec/swagger.json
generated
7
api/openapi-spec/swagger.json
generated
@ -3633,7 +3633,7 @@
|
|||||||
"description": "JobStatus represents the current state of a Job.",
|
"description": "JobStatus represents the current state of a Job.",
|
||||||
"properties": {
|
"properties": {
|
||||||
"active": {
|
"active": {
|
||||||
"description": "The number of actively running pods.",
|
"description": "The number of pending and running pods.",
|
||||||
"format": "int32",
|
"format": "int32",
|
||||||
"type": "integer"
|
"type": "integer"
|
||||||
},
|
},
|
||||||
@ -3660,6 +3660,11 @@
|
|||||||
"format": "int32",
|
"format": "int32",
|
||||||
"type": "integer"
|
"type": "integer"
|
||||||
},
|
},
|
||||||
|
"ready": {
|
||||||
|
"description": "The number of pods which have a Ready condition.\n\nThis field is alpha-level. The job controller populates the field when the feature gate JobReadyPods is enabled (disabled by default).",
|
||||||
|
"format": "int32",
|
||||||
|
"type": "integer"
|
||||||
|
},
|
||||||
"startTime": {
|
"startTime": {
|
||||||
"$ref": "#/definitions/io.k8s.apimachinery.pkg.apis.meta.v1.Time",
|
"$ref": "#/definitions/io.k8s.apimachinery.pkg.apis.meta.v1.Time",
|
||||||
"description": "Represents time when the job controller started processing a job. When a Job is created in the suspended state, this field is not set until the first time it is resumed. This field is reset every time a Job is resumed from suspension. It is represented in RFC3339 form and is in UTC."
|
"description": "Represents time when the job controller started processing a job. When a Job is created in the suspended state, this field is not set until the first time it is resumed. This field is reset every time a Job is resumed from suspension. It is represented in RFC3339 form and is in UTC."
|
||||||
|
@ -241,10 +241,17 @@ type JobStatus struct {
|
|||||||
// +optional
|
// +optional
|
||||||
CompletionTime *metav1.Time
|
CompletionTime *metav1.Time
|
||||||
|
|
||||||
// The number of actively running pods.
|
// The number of pending and running pods.
|
||||||
// +optional
|
// +optional
|
||||||
Active int32
|
Active int32
|
||||||
|
|
||||||
|
// The number of active pods which have a Ready condition.
|
||||||
|
//
|
||||||
|
// This field is alpha-level. The job controller populates the field when
|
||||||
|
// the feature gate JobReadyPods is enabled (disabled by default).
|
||||||
|
// +optional
|
||||||
|
Ready *int32
|
||||||
|
|
||||||
// The number of pods which reached phase Succeeded.
|
// The number of pods which reached phase Succeeded.
|
||||||
// +optional
|
// +optional
|
||||||
Succeeded int32
|
Succeeded int32
|
||||||
|
2
pkg/apis/batch/v1/zz_generated.conversion.go
generated
2
pkg/apis/batch/v1/zz_generated.conversion.go
generated
@ -434,6 +434,7 @@ func autoConvert_v1_JobStatus_To_batch_JobStatus(in *v1.JobStatus, out *batch.Jo
|
|||||||
out.Failed = in.Failed
|
out.Failed = in.Failed
|
||||||
out.CompletedIndexes = in.CompletedIndexes
|
out.CompletedIndexes = in.CompletedIndexes
|
||||||
out.UncountedTerminatedPods = (*batch.UncountedTerminatedPods)(unsafe.Pointer(in.UncountedTerminatedPods))
|
out.UncountedTerminatedPods = (*batch.UncountedTerminatedPods)(unsafe.Pointer(in.UncountedTerminatedPods))
|
||||||
|
out.Ready = (*int32)(unsafe.Pointer(in.Ready))
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -447,6 +448,7 @@ func autoConvert_batch_JobStatus_To_v1_JobStatus(in *batch.JobStatus, out *v1.Jo
|
|||||||
out.StartTime = (*metav1.Time)(unsafe.Pointer(in.StartTime))
|
out.StartTime = (*metav1.Time)(unsafe.Pointer(in.StartTime))
|
||||||
out.CompletionTime = (*metav1.Time)(unsafe.Pointer(in.CompletionTime))
|
out.CompletionTime = (*metav1.Time)(unsafe.Pointer(in.CompletionTime))
|
||||||
out.Active = in.Active
|
out.Active = in.Active
|
||||||
|
out.Ready = (*int32)(unsafe.Pointer(in.Ready))
|
||||||
out.Succeeded = in.Succeeded
|
out.Succeeded = in.Succeeded
|
||||||
out.Failed = in.Failed
|
out.Failed = in.Failed
|
||||||
out.CompletedIndexes = in.CompletedIndexes
|
out.CompletedIndexes = in.CompletedIndexes
|
||||||
|
@ -186,6 +186,9 @@ func validateJobStatus(status *batch.JobStatus, fldPath *field.Path) field.Error
|
|||||||
allErrs = append(allErrs, apivalidation.ValidateNonnegativeField(int64(status.Active), fldPath.Child("active"))...)
|
allErrs = append(allErrs, apivalidation.ValidateNonnegativeField(int64(status.Active), fldPath.Child("active"))...)
|
||||||
allErrs = append(allErrs, apivalidation.ValidateNonnegativeField(int64(status.Succeeded), fldPath.Child("succeeded"))...)
|
allErrs = append(allErrs, apivalidation.ValidateNonnegativeField(int64(status.Succeeded), fldPath.Child("succeeded"))...)
|
||||||
allErrs = append(allErrs, apivalidation.ValidateNonnegativeField(int64(status.Failed), fldPath.Child("failed"))...)
|
allErrs = append(allErrs, apivalidation.ValidateNonnegativeField(int64(status.Failed), fldPath.Child("failed"))...)
|
||||||
|
if status.Ready != nil {
|
||||||
|
allErrs = append(allErrs, apivalidation.ValidateNonnegativeField(int64(*status.Ready), fldPath.Child("ready"))...)
|
||||||
|
}
|
||||||
if status.UncountedTerminatedPods != nil {
|
if status.UncountedTerminatedPods != nil {
|
||||||
path := fldPath.Child("uncountedTerminatedPods")
|
path := fldPath.Child("uncountedTerminatedPods")
|
||||||
seen := sets.NewString()
|
seen := sets.NewString()
|
||||||
|
@ -686,6 +686,21 @@ func TestValidateJobUpdateStatus(t *testing.T) {
|
|||||||
},
|
},
|
||||||
},
|
},
|
||||||
update: batch.Job{
|
update: batch.Job{
|
||||||
|
ObjectMeta: metav1.ObjectMeta{
|
||||||
|
Name: "abc",
|
||||||
|
Namespace: metav1.NamespaceDefault,
|
||||||
|
ResourceVersion: "1",
|
||||||
|
},
|
||||||
|
Status: batch.JobStatus{
|
||||||
|
Active: 2,
|
||||||
|
Succeeded: 3,
|
||||||
|
Failed: 4,
|
||||||
|
Ready: pointer.Int32(1),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
"nil ready": {
|
||||||
|
old: batch.Job{
|
||||||
ObjectMeta: metav1.ObjectMeta{
|
ObjectMeta: metav1.ObjectMeta{
|
||||||
Name: "abc",
|
Name: "abc",
|
||||||
Namespace: metav1.NamespaceDefault,
|
Namespace: metav1.NamespaceDefault,
|
||||||
@ -693,10 +708,22 @@ func TestValidateJobUpdateStatus(t *testing.T) {
|
|||||||
},
|
},
|
||||||
Status: batch.JobStatus{
|
Status: batch.JobStatus{
|
||||||
Active: 1,
|
Active: 1,
|
||||||
Succeeded: 1,
|
Succeeded: 2,
|
||||||
Failed: 3,
|
Failed: 3,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
update: batch.Job{
|
||||||
|
ObjectMeta: metav1.ObjectMeta{
|
||||||
|
Name: "abc",
|
||||||
|
Namespace: metav1.NamespaceDefault,
|
||||||
|
ResourceVersion: "1",
|
||||||
|
},
|
||||||
|
Status: batch.JobStatus{
|
||||||
|
Active: 2,
|
||||||
|
Succeeded: 3,
|
||||||
|
Failed: 4,
|
||||||
|
},
|
||||||
|
},
|
||||||
},
|
},
|
||||||
"negative counts": {
|
"negative counts": {
|
||||||
old: batch.Job{
|
old: batch.Job{
|
||||||
@ -720,12 +747,15 @@ func TestValidateJobUpdateStatus(t *testing.T) {
|
|||||||
Status: batch.JobStatus{
|
Status: batch.JobStatus{
|
||||||
Active: -1,
|
Active: -1,
|
||||||
Succeeded: -2,
|
Succeeded: -2,
|
||||||
Failed: 3,
|
Failed: -3,
|
||||||
|
Ready: pointer.Int32(-1),
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
wantErrs: field.ErrorList{
|
wantErrs: field.ErrorList{
|
||||||
{Type: field.ErrorTypeInvalid, Field: "status.active"},
|
{Type: field.ErrorTypeInvalid, Field: "status.active"},
|
||||||
{Type: field.ErrorTypeInvalid, Field: "status.succeeded"},
|
{Type: field.ErrorTypeInvalid, Field: "status.succeeded"},
|
||||||
|
{Type: field.ErrorTypeInvalid, Field: "status.failed"},
|
||||||
|
{Type: field.ErrorTypeInvalid, Field: "status.ready"},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
"empty and duplicated uncounted pods": {
|
"empty and duplicated uncounted pods": {
|
||||||
|
5
pkg/apis/batch/zz_generated.deepcopy.go
generated
5
pkg/apis/batch/zz_generated.deepcopy.go
generated
@ -314,6 +314,11 @@ func (in *JobStatus) DeepCopyInto(out *JobStatus) {
|
|||||||
in, out := &in.CompletionTime, &out.CompletionTime
|
in, out := &in.CompletionTime, &out.CompletionTime
|
||||||
*out = (*in).DeepCopy()
|
*out = (*in).DeepCopy()
|
||||||
}
|
}
|
||||||
|
if in.Ready != nil {
|
||||||
|
in, out := &in.Ready, &out.Ready
|
||||||
|
*out = new(int32)
|
||||||
|
**out = **in
|
||||||
|
}
|
||||||
if in.UncountedTerminatedPods != nil {
|
if in.UncountedTerminatedPods != nil {
|
||||||
in, out := &in.UncountedTerminatedPods, &out.UncountedTerminatedPods
|
in, out := &in.UncountedTerminatedPods, &out.UncountedTerminatedPods
|
||||||
*out = new(UncountedTerminatedPods)
|
*out = new(UncountedTerminatedPods)
|
||||||
|
@ -49,12 +49,18 @@ import (
|
|||||||
"k8s.io/client-go/util/workqueue"
|
"k8s.io/client-go/util/workqueue"
|
||||||
"k8s.io/component-base/metrics/prometheus/ratelimiter"
|
"k8s.io/component-base/metrics/prometheus/ratelimiter"
|
||||||
"k8s.io/klog/v2"
|
"k8s.io/klog/v2"
|
||||||
|
podutil "k8s.io/kubernetes/pkg/api/v1/pod"
|
||||||
"k8s.io/kubernetes/pkg/controller"
|
"k8s.io/kubernetes/pkg/controller"
|
||||||
"k8s.io/kubernetes/pkg/controller/job/metrics"
|
"k8s.io/kubernetes/pkg/controller/job/metrics"
|
||||||
"k8s.io/kubernetes/pkg/features"
|
"k8s.io/kubernetes/pkg/features"
|
||||||
"k8s.io/utils/integer"
|
"k8s.io/utils/integer"
|
||||||
|
"k8s.io/utils/pointer"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
// podUpdateBatchPeriod is the batch period to hold pod updates before syncing
|
||||||
|
// a Job. It is used if the feature gate JobReadyPods is enabled.
|
||||||
|
const podUpdateBatchPeriod = 500 * time.Millisecond
|
||||||
|
|
||||||
// controllerKind contains the schema.GroupVersionKind for this controller type.
|
// controllerKind contains the schema.GroupVersionKind for this controller type.
|
||||||
var controllerKind = batch.SchemeGroupVersion.WithKind("Job")
|
var controllerKind = batch.SchemeGroupVersion.WithKind("Job")
|
||||||
|
|
||||||
@ -110,6 +116,8 @@ type Controller struct {
|
|||||||
orphanQueue workqueue.RateLimitingInterface
|
orphanQueue workqueue.RateLimitingInterface
|
||||||
|
|
||||||
recorder record.EventRecorder
|
recorder record.EventRecorder
|
||||||
|
|
||||||
|
podUpdateBatchPeriod time.Duration
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewController creates a new Job controller that keeps the relevant pods
|
// NewController creates a new Job controller that keeps the relevant pods
|
||||||
@ -135,6 +143,9 @@ func NewController(podInformer coreinformers.PodInformer, jobInformer batchinfor
|
|||||||
orphanQueue: workqueue.NewNamedRateLimitingQueue(workqueue.NewItemExponentialFailureRateLimiter(DefaultJobBackOff, MaxJobBackOff), "job_orphan_pod"),
|
orphanQueue: workqueue.NewNamedRateLimitingQueue(workqueue.NewItemExponentialFailureRateLimiter(DefaultJobBackOff, MaxJobBackOff), "job_orphan_pod"),
|
||||||
recorder: eventBroadcaster.NewRecorder(scheme.Scheme, v1.EventSource{Component: "job-controller"}),
|
recorder: eventBroadcaster.NewRecorder(scheme.Scheme, v1.EventSource{Component: "job-controller"}),
|
||||||
}
|
}
|
||||||
|
if feature.DefaultFeatureGate.Enabled(features.JobReadyPods) {
|
||||||
|
jm.podUpdateBatchPeriod = podUpdateBatchPeriod
|
||||||
|
}
|
||||||
|
|
||||||
jobInformer.Informer().AddEventHandler(cache.ResourceEventHandlerFuncs{
|
jobInformer.Informer().AddEventHandler(cache.ResourceEventHandlerFuncs{
|
||||||
AddFunc: func(obj interface{}) {
|
AddFunc: func(obj interface{}) {
|
||||||
@ -249,7 +260,7 @@ func (jm *Controller) addPod(obj interface{}) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
jm.expectations.CreationObserved(jobKey)
|
jm.expectations.CreationObserved(jobKey)
|
||||||
jm.enqueueController(job, true)
|
jm.enqueueControllerPodUpdate(job, true)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -258,7 +269,7 @@ func (jm *Controller) addPod(obj interface{}) {
|
|||||||
// DO NOT observe creation because no controller should be waiting for an
|
// DO NOT observe creation because no controller should be waiting for an
|
||||||
// orphan.
|
// orphan.
|
||||||
for _, job := range jm.getPodJobs(pod) {
|
for _, job := range jm.getPodJobs(pod) {
|
||||||
jm.enqueueController(job, true)
|
jm.enqueueControllerPodUpdate(job, true)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -303,7 +314,7 @@ func (jm *Controller) updatePod(old, cur interface{}) {
|
|||||||
jm.finalizerExpectations.finalizerRemovalObserved(key, string(curPod.UID))
|
jm.finalizerExpectations.finalizerRemovalObserved(key, string(curPod.UID))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
jm.enqueueController(job, immediate)
|
jm.enqueueControllerPodUpdate(job, immediate)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -319,7 +330,7 @@ func (jm *Controller) updatePod(old, cur interface{}) {
|
|||||||
jm.finalizerExpectations.finalizerRemovalObserved(key, string(curPod.UID))
|
jm.finalizerExpectations.finalizerRemovalObserved(key, string(curPod.UID))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
jm.enqueueController(job, immediate)
|
jm.enqueueControllerPodUpdate(job, immediate)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -328,7 +339,7 @@ func (jm *Controller) updatePod(old, cur interface{}) {
|
|||||||
labelChanged := !reflect.DeepEqual(curPod.Labels, oldPod.Labels)
|
labelChanged := !reflect.DeepEqual(curPod.Labels, oldPod.Labels)
|
||||||
if labelChanged || controllerRefChanged {
|
if labelChanged || controllerRefChanged {
|
||||||
for _, job := range jm.getPodJobs(curPod) {
|
for _, job := range jm.getPodJobs(curPod) {
|
||||||
jm.enqueueController(job, immediate)
|
jm.enqueueControllerPodUpdate(job, immediate)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -379,7 +390,7 @@ func (jm *Controller) deletePod(obj interface{}, final bool) {
|
|||||||
jm.finalizerExpectations.finalizerRemovalObserved(jobKey, string(pod.UID))
|
jm.finalizerExpectations.finalizerRemovalObserved(jobKey, string(pod.UID))
|
||||||
}
|
}
|
||||||
|
|
||||||
jm.enqueueController(job, true)
|
jm.enqueueControllerPodUpdate(job, true)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (jm *Controller) updateJob(old, cur interface{}) {
|
func (jm *Controller) updateJob(old, cur interface{}) {
|
||||||
@ -415,13 +426,21 @@ func (jm *Controller) updateJob(old, cur interface{}) {
|
|||||||
// immediate tells the controller to update the status right away, and should
|
// immediate tells the controller to update the status right away, and should
|
||||||
// happen ONLY when there was a successful pod run.
|
// happen ONLY when there was a successful pod run.
|
||||||
func (jm *Controller) enqueueController(obj interface{}, immediate bool) {
|
func (jm *Controller) enqueueController(obj interface{}, immediate bool) {
|
||||||
|
jm.enqueueControllerDelayed(obj, immediate, 0)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (jm *Controller) enqueueControllerPodUpdate(obj interface{}, immediate bool) {
|
||||||
|
jm.enqueueControllerDelayed(obj, immediate, jm.podUpdateBatchPeriod)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (jm *Controller) enqueueControllerDelayed(obj interface{}, immediate bool, delay time.Duration) {
|
||||||
key, err := controller.KeyFunc(obj)
|
key, err := controller.KeyFunc(obj)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
utilruntime.HandleError(fmt.Errorf("Couldn't get key for object %+v: %v", obj, err))
|
utilruntime.HandleError(fmt.Errorf("Couldn't get key for object %+v: %v", obj, err))
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
backoff := time.Duration(0)
|
backoff := delay
|
||||||
if !immediate {
|
if !immediate {
|
||||||
backoff = getBackoff(jm.queue, key)
|
backoff = getBackoff(jm.queue, key)
|
||||||
}
|
}
|
||||||
@ -670,6 +689,10 @@ func (jm *Controller) syncJob(key string) (forget bool, rErr error) {
|
|||||||
activePods := controller.FilterActivePods(pods)
|
activePods := controller.FilterActivePods(pods)
|
||||||
active := int32(len(activePods))
|
active := int32(len(activePods))
|
||||||
succeeded, failed := getStatus(&job, pods, uncounted, expectedRmFinalizers)
|
succeeded, failed := getStatus(&job, pods, uncounted, expectedRmFinalizers)
|
||||||
|
var ready *int32
|
||||||
|
if feature.DefaultFeatureGate.Enabled(features.JobReadyPods) {
|
||||||
|
ready = pointer.Int32(countReadyPods(activePods))
|
||||||
|
}
|
||||||
// Job first start. Set StartTime and start the ActiveDeadlineSeconds timer
|
// Job first start. Set StartTime and start the ActiveDeadlineSeconds timer
|
||||||
// only if the job is not in the suspended state.
|
// only if the job is not in the suspended state.
|
||||||
if job.Status.StartTime == nil && !jobSuspended(&job) {
|
if job.Status.StartTime == nil && !jobSuspended(&job) {
|
||||||
@ -787,8 +810,9 @@ func (jm *Controller) syncJob(key string) (forget bool, rErr error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if uncounted != nil {
|
if uncounted != nil {
|
||||||
needsStatusUpdate := suspendCondChanged || active != job.Status.Active
|
needsStatusUpdate := suspendCondChanged || active != job.Status.Active || !equalReady(ready, job.Status.Ready)
|
||||||
job.Status.Active = active
|
job.Status.Active = active
|
||||||
|
job.Status.Ready = ready
|
||||||
err = jm.trackJobStatusAndRemoveFinalizers(&job, pods, prevSucceededIndexes, *uncounted, expectedRmFinalizers, finishedCondition, needsStatusUpdate)
|
err = jm.trackJobStatusAndRemoveFinalizers(&job, pods, prevSucceededIndexes, *uncounted, expectedRmFinalizers, finishedCondition, needsStatusUpdate)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return false, fmt.Errorf("tracking status: %w", err)
|
return false, fmt.Errorf("tracking status: %w", err)
|
||||||
@ -809,10 +833,11 @@ func (jm *Controller) syncJob(key string) (forget bool, rErr error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// no need to update the job if the status hasn't changed since last time
|
// no need to update the job if the status hasn't changed since last time
|
||||||
if job.Status.Active != active || job.Status.Succeeded != succeeded || job.Status.Failed != failed || suspendCondChanged || finishedCondition != nil {
|
if job.Status.Active != active || job.Status.Succeeded != succeeded || job.Status.Failed != failed || !equalReady(job.Status.Ready, ready) || suspendCondChanged || finishedCondition != nil {
|
||||||
job.Status.Active = active
|
job.Status.Active = active
|
||||||
job.Status.Succeeded = succeeded
|
job.Status.Succeeded = succeeded
|
||||||
job.Status.Failed = failed
|
job.Status.Failed = failed
|
||||||
|
job.Status.Ready = ready
|
||||||
if isIndexedJob(&job) {
|
if isIndexedJob(&job) {
|
||||||
job.Status.CompletedIndexes = succeededIndexes.String()
|
job.Status.CompletedIndexes = succeededIndexes.String()
|
||||||
}
|
}
|
||||||
@ -1609,3 +1634,20 @@ func recordJobPodFinished(job *batch.Job, oldCounters batch.JobStatus) {
|
|||||||
diff = job.Status.Failed - oldCounters.Failed
|
diff = job.Status.Failed - oldCounters.Failed
|
||||||
metrics.JobPodsFinished.WithLabelValues(completionMode, metrics.Failed).Add(float64(diff))
|
metrics.JobPodsFinished.WithLabelValues(completionMode, metrics.Failed).Add(float64(diff))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func countReadyPods(pods []*v1.Pod) int32 {
|
||||||
|
cnt := int32(0)
|
||||||
|
for _, p := range pods {
|
||||||
|
if podutil.IsPodReady(p) {
|
||||||
|
cnt++
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return cnt
|
||||||
|
}
|
||||||
|
|
||||||
|
func equalReady(a, b *int32) bool {
|
||||||
|
if a != nil && b != nil {
|
||||||
|
return *a == *b
|
||||||
|
}
|
||||||
|
return a == b
|
||||||
|
}
|
||||||
|
@ -125,31 +125,41 @@ func newPod(name string, job *batch.Job) *v1.Pod {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// create count pods with the given phase for the given job
|
// create count pods with the given phase for the given job
|
||||||
func newPodList(count int32, status v1.PodPhase, job *batch.Job) []v1.Pod {
|
func newPodList(count int, status v1.PodPhase, job *batch.Job) []*v1.Pod {
|
||||||
pods := []v1.Pod{}
|
var pods []*v1.Pod
|
||||||
for i := int32(0); i < count; i++ {
|
for i := 0; i < count; i++ {
|
||||||
newPod := newPod(fmt.Sprintf("pod-%v", rand.String(10)), job)
|
newPod := newPod(fmt.Sprintf("pod-%v", rand.String(10)), job)
|
||||||
newPod.Status = v1.PodStatus{Phase: status}
|
newPod.Status = v1.PodStatus{Phase: status}
|
||||||
if trackingUncountedPods(job) {
|
if trackingUncountedPods(job) {
|
||||||
newPod.Finalizers = append(newPod.Finalizers, batch.JobTrackingFinalizer)
|
newPod.Finalizers = append(newPod.Finalizers, batch.JobTrackingFinalizer)
|
||||||
}
|
}
|
||||||
pods = append(pods, *newPod)
|
pods = append(pods, newPod)
|
||||||
}
|
}
|
||||||
return pods
|
return pods
|
||||||
}
|
}
|
||||||
|
|
||||||
func setPodsStatuses(podIndexer cache.Indexer, job *batch.Job, pendingPods, activePods, succeededPods, failedPods int32) {
|
func setPodsStatuses(podIndexer cache.Indexer, job *batch.Job, pendingPods, activePods, succeededPods, failedPods, readyPods int) {
|
||||||
for _, pod := range newPodList(pendingPods, v1.PodPending, job) {
|
for _, pod := range newPodList(pendingPods, v1.PodPending, job) {
|
||||||
podIndexer.Add(&pod)
|
podIndexer.Add(pod)
|
||||||
}
|
}
|
||||||
for _, pod := range newPodList(activePods, v1.PodRunning, job) {
|
running := newPodList(activePods, v1.PodRunning, job)
|
||||||
podIndexer.Add(&pod)
|
for i, p := range running {
|
||||||
|
if i >= readyPods {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
p.Status.Conditions = append(p.Status.Conditions, v1.PodCondition{
|
||||||
|
Type: v1.PodReady,
|
||||||
|
Status: v1.ConditionTrue,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
for _, pod := range running {
|
||||||
|
podIndexer.Add(pod)
|
||||||
}
|
}
|
||||||
for _, pod := range newPodList(succeededPods, v1.PodSucceeded, job) {
|
for _, pod := range newPodList(succeededPods, v1.PodSucceeded, job) {
|
||||||
podIndexer.Add(&pod)
|
podIndexer.Add(pod)
|
||||||
}
|
}
|
||||||
for _, pod := range newPodList(failedPods, v1.PodFailed, job) {
|
for _, pod := range newPodList(failedPods, v1.PodFailed, job) {
|
||||||
podIndexer.Add(&pod)
|
podIndexer.Add(pod)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -189,10 +199,11 @@ func TestControllerSyncJob(t *testing.T) {
|
|||||||
// pod setup
|
// pod setup
|
||||||
podControllerError error
|
podControllerError error
|
||||||
jobKeyForget bool
|
jobKeyForget bool
|
||||||
pendingPods int32
|
pendingPods int
|
||||||
activePods int32
|
activePods int
|
||||||
succeededPods int32
|
readyPods int
|
||||||
failedPods int32
|
succeededPods int
|
||||||
|
failedPods int
|
||||||
podsWithIndexes []indexPhase
|
podsWithIndexes []indexPhase
|
||||||
fakeExpectationAtCreation int32 // negative: ExpectDeletions, positive: ExpectCreations
|
fakeExpectationAtCreation int32 // negative: ExpectDeletions, positive: ExpectCreations
|
||||||
|
|
||||||
@ -200,6 +211,7 @@ func TestControllerSyncJob(t *testing.T) {
|
|||||||
expectedCreations int32
|
expectedCreations int32
|
||||||
expectedDeletions int32
|
expectedDeletions int32
|
||||||
expectedActive int32
|
expectedActive int32
|
||||||
|
expectedReady *int32
|
||||||
expectedSucceeded int32
|
expectedSucceeded int32
|
||||||
expectedCompletedIdxs string
|
expectedCompletedIdxs string
|
||||||
expectedFailed int32
|
expectedFailed int32
|
||||||
@ -214,6 +226,7 @@ func TestControllerSyncJob(t *testing.T) {
|
|||||||
// features
|
// features
|
||||||
indexedJobEnabled bool
|
indexedJobEnabled bool
|
||||||
suspendJobEnabled bool
|
suspendJobEnabled bool
|
||||||
|
jobReadyPodsEnabled bool
|
||||||
}{
|
}{
|
||||||
"job start": {
|
"job start": {
|
||||||
parallelism: 2,
|
parallelism: 2,
|
||||||
@ -240,12 +253,24 @@ func TestControllerSyncJob(t *testing.T) {
|
|||||||
expectedActive: 2,
|
expectedActive: 2,
|
||||||
},
|
},
|
||||||
"correct # of pods": {
|
"correct # of pods": {
|
||||||
parallelism: 2,
|
parallelism: 3,
|
||||||
completions: 5,
|
completions: 5,
|
||||||
backoffLimit: 6,
|
backoffLimit: 6,
|
||||||
jobKeyForget: true,
|
jobKeyForget: true,
|
||||||
activePods: 2,
|
activePods: 3,
|
||||||
expectedActive: 2,
|
readyPods: 2,
|
||||||
|
expectedActive: 3,
|
||||||
|
},
|
||||||
|
"correct # of pods, ready enabled": {
|
||||||
|
parallelism: 3,
|
||||||
|
completions: 5,
|
||||||
|
backoffLimit: 6,
|
||||||
|
jobKeyForget: true,
|
||||||
|
activePods: 3,
|
||||||
|
readyPods: 2,
|
||||||
|
expectedActive: 3,
|
||||||
|
expectedReady: pointer.Int32(2),
|
||||||
|
jobReadyPodsEnabled: true,
|
||||||
},
|
},
|
||||||
"WQ job: correct # of pods": {
|
"WQ job: correct # of pods": {
|
||||||
parallelism: 2,
|
parallelism: 2,
|
||||||
@ -709,6 +734,7 @@ func TestControllerSyncJob(t *testing.T) {
|
|||||||
}
|
}
|
||||||
defer featuregatetesting.SetFeatureGateDuringTest(t, feature.DefaultFeatureGate, features.IndexedJob, tc.indexedJobEnabled)()
|
defer featuregatetesting.SetFeatureGateDuringTest(t, feature.DefaultFeatureGate, features.IndexedJob, tc.indexedJobEnabled)()
|
||||||
defer featuregatetesting.SetFeatureGateDuringTest(t, feature.DefaultFeatureGate, features.SuspendJob, tc.suspendJobEnabled)()
|
defer featuregatetesting.SetFeatureGateDuringTest(t, feature.DefaultFeatureGate, features.SuspendJob, tc.suspendJobEnabled)()
|
||||||
|
defer featuregatetesting.SetFeatureGateDuringTest(t, feature.DefaultFeatureGate, features.JobReadyPods, tc.jobReadyPodsEnabled)()
|
||||||
defer featuregatetesting.SetFeatureGateDuringTest(t, feature.DefaultFeatureGate, features.JobTrackingWithFinalizers, wFinalizers)()
|
defer featuregatetesting.SetFeatureGateDuringTest(t, feature.DefaultFeatureGate, features.JobTrackingWithFinalizers, wFinalizers)()
|
||||||
|
|
||||||
// job manager setup
|
// job manager setup
|
||||||
@ -745,7 +771,7 @@ func TestControllerSyncJob(t *testing.T) {
|
|||||||
}
|
}
|
||||||
sharedInformerFactory.Batch().V1().Jobs().Informer().GetIndexer().Add(job)
|
sharedInformerFactory.Batch().V1().Jobs().Informer().GetIndexer().Add(job)
|
||||||
podIndexer := sharedInformerFactory.Core().V1().Pods().Informer().GetIndexer()
|
podIndexer := sharedInformerFactory.Core().V1().Pods().Informer().GetIndexer()
|
||||||
setPodsStatuses(podIndexer, job, tc.pendingPods, tc.activePods, tc.succeededPods, tc.failedPods)
|
setPodsStatuses(podIndexer, job, tc.pendingPods, tc.activePods, tc.succeededPods, tc.failedPods, tc.readyPods)
|
||||||
setPodsStatusesWithIndexes(podIndexer, job, tc.podsWithIndexes)
|
setPodsStatusesWithIndexes(podIndexer, job, tc.podsWithIndexes)
|
||||||
|
|
||||||
actual := job
|
actual := job
|
||||||
@ -822,6 +848,9 @@ func TestControllerSyncJob(t *testing.T) {
|
|||||||
if actual.Status.Active != tc.expectedActive {
|
if actual.Status.Active != tc.expectedActive {
|
||||||
t.Errorf("Unexpected number of active pods. Expected %d, saw %d\n", tc.expectedActive, actual.Status.Active)
|
t.Errorf("Unexpected number of active pods. Expected %d, saw %d\n", tc.expectedActive, actual.Status.Active)
|
||||||
}
|
}
|
||||||
|
if diff := cmp.Diff(tc.expectedReady, actual.Status.Ready); diff != "" {
|
||||||
|
t.Errorf("Unexpected number of ready pods (-want,+got): %s", diff)
|
||||||
|
}
|
||||||
if actual.Status.Succeeded != tc.expectedSucceeded {
|
if actual.Status.Succeeded != tc.expectedSucceeded {
|
||||||
t.Errorf("Unexpected number of succeeded pods. Expected %d, saw %d\n", tc.expectedSucceeded, actual.Status.Succeeded)
|
t.Errorf("Unexpected number of succeeded pods. Expected %d, saw %d\n", tc.expectedSucceeded, actual.Status.Succeeded)
|
||||||
}
|
}
|
||||||
@ -1655,9 +1684,9 @@ func TestSyncJobPastDeadline(t *testing.T) {
|
|||||||
suspend bool
|
suspend bool
|
||||||
|
|
||||||
// pod setup
|
// pod setup
|
||||||
activePods int32
|
activePods int
|
||||||
succeededPods int32
|
succeededPods int
|
||||||
failedPods int32
|
failedPods int
|
||||||
|
|
||||||
// expectations
|
// expectations
|
||||||
expectedForGetKey bool
|
expectedForGetKey bool
|
||||||
@ -1759,7 +1788,7 @@ func TestSyncJobPastDeadline(t *testing.T) {
|
|||||||
job.Status.StartTime = &start
|
job.Status.StartTime = &start
|
||||||
sharedInformerFactory.Batch().V1().Jobs().Informer().GetIndexer().Add(job)
|
sharedInformerFactory.Batch().V1().Jobs().Informer().GetIndexer().Add(job)
|
||||||
podIndexer := sharedInformerFactory.Core().V1().Pods().Informer().GetIndexer()
|
podIndexer := sharedInformerFactory.Core().V1().Pods().Informer().GetIndexer()
|
||||||
setPodsStatuses(podIndexer, job, 0, tc.activePods, tc.succeededPods, tc.failedPods)
|
setPodsStatuses(podIndexer, job, 0, tc.activePods, tc.succeededPods, tc.failedPods, 0)
|
||||||
|
|
||||||
// run
|
// run
|
||||||
forget, err := manager.syncJob(testutil.GetKey(job, t))
|
forget, err := manager.syncJob(testutil.GetKey(job, t))
|
||||||
@ -2447,14 +2476,14 @@ func TestSyncJobExpectations(t *testing.T) {
|
|||||||
sharedInformerFactory.Batch().V1().Jobs().Informer().GetIndexer().Add(job)
|
sharedInformerFactory.Batch().V1().Jobs().Informer().GetIndexer().Add(job)
|
||||||
pods := newPodList(2, v1.PodPending, job)
|
pods := newPodList(2, v1.PodPending, job)
|
||||||
podIndexer := sharedInformerFactory.Core().V1().Pods().Informer().GetIndexer()
|
podIndexer := sharedInformerFactory.Core().V1().Pods().Informer().GetIndexer()
|
||||||
podIndexer.Add(&pods[0])
|
podIndexer.Add(pods[0])
|
||||||
|
|
||||||
manager.expectations = FakeJobExpectations{
|
manager.expectations = FakeJobExpectations{
|
||||||
controller.NewControllerExpectations(), true, func() {
|
controller.NewControllerExpectations(), true, func() {
|
||||||
// If we check active pods before checking expectations, the job
|
// If we check active pods before checking expectations, the job
|
||||||
// will create a new replica because it doesn't see this pod, but
|
// will create a new replica because it doesn't see this pod, but
|
||||||
// has fulfilled its expectations.
|
// has fulfilled its expectations.
|
||||||
podIndexer.Add(&pods[1])
|
podIndexer.Add(pods[1])
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
manager.syncJob(testutil.GetKey(job, t))
|
manager.syncJob(testutil.GetKey(job, t))
|
||||||
@ -2551,7 +2580,7 @@ func TestWatchPods(t *testing.T) {
|
|||||||
pods := newPodList(1, v1.PodRunning, testJob)
|
pods := newPodList(1, v1.PodRunning, testJob)
|
||||||
testPod := pods[0]
|
testPod := pods[0]
|
||||||
testPod.Status.Phase = v1.PodFailed
|
testPod.Status.Phase = v1.PodFailed
|
||||||
fakeWatch.Add(&testPod)
|
fakeWatch.Add(testPod)
|
||||||
|
|
||||||
t.Log("Waiting for pod to reach syncHandler")
|
t.Log("Waiting for pod to reach syncHandler")
|
||||||
<-received
|
<-received
|
||||||
@ -2604,10 +2633,10 @@ func bumpResourceVersion(obj metav1.Object) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
type pods struct {
|
type pods struct {
|
||||||
pending int32
|
pending int
|
||||||
active int32
|
active int
|
||||||
succeed int32
|
succeed int
|
||||||
failed int32
|
failed int
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestJobBackoffReset(t *testing.T) {
|
func TestJobBackoffReset(t *testing.T) {
|
||||||
@ -2656,7 +2685,7 @@ func TestJobBackoffReset(t *testing.T) {
|
|||||||
sharedInformerFactory.Batch().V1().Jobs().Informer().GetIndexer().Add(job)
|
sharedInformerFactory.Batch().V1().Jobs().Informer().GetIndexer().Add(job)
|
||||||
podIndexer := sharedInformerFactory.Core().V1().Pods().Informer().GetIndexer()
|
podIndexer := sharedInformerFactory.Core().V1().Pods().Informer().GetIndexer()
|
||||||
|
|
||||||
setPodsStatuses(podIndexer, job, tc.pods[0].pending, tc.pods[0].active, tc.pods[0].succeed, tc.pods[0].failed)
|
setPodsStatuses(podIndexer, job, tc.pods[0].pending, tc.pods[0].active, tc.pods[0].succeed, tc.pods[0].failed, 0)
|
||||||
manager.queue.Add(key)
|
manager.queue.Add(key)
|
||||||
manager.processNextWorkItem()
|
manager.processNextWorkItem()
|
||||||
retries := manager.queue.NumRequeues(key)
|
retries := manager.queue.NumRequeues(key)
|
||||||
@ -2666,7 +2695,7 @@ func TestJobBackoffReset(t *testing.T) {
|
|||||||
|
|
||||||
job = actual
|
job = actual
|
||||||
sharedInformerFactory.Batch().V1().Jobs().Informer().GetIndexer().Replace([]interface{}{actual}, actual.ResourceVersion)
|
sharedInformerFactory.Batch().V1().Jobs().Informer().GetIndexer().Replace([]interface{}{actual}, actual.ResourceVersion)
|
||||||
setPodsStatuses(podIndexer, job, tc.pods[1].pending, tc.pods[1].active, tc.pods[1].succeed, tc.pods[1].failed)
|
setPodsStatuses(podIndexer, job, tc.pods[1].pending, tc.pods[1].active, tc.pods[1].succeed, tc.pods[1].failed, 0)
|
||||||
manager.processNextWorkItem()
|
manager.processNextWorkItem()
|
||||||
retries = manager.queue.NumRequeues(key)
|
retries = manager.queue.NumRequeues(key)
|
||||||
if retries != 0 {
|
if retries != 0 {
|
||||||
@ -2835,9 +2864,9 @@ func TestJobBackoffForOnFailure(t *testing.T) {
|
|||||||
job.Spec.Template.Spec.RestartPolicy = v1.RestartPolicyOnFailure
|
job.Spec.Template.Spec.RestartPolicy = v1.RestartPolicyOnFailure
|
||||||
sharedInformerFactory.Batch().V1().Jobs().Informer().GetIndexer().Add(job)
|
sharedInformerFactory.Batch().V1().Jobs().Informer().GetIndexer().Add(job)
|
||||||
podIndexer := sharedInformerFactory.Core().V1().Pods().Informer().GetIndexer()
|
podIndexer := sharedInformerFactory.Core().V1().Pods().Informer().GetIndexer()
|
||||||
for i, pod := range newPodList(int32(len(tc.restartCounts)), tc.podPhase, job) {
|
for i, pod := range newPodList(len(tc.restartCounts), tc.podPhase, job) {
|
||||||
pod.Status.ContainerStatuses = []v1.ContainerStatus{{RestartCount: tc.restartCounts[i]}}
|
pod.Status.ContainerStatuses = []v1.ContainerStatus{{RestartCount: tc.restartCounts[i]}}
|
||||||
podIndexer.Add(&pod)
|
podIndexer.Add(pod)
|
||||||
}
|
}
|
||||||
|
|
||||||
// run
|
// run
|
||||||
@ -2878,8 +2907,8 @@ func TestJobBackoffOnRestartPolicyNever(t *testing.T) {
|
|||||||
|
|
||||||
// pod setup
|
// pod setup
|
||||||
activePodsPhase v1.PodPhase
|
activePodsPhase v1.PodPhase
|
||||||
activePods int32
|
activePods int
|
||||||
failedPods int32
|
failedPods int
|
||||||
|
|
||||||
// expectations
|
// expectations
|
||||||
isExpectingAnError bool
|
isExpectingAnError bool
|
||||||
@ -2938,10 +2967,10 @@ func TestJobBackoffOnRestartPolicyNever(t *testing.T) {
|
|||||||
sharedInformerFactory.Batch().V1().Jobs().Informer().GetIndexer().Add(job)
|
sharedInformerFactory.Batch().V1().Jobs().Informer().GetIndexer().Add(job)
|
||||||
podIndexer := sharedInformerFactory.Core().V1().Pods().Informer().GetIndexer()
|
podIndexer := sharedInformerFactory.Core().V1().Pods().Informer().GetIndexer()
|
||||||
for _, pod := range newPodList(tc.failedPods, v1.PodFailed, job) {
|
for _, pod := range newPodList(tc.failedPods, v1.PodFailed, job) {
|
||||||
podIndexer.Add(&pod)
|
podIndexer.Add(pod)
|
||||||
}
|
}
|
||||||
for _, pod := range newPodList(tc.activePods, tc.activePodsPhase, job) {
|
for _, pod := range newPodList(tc.activePods, tc.activePodsPhase, job) {
|
||||||
podIndexer.Add(&pod)
|
podIndexer.Add(pod)
|
||||||
}
|
}
|
||||||
|
|
||||||
// run
|
// run
|
||||||
@ -3079,8 +3108,8 @@ func TestFinalizersRemovedExpectations(t *testing.T) {
|
|||||||
podIndexer := podInformer.GetIndexer()
|
podIndexer := podInformer.GetIndexer()
|
||||||
uids := sets.NewString()
|
uids := sets.NewString()
|
||||||
for i := range pods {
|
for i := range pods {
|
||||||
clientset.Tracker().Add(&pods[i])
|
clientset.Tracker().Add(pods[i])
|
||||||
podIndexer.Add(&pods[i])
|
podIndexer.Add(pods[i])
|
||||||
uids.Insert(string(pods[i].UID))
|
uids.Insert(string(pods[i].UID))
|
||||||
}
|
}
|
||||||
jobKey := testutil.GetKey(job, t)
|
jobKey := testutil.GetKey(job, t)
|
||||||
|
@ -232,6 +232,12 @@ const (
|
|||||||
// yet.
|
// yet.
|
||||||
JobTrackingWithFinalizers featuregate.Feature = "JobTrackingWithFinalizers"
|
JobTrackingWithFinalizers featuregate.Feature = "JobTrackingWithFinalizers"
|
||||||
|
|
||||||
|
// owner: @alculquicondor
|
||||||
|
// alpha: v1.23
|
||||||
|
//
|
||||||
|
// Track the number of pods with Ready condition in the Job status.
|
||||||
|
JobReadyPods featuregate.Feature = "JobReadyPods"
|
||||||
|
|
||||||
// owner: @dashpole
|
// owner: @dashpole
|
||||||
// alpha: v1.13
|
// alpha: v1.13
|
||||||
// beta: v1.15
|
// beta: v1.15
|
||||||
@ -829,6 +835,7 @@ var defaultKubernetesFeatureGates = map[featuregate.Feature]featuregate.FeatureS
|
|||||||
TTLAfterFinished: {Default: true, PreRelease: featuregate.GA, LockToDefault: true}, // remove in 1.25
|
TTLAfterFinished: {Default: true, PreRelease: featuregate.GA, LockToDefault: true}, // remove in 1.25
|
||||||
IndexedJob: {Default: true, PreRelease: featuregate.Beta},
|
IndexedJob: {Default: true, PreRelease: featuregate.Beta},
|
||||||
JobTrackingWithFinalizers: {Default: true, PreRelease: featuregate.Beta},
|
JobTrackingWithFinalizers: {Default: true, PreRelease: featuregate.Beta},
|
||||||
|
JobReadyPods: {Default: false, PreRelease: featuregate.Alpha},
|
||||||
KubeletPodResources: {Default: true, PreRelease: featuregate.Beta},
|
KubeletPodResources: {Default: true, PreRelease: featuregate.Beta},
|
||||||
LocalStorageCapacityIsolationFSQuotaMonitoring: {Default: false, PreRelease: featuregate.Alpha},
|
LocalStorageCapacityIsolationFSQuotaMonitoring: {Default: false, PreRelease: featuregate.Alpha},
|
||||||
NonPreemptingPriority: {Default: true, PreRelease: featuregate.Beta},
|
NonPreemptingPriority: {Default: true, PreRelease: featuregate.Beta},
|
||||||
|
206
staging/src/k8s.io/api/batch/v1/generated.pb.go
generated
206
staging/src/k8s.io/api/batch/v1/generated.pb.go
generated
@ -375,95 +375,96 @@ func init() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
var fileDescriptor_3b52da57c93de713 = []byte{
|
var fileDescriptor_3b52da57c93de713 = []byte{
|
||||||
// 1395 bytes of a gzipped FileDescriptorProto
|
// 1413 bytes of a gzipped FileDescriptorProto
|
||||||
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xcc, 0x57, 0xcf, 0x6f, 0x1b, 0xc5,
|
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xcc, 0x57, 0x41, 0x6f, 0x1b, 0xc5,
|
||||||
0x17, 0xcf, 0xc6, 0x76, 0x6c, 0x8f, 0x93, 0xd4, 0x9d, 0x7e, 0xdb, 0xfa, 0x6b, 0x2a, 0x6f, 0x6a,
|
0x17, 0xcf, 0x26, 0x71, 0x62, 0x8f, 0x93, 0xd4, 0x9d, 0xfe, 0xdb, 0xfa, 0x6f, 0x2a, 0x6f, 0x6a,
|
||||||
0x0a, 0x0a, 0xa8, 0xac, 0x49, 0x88, 0x10, 0x42, 0x80, 0x94, 0x4d, 0x55, 0x68, 0x70, 0xd4, 0x30,
|
0x0a, 0x0a, 0xa8, 0xac, 0x49, 0x88, 0x10, 0x42, 0x80, 0x94, 0x4d, 0x55, 0x68, 0x70, 0xd4, 0x30,
|
||||||
0x76, 0x84, 0x04, 0x05, 0xb1, 0xde, 0x1d, 0x3b, 0xdb, 0xec, 0xee, 0x58, 0x3b, 0x63, 0x8b, 0xdc,
|
0x76, 0x84, 0x04, 0x05, 0xb1, 0xde, 0x1d, 0x3b, 0xdb, 0xec, 0xee, 0x58, 0x3b, 0x63, 0x0b, 0xdf,
|
||||||
0x90, 0xf8, 0x07, 0xf8, 0x2b, 0x10, 0x27, 0x84, 0x04, 0x67, 0x8e, 0xa8, 0xc7, 0x1e, 0x7b, 0x5a,
|
0x90, 0xf8, 0x02, 0xf0, 0x25, 0x10, 0x27, 0x84, 0x04, 0x67, 0x8e, 0xa8, 0xc7, 0x1e, 0x7b, 0x5a,
|
||||||
0xd1, 0xe5, 0x0f, 0x80, 0x73, 0xb8, 0xa0, 0x9d, 0x1d, 0xef, 0x0f, 0x7b, 0x37, 0xa4, 0x3d, 0x54,
|
0xd1, 0xe5, 0x03, 0x70, 0x0f, 0x17, 0x34, 0xb3, 0xe3, 0xdd, 0xb5, 0xbd, 0x1b, 0xd2, 0x1e, 0x2a,
|
||||||
0xdc, 0xbc, 0x6f, 0x3e, 0x9f, 0xcf, 0xbc, 0x99, 0xf7, 0xe6, 0xbd, 0x67, 0xf0, 0xde, 0xc9, 0x3b,
|
0x6e, 0xd9, 0x37, 0xbf, 0xf7, 0x9b, 0xe7, 0xf7, 0x7e, 0xf3, 0xde, 0x0b, 0x78, 0xef, 0xf4, 0x1d,
|
||||||
0x54, 0x31, 0x49, 0xe7, 0x64, 0x32, 0xc0, 0xae, 0x83, 0x19, 0xa6, 0x9d, 0x29, 0x76, 0x0c, 0xe2,
|
0xaa, 0xd9, 0xa4, 0x79, 0x3a, 0xec, 0x62, 0xdf, 0xc3, 0x0c, 0xd3, 0xe6, 0x08, 0x7b, 0x16, 0xf1,
|
||||||
0x76, 0xc4, 0x82, 0x36, 0x36, 0x3b, 0x03, 0x8d, 0xe9, 0xc7, 0x9d, 0xe9, 0x56, 0x67, 0x84, 0x1d,
|
0x9b, 0xf2, 0xc0, 0x18, 0xd8, 0xcd, 0xae, 0xc1, 0xcc, 0x93, 0xe6, 0x68, 0xbb, 0xd9, 0xc7, 0x1e,
|
||||||
0xec, 0x6a, 0x0c, 0x1b, 0xca, 0xd8, 0x25, 0x8c, 0xc0, 0x2b, 0x21, 0x48, 0xd1, 0xc6, 0xa6, 0xc2,
|
0xf6, 0x0d, 0x86, 0x2d, 0x6d, 0xe0, 0x13, 0x46, 0xe0, 0x95, 0x08, 0xa4, 0x19, 0x03, 0x5b, 0x13,
|
||||||
0x41, 0xca, 0x74, 0xab, 0xf9, 0xc6, 0xc8, 0x64, 0xc7, 0x93, 0x81, 0xa2, 0x13, 0xbb, 0x33, 0x22,
|
0x20, 0x6d, 0xb4, 0x5d, 0x7b, 0xa3, 0x6f, 0xb3, 0x93, 0x61, 0x57, 0x33, 0x89, 0xdb, 0xec, 0x93,
|
||||||
0x23, 0xd2, 0xe1, 0xd8, 0xc1, 0x64, 0xc8, 0xbf, 0xf8, 0x07, 0xff, 0x15, 0x6a, 0x34, 0xdb, 0x89,
|
0x3e, 0x69, 0x0a, 0x6c, 0x77, 0xd8, 0x13, 0x5f, 0xe2, 0x43, 0xfc, 0x15, 0x71, 0xd4, 0x1a, 0xa9,
|
||||||
0x8d, 0x74, 0xe2, 0xe2, 0x8c, 0x7d, 0x9a, 0x3b, 0x31, 0xc6, 0xd6, 0xf4, 0x63, 0xd3, 0xc1, 0xee,
|
0x8b, 0x4c, 0xe2, 0xe3, 0x8c, 0x7b, 0x6a, 0xbb, 0x09, 0xc6, 0x35, 0xcc, 0x13, 0xdb, 0xc3, 0xfe,
|
||||||
0x69, 0x67, 0x7c, 0x32, 0x0a, 0x0c, 0xb4, 0x63, 0x63, 0xa6, 0x65, 0xb1, 0x3a, 0x79, 0x2c, 0x77,
|
0xb8, 0x39, 0x38, 0xed, 0x73, 0x03, 0x6d, 0xba, 0x98, 0x19, 0x59, 0x5e, 0xcd, 0x3c, 0x2f, 0x7f,
|
||||||
0xe2, 0x30, 0xd3, 0xc6, 0x0b, 0x84, 0xb7, 0xff, 0x8d, 0x40, 0xf5, 0x63, 0x6c, 0x6b, 0xf3, 0xbc,
|
0xe8, 0x31, 0xdb, 0xc5, 0x73, 0x0e, 0x6f, 0xff, 0x9b, 0x03, 0x35, 0x4f, 0xb0, 0x6b, 0xcc, 0xfa,
|
||||||
0xf6, 0xdf, 0x12, 0x28, 0xef, 0xb9, 0xc4, 0xd9, 0x27, 0x03, 0xf8, 0x15, 0xa8, 0x04, 0xfe, 0x18,
|
0x35, 0xfe, 0x56, 0xc0, 0xea, 0xbe, 0x4f, 0xbc, 0x03, 0xd2, 0x85, 0x5f, 0x81, 0x22, 0x8f, 0xc7,
|
||||||
0x1a, 0xd3, 0x1a, 0xd2, 0x86, 0xb4, 0x59, 0xdb, 0x7e, 0x53, 0x89, 0x6f, 0x29, 0x92, 0x55, 0xc6,
|
0x32, 0x98, 0x51, 0x55, 0x36, 0x95, 0xad, 0xf2, 0xce, 0x9b, 0x5a, 0x92, 0xa5, 0x98, 0x56, 0x1b,
|
||||||
0x27, 0xa3, 0xc0, 0x40, 0x95, 0x00, 0xad, 0x4c, 0xb7, 0x94, 0xfb, 0x83, 0x87, 0x58, 0x67, 0x07,
|
0x9c, 0xf6, 0xb9, 0x81, 0x6a, 0x1c, 0xad, 0x8d, 0xb6, 0xb5, 0xfb, 0xdd, 0x87, 0xd8, 0x64, 0x87,
|
||||||
0x98, 0x69, 0x2a, 0x7c, 0xe4, 0xc9, 0x4b, 0xbe, 0x27, 0x83, 0xd8, 0x86, 0x22, 0x55, 0xa8, 0x82,
|
0x98, 0x19, 0x3a, 0x7c, 0x14, 0xa8, 0x0b, 0x61, 0xa0, 0x82, 0xc4, 0x86, 0x62, 0x56, 0xa8, 0x83,
|
||||||
0x22, 0x1d, 0x63, 0xbd, 0xb1, 0xcc, 0xd5, 0x37, 0x94, 0x8c, 0x18, 0x28, 0xc2, 0x9b, 0xde, 0x18,
|
0x65, 0x3a, 0xc0, 0x66, 0x75, 0x51, 0xb0, 0x6f, 0x6a, 0x19, 0x35, 0xd0, 0x64, 0x34, 0xed, 0x01,
|
||||||
0xeb, 0xea, 0xaa, 0x50, 0x2b, 0x06, 0x5f, 0x88, 0x73, 0xe1, 0x3e, 0x58, 0xa1, 0x4c, 0x63, 0x13,
|
0x36, 0xf5, 0x35, 0xc9, 0xb6, 0xcc, 0xbf, 0x90, 0xf0, 0x85, 0x07, 0x60, 0x85, 0x32, 0x83, 0x0d,
|
||||||
0xda, 0x28, 0x70, 0x95, 0xf6, 0xb9, 0x2a, 0x1c, 0xa9, 0xae, 0x0b, 0x9d, 0x95, 0xf0, 0x1b, 0x09,
|
0x69, 0x75, 0x49, 0xb0, 0x34, 0xce, 0x65, 0x11, 0x48, 0x7d, 0x43, 0xf2, 0xac, 0x44, 0xdf, 0x48,
|
||||||
0x85, 0xf6, 0x8f, 0x12, 0xa8, 0x09, 0x64, 0xd7, 0xa4, 0x0c, 0x3e, 0x58, 0xb8, 0x01, 0xe5, 0x62,
|
0x32, 0x34, 0x7e, 0x52, 0x40, 0x59, 0x22, 0x5b, 0x36, 0x65, 0xf0, 0xc1, 0x5c, 0x06, 0xb4, 0x8b,
|
||||||
0x37, 0x10, 0xb0, 0xf9, 0xf9, 0xeb, 0x62, 0xa7, 0xca, 0xcc, 0x92, 0x38, 0xfd, 0x2e, 0x28, 0x99,
|
0x65, 0x80, 0x7b, 0x8b, 0xdf, 0x5f, 0x91, 0x37, 0x15, 0x27, 0x96, 0xd4, 0xaf, 0xdf, 0x03, 0x05,
|
||||||
0x0c, 0xdb, 0xb4, 0xb1, 0xbc, 0x51, 0xd8, 0xac, 0x6d, 0xdf, 0x38, 0xcf, 0x71, 0x75, 0x4d, 0x08,
|
0x9b, 0x61, 0x97, 0x56, 0x17, 0x37, 0x97, 0xb6, 0xca, 0x3b, 0x37, 0xce, 0x0b, 0x5c, 0x5f, 0x97,
|
||||||
0x95, 0xee, 0x05, 0x14, 0x14, 0x32, 0xdb, 0x3f, 0x14, 0x23, 0x87, 0x83, 0x2b, 0x81, 0xb7, 0x41,
|
0x44, 0x85, 0x7b, 0xdc, 0x05, 0x45, 0x9e, 0x8d, 0x1f, 0x97, 0xe3, 0x80, 0x79, 0x4a, 0xe0, 0x6d,
|
||||||
0x25, 0x08, 0xac, 0x31, 0xb1, 0x30, 0x77, 0xb8, 0x1a, 0x3b, 0xd0, 0x13, 0x76, 0x14, 0x21, 0xe0,
|
0x50, 0xe4, 0x85, 0xb5, 0x86, 0x0e, 0x16, 0x01, 0x97, 0x92, 0x00, 0xda, 0xd2, 0x8e, 0x62, 0x04,
|
||||||
0x11, 0xb8, 0x4e, 0x99, 0xe6, 0x32, 0xd3, 0x19, 0xdd, 0xc1, 0x9a, 0x61, 0x99, 0x0e, 0xee, 0x61,
|
0x3c, 0x06, 0xd7, 0x29, 0x33, 0x7c, 0x66, 0x7b, 0xfd, 0x3b, 0xd8, 0xb0, 0x1c, 0xdb, 0xc3, 0x6d,
|
||||||
0x9d, 0x38, 0x06, 0xe5, 0x11, 0x29, 0xa8, 0x2f, 0xf9, 0x9e, 0x7c, 0xbd, 0x97, 0x0d, 0x41, 0x79,
|
0x6c, 0x12, 0xcf, 0xa2, 0xa2, 0x22, 0x4b, 0xfa, 0x4b, 0x61, 0xa0, 0x5e, 0x6f, 0x67, 0x43, 0x50,
|
||||||
0x5c, 0xf8, 0x00, 0x5c, 0xd6, 0x89, 0xa3, 0x4f, 0x5c, 0x17, 0x3b, 0xfa, 0xe9, 0x21, 0xb1, 0x4c,
|
0x9e, 0x2f, 0x7c, 0x00, 0x2e, 0x9b, 0xc4, 0x33, 0x87, 0xbe, 0x8f, 0x3d, 0x73, 0x7c, 0x44, 0x1c,
|
||||||
0xfd, 0x94, 0x07, 0xa7, 0xaa, 0x2a, 0xc2, 0x9b, 0xcb, 0x7b, 0xf3, 0x80, 0xb3, 0x2c, 0x23, 0x5a,
|
0xdb, 0x1c, 0x8b, 0xe2, 0x94, 0x74, 0x4d, 0x46, 0x73, 0x79, 0x7f, 0x16, 0x70, 0x96, 0x65, 0x44,
|
||||||
0x14, 0x82, 0xaf, 0x80, 0x32, 0x9d, 0xd0, 0x31, 0x76, 0x8c, 0x46, 0x71, 0x43, 0xda, 0xac, 0xa8,
|
0xf3, 0x44, 0xf0, 0x15, 0xb0, 0x4a, 0x87, 0x74, 0x80, 0x3d, 0xab, 0xba, 0xbc, 0xa9, 0x6c, 0x15,
|
||||||
0x35, 0xdf, 0x93, 0xcb, 0xbd, 0xd0, 0x84, 0x66, 0x6b, 0xf0, 0x73, 0x50, 0x7b, 0x48, 0x06, 0x7d,
|
0xf5, 0x72, 0x18, 0xa8, 0xab, 0xed, 0xc8, 0x84, 0x26, 0x67, 0xf0, 0x73, 0x50, 0x7e, 0x48, 0xba,
|
||||||
0x6c, 0x8f, 0x2d, 0x8d, 0xe1, 0x46, 0x89, 0x47, 0xef, 0x56, 0xe6, 0x15, 0xef, 0xc7, 0x38, 0x9e,
|
0x1d, 0xec, 0x0e, 0x1c, 0x83, 0xe1, 0x6a, 0x41, 0x54, 0xef, 0x56, 0x66, 0x8a, 0x0f, 0x12, 0x9c,
|
||||||
0x65, 0x57, 0x84, 0x93, 0xb5, 0xc4, 0x02, 0x4a, 0xaa, 0xc1, 0x2f, 0x41, 0x93, 0x4e, 0x74, 0x1d,
|
0x50, 0xd9, 0x15, 0x19, 0x64, 0x39, 0x75, 0x80, 0xd2, 0x6c, 0xf0, 0x4b, 0x50, 0xa3, 0x43, 0xd3,
|
||||||
0x53, 0x3a, 0x9c, 0x58, 0xfb, 0x64, 0x40, 0x3f, 0x32, 0x29, 0x23, 0xee, 0x69, 0xd7, 0xb4, 0x4d,
|
0xc4, 0x94, 0xf6, 0x86, 0xce, 0x01, 0xe9, 0xd2, 0x8f, 0x6c, 0xca, 0x88, 0x3f, 0x6e, 0xd9, 0xae,
|
||||||
0xd6, 0x58, 0xd9, 0x90, 0x36, 0x4b, 0x6a, 0xcb, 0xf7, 0xe4, 0x66, 0x2f, 0x17, 0x85, 0xce, 0x51,
|
0xcd, 0xaa, 0x2b, 0x9b, 0xca, 0x56, 0x41, 0xaf, 0x87, 0x81, 0x5a, 0x6b, 0xe7, 0xa2, 0xd0, 0x39,
|
||||||
0x80, 0x08, 0x5c, 0x1b, 0x6a, 0xa6, 0x85, 0x8d, 0x05, 0xed, 0x32, 0xd7, 0x6e, 0xfa, 0x9e, 0x7c,
|
0x0c, 0x10, 0x81, 0x6b, 0x3d, 0xc3, 0x76, 0xb0, 0x35, 0xc7, 0xbd, 0x2a, 0xb8, 0x6b, 0x61, 0xa0,
|
||||||
0xed, 0x6e, 0x26, 0x02, 0xe5, 0x30, 0xdb, 0xbf, 0x2e, 0x83, 0xb5, 0xd4, 0x2b, 0x80, 0x1f, 0x83,
|
0x5e, 0xbb, 0x9b, 0x89, 0x40, 0x39, 0x9e, 0x8d, 0xdf, 0x16, 0xc1, 0xfa, 0xd4, 0x2b, 0x80, 0x1f,
|
||||||
0x15, 0x4d, 0x67, 0xe6, 0x34, 0x48, 0x95, 0x20, 0x01, 0x5f, 0x4e, 0xde, 0x4e, 0x50, 0xbf, 0xe2,
|
0x83, 0x15, 0xc3, 0x64, 0xf6, 0x88, 0x4b, 0x85, 0x0b, 0xf0, 0xe5, 0x74, 0x76, 0x78, 0xff, 0x4a,
|
||||||
0xb7, 0x8c, 0xf0, 0x10, 0x07, 0x41, 0xc0, 0xf1, 0xd3, 0xd9, 0xe5, 0x54, 0x24, 0x24, 0xa0, 0x05,
|
0xde, 0x32, 0xc2, 0x3d, 0xcc, 0x8b, 0x80, 0x93, 0xa7, 0xb3, 0x27, 0x5c, 0x91, 0xa4, 0x80, 0x0e,
|
||||||
0xea, 0x96, 0x46, 0xd9, 0x2c, 0xcb, 0xfa, 0xa6, 0x8d, 0x79, 0x7c, 0x6a, 0xdb, 0xaf, 0x5f, 0xec,
|
0xa8, 0x38, 0x06, 0x65, 0x13, 0x95, 0x75, 0x6c, 0x17, 0x8b, 0xfa, 0x94, 0x77, 0x5e, 0xbf, 0xd8,
|
||||||
0xc9, 0x04, 0x0c, 0xf5, 0x7f, 0xbe, 0x27, 0xd7, 0xbb, 0x73, 0x3a, 0x68, 0x41, 0x19, 0xba, 0x00,
|
0x93, 0xe1, 0x1e, 0xfa, 0xff, 0xc2, 0x40, 0xad, 0xb4, 0x66, 0x78, 0xd0, 0x1c, 0x33, 0xf4, 0x01,
|
||||||
0x72, 0x5b, 0x74, 0x85, 0x7c, 0xbf, 0xd2, 0x33, 0xef, 0x77, 0xcd, 0xf7, 0x64, 0xd8, 0x5d, 0x50,
|
0x14, 0xb6, 0x38, 0x85, 0xe2, 0xbe, 0xc2, 0x33, 0xdf, 0x77, 0x2d, 0x0c, 0x54, 0xd8, 0x9a, 0x63,
|
||||||
0x42, 0x19, 0xea, 0xed, 0x3f, 0x25, 0x50, 0x78, 0x31, 0x65, 0xf1, 0x83, 0x54, 0x59, 0xbc, 0x91,
|
0x42, 0x19, 0xec, 0x8d, 0xbf, 0x14, 0xb0, 0xf4, 0x62, 0xda, 0xe2, 0x07, 0x53, 0x6d, 0xf1, 0x46,
|
||||||
0x97, 0xb4, 0xb9, 0x25, 0xf1, 0xee, 0x5c, 0x49, 0x6c, 0xe5, 0x2a, 0x9c, 0x5f, 0x0e, 0x7f, 0x2b,
|
0x9e, 0x68, 0x73, 0x5b, 0xe2, 0xdd, 0x99, 0x96, 0x58, 0xcf, 0x65, 0x38, 0xbf, 0x1d, 0xfe, 0xbe,
|
||||||
0x80, 0xd5, 0x7d, 0x32, 0xd8, 0x23, 0x8e, 0x61, 0x32, 0x93, 0x38, 0x70, 0x07, 0x14, 0xd9, 0xe9,
|
0x04, 0xd6, 0x0e, 0x48, 0x77, 0x9f, 0x78, 0x96, 0xcd, 0x6c, 0xe2, 0xc1, 0x5d, 0xb0, 0xcc, 0xc6,
|
||||||
0x78, 0x56, 0x5a, 0x36, 0x66, 0x5b, 0xf7, 0x4f, 0xc7, 0xf8, 0xcc, 0x93, 0xeb, 0x49, 0x6c, 0x60,
|
0x83, 0x49, 0x6b, 0xd9, 0x9c, 0x5c, 0xdd, 0x19, 0x0f, 0xf0, 0x59, 0xa0, 0x56, 0xd2, 0x58, 0x6e,
|
||||||
0x43, 0x1c, 0x0d, 0xbb, 0x91, 0x3b, 0xcb, 0x9c, 0xb7, 0x93, 0xde, 0xee, 0xcc, 0x93, 0x33, 0x1a,
|
0x43, 0x02, 0x0d, 0x5b, 0x71, 0x38, 0x8b, 0xc2, 0x6f, 0x77, 0xfa, 0xba, 0xb3, 0x40, 0xcd, 0x18,
|
||||||
0xa7, 0x12, 0x29, 0xa5, 0x9d, 0x82, 0x23, 0xb0, 0x16, 0x04, 0xe7, 0xd0, 0x25, 0x83, 0x30, 0xcb,
|
0x9c, 0x5a, 0xcc, 0x34, 0x1d, 0x14, 0xec, 0x83, 0x75, 0x5e, 0x9c, 0x23, 0x9f, 0x74, 0x23, 0x95,
|
||||||
0x0a, 0xcf, 0x1c, 0xf5, 0xab, 0xc2, 0x81, 0xb5, 0x6e, 0x52, 0x08, 0xa5, 0x75, 0xe1, 0x34, 0xcc,
|
0x2d, 0x3d, 0x73, 0xd5, 0xaf, 0xca, 0x00, 0xd6, 0x5b, 0x69, 0x22, 0x34, 0xcd, 0x0b, 0x47, 0x91,
|
||||||
0xb1, 0xbe, 0xab, 0x39, 0x34, 0x3c, 0xd2, 0xf3, 0xe5, 0x74, 0x53, 0xec, 0xc6, 0xf3, 0x2c, 0xad,
|
0xc6, 0x3a, 0xbe, 0xe1, 0xd1, 0xe8, 0x27, 0x3d, 0x9f, 0xa6, 0x6b, 0xf2, 0x36, 0xa1, 0xb3, 0x69,
|
||||||
0x86, 0x32, 0x76, 0x80, 0xaf, 0x82, 0x15, 0x17, 0x6b, 0x94, 0x38, 0x3c, 0x9f, 0xab, 0x71, 0x74,
|
0x36, 0x94, 0x71, 0x03, 0x7c, 0x15, 0xac, 0xf8, 0xd8, 0xa0, 0xc4, 0x13, 0x7a, 0x2e, 0x25, 0xd5,
|
||||||
0x10, 0xb7, 0x22, 0xb1, 0x0a, 0x5f, 0x03, 0x65, 0x1b, 0x53, 0xaa, 0x8d, 0x30, 0xaf, 0x38, 0x55,
|
0x41, 0xc2, 0x8a, 0xe4, 0x29, 0x7c, 0x0d, 0xac, 0xba, 0x98, 0x52, 0xa3, 0x8f, 0x45, 0xc7, 0x29,
|
||||||
0xf5, 0x92, 0x00, 0x96, 0x0f, 0x42, 0x33, 0x9a, 0xad, 0xb7, 0xbf, 0x97, 0x40, 0xf9, 0xc5, 0xf4,
|
0xe9, 0x97, 0x24, 0x70, 0xf5, 0x30, 0x32, 0xa3, 0xc9, 0x79, 0xe3, 0x07, 0x05, 0xac, 0xbe, 0x98,
|
||||||
0xb4, 0xf7, 0xd3, 0x3d, 0xad, 0x91, 0x97, 0x79, 0x39, 0xfd, 0xec, 0xa7, 0x12, 0x77, 0x94, 0xf7,
|
0x99, 0xf6, 0xfe, 0xf4, 0x4c, 0xab, 0xe6, 0x29, 0x2f, 0x67, 0x9e, 0xfd, 0x5c, 0x10, 0x81, 0x8a,
|
||||||
0xb2, 0x2d, 0x50, 0x1b, 0x6b, 0xae, 0x66, 0x59, 0xd8, 0x32, 0xa9, 0xcd, 0x7d, 0x2d, 0xa9, 0x97,
|
0x59, 0xb6, 0x0d, 0xca, 0x03, 0xc3, 0x37, 0x1c, 0x07, 0x3b, 0x36, 0x75, 0x45, 0xac, 0x05, 0xfd,
|
||||||
0x82, 0xba, 0x7c, 0x18, 0x9b, 0x51, 0x12, 0x13, 0x50, 0x74, 0x62, 0x8f, 0x2d, 0x1c, 0x5c, 0x66,
|
0x12, 0xef, 0xcb, 0x47, 0x89, 0x19, 0xa5, 0x31, 0xdc, 0xc5, 0x24, 0xee, 0xc0, 0xc1, 0x3c, 0x99,
|
||||||
0x98, 0x6e, 0x82, 0xb2, 0x17, 0x9b, 0x51, 0x12, 0x03, 0xef, 0x83, 0xab, 0x61, 0x05, 0x9b, 0xef,
|
0x91, 0xdc, 0xa4, 0xcb, 0x7e, 0x62, 0x46, 0x69, 0x0c, 0xbc, 0x0f, 0xae, 0x46, 0x1d, 0x6c, 0x76,
|
||||||
0x80, 0x05, 0xde, 0x01, 0xff, 0xef, 0x7b, 0xf2, 0xd5, 0xdd, 0x2c, 0x00, 0xca, 0xe6, 0xc1, 0x1d,
|
0x02, 0x2e, 0x89, 0x09, 0xf8, 0xff, 0x30, 0x50, 0xaf, 0xee, 0x65, 0x01, 0x50, 0xb6, 0x1f, 0xdc,
|
||||||
0xb0, 0x3a, 0xd0, 0xf4, 0x13, 0x32, 0x1c, 0x26, 0x2b, 0x76, 0xdd, 0xf7, 0xe4, 0x55, 0x35, 0x61,
|
0x05, 0x6b, 0x5d, 0xc3, 0x3c, 0x25, 0xbd, 0x5e, 0xba, 0x63, 0x57, 0xc2, 0x40, 0x5d, 0xd3, 0x53,
|
||||||
0x47, 0x29, 0x14, 0xfc, 0x02, 0x54, 0x28, 0xb6, 0xb0, 0xce, 0x88, 0x2b, 0x52, 0xec, 0xad, 0x0b,
|
0x76, 0x34, 0x85, 0x82, 0x5f, 0x80, 0x22, 0xc5, 0x0e, 0x36, 0x19, 0xf1, 0xa5, 0xc4, 0xde, 0xba,
|
||||||
0x46, 0x45, 0x1b, 0x60, 0xab, 0x27, 0xa8, 0xea, 0x2a, 0xef, 0xf4, 0xe2, 0x0b, 0x45, 0x92, 0xf0,
|
0x60, 0x55, 0x8c, 0x2e, 0x76, 0xda, 0xd2, 0x55, 0x5f, 0x13, 0x93, 0x5e, 0x7e, 0xa1, 0x98, 0x12,
|
||||||
0x5d, 0xb0, 0x6e, 0x6b, 0xce, 0x44, 0x8b, 0x90, 0x3c, 0xb7, 0x2a, 0x2a, 0xf4, 0x3d, 0x79, 0xfd,
|
0xbe, 0x0b, 0x36, 0x5c, 0xc3, 0x1b, 0x1a, 0x31, 0x52, 0x68, 0xab, 0xa8, 0xc3, 0x30, 0x50, 0x37,
|
||||||
0x20, 0xb5, 0x82, 0xe6, 0x90, 0xf0, 0x13, 0x50, 0x61, 0xb3, 0x36, 0xba, 0xc2, 0x5d, 0xcb, 0x6c,
|
0x0e, 0xa7, 0x4e, 0xd0, 0x0c, 0x12, 0x7e, 0x02, 0x8a, 0x6c, 0x32, 0x46, 0x57, 0x44, 0x68, 0x99,
|
||||||
0x14, 0x87, 0xc4, 0x48, 0x75, 0xd1, 0x28, 0x4b, 0xa2, 0x16, 0x1a, 0xc9, 0x04, 0x83, 0x07, 0x63,
|
0x83, 0xe2, 0x88, 0x58, 0x53, 0x53, 0x34, 0x56, 0x49, 0x3c, 0x42, 0x63, 0x1a, 0xbe, 0x78, 0x30,
|
||||||
0x96, 0xb8, 0xb1, 0xdd, 0x21, 0xc3, 0xee, 0x5d, 0xd3, 0x31, 0xe9, 0x31, 0x36, 0x1a, 0x15, 0x7e,
|
0xe6, 0xc8, 0x8c, 0xed, 0xf5, 0x18, 0xf6, 0xef, 0xda, 0x9e, 0x4d, 0x4f, 0xb0, 0x55, 0x2d, 0x8a,
|
||||||
0x5d, 0x7c, 0xf0, 0xe8, 0xf7, 0xbb, 0x59, 0x10, 0x94, 0xc7, 0x85, 0x5d, 0xb0, 0x1e, 0x87, 0xf6,
|
0x74, 0x89, 0xc5, 0xa3, 0xd3, 0x69, 0x65, 0x41, 0x50, 0x9e, 0x2f, 0x6c, 0x81, 0x8d, 0xa4, 0xb4,
|
||||||
0x80, 0x18, 0xb8, 0x51, 0xe5, 0x0f, 0xe3, 0x56, 0x70, 0xca, 0xbd, 0xd4, 0xca, 0xd9, 0x82, 0x05,
|
0x87, 0xc4, 0xc2, 0xd5, 0x92, 0x78, 0x18, 0xb7, 0xf8, 0xaf, 0xdc, 0x9f, 0x3a, 0x39, 0x9b, 0xb3,
|
||||||
0xcd, 0x71, 0x93, 0x83, 0x06, 0xc8, 0x1f, 0x34, 0xda, 0x7f, 0x15, 0x41, 0x35, 0xee, 0xa9, 0x47,
|
0xa0, 0x19, 0xdf, 0xf4, 0xa2, 0x01, 0xf2, 0x17, 0x8d, 0xc6, 0xf7, 0x05, 0x50, 0x4a, 0x66, 0xea,
|
||||||
0x00, 0xe8, 0xb3, 0xc2, 0x45, 0x45, 0x5f, 0xbd, 0x99, 0xf7, 0x08, 0xa2, 0x12, 0x17, 0xf7, 0x83,
|
0x31, 0x00, 0xe6, 0xa4, 0x71, 0x51, 0x39, 0x57, 0x6f, 0xe6, 0x3d, 0x82, 0xb8, 0xc5, 0x25, 0xf3,
|
||||||
0xc8, 0x44, 0x51, 0x42, 0x08, 0x7e, 0x0a, 0xaa, 0x7c, 0xda, 0xe2, 0x25, 0x68, 0xf9, 0x99, 0x4b,
|
0x20, 0x36, 0x51, 0x94, 0x22, 0x82, 0x9f, 0x82, 0x92, 0xd8, 0xb6, 0x44, 0x0b, 0x5a, 0x7c, 0xe6,
|
||||||
0xd0, 0x9a, 0xef, 0xc9, 0xd5, 0xde, 0x4c, 0x00, 0xc5, 0x5a, 0x70, 0x98, 0xbc, 0xb2, 0xe7, 0x2c,
|
0x16, 0xb4, 0x1e, 0x06, 0x6a, 0xa9, 0x3d, 0x21, 0x40, 0x09, 0x17, 0xec, 0xa5, 0x53, 0xf6, 0x9c,
|
||||||
0xa7, 0x30, 0x7d, 0xbd, 0x7c, 0x8b, 0x39, 0xd5, 0xa0, 0xa8, 0x89, 0x59, 0xa3, 0xc8, 0x03, 0x9c,
|
0xed, 0x14, 0x4e, 0xa7, 0x57, 0x5c, 0x31, 0xc3, 0xca, 0x9b, 0x9a, 0xdc, 0x35, 0x96, 0x45, 0x81,
|
||||||
0x37, 0x46, 0x74, 0x40, 0x95, 0xcf, 0x45, 0xd8, 0xc0, 0x06, 0xcf, 0xd1, 0x92, 0x7a, 0x59, 0x40,
|
0xf3, 0xd6, 0x88, 0x26, 0x28, 0x89, 0xbd, 0x08, 0x5b, 0xd8, 0x12, 0x1a, 0x2d, 0xe8, 0x97, 0x25,
|
||||||
0xab, 0xbd, 0xd9, 0x02, 0x8a, 0x31, 0x81, 0x70, 0x38, 0xf0, 0x88, 0xb1, 0x2b, 0x12, 0x0e, 0xc7,
|
0xb4, 0xd4, 0x9e, 0x1c, 0xa0, 0x04, 0xc3, 0x89, 0xa3, 0x85, 0x47, 0xae, 0x5d, 0x31, 0x71, 0xb4,
|
||||||
0x23, 0x24, 0x56, 0xe1, 0x1d, 0x50, 0x17, 0x2e, 0x61, 0xe3, 0x9e, 0x63, 0xe0, 0xaf, 0x31, 0xe5,
|
0x1e, 0x21, 0x79, 0x0a, 0xef, 0x80, 0x8a, 0x0c, 0x09, 0x5b, 0xf7, 0x3c, 0x0b, 0x7f, 0x8d, 0xa9,
|
||||||
0x4f, 0xb3, 0xaa, 0x36, 0x04, 0xa3, 0xbe, 0x37, 0xb7, 0x8e, 0x16, 0x18, 0xf0, 0x5b, 0x09, 0x5c,
|
0x78, 0x9a, 0x25, 0xbd, 0x2a, 0x3d, 0x2a, 0xfb, 0x33, 0xe7, 0x68, 0xce, 0x03, 0x7e, 0xab, 0x80,
|
||||||
0x9f, 0x38, 0x3a, 0x99, 0x38, 0x0c, 0x1b, 0x7d, 0xec, 0xda, 0xa6, 0x13, 0xfc, 0x79, 0x3a, 0x24,
|
0xeb, 0x43, 0xcf, 0x24, 0x43, 0x8f, 0x61, 0xab, 0x83, 0x7d, 0xd7, 0xf6, 0xf8, 0x3f, 0x4f, 0x47,
|
||||||
0x06, 0xe5, 0x99, 0x5b, 0xdb, 0xbe, 0x9d, 0x19, 0xec, 0xa3, 0x6c, 0x4e, 0x98, 0xe7, 0x39, 0x8b,
|
0xc4, 0xa2, 0x42, 0xb9, 0xe5, 0x9d, 0xdb, 0x99, 0xc5, 0x3e, 0xce, 0xf6, 0x89, 0x74, 0x9e, 0x73,
|
||||||
0x28, 0x6f, 0xa7, 0xf6, 0xcf, 0x12, 0xb8, 0x34, 0x37, 0xb4, 0xfe, 0xf7, 0xa7, 0x92, 0xf6, 0x2f,
|
0x88, 0xf2, 0x6e, 0x82, 0x2a, 0x28, 0xf8, 0xd8, 0xb0, 0xc6, 0x42, 0xde, 0x05, 0xbd, 0xc4, 0xdb,
|
||||||
0x12, 0xc8, 0x3b, 0x2a, 0x3c, 0x4c, 0x86, 0x3d, 0x78, 0x35, 0x55, 0x75, 0x3b, 0x15, 0xf2, 0x33,
|
0x28, 0xe2, 0x06, 0x14, 0xd9, 0x1b, 0xbf, 0x28, 0xe0, 0xd2, 0xcc, 0x56, 0xfb, 0xdf, 0x5f, 0x5b,
|
||||||
0x4f, 0xbe, 0x99, 0xf7, 0x97, 0x36, 0x18, 0x32, 0xa8, 0x72, 0x74, 0xef, 0x4e, 0x32, 0x2f, 0x3e,
|
0x1a, 0xbf, 0x2a, 0x20, 0x2f, 0x17, 0xf0, 0x28, 0xad, 0x0b, 0xfe, 0xac, 0x4a, 0xfa, 0xce, 0x94,
|
||||||
0x8c, 0xf2, 0x62, 0x99, 0xcb, 0x75, 0xe2, 0x9c, 0xb8, 0x98, 0x96, 0xa0, 0xab, 0x9b, 0x8f, 0x9e,
|
0x26, 0xce, 0x02, 0xf5, 0x66, 0xde, 0xff, 0xbc, 0x7c, 0x0b, 0xa1, 0xda, 0xf1, 0xbd, 0x3b, 0x69,
|
||||||
0xb6, 0x96, 0x1e, 0x3f, 0x6d, 0x2d, 0x3d, 0x79, 0xda, 0x5a, 0xfa, 0xc6, 0x6f, 0x49, 0x8f, 0xfc,
|
0xe1, 0x7c, 0x18, 0x0b, 0x67, 0x51, 0xd0, 0x35, 0x13, 0xd1, 0x5c, 0x8c, 0x4b, 0xba, 0xeb, 0x5b,
|
||||||
0x96, 0xf4, 0xd8, 0x6f, 0x49, 0x4f, 0xfc, 0x96, 0xf4, 0xbb, 0xdf, 0x92, 0xbe, 0xfb, 0xa3, 0xb5,
|
0x8f, 0x9e, 0xd6, 0x17, 0x1e, 0x3f, 0xad, 0x2f, 0x3c, 0x79, 0x5a, 0x5f, 0xf8, 0x26, 0xac, 0x2b,
|
||||||
0xf4, 0xd9, 0xf2, 0x74, 0xeb, 0x9f, 0x00, 0x00, 0x00, 0xff, 0xff, 0xa8, 0xfc, 0x0b, 0x48, 0x81,
|
0x8f, 0xc2, 0xba, 0xf2, 0x38, 0xac, 0x2b, 0x4f, 0xc2, 0xba, 0xf2, 0x47, 0x58, 0x57, 0xbe, 0xfb,
|
||||||
0x10, 0x00, 0x00,
|
0xb3, 0xbe, 0xf0, 0xd9, 0xe2, 0x68, 0xfb, 0x9f, 0x00, 0x00, 0x00, 0xff, 0xff, 0x54, 0x31, 0x16,
|
||||||
|
0xcf, 0xa2, 0x10, 0x00, 0x00,
|
||||||
}
|
}
|
||||||
|
|
||||||
func (m *CronJob) Marshal() (dAtA []byte, err error) {
|
func (m *CronJob) Marshal() (dAtA []byte, err error) {
|
||||||
@ -975,6 +976,11 @@ func (m *JobStatus) MarshalToSizedBuffer(dAtA []byte) (int, error) {
|
|||||||
_ = i
|
_ = i
|
||||||
var l int
|
var l int
|
||||||
_ = l
|
_ = l
|
||||||
|
if m.Ready != nil {
|
||||||
|
i = encodeVarintGenerated(dAtA, i, uint64(*m.Ready))
|
||||||
|
i--
|
||||||
|
dAtA[i] = 0x48
|
||||||
|
}
|
||||||
if m.UncountedTerminatedPods != nil {
|
if m.UncountedTerminatedPods != nil {
|
||||||
{
|
{
|
||||||
size, err := m.UncountedTerminatedPods.MarshalToSizedBuffer(dAtA[:i])
|
size, err := m.UncountedTerminatedPods.MarshalToSizedBuffer(dAtA[:i])
|
||||||
@ -1341,6 +1347,9 @@ func (m *JobStatus) Size() (n int) {
|
|||||||
l = m.UncountedTerminatedPods.Size()
|
l = m.UncountedTerminatedPods.Size()
|
||||||
n += 1 + l + sovGenerated(uint64(l))
|
n += 1 + l + sovGenerated(uint64(l))
|
||||||
}
|
}
|
||||||
|
if m.Ready != nil {
|
||||||
|
n += 1 + sovGenerated(uint64(*m.Ready))
|
||||||
|
}
|
||||||
return n
|
return n
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1525,6 +1534,7 @@ func (this *JobStatus) String() string {
|
|||||||
`Failed:` + fmt.Sprintf("%v", this.Failed) + `,`,
|
`Failed:` + fmt.Sprintf("%v", this.Failed) + `,`,
|
||||||
`CompletedIndexes:` + fmt.Sprintf("%v", this.CompletedIndexes) + `,`,
|
`CompletedIndexes:` + fmt.Sprintf("%v", this.CompletedIndexes) + `,`,
|
||||||
`UncountedTerminatedPods:` + strings.Replace(this.UncountedTerminatedPods.String(), "UncountedTerminatedPods", "UncountedTerminatedPods", 1) + `,`,
|
`UncountedTerminatedPods:` + strings.Replace(this.UncountedTerminatedPods.String(), "UncountedTerminatedPods", "UncountedTerminatedPods", 1) + `,`,
|
||||||
|
`Ready:` + valueToStringGenerated(this.Ready) + `,`,
|
||||||
`}`,
|
`}`,
|
||||||
}, "")
|
}, "")
|
||||||
return s
|
return s
|
||||||
@ -3273,6 +3283,26 @@ func (m *JobStatus) Unmarshal(dAtA []byte) error {
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
iNdEx = postIndex
|
iNdEx = postIndex
|
||||||
|
case 9:
|
||||||
|
if wireType != 0 {
|
||||||
|
return fmt.Errorf("proto: wrong wireType = %d for field Ready", wireType)
|
||||||
|
}
|
||||||
|
var v int32
|
||||||
|
for shift := uint(0); ; shift += 7 {
|
||||||
|
if shift >= 64 {
|
||||||
|
return ErrIntOverflowGenerated
|
||||||
|
}
|
||||||
|
if iNdEx >= l {
|
||||||
|
return io.ErrUnexpectedEOF
|
||||||
|
}
|
||||||
|
b := dAtA[iNdEx]
|
||||||
|
iNdEx++
|
||||||
|
v |= int32(b&0x7F) << shift
|
||||||
|
if b < 0x80 {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
m.Ready = &v
|
||||||
default:
|
default:
|
||||||
iNdEx = preIndex
|
iNdEx = preIndex
|
||||||
skippy, err := skipGenerated(dAtA[iNdEx:])
|
skippy, err := skipGenerated(dAtA[iNdEx:])
|
||||||
|
@ -298,7 +298,7 @@ message JobStatus {
|
|||||||
// +optional
|
// +optional
|
||||||
optional k8s.io.apimachinery.pkg.apis.meta.v1.Time completionTime = 3;
|
optional k8s.io.apimachinery.pkg.apis.meta.v1.Time completionTime = 3;
|
||||||
|
|
||||||
// The number of actively running pods.
|
// The number of pending and running pods.
|
||||||
// +optional
|
// +optional
|
||||||
optional int32 active = 4;
|
optional int32 active = 4;
|
||||||
|
|
||||||
@ -338,6 +338,13 @@ message JobStatus {
|
|||||||
// remains null.
|
// remains null.
|
||||||
// +optional
|
// +optional
|
||||||
optional UncountedTerminatedPods uncountedTerminatedPods = 8;
|
optional UncountedTerminatedPods uncountedTerminatedPods = 8;
|
||||||
|
|
||||||
|
// The number of pods which have a Ready condition.
|
||||||
|
//
|
||||||
|
// This field is alpha-level. The job controller populates the field when
|
||||||
|
// the feature gate JobReadyPods is enabled (disabled by default).
|
||||||
|
// +optional
|
||||||
|
optional int32 ready = 9;
|
||||||
}
|
}
|
||||||
|
|
||||||
// JobTemplateSpec describes the data a Job should have when created from a template
|
// JobTemplateSpec describes the data a Job should have when created from a template
|
||||||
|
@ -225,7 +225,7 @@ type JobStatus struct {
|
|||||||
// +optional
|
// +optional
|
||||||
CompletionTime *metav1.Time `json:"completionTime,omitempty" protobuf:"bytes,3,opt,name=completionTime"`
|
CompletionTime *metav1.Time `json:"completionTime,omitempty" protobuf:"bytes,3,opt,name=completionTime"`
|
||||||
|
|
||||||
// The number of actively running pods.
|
// The number of pending and running pods.
|
||||||
// +optional
|
// +optional
|
||||||
Active int32 `json:"active,omitempty" protobuf:"varint,4,opt,name=active"`
|
Active int32 `json:"active,omitempty" protobuf:"varint,4,opt,name=active"`
|
||||||
|
|
||||||
@ -265,6 +265,13 @@ type JobStatus struct {
|
|||||||
// remains null.
|
// remains null.
|
||||||
// +optional
|
// +optional
|
||||||
UncountedTerminatedPods *UncountedTerminatedPods `json:"uncountedTerminatedPods,omitempty" protobuf:"bytes,8,opt,name=uncountedTerminatedPods"`
|
UncountedTerminatedPods *UncountedTerminatedPods `json:"uncountedTerminatedPods,omitempty" protobuf:"bytes,8,opt,name=uncountedTerminatedPods"`
|
||||||
|
|
||||||
|
// The number of pods which have a Ready condition.
|
||||||
|
//
|
||||||
|
// This field is alpha-level. The job controller populates the field when
|
||||||
|
// the feature gate JobReadyPods is enabled (disabled by default).
|
||||||
|
// +optional
|
||||||
|
Ready *int32 `json:"ready,omitempty" protobuf:"varint,9,opt,name=ready"`
|
||||||
}
|
}
|
||||||
|
|
||||||
// UncountedTerminatedPods holds UIDs of Pods that have terminated but haven't
|
// UncountedTerminatedPods holds UIDs of Pods that have terminated but haven't
|
||||||
|
@ -132,11 +132,12 @@ var map_JobStatus = map[string]string{
|
|||||||
"conditions": "The latest available observations of an object's current state. When a Job fails, one of the conditions will have type \"Failed\" and status true. When a Job is suspended, one of the conditions will have type \"Suspended\" and status true; when the Job is resumed, the status of this condition will become false. When a Job is completed, one of the conditions will have type \"Complete\" and status true. More info: https://kubernetes.io/docs/concepts/workloads/controllers/jobs-run-to-completion/",
|
"conditions": "The latest available observations of an object's current state. When a Job fails, one of the conditions will have type \"Failed\" and status true. When a Job is suspended, one of the conditions will have type \"Suspended\" and status true; when the Job is resumed, the status of this condition will become false. When a Job is completed, one of the conditions will have type \"Complete\" and status true. More info: https://kubernetes.io/docs/concepts/workloads/controllers/jobs-run-to-completion/",
|
||||||
"startTime": "Represents time when the job controller started processing a job. When a Job is created in the suspended state, this field is not set until the first time it is resumed. This field is reset every time a Job is resumed from suspension. It is represented in RFC3339 form and is in UTC.",
|
"startTime": "Represents time when the job controller started processing a job. When a Job is created in the suspended state, this field is not set until the first time it is resumed. This field is reset every time a Job is resumed from suspension. It is represented in RFC3339 form and is in UTC.",
|
||||||
"completionTime": "Represents time when the job was completed. It is not guaranteed to be set in happens-before order across separate operations. It is represented in RFC3339 form and is in UTC. The completion time is only set when the job finishes successfully.",
|
"completionTime": "Represents time when the job was completed. It is not guaranteed to be set in happens-before order across separate operations. It is represented in RFC3339 form and is in UTC. The completion time is only set when the job finishes successfully.",
|
||||||
"active": "The number of actively running pods.",
|
"active": "The number of pending and running pods.",
|
||||||
"succeeded": "The number of pods which reached phase Succeeded.",
|
"succeeded": "The number of pods which reached phase Succeeded.",
|
||||||
"failed": "The number of pods which reached phase Failed.",
|
"failed": "The number of pods which reached phase Failed.",
|
||||||
"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\".",
|
"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\".",
|
||||||
"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: (1) 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\nThis field is beta-level. The job controller only makes use of this field when the feature gate JobTrackingWithFinalizers is enabled (enabled by default). Old jobs might not be tracked using this field, in which case the field remains null.",
|
"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: (1) 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\nThis field is beta-level. The job controller only makes use of this field when the feature gate JobTrackingWithFinalizers is enabled (enabled by default). Old jobs might not be tracked using this field, in which case the field remains null.",
|
||||||
|
"ready": "The number of pods which have a Ready condition.\n\nThis field is alpha-level. The job controller populates the field when the feature gate JobReadyPods is enabled (disabled by default).",
|
||||||
}
|
}
|
||||||
|
|
||||||
func (JobStatus) SwaggerDoc() map[string]string {
|
func (JobStatus) SwaggerDoc() map[string]string {
|
||||||
|
@ -319,6 +319,11 @@ func (in *JobStatus) DeepCopyInto(out *JobStatus) {
|
|||||||
*out = new(UncountedTerminatedPods)
|
*out = new(UncountedTerminatedPods)
|
||||||
(*in).DeepCopyInto(*out)
|
(*in).DeepCopyInto(*out)
|
||||||
}
|
}
|
||||||
|
if in.Ready != nil {
|
||||||
|
in, out := &in.Ready, &out.Ready
|
||||||
|
*out = new(int32)
|
||||||
|
**out = **in
|
||||||
|
}
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1573,6 +1573,7 @@
|
|||||||
"failed": [
|
"failed": [
|
||||||
"W"
|
"W"
|
||||||
]
|
]
|
||||||
}
|
},
|
||||||
|
"ready": -1917014749
|
||||||
}
|
}
|
||||||
}
|
}
|
BIN
staging/src/k8s.io/api/testdata/HEAD/batch.v1.Job.pb
vendored
BIN
staging/src/k8s.io/api/testdata/HEAD/batch.v1.Job.pb
vendored
Binary file not shown.
@ -1071,6 +1071,7 @@ status:
|
|||||||
status: 翻颌徚J殦殐ƕ蟶ŃēÖ釐駆Ŕƿe魛ĩ
|
status: 翻颌徚J殦殐ƕ蟶ŃēÖ釐駆Ŕƿe魛ĩ
|
||||||
type: ɓ为\Ŧƺ猑\#ȼ縤ɰTaI楅©
|
type: ɓ为\Ŧƺ猑\#ȼ縤ɰTaI楅©
|
||||||
failed: 77405208
|
failed: 77405208
|
||||||
|
ready: -1917014749
|
||||||
succeeded: -377965530
|
succeeded: -377965530
|
||||||
uncountedTerminatedPods:
|
uncountedTerminatedPods:
|
||||||
failed:
|
failed:
|
||||||
|
@ -33,6 +33,7 @@ type JobStatusApplyConfiguration struct {
|
|||||||
Failed *int32 `json:"failed,omitempty"`
|
Failed *int32 `json:"failed,omitempty"`
|
||||||
CompletedIndexes *string `json:"completedIndexes,omitempty"`
|
CompletedIndexes *string `json:"completedIndexes,omitempty"`
|
||||||
UncountedTerminatedPods *UncountedTerminatedPodsApplyConfiguration `json:"uncountedTerminatedPods,omitempty"`
|
UncountedTerminatedPods *UncountedTerminatedPodsApplyConfiguration `json:"uncountedTerminatedPods,omitempty"`
|
||||||
|
Ready *int32 `json:"ready,omitempty"`
|
||||||
}
|
}
|
||||||
|
|
||||||
// JobStatusApplyConfiguration constructs an declarative configuration of the JobStatus type for use with
|
// JobStatusApplyConfiguration constructs an declarative configuration of the JobStatus type for use with
|
||||||
@ -109,3 +110,11 @@ func (b *JobStatusApplyConfiguration) WithUncountedTerminatedPods(value *Uncount
|
|||||||
b.UncountedTerminatedPods = value
|
b.UncountedTerminatedPods = value
|
||||||
return b
|
return b
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// WithReady sets the Ready field in the declarative configuration to the given value
|
||||||
|
// and returns the receiver, so that objects can be built by chaining "With" function invocations.
|
||||||
|
// If called multiple times, the Ready field is set to the value of the last call.
|
||||||
|
func (b *JobStatusApplyConfiguration) WithReady(value int32) *JobStatusApplyConfiguration {
|
||||||
|
b.Ready = &value
|
||||||
|
return b
|
||||||
|
}
|
||||||
|
@ -2671,6 +2671,9 @@ var schemaYAML = typed.YAMLObject(`types:
|
|||||||
- name: failed
|
- name: failed
|
||||||
type:
|
type:
|
||||||
scalar: numeric
|
scalar: numeric
|
||||||
|
- name: ready
|
||||||
|
type:
|
||||||
|
scalar: numeric
|
||||||
- name: startTime
|
- name: startTime
|
||||||
type:
|
type:
|
||||||
namedType: io.k8s.apimachinery.pkg.apis.meta.v1.Time
|
namedType: io.k8s.apimachinery.pkg.apis.meta.v1.Time
|
||||||
|
@ -2216,7 +2216,11 @@ func describeJob(job *batchv1.Job, events *corev1.EventList) (string, error) {
|
|||||||
if job.Spec.ActiveDeadlineSeconds != nil {
|
if job.Spec.ActiveDeadlineSeconds != nil {
|
||||||
w.Write(LEVEL_0, "Active Deadline Seconds:\t%ds\n", *job.Spec.ActiveDeadlineSeconds)
|
w.Write(LEVEL_0, "Active Deadline Seconds:\t%ds\n", *job.Spec.ActiveDeadlineSeconds)
|
||||||
}
|
}
|
||||||
w.Write(LEVEL_0, "Pods Statuses:\t%d Running / %d Succeeded / %d Failed\n", job.Status.Active, job.Status.Succeeded, job.Status.Failed)
|
if job.Status.Ready == nil {
|
||||||
|
w.Write(LEVEL_0, "Pods Statuses:\t%d Active / %d Succeeded / %d Failed\n", job.Status.Active, job.Status.Succeeded, job.Status.Failed)
|
||||||
|
} else {
|
||||||
|
w.Write(LEVEL_0, "Pods Statuses:\t%d Active (%d Ready) / %d Succeeded / %d Failed\n", job.Status.Active, *job.Status.Ready, job.Status.Succeeded, job.Status.Failed)
|
||||||
|
}
|
||||||
if job.Spec.CompletionMode != nil && *job.Spec.CompletionMode == batchv1.IndexedCompletion {
|
if job.Spec.CompletionMode != nil && *job.Spec.CompletionMode == batchv1.IndexedCompletion {
|
||||||
w.Write(LEVEL_0, "Completed Indexes:\t%s\n", capIndexesListOrNone(job.Status.CompletedIndexes, 50))
|
w.Write(LEVEL_0, "Completed Indexes:\t%s\n", capIndexesListOrNone(job.Status.CompletedIndexes, 50))
|
||||||
}
|
}
|
||||||
|
@ -42,6 +42,7 @@ import (
|
|||||||
restclient "k8s.io/client-go/rest"
|
restclient "k8s.io/client-go/rest"
|
||||||
"k8s.io/client-go/util/retry"
|
"k8s.io/client-go/util/retry"
|
||||||
featuregatetesting "k8s.io/component-base/featuregate/testing"
|
featuregatetesting "k8s.io/component-base/featuregate/testing"
|
||||||
|
podutil "k8s.io/kubernetes/pkg/api/v1/pod"
|
||||||
jobcontroller "k8s.io/kubernetes/pkg/controller/job"
|
jobcontroller "k8s.io/kubernetes/pkg/controller/job"
|
||||||
"k8s.io/kubernetes/pkg/features"
|
"k8s.io/kubernetes/pkg/features"
|
||||||
"k8s.io/kubernetes/test/integration/framework"
|
"k8s.io/kubernetes/test/integration/framework"
|
||||||
@ -108,9 +109,26 @@ func TestNonParallelJob(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func TestParallelJob(t *testing.T) {
|
func TestParallelJob(t *testing.T) {
|
||||||
for _, wFinalizers := range []bool{false, true} {
|
cases := map[string]struct {
|
||||||
t.Run(fmt.Sprintf("finalizers=%t", wFinalizers), func(t *testing.T) {
|
trackWithFinalizers bool
|
||||||
defer featuregatetesting.SetFeatureGateDuringTest(t, feature.DefaultFeatureGate, features.JobTrackingWithFinalizers, wFinalizers)()
|
enableReadyPods bool
|
||||||
|
}{
|
||||||
|
"none": {},
|
||||||
|
"with finalizers": {
|
||||||
|
trackWithFinalizers: true,
|
||||||
|
},
|
||||||
|
"ready pods": {
|
||||||
|
enableReadyPods: true,
|
||||||
|
},
|
||||||
|
"all": {
|
||||||
|
trackWithFinalizers: true,
|
||||||
|
enableReadyPods: true,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
for name, tc := range cases {
|
||||||
|
t.Run(name, func(t *testing.T) {
|
||||||
|
defer featuregatetesting.SetFeatureGateDuringTest(t, feature.DefaultFeatureGate, features.JobTrackingWithFinalizers, tc.trackWithFinalizers)()
|
||||||
|
defer featuregatetesting.SetFeatureGateDuringTest(t, feature.DefaultFeatureGate, features.JobReadyPods, tc.enableReadyPods)()
|
||||||
|
|
||||||
closeFn, restConfig, clientSet, ns := setup(t, "parallel")
|
closeFn, restConfig, clientSet, ns := setup(t, "parallel")
|
||||||
defer closeFn()
|
defer closeFn()
|
||||||
@ -125,43 +143,71 @@ func TestParallelJob(t *testing.T) {
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("Failed to create Job: %v", err)
|
t.Fatalf("Failed to create Job: %v", err)
|
||||||
}
|
}
|
||||||
validateJobPodsStatus(ctx, t, clientSet, jobObj, podsByStatus{
|
want := podsByStatus{Active: 5}
|
||||||
Active: 5,
|
if tc.enableReadyPods {
|
||||||
}, wFinalizers)
|
want.Ready = pointer.Int32Ptr(0)
|
||||||
|
}
|
||||||
|
validateJobPodsStatus(ctx, t, clientSet, jobObj, want, tc.trackWithFinalizers)
|
||||||
|
|
||||||
|
// Tracks ready pods, if enabled.
|
||||||
|
if err := setJobPodsReady(ctx, clientSet, jobObj, 2); err != nil {
|
||||||
|
t.Fatalf("Failed Marking Pods as ready: %v", err)
|
||||||
|
}
|
||||||
|
if tc.enableReadyPods {
|
||||||
|
*want.Ready = 2
|
||||||
|
}
|
||||||
|
validateJobPodsStatus(ctx, t, clientSet, jobObj, want, tc.trackWithFinalizers)
|
||||||
|
|
||||||
// Failed Pods are replaced.
|
// Failed Pods are replaced.
|
||||||
if err := setJobPodsPhase(ctx, clientSet, jobObj, v1.PodFailed, 2); err != nil {
|
if err := setJobPodsPhase(ctx, clientSet, jobObj, v1.PodFailed, 2); err != nil {
|
||||||
t.Fatalf("Failed setting phase %s on Job Pods: %v", v1.PodFailed, err)
|
t.Fatalf("Failed setting phase %s on Job Pods: %v", v1.PodFailed, err)
|
||||||
}
|
}
|
||||||
validateJobPodsStatus(ctx, t, clientSet, jobObj, podsByStatus{
|
want = podsByStatus{
|
||||||
Active: 5,
|
Active: 5,
|
||||||
Failed: 2,
|
Failed: 2,
|
||||||
}, wFinalizers)
|
}
|
||||||
|
if tc.enableReadyPods {
|
||||||
|
want.Ready = pointer.Int32(0)
|
||||||
|
}
|
||||||
|
validateJobPodsStatus(ctx, t, clientSet, jobObj, want, tc.trackWithFinalizers)
|
||||||
// Once one Pod succeeds, no more Pods are created, even if some fail.
|
// Once one Pod succeeds, no more Pods are created, even if some fail.
|
||||||
if err := setJobPodsPhase(ctx, clientSet, jobObj, v1.PodSucceeded, 1); err != nil {
|
if err := setJobPodsPhase(ctx, clientSet, jobObj, v1.PodSucceeded, 1); err != nil {
|
||||||
t.Fatalf("Failed setting phase %s on Job Pod: %v", v1.PodSucceeded, err)
|
t.Fatalf("Failed setting phase %s on Job Pod: %v", v1.PodSucceeded, err)
|
||||||
}
|
}
|
||||||
validateJobPodsStatus(ctx, t, clientSet, jobObj, podsByStatus{
|
want = podsByStatus{
|
||||||
Failed: 2,
|
Failed: 2,
|
||||||
Succeeded: 1,
|
Succeeded: 1,
|
||||||
Active: 4,
|
Active: 4,
|
||||||
}, wFinalizers)
|
}
|
||||||
|
if tc.enableReadyPods {
|
||||||
|
want.Ready = pointer.Int32(0)
|
||||||
|
}
|
||||||
|
validateJobPodsStatus(ctx, t, clientSet, jobObj, want, tc.trackWithFinalizers)
|
||||||
if err := setJobPodsPhase(ctx, clientSet, jobObj, v1.PodFailed, 2); err != nil {
|
if err := setJobPodsPhase(ctx, clientSet, jobObj, v1.PodFailed, 2); err != nil {
|
||||||
t.Fatalf("Failed setting phase %s on Job Pods: %v", v1.PodFailed, err)
|
t.Fatalf("Failed setting phase %s on Job Pods: %v", v1.PodFailed, err)
|
||||||
}
|
}
|
||||||
validateJobPodsStatus(ctx, t, clientSet, jobObj, podsByStatus{
|
want = podsByStatus{
|
||||||
Failed: 4,
|
Failed: 4,
|
||||||
Succeeded: 1,
|
Succeeded: 1,
|
||||||
Active: 2,
|
Active: 2,
|
||||||
}, wFinalizers)
|
}
|
||||||
|
if tc.enableReadyPods {
|
||||||
|
want.Ready = pointer.Int32(0)
|
||||||
|
}
|
||||||
|
validateJobPodsStatus(ctx, t, clientSet, jobObj, want, tc.trackWithFinalizers)
|
||||||
// No more Pods are created after remaining Pods succeed.
|
// No more Pods are created after remaining Pods succeed.
|
||||||
if err := setJobPodsPhase(ctx, clientSet, jobObj, v1.PodSucceeded, 2); err != nil {
|
if err := setJobPodsPhase(ctx, clientSet, jobObj, v1.PodSucceeded, 2); err != nil {
|
||||||
t.Fatalf("Failed setting phase %s on Job Pods: %v", v1.PodSucceeded, err)
|
t.Fatalf("Failed setting phase %s on Job Pods: %v", v1.PodSucceeded, err)
|
||||||
}
|
}
|
||||||
validateJobSucceeded(ctx, t, clientSet, jobObj)
|
validateJobSucceeded(ctx, t, clientSet, jobObj)
|
||||||
validateJobPodsStatus(ctx, t, clientSet, jobObj, podsByStatus{
|
want = podsByStatus{
|
||||||
Failed: 4,
|
Failed: 4,
|
||||||
Succeeded: 3,
|
Succeeded: 3,
|
||||||
}, false)
|
}
|
||||||
|
if tc.enableReadyPods {
|
||||||
|
want.Ready = pointer.Int32(0)
|
||||||
|
}
|
||||||
|
validateJobPodsStatus(ctx, t, clientSet, jobObj, want, false)
|
||||||
validateFinishedPodsNoFinalizer(ctx, t, clientSet, jobObj)
|
validateFinishedPodsNoFinalizer(ctx, t, clientSet, jobObj)
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
@ -228,9 +274,26 @@ func TestParallelJobWithCompletions(t *testing.T) {
|
|||||||
// number of pods.
|
// number of pods.
|
||||||
t.Cleanup(setDuringTest(&jobcontroller.MaxUncountedPods, 10))
|
t.Cleanup(setDuringTest(&jobcontroller.MaxUncountedPods, 10))
|
||||||
t.Cleanup(setDuringTest(&jobcontroller.MaxPodCreateDeletePerSync, 10))
|
t.Cleanup(setDuringTest(&jobcontroller.MaxPodCreateDeletePerSync, 10))
|
||||||
for _, wFinalizers := range []bool{false, true} {
|
cases := map[string]struct {
|
||||||
t.Run(fmt.Sprintf("finalizers=%t", wFinalizers), func(t *testing.T) {
|
trackWithFinalizers bool
|
||||||
defer featuregatetesting.SetFeatureGateDuringTest(t, feature.DefaultFeatureGate, features.JobTrackingWithFinalizers, wFinalizers)()
|
enableReadyPods bool
|
||||||
|
}{
|
||||||
|
"none": {},
|
||||||
|
"with finalizers": {
|
||||||
|
trackWithFinalizers: true,
|
||||||
|
},
|
||||||
|
"ready pods": {
|
||||||
|
enableReadyPods: true,
|
||||||
|
},
|
||||||
|
"all": {
|
||||||
|
trackWithFinalizers: true,
|
||||||
|
enableReadyPods: true,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
for name, tc := range cases {
|
||||||
|
t.Run(name, func(t *testing.T) {
|
||||||
|
defer featuregatetesting.SetFeatureGateDuringTest(t, feature.DefaultFeatureGate, features.JobTrackingWithFinalizers, tc.trackWithFinalizers)()
|
||||||
|
defer featuregatetesting.SetFeatureGateDuringTest(t, feature.DefaultFeatureGate, features.JobReadyPods, tc.enableReadyPods)()
|
||||||
closeFn, restConfig, clientSet, ns := setup(t, "completions")
|
closeFn, restConfig, clientSet, ns := setup(t, "completions")
|
||||||
defer closeFn()
|
defer closeFn()
|
||||||
ctx, cancel := startJobController(restConfig, clientSet)
|
ctx, cancel := startJobController(restConfig, clientSet)
|
||||||
@ -245,38 +308,62 @@ func TestParallelJobWithCompletions(t *testing.T) {
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("Failed to create Job: %v", err)
|
t.Fatalf("Failed to create Job: %v", err)
|
||||||
}
|
}
|
||||||
if got := hasJobTrackingAnnotation(jobObj); got != wFinalizers {
|
if got := hasJobTrackingAnnotation(jobObj); got != tc.trackWithFinalizers {
|
||||||
t.Errorf("apiserver created job with tracking annotation: %t, want %t", got, wFinalizers)
|
t.Errorf("apiserver created job with tracking annotation: %t, want %t", got, tc.trackWithFinalizers)
|
||||||
}
|
}
|
||||||
validateJobPodsStatus(ctx, t, clientSet, jobObj, podsByStatus{
|
want := podsByStatus{Active: 54}
|
||||||
Active: 54,
|
if tc.enableReadyPods {
|
||||||
}, wFinalizers)
|
want.Ready = pointer.Int32Ptr(0)
|
||||||
|
}
|
||||||
|
validateJobPodsStatus(ctx, t, clientSet, jobObj, want, tc.trackWithFinalizers)
|
||||||
|
|
||||||
|
// Tracks ready pods, if enabled.
|
||||||
|
if err := setJobPodsReady(ctx, clientSet, jobObj, 52); err != nil {
|
||||||
|
t.Fatalf("Failed Marking Pods as ready: %v", err)
|
||||||
|
}
|
||||||
|
if tc.enableReadyPods {
|
||||||
|
want.Ready = pointer.Int32(52)
|
||||||
|
}
|
||||||
|
validateJobPodsStatus(ctx, t, clientSet, jobObj, want, tc.trackWithFinalizers)
|
||||||
|
|
||||||
// Failed Pods are replaced.
|
// Failed Pods are replaced.
|
||||||
if err := setJobPodsPhase(ctx, clientSet, jobObj, v1.PodFailed, 2); err != nil {
|
if err := setJobPodsPhase(ctx, clientSet, jobObj, v1.PodFailed, 2); err != nil {
|
||||||
t.Fatalf("Failed setting phase %s on Job Pods: %v", v1.PodFailed, err)
|
t.Fatalf("Failed setting phase %s on Job Pods: %v", v1.PodFailed, err)
|
||||||
}
|
}
|
||||||
validateJobPodsStatus(ctx, t, clientSet, jobObj, podsByStatus{
|
want = podsByStatus{
|
||||||
Active: 54,
|
Active: 54,
|
||||||
Failed: 2,
|
Failed: 2,
|
||||||
}, wFinalizers)
|
}
|
||||||
|
if tc.enableReadyPods {
|
||||||
|
want.Ready = pointer.Int32(50)
|
||||||
|
}
|
||||||
|
validateJobPodsStatus(ctx, t, clientSet, jobObj, want, tc.trackWithFinalizers)
|
||||||
// Pods are created until the number of succeeded Pods equals completions.
|
// Pods are created until the number of succeeded Pods equals completions.
|
||||||
if err := setJobPodsPhase(ctx, clientSet, jobObj, v1.PodSucceeded, 53); err != nil {
|
if err := setJobPodsPhase(ctx, clientSet, jobObj, v1.PodSucceeded, 53); err != nil {
|
||||||
t.Fatalf("Failed setting phase %s on Job Pod: %v", v1.PodSucceeded, err)
|
t.Fatalf("Failed setting phase %s on Job Pod: %v", v1.PodSucceeded, err)
|
||||||
}
|
}
|
||||||
validateJobPodsStatus(ctx, t, clientSet, jobObj, podsByStatus{
|
want = podsByStatus{
|
||||||
Failed: 2,
|
Failed: 2,
|
||||||
Succeeded: 53,
|
Succeeded: 53,
|
||||||
Active: 3,
|
Active: 3,
|
||||||
}, wFinalizers)
|
}
|
||||||
|
if tc.enableReadyPods {
|
||||||
|
want.Ready = pointer.Int32(0)
|
||||||
|
}
|
||||||
|
validateJobPodsStatus(ctx, t, clientSet, jobObj, want, tc.trackWithFinalizers)
|
||||||
// No more Pods are created after the Job completes.
|
// No more Pods are created after the Job completes.
|
||||||
if err := setJobPodsPhase(ctx, clientSet, jobObj, v1.PodSucceeded, 3); err != nil {
|
if err := setJobPodsPhase(ctx, clientSet, jobObj, v1.PodSucceeded, 3); err != nil {
|
||||||
t.Fatalf("Failed setting phase %s on Job Pods: %v", v1.PodSucceeded, err)
|
t.Fatalf("Failed setting phase %s on Job Pods: %v", v1.PodSucceeded, err)
|
||||||
}
|
}
|
||||||
validateJobSucceeded(ctx, t, clientSet, jobObj)
|
validateJobSucceeded(ctx, t, clientSet, jobObj)
|
||||||
validateJobPodsStatus(ctx, t, clientSet, jobObj, podsByStatus{
|
want = podsByStatus{
|
||||||
Failed: 2,
|
Failed: 2,
|
||||||
Succeeded: 56,
|
Succeeded: 56,
|
||||||
}, false)
|
}
|
||||||
|
if tc.enableReadyPods {
|
||||||
|
want.Ready = pointer.Int32(0)
|
||||||
|
}
|
||||||
|
validateJobPodsStatus(ctx, t, clientSet, jobObj, want, false)
|
||||||
validateFinishedPodsNoFinalizer(ctx, t, clientSet, jobObj)
|
validateFinishedPodsNoFinalizer(ctx, t, clientSet, jobObj)
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
@ -709,6 +796,7 @@ func TestNodeSelectorUpdate(t *testing.T) {
|
|||||||
|
|
||||||
type podsByStatus struct {
|
type podsByStatus struct {
|
||||||
Active int
|
Active int
|
||||||
|
Ready *int32
|
||||||
Failed int
|
Failed int
|
||||||
Succeeded int
|
Succeeded int
|
||||||
}
|
}
|
||||||
@ -723,6 +811,7 @@ func validateJobPodsStatus(ctx context.Context, t *testing.T, clientSet clientse
|
|||||||
}
|
}
|
||||||
actualCounts = podsByStatus{
|
actualCounts = podsByStatus{
|
||||||
Active: int(updatedJob.Status.Active),
|
Active: int(updatedJob.Status.Active),
|
||||||
|
Ready: updatedJob.Status.Ready,
|
||||||
Succeeded: int(updatedJob.Status.Succeeded),
|
Succeeded: int(updatedJob.Status.Succeeded),
|
||||||
Failed: int(updatedJob.Status.Failed),
|
Failed: int(updatedJob.Status.Failed),
|
||||||
}
|
}
|
||||||
@ -860,6 +949,28 @@ func validateJobSucceeded(ctx context.Context, t *testing.T, clientSet clientset
|
|||||||
}
|
}
|
||||||
|
|
||||||
func setJobPodsPhase(ctx context.Context, clientSet clientset.Interface, jobObj *batchv1.Job, phase v1.PodPhase, cnt int) error {
|
func setJobPodsPhase(ctx context.Context, clientSet clientset.Interface, jobObj *batchv1.Job, phase v1.PodPhase, cnt int) error {
|
||||||
|
op := func(p *v1.Pod) bool {
|
||||||
|
p.Status.Phase = phase
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
return updateJobPodsStatus(ctx, clientSet, jobObj, op, cnt)
|
||||||
|
}
|
||||||
|
|
||||||
|
func setJobPodsReady(ctx context.Context, clientSet clientset.Interface, jobObj *batchv1.Job, cnt int) error {
|
||||||
|
op := func(p *v1.Pod) bool {
|
||||||
|
if podutil.IsPodReady(p) {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
p.Status.Conditions = append(p.Status.Conditions, v1.PodCondition{
|
||||||
|
Type: v1.PodReady,
|
||||||
|
Status: v1.ConditionTrue,
|
||||||
|
})
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
return updateJobPodsStatus(ctx, clientSet, jobObj, op, cnt)
|
||||||
|
}
|
||||||
|
|
||||||
|
func updateJobPodsStatus(ctx context.Context, clientSet clientset.Interface, jobObj *batchv1.Job, op func(*v1.Pod) bool, cnt int) error {
|
||||||
pods, err := clientSet.CoreV1().Pods(jobObj.Namespace).List(ctx, metav1.ListOptions{})
|
pods, err := clientSet.CoreV1().Pods(jobObj.Namespace).List(ctx, metav1.ListOptions{})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("listing Job Pods: %w", err)
|
return fmt.Errorf("listing Job Pods: %w", err)
|
||||||
@ -870,7 +981,9 @@ func setJobPodsPhase(ctx context.Context, clientSet clientset.Interface, jobObj
|
|||||||
break
|
break
|
||||||
}
|
}
|
||||||
if p := pod.Status.Phase; isPodOwnedByJob(&pod, jobObj) && p != v1.PodFailed && p != v1.PodSucceeded {
|
if p := pod.Status.Phase; isPodOwnedByJob(&pod, jobObj) && p != v1.PodFailed && p != v1.PodSucceeded {
|
||||||
pod.Status.Phase = phase
|
if !op(&pod) {
|
||||||
|
continue
|
||||||
|
}
|
||||||
updates = append(updates, pod)
|
updates = append(updates, pod)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user