@@ -22,6 +22,7 @@ import (
2222 "fmt"
2323 "maps"
2424 "slices"
25+ "sort"
2526 "strings"
2627 "time"
2728
@@ -111,6 +112,41 @@ func getSecret(
111112 return ctrl.Result {}, nil
112113}
113114
115+ // getExternalMasterServiceIPs returns the LoadBalancer ingress IPs for external master services
116+ // matching the given pool name. The second return value is true when at least one matching service
117+ // has no ingress IP yet, signalling that the caller should requeue and retry later.
118+ func getExternalMasterServiceIPs (ctx context.Context , helper * helper.Helper , instance * designatev1beta1.Designate , poolName string , Log logr.Logger ) ([]string , bool , error ) {
119+ services := & corev1.ServiceList {}
120+ err := helper .GetClient ().List (ctx , services , client .InNamespace (instance .Namespace ), client.MatchingLabels {
121+ designate .ExternalMasterServiceLabel : "true" ,
122+ "service" : "designate-mdns" ,
123+ })
124+ if err != nil {
125+ return nil , false , err
126+ }
127+ ips := make ([]string , 0 , len (services .Items ))
128+ pendingIngress := false
129+ for _ , service := range services .Items {
130+ if service .Spec .Type != corev1 .ServiceTypeLoadBalancer {
131+ continue
132+ }
133+ // If the service is missing the annotation, apply to all pools by skipping the pool name check.
134+ servicePool , ok := service .Annotations [designate .ExternalPoolServiceAnnotation ]
135+ if ok && servicePool != poolName {
136+ continue
137+ }
138+
139+ if len (service .Status .LoadBalancer .Ingress ) == 0 {
140+ Log .Info (fmt .Sprintf ("External master Service %s/%s has no LoadBalancer ingress IP yet, will requeue" , service .Namespace , service .Name ))
141+ pendingIngress = true
142+ continue
143+ }
144+ ips = append (ips , service .Status .LoadBalancer .Ingress [0 ].IP )
145+ }
146+ sort .Strings (ips )
147+ return ips , pendingIngress , nil
148+ }
149+
114150// GetClient -
115151func (r * DesignateReconciler ) GetClient () client.Client {
116152 return r .Client
@@ -299,6 +335,7 @@ func (r *DesignateReconciler) validatePoolRemovals(
299335// +kubebuilder:rbac:groups="security.openshift.io",resourceNames=anyuid;privileged,resources=securitycontextconstraints,verbs=use
300336// +kubebuilder:rbac:groups="",resources=pods,verbs=create;delete;get;list;patch;update;watch
301337// +kubebuilder:rbac:groups="",resources=pods/log,verbs=get
338+ // +kubebuilder:rbac:groups="",resources=services,verbs=get;list;watch
302339
303340// Reconcile -
304341func (r * DesignateReconciler ) Reconcile (ctx context.Context , req ctrl.Request ) (result ctrl.Result , _err error ) {
@@ -503,6 +540,25 @@ func (r *DesignateReconciler) SetupWithManager(ctx context.Context, mgr ctrl.Man
503540 return result
504541 }
505542
543+ externalMasterServiceFn := func (ctx context.Context , o client.Object ) []reconcile.Request {
544+ if o .GetLabels ()[designate .ExternalMasterServiceLabel ] != "true" {
545+ return nil
546+ }
547+
548+ designates := & designatev1beta1.DesignateList {}
549+ if err := r .List (ctx , designates , client .InNamespace (o .GetNamespace ())); err != nil {
550+ Log .Error (err , "Unable to retrieve Designate CRs" )
551+ return nil
552+ }
553+ var result []reconcile.Request
554+ for _ , cr := range designates .Items {
555+ result = append (result , reconcile.Request {
556+ NamespacedName : client.ObjectKey {Namespace : o .GetNamespace (), Name : cr .Name },
557+ })
558+ }
559+ return result
560+ }
561+
506562 // TODO(beagles):
507563 // - Watch for changes to the redis PODs and resync the headless hostnames for the PODs if necessary.
508564 return ctrl .NewControllerManagedBy (mgr ).
@@ -541,6 +597,12 @@ func (r *DesignateReconciler) SetupWithManager(ctx context.Context, mgr ctrl.Man
541597 handler .EnqueueRequestsFromMapFunc (redisWatchFn ),
542598 builder .WithPredicates (predicate.ResourceVersionChangedPredicate {}),
543599 ).
600+ // Watch for external master Service changes (LoadBalancer IP assignments)
601+ Watches (
602+ & corev1.Service {},
603+ handler .EnqueueRequestsFromMapFunc (externalMasterServiceFn ),
604+ builder .WithPredicates (predicate.ResourceVersionChangedPredicate {}),
605+ ).
544606 Complete (r )
545607}
546608
@@ -1005,6 +1067,7 @@ func (r *DesignateReconciler) reconcileNormal(ctx context.Context, instance *des
10051067
10061068 externalBindData := make (map [string ][]designate.ExternalBind )
10071069 externalRndcSecretData := make (map [string ]string )
1070+ externalMasterServiceIPs := make (map [string ][]string )
10081071 updateRndcSecret := false
10091072
10101073 if instance .Spec .ExternalBindsSecret != "" {
@@ -1048,9 +1111,18 @@ func (r *DesignateReconciler) reconcileNormal(ctx context.Context, instance *des
10481111 externalBindData [poolName ][i ].RndcFile = rndcFilename
10491112 externalRndcSecretData [rndcFilename ] = rndcBlock
10501113 }
1114+ var pendingIngress bool
1115+ externalMasterServiceIPs [poolName ], pendingIngress , err = getExternalMasterServiceIPs (ctx , helper , instance , poolName , Log )
1116+ if err != nil {
1117+ return ctrl.Result {}, err
1118+ }
1119+ if pendingIngress {
1120+ return ctrl.Result {RequeueAfter : 10 * time .Second }, nil
1121+ }
10511122 }
10521123 updateRndcSecret = hash != instance .Status .Hash [designate .ExternalBindsData ]
10531124 instance .Status .Hash [designate .ExternalBindsData ] = hash
1125+
10541126 } else {
10551127 // No external binds secret, so we need to check if the external rndc secret data is present
10561128 // and if it is - remove the contents so the workers have up to date.
@@ -1265,7 +1337,7 @@ func (r *DesignateReconciler) reconcileNormal(ctx context.Context, instance *des
12651337 Data : make (map [string ]string ),
12661338 }
12671339
1268- poolsYaml , poolsYamlHash , err := designate .GeneratePoolsYamlDataAndHash (updatedBindMap , mdnsConfigMap .Data , nsRecords , multipoolConfig , externalBindData )
1340+ poolsYaml , poolsYamlHash , err := designate .GeneratePoolsYamlDataAndHash (updatedBindMap , mdnsConfigMap .Data , nsRecords , multipoolConfig , externalBindData , externalMasterServiceIPs )
12691341 if err != nil {
12701342 return ctrl.Result {}, err
12711343 }
0 commit comments