Skip to content

Commit 3f352d7

Browse files
author
Jeff Peeler
committed
fix(olm): requeue as needed upon permission changes
The fix here is a combination of resetting the phase on CSV that has been set to a "no retry" state based on previous permission failures along with requeuing. The requeuing notifies OLM when RBAC additions are made as well as changes to the service account when specified on an operator group.
1 parent 2165590 commit 3f352d7

File tree

5 files changed

+89
-28
lines changed

5 files changed

+89
-28
lines changed

pkg/api/apis/operators/v1alpha1/clusterserviceversion_types.go

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -231,7 +231,7 @@ const (
231231
CSVReasonRequirementsMet ConditionReason = "AllRequirementsMet"
232232
CSVReasonOwnerConflict ConditionReason = "OwnerConflict"
233233
CSVReasonComponentFailed ConditionReason = "InstallComponentFailed"
234-
CSVReasonComponentFailedNoRetry ConditionReason = "InstallComponentFailedNoRetry"
234+
CSVReasonComponentFailedNoRetry ConditionReason = "InstallComponentFailedNoRetry"
235235
CSVReasonInvalidStrategy ConditionReason = "InvalidInstallStrategy"
236236
CSVReasonWaiting ConditionReason = "InstallWaiting"
237237
CSVReasonInstallSuccessful ConditionReason = "InstallSucceeded"
@@ -252,6 +252,7 @@ const (
252252
CSVReasonTooManyOperatorGroups ConditionReason = "TooManyOperatorGroups"
253253
CSVReasonInterOperatorGroupOwnerConflict ConditionReason = "InterOperatorGroupOwnerConflict"
254254
CSVReasonCannotModifyStaticOperatorGroupProvidedAPIs ConditionReason = "CannotModifyStaticOperatorGroupProvidedAPIs"
255+
CSVReasonDetectedClusterChange ConditionReason = "DetectedClusterChange"
255256
)
256257

257258
// Conditions appear in the status as a record of state transitions on the ClusterServiceVersion

pkg/controller/operators/catalog/installplan_sync.go

Lines changed: 2 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -7,11 +7,10 @@ import (
77

88
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
99
"k8s.io/apimachinery/pkg/labels"
10-
"k8s.io/apimachinery/pkg/runtime"
1110
utilerrors "k8s.io/apimachinery/pkg/util/errors"
1211

12+
"github.com/operator-framework/operator-lifecycle-manager/pkg/lib/scoped"
1313
"github.com/operator-framework/operator-lifecycle-manager/pkg/api/apis/operators/v1alpha1"
14-
"github.com/operator-framework/operator-lifecycle-manager/pkg/lib/ownerutil"
1514
)
1615

1716
// When a user adds permission to a ServiceAccount by creating or updating
@@ -26,7 +25,7 @@ func (o *Operator) triggerInstallPlanRetry(obj interface{}) (syncError error) {
2625
return
2726
}
2827

29-
related, _ := isObjectRBACRelated(obj)
28+
related, _ := scoped.IsObjectRBACRelated(obj)
3029
if !related {
3130
return
3231
}
@@ -75,26 +74,3 @@ func (o *Operator) triggerInstallPlanRetry(obj interface{}) (syncError error) {
7574
syncError = utilerrors.NewAggregate(errs)
7675
return
7776
}
78-
79-
func isObjectRBACRelated(obj interface{}) (related bool, object runtime.Object) {
80-
object, ok := obj.(runtime.Object)
81-
if !ok {
82-
return
83-
}
84-
85-
if err := ownerutil.InferGroupVersionKind(object); err != nil {
86-
return
87-
}
88-
89-
kind := object.GetObjectKind().GroupVersionKind().Kind
90-
switch kind {
91-
case roleKind:
92-
fallthrough
93-
case roleBindingKind:
94-
fallthrough
95-
case serviceAccountKind:
96-
related = true
97-
}
98-
99-
return
100-
}

pkg/controller/operators/olm/operator.go

Lines changed: 30 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -679,6 +679,29 @@ func (a *Operator) syncObject(obj interface{}) (syncError error) {
679679
a.requeueCSVsByLabelSet(logger, labelSets...)
680680
}
681681

682+
// Requeue CSVs that have the reason of `CSVReasonComponentFailedNoRetry` in the case of an RBAC change
683+
var errs []error
684+
related, _ := scoped.IsObjectRBACRelated(metaObj)
685+
if related {
686+
csvList := a.csvSet(metaObj.GetNamespace(), v1alpha1.CSVPhaseFailed)
687+
for _, csv := range csvList {
688+
if csv.Status.Reason != v1alpha1.CSVReasonComponentFailedNoRetry {
689+
continue
690+
}
691+
csv.SetPhase(v1alpha1.CSVPhasePending, v1alpha1.CSVReasonDetectedClusterChange, "Cluster resources changed state", a.now())
692+
_, err := a.client.OperatorsV1alpha1().ClusterServiceVersions(csv.GetNamespace()).UpdateStatus(csv)
693+
if err != nil {
694+
errs = append(errs, err)
695+
continue
696+
}
697+
if err := a.csvQueueSet.Requeue(csv.GetNamespace(), csv.GetName()); err != nil {
698+
errs = append(errs, err)
699+
}
700+
logger.Debug("Requeuing CSV due to detected RBAC change")
701+
}
702+
}
703+
704+
syncError = utilerrors.NewAggregate(errs)
682705
return nil
683706
}
684707

@@ -1096,6 +1119,12 @@ func (a *Operator) operatorGroupForCSV(csv *v1alpha1.ClusterServiceVersion, logg
10961119
if targetNamespaceList, err := a.getOperatorGroupTargets(operatorGroup); err == nil && len(targetNamespaceList) == 0 {
10971120
csv.SetPhaseWithEventIfChanged(v1alpha1.CSVPhaseFailed, v1alpha1.CSVReasonNoTargetNamespaces, "no targetNamespaces are matched operatorgroups namespace selection", now, a.recorder)
10981121
}
1122+
logger.Debug("CSV not in operatorgroup, requeuing operator group")
1123+
// this requeue helps when an operator group has not annotated a CSV due to a permissions error
1124+
// but the permissions issue has now been resolved
1125+
if err := a.ogQueueSet.Requeue(operatorGroup.GetNamespace(), operatorGroup.GetName()); err != nil {
1126+
return nil, err
1127+
}
10991128
return nil, nil
11001129
}
11011130
logger.Info("csv in operatorgroup")
@@ -1120,7 +1149,7 @@ func (a *Operator) transitionCSVState(in v1alpha1.ClusterServiceVersion) (out *v
11201149
})
11211150

11221151
if in.Status.Reason == v1alpha1.CSVReasonComponentFailedNoRetry {
1123-
// will change phase out of failed-no-retry in the event of an intentional requeue
1152+
// will change phase out of failed in the event of an intentional requeue
11241153
logger.Debugf("skipping sync for CSV in failed-no-retry state")
11251154
return
11261155
}

pkg/controller/operators/olm/operatorgroup.go

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -53,11 +53,34 @@ func (a *Operator) syncOperatorGroups(obj interface{}) error {
5353
"namespace": op.GetNamespace(),
5454
})
5555

56+
previousRef := op.Status.ServiceAccountRef.DeepCopy()
5657
op, err := a.serviceAccountSyncer.SyncOperatorGroup(op)
5758
if err != nil {
5859
logger.Errorf("error updating service account - %v", err)
5960
return err
6061
}
62+
if op.Status.ServiceAccountRef != previousRef {
63+
crdList, err := a.lister.OperatorsV1alpha1().ClusterServiceVersionLister().List(labels.Everything())
64+
if err != nil {
65+
return err
66+
}
67+
for _, csv := range crdList {
68+
if group, ok := csv.GetAnnotations()[v1.OperatorGroupAnnotationKey]; !ok || group != op.GetName() {
69+
continue
70+
}
71+
if csv.Status.Reason == v1alpha1.CSVReasonComponentFailedNoRetry {
72+
csv.SetPhase(v1alpha1.CSVPhasePending, v1alpha1.CSVReasonDetectedClusterChange, "Cluster resources changed state", a.now())
73+
_, err := a.client.OperatorsV1alpha1().ClusterServiceVersions(csv.GetNamespace()).UpdateStatus(csv)
74+
if err != nil {
75+
return err
76+
}
77+
if err := a.csvQueueSet.Requeue(csv.GetNamespace(), csv.GetName()); err != nil {
78+
return err
79+
}
80+
logger.Debug("Requeuing CSV due to detected service account change")
81+
}
82+
}
83+
}
6184

6285
targetNamespaces, err := a.updateNamespaceList(op)
6386
if err != nil {

pkg/lib/scoped/util.go

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,15 @@ package scoped
22

33
import (
44
v1 "k8s.io/api/core/v1"
5+
rbacv1 "k8s.io/api/rbac/v1"
6+
"k8s.io/apimachinery/pkg/runtime"
7+
8+
"github.com/operator-framework/operator-lifecycle-manager/pkg/lib/ownerutil"
9+
)
10+
11+
const (
12+
roleKind = "Role"
13+
roleBindingKind = "RoleBinding"
514
)
615

716
// IsServiceAccountToken returns true if the secret is a valid api token for the service account
@@ -24,3 +33,26 @@ func IsServiceAccountToken(secret *v1.Secret, sa *v1.ServiceAccount) bool {
2433

2534
return true
2635
}
36+
37+
func IsObjectRBACRelated(obj interface{}) (related bool, object runtime.Object) {
38+
object, ok := obj.(runtime.Object)
39+
if !ok {
40+
return
41+
}
42+
43+
if err := ownerutil.InferGroupVersionKind(object); err != nil {
44+
return
45+
}
46+
47+
kind := object.GetObjectKind().GroupVersionKind().Kind
48+
switch kind {
49+
case roleKind:
50+
fallthrough
51+
case roleBindingKind:
52+
fallthrough
53+
case rbacv1.ServiceAccountKind:
54+
related = true
55+
}
56+
57+
return
58+
}

0 commit comments

Comments
 (0)