@@ -66,13 +66,39 @@ func (h *HCHandler) RemoveHCP(timeout time.Duration) error {
66
66
log .Printf ("\t Waiting for the HC to be deleted" )
67
67
err := wait .PollUntilContextTimeout (h .Ctx , time .Second * 5 , timeout , true , func (ctx context.Context ) (bool , error ) {
68
68
log .Printf ("\t Attempting to verify HC deletion..." )
69
- result := IsHCDeleted (h )
70
- log .Printf ("\t HC deletion check result: %v" , result )
71
- return result , nil
69
+ deleted , err := IsHCDeleted (h )
70
+ if err != nil {
71
+ log .Printf ("\t HC deletion check error: %v" , err )
72
+ return false , err
73
+ }
74
+ log .Printf ("\t HC deletion check result: %v" , deleted )
75
+ return deleted , nil
72
76
})
73
77
74
78
if err != nil {
75
- return fmt .Errorf ("failed to wait for HC deletion: %v" , err )
79
+ log .Printf ("HC deletion timed out, attempting to nuke resources with finalizers" )
80
+ if nukeErr := h .NukeHostedCluster (); nukeErr != nil {
81
+ return fmt .Errorf ("failed to wait for HC deletion (timeout: %v) and failed to nuke resources: %v" , err , nukeErr )
82
+ }
83
+
84
+ // Try deletion again after nuking finalizers
85
+ log .Printf ("Retrying HC deletion after removing finalizers" )
86
+ retryErr := wait .PollUntilContextTimeout (h .Ctx , time .Second * 5 , time .Minute * 5 , true , func (ctx context.Context ) (bool , error ) {
87
+ log .Printf ("\t Retry: Attempting to verify HC deletion..." )
88
+ deleted , err := IsHCDeleted (h )
89
+ if err != nil {
90
+ log .Printf ("\t Retry: HC deletion check error: %v" , err )
91
+ return false , err
92
+ }
93
+ log .Printf ("\t Retry: HC deletion check result: %v" , deleted )
94
+ return deleted , nil
95
+ })
96
+
97
+ if retryErr != nil {
98
+ return fmt .Errorf ("failed to wait for HC deletion even after removing finalizers (original timeout: %v, retry error: %v)" , err , retryErr )
99
+ }
100
+
101
+ log .Printf ("\t HC successfully deleted after removing finalizers" )
76
102
}
77
103
78
104
return nil
@@ -221,22 +247,76 @@ func (h *HCHandler) DeleteHCSecrets() error {
221
247
222
248
// WaitForHCDeletion waits for the HostedCluster to be deleted
223
249
func (h * HCHandler ) WaitForHCDeletion () error {
224
- return wait .PollUntilContextTimeout (h .Ctx , WaitForNextCheckTimeout , Wait10Min , true , func (ctx context.Context ) (bool , error ) {
225
- return IsHCDeleted (h ), nil
250
+ err := wait .PollUntilContextTimeout (h .Ctx , WaitForNextCheckTimeout , Wait10Min , true , func (ctx context.Context ) (bool , error ) {
251
+ deleted , err := IsHCDeleted (h )
252
+ if err != nil {
253
+ // Return the error to stop polling and propagate the error details
254
+ return false , err
255
+ }
256
+ return deleted , nil
226
257
})
258
+
259
+ if err != nil {
260
+ log .Printf ("HC deletion timed out in WaitForHCDeletion, attempting to nuke resources with finalizers" )
261
+ if nukeErr := h .NukeHostedCluster (); nukeErr != nil {
262
+ return fmt .Errorf ("failed to wait for HC deletion (timeout: %v) and failed to nuke resources: %v" , err , nukeErr )
263
+ }
264
+
265
+ // Try deletion again after nuking finalizers
266
+ log .Printf ("Retrying HC deletion after removing finalizers in WaitForHCDeletion" )
267
+ retryErr := wait .PollUntilContextTimeout (h .Ctx , WaitForNextCheckTimeout , time .Minute * 5 , true , func (ctx context.Context ) (bool , error ) {
268
+ deleted , err := IsHCDeleted (h )
269
+ if err != nil {
270
+ return false , err
271
+ }
272
+ return deleted , nil
273
+ })
274
+
275
+ if retryErr != nil {
276
+ return fmt .Errorf ("failed to wait for HC deletion even after removing finalizers (original timeout: %v, retry error: %v)" , err , retryErr )
277
+ }
278
+
279
+ log .Printf ("HC successfully deleted after removing finalizers in WaitForHCDeletion" )
280
+ }
281
+
282
+ return nil
227
283
}
228
284
229
285
// WaitForHCPDeletion waits for the HostedControlPlane to be deleted
230
286
func (h * HCHandler ) WaitForHCPDeletion (hcp * hypershiftv1.HostedControlPlane ) error {
231
287
return wait .PollUntilContextTimeout (h .Ctx , WaitForNextCheckTimeout , Wait10Min , true , func (ctx context.Context ) (bool , error ) {
232
- return IsHCPDeleted (h , hcp ), nil
288
+ deleted , err := IsHCPDeleted (h , hcp )
289
+ if err != nil {
290
+ // Return the error to stop polling and propagate the error details
291
+ return false , err
292
+ }
293
+ return deleted , nil
233
294
})
234
295
}
235
296
236
297
// NukeHostedCluster removes all resources associated with a HostedCluster
237
298
func (h * HCHandler ) NukeHostedCluster () error {
238
299
// List of resource types to check
239
300
log .Printf ("\t Nuking HostedCluster" )
301
+
302
+ // First, handle HostedCluster resources in the clusters namespace
303
+ if h .HostedCluster != nil {
304
+ log .Printf ("\t NUKE: Checking HostedCluster %s in namespace %s for finalizers" , h .HostedCluster .Name , h .HostedCluster .Namespace )
305
+ hc := & hypershiftv1.HostedCluster {}
306
+ err := h .Client .Get (h .Ctx , types.NamespacedName {
307
+ Name : h .HostedCluster .Name ,
308
+ Namespace : h .HostedCluster .Namespace ,
309
+ }, hc )
310
+ if err == nil && len (hc .GetFinalizers ()) > 0 {
311
+ log .Printf ("\t NUKE: Removing finalizers from HostedCluster %s" , hc .Name )
312
+ hc .SetFinalizers ([]string {})
313
+ if err := h .Client .Update (h .Ctx , hc ); err != nil {
314
+ return fmt .Errorf ("\t NUKE: Error removing finalizers from HostedCluster %s: %v" , hc .Name , err )
315
+ }
316
+ }
317
+ }
318
+
319
+ // Then handle other resources in the HCP namespace
240
320
resourceTypes := []struct {
241
321
kind string
242
322
gvk schema.GroupVersionKind
@@ -513,10 +593,10 @@ func handleDeploymentValidationFailure(ctx context.Context, ocClient client.Clie
513
593
}
514
594
515
595
// IsHCPDeleted checks if a HostedControlPlane has been deleted
516
- func IsHCPDeleted (h * HCHandler , hcp * hypershiftv1.HostedControlPlane ) bool {
596
+ func IsHCPDeleted (h * HCHandler , hcp * hypershiftv1.HostedControlPlane ) ( bool , error ) {
517
597
if hcp == nil {
518
598
log .Printf ("\t No HCP provided, assuming deleted" )
519
- return true
599
+ return true , nil
520
600
}
521
601
log .Printf ("\t Checking if HCP %s is deleted..." , hcp .Name )
522
602
newHCP := & hypershiftv1.HostedControlPlane {}
@@ -526,20 +606,20 @@ func IsHCPDeleted(h *HCHandler, hcp *hypershiftv1.HostedControlPlane) bool {
526
606
if err != nil {
527
607
if apierrors .IsNotFound (err ) {
528
608
log .Printf ("\t HCP %s is confirmed deleted" , hcp .Name )
529
- return true
609
+ return true , nil
530
610
}
531
611
log .Printf ("\t HCP %s deletion check failed with error: %v" , hcp .Name , err )
532
- return false
612
+ return false , fmt . Errorf ( "failed to check HCP deletion: %w" , err )
533
613
}
534
614
log .Printf ("\t HCP %s still exists" , hcp .Name )
535
- return false
615
+ return false , nil
536
616
}
537
617
538
618
// IsHCDeleted checks if a HostedCluster has been deleted
539
- func IsHCDeleted (h * HCHandler ) bool {
619
+ func IsHCDeleted (h * HCHandler ) ( bool , error ) {
540
620
if h .HostedCluster == nil {
541
621
log .Printf ("\t No HostedCluster provided, assuming deleted" )
542
- return true
622
+ return true , nil
543
623
}
544
624
log .Printf ("\t Checking if HC %s is deleted..." , h .HostedCluster .Name )
545
625
newHC := & hypershiftv1.HostedCluster {}
@@ -549,13 +629,13 @@ func IsHCDeleted(h *HCHandler) bool {
549
629
if err != nil {
550
630
if apierrors .IsNotFound (err ) {
551
631
log .Printf ("\t HC %s is confirmed deleted" , h .HostedCluster .Name )
552
- return true
632
+ return true , nil
553
633
}
554
634
log .Printf ("\t HC %s deletion check failed with error: %v" , h .HostedCluster .Name , err )
555
- return false
635
+ return false , fmt . Errorf ( "failed to check HC deletion: %w" , err )
556
636
}
557
637
log .Printf ("\t HC %s still exists" , h .HostedCluster .Name )
558
- return false
638
+ return false , nil
559
639
}
560
640
561
641
// GetHCPNamespace returns the namespace for a HostedControlPlane
0 commit comments