Skip to content

Commit aa70bf3

Browse files
simplify controller logic + lock down cr
1 parent 2f12153 commit aa70bf3

5 files changed

Lines changed: 77 additions & 85 deletions

File tree

manifests/03-rbac-role-cluster.yaml

Lines changed: 16 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -153,12 +153,25 @@ rules:
153153
resources:
154154
- serviceaccounts
155155
verbs:
156-
- get
157156
- list
158-
- delete
157+
- watch
158+
- get
159+
- apiGroups:
160+
- ""
161+
resources:
162+
- serviceaccounts
163+
verbs:
159164
- create
165+
- apiGroups:
166+
- ""
167+
resources:
168+
- serviceaccounts
169+
verbs:
160170
- update
161-
- watch
171+
- delete
172+
resourceNames:
173+
- console
174+
- downloads
162175
---
163176
kind: ClusterRole
164177
apiVersion: rbac.authorization.k8s.io/v1

pkg/api/api.go

Lines changed: 12 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -56,18 +56,16 @@ const (
5656
DefaultIngressController = "default"
5757
IngressControllerNamespace = "openshift-ingress-operator"
5858

59-
OAuthClientName = OpenShiftConsoleName
60-
OpenShiftConsoleDeploymentName = OpenShiftConsoleName
61-
OpenShiftConsoleDownloadsDeploymentName = DownloadsResourceName
62-
OpenShiftConsoleDownloadsPDBName = DownloadsResourceName
63-
OpenShiftConsoleDownloadsRouteName = DownloadsResourceName
64-
OpenShiftConsoleNamespace = TargetNamespace
65-
OpenShiftConsolePDBName = OpenShiftConsoleName
66-
OpenShiftConsoleRouteName = OpenShiftConsoleName
67-
OpenShiftConsoleServiceName = OpenShiftConsoleName
68-
OpenShiftConsoleDownloadsServiceAccountName = OpenShiftConsoleDownloadsDeploymentName
69-
OpenshiftConsoleServiceAccountName = OpenShiftConsoleDeploymentName
70-
RedirectContainerTargetPort = RedirectContainerPort
71-
OpenShiftConsoleSASyncControllerSuffix = "ConsoleServiceAccountSyncController"
72-
OpenshiftConsoleDownloadsSASyncControllerPrefix = "DownloadsServiceAccountSyncController"
59+
OAuthClientName = OpenShiftConsoleName
60+
OpenShiftConsoleDeploymentName = OpenShiftConsoleName
61+
OpenShiftConsoleDownloadsDeploymentName = DownloadsResourceName
62+
OpenShiftConsoleDownloadsPDBName = DownloadsResourceName
63+
OpenShiftConsoleDownloadsRouteName = DownloadsResourceName
64+
OpenShiftConsoleNamespace = TargetNamespace
65+
OpenShiftConsolePDBName = OpenShiftConsoleName
66+
OpenShiftConsoleRouteName = OpenShiftConsoleName
67+
OpenShiftConsoleServiceName = OpenShiftConsoleName
68+
OpenShiftConsoleDownloadsServiceAccountName = OpenShiftConsoleDownloadsDeploymentName
69+
OpenShiftConsoleServiceAccountName = OpenShiftConsoleDeploymentName
70+
RedirectContainerTargetPort = RedirectContainerPort
7371
)

pkg/console/controllers/serviceaccounts/controller.go

Lines changed: 48 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ package serviceaccounts
33
import (
44
"context"
55
"fmt"
6+
"strings"
67
"time"
78

89
operatorv1 "github.com/openshift/api/operator/v1"
@@ -11,16 +12,16 @@ import (
1112
operatorinformerv1 "github.com/openshift/client-go/operator/informers/externalversions/operator/v1"
1213
operatorlistersv1 "github.com/openshift/client-go/operator/listers/operator/v1"
1314

15+
"github.com/openshift/console-operator/bindata"
1416
"github.com/openshift/console-operator/pkg/api"
1517
"github.com/openshift/console-operator/pkg/console/controllers/util"
1618
"github.com/openshift/console-operator/pkg/console/status"
17-
serviceaccountssub "github.com/openshift/console-operator/pkg/console/subresource/serviceaccount"
1819
"github.com/openshift/library-go/pkg/controller/factory"
1920
"github.com/openshift/library-go/pkg/operator/events"
2021
"github.com/openshift/library-go/pkg/operator/resource/resourceapply"
22+
"github.com/openshift/library-go/pkg/operator/resource/resourceread"
2123
"github.com/openshift/library-go/pkg/operator/v1helpers"
2224

23-
corev1 "k8s.io/api/core/v1"
2425
apierrors "k8s.io/apimachinery/pkg/api/errors"
2526
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
2627
coreinformersv1 "k8s.io/client-go/informers/core/v1"
@@ -31,6 +32,7 @@ import (
3132

3233
type ServiceAccountSyncController struct {
3334
serviceAccountName string
35+
conditionType string
3436
operatorClient v1helpers.OperatorClient
3537
// configs
3638
consoleOperatorLister operatorlistersv1.ConsoleLister
@@ -54,13 +56,12 @@ func NewServiceAccountSyncController(
5456
serviceAccountName string,
5557
// controllerName,
5658
controllerName string,
57-
// controllerSuffix
58-
controllerSuffix string,
5959
) factory.Controller {
6060
configV1Informers := configInformer.Config().V1()
6161

6262
ctrl := &ServiceAccountSyncController{
6363
serviceAccountName: serviceAccountName,
64+
conditionType: fmt.Sprintf("%sServiceAccountSync", controllerName),
6465
// configs
6566
operatorClient: operatorClient,
6667
consoleOperatorLister: operatorConfigInformer.Lister(),
@@ -81,32 +82,35 @@ func NewServiceAccountSyncController(
8182
serviceAccountNameFilter,
8283
serviceAccountInformer.Informer(),
8384
).ResyncEvery(time.Minute).WithSync(ctrl.Sync).
84-
ToController(controllerName, recorder.WithComponentSuffix(controllerSuffix))
85+
ToController(fmt.Sprintf("%sServiceAccountController", strings.Title(controllerName)), recorder.WithComponentSuffix(fmt.Sprintf("%s-service-account-controller", controllerName)))
8586
}
8687

8788
func (c *ServiceAccountSyncController) Sync(ctx context.Context, controllerContext factory.SyncContext) error {
8889
operatorConfig, err := c.consoleOperatorLister.Get(api.ConfigResourceName)
8990
if err != nil {
90-
return err
91+
return fmt.Errorf("failed to get console operator config %s: %w", api.ConfigResourceName, err)
9192
}
9293
operatorConfigCopy := operatorConfig.DeepCopy()
9394

9495
switch operatorConfigCopy.Spec.ManagementState {
9596
case operatorv1.Managed:
96-
klog.V(4).Infoln("console is in a managed state: syncing service account")
97+
klog.V(4).Infoln("console is in a managed state: syncing serviceaccount")
9798
case operatorv1.Unmanaged:
98-
klog.V(4).Infoln("console is in an unmanaged state: skipping service account sync")
99+
klog.V(4).Infoln("console is in an unmanaged state: skipping serviceaccount sync")
99100
return nil
100101
case operatorv1.Removed:
101-
klog.V(4).Infoln("console is in a removed state: removing synced service account")
102-
return c.removeServiceAccount(ctx)
102+
klog.V(4).Infoln("console is in a removed state: removing synced serviceaccount")
103+
statusHandler := status.NewStatusHandler(c.operatorClient)
104+
removeErr := c.removeServiceAccount(ctx)
105+
statusHandler.AddConditions(status.HandleProgressingOrDegraded(c.conditionType, "FailedRemove", removeErr))
106+
return statusHandler.FlushAndReturn(removeErr)
103107
default:
104108
return fmt.Errorf("unknown state: %v", operatorConfigCopy.Spec.ManagementState)
105109
}
106110
statusHandler := status.NewStatusHandler(c.operatorClient)
107111

108-
_, _, serviceAccountErr := c.SyncServiceAccount(ctx, operatorConfigCopy, controllerContext)
109-
statusHandler.AddConditions(status.HandleProgressingOrDegraded("ServiceAccountSync", "FailedApply", serviceAccountErr))
112+
serviceAccountErr := c.SyncServiceAccount(ctx, operatorConfigCopy, controllerContext)
113+
statusHandler.AddConditions(status.HandleProgressingOrDegraded(c.conditionType, "FailedApply", serviceAccountErr))
110114
if serviceAccountErr != nil {
111115
return statusHandler.FlushAndReturn(serviceAccountErr)
112116
}
@@ -122,25 +126,44 @@ func (c *ServiceAccountSyncController) removeServiceAccount(ctx context.Context)
122126
return err
123127
}
124128

125-
func (c *ServiceAccountSyncController) SyncServiceAccount(ctx context.Context, operatorConfigCopy *operatorv1.Console, controllerContext factory.SyncContext) (*corev1.ServiceAccount, bool, error) {
126-
requiredServiceAccount, err := serviceaccountssub.DefaultServiceAccountFactory(c.serviceAccountName, operatorConfigCopy)
127-
if err != nil {
128-
return nil, false, err
129+
func (c *ServiceAccountSyncController) SyncServiceAccount(ctx context.Context, operatorConfigCopy *operatorv1.Console, controllerContext factory.SyncContext) error {
130+
serviceAccount := resourceread.ReadServiceAccountV1OrDie(
131+
bindata.MustAsset(fmt.Sprintf("assets/serviceaccounts/%s-sa.yaml", c.serviceAccountName)),
132+
)
133+
if serviceAccount.Name == "" {
134+
return fmt.Errorf("No service account found for name %v .", c.serviceAccountName)
129135
}
130136

131-
// if the object has one or more ownerRef objects, then we must
132-
// ensure that their controller attribute is set to false.
133-
// Only one ownerRef.controller == true .
134-
// https://kubernetes.io/docs/concepts/overview/working-with-objects/owners-dependents/#owner-references-in-object-specifications
135-
136-
for oR := range requiredServiceAccount.OwnerReferences {
137+
// Fetch the live SA to get its actual ownerRefs (e.g. ClusterVersion/version
138+
// set by CVO from the old manifests/06-sa.yaml, or any previously set
139+
// Console/cluster ref). We need these on the *required* object so that
140+
// MergeOwnerRefs will update them — it only modifies refs that appear in
141+
// required (matched by Name+Kind+APIVersion.Group).
142+
existing, err := c.serviceAccountClient.ServiceAccounts(api.OpenShiftConsoleNamespace).Get(ctx, c.serviceAccountName, metav1.GetOptions{})
143+
if err != nil && !apierrors.IsNotFound(err) {
144+
return fmt.Errorf("failed to get service account %s: %w", c.serviceAccountName, err)
145+
}
146+
if err == nil {
147+
// Clear controller:true from all existing ownerRefs to satisfy the
148+
// Kubernetes invariant that only one ownerRef may have controller:true.
149+
// https://kubernetes.io/docs/concepts/overview/working-with-objects/owners-dependents/
137150
falseBool := false
138-
requiredServiceAccount.OwnerReferences[oR].Controller = &falseBool
151+
ownerRefs := existing.DeepCopy().GetOwnerReferences()
152+
for i := range ownerRefs {
153+
ownerRefs[i].Controller = &falseBool
154+
}
155+
serviceAccount.SetOwnerReferences(ownerRefs)
139156
}
140157

141-
return resourceapply.ApplyServiceAccount(ctx,
158+
_, _, err = resourceapply.ApplyServiceAccount(ctx,
142159
c.serviceAccountClient,
143160
controllerContext.Recorder(),
144-
requiredServiceAccount,
161+
serviceAccount,
145162
)
163+
164+
if err != nil {
165+
return fmt.Errorf("failed to apply service account %s: %w", c.serviceAccountName, err)
166+
}
167+
168+
return nil
146169
}

pkg/console/starter/starter.go

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -338,9 +338,8 @@ func RunOperator(ctx context.Context, controllerContext *controllercmd.Controlle
338338
kubeInformersNamespaced.Core().V1().ServiceAccounts(), // ServiceAccount
339339

340340
recorder,
341-
api.OpenshiftConsoleServiceAccountName,
341+
api.OpenShiftConsoleServiceAccountName,
342342
api.OpenShiftConsoleName, // controller name
343-
api.OpenShiftConsoleSASyncControllerSuffix,
344343
)
345344

346345
downloadsServiceAccountController := serviceaccounts.NewServiceAccountSyncController(
@@ -357,7 +356,6 @@ func RunOperator(ctx context.Context, controllerContext *controllercmd.Controlle
357356

358357
api.OpenShiftConsoleDownloadsServiceAccountName,
359358
api.DownloadsResourceName,
360-
api.OpenshiftConsoleDownloadsSASyncControllerPrefix,
361359
)
362360

363361
downloadsDeploymentController := downloadsdeployment.NewDownloadsDeploymentSyncController(

pkg/console/subresource/serviceaccount/serviceaccount.go

Lines changed: 0 additions & 40 deletions
This file was deleted.

0 commit comments

Comments
 (0)