@@ -4050,11 +4050,11 @@ func TestNodeSelectorUpdate(t *testing.T) {
4050
4050
4051
4051
}
4052
4052
4053
- // TestDelayedJobSucceededUpdateEvent tests that a Job only creates one Pod even when
4054
- // the job success events are delayed. This test verfies the finishedJobStore is working
4053
+ // TestDelayedJobUpdateEvent tests that a Job only creates one Pod even when
4054
+ // the job events are delayed. This test verfies the finishedJobStore is working
4055
4055
// correctly and preventing from job controller creating a new pod if the job success
4056
- // even is delayed.
4057
- func TestDelayedJobSucceededUpdateEvent (t * testing.T ) {
4056
+ // or fail event is delayed.
4057
+ func TestDelayedJobUpdateEvent (t * testing.T ) {
4058
4058
t .Cleanup (setDurationDuringTest (& jobcontroller .DefaultJobPodFailureBackOff , fastPodFailureBackoff ))
4059
4059
t .Cleanup (setDurationDuringTest (& jobcontroller .SyncJobBatchPeriod , fastSyncJobBatchPeriod ))
4060
4060
closeFn , restConfig , clientSet , ns := setup (t , "simple" )
@@ -4070,135 +4070,123 @@ func TestDelayedJobSucceededUpdateEvent(t *testing.T) {
4070
4070
}
4071
4071
return obj , nil
4072
4072
}))
4073
- ctx , cancel := startJobControllerAndWaitForCaches (t , restConfig , transformOpt )
4074
- t .Cleanup (func () {
4075
- cancel ()
4076
- })
4077
- resetMetrics ()
4078
4073
4079
- jobObj , err := createJobWithDefaults (ctx , clientSet , ns .Name , & batchv1.Job {})
4080
- if err != nil {
4081
- t .Fatalf ("Failed to create Job: %v" , err )
4082
- }
4083
- validateJobPodsStatus (ctx , t , clientSet , jobObj , podsByStatus {
4084
- Active : 1 ,
4085
- Ready : ptr.To [int32 ](0 ),
4086
- Terminating : ptr.To [int32 ](0 ),
4087
- })
4088
-
4089
- if _ , err := setJobPodsPhase (ctx , clientSet , jobObj , v1 .PodSucceeded , 1 ); err != nil {
4090
- t .Fatalf ("Failed setting phase %s on Job Pod: %v" , v1 .PodSucceeded , err )
4091
- }
4092
- validateJobComplete (ctx , t , clientSet , jobObj )
4093
- validateJobsPodsStatusOnly (ctx , t , clientSet , jobObj , podsByStatus {
4094
- Failed : 0 ,
4095
- Succeeded : 1 ,
4096
- Ready : ptr.To [int32 ](0 ),
4097
- Terminating : ptr.To [int32 ](0 ),
4098
- })
4099
- validateCounterMetric (ctx , t , metrics .JobFinishedNum , metricLabelsWithValue {
4100
- Labels : []string {"NonIndexed" , "succeeded" , "CompletionsReached" },
4101
- Value : 1 ,
4102
- })
4103
- validateCounterMetric (ctx , t , metrics .JobPodsFinished , metricLabelsWithValue {
4104
- Labels : []string {"NonIndexed" , "succeeded" },
4105
- Value : 1 ,
4106
- })
4107
- jobPods , err := getJobPods (ctx , t , clientSet , jobObj , func (ps v1.PodStatus ) bool { return true })
4108
- if err != nil {
4109
- t .Fatalf ("Error %v getting the list of pods for job %q" , err , klog .KObj (jobObj ))
4110
- }
4111
- if len (jobPods ) != 1 {
4112
- t .Errorf ("Found %d Pods for the job %q, want 1" , len (jobPods ), klog .KObj (jobObj ))
4074
+ type jobStatus struct {
4075
+ succeeded int
4076
+ failed int
4077
+ status batchv1.JobConditionType
4113
4078
}
4114
- }
4115
-
4116
- // TestDelayedJobFailedUpdateEvent tests that a Job only creates one Pod even when
4117
- // the job failed events are delayed. This test verfies the finishedJobStore is working
4118
- // correctly and preventing from job controller creating a new pod if the job failed
4119
- // event is delayed.
4120
- func TestDelayedJobFailedUpdateEvent (t * testing.T ) {
4121
- t .Cleanup (setDurationDuringTest (& jobcontroller .DefaultJobPodFailureBackOff , fastPodFailureBackoff ))
4122
- t .Cleanup (setDurationDuringTest (& jobcontroller .SyncJobBatchPeriod , fastSyncJobBatchPeriod ))
4123
- closeFn , restConfig , clientSet , ns := setup (t , "pod-failure-policy" )
4124
- t .Cleanup (closeFn )
4125
- // the transform is used to introduce a delay for the job events. Since all the object have to go through
4126
- // transform func first before being added to the informer cache, this would serve as an indirect way to
4127
- // introduce watch event delay.
4128
- transformOpt := informers .WithTransform (cache .TransformFunc (func (obj interface {}) (interface {}, error ) {
4129
- _ , ok := obj .(* batchv1.Job )
4130
- if ok {
4131
- // This will make sure pod events are processed before the job events occur.
4132
- time .Sleep (2 * fastSyncJobBatchPeriod )
4133
- }
4134
- return obj , nil
4135
- }))
4136
- ctx , cancel := startJobControllerAndWaitForCaches (t , restConfig , transformOpt )
4137
- t .Cleanup (func () {
4138
- cancel ()
4139
- })
4140
- resetMetrics ()
4141
4079
4142
- jobObj , err := createJobWithDefaults (ctx , clientSet , ns .Name , & batchv1.Job {
4143
- Spec : batchv1.JobSpec {
4144
- Template : v1.PodTemplateSpec {
4145
- Spec : v1.PodSpec {
4146
- Containers : []v1.Container {
4147
- {
4148
- Name : "main-container" ,
4149
- Image : "foo" ,
4150
- ImagePullPolicy : v1 .PullIfNotPresent ,
4151
- TerminationMessagePolicy : v1 .TerminationMessageFallbackToLogsOnError ,
4080
+ cases := map [string ]struct {
4081
+ podReplacementPolicyEnabled bool
4082
+ job * batchv1.Job
4083
+ podUpdate func (* v1.Pod ) bool
4084
+ wantStatus jobStatus
4085
+ }{
4086
+ "job succeeded event delayed" : {
4087
+ job : & batchv1.Job {},
4088
+ podUpdate : func (p * v1.Pod ) bool {
4089
+ p .Status .Phase = v1 .PodSucceeded
4090
+ p .Status .ContainerStatuses = []v1.ContainerStatus {
4091
+ {
4092
+ State : v1.ContainerState {
4093
+ Terminated : & v1.ContainerStateTerminated {
4094
+ FinishedAt : metav1 .Now (),
4095
+ },
4152
4096
},
4153
4097
},
4154
- },
4098
+ }
4099
+ return true
4100
+ },
4101
+ wantStatus : jobStatus {
4102
+ succeeded : 1 ,
4103
+ failed : 0 ,
4104
+ status : batchv1 .JobComplete ,
4155
4105
},
4156
- BackoffLimit : ptr.To [int32 ](0 ),
4157
4106
},
4158
- })
4159
- if err != nil {
4160
- t .Fatalf ("Failed to create Job: %v" , err )
4161
- }
4162
- validateJobPodsStatus (ctx , t , clientSet , jobObj , podsByStatus {
4163
- Active : 1 ,
4164
- Ready : ptr.To [int32 ](0 ),
4165
- Terminating : ptr.To [int32 ](0 ),
4166
- })
4167
-
4168
- op := func (p * v1.Pod ) bool {
4169
- p .Status = v1.PodStatus {
4170
- Phase : v1 .PodFailed ,
4171
- ContainerStatuses : []v1.ContainerStatus {
4172
- {
4173
- Name : "main-container" ,
4174
- State : v1.ContainerState {
4175
- Terminated : & v1.ContainerStateTerminated {
4176
- ExitCode : 5 ,
4107
+ "job failed event delayed" : {
4108
+ job : & batchv1.Job {
4109
+ Spec : batchv1.JobSpec {
4110
+ Template : v1.PodTemplateSpec {
4111
+ Spec : v1.PodSpec {
4112
+ Containers : []v1.Container {
4113
+ {
4114
+ Name : "main-container" ,
4115
+ Image : "foo" ,
4116
+ ImagePullPolicy : v1 .PullIfNotPresent ,
4117
+ TerminationMessagePolicy : v1 .TerminationMessageFallbackToLogsOnError ,
4118
+ },
4119
+ },
4177
4120
},
4178
4121
},
4122
+ BackoffLimit : ptr.To [int32 ](0 ),
4179
4123
},
4180
4124
},
4181
- }
4182
- return true
4183
- }
4184
- if _ , err := updateJobPodsStatus (ctx , clientSet , jobObj , op , 1 ); err != nil {
4185
- t .Fatalf ("Error %q while updating pod status for Job: %v" , err , jobObj .Name )
4125
+ podUpdate : func (p * v1.Pod ) bool {
4126
+ p .Status = v1.PodStatus {
4127
+ Phase : v1 .PodFailed ,
4128
+ ContainerStatuses : []v1.ContainerStatus {
4129
+ {
4130
+ Name : "main-container" ,
4131
+ State : v1.ContainerState {
4132
+ Terminated : & v1.ContainerStateTerminated {
4133
+ ExitCode : 5 ,
4134
+ },
4135
+ },
4136
+ },
4137
+ },
4138
+ }
4139
+ return true
4140
+ },
4141
+ wantStatus : jobStatus {
4142
+ succeeded : 0 ,
4143
+ failed : 1 ,
4144
+ status : batchv1 .JobFailed ,
4145
+ },
4146
+ },
4186
4147
}
4187
- validateJobsPodsStatusOnly (ctx , t , clientSet , jobObj , podsByStatus {
4188
- Active : 0 ,
4189
- Failed : 1 ,
4190
- Ready : ptr.To [int32 ](0 ),
4191
- Terminating : ptr.To [int32 ](0 ),
4192
- })
4193
4148
4194
- validateJobFailed (ctx , t , clientSet , jobObj )
4195
- jobPods , err := getJobPods (ctx , t , clientSet , jobObj , func (ps v1.PodStatus ) bool { return true })
4196
- if err != nil {
4197
- t .Fatalf ("Error %v getting the list of pods for job %q" , err , klog .KObj (jobObj ))
4198
- }
4199
- if len (jobPods ) != 1 {
4200
- t .Errorf ("Found %d Pods for the job %q, want 1" , len (jobPods ), klog .KObj (jobObj ))
4149
+ for name , tc := range cases {
4150
+ tc := tc
4151
+ t .Run (name , func (t * testing.T ) {
4152
+ ctx , cancel := startJobControllerAndWaitForCaches (t , restConfig , transformOpt )
4153
+ t .Cleanup (cancel )
4154
+ resetMetrics ()
4155
+
4156
+ jobObj , err := createJobWithDefaults (ctx , clientSet , ns .Name , tc .job )
4157
+ if err != nil {
4158
+ t .Fatalf ("Failed to create Job: %v" , err )
4159
+ }
4160
+
4161
+ validateJobPodsStatus (ctx , t , clientSet , jobObj , podsByStatus {
4162
+ Active : 1 ,
4163
+ Ready : ptr.To [int32 ](0 ),
4164
+ Terminating : ptr.To [int32 ](0 ),
4165
+ })
4166
+
4167
+ if _ , err := updateJobPodsStatus (ctx , clientSet , jobObj , tc .podUpdate , 1 ); err != nil {
4168
+ t .Fatalf ("Error %q while updating pod status for Job: %v" , err , jobObj .Name )
4169
+ }
4170
+
4171
+ validateJobsPodsStatusOnly (ctx , t , clientSet , jobObj , podsByStatus {
4172
+ Failed : tc .wantStatus .failed ,
4173
+ Succeeded : tc .wantStatus .succeeded ,
4174
+ Ready : ptr.To [int32 ](0 ),
4175
+ Terminating : ptr.To [int32 ](0 ),
4176
+ })
4177
+
4178
+ validateJobCondition (ctx , t , clientSet , jobObj , tc .wantStatus .status )
4179
+
4180
+ jobPods , err := getJobPods (ctx , t , clientSet , jobObj , func (ps v1.PodStatus ) bool { return true })
4181
+ if err != nil {
4182
+ t .Fatalf ("Error %v getting the list of pods for job %q" , err , klog .KObj (jobObj ))
4183
+ }
4184
+ if len (jobPods ) != 1 {
4185
+ t .Errorf ("Found %d Pods for the job %q, want 1" , len (jobPods ), klog .KObj (jobObj ))
4186
+ }
4187
+ })
4201
4188
}
4189
+
4202
4190
}
4203
4191
4204
4192
type podsByStatus struct {
0 commit comments