@@ -874,3 +874,45 @@ func getEnvVarOrDefault[T any](key string, defaultValue T) T {
874874 }
875875 return val
876876}
877+
878+ // waitForDaemonSetsReady waits for DaemonSets in a namespace to be ready, optionally filtered by label selector
879+ func waitForDaemonSetsReady (ctx context.Context , client kubernetes.Interface , namespace , labelSelector string ) error {
880+ EventuallyWithOffset (1 , func (g Gomega ) error {
881+ dsList , err := client .AppsV1 ().DaemonSets (namespace ).List (ctx , metav1.ListOptions {
882+ LabelSelector : labelSelector ,
883+ })
884+ if err != nil {
885+ return err
886+ }
887+
888+ if len (dsList .Items ) == 0 {
889+ return fmt .Errorf ("no daemonsets found in namespace %s with selector '%s'" , namespace , labelSelector )
890+ }
891+
892+ for _ , ds := range dsList .Items {
893+ // Skip if no pods are desired
894+ if ds .Status .DesiredNumberScheduled == 0 {
895+ continue
896+ }
897+
898+ if ds .Status .NumberReady != ds .Status .DesiredNumberScheduled {
899+ return fmt .Errorf ("daemonset %s/%s rollout incomplete: %d/%d pods ready" ,
900+ namespace , ds .Name , ds .Status .NumberReady , ds .Status .DesiredNumberScheduled )
901+ }
902+
903+ if ds .Status .UpdatedNumberScheduled != ds .Status .DesiredNumberScheduled {
904+ return fmt .Errorf ("daemonset %s/%s update incomplete: %d/%d pods updated" ,
905+ namespace , ds .Name , ds .Status .UpdatedNumberScheduled , ds .Status .DesiredNumberScheduled )
906+ }
907+
908+ // Check generation to ensure we're looking at the latest spec
909+ if ds .Generation != ds .Status .ObservedGeneration {
910+ return fmt .Errorf ("daemonset %s/%s generation mismatch: %d != %d" ,
911+ namespace , ds .Name , ds .Generation , ds .Status .ObservedGeneration )
912+ }
913+ }
914+
915+ return nil
916+ }).WithContext (ctx ).WithPolling (2 * time .Second ).WithTimeout (5 * time .Minute ).Should (Succeed ())
917+ return nil
918+ }
0 commit comments