@@ -12,8 +12,6 @@ import (
12
12
k8serrors "k8s.io/apimachinery/pkg/api/errors"
13
13
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
14
14
"k8s.io/apimachinery/pkg/labels"
15
- "k8s.io/apimachinery/pkg/runtime"
16
- "k8s.io/apimachinery/pkg/types"
17
15
utilruntime "k8s.io/apimachinery/pkg/util/runtime"
18
16
"k8s.io/client-go/informers"
19
17
"k8s.io/client-go/tools/cache"
@@ -50,13 +48,14 @@ const (
50
48
51
49
type Operator struct {
52
50
* queueinformer.Operator
53
- csvQueueSet queueinformer.ResourceQueueSet
54
- ogQueueSet queueinformer.ResourceQueueSet
55
- client versioned.Interface
56
- resolver install.StrategyResolverInterface
57
- apiReconciler resolver.APIIntersectionReconciler
58
- lister operatorlister.OperatorLister
59
- recorder record.EventRecorder
51
+ csvQueueSet queueinformer.ResourceQueueSet
52
+ ogQueueSet queueinformer.ResourceQueueSet
53
+ client versioned.Interface
54
+ resolver install.StrategyResolverInterface
55
+ apiReconciler resolver.APIIntersectionReconciler
56
+ lister operatorlister.OperatorLister
57
+ recorder record.EventRecorder
58
+ copyQueueIndexer * queueinformer.QueueIndexer
60
59
}
61
60
62
61
func NewOperator (logger * logrus.Logger , crClient versioned.Interface , opClient operatorclient.ClientInterface , strategyResolver install.StrategyResolverInterface , wakeupInterval time.Duration , namespaces []string ) (* Operator , error ) {
@@ -146,7 +145,10 @@ func NewOperator(logger *logrus.Logger, crClient versioned.Interface, opClient o
146
145
workqueue .NewNamedRateLimitingQueue (workqueue .DefaultControllerRateLimiter (), "namespaces" ),
147
146
namespaceInformer .Informer (),
148
147
op .syncObject ,
149
- nil ,
148
+ & cache.ResourceEventHandlerFuncs {
149
+ DeleteFunc : op .namespaceAddedOrRemoved ,
150
+ AddFunc : op .namespaceAddedOrRemoved ,
151
+ },
150
152
"namespaces" ,
151
153
metrics .NewMetricsNil (),
152
154
logger ,
@@ -229,6 +231,8 @@ func NewOperator(logger *logrus.Logger, crClient versioned.Interface, opClient o
229
231
))
230
232
op .lister .CoreV1 ().RegisterServiceAccountLister (metav1 .NamespaceAll , serviceAccountInformer .Lister ())
231
233
234
+ csvIndexes := map [string ]cache.Indexer {}
235
+
232
236
// csvInformers for each namespace all use the same backing queue keys are namespaced
233
237
csvHandlers := & cache.ResourceEventHandlerFuncs {
234
238
DeleteFunc : op .handleClusterServiceVersionDeletion ,
@@ -245,8 +249,16 @@ func NewOperator(logger *logrus.Logger, crClient versioned.Interface, opClient o
245
249
csvQueueInformer := queueinformer .NewInformer (csvQueue , csvInformer .Informer (), op .syncClusterServiceVersion , csvHandlers , queueName , metrics .NewMetricsCSV (op .lister .OperatorsV1alpha1 ().ClusterServiceVersionLister ()), logger )
246
250
op .RegisterQueueInformer (csvQueueInformer )
247
251
op .csvQueueSet [namespace ] = csvQueue
252
+
253
+ csvIndexes [namespace ] = csvInformer .Informer ().GetIndexer ()
248
254
}
249
255
256
+ // Register separate queue for copying csvs
257
+ csvCopyQueue := workqueue .NewNamedRateLimitingQueue (workqueue .DefaultControllerRateLimiter (), "csvCopy" )
258
+ csvQueueIndexer := queueinformer .NewQueueIndexer (csvCopyQueue , csvIndexes , op .syncCopyCSV , "csvCopy" , logger , metrics .NewMetricsNil ())
259
+ op .RegisterQueueIndexer (csvQueueIndexer )
260
+ op .copyQueueIndexer = csvQueueIndexer
261
+
250
262
// Set up watch on deployments
251
263
depHandlers := & cache.ResourceEventHandlerFuncs {
252
264
// TODO: pass closure that forgets queue item after calling custom deletion handler.
@@ -283,35 +295,19 @@ func NewOperator(logger *logrus.Logger, crClient versioned.Interface, opClient o
283
295
}
284
296
285
297
func (a * Operator ) syncObject (obj interface {}) (syncError error ) {
286
- // Assert as runtime.Object
287
- runtimeObj , ok := obj .(runtime.Object )
288
- if ! ok {
289
- syncError = errors .New ("object sync: casting to runtime.Object failed" )
290
- a .Log .Warn (syncError .Error ())
291
- return
292
- }
293
-
294
- gvk := runtimeObj .GetObjectKind ().GroupVersionKind ()
295
- logger := a .Log .WithFields (logrus.Fields {
296
- "group" : gvk .Group ,
297
- "version" : gvk .Version ,
298
- "kind" : gvk .Kind ,
299
- })
300
-
301
298
// Assert as metav1.Object
302
299
metaObj , ok := obj .(metav1.Object )
303
300
if ! ok {
304
301
syncError = errors .New ("object sync: casting to metav1.Object failed" )
305
- logger .Warn (syncError .Error ())
302
+ a . Log .Warn (syncError .Error ())
306
303
return
307
304
}
308
- logger = a .Log .WithFields (logrus.Fields {
305
+ logger : = a .Log .WithFields (logrus.Fields {
309
306
"name" : metaObj .GetName (),
310
307
"namespace" : metaObj .GetNamespace (),
308
+ "sel" : metaObj .GetSelfLink (),
311
309
})
312
310
313
- logger .Debug ("syncing" )
314
-
315
311
// Requeue all owner CSVs
316
312
if ownerutil .IsOwnedByKind (metaObj , v1alpha1 .ClusterServiceVersionKind ) {
317
313
logger .Debug ("requeueing owner CSVs" )
@@ -324,29 +320,34 @@ func (a *Operator) syncObject(obj interface{}) (syncError error) {
324
320
a .requeueOwnerCSVs (metaObj )
325
321
}
326
322
327
- // TODO: only check this on namespace add/delete, not on every namespace sync
323
+ return nil
324
+ }
325
+
326
+ func (a * Operator ) namespaceAddedOrRemoved (obj interface {}) {
328
327
// Check to see if any operator groups are associated with this namespace
329
328
namespace , ok := obj .(* corev1.Namespace )
330
329
if ! ok {
331
- return nil
330
+ return
332
331
}
333
332
333
+ logger := a .Log .WithFields (logrus.Fields {
334
+ "name" : namespace .GetName (),
335
+ })
336
+
334
337
operatorGroupList , err := a .lister .OperatorsV1alpha2 ().OperatorGroupLister ().OperatorGroups (metav1 .NamespaceAll ).List (labels .Everything ())
335
338
if err != nil {
336
- syncError = fmt .Errorf ("lister failed: %v" , err )
337
- logger .Warn (syncError .Error ())
339
+ logger .WithError (err ).Warn ("lister failed" )
338
340
return
339
341
}
340
342
341
343
for _ , group := range operatorGroupList {
342
344
if resolver .NewNamespaceSet (group .Status .Namespaces ).Contains (namespace .GetName ()) {
343
345
if err := a .ogQueueSet .Requeue (group .Name , group .Namespace ); err != nil {
344
- logger .Warn (err )
346
+ logger .WithError (err ). Warn ( "error requeuing operatorgroup" )
345
347
}
346
348
}
347
349
}
348
-
349
- return nil
350
+ return
350
351
}
351
352
352
353
func (a * Operator ) handleClusterServiceVersionDeletion (obj interface {}) {
@@ -482,8 +483,9 @@ func (a *Operator) removeDanglingChildCSVs(csv *v1alpha1.ClusterServiceVersion)
482
483
}
483
484
484
485
if annotations := parent .GetAnnotations (); annotations != nil {
485
- if resolver .NewNamespaceSet (strings .Split (annotations [v1alpha2 .OperatorGroupTargetsAnnotationKey ], "," )).Contains (csv .GetNamespace ()) {
486
- logger .Debug ("deleting copied CSV since parent no longer lists this as a target namespace" )
486
+ if ! resolver .NewNamespaceSetFromString (annotations [v1alpha2 .OperatorGroupTargetsAnnotationKey ]).Contains (csv .GetNamespace ()) {
487
+ logger .WithField ("parentTargets" , annotations [v1alpha2 .OperatorGroupTargetsAnnotationKey ]).
488
+ Debug ("deleting copied CSV since parent no longer lists this as a target namespace" )
487
489
return a .deleteChild (csv )
488
490
}
489
491
}
@@ -513,6 +515,10 @@ func (a *Operator) syncClusterServiceVersion(obj interface{}) (syncError error)
513
515
514
516
outCSV , syncError := a .transitionCSVState (* clusterServiceVersion )
515
517
518
+ if outCSV == nil {
519
+ return
520
+ }
521
+
516
522
// status changed, update CSV
517
523
if ! (outCSV .Status .LastUpdateTime == clusterServiceVersion .Status .LastUpdateTime &&
518
524
outCSV .Status .Phase == clusterServiceVersion .Status .Phase &&
@@ -536,27 +542,55 @@ func (a *Operator) syncClusterServiceVersion(obj interface{}) (syncError error)
536
542
return
537
543
}
538
544
539
- operatorGroup := a .operatorGroupForActiveCSV (logger , outCSV )
545
+ a .copyQueueIndexer .Enqueue (outCSV )
546
+
547
+ return
548
+ }
549
+
550
+ func (a * Operator ) syncCopyCSV (obj interface {}) (syncError error ) {
551
+ clusterServiceVersion , ok := obj .(* v1alpha1.ClusterServiceVersion )
552
+ if ! ok {
553
+ a .Log .Debugf ("wrong type: %#v" , obj )
554
+ return fmt .Errorf ("casting ClusterServiceVersion failed" )
555
+ }
556
+
557
+ logger := a .Log .WithFields (logrus.Fields {
558
+ "id" : queueinformer .NewLoopID (),
559
+ "csv" : clusterServiceVersion .GetName (),
560
+ "namespace" : clusterServiceVersion .GetNamespace (),
561
+ "phase" : clusterServiceVersion .Status .Phase ,
562
+ })
563
+
564
+ logger .Debug ("copying CSV" )
565
+
566
+ operatorGroup := a .operatorGroupForActiveCSV (logger , clusterServiceVersion )
540
567
if operatorGroup == nil {
541
- logger .WithField ("reason" , "no operatorgroup found for active CSV" ).Info ("skipping CSV resource copy to target namespaces" )
568
+ logger .WithField ("reason" , "no operatorgroup found for active CSV" ).Debug ("skipping CSV resource copy to target namespaces" )
569
+ return
570
+ }
571
+
572
+ if len (operatorGroup .Status .Namespaces ) == 1 && operatorGroup .Status .Namespaces [0 ] == operatorGroup .GetNamespace () {
573
+ logger .Debug ("skipping copy for OwnNamespace operatorgroup" )
542
574
return
543
575
}
544
576
545
577
// Check if we need to do any copying / annotation for the operatorgroup
546
578
if err := a .ensureCSVsInNamespaces (clusterServiceVersion , operatorGroup , resolver .NewNamespaceSet (operatorGroup .Status .Namespaces )); err != nil {
547
579
logger .WithError (err ).Info ("couldn't copy CSV to target namespaces" )
580
+ syncError = err
548
581
}
549
582
550
583
// Ensure operator has access to targetnamespaces
551
- if err := a .ensureRBACInTargetNamespace (outCSV , operatorGroup ); err != nil {
584
+ if err := a .ensureRBACInTargetNamespace (clusterServiceVersion , operatorGroup ); err != nil {
552
585
logger .WithError (err ).Info ("couldn't ensure RBAC in target namespaces" )
586
+ syncError = err
553
587
}
554
588
555
589
// Ensure cluster roles exist for using provided apis
556
- if err := a .ensureClusterRolesForCSV (outCSV , operatorGroup ); err != nil {
590
+ if err := a .ensureClusterRolesForCSV (clusterServiceVersion , operatorGroup ); err != nil {
557
591
logger .WithError (err ).Info ("couldn't ensure clusterroles for provided api types" )
592
+ syncError = err
558
593
}
559
-
560
594
return
561
595
}
562
596
@@ -1214,51 +1248,22 @@ func (a *Operator) requeueOwnerCSVs(ownee metav1.Object) {
1214
1248
1215
1249
// Attempt to requeue CSV owners in the same namespace as the object
1216
1250
owners := ownerutil .GetOwnersByKind (ownee , v1alpha1 .ClusterServiceVersionKind )
1217
- if len (owners ) == 0 {
1218
- logger .Debugf ("No ownerreferences found" )
1219
- return
1220
- }
1221
-
1222
- if ownee .GetNamespace () != metav1 .NamespaceAll {
1251
+ if len (owners ) > 0 && ownee .GetNamespace () != metav1 .NamespaceAll {
1223
1252
for _ , ownerCSV := range owners {
1224
1253
// Since cross-namespace CSVs can't exist we're guaranteed the owner will be in the same namespace
1225
1254
err := a .csvQueueSet .Requeue (ownerCSV .Name , ownee .GetNamespace ())
1226
1255
if err != nil {
1227
- a . Log .Warn (err .Error ())
1256
+ logger .Warn (err .Error ())
1228
1257
}
1229
1258
}
1230
-
1231
1259
return
1232
1260
}
1233
1261
1234
- // Get all existing CSVs from the indexer
1235
- csvs , err := a .lister .OperatorsV1alpha1 ().ClusterServiceVersionLister ().List (labels .Everything ())
1236
- if err != nil {
1237
- logger .Warnf ("error attempting to list all CSVs in indexer: %s" , err .Error ())
1238
- return
1239
- }
1240
- if len (csvs ) == 0 {
1241
- logger .Infof ("no existing CSVs found" )
1242
- return
1243
- }
1244
-
1245
- csvSet := make (map [types.UID ]* v1alpha1.ClusterServiceVersion , len (csvs ))
1246
- for _ , csv := range csvs {
1247
- csvSet [csv .GetUID ()] = csv
1248
- }
1249
- logger .WithField ("clusterwide" , len (csvs )).Debug ("number of csvs" )
1250
-
1251
- // Requeue existing owner CSVs
1252
- for _ , owner := range owners {
1253
- csv , ok := csvSet [owner .UID ]
1254
- if ! ok {
1255
- logger .Warnf ("owner %v does not exist" , owner .UID )
1256
- continue
1257
- }
1258
-
1259
- err = a .csvQueueSet .Requeue (csv .GetName (), csv .GetNamespace ())
1262
+ // Requeue owners based on labels
1263
+ if name , ns , ok := ownerutil .GetOwnerByKindLabel (ownee , v1alpha1 .ClusterServiceVersionKind ); ok {
1264
+ err := a .csvQueueSet .Requeue (name , ns )
1260
1265
if err != nil {
1261
- a . Log .Warn (err .Error ())
1266
+ logger .Warn (err .Error ())
1262
1267
}
1263
1268
}
1264
1269
}
0 commit comments