@@ -6,17 +6,21 @@ import (
66 "maps"
77 "slices"
88 "strings"
9+ "sync"
910 "time"
1011
1112 corev1 "k8s.io/api/core/v1"
1213 rbacv1 "k8s.io/api/rbac/v1"
1314 apierrors "k8s.io/apimachinery/pkg/api/errors"
1415 metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
1516 "k8s.io/apimachinery/pkg/runtime/schema"
17+ "k8s.io/apimachinery/pkg/types"
1618 "k8s.io/client-go/tools/record"
1719 ctrl "sigs.k8s.io/controller-runtime"
20+ "sigs.k8s.io/controller-runtime/pkg/builder"
1821 "sigs.k8s.io/controller-runtime/pkg/client"
1922 "sigs.k8s.io/controller-runtime/pkg/controller/controllerutil"
23+ "sigs.k8s.io/controller-runtime/pkg/handler"
2024 "sigs.k8s.io/controller-runtime/pkg/predicate"
2125 "sigs.k8s.io/controller-runtime/pkg/reconcile"
2226
@@ -41,13 +45,15 @@ import (
4145)
4246
4347const ControllerName = "DNSCluster"
44- const defaultRequeueAfterDuration = 30 * time .Second
48+ const defaultRequeueAfterDuration = 1 * time .Minute
4549
4650type ClusterReconciler struct {
4751 PlatformCluster * clusters.Cluster
4852 eventRecorder record.EventRecorder
4953 ProviderName string
5054 ProviderNamespace string
55+ KnownClusters map [types.NamespacedName ]struct {}
56+ KnownClustersLock * sync.RWMutex
5157}
5258
5359func NewClusterReconciler (platformCluster * clusters.Cluster , recorder record.EventRecorder , providerName , providerNamespace string ) * ClusterReconciler {
@@ -56,6 +62,8 @@ func NewClusterReconciler(platformCluster *clusters.Cluster, recorder record.Eve
5662 eventRecorder : recorder ,
5763 ProviderName : providerName ,
5864 ProviderNamespace : providerNamespace ,
65+ KnownClusters : map [types.NamespacedName ]struct {}{},
66+ KnownClustersLock : & sync.RWMutex {},
5967 }
6068}
6169
@@ -90,6 +98,7 @@ func (r *ClusterReconciler) Reconcile(ctx context.Context, req reconcile.Request
9098 if err := r .PlatformCluster .Client ().Get (ctx , req .NamespacedName , c ); err != nil {
9199 if apierrors .IsNotFound (err ) {
92100 log .Info ("Resource not found" )
101+ r .removeKnownClusterRaw (req .Name , req .Namespace )
93102 return reconcile.Result {}, nil
94103 }
95104 return reconcile.Result {}, fmt .Errorf ("unable to get resource '%s' from cluster: %w" , req .String (), err )
@@ -178,6 +187,7 @@ func (r *ClusterReconciler) reconcile(ctx context.Context, c *clustersv1alpha1.C
178187 return rr
179188 }
180189 }
190+ r .addKnownCluster (c )
181191
182192 // get access to the Cluster
183193 accessMgr := accesslib .NewClusterAccessManager (r .PlatformCluster .Client (), strings .ToLower (ControllerName ), c .Namespace )
@@ -270,6 +280,7 @@ func (r *ClusterReconciler) reconcile(ctx context.Context, c *clustersv1alpha1.C
270280 return rr
271281 }
272282 }
283+ r .removeKnownCluster (c )
273284
274285 rr .Message = "Successfully removed external-dns from Cluster"
275286 }
@@ -656,6 +667,34 @@ func clusterBasedResourceName(clusterName string) string {
656667 return ctrlutils .ShortenToXCharactersUnsafe (clusterName , ctrlutils .K8sMaxNameLength - len (suffix )) + suffix
657668}
658669
670+ func (r * ClusterReconciler ) addKnownCluster (c * clustersv1alpha1.Cluster ) {
671+ nn := types.NamespacedName {Namespace : c .Namespace , Name : c .Name }
672+ r .KnownClustersLock .Lock ()
673+ defer r .KnownClustersLock .Unlock ()
674+ r .KnownClusters [nn ] = struct {}{}
675+ }
676+
677+ func (r * ClusterReconciler ) removeKnownCluster (c * clustersv1alpha1.Cluster ) {
678+ r .removeKnownClusterRaw (c .Name , c .Namespace )
679+ }
680+
681+ func (r * ClusterReconciler ) removeKnownClusterRaw (name , namespace string ) {
682+ nn := types.NamespacedName {Namespace : namespace , Name : name }
683+ r .KnownClustersLock .Lock ()
684+ defer r .KnownClustersLock .Unlock ()
685+ delete (r .KnownClusters , nn )
686+ }
687+
688+ func (r * ClusterReconciler ) listKnownClusters () []types.NamespacedName {
689+ r .KnownClustersLock .RLock ()
690+ defer r .KnownClustersLock .RUnlock ()
691+ result := make ([]types.NamespacedName , 0 , len (r .KnownClusters ))
692+ for nn := range r .KnownClusters {
693+ result = append (result , nn )
694+ }
695+ return result
696+ }
697+
659698// SetupWithManager sets up the controller with the Manager.
660699func (r * ClusterReconciler ) SetupWithManager (mgr ctrl.Manager ) error {
661700 return ctrl .NewControllerManagedBy (mgr ).
@@ -672,5 +711,14 @@ func (r *ClusterReconciler) SetupWithManager(mgr ctrl.Manager) error {
672711 ctrlutils .HasAnnotationPredicate (openmcpconst .OperationAnnotation , openmcpconst .OperationAnnotationValueIgnore ),
673712 ),
674713 )).
714+ // watch DNSServiceConfig resource and reconcile all Clusters that are known to have external-dns deployed if it changes
715+ Watches (& dnsv1alpha1.DNSServiceConfig {}, handler .EnqueueRequestsFromMapFunc (func (_ context.Context , _ client.Object ) []ctrl.Request {
716+ return collections .ProjectSliceToSlice (r .listKnownClusters (), func (nn types.NamespacedName ) ctrl.Request {
717+ return ctrl.Request {NamespacedName : nn }
718+ })
719+ }), builder .WithPredicates (predicate .And (
720+ predicate.GenerationChangedPredicate {},
721+ ctrlutils .ExactNamePredicate (r .ProviderName , r .ProviderNamespace ),
722+ ))).
675723 Complete (r )
676724}
0 commit comments