Skip to content

Commit 4ee4e87

Browse files
Merge pull request #1885 from dinhxuanvu/create-operatorconditions-for-operator
Add OLM support for the Upgradeable OperatorCondition and Admin overrides
2 parents cfda6a3 + abaf218 commit 4ee4e87

File tree

11 files changed

+532
-6
lines changed

11 files changed

+532
-6
lines changed

go.mod

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@ require (
2525
github.com/onsi/gomega v1.9.0
2626
github.com/openshift/api v0.0.0-20200331152225-585af27e34fd
2727
github.com/openshift/client-go v0.0.0-20200326155132-2a6cd50aedd0
28-
github.com/operator-framework/api v0.3.23
28+
github.com/operator-framework/api v0.3.25
2929
github.com/operator-framework/operator-registry v1.13.6
3030
github.com/otiai10/copy v1.2.0
3131
github.com/pkg/errors v0.9.1

go.sum

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -756,8 +756,8 @@ github.com/openzipkin/zipkin-go v0.1.6/go.mod h1:QgAqvLzwWbR/WpD4A3cGpPtJrZXNIiJ
756756
github.com/openzipkin/zipkin-go v0.2.1/go.mod h1:NaW6tEwdmWMaCDZzg8sh+IBNOxHMPnhQw8ySjnjRyN4=
757757
github.com/openzipkin/zipkin-go v0.2.2/go.mod h1:NaW6tEwdmWMaCDZzg8sh+IBNOxHMPnhQw8ySjnjRyN4=
758758
github.com/operator-framework/api v0.3.7-0.20200602203552-431198de9fc2/go.mod h1:Xbje9x0SHmh0nihE21kpesB38vk3cyxnE6JdDS8Jo1Q=
759-
github.com/operator-framework/api v0.3.23 h1:+QiJ0m5SjfV+iMv8uzuGac+PoJFlTaMFIN8eVccUnoY=
760-
github.com/operator-framework/api v0.3.23/go.mod h1:GVNiB6AQucwdZz3ZFXNv9HtcLOzcFnr6O/QldzKG93g=
759+
github.com/operator-framework/api v0.3.25 h1:d6WgHCshCffT37okVZeL+IbGlhrsHy57xdfMnopC8rI=
760+
github.com/operator-framework/api v0.3.25/go.mod h1:GVNiB6AQucwdZz3ZFXNv9HtcLOzcFnr6O/QldzKG93g=
761761
github.com/operator-framework/operator-registry v1.13.6 h1:h/dIjQQS7uneQNRifrSz7h0xg4Xyjg6C9f6XZofbMPg=
762762
github.com/operator-framework/operator-registry v1.13.6/go.mod h1:YhnIzOVjRU2ZwZtzt+fjcjW8ujJaSFynBEu7QVKaSdU=
763763
github.com/otiai10/copy v1.2.0 h1:HvG945u96iNadPoG2/Ja2+AUJeW5YuFQMixq9yirC+k=

pkg/controller/operators/olm/operator.go

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -220,6 +220,22 @@ func newOperatorWithConfig(ctx context.Context, config *operatorConfig) (*Operat
220220
return nil, err
221221
}
222222

223+
// Register OperatorCondition QueueInformer
224+
opConditionInformer := extInformerFactory.Operators().V1().OperatorConditions()
225+
op.lister.OperatorsV1().RegisterOperatorConditionLister(namespace, opConditionInformer.Lister())
226+
opConditionQueueInformer, err := queueinformer.NewQueueInformer(
227+
ctx,
228+
queueinformer.WithLogger(op.logger),
229+
queueinformer.WithInformer(opConditionInformer.Informer()),
230+
queueinformer.WithSyncer(k8sSyncer),
231+
)
232+
if err != nil {
233+
return nil, err
234+
}
235+
if err := op.RegisterQueueInformer(opConditionQueueInformer); err != nil {
236+
return nil, err
237+
}
238+
223239
subInformer := extInformerFactory.Operators().V1alpha1().Subscriptions()
224240
op.lister.OperatorsV1alpha1().RegisterSubscriptionLister(namespace, subInformer.Lister())
225241
subQueueInformer, err := queueinformer.NewQueueInformer(
@@ -1426,6 +1442,15 @@ func (a *Operator) transitionCSVState(in v1alpha1.ClusterServiceVersion) (out *v
14261442
logger.Info("scheduling ClusterServiceVersion for requirement verification")
14271443
out.SetPhaseWithEvent(v1alpha1.CSVPhasePending, v1alpha1.CSVReasonRequirementsUnknown, "requirements not yet checked", now, a.recorder)
14281444
case v1alpha1.CSVPhasePending:
1445+
// Check previous version's Upgradeable condition
1446+
replacedCSV := a.isReplacing(out)
1447+
if replacedCSV != nil {
1448+
operatorUpgradeable, condErr := a.isOperatorUpgradeable(replacedCSV)
1449+
if !operatorUpgradeable {
1450+
out.SetPhaseWithEventIfChanged(v1alpha1.CSVPhasePending, v1alpha1.CSVReasonOperatorConditionNotUpgradeable, fmt.Sprintf("operator is not upgradeable: %s", condErr), now, a.recorder)
1451+
return
1452+
}
1453+
}
14291454
met, statuses, err := a.requirementAndPermissionStatus(out)
14301455
if err != nil {
14311456
// TODO: account for Bad Rule as well
Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
package olm
2+
3+
import (
4+
"fmt"
5+
6+
k8serrors "k8s.io/apimachinery/pkg/api/errors"
7+
meta "k8s.io/apimachinery/pkg/api/meta"
8+
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
9+
10+
operatorsv1 "github.com/operator-framework/api/pkg/operators/v1"
11+
"github.com/operator-framework/api/pkg/operators/v1alpha1"
12+
)
13+
14+
func (a *Operator) isOperatorUpgradeable(csv *v1alpha1.ClusterServiceVersion) (bool, error) {
15+
if csv == nil {
16+
return false, fmt.Errorf("CSV is invalid")
17+
}
18+
19+
cond, err := a.lister.OperatorsV1().OperatorConditionLister().OperatorConditions(csv.GetNamespace()).Get(csv.GetName())
20+
if err != nil {
21+
if k8serrors.IsNotFound(err) {
22+
return true, nil
23+
}
24+
return false, err
25+
}
26+
27+
// Check condition overrides
28+
for _, override := range cond.Spec.Overrides {
29+
if override.Type == operatorsv1.OperatorUpgradeable {
30+
if override.Status == metav1.ConditionTrue {
31+
return true, nil
32+
}
33+
return false, fmt.Errorf("The operator is not upgradeable: %s", override.Message)
34+
}
35+
}
36+
37+
// Check for OperatorUpgradeable condition status
38+
if c := meta.FindStatusCondition(cond.Status.Conditions, operatorsv1.OperatorUpgradeable); c != nil {
39+
if c.Status == metav1.ConditionFalse {
40+
return false, fmt.Errorf("The operator is not upgradeable: %s", c.Message)
41+
}
42+
}
43+
44+
return true, nil
45+
}

pkg/lib/operatorlister/lister.go

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -102,8 +102,10 @@ type OperatorsV1alpha1Lister interface {
102102
//go:generate go run github.com/maxbrunsfeld/counterfeiter/v6 . OperatorsV1Lister
103103
type OperatorsV1Lister interface {
104104
RegisterOperatorGroupLister(namespace string, lister v1.OperatorGroupLister)
105+
RegisterOperatorConditionLister(namespace string, lister v1.OperatorConditionLister)
105106

106107
OperatorGroupLister() v1.OperatorGroupLister
108+
OperatorConditionLister() v1.OperatorConditionLister
107109
}
108110

109111
type appsV1Lister struct {
@@ -189,12 +191,14 @@ func newOperatorsV1alpha1Lister() *operatorsV1alpha1Lister {
189191
}
190192

191193
type operatorsV1Lister struct {
192-
operatorGroupLister *UnionOperatorGroupLister
194+
operatorGroupLister *UnionOperatorGroupLister
195+
operatorConditionLister *UnionOperatorConditionLister
193196
}
194197

195198
func newOperatorsV1Lister() *operatorsV1Lister {
196199
return &operatorsV1Lister{
197-
operatorGroupLister: &UnionOperatorGroupLister{},
200+
operatorGroupLister: &UnionOperatorGroupLister{},
201+
operatorConditionLister: &UnionOperatorConditionLister{},
198202
}
199203
}
200204

Lines changed: 96 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,96 @@
1+
package operatorlister
2+
3+
import (
4+
"fmt"
5+
"sync"
6+
7+
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
8+
"k8s.io/apimachinery/pkg/labels"
9+
"k8s.io/apimachinery/pkg/types"
10+
11+
v1 "github.com/operator-framework/api/pkg/operators/v1"
12+
listers "github.com/operator-framework/operator-lifecycle-manager/pkg/api/client/listers/operators/v1"
13+
)
14+
15+
type UnionOperatorConditionLister struct {
16+
opConditionListers map[string]listers.OperatorConditionLister
17+
opConditionLock sync.RWMutex
18+
}
19+
20+
// List lists all OperatorConditions in the indexer.
21+
func (uol *UnionOperatorConditionLister) List(selector labels.Selector) (ret []*v1.OperatorCondition, err error) {
22+
uol.opConditionLock.RLock()
23+
defer uol.opConditionLock.RUnlock()
24+
25+
set := make(map[types.UID]*v1.OperatorCondition)
26+
for _, cl := range uol.opConditionListers {
27+
csvs, err := cl.List(selector)
28+
if err != nil {
29+
return nil, err
30+
}
31+
32+
for _, csv := range csvs {
33+
set[csv.GetUID()] = csv
34+
}
35+
}
36+
37+
for _, csv := range set {
38+
ret = append(ret, csv)
39+
}
40+
41+
return
42+
}
43+
44+
// OperatorConditions returns an object that can list and get OperatorConditions.
45+
func (uol *UnionOperatorConditionLister) OperatorConditions(namespace string) listers.OperatorConditionNamespaceLister {
46+
uol.opConditionLock.RLock()
47+
defer uol.opConditionLock.RUnlock()
48+
49+
// Check for specific namespace listers
50+
if cl, ok := uol.opConditionListers[namespace]; ok {
51+
return cl.OperatorConditions(namespace)
52+
}
53+
54+
// Check for any namespace-all listers
55+
if cl, ok := uol.opConditionListers[metav1.NamespaceAll]; ok {
56+
return cl.OperatorConditions(namespace)
57+
}
58+
59+
return &NullOperatorConditionNamespaceLister{}
60+
}
61+
62+
func (uol *UnionOperatorConditionLister) RegisterOperatorConditionLister(namespace string, lister listers.OperatorConditionLister) {
63+
uol.opConditionLock.Lock()
64+
defer uol.opConditionLock.Unlock()
65+
66+
if uol.opConditionListers == nil {
67+
uol.opConditionListers = make(map[string]listers.OperatorConditionLister)
68+
}
69+
70+
uol.opConditionListers[namespace] = lister
71+
}
72+
73+
func (l *operatorsV1Lister) RegisterOperatorConditionLister(namespace string, lister listers.OperatorConditionLister) {
74+
l.operatorConditionLister.RegisterOperatorConditionLister(namespace, lister)
75+
}
76+
77+
func (l *operatorsV1Lister) OperatorConditionLister() listers.OperatorConditionLister {
78+
return l.operatorConditionLister
79+
}
80+
81+
// NullOperatorConditionNamespaceLister is an implementation of a null OperatorConditionNamespaceLister. It is
82+
// used to prevent nil pointers when no OperatorConditionNamespaceLister has been registered for a given
83+
// namespace.
84+
type NullOperatorConditionNamespaceLister struct {
85+
listers.OperatorConditionNamespaceLister
86+
}
87+
88+
// List returns nil and an error explaining that this is a NullOperatorConditionNamespaceLister.
89+
func (n *NullOperatorConditionNamespaceLister) List(selector labels.Selector) (ret []*v1.OperatorCondition, err error) {
90+
return nil, fmt.Errorf("cannot list OperatorConditions with a NullOperatorConditionNamespaceLister")
91+
}
92+
93+
// Get returns nil and an error explaining that this is a NullOperatorConditionNamespaceLister.
94+
func (n *NullOperatorConditionNamespaceLister) Get(name string) (*v1.OperatorCondition, error) {
95+
return nil, fmt.Errorf("cannot get OperatorCondition with a NullOperatorConditionNamespaceLister")
96+
}

pkg/lib/operatorlister/operatorlisterfakes/fake_operators_v1lister.go

Lines changed: 104 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

0 commit comments

Comments
 (0)