Skip to content

Commit 778aed5

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 7055812 commit 778aed5

File tree

1 file changed

+61
-19
lines changed

1 file changed

+61
-19
lines changed

pkg/addon/controllers/addontemplate/controller.go

Lines changed: 61 additions & 19 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.RateLimitingInterface
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,35 +97,70 @@ 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+
// following the pattern from managedClusterSetController
117+
_, err := addonInformers.Addon().V1alpha1().ManagedClusterAddOns().Informer().AddEventHandler(cache.ResourceEventHandlerFuncs{
118+
UpdateFunc: func(oldObj, newObj interface{}) {
119+
// Only handle configReference updates for AddOnTemplates
120+
oldMCA, ok := oldObj.(*addonv1alpha1.ManagedClusterAddOn)
121+
if !ok {
122+
return
123+
}
124+
newMCA, ok := newObj.(*addonv1alpha1.ManagedClusterAddOn)
125+
if !ok {
126+
return
127+
}
128+
129+
// Extract AddOnTemplate configReferences from both old and new
130+
oldTemplateRefs := extractAddOnTemplateConfigRefs(oldMCA)
131+
newTemplateRefs := extractAddOnTemplateConfigRefs(newMCA)
132+
133+
// Only process if AddOnTemplate configReferences changed
134+
if !reflect.DeepEqual(oldTemplateRefs, newTemplateRefs) {
135+
// Queue the addon name to trigger reconciliation
136+
c.queue.Add(newMCA.Name)
137+
}
138+
},
139+
DeleteFunc: func(obj interface{}) {
140+
mca, ok := obj.(*addonv1alpha1.ManagedClusterAddOn)
141+
if !ok {
142+
return
143+
}
144+
c.queue.Add(mca.Name)
145+
},
146+
})
147+
if err != nil {
148+
utilruntime.HandleError(err)
149+
}
150+
151+
return controller
152+
}
153+
154+
// extractAddOnTemplateConfigRefs extracts only AddOnTemplate configReferences
155+
func extractAddOnTemplateConfigRefs(mca *addonv1alpha1.ManagedClusterAddOn) []addonv1alpha1.ConfigReference {
156+
var templateRefs []addonv1alpha1.ConfigReference
157+
for _, configRef := range mca.Status.ConfigReferences {
158+
if configRef.ConfigGroupResource.Group == "addon.open-cluster-management.io" &&
159+
configRef.ConfigGroupResource.Resource == "addontemplates" {
160+
templateRefs = append(templateRefs, configRef)
161+
}
162+
}
163+
return templateRefs
122164
}
123165

124166
func (c *addonTemplateController) stopUnusedManagers(

0 commit comments

Comments
 (0)