@@ -8,9 +8,11 @@ import (
8
8
"time"
9
9
10
10
v1 "github.com/operator-framework/operator-lifecycle-manager/pkg/api/apis/operators/v1"
11
+ "github.com/operator-framework/operator-lifecycle-manager/pkg/lib/kubestate"
11
12
"github.com/sirupsen/logrus"
12
13
log "github.com/sirupsen/logrus"
13
14
corev1 "k8s.io/api/core/v1"
15
+ rbacv1 "k8s.io/api/rbac/v1"
14
16
extinf "k8s.io/apiextensions-apiserver/pkg/client/informers/externalversions"
15
17
k8serrors "k8s.io/apimachinery/pkg/api/errors"
16
18
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
@@ -32,6 +34,7 @@ import (
32
34
"github.com/operator-framework/operator-lifecycle-manager/pkg/api/client/informers/externalversions"
33
35
"github.com/operator-framework/operator-lifecycle-manager/pkg/controller/certs"
34
36
"github.com/operator-framework/operator-lifecycle-manager/pkg/controller/install"
37
+ "github.com/operator-framework/operator-lifecycle-manager/pkg/controller/operators/olm/envvar"
35
38
"github.com/operator-framework/operator-lifecycle-manager/pkg/controller/registry/resolver"
36
39
csvutility "github.com/operator-framework/operator-lifecycle-manager/pkg/lib/csv"
37
40
"github.com/operator-framework/operator-lifecycle-manager/pkg/lib/event"
@@ -40,10 +43,9 @@ import (
40
43
"github.com/operator-framework/operator-lifecycle-manager/pkg/lib/operatorclient"
41
44
"github.com/operator-framework/operator-lifecycle-manager/pkg/lib/operatorlister"
42
45
"github.com/operator-framework/operator-lifecycle-manager/pkg/lib/ownerutil"
46
+ "github.com/operator-framework/operator-lifecycle-manager/pkg/lib/proxy"
43
47
"github.com/operator-framework/operator-lifecycle-manager/pkg/lib/queueinformer"
44
48
"github.com/operator-framework/operator-lifecycle-manager/pkg/lib/scoped"
45
- "github.com/operator-framework/operator-lifecycle-manager/pkg/lib/proxy"
46
- "github.com/operator-framework/operator-lifecycle-manager/pkg/controller/operators/olm/envvar"
47
49
"github.com/operator-framework/operator-lifecycle-manager/pkg/metrics"
48
50
)
49
51
@@ -65,6 +67,7 @@ type Operator struct {
65
67
csvQueueSet * queueinformer.ResourceQueueSet
66
68
csvCopyQueueSet * queueinformer.ResourceQueueSet
67
69
csvGCQueueSet * queueinformer.ResourceQueueSet
70
+ objGCQueueSet * queueinformer.ResourceQueueSet
68
71
apiServiceQueue workqueue.RateLimitingInterface
69
72
csvIndexers map [string ]cache.Indexer
70
73
recorder record.EventRecorder
@@ -118,6 +121,7 @@ func newOperatorWithConfig(ctx context.Context, config *operatorConfig) (*Operat
118
121
csvQueueSet : queueinformer .NewEmptyResourceQueueSet (),
119
122
csvCopyQueueSet : queueinformer .NewEmptyResourceQueueSet (),
120
123
csvGCQueueSet : queueinformer .NewEmptyResourceQueueSet (),
124
+ objGCQueueSet : queueinformer .NewEmptyResourceQueueSet (),
121
125
apiServiceQueue : workqueue .NewNamedRateLimitingQueue (workqueue .DefaultControllerRateLimiter (), "apiservice" ),
122
126
resolver : config .strategyResolver ,
123
127
apiReconciler : config .apiReconciler ,
@@ -215,7 +219,7 @@ func newOperatorWithConfig(ctx context.Context, config *operatorConfig) (*Operat
215
219
}
216
220
217
221
subInformer := extInformerFactory .Operators ().V1alpha1 ().Subscriptions ()
218
- op .lister .OperatorsV1alpha1 ().RegisterSubscriptionLister (namespace , subInformer .Lister ())
222
+ op .lister .OperatorsV1alpha1 ().RegisterSubscriptionLister (namespace , subInformer .Lister ())
219
223
subQueueInformer , err := queueinformer .NewQueueInformer (
220
224
ctx ,
221
225
queueinformer .WithLogger (op .logger ),
@@ -319,6 +323,38 @@ func newOperatorWithConfig(ctx context.Context, config *operatorConfig) (*Operat
319
323
if err := op .RegisterQueueInformer (serviceAccountQueueInformer ); err != nil {
320
324
return nil , err
321
325
}
326
+
327
+ objGCQueue := workqueue .NewNamedRateLimitingQueue (workqueue .DefaultControllerRateLimiter (), fmt .Sprintf ("%s/obj-gc" , namespace ))
328
+ op .objGCQueueSet .Set (namespace , objGCQueue )
329
+ objGCQueueInformer , err := queueinformer .NewQueue (
330
+ ctx ,
331
+ queueinformer .WithLogger (op .logger ),
332
+ queueinformer .WithQueue (objGCQueue ),
333
+ queueinformer .WithSyncer (queueinformer .LegacySyncHandler (op .syncGCObject ).ToSyncer ()),
334
+ )
335
+ if err != nil {
336
+ return nil , err
337
+ }
338
+ if err := op .RegisterQueueInformer (objGCQueueInformer ); err != nil {
339
+ return nil , err
340
+ }
341
+
342
+ }
343
+
344
+ // add queue for all namespaces as well
345
+ objGCQueue := workqueue .NewNamedRateLimitingQueue (workqueue .DefaultControllerRateLimiter (), fmt .Sprintf ("%s/obj-gc" , "" ))
346
+ op .objGCQueueSet .Set ("" , objGCQueue )
347
+ objGCQueueInformer , err := queueinformer .NewQueue (
348
+ ctx ,
349
+ queueinformer .WithLogger (op .logger ),
350
+ queueinformer .WithQueue (objGCQueue ),
351
+ queueinformer .WithSyncer (queueinformer .LegacySyncHandler (op .syncGCObject ).ToSyncer ()),
352
+ )
353
+ if err != nil {
354
+ return nil , err
355
+ }
356
+ if err := op .RegisterQueueInformer (objGCQueueInformer ); err != nil {
357
+ return nil , err
322
358
}
323
359
324
360
k8sInformerFactory := informers .NewSharedInformerFactory (op .opClient .KubernetesInterface (), config .resyncPeriod )
@@ -444,7 +480,7 @@ func newOperatorWithConfig(ctx context.Context, config *operatorConfig) (*Operat
444
480
op .resolver = & install.StrategyResolver {
445
481
ProxyInjectorBuilderFunc : proxyEnvInjector .GetDeploymentInitializer ,
446
482
}
447
-
483
+
448
484
return op , nil
449
485
}
450
486
@@ -536,6 +572,60 @@ func (a *Operator) RegisterCSVWatchNotification(csvNotification csvutility.Watch
536
572
a .csvNotification = csvNotification
537
573
}
538
574
575
+ func (a * Operator ) syncGCObject (obj interface {}) (syncError error ) {
576
+ metaObj , ok := obj .(metav1.Object )
577
+ if ! ok {
578
+ a .logger .Warn ("object sync: casting to metav1.Object failed" )
579
+ return
580
+ }
581
+ logger := a .logger .WithFields (logrus.Fields {
582
+ "name" : metaObj .GetName (),
583
+ "namespace" : metaObj .GetNamespace (),
584
+ "self" : metaObj .GetSelfLink (),
585
+ })
586
+
587
+ switch metaObj .(type ) {
588
+ case * rbacv1.ClusterRole :
589
+ if name , ns , ok := ownerutil .GetOwnerByKindLabel (metaObj , v1alpha1 .ClusterServiceVersionKind ); ok {
590
+ _ , err := a .lister .OperatorsV1alpha1 ().ClusterServiceVersionLister ().ClusterServiceVersions (ns ).Get (name )
591
+ if err == nil {
592
+ logger .Debugf ("CSV still present, must wait until it is deleted (owners=%v/%v)" , ns , name )
593
+ syncError = fmt .Errorf ("cleanup must wait" )
594
+ return
595
+ } else if ! k8serrors .IsNotFound (err ) {
596
+ syncError = err
597
+ return
598
+ }
599
+ }
600
+
601
+ if err := a .opClient .DeleteClusterRole (metaObj .GetName (), & metav1.DeleteOptions {}); err != nil {
602
+ logger .WithError (err ).Warn ("cannot delete cluster role" )
603
+ break
604
+ }
605
+ logger .Debugf ("Deleted cluster role %v due to no owning CSV" , metaObj .GetName ())
606
+ case * rbacv1.ClusterRoleBinding :
607
+ if name , ns , ok := ownerutil .GetOwnerByKindLabel (metaObj , v1alpha1 .ClusterServiceVersionKind ); ok {
608
+ _ , err := a .lister .OperatorsV1alpha1 ().ClusterServiceVersionLister ().ClusterServiceVersions (ns ).Get (name )
609
+ if err == nil {
610
+ logger .Debugf ("CSV still present, must wait until it is deleted (owners=%v)" , name )
611
+ syncError = fmt .Errorf ("cleanup must wait" )
612
+ return
613
+ } else if ! k8serrors .IsNotFound (err ) {
614
+ syncError = err
615
+ return
616
+ }
617
+ }
618
+
619
+ if err := a .opClient .DeleteClusterRoleBinding (metaObj .GetName (), & metav1.DeleteOptions {}); err != nil {
620
+ logger .WithError (err ).Warn ("cannot delete cluster role binding" )
621
+ break
622
+ }
623
+ logger .Debugf ("Deleted cluster role binding %v due to no owning CSV" , metaObj .GetName ())
624
+ }
625
+
626
+ return
627
+ }
628
+
539
629
func (a * Operator ) syncObject (obj interface {}) (syncError error ) {
540
630
// Assert as metav1.Object
541
631
metaObj , ok := obj .(metav1.Object )
@@ -550,14 +640,33 @@ func (a *Operator) syncObject(obj interface{}) (syncError error) {
550
640
"self" : metaObj .GetSelfLink (),
551
641
})
552
642
553
- // Requeue all owner CSVs
554
- if ownerutil .IsOwnedByKind (metaObj , v1alpha1 .ClusterServiceVersionKind ) {
555
- logger .Debug ("requeueing owner csvs" )
556
- a .requeueOwnerCSVs (metaObj )
557
- }
558
-
559
643
// Requeues objects that can't have ownerrefs (cluster -> namespace, cross-namespace)
560
644
if ownerutil .IsOwnedByKindLabel (metaObj , v1alpha1 .ClusterServiceVersionKind ) {
645
+ name , ns , ok := ownerutil .GetOwnerByKindLabel (metaObj , v1alpha1 .ClusterServiceVersionKind )
646
+ if ! ok {
647
+ logger .Error ("unexpected owner label retrieval failure" )
648
+ }
649
+ _ , err := a .lister .OperatorsV1alpha1 ().ClusterServiceVersionLister ().ClusterServiceVersions (ns ).Get (name )
650
+ if ! k8serrors .IsNotFound (err ) {
651
+ logger .Debug ("requeueing owner csvs from owner label" )
652
+ a .requeueOwnerCSVs (metaObj )
653
+ } else {
654
+ switch metaObj .(type ) {
655
+ case * rbacv1.ClusterRole , * rbacv1.ClusterRoleBinding :
656
+ resourceEvent := kubestate .NewResourceEvent (
657
+ kubestate .ResourceUpdated ,
658
+ metaObj ,
659
+ )
660
+ syncError = a .objGCQueueSet .RequeueEvent (ns , resourceEvent )
661
+ logger .Debugf ("syncObject - requeued update event for %v, res=%v" , resourceEvent , syncError )
662
+ return
663
+ }
664
+ }
665
+
666
+ }
667
+
668
+ // Requeue all owner CSVs
669
+ if ownerutil .IsOwnedByKind (metaObj , v1alpha1 .ClusterServiceVersionKind ) {
561
670
logger .Debug ("requeueing owner csvs" )
562
671
a .requeueOwnerCSVs (metaObj )
563
672
}
@@ -712,6 +821,25 @@ func (a *Operator) handleClusterServiceVersionDeletion(obj interface{}) {
712
821
}
713
822
}
714
823
}
824
+
825
+ ownerSelector := ownerutil .CSVOwnerSelector (clusterServiceVersion )
826
+ crbs , err := a .lister .RbacV1 ().ClusterRoleBindingLister ().List (ownerSelector )
827
+ if err != nil {
828
+ logger .WithError (err ).Warn ("cannot list cluster role bindings" )
829
+ }
830
+ for _ , crb := range crbs {
831
+ syncError := a .objGCQueueSet .RequeueEvent ("" , kubestate .NewResourceEvent (kubestate .ResourceUpdated , crb ))
832
+ logger .Debugf ("handleCSVdeletion - requeued update event for %v, res=%v" , crb , syncError )
833
+ }
834
+
835
+ crs , err := a .lister .RbacV1 ().ClusterRoleLister ().List (ownerSelector )
836
+ if err != nil {
837
+ logger .WithError (err ).Warn ("cannot list cluster roles" )
838
+ }
839
+ for _ , cr := range crs {
840
+ syncError := a .objGCQueueSet .RequeueEvent ("" , kubestate .NewResourceEvent (kubestate .ResourceUpdated , cr ))
841
+ logger .Debugf ("handleCSVdeletion - requeued update event for %v, res=%v" , cr , syncError )
842
+ }
715
843
}
716
844
717
845
func (a * Operator ) removeDanglingChildCSVs (csv * v1alpha1.ClusterServiceVersion ) error {
@@ -835,6 +963,7 @@ func (a *Operator) syncClusterServiceVersion(obj interface{}) (syncError error)
835
963
a .csvCopyQueueSet .Requeue (outCSV .GetNamespace (), outCSV .GetName ())
836
964
}
837
965
966
+ logger .Debug ("done syncing CSV" )
838
967
return
839
968
}
840
969
@@ -1580,14 +1709,14 @@ func (a *Operator) handleDeletion(obj interface{}) {
1580
1709
})
1581
1710
logger .Debug ("handling resource deletion" )
1582
1711
1583
- logger .Debug ("requeueing owner csvs" )
1712
+ logger .Debug ("requeueing owner csvs due to deletion " )
1584
1713
a .requeueOwnerCSVs (metaObj )
1585
1714
1586
1715
// Requeue CSVs with provided and required labels (for CRDs)
1587
1716
if labelSets , err := a .apiLabeler .LabelSetsFor (metaObj ); err != nil {
1588
1717
logger .WithError (err ).Warn ("couldn't create label set" )
1589
1718
} else if len (labelSets ) > 0 {
1590
- logger .Debug ("requeueing providing/requiring csvs" )
1719
+ logger .Debug ("requeueing providing/requiring csvs due to deletion " )
1591
1720
a .requeueCSVsByLabelSet (logger , labelSets ... )
1592
1721
}
1593
1722
}
@@ -1619,8 +1748,13 @@ func (a *Operator) requeueOwnerCSVs(ownee metav1.Object) {
1619
1748
owners := ownerutil .GetOwnersByKind (ownee , v1alpha1 .ClusterServiceVersionKind )
1620
1749
if len (owners ) > 0 && ownee .GetNamespace () != metav1 .NamespaceAll {
1621
1750
for _ , ownerCSV := range owners {
1751
+ _ , err := a .lister .OperatorsV1alpha1 ().ClusterServiceVersionLister ().ClusterServiceVersions (ownee .GetNamespace ()).Get (ownerCSV .Name )
1752
+ if k8serrors .IsNotFound (err ) {
1753
+ logger .Debugf ("skipping requeue since CSV %v is not in cache" , ownerCSV .Name )
1754
+ continue
1755
+ }
1622
1756
// Since cross-namespace CSVs can't exist we're guaranteed the owner will be in the same namespace
1623
- err : = a .csvQueueSet .Requeue (ownee .GetNamespace (), ownerCSV .Name )
1757
+ err = a .csvQueueSet .Requeue (ownee .GetNamespace (), ownerCSV .Name )
1624
1758
if err != nil {
1625
1759
logger .Warn (err .Error ())
1626
1760
}
@@ -1630,7 +1764,13 @@ func (a *Operator) requeueOwnerCSVs(ownee metav1.Object) {
1630
1764
1631
1765
// Requeue owners based on labels
1632
1766
if name , ns , ok := ownerutil .GetOwnerByKindLabel (ownee , v1alpha1 .ClusterServiceVersionKind ); ok {
1633
- err := a .csvQueueSet .Requeue (ns , name )
1767
+ _ , err := a .lister .OperatorsV1alpha1 ().ClusterServiceVersionLister ().ClusterServiceVersions (ns ).Get (name )
1768
+ if k8serrors .IsNotFound (err ) {
1769
+ logger .Debugf ("skipping requeue since CSV %v is not in cache" , name )
1770
+ return
1771
+ }
1772
+
1773
+ err = a .csvQueueSet .Requeue (ns , name )
1634
1774
if err != nil {
1635
1775
logger .Warn (err .Error ())
1636
1776
}
0 commit comments