@@ -11,6 +11,7 @@ import (
1111
1212 batchv1 "k8s.io/api/batch/v1"
1313 corev1 "k8s.io/api/core/v1"
14+ apierrors "k8s.io/apimachinery/pkg/api/errors"
1415 "k8s.io/apimachinery/pkg/api/meta"
1516 "k8s.io/apimachinery/pkg/api/resource"
1617 metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
@@ -76,14 +77,51 @@ func verifyCatalogEndpoint(ctx SpecContext, catalog, endpoint, query string) {
7677 strings .ReplaceAll (endpoint , "?" , "" ),
7778 strings .ReplaceAll (catalog , "-" , "" ))
7879
79- job := buildCurlJob (jobNamePrefix , "default" , serviceURL )
80- err = k8sClient .Create (ctx , job )
81- Expect (err ).NotTo (HaveOccurred (), "failed to create Job" )
80+ // Create the ServiceAccount first
81+ serviceAccount := & corev1.ServiceAccount {
82+ ObjectMeta : metav1.ObjectMeta {
83+ Name : jobNamePrefix ,
84+ Namespace : "default" ,
85+ },
86+ }
87+
88+ // Create the Job
89+ job := buildCurlJob (jobNamePrefix , "default" , serviceURL , serviceAccount .Name )
8290
8391 DeferCleanup (func (ctx SpecContext ) {
84- _ = k8sClient .Delete (ctx , job )
92+ // Force delete job with zero grace period to ensure cleanup doesn't hang
93+ // Use Foreground propagation to ensure Pods are deleted before the Job is removed,
94+ // guaranteeing the ServiceAccount isn't deleted while Pods are still using it
95+ deletePolicy := metav1 .DeletePropagationForeground
96+ gracePeriod := int64 (0 )
97+ // Poll for service account deletion - in case we have race condtions
98+ // or a bad API call.
99+ Eventually (func (ctx SpecContext ) error {
100+ err := k8sClient .Delete (ctx , job , & client.DeleteOptions {
101+ GracePeriodSeconds : & gracePeriod ,
102+ PropagationPolicy : & deletePolicy ,
103+ })
104+ return client .IgnoreNotFound (err )
105+ }).WithTimeout (helpers .DefaultTimeout ).WithPolling (helpers .DefaultPolling ).Should (Succeed ())
106+ // While the delete call may be successful, we need to ensure the deletion itself has
107+ // occurred first before deleting the service account.
108+ Eventually (func (g Gomega ) {
109+ err := k8sClient .Get (ctx , client .ObjectKeyFromObject (job ), & batchv1.Job {})
110+ g .Expect (err ).To (WithTransform (apierrors .IsNotFound , BeTrue ()), "Expected a 'NotFound' error, but got: %v" , err )
111+ }).WithTimeout (helpers .DefaultTimeout ).WithPolling (helpers .DefaultPolling ).Should (Succeed ())
112+ // We should also poll for service account deletion too.
113+ Eventually (func (ctx SpecContext ) error {
114+ err = k8sClient .Delete (ctx , serviceAccount )
115+ return client .IgnoreNotFound (err )
116+ }).WithTimeout (helpers .DefaultTimeout ).WithPolling (helpers .DefaultPolling ).Should (Succeed ())
85117 })
86118
119+ err = k8sClient .Create (ctx , serviceAccount )
120+ Expect (err ).NotTo (HaveOccurred (), "failed to create ServiceAccount" )
121+
122+ err = k8sClient .Create (ctx , job )
123+ Expect (err ).NotTo (HaveOccurred (), "failed to create Job" )
124+
87125 By ("Waiting for Job to succeed" )
88126 Eventually (func (g Gomega ) {
89127 recheck := & batchv1.Job {}
@@ -94,7 +132,7 @@ func verifyCatalogEndpoint(ctx SpecContext, catalog, endpoint, query string) {
94132 return
95133 }
96134 if c .Type == batchv1 .JobFailed && c .Status == corev1 .ConditionTrue {
97- Fail (fmt .Sprintf ("Job failed: %s" , c .Message ))
135+ StopTrying (fmt .Sprintf ("Job failed: %s" , c .Message )). Now ( )
98136 }
99137 }
100138 }).WithTimeout (helpers .DefaultTimeout ).WithPolling (helpers .DefaultPolling ).Should (Succeed ())
@@ -203,7 +241,7 @@ var _ = Describe("[sig-olmv1][OCPFeatureGate:NewOLM][Skipped:Disconnected] OLMv1
203241 })
204242})
205243
206- func buildCurlJob (prefix , namespace , url string ) * batchv1.Job {
244+ func buildCurlJob (prefix , namespace , url , serviceAccountName string ) * batchv1.Job {
207245 backoff := int32 (1 )
208246 // This means the k8s garbage collector will automatically delete the job 5 minutes
209247 // after it has completed or failed.
@@ -232,7 +270,8 @@ func buildCurlJob(prefix, namespace, url string) *batchv1.Job {
232270 BackoffLimit : & backoff ,
233271 Template : corev1.PodTemplateSpec {
234272 Spec : corev1.PodSpec {
235- RestartPolicy : corev1 .RestartPolicyNever ,
273+ ServiceAccountName : serviceAccountName ,
274+ RestartPolicy : corev1 .RestartPolicyNever ,
236275 Containers : []corev1.Container {{
237276 Name : "api-tester" ,
238277 Image : "registry.redhat.io/rhel8/httpd-24:latest" ,
0 commit comments