From 0e1d7bc9c008f69131c2945be8e3855c37b1b4b8 Mon Sep 17 00:00:00 2001 From: Evan Hearne Date: Wed, 7 Jan 2026 11:04:59 +0000 Subject: [PATCH 1/5] add config map service account --- pkg/controller/bundle/bundle_unpacker.go | 40 ++++++++++++++++++- pkg/controller/bundle/bundle_unpacker_test.go | 6 ++- 2 files changed, 43 insertions(+), 3 deletions(-) diff --git a/pkg/controller/bundle/bundle_unpacker.go b/pkg/controller/bundle/bundle_unpacker.go index 5f2d94d26e..665b487e15 100644 --- a/pkg/controller/bundle/bundle_unpacker.go +++ b/pkg/controller/bundle/bundle_unpacker.go @@ -337,6 +337,7 @@ type ConfigMapUnpacker struct { podLister listerscorev1.PodLister roleLister listersrbacv1.RoleLister rbLister listersrbacv1.RoleBindingLister + saLister listerscorev1.ServiceAccountLister loader *configmap.BundleLoader now func() metav1.Time unpackTimeout time.Duration @@ -424,6 +425,12 @@ func WithRoleBindingLister(rbLister listersrbacv1.RoleBindingLister) ConfigMapUn } } +func WithServiceAccountLister(saLister listerscorev1.ServiceAccountLister) ConfigMapUnpackerOption { + return func(unpacker *ConfigMapUnpacker) { + unpacker.saLister = saLister + } +} + func WithNow(now func() metav1.Time) ConfigMapUnpackerOption { return func(unpacker *ConfigMapUnpacker) { unpacker.now = now @@ -536,6 +543,11 @@ func (c *ConfigMapUnpacker) UnpackBundle(lookup *operatorsv1alpha1.BundleLookup, return } + _, err = c.ensureServiceAccount(cmRef) + if err != nil { + return + } + _, err = c.ensureRoleBinding(cmRef) if err != nil { return @@ -791,13 +803,39 @@ func (c *ConfigMapUnpacker) ensureRole(cmRef *corev1.ObjectReference) (role *rba return } +func (c *ConfigMapUnpacker) ensureServiceAccount(cmRef *corev1.ObjectReference) (serviceAccount *corev1.ServiceAccount, err error) { + + fresh := &corev1.ServiceAccount{ + ObjectMeta: metav1.ObjectMeta{ + Name: cmRef.Name, + Namespace: cmRef.Namespace, + }, + } + + fresh.SetNamespace(cmRef.Namespace) + fresh.SetName(cmRef.Name) + fresh.SetOwnerReferences([]metav1.OwnerReference{ownerRef(cmRef)}) + fresh.SetLabels(map[string]string{install.OLMManagedLabelKey: install.OLMManagedLabelValue}) + + serviceAccount, err = c.saLister.ServiceAccounts(fresh.GetNamespace()).Get(fresh.GetName()) + + if err != nil { + if apierrors.IsNotFound(err) { + serviceAccount, err = c.client.CoreV1().ServiceAccounts(fresh.GetNamespace()).Create(context.TODO(), fresh, metav1.CreateOptions{}) + } + return + } + + return +} + func (c *ConfigMapUnpacker) ensureRoleBinding(cmRef *corev1.ObjectReference) (roleBinding *rbacv1.RoleBinding, err error) { fresh := &rbacv1.RoleBinding{ Subjects: []rbacv1.Subject{ { Kind: "ServiceAccount", APIGroup: "", - Name: "default", + Name: cmRef.Name, Namespace: cmRef.Namespace, }, }, diff --git a/pkg/controller/bundle/bundle_unpacker_test.go b/pkg/controller/bundle/bundle_unpacker_test.go index f9ec614d5c..b2328b0922 100644 --- a/pkg/controller/bundle/bundle_unpacker_test.go +++ b/pkg/controller/bundle/bundle_unpacker_test.go @@ -450,7 +450,7 @@ func TestConfigMapUnpacker(t *testing.T) { { Kind: "ServiceAccount", APIGroup: "", - Name: "default", + Name: pathHash, Namespace: "ns-a", }, }, @@ -941,7 +941,7 @@ func TestConfigMapUnpacker(t *testing.T) { { Kind: "ServiceAccount", APIGroup: "", - Name: "default", + Name: digestHash, Namespace: "ns-a", }, }, @@ -1618,6 +1618,7 @@ func TestConfigMapUnpacker(t *testing.T) { podLister := factory.Core().V1().Pods().Lister() roleLister := factory.Rbac().V1().Roles().Lister() rbLister := factory.Rbac().V1().RoleBindings().Lister() + saLister := factory.Core().V1().ServiceAccounts().Lister() stop := make(chan struct{}) defer close(stop) @@ -1639,6 +1640,7 @@ func TestConfigMapUnpacker(t *testing.T) { WithPodLister(podLister), WithRoleLister(roleLister), WithRoleBindingLister(rbLister), + WithServiceAccountLister(saLister), WithOPMImage(opmImage), WithUtilImage(utilImage), WithNow(now), From 6160e7f1b2195bb1b93fa5a3e56ff5a4ffbb7f3f Mon Sep 17 00:00:00 2001 From: Evan Hearne Date: Fri, 9 Jan 2026 13:00:53 +0000 Subject: [PATCH 2/5] add service account lister to configmapunpacker in test --- pkg/controller/operators/catalog/operator.go | 1 + 1 file changed, 1 insertion(+) diff --git a/pkg/controller/operators/catalog/operator.go b/pkg/controller/operators/catalog/operator.go index 24336fbd95..069e08ab76 100644 --- a/pkg/controller/operators/catalog/operator.go +++ b/pkg/controller/operators/catalog/operator.go @@ -736,6 +736,7 @@ func NewOperator(ctx context.Context, kubeconfigPath string, clock utilclock.Clo bundle.WithPodLister(buPodInformer.Lister()), bundle.WithRoleLister(roleInformer.Lister()), bundle.WithRoleBindingLister(roleBindingInformer.Lister()), + bundle.WithServiceAccountLister(serviceAccountInformer.Lister()), bundle.WithOPMImage(opmImage), bundle.WithUtilImage(utilImage), bundle.WithNow(op.now), From ac5fdc211bd7e7dc425b09327c03bda6c068cb04 Mon Sep 17 00:00:00 2001 From: Evan Hearne Date: Fri, 9 Jan 2026 17:04:13 +0000 Subject: [PATCH 3/5] add the service account to the job pod spec --- pkg/controller/bundle/bundle_unpacker.go | 1 + pkg/controller/bundle/bundle_unpacker_test.go | 6 ++++++ 2 files changed, 7 insertions(+) diff --git a/pkg/controller/bundle/bundle_unpacker.go b/pkg/controller/bundle/bundle_unpacker.go index 665b487e15..ba0d1647dd 100644 --- a/pkg/controller/bundle/bundle_unpacker.go +++ b/pkg/controller/bundle/bundle_unpacker.go @@ -118,6 +118,7 @@ func (c *ConfigMapUnpacker) job(cmRef *corev1.ObjectReference, bundlePath string // Keeping the pods around after failures helps in inspecting the logs of a failed bundle unpack job. // See: https://kubernetes.io/docs/concepts/workloads/controllers/job/#pod-backoff-failure-policy RestartPolicy: corev1.RestartPolicyNever, + ServiceAccountName: cmRef.Name, ImagePullSecrets: secrets, SecurityContext: &corev1.PodSecurityContext{ SeccompProfile: &corev1.SeccompProfile{ diff --git a/pkg/controller/bundle/bundle_unpacker_test.go b/pkg/controller/bundle/bundle_unpacker_test.go index b2328b0922..cc2a373e79 100644 --- a/pkg/controller/bundle/bundle_unpacker_test.go +++ b/pkg/controller/bundle/bundle_unpacker_test.go @@ -275,6 +275,7 @@ func TestConfigMapUnpacker(t *testing.T) { }, Spec: corev1.PodSpec{ RestartPolicy: corev1.RestartPolicyNever, + ServiceAccountName: pathHash, ImagePullSecrets: []corev1.LocalObjectReference{{Name: "my-secret"}}, SecurityContext: &corev1.PodSecurityContext{ RunAsNonRoot: ptr.To(bool(true)), @@ -495,6 +496,7 @@ func TestConfigMapUnpacker(t *testing.T) { }, Spec: corev1.PodSpec{ RestartPolicy: corev1.RestartPolicyNever, + ServiceAccountName: digestHash, SecurityContext: &corev1.PodSecurityContext{ RunAsNonRoot: ptr.To(bool(true)), RunAsUser: ptr.To(int64(runAsUser)), @@ -754,6 +756,7 @@ func TestConfigMapUnpacker(t *testing.T) { }, Spec: corev1.PodSpec{ RestartPolicy: corev1.RestartPolicyNever, + ServiceAccountName: digestHash, SecurityContext: &corev1.PodSecurityContext{ RunAsNonRoot: ptr.To(bool(true)), RunAsUser: ptr.To(int64(runAsUser)), @@ -1008,6 +1011,7 @@ func TestConfigMapUnpacker(t *testing.T) { }, Spec: corev1.PodSpec{ RestartPolicy: corev1.RestartPolicyNever, + ServiceAccountName: pathHash, SecurityContext: &corev1.PodSecurityContext{ RunAsNonRoot: ptr.To(bool(true)), RunAsUser: ptr.To(int64(runAsUser)), @@ -1232,6 +1236,7 @@ func TestConfigMapUnpacker(t *testing.T) { }, Spec: corev1.PodSpec{ RestartPolicy: corev1.RestartPolicyNever, + ServiceAccountName: pathHash, SecurityContext: &corev1.PodSecurityContext{ RunAsNonRoot: ptr.To(bool(true)), RunAsUser: ptr.To(int64(runAsUser)), @@ -1469,6 +1474,7 @@ func TestConfigMapUnpacker(t *testing.T) { }, Spec: corev1.PodSpec{ RestartPolicy: corev1.RestartPolicyNever, + ServiceAccountName: pathHash, SecurityContext: &corev1.PodSecurityContext{ RunAsNonRoot: ptr.To(bool(true)), RunAsUser: ptr.To(int64(runAsUser)), From 01d0cbe1ffcf7c6946f2f5aa361ba89384d8ae7d Mon Sep 17 00:00:00 2001 From: Evan Hearne Date: Tue, 13 Jan 2026 10:55:36 +0000 Subject: [PATCH 4/5] fix formatting issues. --- pkg/controller/bundle/bundle_unpacker.go | 5 ++--- pkg/controller/bundle/bundle_unpacker_test.go | 14 +++++++------- 2 files changed, 9 insertions(+), 10 deletions(-) diff --git a/pkg/controller/bundle/bundle_unpacker.go b/pkg/controller/bundle/bundle_unpacker.go index ba0d1647dd..f6284b4d8f 100644 --- a/pkg/controller/bundle/bundle_unpacker.go +++ b/pkg/controller/bundle/bundle_unpacker.go @@ -117,9 +117,9 @@ func (c *ConfigMapUnpacker) job(cmRef *corev1.ObjectReference, bundlePath string // By setting restartPolicy = "Never" the pods don't get cleaned up since they're not running after a failure. // Keeping the pods around after failures helps in inspecting the logs of a failed bundle unpack job. // See: https://kubernetes.io/docs/concepts/workloads/controllers/job/#pod-backoff-failure-policy - RestartPolicy: corev1.RestartPolicyNever, + RestartPolicy: corev1.RestartPolicyNever, ServiceAccountName: cmRef.Name, - ImagePullSecrets: secrets, + ImagePullSecrets: secrets, SecurityContext: &corev1.PodSecurityContext{ SeccompProfile: &corev1.SeccompProfile{ Type: corev1.SeccompProfileTypeRuntimeDefault, @@ -805,7 +805,6 @@ func (c *ConfigMapUnpacker) ensureRole(cmRef *corev1.ObjectReference) (role *rba } func (c *ConfigMapUnpacker) ensureServiceAccount(cmRef *corev1.ObjectReference) (serviceAccount *corev1.ServiceAccount, err error) { - fresh := &corev1.ServiceAccount{ ObjectMeta: metav1.ObjectMeta{ Name: cmRef.Name, diff --git a/pkg/controller/bundle/bundle_unpacker_test.go b/pkg/controller/bundle/bundle_unpacker_test.go index cc2a373e79..c2b53dd354 100644 --- a/pkg/controller/bundle/bundle_unpacker_test.go +++ b/pkg/controller/bundle/bundle_unpacker_test.go @@ -274,9 +274,9 @@ func TestConfigMapUnpacker(t *testing.T) { }, }, Spec: corev1.PodSpec{ - RestartPolicy: corev1.RestartPolicyNever, + RestartPolicy: corev1.RestartPolicyNever, ServiceAccountName: pathHash, - ImagePullSecrets: []corev1.LocalObjectReference{{Name: "my-secret"}}, + ImagePullSecrets: []corev1.LocalObjectReference{{Name: "my-secret"}}, SecurityContext: &corev1.PodSecurityContext{ RunAsNonRoot: ptr.To(bool(true)), RunAsUser: ptr.To(int64(runAsUser)), @@ -495,7 +495,7 @@ func TestConfigMapUnpacker(t *testing.T) { }, }, Spec: corev1.PodSpec{ - RestartPolicy: corev1.RestartPolicyNever, + RestartPolicy: corev1.RestartPolicyNever, ServiceAccountName: digestHash, SecurityContext: &corev1.PodSecurityContext{ RunAsNonRoot: ptr.To(bool(true)), @@ -755,7 +755,7 @@ func TestConfigMapUnpacker(t *testing.T) { }, }, Spec: corev1.PodSpec{ - RestartPolicy: corev1.RestartPolicyNever, + RestartPolicy: corev1.RestartPolicyNever, ServiceAccountName: digestHash, SecurityContext: &corev1.PodSecurityContext{ RunAsNonRoot: ptr.To(bool(true)), @@ -1010,7 +1010,7 @@ func TestConfigMapUnpacker(t *testing.T) { }, }, Spec: corev1.PodSpec{ - RestartPolicy: corev1.RestartPolicyNever, + RestartPolicy: corev1.RestartPolicyNever, ServiceAccountName: pathHash, SecurityContext: &corev1.PodSecurityContext{ RunAsNonRoot: ptr.To(bool(true)), @@ -1235,7 +1235,7 @@ func TestConfigMapUnpacker(t *testing.T) { }, }, Spec: corev1.PodSpec{ - RestartPolicy: corev1.RestartPolicyNever, + RestartPolicy: corev1.RestartPolicyNever, ServiceAccountName: pathHash, SecurityContext: &corev1.PodSecurityContext{ RunAsNonRoot: ptr.To(bool(true)), @@ -1473,7 +1473,7 @@ func TestConfigMapUnpacker(t *testing.T) { }, }, Spec: corev1.PodSpec{ - RestartPolicy: corev1.RestartPolicyNever, + RestartPolicy: corev1.RestartPolicyNever, ServiceAccountName: pathHash, SecurityContext: &corev1.PodSecurityContext{ RunAsNonRoot: ptr.To(bool(true)), From e9e0d459789a0ca14a28d9cbd09705f83569c82f Mon Sep 17 00:00:00 2001 From: Evan Hearne Date: Thu, 15 Jan 2026 09:41:10 +0000 Subject: [PATCH 5/5] remove setting ns and name as sa object already does this --- pkg/controller/bundle/bundle_unpacker.go | 2 -- 1 file changed, 2 deletions(-) diff --git a/pkg/controller/bundle/bundle_unpacker.go b/pkg/controller/bundle/bundle_unpacker.go index f6284b4d8f..7d2614bb01 100644 --- a/pkg/controller/bundle/bundle_unpacker.go +++ b/pkg/controller/bundle/bundle_unpacker.go @@ -812,8 +812,6 @@ func (c *ConfigMapUnpacker) ensureServiceAccount(cmRef *corev1.ObjectReference) }, } - fresh.SetNamespace(cmRef.Namespace) - fresh.SetName(cmRef.Name) fresh.SetOwnerReferences([]metav1.OwnerReference{ownerRef(cmRef)}) fresh.SetLabels(map[string]string{install.OLMManagedLabelKey: install.OLMManagedLabelValue})