Skip to content

Commit d899968

Browse files
committed
fix(subscriptions): add check for csv manifest dif before applying new
installplans
1 parent 316612a commit d899968

File tree

9 files changed

+82
-13
lines changed

9 files changed

+82
-13
lines changed

Makefile

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -153,6 +153,7 @@ container-mockgen:
153153
docker cp temp-mockgen:/go/src/github.com/operator-framework/operator-lifecycle-manager/pkg/fakes/client-go/listers/. ./pkg/fakes/client-go/listers
154154
docker cp temp-mockgen:/go/src/github.com/operator-framework/operator-lifecycle-manager/pkg/lib/operatorlister/operatorlisterfakes/. ./pkg/lib/operatorlister/operatorlisterfakes
155155
docker cp temp-mockgen:/go/src/github.com/operator-framework/operator-lifecycle-manager/pkg/lib/operatorclient/mock_client.go ./pkg/lib/operatorclient/mock_client.go
156+
docker cp temp-mockgen:/go/src/github.com/operator-framework/operator-lifecycle-manager/pkg/fakes/. ./pkg/fakes/.
156157
docker rm temp-mockgen
157158

158159
# Must be run in gopath: https://github.com/kubernetes/kubernetes/issues/67566

go.mod

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
module github.com/operator-framework/operator-lifecycle-manager
22

33
require (
4+
github.com/coreos/bbolt v1.3.2 // indirect
45
github.com/coreos/etcd v3.3.10+incompatible // indirect
56
github.com/coreos/go-semver v0.2.0
67
github.com/coreos/go-systemd v0.0.0-20181031085051-9002847aa142 // indirect
@@ -12,12 +13,13 @@ require (
1213
github.com/go-openapi/strfmt v0.18.0 // indirect
1314
github.com/go-openapi/validate v0.18.0 // indirect
1415
github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b
16+
github.com/golang/groupcache v0.0.0-20190129154638-5b532d6fd5ef // indirect
1517
github.com/golang/mock v1.1.1
1618
github.com/google/btree v0.0.0-20180813153112-4030bb1f1f0c // indirect
1719
github.com/google/gofuzz v0.0.0-20170612174753-24818f796faf // indirect
1820
github.com/googleapis/gnostic v0.2.0 // indirect
1921
github.com/grpc-ecosystem/go-grpc-middleware v1.0.0 // indirect
20-
github.com/grpc-ecosystem/grpc-gateway v1.6.3
22+
github.com/grpc-ecosystem/grpc-gateway v1.6.3 // indirect
2123
github.com/imdario/mergo v0.3.6 // indirect
2224
github.com/inconshreveable/mousetrap v1.0.0 // indirect
2325
github.com/json-iterator/go v1.1.5 // indirect
@@ -37,6 +39,7 @@ require (
3739
github.com/tmc/grpc-websocket-proxy v0.0.0-20190109142713-0ad062ec5ee5 // indirect
3840
github.com/ugorji/go/codec v0.0.0-20181022190402-e5e69e061d4f // indirect
3941
github.com/xiang90/probing v0.0.0-20190116061207-43a291ad63a2 // indirect
42+
go.etcd.io/bbolt v1.3.2 // indirect
4043
go.uber.org/atomic v1.3.2 // indirect
4144
go.uber.org/multierr v1.1.0 // indirect
4245
go.uber.org/zap v1.9.1 // indirect

go.sum

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,8 @@ github.com/boltdb/bolt v1.3.1/go.mod h1:clJnj/oiGkjum5o1McbSZDSLxVThjynRyGBgiAx2
2020
github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw=
2121
github.com/coreos/bbolt v1.3.0 h1:HIgH5xUWXT914HCI671AxuTTqjj64UOFr7pHn48LUTI=
2222
github.com/coreos/bbolt v1.3.0/go.mod h1:iRUV2dpdMOn7Bo10OQBFzIJO9kkE559Wcmn+qkEiiKk=
23+
github.com/coreos/bbolt v1.3.2 h1:wZwiHHUieZCquLkDL0B8UhzreNWsPHooDAG3q34zk0s=
24+
github.com/coreos/bbolt v1.3.2/go.mod h1:iRUV2dpdMOn7Bo10OQBFzIJO9kkE559Wcmn+qkEiiKk=
2325
github.com/coreos/etcd v3.3.9+incompatible/go.mod h1:uF7uidLiAD3TWHmW31ZFd/JWoc32PjwdhPthX9715RE=
2426
github.com/coreos/etcd v3.3.10+incompatible h1:KjVWqrZ5U0wa3CxY2AxlH6/UcB+PK2td1DcsYhA+HRs=
2527
github.com/coreos/etcd v3.3.10+incompatible/go.mod h1:uF7uidLiAD3TWHmW31ZFd/JWoc32PjwdhPthX9715RE=
@@ -89,6 +91,8 @@ github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfU
8991
github.com/golang/groupcache v0.0.0-20180924190550-6f2cf27854a4/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc=
9092
github.com/golang/groupcache v0.0.0-20181024230925-c65c006176ff h1:kOkM9whyQYodu09SJ6W3NCsHG7crFaJILQ22Gozp3lg=
9193
github.com/golang/groupcache v0.0.0-20181024230925-c65c006176ff/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc=
94+
github.com/golang/groupcache v0.0.0-20190129154638-5b532d6fd5ef h1:veQD95Isof8w9/WXiA+pa3tz3fJXkt5B7QaRBrM62gk=
95+
github.com/golang/groupcache v0.0.0-20190129154638-5b532d6fd5ef/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc=
9296
github.com/golang/lint v0.0.0-20180702182130-06c8688daad7/go.mod h1:tluoj9z5200jBnyusfRPU2LqT6J+DAorxEvtC7LHB+E=
9397
github.com/golang/mock v1.1.1 h1:G5FRp8JnTd7RQH5kemVNlMeyXQAztQ3mOWV95KxsXH8=
9498
github.com/golang/mock v1.1.1/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A=
@@ -206,6 +210,8 @@ github.com/ugorji/go/codec v0.0.0-20181022190402-e5e69e061d4f/go.mod h1:VFNgLljT
206210
github.com/xiang90/probing v0.0.0-20160813154853-07dd2e8dfe18/go.mod h1:UETIi67q53MR2AWcXfiuqkDkRtnGDLqkBTpCHuJHxtU=
207211
github.com/xiang90/probing v0.0.0-20190116061207-43a291ad63a2 h1:eY9dn8+vbi4tKz5Qo6v2eYzo7kUS51QINcR5jNpbZS8=
208212
github.com/xiang90/probing v0.0.0-20190116061207-43a291ad63a2/go.mod h1:UETIi67q53MR2AWcXfiuqkDkRtnGDLqkBTpCHuJHxtU=
213+
go.etcd.io/bbolt v1.3.2 h1:Z/90sZLPOeCy2PwprqkFa25PdkusRzaj9P8zm/KNyvk=
214+
go.etcd.io/bbolt v1.3.2/go.mod h1:IbVyRI1SCnLcuJnV2u8VeU0CEYM7e686BmAb1XKL+uU=
209215
go.uber.org/atomic v1.3.2 h1:2Oa65PReHzfn29GpvgsYwloV9AVFHPDk8tYxt2c2tr4=
210216
go.uber.org/atomic v1.3.2/go.mod h1:gD2HeocX3+yG+ygLZcrzQJaqmWj9AIm7n08wl/qW/PE=
211217
go.uber.org/multierr v1.1.0 h1:HoEmRHQPVSqub6w2z2d2EOVs2fjyFRGyofhKuyDq0QI=

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

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -145,6 +145,43 @@ type Step struct {
145145
Status StepStatus `json:"status"`
146146
}
147147

148+
// ManifestsMatch returns true if the CSV manifests in the StepResources of the given list of steps
149+
// matches those in the InstallPlanStatus.
150+
func (s *InstallPlanStatus) CSVManifestsMatch(steps []*Step) bool {
151+
if s.Plan == nil && steps == nil {
152+
return true
153+
}
154+
if s.Plan == nil || steps == nil {
155+
return false
156+
}
157+
158+
manifests := make(map[string]struct{})
159+
for _, step := range s.Plan {
160+
resource := step.Resource
161+
if resource.Kind != ClusterServiceVersionKind {
162+
continue
163+
}
164+
manifests[resource.Manifest] = struct{}{}
165+
}
166+
167+
for _, step := range steps {
168+
resource := step.Resource
169+
if resource.Kind != ClusterServiceVersionKind {
170+
continue
171+
}
172+
if _, ok := manifests[resource.Manifest]; !ok {
173+
return false
174+
}
175+
delete(manifests, resource.Manifest)
176+
}
177+
178+
if len(manifests) == 0 {
179+
return true
180+
}
181+
182+
return false
183+
}
184+
148185
func (s *Step) String() string {
149186
return fmt.Sprintf("%s: %s (%s)", s.Resolving, s.Resource, s.Status)
150187
}

pkg/controller/operators/catalog/operator.go

Lines changed: 25 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -47,8 +47,7 @@ const (
4747
serviceKind = "Service"
4848
roleKind = "Role"
4949
roleBindingKind = "RoleBinding"
50-
51-
generatedByKey = "olm/generated-by"
50+
generatedByKey = "olm.generated-by"
5251
)
5352

5453
// for test stubbing and for ensuring standardization of timezones to UTC
@@ -580,9 +579,9 @@ func (o *Operator) syncResolvingNamespace(obj interface{}) error {
580579
break
581580
}
582581
}
583-
installplanReference, err := o.createInstallPlan(namespace, subs, installPlanApproval, steps)
582+
installplanReference, err := o.ensureInstallPlan(logger, namespace, subs, installPlanApproval, steps)
584583
if err != nil {
585-
logger.WithError(err).Debug("error creating installplan")
584+
logger.WithError(err).Debug("error ensuring installplan")
586585
return err
587586
}
588587

@@ -679,8 +678,6 @@ func (o *Operator) ensureSubscriptionInstallPlanState(logger *logrus.Entry, sub
679678
// this indicates it was newly resolved by another operator, and we should reference that installplan in the status
680679
ipName, ok := sub.GetAnnotations()[generatedByKey]
681680
if !ok {
682-
// err := fmt.Errorf("no installplan reference or %s annotation found", generatedByKey)
683-
// logger.WithField("err", err.Error()).Error("an error occurred while associating a subscription with an installplan")
684681
return sub, nil
685682
}
686683

@@ -744,6 +741,28 @@ func (o *Operator) updateSubscriptionSetInstallPlanState(namespace string, subs
744741
return nil
745742
}
746743

744+
func (o *Operator) ensureInstallPlan(logger *logrus.Entry, namespace string, subs []*v1alpha1.Subscription, installPlanApproval v1alpha1.Approval, steps []*v1alpha1.Step) (*v1alpha1.InstallPlanReference, error) {
745+
if len(steps) == 0 {
746+
return nil, nil
747+
}
748+
749+
// Check if any existing installplans are creating the same resources
750+
installPlans, err := o.lister.OperatorsV1alpha1().InstallPlanLister().InstallPlans(namespace).List(labels.Everything())
751+
if err != nil {
752+
return nil, err
753+
}
754+
755+
for _, installPlan := range installPlans {
756+
if installPlan.Status.CSVManifestsMatch(steps) {
757+
logger.Infof("found InstallPlan with matching manifests: %s", installPlan.GetName())
758+
return o.referenceForInstallPlan(installPlan), nil
759+
}
760+
}
761+
logger.Warn("no installplan found with matching manifests, creating new one")
762+
763+
return o.createInstallPlan(namespace, subs, installPlanApproval, steps)
764+
}
765+
747766
func (o *Operator) createInstallPlan(namespace string, subs []*v1alpha1.Subscription, installPlanApproval v1alpha1.Approval, steps []*v1alpha1.Step) (*v1alpha1.InstallPlanReference, error) {
748767
if len(steps) == 0 {
749768
return nil, nil

pkg/controller/operators/catalog/operator_test.go

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -488,7 +488,8 @@ func NewFakeOperator(clientObjs []runtime.Object, k8sObjs []runtime.Object, extO
488488
podInformer := informerFactory.Core().V1().Pods()
489489
configMapInformer := informerFactory.Core().V1().ConfigMaps()
490490
subscriptionInformer := externalversions.NewSharedInformerFactoryWithOptions(clientFake, wakeupInterval, externalversions.WithNamespace(namespace)).Operators().V1alpha1().Subscriptions()
491-
491+
installPlanInformer := externalversions.NewSharedInformerFactoryWithOptions(clientFake, wakeupInterval, externalversions.WithNamespace(namespace)).Operators().V1alpha1().InstallPlans()
492+
492493
// register informers
493494
registryInformers := []cache.SharedIndexInformer{
494495
roleInformer.Informer(),
@@ -498,6 +499,7 @@ func NewFakeOperator(clientObjs []runtime.Object, k8sObjs []runtime.Object, extO
498499
podInformer.Informer(),
499500
configMapInformer.Informer(),
500501
subscriptionInformer.Informer(),
502+
installPlanInformer.Informer(),
501503
}
502504

503505
// register listers
@@ -509,6 +511,7 @@ func NewFakeOperator(clientObjs []runtime.Object, k8sObjs []runtime.Object, extO
509511
lister.CoreV1().RegisterPodLister(namespace, podInformer.Lister())
510512
lister.CoreV1().RegisterConfigMapLister(namespace, configMapInformer.Lister())
511513
lister.OperatorsV1alpha1().RegisterSubscriptionLister(namespace, subscriptionInformer.Lister())
514+
lister.OperatorsV1alpha1().RegisterInstallPlanLister(namespace, installPlanInformer.Lister())
512515

513516
// Create the new operator
514517
queueOperator, err := queueinformer.NewOperatorFromClient(opClientFake, logrus.New())

pkg/lib/operatorclient/mock_client.go

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

vendor/github.com/golang/groupcache/lru/lru.go

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

vendor/modules.txt

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -71,7 +71,7 @@ github.com/gogo/protobuf/gogoproto
7171
github.com/gogo/protobuf/protoc-gen-gogo/descriptor
7272
# github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b
7373
github.com/golang/glog
74-
# github.com/golang/groupcache v0.0.0-20181024230925-c65c006176ff
74+
# github.com/golang/groupcache v0.0.0-20190129154638-5b532d6fd5ef
7575
github.com/golang/groupcache/lru
7676
# github.com/golang/mock v1.1.1
7777
github.com/golang/mock/mockgen
@@ -336,20 +336,21 @@ k8s.io/apimachinery/pkg/api/equality
336336
k8s.io/apimachinery/pkg/api/validation
337337
k8s.io/apimachinery/pkg/util/yaml
338338
k8s.io/apimachinery/pkg/util/framer
339+
k8s.io/apimachinery/pkg/util/rand
339340
k8s.io/apimachinery/pkg/apis/meta/v1beta1
340341
k8s.io/apimachinery/pkg/util/mergepatch
341342
k8s.io/apimachinery/third_party/forked/golang/json
342343
k8s.io/apimachinery/pkg/api/validation/path
343344
k8s.io/apimachinery/pkg/apis/meta/v1/validation
344345
k8s.io/apimachinery/pkg/util/uuid
345346
k8s.io/apimachinery/third_party/forked/golang/reflect
346-
k8s.io/apimachinery/pkg/util/rand
347347
# k8s.io/apiserver v0.0.0-20181026151315-13cfe3978170
348348
k8s.io/apiserver/pkg/server
349349
k8s.io/apiserver/pkg/util/logs
350350
k8s.io/apiserver/pkg/authentication/serviceaccount
351351
k8s.io/apiserver/pkg/authentication/user
352352
k8s.io/apiserver/pkg/authorization/authorizer
353+
k8s.io/apiserver/pkg/storage/names
353354
k8s.io/apiserver/pkg/endpoints/openapi
354355
k8s.io/apiserver/pkg/registry/rest
355356
k8s.io/apiserver/pkg/server/options
@@ -379,7 +380,6 @@ k8s.io/apiserver/pkg/server/mux
379380
k8s.io/apiserver/pkg/server/routes
380381
k8s.io/apiserver/pkg/server/storage
381382
k8s.io/apiserver/pkg/util/feature
382-
k8s.io/apiserver/pkg/storage/names
383383
k8s.io/apiserver/pkg/admission/initializer
384384
k8s.io/apiserver/pkg/admission/metrics
385385
k8s.io/apiserver/pkg/apis/apiserver

0 commit comments

Comments
 (0)