diff --git a/pkg/controller/operators/catalog/operator.go b/pkg/controller/operators/catalog/operator.go index 522485df9f1..605ee9e8019 100644 --- a/pkg/controller/operators/catalog/operator.go +++ b/pkg/controller/operators/catalog/operator.go @@ -185,7 +185,7 @@ func NewOperator(ctx context.Context, kubeconfigPath string, clock utilclock.Clo return nil, err } - canFilter, err := labeller.Validate(ctx, logger, metadataClient) + canFilter, err := labeller.Validate(ctx, logger, metadataClient, crClient) if err != nil { return nil, err } @@ -490,7 +490,18 @@ func NewOperator(ctx context.Context, kubeconfigPath string, clock utilclock.Clo serviceaccountsgvk := corev1.SchemeGroupVersion.WithResource("serviceaccounts") if err := labelObjects(serviceaccountsgvk, serviceAccountInformer.Informer(), labeller.ObjectLabeler[*corev1.ServiceAccount, *corev1applyconfigurations.ServiceAccountApplyConfiguration]( - ctx, op.logger, labeller.Filter(serviceaccountsgvk), + ctx, op.logger, labeller.ServiceAccountFilter(func(namespace, name string) bool { + operatorGroups, err := operatorGroupInformer.Lister().OperatorGroups(namespace).List(labels.Everything()) + if err != nil { + return false + } + for _, operatorGroup := range operatorGroups { + if operatorGroup.Spec.ServiceAccountName == name { + return true + } + } + return false + }), serviceAccountInformer.Lister().List, corev1applyconfigurations.ServiceAccount, func(namespace string, ctx context.Context, cfg *corev1applyconfigurations.ServiceAccountApplyConfiguration, opts metav1.ApplyOptions) (*corev1.ServiceAccount, error) { diff --git a/pkg/controller/operators/labeller/filters.go b/pkg/controller/operators/labeller/filters.go index c5f50106221..11e04a24d8d 100644 --- a/pkg/controller/operators/labeller/filters.go +++ b/pkg/controller/operators/labeller/filters.go @@ -6,6 +6,7 @@ import ( "strings" "sync" + operators "github.com/operator-framework/operator-lifecycle-manager/pkg/api/client/clientset/versioned" "github.com/operator-framework/operator-lifecycle-manager/pkg/controller/registry/reconciler" "github.com/sirupsen/logrus" "golang.org/x/sync/errgroup" @@ -16,6 +17,8 @@ import ( apiextensionsv1 "k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/runtime/schema" + "k8s.io/apimachinery/pkg/types" + "k8s.io/apimachinery/pkg/util/sets" "k8s.io/client-go/metadata" "github.com/operator-framework/operator-lifecycle-manager/pkg/controller/operators/internal/alongside" @@ -49,15 +52,18 @@ func JobFilter(getConfigMap func(namespace, name string) (metav1.Object, error)) } } +func ServiceAccountFilter(isServiceAccountReferenced func(namespace, name string) bool) func(object metav1.Object) bool { + return func(object metav1.Object) bool { + return HasOLMOwnerRef(object) || HasOLMLabel(object) || isServiceAccountReferenced(object.GetNamespace(), object.GetName()) + } +} + var filters = map[schema.GroupVersionResource]func(metav1.Object) bool{ corev1.SchemeGroupVersion.WithResource("services"): HasOLMOwnerRef, corev1.SchemeGroupVersion.WithResource("pods"): func(object metav1.Object) bool { _, ok := object.GetLabels()[reconciler.CatalogSourceLabelKey] return ok }, - corev1.SchemeGroupVersion.WithResource("serviceaccounts"): func(object metav1.Object) bool { - return HasOLMOwnerRef(object) || HasOLMLabel(object) - }, appsv1.SchemeGroupVersion.WithResource("deployments"): HasOLMOwnerRef, rbacv1.SchemeGroupVersion.WithResource("roles"): HasOLMOwnerRef, rbacv1.SchemeGroupVersion.WithResource("rolebindings"): HasOLMOwnerRef, @@ -73,7 +79,7 @@ var filters = map[schema.GroupVersionResource]func(metav1.Object) bool{ }, } -func Validate(ctx context.Context, logger *logrus.Logger, metadataClient metadata.Interface) (bool, error) { +func Validate(ctx context.Context, logger *logrus.Logger, metadataClient metadata.Interface, operatorClient operators.Interface) (bool, error) { okLock := sync.Mutex{} ok := true g, ctx := errgroup.WithContext(ctx) @@ -96,6 +102,27 @@ func Validate(ctx context.Context, logger *logrus.Logger, metadataClient metadat return previous != nil && previous(object) && ContentHashFilter(object) } } + + operatorGroups, err := operatorClient.OperatorsV1().OperatorGroups(metav1.NamespaceAll).List(ctx, metav1.ListOptions{}) + if err != nil { + return false, err + } + userProvidedServiceAccounts := sets.New[types.NamespacedName]() + for _, operatorGroup := range operatorGroups.Items { + if operatorGroup.Spec.ServiceAccountName != "" { + userProvidedServiceAccounts.Insert(types.NamespacedName{ + Namespace: operatorGroup.Namespace, + Name: operatorGroup.Spec.ServiceAccountName, + }) + } + } + allFilters[corev1.SchemeGroupVersion.WithResource("serviceaccounts")] = ServiceAccountFilter(func(namespace, name string) bool { + return userProvidedServiceAccounts.Has(types.NamespacedName{ + Namespace: namespace, + Name: name, + }) + }) + for gvr, filter := range allFilters { gvr, filter := gvr, filter g.Go(func() error { diff --git a/pkg/controller/operators/olm/operator.go b/pkg/controller/operators/olm/operator.go index 2ba02129a96..de028b69f73 100644 --- a/pkg/controller/operators/olm/operator.go +++ b/pkg/controller/operators/olm/operator.go @@ -186,7 +186,7 @@ func newOperatorWithConfig(ctx context.Context, config *operatorConfig) (*Operat return nil, err } - canFilter, err := labeller.Validate(ctx, config.logger, config.metadataClient) + canFilter, err := labeller.Validate(ctx, config.logger, config.metadataClient, config.externalClient) if err != nil { return nil, err } diff --git a/pkg/lib/scoped/syncer.go b/pkg/lib/scoped/syncer.go index 6a8921b2ea3..f69505beff5 100644 --- a/pkg/lib/scoped/syncer.go +++ b/pkg/lib/scoped/syncer.go @@ -78,14 +78,6 @@ func (s *UserDefinedServiceAccountSyncer) SyncOperatorGroup(in *v1.OperatorGroup return } - // A service account has been specified, but likely does not have the labels we expect it to have so it will - // show up in our listers, so let's add that and queue again later - config := corev1applyconfigurations.ServiceAccount(serviceAccountName, namespace) - config.Labels = map[string]string{install.OLMManagedLabelKey: install.OLMManagedLabelValue} - if _, err := s.client.KubernetesInterface().CoreV1().ServiceAccounts(namespace).Apply(context.TODO(), config, metav1.ApplyOptions{FieldManager: "operator-lifecycle-manager"}); err != nil { - return out, fmt.Errorf("failed to apply labels[%s]=%s to serviceaccount %s/%s: %w", install.OLMManagedLabelKey, install.OLMManagedLabelValue, namespace, serviceAccountName, err) - } - // A service account has been specified, we need to update the status. sa, err := s.client.KubernetesInterface().CoreV1().ServiceAccounts(namespace).Get(context.TODO(), serviceAccountName, metav1.GetOptions{}) if err != nil { @@ -108,6 +100,14 @@ func (s *UserDefinedServiceAccountSyncer) SyncOperatorGroup(in *v1.OperatorGroup return } + // A service account has been specified, but likely does not have the labels we expect it to have so it will + // show up in our listers, so let's add that and queue again later + config := corev1applyconfigurations.ServiceAccount(serviceAccountName, namespace) + config.Labels = map[string]string{install.OLMManagedLabelKey: install.OLMManagedLabelValue} + if _, err := s.client.KubernetesInterface().CoreV1().ServiceAccounts(namespace).Apply(context.TODO(), config, metav1.ApplyOptions{FieldManager: "operator-lifecycle-manager"}); err != nil { + return out, fmt.Errorf("failed to apply labels[%s]=%s to serviceaccount %s/%s: %w", install.OLMManagedLabelKey, install.OLMManagedLabelValue, namespace, serviceAccountName, err) + } + ref, err := reference.GetReference(s.scheme, sa) if err != nil { return