@@ -27,7 +27,9 @@ import (
27
27
snapshotterClientSet "github.com/kubernetes-csi/external-snapshotter/client/v8/clientset/versioned"
28
28
apierrors "k8s.io/apimachinery/pkg/api/errors"
29
29
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
30
+ "k8s.io/apimachinery/pkg/fields"
30
31
"k8s.io/apimachinery/pkg/util/wait"
32
+ "k8s.io/apimachinery/pkg/watch"
31
33
clientset "k8s.io/client-go/kubernetes"
32
34
33
35
"github.com/container-storage-interface/spec/lib/go/csi"
@@ -448,3 +450,103 @@ func WaitForVolumeSnapshotDeleted(ctx context.Context, client snapshotterClientS
448
450
449
451
return nil
450
452
}
453
+
454
+ // WaitForVolumeSnapshotDeletedWithWatch waits for a VolumeSnapshot to get deleted using Watch API instead of polling.
455
+ func WaitForVolumeSnapshotDeletedWithWatch (ctx context.Context , client snapshotterClientSet.Interface ,
456
+ snapshotName string , namespace string , timeout time.Duration ) error {
457
+ log := logger .GetLogger (ctx )
458
+ timeoutSeconds := int64 (timeout .Seconds ())
459
+
460
+ log .Infof ("Waiting up to %d seconds for VolumeSnapshot %s in namespace %s to be deleted using Watch API" ,
461
+ timeoutSeconds , snapshotName , namespace )
462
+
463
+ // First check if VolumeSnapshot already exists
464
+ _ , err := client .SnapshotV1 ().VolumeSnapshots (namespace ).Get (ctx , snapshotName , metav1.GetOptions {})
465
+ if err != nil {
466
+ if apierrors .IsNotFound (err ) {
467
+ log .Infof ("VolumeSnapshot %s/%s is already deleted" , namespace , snapshotName )
468
+ return nil
469
+ }
470
+ return fmt .Errorf ("unable to fetch VolumeSnapshot %s/%s with err: %+v" , namespace , snapshotName , err )
471
+ }
472
+
473
+ // Set up watch for the specific VolumeSnapshot
474
+ watchSnapshot , err := client .SnapshotV1 ().VolumeSnapshots (namespace ).Watch (
475
+ ctx ,
476
+ metav1.ListOptions {
477
+ FieldSelector : fields .OneTermEqualSelector ("metadata.name" , snapshotName ).String (),
478
+ TimeoutSeconds : & timeoutSeconds ,
479
+ Watch : true ,
480
+ })
481
+ if err != nil {
482
+ return fmt .Errorf ("failed to watch VolumeSnapshot %s in namespace %s with Error: %+v" ,
483
+ snapshotName , namespace , err )
484
+ }
485
+ defer watchSnapshot .Stop ()
486
+
487
+ // Watch for deletion events
488
+ for event := range watchSnapshot .ResultChan () {
489
+ switch event .Type {
490
+ case watch .Deleted :
491
+ log .Infof ("VolumeSnapshot %s/%s was deleted" , namespace , snapshotName )
492
+ return nil
493
+ case watch .Error :
494
+ return fmt .Errorf ("error watching VolumeSnapshot %s/%s: %+v" , namespace , snapshotName , event .Object )
495
+ }
496
+ // Continue watching for other event types (Added, Modified)
497
+ }
498
+
499
+ // If we reach here, the watch timed out
500
+ return fmt .Errorf ("volumeSnapshot %s/%s was not deleted within %d seconds" ,
501
+ namespace , snapshotName , timeoutSeconds )
502
+ }
503
+
504
+ // WaitForPVCDeletedWithWatch waits for a PVC to get deleted using Watch API instead of polling.
505
+ func WaitForPVCDeletedWithWatch (ctx context.Context , client clientset.Interface , pvcName string ,
506
+ namespace string , timeout time.Duration ) error {
507
+ log := logger .GetLogger (ctx )
508
+ timeoutSeconds := int64 (timeout .Seconds ())
509
+
510
+ log .Infof ("Waiting up to %d seconds for PersistentVolumeClaim %s in namespace %s to be deleted using Watch API" ,
511
+ timeoutSeconds , pvcName , namespace )
512
+
513
+ // First check if PVC already exists
514
+ _ , err := client .CoreV1 ().PersistentVolumeClaims (namespace ).Get (ctx , pvcName , metav1.GetOptions {})
515
+ if err != nil {
516
+ if apierrors .IsNotFound (err ) {
517
+ log .Infof ("PersistentVolumeClaim %s/%s is already deleted" , namespace , pvcName )
518
+ return nil
519
+ }
520
+ return fmt .Errorf ("unable to fetch PersistentVolumeClaim %s/%s with err: %+v" , namespace , pvcName , err )
521
+ }
522
+
523
+ // Set up watch for the specific PVC
524
+ watchPVC , err := client .CoreV1 ().PersistentVolumeClaims (namespace ).Watch (
525
+ ctx ,
526
+ metav1.ListOptions {
527
+ FieldSelector : fields .OneTermEqualSelector ("metadata.name" , pvcName ).String (),
528
+ TimeoutSeconds : & timeoutSeconds ,
529
+ Watch : true ,
530
+ })
531
+ if err != nil {
532
+ return fmt .Errorf ("failed to watch PersistentVolumeClaim %s in namespace %s with Error: %+v" ,
533
+ pvcName , namespace , err )
534
+ }
535
+ defer watchPVC .Stop ()
536
+
537
+ // Watch for deletion events
538
+ for event := range watchPVC .ResultChan () {
539
+ switch event .Type {
540
+ case watch .Deleted :
541
+ log .Infof ("PersistentVolumeClaim %s/%s was deleted" , namespace , pvcName )
542
+ return nil
543
+ case watch .Error :
544
+ return fmt .Errorf ("error watching PersistentVolumeClaim %s/%s: %+v" , namespace , pvcName , event .Object )
545
+ }
546
+ // Continue watching for other event types (Added, Modified)
547
+ }
548
+
549
+ // If we reach here, the watch timed out
550
+ return fmt .Errorf ("persistentVolumeClaim %s/%s was not deleted within %d seconds" ,
551
+ namespace , pvcName , timeoutSeconds )
552
+ }
0 commit comments