@@ -427,16 +427,17 @@ func TestJobPodFailurePolicy(t *testing.T) {
427
427
},
428
428
},
429
429
}
430
+
431
+ closeFn , restConfig , clientSet , ns := setup (t , "pod-failure-policy" )
432
+ t .Cleanup (closeFn )
430
433
for name , test := range testCases {
431
434
t .Run (name , func (t * testing.T ) {
432
435
resetMetrics ()
433
436
434
- closeFn , restConfig , clientSet , ns := setup (t , "simple" )
435
- defer closeFn ()
436
437
ctx , cancel := startJobControllerAndWaitForCaches (t , restConfig )
437
- defer func () {
438
+ t . Cleanup ( func () {
438
439
cancel ()
439
- }( )
440
+ })
440
441
441
442
jobObj , err := createJobWithDefaults (ctx , clientSet , ns .Name , & test .job )
442
443
if err != nil {
@@ -761,18 +762,18 @@ func TestSuccessPolicy(t *testing.T) {
761
762
wantConditionTypes : []batchv1.JobConditionType {batchv1 .JobFailed },
762
763
},
763
764
}
765
+
766
+ closeFn , restConfig , clientSet , ns := setup (t , "success-policy" )
767
+ t .Cleanup (closeFn )
764
768
for name , tc := range testCases {
765
769
t .Run (name , func (t * testing.T ) {
766
770
resetMetrics ()
767
771
featuregatetesting .SetFeatureGateDuringTest (t , feature .DefaultFeatureGate , features .JobSuccessPolicy , tc .enableJobSuccessPolicy )
768
772
featuregatetesting .SetFeatureGateDuringTest (t , feature .DefaultFeatureGate , features .JobBackoffLimitPerIndex , tc .enableBackoffLimitPerIndex )
769
773
770
- closeFn , restConfig , clientSet , ns := setup (t , "simple" )
771
- defer closeFn ()
772
774
ctx , cancel := startJobControllerAndWaitForCaches (t , restConfig )
773
- defer func () {
774
- cancel ()
775
- }()
775
+ t .Cleanup (cancel )
776
+
776
777
jobObj , err := createJobWithDefaults (ctx , clientSet , ns .Name , & tc .job )
777
778
if err != nil {
778
779
t .Fatalf ("Error %v while creating the Job %q" , err , jobObj .Name )
@@ -1180,11 +1181,12 @@ func TestBackoffLimitPerIndex_JobPodsCreatedWithExponentialBackoff(t *testing.T)
1180
1181
// are terminal. The fate of the Job is indicated by the interim Job conditions:
1181
1182
// FailureTarget, or SuccessCriteriaMet.
1182
1183
func TestDelayTerminalPhaseCondition (t * testing.T ) {
1184
+ const blockDeletionFinalizerForTest string = "fake.example.com/blockDeletion"
1183
1185
t .Cleanup (setDurationDuringTest (& jobcontroller .DefaultJobPodFailureBackOff , fastPodFailureBackoff ))
1184
1186
1185
1187
podTemplateSpec := v1.PodTemplateSpec {
1186
1188
ObjectMeta : metav1.ObjectMeta {
1187
- Finalizers : []string {"fake.example.com/blockDeletion" },
1189
+ Finalizers : []string {blockDeletionFinalizerForTest },
1188
1190
},
1189
1191
Spec : v1.PodSpec {
1190
1192
Containers : []v1.Container {
@@ -1515,6 +1517,9 @@ func TestDelayTerminalPhaseCondition(t *testing.T) {
1515
1517
},
1516
1518
},
1517
1519
}
1520
+
1521
+ closeFn , restConfig , clientSet , ns := setup (t , "delay-terminal-condition" )
1522
+ t .Cleanup (closeFn )
1518
1523
for name , test := range testCases {
1519
1524
t .Run (name , func (t * testing.T ) {
1520
1525
resetMetrics ()
@@ -1523,16 +1528,18 @@ func TestDelayTerminalPhaseCondition(t *testing.T) {
1523
1528
featuregatetesting .SetFeatureGateDuringTest (t , feature .DefaultFeatureGate , features .ElasticIndexedJob , true )
1524
1529
featuregatetesting .SetFeatureGateDuringTest (t , feature .DefaultFeatureGate , features .JobSuccessPolicy , test .enableJobSuccessPolicy )
1525
1530
1526
- closeFn , restConfig , clientSet , ns := setup (t , "delay-terminal-condition" )
1527
- t .Cleanup (closeFn )
1528
1531
ctx , cancel := startJobControllerAndWaitForCaches (t , restConfig )
1529
1532
t .Cleanup (cancel )
1530
1533
1531
1534
jobObj , err := createJobWithDefaults (ctx , clientSet , ns .Name , & test .job )
1532
1535
if err != nil {
1533
1536
t .Fatalf ("Error %q while creating the job %q" , err , jobObj .Name )
1534
1537
}
1535
- t .Cleanup (func () { removePodsFinalizer (ctx , t , clientSet , ns .Name ) })
1538
+ t .Cleanup (func () {
1539
+ if err := cleanUp (ctx , clientSet , jobObj , []string {blockDeletionFinalizerForTest , batchv1 .JobTrackingFinalizer }); err != nil {
1540
+ t .Fatalf ("Failed cleanup: %v" , err )
1541
+ }
1542
+ })
1536
1543
jobClient := clientSet .BatchV1 ().Jobs (jobObj .Namespace )
1537
1544
1538
1545
waitForPodsToBeActive (ctx , t , jobClient , * jobObj .Spec .Parallelism , jobObj )
@@ -1901,17 +1908,17 @@ func TestBackoffLimitPerIndex(t *testing.T) {
1901
1908
},
1902
1909
},
1903
1910
}
1911
+
1912
+ closeFn , restConfig , clientSet , ns := setup (t , "backoff-limit-per-index" )
1913
+ t .Cleanup (closeFn )
1904
1914
for name , test := range testCases {
1905
1915
t .Run (name , func (t * testing.T ) {
1906
1916
resetMetrics ()
1907
1917
featuregatetesting .SetFeatureGateDuringTest (t , feature .DefaultFeatureGate , features .JobBackoffLimitPerIndex , true )
1908
1918
1909
- closeFn , restConfig , clientSet , ns := setup (t , "simple" )
1910
- defer closeFn ()
1911
1919
ctx , cancel := startJobControllerAndWaitForCaches (t , restConfig )
1912
- defer func () {
1913
- cancel ()
1914
- }()
1920
+ t .Cleanup (cancel )
1921
+
1915
1922
jobObj , err := createJobWithDefaults (ctx , clientSet , ns .Name , & test .job )
1916
1923
if err != nil {
1917
1924
t .Fatalf ("Error %q while creating the job %q" , err , jobObj .Name )
@@ -1972,6 +1979,7 @@ func TestBackoffLimitPerIndex(t *testing.T) {
1972
1979
// reconcile or skip reconciliation of the Job depending on the Job's managedBy
1973
1980
// field, and the enablement of the JobManagedBy feature gate.
1974
1981
func TestManagedBy (t * testing.T ) {
1982
+ const blockDeletionFinalizerForTest string = "fake.example.com/blockDeletion"
1975
1983
customControllerName := "example.com/custom-job-controller"
1976
1984
podTemplateSpec := v1.PodTemplateSpec {
1977
1985
Spec : v1.PodSpec {
@@ -2064,20 +2072,29 @@ func TestManagedBy(t *testing.T) {
2064
2072
},
2065
2073
},
2066
2074
}
2075
+
2076
+ closeFn , restConfig , clientSet , ns := setup (t , "managed-by" )
2077
+ t .Cleanup (closeFn )
2067
2078
for name , test := range testCases {
2068
2079
t .Run (name , func (t * testing.T ) {
2069
2080
resetMetrics ()
2070
2081
featuregatetesting .SetFeatureGateDuringTest (t , feature .DefaultFeatureGate , features .JobManagedBy , test .enableJobManagedBy )
2071
2082
2072
- closeFn , restConfig , clientSet , ns := setup (t , "managed-by" )
2073
- defer closeFn ()
2074
2083
ctx , cancel := startJobControllerAndWaitForCaches (t , restConfig )
2075
- defer cancel ()
2084
+ t .Cleanup (cancel )
2085
+
2076
2086
jobObj , err := createJobWithDefaults (ctx , clientSet , ns .Name , & test .job )
2077
2087
if err != nil {
2078
2088
t .Fatalf ("Error %v while creating the job %q" , err , klog .KObj (jobObj ))
2079
2089
}
2080
2090
2091
+ t .Cleanup (func () {
2092
+ // Wait for cleanup to finish to prevent this job from affecting metrics
2093
+ if err := cleanUp (ctx , clientSet , jobObj , []string {blockDeletionFinalizerForTest , batchv1 .JobTrackingFinalizer }); err != nil {
2094
+ t .Fatalf ("Failed cleanup: %v" , err )
2095
+ }
2096
+ })
2097
+
2081
2098
if test .wantReconciledByBuiltInController {
2082
2099
validateJobPodsStatus (ctx , t , clientSet , jobObj , podsByStatus {
2083
2100
Active : int (* jobObj .Spec .Parallelism ),
@@ -2817,6 +2834,7 @@ func TestIndexedJob(t *testing.T) {
2817
2834
}
2818
2835
2819
2836
func TestJobPodReplacementPolicy (t * testing.T ) {
2837
+ const blockDeletionFinalizerForTest string = "fake.example.com/blockDeletion"
2820
2838
t .Cleanup (setDurationDuringTest (& jobcontroller .DefaultJobPodFailureBackOff , fastPodFailureBackoff ))
2821
2839
indexedCompletion := batchv1 .IndexedCompletion
2822
2840
nonIndexedCompletion := batchv1 .NonIndexedCompletion
@@ -2847,7 +2865,7 @@ func TestJobPodReplacementPolicy(t *testing.T) {
2847
2865
CompletionMode : & indexedCompletion ,
2848
2866
Template : v1.PodTemplateSpec {
2849
2867
ObjectMeta : metav1.ObjectMeta {
2850
- Finalizers : []string {"fake.example.com/blockDeletion" },
2868
+ Finalizers : []string {blockDeletionFinalizerForTest },
2851
2869
},
2852
2870
},
2853
2871
},
@@ -2872,7 +2890,7 @@ func TestJobPodReplacementPolicy(t *testing.T) {
2872
2890
PodReplacementPolicy : podReplacementPolicy (batchv1 .TerminatingOrFailed ),
2873
2891
Template : v1.PodTemplateSpec {
2874
2892
ObjectMeta : metav1.ObjectMeta {
2875
- Finalizers : []string {"fake.example.com/blockDeletion" },
2893
+ Finalizers : []string {blockDeletionFinalizerForTest },
2876
2894
},
2877
2895
},
2878
2896
},
@@ -2900,7 +2918,7 @@ func TestJobPodReplacementPolicy(t *testing.T) {
2900
2918
PodReplacementPolicy : podReplacementPolicy (batchv1 .TerminatingOrFailed ),
2901
2919
Template : v1.PodTemplateSpec {
2902
2920
ObjectMeta : metav1.ObjectMeta {
2903
- Finalizers : []string {"fake.example.com/blockDeletion" },
2921
+ Finalizers : []string {blockDeletionFinalizerForTest },
2904
2922
},
2905
2923
},
2906
2924
},
@@ -2928,7 +2946,7 @@ func TestJobPodReplacementPolicy(t *testing.T) {
2928
2946
PodReplacementPolicy : podReplacementPolicy (batchv1 .Failed ),
2929
2947
Template : v1.PodTemplateSpec {
2930
2948
ObjectMeta : metav1.ObjectMeta {
2931
- Finalizers : []string {"fake.example.com/blockDeletion" },
2949
+ Finalizers : []string {blockDeletionFinalizerForTest },
2932
2950
},
2933
2951
},
2934
2952
PodFailurePolicy : & batchv1.PodFailurePolicy {
@@ -2962,7 +2980,7 @@ func TestJobPodReplacementPolicy(t *testing.T) {
2962
2980
PodReplacementPolicy : podReplacementPolicy (batchv1 .Failed ),
2963
2981
Template : v1.PodTemplateSpec {
2964
2982
ObjectMeta : metav1.ObjectMeta {
2965
- Finalizers : []string {"fake.example.com/blockDeletion" },
2983
+ Finalizers : []string {blockDeletionFinalizerForTest },
2966
2984
},
2967
2985
},
2968
2986
},
@@ -2990,7 +3008,7 @@ func TestJobPodReplacementPolicy(t *testing.T) {
2990
3008
PodReplacementPolicy : podReplacementPolicy (batchv1 .Failed ),
2991
3009
Template : v1.PodTemplateSpec {
2992
3010
ObjectMeta : metav1.ObjectMeta {
2993
- Finalizers : []string {"fake.example.com/blockDeletion" },
3011
+ Finalizers : []string {blockDeletionFinalizerForTest },
2994
3012
},
2995
3013
},
2996
3014
},
@@ -3010,13 +3028,14 @@ func TestJobPodReplacementPolicy(t *testing.T) {
3010
3028
},
3011
3029
},
3012
3030
}
3031
+
3032
+ closeFn , restConfig , clientSet , ns := setup (t , "pod-replacement-policy" )
3033
+ t .Cleanup (closeFn )
3013
3034
for name , tc := range cases {
3014
3035
tc := tc
3015
3036
t .Run (name , func (t * testing.T ) {
3016
3037
featuregatetesting .SetFeatureGateDuringTest (t , feature .DefaultFeatureGate , features .JobPodReplacementPolicy , tc .podReplacementPolicyEnabled )
3017
3038
3018
- closeFn , restConfig , clientSet , ns := setup (t , "pod-replacement-policy" )
3019
- t .Cleanup (closeFn )
3020
3039
ctx , cancel := startJobControllerAndWaitForCaches (t , restConfig )
3021
3040
t .Cleanup (cancel )
3022
3041
resetMetrics ()
@@ -3030,7 +3049,11 @@ func TestJobPodReplacementPolicy(t *testing.T) {
3030
3049
jobClient := clientSet .BatchV1 ().Jobs (jobObj .Namespace )
3031
3050
3032
3051
waitForPodsToBeActive (ctx , t , jobClient , 2 , jobObj )
3033
- t .Cleanup (func () { removePodsFinalizer (ctx , t , clientSet , ns .Name ) })
3052
+ t .Cleanup (func () {
3053
+ if err := cleanUp (ctx , clientSet , jobObj , []string {blockDeletionFinalizerForTest , batchv1 .JobTrackingFinalizer }); err != nil {
3054
+ t .Fatalf ("Failed cleanup: %v" , err )
3055
+ }
3056
+ })
3034
3057
3035
3058
deletePods (ctx , t , clientSet , ns .Name )
3036
3059
@@ -3221,11 +3244,11 @@ func TestElasticIndexedJob(t *testing.T) {
3221
3244
},
3222
3245
}
3223
3246
3247
+ closeFn , restConfig , clientSet , ns := setup (t , "indexed" )
3248
+ t .Cleanup (closeFn )
3224
3249
for name , tc := range cases {
3225
3250
tc := tc
3226
3251
t .Run (name , func (t * testing.T ) {
3227
- closeFn , restConfig , clientSet , ns := setup (t , "indexed" )
3228
- defer closeFn ()
3229
3252
ctx , cancel := startJobControllerAndWaitForCaches (t , restConfig )
3230
3253
defer cancel ()
3231
3254
resetMetrics ()
@@ -3362,7 +3385,7 @@ func BenchmarkLargeIndexedJob(b *testing.B) {
3362
3385
b .Fatalf ("Failed to create Job: %v" , err )
3363
3386
}
3364
3387
b .Cleanup (func () {
3365
- if err := cleanUp (ctx , clientSet , jobObj ); err != nil {
3388
+ if err := cleanUp (ctx , clientSet , jobObj , [] string { batchv1 . JobTrackingFinalizer } ); err != nil {
3366
3389
b .Fatalf ("Failed cleanup: %v" , err )
3367
3390
}
3368
3391
})
@@ -3450,7 +3473,7 @@ func BenchmarkLargeFailureHandling(b *testing.B) {
3450
3473
b .Fatalf ("Failed to create Job: %v" , err )
3451
3474
}
3452
3475
b .Cleanup (func () {
3453
- if err := cleanUp (ctx , clientSet , jobObj ); err != nil {
3476
+ if err := cleanUp (ctx , clientSet , jobObj , [] string { batchv1 . JobTrackingFinalizer } ); err != nil {
3454
3477
b .Fatalf ("Failed cleanup: %v" , err )
3455
3478
}
3456
3479
})
@@ -3484,8 +3507,11 @@ func BenchmarkLargeFailureHandling(b *testing.B) {
3484
3507
}
3485
3508
}
3486
3509
3487
- // cleanUp deletes all pods and the job
3488
- func cleanUp (ctx context.Context , clientSet clientset.Interface , jobObj * batchv1.Job ) error {
3510
+ // cleanUp removes the specified pod finalizers, then deletes all pods and the job.
3511
+ func cleanUp (ctx context.Context , clientSet clientset.Interface , jobObj * batchv1.Job , podFinalizersToRemove []string ) error {
3512
+ if err := removePodsFinalizers (ctx , clientSet , jobObj .Namespace , podFinalizersToRemove ); err != nil {
3513
+ return err
3514
+ }
3489
3515
// Clean up pods in pages, because DeleteCollection might timeout.
3490
3516
// #90743
3491
3517
for {
@@ -3505,14 +3531,18 @@ func cleanUp(ctx context.Context, clientSet clientset.Interface, jobObj *batchv1
3505
3531
return err
3506
3532
}
3507
3533
}
3508
- return clientSet .BatchV1 ().Jobs (jobObj .Namespace ).Delete (ctx , jobObj .Name , metav1.DeleteOptions {})
3534
+
3535
+ // Set the propagation policy to background to ensure that the job doesn't receive any finalizer at deletion time
3536
+ return clientSet .BatchV1 ().Jobs (jobObj .Namespace ).Delete (ctx , jobObj .Name , metav1.DeleteOptions {
3537
+ PropagationPolicy : ptr .To (metav1 .DeletePropagationBackground ),
3538
+ })
3509
3539
}
3510
3540
3511
3541
func TestOrphanPodsFinalizersClearedWithGC (t * testing.T ) {
3542
+ closeFn , restConfig , clientSet , ns := setup (t , "orphan-pod-finalizers" )
3543
+ t .Cleanup (closeFn )
3512
3544
for _ , policy := range []metav1.DeletionPropagation {metav1 .DeletePropagationOrphan , metav1 .DeletePropagationBackground , metav1 .DeletePropagationForeground } {
3513
3545
t .Run (string (policy ), func (t * testing.T ) {
3514
- closeFn , restConfig , clientSet , ns := setup (t , "simple" )
3515
- defer closeFn ()
3516
3546
informerSet := informers .NewSharedInformerFactory (clientset .NewForConfigOrDie (restclient .AddUserAgent (restConfig , "controller-informers" )), 0 )
3517
3547
// Make the job controller significantly slower to trigger race condition.
3518
3548
restConfig .QPS = 1
@@ -3821,11 +3851,11 @@ func TestSuspendJob(t *testing.T) {
3821
3851
},
3822
3852
}
3823
3853
3854
+ closeFn , restConfig , clientSet , ns := setup (t , "suspend" )
3855
+ t .Cleanup (closeFn )
3824
3856
for _ , tc := range testCases {
3825
3857
name := fmt .Sprintf ("feature=%v,create=%v,update=%v" , tc .featureGate , tc .create .flag , tc .update .flag )
3826
3858
t .Run (name , func (t * testing.T ) {
3827
- closeFn , restConfig , clientSet , ns := setup (t , "suspend" )
3828
- defer closeFn ()
3829
3859
ctx , cancel := startJobControllerAndWaitForCaches (t , restConfig )
3830
3860
defer cancel ()
3831
3861
events , err := clientSet .EventsV1 ().Events (ns .Name ).Watch (ctx , metav1.ListOptions {})
@@ -4341,7 +4371,7 @@ func getCompletionIndex(p *v1.Pod) (int, error) {
4341
4371
4342
4372
func createJobWithDefaults (ctx context.Context , clientSet clientset.Interface , ns string , jobObj * batchv1.Job ) (* batchv1.Job , error ) {
4343
4373
if jobObj .Name == "" {
4344
- jobObj .Name = "test-job"
4374
+ jobObj .GenerateName = "test-job"
4345
4375
}
4346
4376
if len (jobObj .Spec .Template .Spec .Containers ) == 0 {
4347
4377
jobObj .Spec .Template .Spec .Containers = []v1.Container {
@@ -4476,23 +4506,25 @@ func deletePods(ctx context.Context, t *testing.T, clientSet clientset.Interface
4476
4506
}
4477
4507
}
4478
4508
4479
- func removePodsFinalizer (ctx context.Context , t * testing.T , clientSet clientset.Interface , namespace string ) {
4480
- t .Helper ()
4509
+ func removePodsFinalizers (ctx context.Context , clientSet clientset.Interface , namespace string , finalizersNames []string ) error {
4481
4510
pods , err := clientSet .CoreV1 ().Pods (namespace ).List (ctx , metav1.ListOptions {})
4482
4511
if err != nil {
4483
- t . Fatalf ( "Failed to list pods: %v" , err )
4512
+ return err
4484
4513
}
4485
- updatePod (ctx , t , clientSet , pods .Items , func (pod * v1.Pod ) {
4486
- for i , finalizer := range pod .Finalizers {
4487
- if finalizer == "fake.example.com/blockDeletion" {
4488
- pod .Finalizers = append (pod .Finalizers [:i ], pod .Finalizers [i + 1 :]... )
4514
+
4515
+ finalizersSet := sets .New (finalizersNames ... )
4516
+ return updatePod (ctx , clientSet , pods .Items , func (pod * v1.Pod ) {
4517
+ podFinalizers := []string {}
4518
+ for _ , podFinalizer := range pod .Finalizers {
4519
+ if _ , found := finalizersSet [podFinalizer ]; ! found {
4520
+ podFinalizers = append (podFinalizers , podFinalizer )
4489
4521
}
4490
4522
}
4523
+ pod .Finalizers = podFinalizers
4491
4524
})
4492
4525
}
4493
4526
4494
- func updatePod (ctx context.Context , t * testing.T , clientSet clientset.Interface , pods []v1.Pod , updateFunc func (* v1.Pod )) {
4495
- t .Helper ()
4527
+ func updatePod (ctx context.Context , clientSet clientset.Interface , pods []v1.Pod , updateFunc func (* v1.Pod )) error {
4496
4528
for _ , val := range pods {
4497
4529
if err := retry .RetryOnConflict (retry .DefaultBackoff , func () error {
4498
4530
newPod , err := clientSet .CoreV1 ().Pods (val .Namespace ).Get (ctx , val .Name , metav1.GetOptions {})
@@ -4503,9 +4535,10 @@ func updatePod(ctx context.Context, t *testing.T, clientSet clientset.Interface,
4503
4535
_ , err = clientSet .CoreV1 ().Pods (val .Namespace ).Update (ctx , newPod , metav1.UpdateOptions {})
4504
4536
return err
4505
4537
}); err != nil {
4506
- t . Fatalf ( "Failed to update pod %s: %v" , val . Name , err )
4538
+ return err
4507
4539
}
4508
4540
}
4541
+ return nil
4509
4542
}
4510
4543
4511
4544
func failTerminatingPods (ctx context.Context , t * testing.T , clientSet clientset.Interface , namespace string ) {
0 commit comments