Skip to content

Commit 4649d1b

Browse files
zhujian7claude
andcommitted
Optimize ManagedClusterAddOn event handling in addon template controller
Replace filtered event handling with custom event handlers that only trigger reconciliation when AddOnTemplate configReferences actually change. This reduces unnecessary reconciliation cycles by using reflect.DeepEqual to compare config references between old and new objects. 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude <[email protected]> Signed-off-by: zhujian <[email protected]>
1 parent cffc8eb commit 4649d1b

File tree

1 file changed

+66
-20
lines changed

1 file changed

+66
-20
lines changed

pkg/addon/controllers/addontemplate/controller.go

Lines changed: 66 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ package addontemplate
22

33
import (
44
"context"
5+
"reflect"
56
"time"
67

78
"github.com/openshift/library-go/pkg/controller/factory"
@@ -14,6 +15,7 @@ import (
1415
"k8s.io/client-go/kubernetes"
1516
"k8s.io/client-go/rest"
1617
"k8s.io/client-go/tools/cache"
18+
"k8s.io/client-go/util/workqueue"
1719
"k8s.io/klog/v2"
1820

1921
"open-cluster-management.io/addon-framework/pkg/addonfactory"
@@ -52,6 +54,7 @@ type addonTemplateController struct {
5254
workInformers workv1informers.SharedInformerFactory
5355
runControllerFunc runController
5456
eventRecorder events.Recorder
57+
queue workqueue.TypedRateLimitingInterface[any]
5558
}
5659

5760
type runController func(ctx context.Context, addonName string) error
@@ -69,6 +72,9 @@ func NewAddonTemplateController(
6972
recorder events.Recorder,
7073
runController ...runController,
7174
) factory.Controller {
75+
controllerName := "addon-template-controller"
76+
syncCtx := factory.NewSyncContext(controllerName, recorder)
77+
7278
c := &addonTemplateController{
7379
kubeConfig: hubKubeconfig,
7480
kubeClient: hubKubeClient,
@@ -82,6 +88,7 @@ func NewAddonTemplateController(
8288
dynamicInformers: dynamicInformers,
8389
workInformers: workInformers,
8490
eventRecorder: recorder,
91+
queue: syncCtx.Queue(),
8592
}
8693

8794
if len(runController) > 0 {
@@ -90,39 +97,78 @@ func NewAddonTemplateController(
9097
// easy to mock in unit tests
9198
c.runControllerFunc = c.runController
9299
}
93-
return factory.New().
100+
101+
controller := factory.New().
102+
WithSyncContext(syncCtx).
94103
WithInformersQueueKeysFunc(
95104
queue.QueueKeyByMetaNamespaceName,
96105
addonInformers.Addon().V1alpha1().ClusterManagementAddOns().Informer()).
97-
WithFilteredEventsInformersQueueKeysFunc(
98-
queue.QueueKeyByMetaName,
99-
func(obj interface{}) bool {
100-
mca, ok := obj.(*addonv1alpha1.ManagedClusterAddOn)
101-
if !ok {
102-
return false
103-
}
104-
105-
// Only process ManagedClusterAddOns that reference AddOnTemplates
106-
for _, configRef := range mca.Status.ConfigReferences {
107-
if configRef.ConfigGroupResource.Group == "addon.open-cluster-management.io" &&
108-
configRef.ConfigGroupResource.Resource == "addontemplates" {
109-
return true
110-
}
111-
}
112-
return false
113-
},
114-
addonInformers.Addon().V1alpha1().ManagedClusterAddOns().Informer()).
115106
WithBareInformers(
107+
addonInformers.Addon().V1alpha1().ManagedClusterAddOns().Informer(),
116108
// do not need to queue, just make sure the controller reconciles after the addonTemplate cache is synced
117109
// otherwise, there will be "xx-addon-template" not found" errors in the log as the controller uses the
118110
// addonTemplate lister to get the template object
119111
addonInformers.Addon().V1alpha1().AddOnTemplates().Informer()).
120112
WithSync(c.sync).
121113
ToController("addon-template-controller", recorder)
114+
115+
// Add custom event handler for ManagedClusterAddon to filter configReference changes
116+
_, err := addonInformers.Addon().V1alpha1().ManagedClusterAddOns().Informer().AddEventHandler(cache.ResourceEventHandlerFuncs{
117+
UpdateFunc: func(oldObj, newObj interface{}) {
118+
// Only handle configReference updates for AddOnTemplates
119+
oldMCA, ok := oldObj.(*addonv1alpha1.ManagedClusterAddOn)
120+
if !ok {
121+
return
122+
}
123+
newMCA, ok := newObj.(*addonv1alpha1.ManagedClusterAddOn)
124+
if !ok {
125+
return
126+
}
127+
128+
// Extract AddOnTemplate configReferences from both old and new
129+
oldTemplateRefs := extractAddOnTemplateConfigRefs(oldMCA)
130+
newTemplateRefs := extractAddOnTemplateConfigRefs(newMCA)
131+
132+
// Only process if AddOnTemplate configReferences changed
133+
if !reflect.DeepEqual(oldTemplateRefs, newTemplateRefs) {
134+
// Queue the addon name to trigger reconciliation
135+
c.queue.Add(newMCA.Name)
136+
}
137+
},
138+
DeleteFunc: func(obj interface{}) {
139+
mca, ok := obj.(*addonv1alpha1.ManagedClusterAddOn)
140+
if !ok {
141+
return
142+
}
143+
144+
// Only process template-based addons
145+
templateRefs := extractAddOnTemplateConfigRefs(mca)
146+
if len(templateRefs) > 0 {
147+
c.queue.Add(mca.Name)
148+
}
149+
},
150+
})
151+
if err != nil {
152+
utilruntime.HandleError(err)
153+
}
154+
155+
return controller
156+
}
157+
158+
// extractAddOnTemplateConfigRefs extracts only AddOnTemplate configReferences
159+
func extractAddOnTemplateConfigRefs(mca *addonv1alpha1.ManagedClusterAddOn) []addonv1alpha1.ConfigReference {
160+
var templateRefs []addonv1alpha1.ConfigReference
161+
for _, configRef := range mca.Status.ConfigReferences {
162+
if configRef.ConfigGroupResource.Group == "addon.open-cluster-management.io" &&
163+
configRef.ConfigGroupResource.Resource == "addontemplates" {
164+
templateRefs = append(templateRefs, configRef)
165+
}
166+
}
167+
return templateRefs
122168
}
123169

124170
func (c *addonTemplateController) stopUnusedManagers(
125-
ctx context.Context, syncCtx factory.SyncContext, addOnName string) error {
171+
ctx context.Context, _ factory.SyncContext, addOnName string) error {
126172
logger := klog.FromContext(ctx)
127173

128174
// Check if all managed cluster addon instances are deleted before stopping the manager

0 commit comments

Comments
 (0)