diff --git a/bootstrap/kubeadm/controllers/alias.go b/bootstrap/kubeadm/controllers/alias.go index 7f8b99b136ca..ecf37ab66e7a 100644 --- a/bootstrap/kubeadm/controllers/alias.go +++ b/bootstrap/kubeadm/controllers/alias.go @@ -25,6 +25,7 @@ import ( "sigs.k8s.io/controller-runtime/pkg/controller" kubeadmbootstrapcontrollers "sigs.k8s.io/cluster-api/bootstrap/kubeadm/internal/controllers" + "sigs.k8s.io/cluster-api/util/predicates" ) // Following types provides access to reconcilers implemented in internal/controllers, thus @@ -42,6 +43,9 @@ type KubeadmConfigReconciler struct { // WatchFilterValue is the label value used to filter events prior to reconciliation. WatchFilterValue string + // Filter checks if a KubeadmConfig object should be reconciled. + Filter predicates.Filter + // TokenTTL is the amount of time a bootstrap token (and therefore a KubeadmConfig) will be valid. TokenTTL time.Duration } @@ -51,6 +55,7 @@ func (r *KubeadmConfigReconciler) SetupWithManager(ctx context.Context, mgr ctrl return (&kubeadmbootstrapcontrollers.KubeadmConfigReconciler{ Client: r.Client, WatchFilterValue: r.WatchFilterValue, + Filter: r.Filter, TokenTTL: r.TokenTTL, }).SetupWithManager(ctx, mgr, options) } diff --git a/bootstrap/kubeadm/internal/controllers/kubeadmconfig_controller.go b/bootstrap/kubeadm/internal/controllers/kubeadmconfig_controller.go index e8ebe12a560d..1e4b3c6a1c6f 100644 --- a/bootstrap/kubeadm/internal/controllers/kubeadmconfig_controller.go +++ b/bootstrap/kubeadm/internal/controllers/kubeadmconfig_controller.go @@ -86,6 +86,8 @@ type KubeadmConfigReconciler struct { // WatchFilterValue is the label value used to filter events prior to reconciliation. WatchFilterValue string + Filter predicates.Filter + // TokenTTL is the amount of time a bootstrap token (and therefore a KubeadmConfig) will be valid. TokenTTL time.Duration @@ -160,6 +162,9 @@ func (r *KubeadmConfigReconciler) Reconcile(ctx context.Context, req ctrl.Reques log.Error(err, "Failed to get config") return ctrl.Result{}, err } + if r.Filter != nil && !r.Filter.Filter(config) { + return ctrl.Result{}, nil + } // AddOwners adds the owners of KubeadmConfig as k/v pairs to the logger. // Specifically, it will add KubeadmControlPlane, MachineSet and MachineDeployment. diff --git a/controllers/alias.go b/controllers/alias.go index 5678d91c7e46..6e80bb989efb 100644 --- a/controllers/alias.go +++ b/controllers/alias.go @@ -34,6 +34,7 @@ import ( machinedeploymenttopologycontroller "sigs.k8s.io/cluster-api/internal/controllers/topology/machinedeployment" machinesettopologycontroller "sigs.k8s.io/cluster-api/internal/controllers/topology/machineset" runtimeclient "sigs.k8s.io/cluster-api/internal/runtime/client" + "sigs.k8s.io/cluster-api/util/predicates" ) // Following types provides access to reconcilers implemented in internal/controllers, thus @@ -46,6 +47,9 @@ type ClusterReconciler struct { // WatchFilterValue is the label value used to filter events prior to reconciliation. WatchFilterValue string + + // Filter checks if a Cluster object should be reconciled. + Filter predicates.Filter } func (r *ClusterReconciler) SetupWithManager(ctx context.Context, mgr ctrl.Manager, options controller.Options) error { @@ -53,6 +57,7 @@ func (r *ClusterReconciler) SetupWithManager(ctx context.Context, mgr ctrl.Manag Client: r.Client, APIReader: r.APIReader, WatchFilterValue: r.WatchFilterValue, + Filter: r.Filter, }).SetupWithManager(ctx, mgr, options) } @@ -64,6 +69,8 @@ type MachineReconciler struct { // WatchFilterValue is the label value used to filter events prior to reconciliation. WatchFilterValue string + // Filter checks if a Machine object should be reconciled. + Filter predicates.Filter } func (r *MachineReconciler) SetupWithManager(ctx context.Context, mgr ctrl.Manager, options controller.Options) error { @@ -72,6 +79,7 @@ func (r *MachineReconciler) SetupWithManager(ctx context.Context, mgr ctrl.Manag APIReader: r.APIReader, Tracker: r.Tracker, WatchFilterValue: r.WatchFilterValue, + Filter: r.Filter, }).SetupWithManager(ctx, mgr, options) } @@ -83,6 +91,8 @@ type MachineSetReconciler struct { // WatchFilterValue is the label value used to filter events prior to reconciliation. WatchFilterValue string + // Filter checks if a MachineSet object should be reconciled. + Filter predicates.Filter } func (r *MachineSetReconciler) SetupWithManager(ctx context.Context, mgr ctrl.Manager, options controller.Options) error { @@ -91,6 +101,7 @@ func (r *MachineSetReconciler) SetupWithManager(ctx context.Context, mgr ctrl.Ma APIReader: r.APIReader, Tracker: r.Tracker, WatchFilterValue: r.WatchFilterValue, + Filter: r.Filter, }).SetupWithManager(ctx, mgr, options) } @@ -101,6 +112,8 @@ type MachineDeploymentReconciler struct { // WatchFilterValue is the label value used to filter events prior to reconciliation. WatchFilterValue string + // Filter checks if a MachineDeployment object should be reconciled. + Filter predicates.Filter } func (r *MachineDeploymentReconciler) SetupWithManager(ctx context.Context, mgr ctrl.Manager, options controller.Options) error { @@ -108,6 +121,7 @@ func (r *MachineDeploymentReconciler) SetupWithManager(ctx context.Context, mgr Client: r.Client, APIReader: r.APIReader, WatchFilterValue: r.WatchFilterValue, + Filter: r.Filter, }).SetupWithManager(ctx, mgr, options) } @@ -118,6 +132,8 @@ type MachineHealthCheckReconciler struct { // WatchFilterValue is the label value used to filter events prior to reconciliation. WatchFilterValue string + // Filter checks if a MachineHealthCheck object should be reconciled. + Filter predicates.Filter } func (r *MachineHealthCheckReconciler) SetupWithManager(ctx context.Context, mgr ctrl.Manager, options controller.Options) error { @@ -125,6 +141,7 @@ func (r *MachineHealthCheckReconciler) SetupWithManager(ctx context.Context, mgr Client: r.Client, Tracker: r.Tracker, WatchFilterValue: r.WatchFilterValue, + Filter: r.Filter, }).SetupWithManager(ctx, mgr, options) } @@ -139,6 +156,8 @@ type ClusterTopologyReconciler struct { // WatchFilterValue is the label value used to filter events prior to reconciliation. WatchFilterValue string + // Filter checks if a ClusterTopology object should be reconciled. + Filter predicates.Filter // UnstructuredCachingClient provides a client that forces caching of unstructured objects, // thus allowing to optimize reads for templates or provider specific objects in a managed topology. @@ -152,6 +171,7 @@ func (r *ClusterTopologyReconciler) SetupWithManager(ctx context.Context, mgr ct RuntimeClient: r.RuntimeClient, UnstructuredCachingClient: r.UnstructuredCachingClient, WatchFilterValue: r.WatchFilterValue, + Filter: r.Filter, }).SetupWithManager(ctx, mgr, options) } @@ -165,6 +185,8 @@ type MachineDeploymentTopologyReconciler struct { // race conditions caused by an outdated cache. APIReader client.Reader WatchFilterValue string + // Filter checks if a MachineDeploymentTopology object should be reconciled. + Filter predicates.Filter } func (r *MachineDeploymentTopologyReconciler) SetupWithManager(ctx context.Context, mgr ctrl.Manager, options controller.Options) error { @@ -172,6 +194,7 @@ func (r *MachineDeploymentTopologyReconciler) SetupWithManager(ctx context.Conte Client: r.Client, APIReader: r.APIReader, WatchFilterValue: r.WatchFilterValue, + Filter: r.Filter, }).SetupWithManager(ctx, mgr, options) } @@ -185,6 +208,8 @@ type MachineSetTopologyReconciler struct { // race conditions caused by an outdated cache. APIReader client.Reader WatchFilterValue string + // Filter checks if a MachineSetTopology object should be reconciled. + Filter predicates.Filter } func (r *MachineSetTopologyReconciler) SetupWithManager(ctx context.Context, mgr ctrl.Manager, options controller.Options) error { @@ -192,6 +217,7 @@ func (r *MachineSetTopologyReconciler) SetupWithManager(ctx context.Context, mgr Client: r.Client, APIReader: r.APIReader, WatchFilterValue: r.WatchFilterValue, + Filter: r.Filter, }).SetupWithManager(ctx, mgr, options) } @@ -202,6 +228,8 @@ type ClusterClassReconciler struct { // WatchFilterValue is the label value used to filter events prior to reconciliation. WatchFilterValue string + // Filter checks if a ClusterClass object should be reconciled. + Filter predicates.Filter // UnstructuredCachingClient provides a client that forces caching of unstructured objects, // thus allowing to optimize reads for templates or provider specific objects. @@ -214,5 +242,6 @@ func (r *ClusterClassReconciler) SetupWithManager(ctx context.Context, mgr ctrl. APIReader: r.APIReader, UnstructuredCachingClient: r.UnstructuredCachingClient, WatchFilterValue: r.WatchFilterValue, + Filter: r.Filter, }).SetupWithManager(ctx, mgr, options) } diff --git a/controlplane/kubeadm/controllers/alias.go b/controlplane/kubeadm/controllers/alias.go index f5584c0dd86e..ce5a63dd5023 100644 --- a/controlplane/kubeadm/controllers/alias.go +++ b/controlplane/kubeadm/controllers/alias.go @@ -26,6 +26,7 @@ import ( "sigs.k8s.io/cluster-api/controllers/remote" kubeadmcontrolplanecontrollers "sigs.k8s.io/cluster-api/controlplane/kubeadm/internal/controllers" + "sigs.k8s.io/cluster-api/util/predicates" ) // KubeadmControlPlaneReconciler reconciles a KubeadmControlPlane object. @@ -39,6 +40,8 @@ type KubeadmControlPlaneReconciler struct { // WatchFilterValue is the label value used to filter events prior to reconciliation. WatchFilterValue string + // Filter checks if a KubeadmControlPlane object should be reconciled. + Filter predicates.Filter } // SetupWithManager sets up the reconciler with the Manager. @@ -50,5 +53,6 @@ func (r *KubeadmControlPlaneReconciler) SetupWithManager(ctx context.Context, mg EtcdDialTimeout: r.EtcdDialTimeout, EtcdCallTimeout: r.EtcdCallTimeout, WatchFilterValue: r.WatchFilterValue, + Filter: r.Filter, }).SetupWithManager(ctx, mgr, options) } diff --git a/controlplane/kubeadm/internal/controllers/controller.go b/controlplane/kubeadm/internal/controllers/controller.go index c29b46fb3ccd..5f314587f2d2 100644 --- a/controlplane/kubeadm/internal/controllers/controller.go +++ b/controlplane/kubeadm/internal/controllers/controller.go @@ -75,6 +75,8 @@ type KubeadmControlPlaneReconciler struct { // WatchFilterValue is the label value used to filter events prior to reconciliation. WatchFilterValue string + Filter predicates.Filter + managementCluster internal.ManagementCluster managementClusterUncached internal.ManagementCluster } @@ -136,6 +138,10 @@ func (r *KubeadmControlPlaneReconciler) Reconcile(ctx context.Context, req ctrl. return ctrl.Result{Requeue: true}, nil } + if r.Filter != nil && !r.Filter.Filter(kcp) { + return ctrl.Result{}, nil + } + // Fetch the Cluster. cluster, err := util.GetOwnerCluster(ctx, r.Client, kcp.ObjectMeta) if err != nil { diff --git a/internal/controllers/cluster/cluster_controller.go b/internal/controllers/cluster/cluster_controller.go index 960fc2c960c6..62aae2c3d830 100644 --- a/internal/controllers/cluster/cluster_controller.go +++ b/internal/controllers/cluster/cluster_controller.go @@ -70,6 +70,7 @@ type Reconciler struct { // WatchFilterValue is the label value used to filter events prior to reconciliation. WatchFilterValue string + Filter predicates.Filter recorder record.EventRecorder externalTracker external.ObjectTracker @@ -113,6 +114,10 @@ func (r *Reconciler) Reconcile(ctx context.Context, req ctrl.Request) (_ ctrl.Re return ctrl.Result{}, err } + if r.Filter != nil && !r.Filter.Filter(cluster) { + return ctrl.Result{}, nil + } + // Return early if the object or Cluster is paused. if annotations.IsPaused(cluster, cluster) { log.Info("Reconciliation is paused for this object") diff --git a/internal/controllers/clusterclass/clusterclass_controller.go b/internal/controllers/clusterclass/clusterclass_controller.go index d1f3b8fbafee..b6e4d21e0986 100644 --- a/internal/controllers/clusterclass/clusterclass_controller.go +++ b/internal/controllers/clusterclass/clusterclass_controller.go @@ -52,6 +52,7 @@ type Reconciler struct { // WatchFilterValue is the label value used to filter events prior to reconciliation. WatchFilterValue string + Filter predicates.Filter // UnstructuredCachingClient provides a client that forces caching of unstructured objects, // thus allowing to optimize reads for templates or provider specific objects. @@ -82,7 +83,9 @@ func (r *Reconciler) Reconcile(ctx context.Context, req ctrl.Request) (_ ctrl.Re // Error reading the object - requeue the request. return ctrl.Result{}, err } - + if r.Filter != nil && !r.Filter.Filter(clusterClass) { + return ctrl.Result{}, nil + } // Return early if the ClusterClass is paused. if annotations.HasPaused(clusterClass) { log.Info("Reconciliation is paused for this object") diff --git a/internal/controllers/machine/machine_controller.go b/internal/controllers/machine/machine_controller.go index 00c302f173d2..8bd031d18be4 100644 --- a/internal/controllers/machine/machine_controller.go +++ b/internal/controllers/machine/machine_controller.go @@ -83,6 +83,7 @@ type Reconciler struct { // WatchFilterValue is the label value used to filter events prior to reconciliation. WatchFilterValue string + Filter predicates.Filter controller controller.Controller recorder record.EventRecorder @@ -155,7 +156,9 @@ func (r *Reconciler) Reconcile(ctx context.Context, req ctrl.Request) (_ ctrl.Re // Error reading the object - requeue the request. return ctrl.Result{}, err } - + if r.Filter != nil && !r.Filter.Filter(m) { + return ctrl.Result{}, nil + } // AddOwners adds the owners of Machine as k/v pairs to the logger. // Specifically, it will add KubeadmControlPlane, MachineSet and MachineDeployment. ctx, log, err := clog.AddOwners(ctx, r.Client, m) diff --git a/internal/controllers/machinedeployment/machinedeployment_controller.go b/internal/controllers/machinedeployment/machinedeployment_controller.go index d276a037ab6a..9f78c43ace1c 100644 --- a/internal/controllers/machinedeployment/machinedeployment_controller.go +++ b/internal/controllers/machinedeployment/machinedeployment_controller.go @@ -63,6 +63,7 @@ type Reconciler struct { // WatchFilterValue is the label value used to filter events prior to reconciliation. WatchFilterValue string + Filter predicates.Filter recorder record.EventRecorder } @@ -118,7 +119,9 @@ func (r *Reconciler) Reconcile(ctx context.Context, req ctrl.Request) (_ ctrl.Re // Error reading the object - requeue the request. return ctrl.Result{}, err } - + if r.Filter != nil && !r.Filter.Filter(deployment) { + return ctrl.Result{}, nil + } log = log.WithValues("Cluster", klog.KRef(deployment.Namespace, deployment.Spec.ClusterName)) ctx = ctrl.LoggerInto(ctx, log) diff --git a/internal/controllers/machinehealthcheck/machinehealthcheck_controller.go b/internal/controllers/machinehealthcheck/machinehealthcheck_controller.go index 14117c3c18e5..7d6a03fbf2ac 100644 --- a/internal/controllers/machinehealthcheck/machinehealthcheck_controller.go +++ b/internal/controllers/machinehealthcheck/machinehealthcheck_controller.go @@ -79,6 +79,7 @@ type Reconciler struct { // WatchFilterValue is the label value used to filter events prior to reconciliation. WatchFilterValue string + Filter predicates.Filter controller controller.Controller recorder record.EventRecorder @@ -131,7 +132,9 @@ func (r *Reconciler) Reconcile(ctx context.Context, req ctrl.Request) (_ ctrl.Re log.Error(err, "Failed to fetch MachineHealthCheck") return ctrl.Result{}, err } - + if r.Filter != nil && !r.Filter.Filter(m) { + return ctrl.Result{}, nil + } log = log.WithValues("Cluster", klog.KRef(m.Namespace, m.Spec.ClusterName)) ctx = ctrl.LoggerInto(ctx, log) diff --git a/internal/controllers/machineset/machineset_controller.go b/internal/controllers/machineset/machineset_controller.go index 01dcde08efba..0b74ea160e91 100644 --- a/internal/controllers/machineset/machineset_controller.go +++ b/internal/controllers/machineset/machineset_controller.go @@ -78,6 +78,7 @@ type Reconciler struct { // WatchFilterValue is the label value used to filter events prior to reconciliation. WatchFilterValue string + Filter predicates.Filter recorder record.EventRecorder } @@ -130,7 +131,9 @@ func (r *Reconciler) Reconcile(ctx context.Context, req ctrl.Request) (_ ctrl.Re // Error reading the object - requeue the request. return ctrl.Result{}, err } - + if r.Filter != nil && !r.Filter.Filter(machineSet) { + return ctrl.Result{}, nil + } // AddOwners adds the owners of MachineSet as k/v pairs to the logger. // Specifically, it will add MachineDeployment. ctx, log, err := clog.AddOwners(ctx, r.Client, machineSet) diff --git a/internal/controllers/topology/cluster/cluster_controller.go b/internal/controllers/topology/cluster/cluster_controller.go index 8921981802af..9deff9fa2e09 100644 --- a/internal/controllers/topology/cluster/cluster_controller.go +++ b/internal/controllers/topology/cluster/cluster_controller.go @@ -71,6 +71,7 @@ type Reconciler struct { // WatchFilterValue is the label value used to filter events prior to reconciliation. WatchFilterValue string + Filter predicates.Filter // UnstructuredCachingClient provides a client that forces caching of unstructured objects, // thus allowing to optimize reads for templates or provider specific objects in a managed topology. @@ -144,6 +145,9 @@ func (r *Reconciler) Reconcile(ctx context.Context, req ctrl.Request) (_ ctrl.Re // Error reading the object - requeue the request. return ctrl.Result{}, err } + if r.Filter != nil && !r.Filter.Filter(cluster) { + return ctrl.Result{}, nil + } cluster.APIVersion = clusterv1.GroupVersion.String() cluster.Kind = "Cluster" diff --git a/internal/controllers/topology/machinedeployment/machinedeployment_controller.go b/internal/controllers/topology/machinedeployment/machinedeployment_controller.go index 4d5bbf2d174a..20e8ba2e3386 100644 --- a/internal/controllers/topology/machinedeployment/machinedeployment_controller.go +++ b/internal/controllers/topology/machinedeployment/machinedeployment_controller.go @@ -52,6 +52,7 @@ type Reconciler struct { // race conditions caused by an outdated cache. APIReader client.Reader WatchFilterValue string + Filter predicates.Filter } func (r *Reconciler) SetupWithManager(ctx context.Context, mgr ctrl.Manager, options controller.Options) error { @@ -98,7 +99,9 @@ func (r *Reconciler) Reconcile(ctx context.Context, req ctrl.Request) (_ ctrl.Re // Error reading the object - requeue the request. return ctrl.Result{}, errors.Wrapf(err, "failed to get MachineDeployment/%s", req.NamespacedName.Name) } - + if r.Filter != nil && !r.Filter.Filter(md) { + return ctrl.Result{}, nil + } log = log.WithValues("Cluster", klog.KRef(md.Namespace, md.Spec.ClusterName)) ctx = ctrl.LoggerInto(ctx, log) diff --git a/internal/controllers/topology/machineset/machineset_controller.go b/internal/controllers/topology/machineset/machineset_controller.go index 58c526680107..932d3ed4c223 100644 --- a/internal/controllers/topology/machineset/machineset_controller.go +++ b/internal/controllers/topology/machineset/machineset_controller.go @@ -54,6 +54,7 @@ type Reconciler struct { // race conditions caused by an outdated cache. APIReader client.Reader WatchFilterValue string + Filter predicates.Filter } func (r *Reconciler) SetupWithManager(ctx context.Context, mgr ctrl.Manager, options controller.Options) error { @@ -98,7 +99,9 @@ func (r *Reconciler) Reconcile(ctx context.Context, req ctrl.Request) (_ ctrl.Re // Error reading the object - requeue the request. return ctrl.Result{}, errors.Wrapf(err, "failed to get MachineSet/%s", req.NamespacedName.Name) } - + if r.Filter != nil && !r.Filter.Filter(ms) { + return ctrl.Result{}, nil + } // AddOwners adds the owners of MachineSet as k/v pairs to the logger. // Specifically, it will add MachineDeployment. ctx, log, err := clog.AddOwners(ctx, r.Client, ms) diff --git a/util/predicates/generic_predicates.go b/util/predicates/generic_predicates.go index ccce5de6d1da..75b82a195bd9 100644 --- a/util/predicates/generic_predicates.go +++ b/util/predicates/generic_predicates.go @@ -28,6 +28,12 @@ import ( "sigs.k8s.io/cluster-api/util/labels" ) +// Filter is used to filter whether an object should be reconciled. +type Filter interface { + // Filter decides whether an object should be reconciled. + Filter(object client.Object) bool +} + // All returns a predicate that returns true only if all given predicates return true. func All(logger logr.Logger, predicates ...predicate.Funcs) predicate.Funcs { return predicate.Funcs{