@@ -424,16 +424,17 @@ func TestJobPodFailurePolicy(t *testing.T) {
424
424
},
425
425
},
426
426
}
427
+
428
+ closeFn , restConfig , clientSet , ns := setup (t , "pod-failure-policy" )
429
+ t .Cleanup (closeFn )
427
430
for name , test := range testCases {
428
431
t .Run (name , func (t * testing.T ) {
429
432
resetMetrics ()
430
433
431
- closeFn , restConfig , clientSet , ns := setup (t , "simple" )
432
- defer closeFn ()
433
434
ctx , cancel := startJobControllerAndWaitForCaches (t , restConfig )
434
- defer func () {
435
+ t . Cleanup ( func () {
435
436
cancel ()
436
- }( )
437
+ })
437
438
438
439
jobObj , err := createJobWithDefaults (ctx , clientSet , ns .Name , & test .job )
439
440
if err != nil {
@@ -758,18 +759,18 @@ func TestSuccessPolicy(t *testing.T) {
758
759
wantConditionTypes : []batchv1.JobConditionType {batchv1 .JobFailed },
759
760
},
760
761
}
762
+
763
+ closeFn , restConfig , clientSet , ns := setup (t , "success-policy" )
764
+ t .Cleanup (closeFn )
761
765
for name , tc := range testCases {
762
766
t .Run (name , func (t * testing.T ) {
763
767
resetMetrics ()
764
768
featuregatetesting .SetFeatureGateDuringTest (t , feature .DefaultFeatureGate , features .JobSuccessPolicy , tc .enableJobSuccessPolicy )
765
769
featuregatetesting .SetFeatureGateDuringTest (t , feature .DefaultFeatureGate , features .JobBackoffLimitPerIndex , tc .enableBackoffLimitPerIndex )
766
770
767
- closeFn , restConfig , clientSet , ns := setup (t , "simple" )
768
- defer closeFn ()
769
771
ctx , cancel := startJobControllerAndWaitForCaches (t , restConfig )
770
- defer func () {
771
- cancel ()
772
- }()
772
+ t .Cleanup (cancel )
773
+
773
774
jobObj , err := createJobWithDefaults (ctx , clientSet , ns .Name , & tc .job )
774
775
if err != nil {
775
776
t .Fatalf ("Error %v while creating the Job %q" , err , jobObj .Name )
@@ -1177,11 +1178,12 @@ func TestBackoffLimitPerIndex_JobPodsCreatedWithExponentialBackoff(t *testing.T)
1177
1178
// are terminal. The fate of the Job is indicated by the interim Job conditions:
1178
1179
// FailureTarget, or SuccessCriteriaMet.
1179
1180
func TestDelayTerminalPhaseCondition (t * testing.T ) {
1181
+ const blockDeletionFinalizerForTest string = "fake.example.com/blockDeletion"
1180
1182
t .Cleanup (setDurationDuringTest (& jobcontroller .DefaultJobPodFailureBackOff , fastPodFailureBackoff ))
1181
1183
1182
1184
podTemplateSpec := v1.PodTemplateSpec {
1183
1185
ObjectMeta : metav1.ObjectMeta {
1184
- Finalizers : []string {"fake.example.com/blockDeletion" },
1186
+ Finalizers : []string {blockDeletionFinalizerForTest },
1185
1187
},
1186
1188
Spec : v1.PodSpec {
1187
1189
Containers : []v1.Container {
@@ -1512,6 +1514,9 @@ func TestDelayTerminalPhaseCondition(t *testing.T) {
1512
1514
},
1513
1515
},
1514
1516
}
1517
+
1518
+ closeFn , restConfig , clientSet , ns := setup (t , "delay-terminal-condition" )
1519
+ t .Cleanup (closeFn )
1515
1520
for name , test := range testCases {
1516
1521
t .Run (name , func (t * testing.T ) {
1517
1522
resetMetrics ()
@@ -1520,16 +1525,18 @@ func TestDelayTerminalPhaseCondition(t *testing.T) {
1520
1525
featuregatetesting .SetFeatureGateDuringTest (t , feature .DefaultFeatureGate , features .ElasticIndexedJob , true )
1521
1526
featuregatetesting .SetFeatureGateDuringTest (t , feature .DefaultFeatureGate , features .JobSuccessPolicy , test .enableJobSuccessPolicy )
1522
1527
1523
- closeFn , restConfig , clientSet , ns := setup (t , "delay-terminal-condition" )
1524
- t .Cleanup (closeFn )
1525
1528
ctx , cancel := startJobControllerAndWaitForCaches (t , restConfig )
1526
1529
t .Cleanup (cancel )
1527
1530
1528
1531
jobObj , err := createJobWithDefaults (ctx , clientSet , ns .Name , & test .job )
1529
1532
if err != nil {
1530
1533
t .Fatalf ("Error %q while creating the job %q" , err , jobObj .Name )
1531
1534
}
1532
- t .Cleanup (func () { removePodsFinalizer (ctx , t , clientSet , ns .Name ) })
1535
+ t .Cleanup (func () {
1536
+ if err := cleanUp (ctx , clientSet , jobObj , []string {blockDeletionFinalizerForTest , batchv1 .JobTrackingFinalizer }); err != nil {
1537
+ t .Fatalf ("Failed cleanup: %v" , err )
1538
+ }
1539
+ })
1533
1540
jobClient := clientSet .BatchV1 ().Jobs (jobObj .Namespace )
1534
1541
1535
1542
waitForPodsToBeActive (ctx , t , jobClient , * jobObj .Spec .Parallelism , jobObj )
@@ -1898,17 +1905,17 @@ func TestBackoffLimitPerIndex(t *testing.T) {
1898
1905
},
1899
1906
},
1900
1907
}
1908
+
1909
+ closeFn , restConfig , clientSet , ns := setup (t , "backoff-limit-per-index" )
1910
+ t .Cleanup (closeFn )
1901
1911
for name , test := range testCases {
1902
1912
t .Run (name , func (t * testing.T ) {
1903
1913
resetMetrics ()
1904
1914
featuregatetesting .SetFeatureGateDuringTest (t , feature .DefaultFeatureGate , features .JobBackoffLimitPerIndex , true )
1905
1915
1906
- closeFn , restConfig , clientSet , ns := setup (t , "simple" )
1907
- defer closeFn ()
1908
1916
ctx , cancel := startJobControllerAndWaitForCaches (t , restConfig )
1909
- defer func () {
1910
- cancel ()
1911
- }()
1917
+ t .Cleanup (cancel )
1918
+
1912
1919
jobObj , err := createJobWithDefaults (ctx , clientSet , ns .Name , & test .job )
1913
1920
if err != nil {
1914
1921
t .Fatalf ("Error %q while creating the job %q" , err , jobObj .Name )
@@ -1969,6 +1976,7 @@ func TestBackoffLimitPerIndex(t *testing.T) {
1969
1976
// reconcile or skip reconciliation of the Job depending on the Job's managedBy
1970
1977
// field, and the enablement of the JobManagedBy feature gate.
1971
1978
func TestManagedBy (t * testing.T ) {
1979
+ const blockDeletionFinalizerForTest string = "fake.example.com/blockDeletion"
1972
1980
customControllerName := "example.com/custom-job-controller"
1973
1981
podTemplateSpec := v1.PodTemplateSpec {
1974
1982
Spec : v1.PodSpec {
@@ -2061,20 +2069,29 @@ func TestManagedBy(t *testing.T) {
2061
2069
},
2062
2070
},
2063
2071
}
2072
+
2073
+ closeFn , restConfig , clientSet , ns := setup (t , "managed-by" )
2074
+ t .Cleanup (closeFn )
2064
2075
for name , test := range testCases {
2065
2076
t .Run (name , func (t * testing.T ) {
2066
2077
resetMetrics ()
2067
2078
featuregatetesting .SetFeatureGateDuringTest (t , feature .DefaultFeatureGate , features .JobManagedBy , test .enableJobManagedBy )
2068
2079
2069
- closeFn , restConfig , clientSet , ns := setup (t , "managed-by" )
2070
- defer closeFn ()
2071
2080
ctx , cancel := startJobControllerAndWaitForCaches (t , restConfig )
2072
- defer cancel ()
2081
+ t .Cleanup (cancel )
2082
+
2073
2083
jobObj , err := createJobWithDefaults (ctx , clientSet , ns .Name , & test .job )
2074
2084
if err != nil {
2075
2085
t .Fatalf ("Error %v while creating the job %q" , err , klog .KObj (jobObj ))
2076
2086
}
2077
2087
2088
+ t .Cleanup (func () {
2089
+ // Wait for cleanup to finish to prevent this job from affecting metrics
2090
+ if err := cleanUp (ctx , clientSet , jobObj , []string {blockDeletionFinalizerForTest , batchv1 .JobTrackingFinalizer }); err != nil {
2091
+ t .Fatalf ("Failed cleanup: %v" , err )
2092
+ }
2093
+ })
2094
+
2078
2095
if test .wantReconciledByBuiltInController {
2079
2096
validateJobPodsStatus (ctx , t , clientSet , jobObj , podsByStatus {
2080
2097
Active : int (* jobObj .Spec .Parallelism ),
@@ -2814,6 +2831,7 @@ func TestIndexedJob(t *testing.T) {
2814
2831
}
2815
2832
2816
2833
func TestJobPodReplacementPolicy (t * testing.T ) {
2834
+ const blockDeletionFinalizerForTest string = "fake.example.com/blockDeletion"
2817
2835
t .Cleanup (setDurationDuringTest (& jobcontroller .DefaultJobPodFailureBackOff , fastPodFailureBackoff ))
2818
2836
indexedCompletion := batchv1 .IndexedCompletion
2819
2837
nonIndexedCompletion := batchv1 .NonIndexedCompletion
@@ -2844,7 +2862,7 @@ func TestJobPodReplacementPolicy(t *testing.T) {
2844
2862
CompletionMode : & indexedCompletion ,
2845
2863
Template : v1.PodTemplateSpec {
2846
2864
ObjectMeta : metav1.ObjectMeta {
2847
- Finalizers : []string {"fake.example.com/blockDeletion" },
2865
+ Finalizers : []string {blockDeletionFinalizerForTest },
2848
2866
},
2849
2867
},
2850
2868
},
@@ -2869,7 +2887,7 @@ func TestJobPodReplacementPolicy(t *testing.T) {
2869
2887
PodReplacementPolicy : podReplacementPolicy (batchv1 .TerminatingOrFailed ),
2870
2888
Template : v1.PodTemplateSpec {
2871
2889
ObjectMeta : metav1.ObjectMeta {
2872
- Finalizers : []string {"fake.example.com/blockDeletion" },
2890
+ Finalizers : []string {blockDeletionFinalizerForTest },
2873
2891
},
2874
2892
},
2875
2893
},
@@ -2897,7 +2915,7 @@ func TestJobPodReplacementPolicy(t *testing.T) {
2897
2915
PodReplacementPolicy : podReplacementPolicy (batchv1 .TerminatingOrFailed ),
2898
2916
Template : v1.PodTemplateSpec {
2899
2917
ObjectMeta : metav1.ObjectMeta {
2900
- Finalizers : []string {"fake.example.com/blockDeletion" },
2918
+ Finalizers : []string {blockDeletionFinalizerForTest },
2901
2919
},
2902
2920
},
2903
2921
},
@@ -2925,7 +2943,7 @@ func TestJobPodReplacementPolicy(t *testing.T) {
2925
2943
PodReplacementPolicy : podReplacementPolicy (batchv1 .Failed ),
2926
2944
Template : v1.PodTemplateSpec {
2927
2945
ObjectMeta : metav1.ObjectMeta {
2928
- Finalizers : []string {"fake.example.com/blockDeletion" },
2946
+ Finalizers : []string {blockDeletionFinalizerForTest },
2929
2947
},
2930
2948
},
2931
2949
PodFailurePolicy : & batchv1.PodFailurePolicy {
@@ -2959,7 +2977,7 @@ func TestJobPodReplacementPolicy(t *testing.T) {
2959
2977
PodReplacementPolicy : podReplacementPolicy (batchv1 .Failed ),
2960
2978
Template : v1.PodTemplateSpec {
2961
2979
ObjectMeta : metav1.ObjectMeta {
2962
- Finalizers : []string {"fake.example.com/blockDeletion" },
2980
+ Finalizers : []string {blockDeletionFinalizerForTest },
2963
2981
},
2964
2982
},
2965
2983
},
@@ -2987,7 +3005,7 @@ func TestJobPodReplacementPolicy(t *testing.T) {
2987
3005
PodReplacementPolicy : podReplacementPolicy (batchv1 .Failed ),
2988
3006
Template : v1.PodTemplateSpec {
2989
3007
ObjectMeta : metav1.ObjectMeta {
2990
- Finalizers : []string {"fake.example.com/blockDeletion" },
3008
+ Finalizers : []string {blockDeletionFinalizerForTest },
2991
3009
},
2992
3010
},
2993
3011
},
@@ -3007,13 +3025,14 @@ func TestJobPodReplacementPolicy(t *testing.T) {
3007
3025
},
3008
3026
},
3009
3027
}
3028
+
3029
+ closeFn , restConfig , clientSet , ns := setup (t , "pod-replacement-policy" )
3030
+ t .Cleanup (closeFn )
3010
3031
for name , tc := range cases {
3011
3032
tc := tc
3012
3033
t .Run (name , func (t * testing.T ) {
3013
3034
featuregatetesting .SetFeatureGateDuringTest (t , feature .DefaultFeatureGate , features .JobPodReplacementPolicy , tc .podReplacementPolicyEnabled )
3014
3035
3015
- closeFn , restConfig , clientSet , ns := setup (t , "pod-replacement-policy" )
3016
- t .Cleanup (closeFn )
3017
3036
ctx , cancel := startJobControllerAndWaitForCaches (t , restConfig )
3018
3037
t .Cleanup (cancel )
3019
3038
resetMetrics ()
@@ -3027,7 +3046,11 @@ func TestJobPodReplacementPolicy(t *testing.T) {
3027
3046
jobClient := clientSet .BatchV1 ().Jobs (jobObj .Namespace )
3028
3047
3029
3048
waitForPodsToBeActive (ctx , t , jobClient , 2 , jobObj )
3030
- t .Cleanup (func () { removePodsFinalizer (ctx , t , clientSet , ns .Name ) })
3049
+ t .Cleanup (func () {
3050
+ if err := cleanUp (ctx , clientSet , jobObj , []string {blockDeletionFinalizerForTest , batchv1 .JobTrackingFinalizer }); err != nil {
3051
+ t .Fatalf ("Failed cleanup: %v" , err )
3052
+ }
3053
+ })
3031
3054
3032
3055
deletePods (ctx , t , clientSet , ns .Name )
3033
3056
@@ -3218,11 +3241,11 @@ func TestElasticIndexedJob(t *testing.T) {
3218
3241
},
3219
3242
}
3220
3243
3244
+ closeFn , restConfig , clientSet , ns := setup (t , "indexed" )
3245
+ t .Cleanup (closeFn )
3221
3246
for name , tc := range cases {
3222
3247
tc := tc
3223
3248
t .Run (name , func (t * testing.T ) {
3224
- closeFn , restConfig , clientSet , ns := setup (t , "indexed" )
3225
- defer closeFn ()
3226
3249
ctx , cancel := startJobControllerAndWaitForCaches (t , restConfig )
3227
3250
defer cancel ()
3228
3251
resetMetrics ()
@@ -3357,7 +3380,7 @@ func BenchmarkLargeIndexedJob(b *testing.B) {
3357
3380
b .Fatalf ("Failed to create Job: %v" , err )
3358
3381
}
3359
3382
b .Cleanup (func () {
3360
- if err := cleanUp (ctx , clientSet , jobObj ); err != nil {
3383
+ if err := cleanUp (ctx , clientSet , jobObj , [] string { batchv1 . JobTrackingFinalizer } ); err != nil {
3361
3384
b .Fatalf ("Failed cleanup: %v" , err )
3362
3385
}
3363
3386
})
@@ -3443,7 +3466,7 @@ func BenchmarkLargeFailureHandling(b *testing.B) {
3443
3466
b .Fatalf ("Failed to create Job: %v" , err )
3444
3467
}
3445
3468
b .Cleanup (func () {
3446
- if err := cleanUp (ctx , clientSet , jobObj ); err != nil {
3469
+ if err := cleanUp (ctx , clientSet , jobObj , [] string { batchv1 . JobTrackingFinalizer } ); err != nil {
3447
3470
b .Fatalf ("Failed cleanup: %v" , err )
3448
3471
}
3449
3472
})
@@ -3477,8 +3500,11 @@ func BenchmarkLargeFailureHandling(b *testing.B) {
3477
3500
}
3478
3501
}
3479
3502
3480
- // cleanUp deletes all pods and the job
3481
- func cleanUp (ctx context.Context , clientSet clientset.Interface , jobObj * batchv1.Job ) error {
3503
+ // cleanUp removes the specified pod finalizers, then deletes all pods and the job.
3504
+ func cleanUp (ctx context.Context , clientSet clientset.Interface , jobObj * batchv1.Job , podFinalizersToRemove []string ) error {
3505
+ if err := removePodsFinalizers (ctx , clientSet , jobObj .Namespace , podFinalizersToRemove ); err != nil {
3506
+ return err
3507
+ }
3482
3508
// Clean up pods in pages, because DeleteCollection might timeout.
3483
3509
// #90743
3484
3510
for {
@@ -3498,14 +3524,18 @@ func cleanUp(ctx context.Context, clientSet clientset.Interface, jobObj *batchv1
3498
3524
return err
3499
3525
}
3500
3526
}
3501
- return clientSet .BatchV1 ().Jobs (jobObj .Namespace ).Delete (ctx , jobObj .Name , metav1.DeleteOptions {})
3527
+
3528
+ // Set the propagation policy to background to ensure that the job doesn't receive any finalizer at deletion time
3529
+ return clientSet .BatchV1 ().Jobs (jobObj .Namespace ).Delete (ctx , jobObj .Name , metav1.DeleteOptions {
3530
+ PropagationPolicy : ptr .To (metav1 .DeletePropagationBackground ),
3531
+ })
3502
3532
}
3503
3533
3504
3534
func TestOrphanPodsFinalizersClearedWithGC (t * testing.T ) {
3535
+ closeFn , restConfig , clientSet , ns := setup (t , "orphan-pod-finalizers" )
3536
+ t .Cleanup (closeFn )
3505
3537
for _ , policy := range []metav1.DeletionPropagation {metav1 .DeletePropagationOrphan , metav1 .DeletePropagationBackground , metav1 .DeletePropagationForeground } {
3506
3538
t .Run (string (policy ), func (t * testing.T ) {
3507
- closeFn , restConfig , clientSet , ns := setup (t , "simple" )
3508
- defer closeFn ()
3509
3539
informerSet := informers .NewSharedInformerFactory (clientset .NewForConfigOrDie (restclient .AddUserAgent (restConfig , "controller-informers" )), 0 )
3510
3540
// Make the job controller significantly slower to trigger race condition.
3511
3541
restConfig .QPS = 1
@@ -3814,11 +3844,11 @@ func TestSuspendJob(t *testing.T) {
3814
3844
},
3815
3845
}
3816
3846
3847
+ closeFn , restConfig , clientSet , ns := setup (t , "suspend" )
3848
+ t .Cleanup (closeFn )
3817
3849
for _ , tc := range testCases {
3818
3850
name := fmt .Sprintf ("feature=%v,create=%v,update=%v" , tc .featureGate , tc .create .flag , tc .update .flag )
3819
3851
t .Run (name , func (t * testing.T ) {
3820
- closeFn , restConfig , clientSet , ns := setup (t , "suspend" )
3821
- defer closeFn ()
3822
3852
ctx , cancel := startJobControllerAndWaitForCaches (t , restConfig )
3823
3853
defer cancel ()
3824
3854
events , err := clientSet .EventsV1 ().Events (ns .Name ).Watch (ctx , metav1.ListOptions {})
@@ -4333,7 +4363,7 @@ func getCompletionIndex(p *v1.Pod) (int, error) {
4333
4363
4334
4364
func createJobWithDefaults (ctx context.Context , clientSet clientset.Interface , ns string , jobObj * batchv1.Job ) (* batchv1.Job , error ) {
4335
4365
if jobObj .Name == "" {
4336
- jobObj .Name = "test-job"
4366
+ jobObj .GenerateName = "test-job"
4337
4367
}
4338
4368
if len (jobObj .Spec .Template .Spec .Containers ) == 0 {
4339
4369
jobObj .Spec .Template .Spec .Containers = []v1.Container {
@@ -4468,23 +4498,25 @@ func deletePods(ctx context.Context, t *testing.T, clientSet clientset.Interface
4468
4498
}
4469
4499
}
4470
4500
4471
- func removePodsFinalizer (ctx context.Context , t * testing.T , clientSet clientset.Interface , namespace string ) {
4472
- t .Helper ()
4501
+ func removePodsFinalizers (ctx context.Context , clientSet clientset.Interface , namespace string , finalizersNames []string ) error {
4473
4502
pods , err := clientSet .CoreV1 ().Pods (namespace ).List (ctx , metav1.ListOptions {})
4474
4503
if err != nil {
4475
- t . Fatalf ( "Failed to list pods: %v" , err )
4504
+ return err
4476
4505
}
4477
- updatePod (ctx , t , clientSet , pods .Items , func (pod * v1.Pod ) {
4478
- for i , finalizer := range pod .Finalizers {
4479
- if finalizer == "fake.example.com/blockDeletion" {
4480
- pod .Finalizers = append (pod .Finalizers [:i ], pod .Finalizers [i + 1 :]... )
4506
+
4507
+ finalizersSet := sets .New (finalizersNames ... )
4508
+ return updatePod (ctx , clientSet , pods .Items , func (pod * v1.Pod ) {
4509
+ podFinalizers := []string {}
4510
+ for _ , podFinalizer := range pod .Finalizers {
4511
+ if _ , found := finalizersSet [podFinalizer ]; ! found {
4512
+ podFinalizers = append (podFinalizers , podFinalizer )
4481
4513
}
4482
4514
}
4515
+ pod .Finalizers = podFinalizers
4483
4516
})
4484
4517
}
4485
4518
4486
- func updatePod (ctx context.Context , t * testing.T , clientSet clientset.Interface , pods []v1.Pod , updateFunc func (* v1.Pod )) {
4487
- t .Helper ()
4519
+ func updatePod (ctx context.Context , clientSet clientset.Interface , pods []v1.Pod , updateFunc func (* v1.Pod )) error {
4488
4520
for _ , val := range pods {
4489
4521
if err := retry .RetryOnConflict (retry .DefaultBackoff , func () error {
4490
4522
newPod , err := clientSet .CoreV1 ().Pods (val .Namespace ).Get (ctx , val .Name , metav1.GetOptions {})
@@ -4495,9 +4527,10 @@ func updatePod(ctx context.Context, t *testing.T, clientSet clientset.Interface,
4495
4527
_ , err = clientSet .CoreV1 ().Pods (val .Namespace ).Update (ctx , newPod , metav1.UpdateOptions {})
4496
4528
return err
4497
4529
}); err != nil {
4498
- t . Fatalf ( "Failed to update pod %s: %v" , val . Name , err )
4530
+ return err
4499
4531
}
4500
4532
}
4533
+ return nil
4501
4534
}
4502
4535
4503
4536
func failTerminatingPods (ctx context.Context , t * testing.T , clientSet clientset.Interface , namespace string ) {
0 commit comments