@@ -2,6 +2,7 @@ package addontemplate
2
2
3
3
import (
4
4
"context"
5
+ "reflect"
5
6
"time"
6
7
7
8
"github.com/openshift/library-go/pkg/controller/factory"
@@ -14,6 +15,7 @@ import (
14
15
"k8s.io/client-go/kubernetes"
15
16
"k8s.io/client-go/rest"
16
17
"k8s.io/client-go/tools/cache"
18
+ "k8s.io/client-go/util/workqueue"
17
19
"k8s.io/klog/v2"
18
20
19
21
"open-cluster-management.io/addon-framework/pkg/addonfactory"
@@ -52,6 +54,7 @@ type addonTemplateController struct {
52
54
workInformers workv1informers.SharedInformerFactory
53
55
runControllerFunc runController
54
56
eventRecorder events.Recorder
57
+ queue workqueue.RateLimitingInterface
55
58
}
56
59
57
60
type runController func (ctx context.Context , addonName string ) error
@@ -69,6 +72,9 @@ func NewAddonTemplateController(
69
72
recorder events.Recorder ,
70
73
runController ... runController ,
71
74
) factory.Controller {
75
+ controllerName := "addon-template-controller"
76
+ syncCtx := factory .NewSyncContext (controllerName , recorder )
77
+
72
78
c := & addonTemplateController {
73
79
kubeConfig : hubKubeconfig ,
74
80
kubeClient : hubKubeClient ,
@@ -82,6 +88,7 @@ func NewAddonTemplateController(
82
88
dynamicInformers : dynamicInformers ,
83
89
workInformers : workInformers ,
84
90
eventRecorder : recorder ,
91
+ queue : syncCtx .Queue (),
85
92
}
86
93
87
94
if len (runController ) > 0 {
@@ -90,35 +97,70 @@ func NewAddonTemplateController(
90
97
// easy to mock in unit tests
91
98
c .runControllerFunc = c .runController
92
99
}
93
- return factory .New ().
100
+
101
+ controller := factory .New ().
102
+ WithSyncContext (syncCtx ).
94
103
WithInformersQueueKeysFunc (
95
104
queue .QueueKeyByMetaNamespaceName ,
96
105
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 ()).
115
106
WithBareInformers (
107
+ addonInformers .Addon ().V1alpha1 ().ManagedClusterAddOns ().Informer (),
116
108
// do not need to queue, just make sure the controller reconciles after the addonTemplate cache is synced
117
109
// otherwise, there will be "xx-addon-template" not found" errors in the log as the controller uses the
118
110
// addonTemplate lister to get the template object
119
111
addonInformers .Addon ().V1alpha1 ().AddOnTemplates ().Informer ()).
120
112
WithSync (c .sync ).
121
113
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
122
164
}
123
165
124
166
func (c * addonTemplateController ) stopUnusedManagers (
0 commit comments