@@ -25,6 +25,7 @@ import (
25
25
26
26
"github.com/spf13/cobra"
27
27
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
28
+ apimachruntime "k8s.io/apimachinery/pkg/runtime"
28
29
"k8s.io/client-go/rest"
29
30
ctrl "sigs.k8s.io/controller-runtime"
30
31
"sigs.k8s.io/controller-runtime/pkg/cache"
@@ -45,6 +46,10 @@ import (
45
46
"github.com/operator-framework/operator-sdk/internal/helm/watches"
46
47
"github.com/operator-framework/operator-sdk/internal/util/k8sutil"
47
48
sdkVersion "github.com/operator-framework/operator-sdk/internal/version"
49
+ "helm.sh/helm/v3/pkg/chart/loader"
50
+ "k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
51
+ "k8s.io/apimachinery/pkg/labels"
52
+ "k8s.io/apimachinery/pkg/selection"
48
53
)
49
54
50
55
var log = logf .Log .WithName ("cmd" )
@@ -136,6 +141,23 @@ func run(cmd *cobra.Command, f *flags.Flags) {
136
141
// Set default manager options
137
142
options = f .ToManagerOptions (options )
138
143
144
+ if options .Scheme == nil {
145
+ options .Scheme = apimachruntime .NewScheme ()
146
+ }
147
+
148
+ ws , err := watches .Load (f .WatchesFile )
149
+ if err != nil {
150
+ log .Error (err , "Failed to load watches file." )
151
+ os .Exit (1 )
152
+ }
153
+
154
+ watchNamespaces := getWatchNamespaces (options .Namespace )
155
+ options .NewCache , err = buildNewCacheFunc (watchNamespaces , ws , options .Scheme )
156
+ if err != nil {
157
+ log .Error (err , "Failed to create NewCache function for manager." )
158
+ os .Exit (1 )
159
+ }
160
+
139
161
if options .NewClient == nil {
140
162
options .NewClient = func (cache cache.Cache , config * rest.Config , options client.Options , uncachedObjects ... client.Object ) (client.Client , error ) {
141
163
// Create the Client for Write operations.
@@ -152,27 +174,6 @@ func run(cmd *cobra.Command, f *flags.Flags) {
152
174
})
153
175
}
154
176
}
155
- namespace , found := os .LookupEnv (k8sutil .WatchNamespaceEnvVar )
156
- log = log .WithValues ("Namespace" , namespace )
157
- if found {
158
- log .V (1 ).Info (fmt .Sprintf ("Setting namespace with value in %s" , k8sutil .WatchNamespaceEnvVar ))
159
- if namespace == metav1 .NamespaceAll {
160
- log .Info ("Watching all namespaces." )
161
- options .Namespace = metav1 .NamespaceAll
162
- } else {
163
- if strings .Contains (namespace , "," ) {
164
- log .Info ("Watching multiple namespaces." )
165
- options .NewCache = cache .MultiNamespacedCacheBuilder (strings .Split (namespace , "," ))
166
- } else {
167
- log .Info ("Watching single namespace." )
168
- options .Namespace = namespace
169
- }
170
- }
171
- } else if options .Namespace == "" {
172
- log .Info (fmt .Sprintf ("Watch namespaces not configured by environment variable %s or file. " +
173
- "Watching all namespaces." , k8sutil .WatchNamespaceEnvVar ))
174
- options .Namespace = metav1 .NamespaceAll
175
- }
176
177
177
178
mgr , err := manager .New (cfg , options )
178
179
if err != nil {
@@ -189,11 +190,6 @@ func run(cmd *cobra.Command, f *flags.Flags) {
189
190
os .Exit (1 )
190
191
}
191
192
192
- ws , err := watches .Load (f .WatchesFile )
193
- if err != nil {
194
- log .Error (err , "Failed to create new manager factories." )
195
- os .Exit (1 )
196
- }
197
193
acg , err := helmClient .NewActionConfigGetter (mgr .GetConfig (), mgr .GetRESTMapper (), mgr .GetLogger ())
198
194
if err != nil {
199
195
log .Error (err , "Failed to create Helm action config getter" )
@@ -207,7 +203,6 @@ func run(cmd *cobra.Command, f *flags.Flags) {
207
203
}
208
204
209
205
err := controller .Add (mgr , controller.WatchOptions {
210
- Namespace : namespace ,
211
206
GVK : w .GroupVersionKind ,
212
207
ManagerFactory : release .NewManagerFactory (mgr , acg , w .ChartDir ),
213
208
ReconcilePeriod : reconcilePeriod ,
@@ -250,3 +245,67 @@ func exitIfUnsupported(options manager.Options) {
250
245
os .Exit (1 )
251
246
}
252
247
}
248
+
249
+ func getWatchNamespaces (defaultNamespace string ) []string {
250
+ namespace , found := os .LookupEnv (k8sutil .WatchNamespaceEnvVar )
251
+ log = log .WithValues ("Namespace" , namespace )
252
+ if found {
253
+ log .V (1 ).Info (fmt .Sprintf ("Setting namespace with value in %s" , k8sutil .WatchNamespaceEnvVar ))
254
+ if namespace == metav1 .NamespaceAll {
255
+ log .Info ("Watching all namespaces." )
256
+ return []string {metav1 .NamespaceAll }
257
+ }
258
+ if strings .Contains (namespace , "," ) {
259
+ log .Info ("Watching multiple namespaces." )
260
+ return strings .Split (namespace , "," )
261
+ }
262
+ log .Info ("Watching single namespace." )
263
+ return []string {namespace }
264
+ }
265
+ if defaultNamespace == "" {
266
+ log .Info (fmt .Sprintf ("Watch namespaces not configured by environment variable %s or file. " +
267
+ "Watching all namespaces." , k8sutil .WatchNamespaceEnvVar ))
268
+ return []string {metav1 .NamespaceAll }
269
+ }
270
+ return []string {defaultNamespace }
271
+ }
272
+
273
+ func buildNewCacheFunc (watchNamespaces []string , ws []watches.Watch , sch * apimachruntime.Scheme ) (cache.NewCacheFunc , error ) {
274
+ selectorsByObject := cache.SelectorsByObject {}
275
+ chartNames := make ([]string , 0 , len (ws ))
276
+ for _ , w := range ws {
277
+ sch .AddKnownTypeWithName (w .GroupVersionKind , & unstructured.Unstructured {})
278
+
279
+ crObj := & unstructured.Unstructured {}
280
+ crObj .SetGroupVersionKind (w .GroupVersionKind )
281
+ sel , err := metav1 .LabelSelectorAsSelector (& w .Selector )
282
+ if err != nil {
283
+ return nil , fmt .Errorf ("unable to parse watch selector for %s: %v" , w .GroupVersionKind , err )
284
+ }
285
+ selectorsByObject [crObj ] = cache.ObjectSelector {Label : sel }
286
+
287
+ chrt , err := loader .LoadDir (w .ChartDir )
288
+ if err != nil {
289
+ return nil , fmt .Errorf ("unable to load chart for %s: %v" , w .GroupVersionKind , err )
290
+ }
291
+ chartNames = append (chartNames , chrt .Name ())
292
+
293
+ }
294
+ req , err := labels .NewRequirement ("helm.sdk.operatorframework.io/chart" , selection .In , chartNames )
295
+ if err != nil {
296
+ return nil , fmt .Errorf ("unable to create label requirement for cache default selector: %v" , err )
297
+ }
298
+ defaultSelector := labels .NewSelector ().Add (* req )
299
+
300
+ return func (config * rest.Config , opts cache.Options ) (cache.Cache , error ) {
301
+ opts .SelectorsByObject = selectorsByObject
302
+ opts .DefaultSelector = cache.ObjectSelector {Label : defaultSelector }
303
+ if len (watchNamespaces ) > 1 {
304
+ return cache .MultiNamespacedCacheBuilder (watchNamespaces )(config , opts )
305
+ }
306
+ if len (watchNamespaces ) == 1 {
307
+ opts .Namespace = watchNamespaces [0 ]
308
+ }
309
+ return cache .New (config , opts )
310
+ }, nil
311
+ }
0 commit comments