Skip to content

Commit b6b7e9e

Browse files
committed
Add custom informer for ManagedClusterAddOns
Signed-off-by: fxiang1 <[email protected]>
1 parent 3267edb commit b6b7e9e

File tree

7 files changed

+666
-87
lines changed

7 files changed

+666
-87
lines changed

controllers/clusterpermission_controller.go

Lines changed: 79 additions & 73 deletions
Original file line numberDiff line numberDiff line change
@@ -30,12 +30,8 @@ import (
3030
"k8s.io/apimachinery/pkg/types"
3131
"k8s.io/client-go/util/retry"
3232
ctrl "sigs.k8s.io/controller-runtime"
33-
"sigs.k8s.io/controller-runtime/pkg/builder"
3433
"sigs.k8s.io/controller-runtime/pkg/client"
35-
"sigs.k8s.io/controller-runtime/pkg/event"
36-
"sigs.k8s.io/controller-runtime/pkg/handler"
3734
"sigs.k8s.io/controller-runtime/pkg/log"
38-
"sigs.k8s.io/controller-runtime/pkg/predicate"
3935
"sigs.k8s.io/controller-runtime/pkg/reconcile"
4036

4137
corev1 "k8s.io/api/core/v1"
@@ -54,43 +50,94 @@ const VALIDATION_MW_RETRY_INTERVAL = 10 * time.Second
5450
type ClusterPermissionReconciler struct {
5551
client.Client
5652
Scheme *runtime.Scheme
53+
// customInformer is the custom informer for ManagedClusterAddOn resources
54+
customInformer *ManagedClusterAddOnInformer
5755
}
5856

5957
// SetupWithManager sets up the controller with the Manager.
6058
func (r *ClusterPermissionReconciler) SetupWithManager(mgr ctrl.Manager) error {
59+
// Create custom informer for ManagedClusterAddOn resources
60+
config := mgr.GetConfig()
61+
eventHandler := r.createCustomInformerEventHandler()
62+
63+
customInformer, err := NewManagedClusterAddOnInformer(config, eventHandler)
64+
if err != nil {
65+
return err
66+
}
67+
68+
// Store the custom informer in the reconciler
69+
r.customInformer = customInformer
70+
71+
// Start the custom informer in a goroutine
72+
go func() {
73+
if err := customInformer.Start(); err != nil {
74+
log.Log.Error(err, "Failed to start custom ManagedClusterAddOn informer")
75+
}
76+
}()
77+
78+
// Setup the controller without the built-in ManagedClusterAddOn watching
79+
// since we're using the custom informer instead
6180
return ctrl.NewControllerManagedBy(mgr).
6281
For(&cpv1alpha1.ClusterPermission{}).
63-
Watches(&addonv1alpha1.ManagedClusterAddOn{},
64-
r.managedClusterAddOnEventHandler(),
65-
builder.WithPredicates(predicate.Funcs{
66-
CreateFunc: func(e event.CreateEvent) bool {
67-
return false // Don't process Create events
68-
},
69-
UpdateFunc: func(e event.UpdateEvent) bool {
70-
// Only process Update events for managed-serviceaccount addon when status.namespace changes
71-
oldAddon, oldOk := e.ObjectOld.(*addonv1alpha1.ManagedClusterAddOn)
72-
newAddon, newOk := e.ObjectNew.(*addonv1alpha1.ManagedClusterAddOn)
82+
Complete(r)
83+
}
7384

74-
if !oldOk || !newOk {
75-
return false
76-
}
85+
// Stop stops the custom informer if it exists
86+
func (r *ClusterPermissionReconciler) Stop() {
87+
if r.customInformer != nil {
88+
r.customInformer.Stop()
89+
}
90+
}
7791

78-
// Only process if this is the managed-serviceaccount addon
79-
if newAddon.Name != msacommon.AddonName {
80-
return false
81-
}
92+
// createCustomInformerEventHandler creates an event handler for the custom informer
93+
func (r *ClusterPermissionReconciler) createCustomInformerEventHandler() func(obj *addonv1alpha1.ManagedClusterAddOn) {
94+
return func(addon *addonv1alpha1.ManagedClusterAddOn) {
95+
log := log.Log.WithName("CustomInformerEventHandler")
8296

83-
// Only process if status.namespace has changed
84-
return oldAddon.Status.Namespace != newAddon.Status.Namespace
85-
},
86-
DeleteFunc: func(e event.DeleteEvent) bool {
87-
return false // Don't process Delete events
88-
},
89-
GenericFunc: func(e event.GenericEvent) bool {
90-
return false // Don't process Generic events
91-
},
92-
})).
93-
Complete(r)
97+
// Find all ClusterPermissions in this addon's namespace that have ManagedServiceAccount subjects
98+
ctx := context.Background()
99+
var clusterPermissions cpv1alpha1.ClusterPermissionList
100+
err := r.List(ctx, &clusterPermissions, &client.ListOptions{
101+
Namespace: addon.Namespace,
102+
})
103+
if err != nil {
104+
log.Error(err, "failed to list ClusterPermissions", "namespace", addon.Namespace)
105+
return
106+
}
107+
108+
// Process each ClusterPermission that uses ManagedServiceAccount
109+
for _, cp := range clusterPermissions.Items {
110+
if r.clusterPermissionUsesManagedServiceAccount(&cp) {
111+
log.Info("Triggering reconciliation for ClusterPermission due to ManagedClusterAddOn change",
112+
"clusterPermission", cp.Name,
113+
"namespace", cp.Namespace,
114+
"addonNamespace", addon.Status.Namespace,
115+
)
116+
117+
// Trigger reconciliation by updating the ClusterPermission
118+
r.reconcileClusterPermission(ctx, &cp)
119+
}
120+
}
121+
}
122+
}
123+
124+
// reconcileClusterPermission triggers reconciliation of a specific ClusterPermission
125+
func (r *ClusterPermissionReconciler) reconcileClusterPermission(ctx context.Context, cp *cpv1alpha1.ClusterPermission) {
126+
log := log.FromContext(ctx)
127+
128+
// Create a reconcile request
129+
req := reconcile.Request{
130+
NamespacedName: types.NamespacedName{
131+
Name: cp.Name,
132+
Namespace: cp.Namespace,
133+
},
134+
}
135+
136+
// Call the reconcile function directly
137+
_, err := r.Reconcile(ctx, req)
138+
if err != nil {
139+
log.Error(err, "Failed to reconcile ClusterPermission", "name", cp.Name, "namespace", cp.Namespace)
140+
}
94141
}
95142

96143
//+kubebuilder:rbac:groups=rbac.open-cluster-management.io,resources=clusterpermissions,verbs=get;list;watch;create;update;patch;delete
@@ -694,47 +741,6 @@ func joinStrings(strings []string, separator string) string {
694741
return result
695742
}
696743

697-
// managedClusterAddOnEventHandler returns an event handler that reconciles ClusterPermissions
698-
// when a ManagedClusterAddOn's status.namespace changes
699-
func (r *ClusterPermissionReconciler) managedClusterAddOnEventHandler() handler.EventHandler {
700-
return handler.EnqueueRequestsFromMapFunc(func(ctx context.Context, obj client.Object) []reconcile.Request {
701-
log := log.FromContext(ctx)
702-
703-
addon, ok := obj.(*addonv1alpha1.ManagedClusterAddOn)
704-
if !ok {
705-
log.Error(nil, "object is not a ManagedClusterAddOn", "object", obj)
706-
return []reconcile.Request{}
707-
}
708-
709-
// Find all ClusterPermissions in this addon's namespace that have ManagedServiceAccount subjects
710-
var clusterPermissions cpv1alpha1.ClusterPermissionList
711-
err := r.List(ctx, &clusterPermissions, &client.ListOptions{
712-
Namespace: addon.Namespace,
713-
})
714-
if err != nil {
715-
log.Error(err, "failed to list ClusterPermissions", "namespace", addon.Namespace)
716-
return []reconcile.Request{}
717-
}
718-
719-
var requests []reconcile.Request
720-
for _, cp := range clusterPermissions.Items {
721-
if r.clusterPermissionUsesManagedServiceAccount(&cp) {
722-
requests = append(requests, reconcile.Request{
723-
NamespacedName: types.NamespacedName{
724-
Name: cp.Name,
725-
Namespace: cp.Namespace,
726-
},
727-
})
728-
}
729-
}
730-
731-
log.Info("ManagedClusterAddOn status.namespace changed, reconciling ClusterPermissions",
732-
"addon", addon.Name, "namespace", addon.Namespace, "requests", len(requests))
733-
734-
return requests
735-
})
736-
}
737-
738744
// clusterPermissionUsesManagedServiceAccount checks if a ClusterPermission uses ManagedServiceAccount subjects
739745
func (r *ClusterPermissionReconciler) clusterPermissionUsesManagedServiceAccount(cp *cpv1alpha1.ClusterPermission) bool {
740746
// Check ClusterRoleBinding

0 commit comments

Comments
 (0)