@@ -51,6 +51,7 @@ var _ = SIGDescribe("CronJob", func() {
51
51
52
52
// Pod will complete instantly
53
53
successCommand := []string {"/bin/true" }
54
+ failureCommand := []string {"/bin/false" }
54
55
55
56
ginkgo .BeforeEach (func () {
56
57
framework .SkipIfMissingResource (f .DynamicClient , CronJobGroupVersionResourceBeta , f .Namespace .Name )
@@ -60,7 +61,7 @@ var _ = SIGDescribe("CronJob", func() {
60
61
ginkgo .It ("should schedule multiple jobs concurrently" , func () {
61
62
ginkgo .By ("Creating a cronjob" )
62
63
cronJob := newTestCronJob ("concurrent" , "*/1 * * * ?" , batchv1beta1 .AllowConcurrent ,
63
- sleepCommand , nil )
64
+ sleepCommand , nil , nil )
64
65
cronJob , err := createCronJob (f .ClientSet , f .Namespace .Name , cronJob )
65
66
framework .ExpectNoError (err , "Failed to create CronJob in namespace %s" , f .Namespace .Name )
66
67
@@ -83,7 +84,7 @@ var _ = SIGDescribe("CronJob", func() {
83
84
ginkgo .It ("should not schedule jobs when suspended [Slow]" , func () {
84
85
ginkgo .By ("Creating a suspended cronjob" )
85
86
cronJob := newTestCronJob ("suspended" , "*/1 * * * ?" , batchv1beta1 .AllowConcurrent ,
86
- sleepCommand , nil )
87
+ sleepCommand , nil , nil )
87
88
t := true
88
89
cronJob .Spec .Suspend = & t
89
90
cronJob , err := createCronJob (f .ClientSet , f .Namespace .Name , cronJob )
@@ -107,7 +108,7 @@ var _ = SIGDescribe("CronJob", func() {
107
108
ginkgo .It ("should not schedule new jobs when ForbidConcurrent [Slow]" , func () {
108
109
ginkgo .By ("Creating a ForbidConcurrent cronjob" )
109
110
cronJob := newTestCronJob ("forbid" , "*/1 * * * ?" , batchv1beta1 .ForbidConcurrent ,
110
- sleepCommand , nil )
111
+ sleepCommand , nil , nil )
111
112
cronJob , err := createCronJob (f .ClientSet , f .Namespace .Name , cronJob )
112
113
framework .ExpectNoError (err , "Failed to create CronJob in namespace %s" , f .Namespace .Name )
113
114
@@ -139,7 +140,7 @@ var _ = SIGDescribe("CronJob", func() {
139
140
ginkgo .It ("should replace jobs when ReplaceConcurrent" , func () {
140
141
ginkgo .By ("Creating a ReplaceConcurrent cronjob" )
141
142
cronJob := newTestCronJob ("replace" , "*/1 * * * ?" , batchv1beta1 .ReplaceConcurrent ,
142
- sleepCommand , nil )
143
+ sleepCommand , nil , nil )
143
144
cronJob , err := createCronJob (f .ClientSet , f .Namespace .Name , cronJob )
144
145
framework .ExpectNoError (err , "Failed to create CronJob in namespace %s" , f .Namespace .Name )
145
146
@@ -171,7 +172,7 @@ var _ = SIGDescribe("CronJob", func() {
171
172
ginkgo .It ("should not emit unexpected warnings" , func () {
172
173
ginkgo .By ("Creating a cronjob" )
173
174
cronJob := newTestCronJob ("concurrent" , "*/1 * * * ?" , batchv1beta1 .AllowConcurrent ,
174
- nil , nil )
175
+ nil , nil , nil )
175
176
cronJob , err := createCronJob (f .ClientSet , f .Namespace .Name , cronJob )
176
177
framework .ExpectNoError (err , "Failed to create CronJob in namespace %s" , f .Namespace .Name )
177
178
@@ -194,7 +195,7 @@ var _ = SIGDescribe("CronJob", func() {
194
195
ginkgo .It ("should remove from active list jobs that have been deleted" , func () {
195
196
ginkgo .By ("Creating a ForbidConcurrent cronjob" )
196
197
cronJob := newTestCronJob ("forbid" , "*/1 * * * ?" , batchv1beta1 .ForbidConcurrent ,
197
- sleepCommand , nil )
198
+ sleepCommand , nil , nil )
198
199
cronJob , err := createCronJob (f .ClientSet , f .Namespace .Name , cronJob )
199
200
framework .ExpectNoError (err , "Failed to create CronJob in namespace %s" , f .Namespace .Name )
200
201
@@ -229,52 +230,75 @@ var _ = SIGDescribe("CronJob", func() {
229
230
framework .ExpectNoError (err , "Failed to remove %s cronjob in namespace %s" , cronJob .Name , f .Namespace .Name )
230
231
})
231
232
232
- // cleanup of successful finished jobs, with limit of one successful job
233
- ginkgo .It ("should delete successful finished jobs with limit of one successful job" , func () {
234
- ginkgo .By ("Creating a AllowConcurrent cronjob with custom history limits" )
235
- successLimit := int32 (1 )
236
- cronJob := newTestCronJob ("concurrent-limit" , "*/1 * * * ?" , batchv1beta1 .AllowConcurrent ,
237
- successCommand , & successLimit )
238
- cronJob , err := createCronJob (f .ClientSet , f .Namespace .Name , cronJob )
239
- framework .ExpectNoError (err , "Failed to create allowconcurrent cronjob with custom history limits in namespace %s" , f .Namespace .Name )
240
-
241
- // Job is going to complete instantly: do not check for an active job
242
- // as we are most likely to miss it
243
-
244
- ginkgo .By ("Ensuring a finished job exists" )
245
- err = waitForAnyFinishedJob (f .ClientSet , f .Namespace .Name )
246
- framework .ExpectNoError (err , "Failed to ensure a finished cronjob exists in namespace %s" , f .Namespace .Name )
247
-
248
- ginkgo .By ("Ensuring a finished job exists by listing jobs explicitly" )
249
- jobs , err := f .ClientSet .BatchV1 ().Jobs (f .Namespace .Name ).List (metav1.ListOptions {})
250
- framework .ExpectNoError (err , "Failed to ensure a finished cronjob exists by listing jobs explicitly in namespace %s" , f .Namespace .Name )
251
- _ , finishedJobs := filterActiveJobs (jobs )
252
- framework .ExpectEqual (len (finishedJobs ), 1 )
253
-
254
- // Job should get deleted when the next job finishes the next minute
255
- ginkgo .By ("Ensuring this job and its pods does not exist anymore" )
256
- err = waitForJobToDisappear (f .ClientSet , f .Namespace .Name , finishedJobs [0 ])
257
- framework .ExpectNoError (err , "Failed to ensure that job does not exists anymore in namespace %s" , f .Namespace .Name )
258
- err = waitForJobsPodToDisappear (f .ClientSet , f .Namespace .Name , finishedJobs [0 ])
259
- framework .ExpectNoError (err , "Failed to ensure that pods for job does not exists anymore in namespace %s" , f .Namespace .Name )
260
-
261
- ginkgo .By ("Ensuring there is 1 finished job by listing jobs explicitly" )
262
- jobs , err = f .ClientSet .BatchV1 ().Jobs (f .Namespace .Name ).List (metav1.ListOptions {})
263
- framework .ExpectNoError (err , "Failed to ensure there is one finished job by listing job explicitly in namespace %s" , f .Namespace .Name )
264
- _ , finishedJobs = filterActiveJobs (jobs )
265
- framework .ExpectEqual (len (finishedJobs ), 1 )
233
+ // cleanup of successful/failed finished jobs, with successfulJobsHistoryLimit and failedJobsHistoryLimit
234
+ ginkgo .It ("should delete successful/failed finished jobs with limit of one job" , func () {
235
+
236
+ testCases := []struct {
237
+ description string
238
+ command []string
239
+ successLimit int32
240
+ failedLimit int32
241
+ }{
242
+ {
243
+ description : "successful-jobs-history-limit" ,
244
+ command : successCommand ,
245
+ successLimit : 1 , // keep one successful job
246
+ failedLimit : 0 , // keep none failed job
247
+ },
248
+ {
249
+ description : "failed-jobs-history-limit" ,
250
+ command : failureCommand ,
251
+ successLimit : 0 , // keep none succcessful job
252
+ failedLimit : 1 , // keep one failed job
253
+ },
254
+ }
266
255
267
- ginkgo .By ("Removing cronjob" )
268
- err = deleteCronJob (f .ClientSet , f .Namespace .Name , cronJob .Name )
269
- framework .ExpectNoError (err , "Failed to remove the %s cronjob in namespace %s" , cronJob .Name , f .Namespace .Name )
256
+ for _ , t := range testCases {
257
+ ginkgo .By (fmt .Sprintf ("Creating a AllowConcurrent cronjob with custom %s" , t .description ))
258
+ cronJob := newTestCronJob (t .description , "*/1 * * * ?" , batchv1beta1 .AllowConcurrent ,
259
+ t .command , & t .successLimit , & t .failedLimit )
260
+ cronJob , err := createCronJob (f .ClientSet , f .Namespace .Name , cronJob )
261
+ framework .ExpectNoError (err , "Failed to create allowconcurrent cronjob with custom history limits in namespace %s" , f .Namespace .Name )
262
+
263
+ // Job is going to complete instantly: do not check for an active job
264
+ // as we are most likely to miss it
265
+
266
+ ginkgo .By ("Ensuring a finished job exists" )
267
+ err = waitForAnyFinishedJob (f .ClientSet , f .Namespace .Name )
268
+ framework .ExpectNoError (err , "Failed to ensure a finished cronjob exists in namespace %s" , f .Namespace .Name )
269
+
270
+ ginkgo .By ("Ensuring a finished job exists by listing jobs explicitly" )
271
+ jobs , err := f .ClientSet .BatchV1 ().Jobs (f .Namespace .Name ).List (metav1.ListOptions {})
272
+ framework .ExpectNoError (err , "Failed to ensure a finished cronjob exists by listing jobs explicitly in namespace %s" , f .Namespace .Name )
273
+ _ , finishedJobs := filterActiveJobs (jobs )
274
+ framework .ExpectEqual (len (finishedJobs ), 1 )
275
+
276
+ // Job should get deleted when the next job finishes the next minute
277
+ ginkgo .By ("Ensuring this job and its pods does not exist anymore" )
278
+ err = waitForJobToDisappear (f .ClientSet , f .Namespace .Name , finishedJobs [0 ])
279
+ framework .ExpectNoError (err , "Failed to ensure that job does not exists anymore in namespace %s" , f .Namespace .Name )
280
+ err = waitForJobsPodToDisappear (f .ClientSet , f .Namespace .Name , finishedJobs [0 ])
281
+ framework .ExpectNoError (err , "Failed to ensure that pods for job does not exists anymore in namespace %s" , f .Namespace .Name )
282
+
283
+ ginkgo .By ("Ensuring there is 1 finished job by listing jobs explicitly" )
284
+ jobs , err = f .ClientSet .BatchV1 ().Jobs (f .Namespace .Name ).List (metav1.ListOptions {})
285
+ framework .ExpectNoError (err , "Failed to ensure there is one finished job by listing job explicitly in namespace %s" , f .Namespace .Name )
286
+ _ , finishedJobs = filterActiveJobs (jobs )
287
+ framework .ExpectEqual (len (finishedJobs ), 1 )
288
+
289
+ ginkgo .By ("Removing cronjob" )
290
+ err = deleteCronJob (f .ClientSet , f .Namespace .Name , cronJob .Name )
291
+ framework .ExpectNoError (err , "Failed to remove the %s cronjob in namespace %s" , cronJob .Name , f .Namespace .Name )
292
+ }
270
293
})
271
294
})
272
295
273
296
// newTestCronJob returns a cronjob which does one of several testing behaviors.
274
297
func newTestCronJob (name , schedule string , concurrencyPolicy batchv1beta1.ConcurrencyPolicy ,
275
- command []string , successfulJobsHistoryLimit * int32 ) * batchv1beta1.CronJob {
298
+ command []string , successfulJobsHistoryLimit * int32 , failedJobsHistoryLimit * int32 ) * batchv1beta1.CronJob {
276
299
parallelism := int32 (1 )
277
300
completions := int32 (1 )
301
+ backofflimit := int32 (1 )
278
302
sj := & batchv1beta1.CronJob {
279
303
ObjectMeta : metav1.ObjectMeta {
280
304
Name : name ,
@@ -287,8 +311,9 @@ func newTestCronJob(name, schedule string, concurrencyPolicy batchv1beta1.Concur
287
311
ConcurrencyPolicy : concurrencyPolicy ,
288
312
JobTemplate : batchv1beta1.JobTemplateSpec {
289
313
Spec : batchv1.JobSpec {
290
- Parallelism : & parallelism ,
291
- Completions : & completions ,
314
+ Parallelism : & parallelism ,
315
+ Completions : & completions ,
316
+ BackoffLimit : & backofflimit ,
292
317
Template : v1.PodTemplateSpec {
293
318
Spec : v1.PodSpec {
294
319
RestartPolicy : v1 .RestartPolicyOnFailure ,
@@ -319,6 +344,7 @@ func newTestCronJob(name, schedule string, concurrencyPolicy batchv1beta1.Concur
319
344
},
320
345
}
321
346
sj .Spec .SuccessfulJobsHistoryLimit = successfulJobsHistoryLimit
347
+ sj .Spec .FailedJobsHistoryLimit = failedJobsHistoryLimit
322
348
if command != nil {
323
349
sj .Spec .JobTemplate .Spec .Template .Spec .Containers [0 ].Command = command
324
350
}
@@ -334,7 +360,8 @@ func getCronJob(c clientset.Interface, ns, name string) (*batchv1beta1.CronJob,
334
360
}
335
361
336
362
func deleteCronJob (c clientset.Interface , ns , name string ) error {
337
- return c .BatchV1beta1 ().CronJobs (ns ).Delete (name , nil )
363
+ propagationPolicy := metav1 .DeletePropagationBackground // Also delete jobs and pods related to cronjob
364
+ return c .BatchV1beta1 ().CronJobs (ns ).Delete (name , & metav1.DeleteOptions {PropagationPolicy : & propagationPolicy })
338
365
}
339
366
340
367
// Wait for at least given amount of active jobs.
0 commit comments