From 58832ebc3533dcfd4eeb30bf9a2cdc97a8b23340 Mon Sep 17 00:00:00 2001 From: Tamal Saha Date: Sat, 6 Jun 2026 21:16:30 +0600 Subject: [PATCH] controller, informers: dedupe secret + source mapping handlers Extract providerSecretName(spec) so the secretToEdns handler stops repeating the same per-provider name check four times. Behavior is identical; the switch lives in one place now. Extract enqueueForKind(ctx, r, kind) for the Node/Service/Ingress informer handlers. The typed predicates still differ per kind (Node looks at Status.Addresses, the others look at Generation + Status.LoadBalancer) and stay where they are. Signed-off-by: Tamal Saha --- .../external-dns/externaldns_controller.go | 52 ++++++++------ pkg/informers/sources.go | 71 ++++++------------- 2 files changed, 54 insertions(+), 69 deletions(-) diff --git a/pkg/controllers/external-dns/externaldns_controller.go b/pkg/controllers/external-dns/externaldns_controller.go index 076e41fb..45e968d9 100644 --- a/pkg/controllers/external-dns/externaldns_controller.go +++ b/pkg/controllers/external-dns/externaldns_controller.go @@ -237,6 +237,31 @@ func (r *ExternalDNSReconciler) handleDeletion(ctx context.Context, edns *api.Ex return ctrl.Result{}, r.Update(ctx, edns) } +// providerSecretName returns the name of the referenced provider secret +// for spec, if any. The boolean is false when the provider doesn't use a +// secret reference (e.g. IRSA/workload-identity). +func providerSecretName(spec *api.ExternalDNSSpec) (string, bool) { + switch spec.Provider { + case api.ProviderAWS: + if spec.AWS != nil && spec.AWS.SecretRef != nil { + return spec.AWS.SecretRef.Name, true + } + case api.ProviderAzure: + if spec.Azure != nil && spec.Azure.SecretRef != nil { + return spec.Azure.SecretRef.Name, true + } + case api.ProviderGoogle: + if spec.Google != nil && spec.Google.SecretRef != nil { + return spec.Google.SecretRef.Name, true + } + case api.ProviderCloudflare: + if spec.Cloudflare != nil && spec.Cloudflare.SecretRef != nil { + return spec.Cloudflare.SecretRef.Name, true + } + } + return "", false +} + // SetupWithManager sets up the controller with the Manager. func (r *ExternalDNSReconciler) SetupWithManager(mgr ctrl.Manager) error { secretToEdns := handler.EnqueueRequestsFromMapFunc(func(ctx context.Context, object client.Object) []reconcile.Request { @@ -247,28 +272,13 @@ func (r *ExternalDNSReconciler) SetupWithManager(mgr ctrl.Manager) error { return reconcileReq } - for _, edns := range ednsList.Items { - switch edns.Spec.Provider { - case api.ProviderAWS: - if edns.Spec.AWS != nil && edns.Spec.AWS.SecretRef != nil && edns.Spec.AWS.SecretRef.Name == object.GetName() { - reconcileReq = append(reconcileReq, reconcile.Request{NamespacedName: client.ObjectKey{Name: edns.Name, Namespace: edns.Namespace}}) - } - - case api.ProviderAzure: - if edns.Spec.Azure != nil && edns.Spec.Azure.SecretRef != nil && edns.Spec.Azure.SecretRef.Name == object.GetName() { - reconcileReq = append(reconcileReq, reconcile.Request{NamespacedName: client.ObjectKey{Name: edns.Name, Namespace: edns.Namespace}}) - } - - case api.ProviderGoogle: - if edns.Spec.Google != nil && edns.Spec.Google.SecretRef != nil && edns.Spec.Google.SecretRef.Name == object.GetName() { - reconcileReq = append(reconcileReq, reconcile.Request{NamespacedName: client.ObjectKey{Name: edns.Name, Namespace: edns.Namespace}}) - } - - case api.ProviderCloudflare: - if edns.Spec.Cloudflare != nil && edns.Spec.Cloudflare.SecretRef != nil && edns.Spec.Cloudflare.SecretRef.Name == object.GetName() { - reconcileReq = append(reconcileReq, reconcile.Request{NamespacedName: client.ObjectKey{Name: edns.Name, Namespace: edns.Namespace}}) - } + for i := range ednsList.Items { + edns := &ednsList.Items[i] + name, ok := providerSecretName(&edns.Spec) + if !ok || name != object.GetName() { + continue } + reconcileReq = append(reconcileReq, reconcile.Request{NamespacedName: client.ObjectKey{Name: edns.Name, Namespace: edns.Namespace}}) } return reconcileReq diff --git a/pkg/informers/sources.go b/pkg/informers/sources.go index 97705e5f..33153f4f 100644 --- a/pkg/informers/sources.go +++ b/pkg/informers/sources.go @@ -42,23 +42,27 @@ const ( kindIngress = "Ingress" ) -func getKindNode(cache cache.Cache, r client.Client) (source.SyncingSource, error) { - hdlr := handler.TypedEnqueueRequestsFromMapFunc(func(ctx context.Context, a *corev1.Node) []reconcile.Request { - reconcileReq := make([]reconcile.Request, 0) - dnsList := &api.ExternalDNSList{} - - if err := r.List(ctx, dnsList); err != nil { - klog.Errorf("failed to list the external dns resources: %s", err.Error()) - return reconcileReq - } - - for _, edns := range dnsList.Items { - if edns.Spec.Source.Type.Kind == kindNode { - reconcileReq = append(reconcileReq, reconcile.Request{NamespacedName: client.ObjectKey{Name: edns.Name, Namespace: edns.Namespace}}) - } +// enqueueForKind returns the set of ExternalDNS reconcile requests that +// subscribe to the given source kind. Cluster-wide list, filtered by +// Spec.Source.Type.Kind. +func enqueueForKind(ctx context.Context, r client.Client, kind string) []reconcile.Request { + reconcileReq := make([]reconcile.Request, 0) + dnsList := &api.ExternalDNSList{} + if err := r.List(ctx, dnsList); err != nil { + klog.Errorf("failed to list the external dns resources: %s", err.Error()) + return reconcileReq + } + for _, edns := range dnsList.Items { + if edns.Spec.Source.Type.Kind == kind { + reconcileReq = append(reconcileReq, reconcile.Request{NamespacedName: client.ObjectKey{Name: edns.Name, Namespace: edns.Namespace}}) } + } + return reconcileReq +} - return reconcileReq +func getKindNode(cache cache.Cache, r client.Client) (source.SyncingSource, error) { + hdlr := handler.TypedEnqueueRequestsFromMapFunc(func(ctx context.Context, _ *corev1.Node) []reconcile.Request { + return enqueueForKind(ctx, r, kindNode) }) return source.Kind(cache, &corev1.Node{}, hdlr, predicate.TypedFuncs[*corev1.Node]{UpdateFunc: func(e event.TypedUpdateEvent[*corev1.Node]) bool { // Reconcile only when the addresses, labels, or annotations change — @@ -71,22 +75,8 @@ func getKindNode(cache cache.Cache, r client.Client) (source.SyncingSource, erro } func getKindService(cache cache.Cache, r client.Client) (source.SyncingSource, error) { - hdlr := handler.TypedEnqueueRequestsFromMapFunc(func(ctx context.Context, a *corev1.Service) []reconcile.Request { - reconcileReq := make([]reconcile.Request, 0) - dnsList := &api.ExternalDNSList{} - - if err := r.List(ctx, dnsList); err != nil { - klog.Errorf("failed to list the external dns resources: %s", err.Error()) - return reconcileReq - } - - for _, edns := range dnsList.Items { - if edns.Spec.Source.Type.Kind == kindService { - reconcileReq = append(reconcileReq, reconcile.Request{NamespacedName: client.ObjectKey{Name: edns.Name, Namespace: edns.Namespace}}) - } - } - - return reconcileReq + hdlr := handler.TypedEnqueueRequestsFromMapFunc(func(ctx context.Context, _ *corev1.Service) []reconcile.Request { + return enqueueForKind(ctx, r, kindService) }) return source.Kind(cache, &corev1.Service{}, hdlr, predicate.TypedFuncs[*corev1.Service]{UpdateFunc: func(e event.TypedUpdateEvent[*corev1.Service]) bool { // Reconcile only on changes that affect the endpoints external-dns @@ -101,24 +91,9 @@ func getKindService(cache cache.Cache, r client.Client) (source.SyncingSource, e } func getKindIngress(cache cache.Cache, r client.Client) (source.SyncingSource, error) { - hdlr := handler.TypedEnqueueRequestsFromMapFunc(func(ctx context.Context, a *networkingv1.Ingress) []reconcile.Request { - reconcileReq := make([]reconcile.Request, 0) - dnsList := &api.ExternalDNSList{} - - if err := r.List(ctx, dnsList); err != nil { - klog.Errorf("failed to list the external dns resources: %s", err.Error()) - return reconcileReq - } - - for _, edns := range dnsList.Items { - if edns.Spec.Source.Type.Kind == kindIngress { - reconcileReq = append(reconcileReq, reconcile.Request{NamespacedName: client.ObjectKey{Name: edns.Name, Namespace: edns.Namespace}}) - } - } - - return reconcileReq + hdlr := handler.TypedEnqueueRequestsFromMapFunc(func(ctx context.Context, _ *networkingv1.Ingress) []reconcile.Request { + return enqueueForKind(ctx, r, kindIngress) }) - return source.Kind(cache, &networkingv1.Ingress{}, hdlr, predicate.TypedFuncs[*networkingv1.Ingress]{UpdateFunc: func(e event.TypedUpdateEvent[*networkingv1.Ingress]) bool { // Reconcile only on changes that affect the endpoints external-dns // derives from an Ingress: spec changes (bumps Generation),