diff --git a/Makefile b/Makefile index 0fa054d17e7..999ac453373 100644 --- a/Makefile +++ b/Makefile @@ -150,10 +150,11 @@ container-mockgen: docker build -t olm:mockgen -f mockgen.Dockerfile . docker run --name temp-mockgen olm:mockgen /bin/true docker cp temp-mockgen:/go/src/github.com/operator-framework/operator-lifecycle-manager/pkg/api/wrappers/wrappersfakes/. ./pkg/api/wrappers/wrappersfakes - docker cp temp-mockgen:/go/src/github.com/operator-framework/operator-lifecycle-manager/pkg/fakes/client-go/listers/. ./pkg/fakes/client-go/listers docker cp temp-mockgen:/go/src/github.com/operator-framework/operator-lifecycle-manager/pkg/lib/operatorlister/operatorlisterfakes/. ./pkg/lib/operatorlister/operatorlisterfakes 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 docker cp temp-mockgen:/go/src/github.com/operator-framework/operator-lifecycle-manager/pkg/fakes/. ./pkg/fakes/. + docker cp temp-mockgen:/go/src/github.com/operator-framework/operator-lifecycle-manager/pkg/controller/registry/resolver/fakes/fake_registry_client.go ./pkg/controller/registry/resolver/fakes/fake_registry_client.go + docker cp temp-mockgen:/go/src/github.com/operator-framework/operator-lifecycle-manager/pkg/package-server/client/fakes/fake_registry_client.go ./pkg/package-server/client/fakes/fake_registry_client.go docker rm temp-mockgen # Must be run in gopath: https://github.com/kubernetes/kubernetes/issues/67566 diff --git a/go.mod b/go.mod index 802a9ba1dac..e638b794d20 100644 --- a/go.mod +++ b/go.mod @@ -29,7 +29,7 @@ require ( github.com/openshift/api v3.9.1-0.20190129160438-bbc4289c54e0+incompatible github.com/openshift/client-go v0.0.0-20190128154758-1540772775fa github.com/openshift/library-go v0.0.0-20190125204812-22b2ba2f485f - github.com/operator-framework/operator-registry v1.0.4 + github.com/operator-framework/operator-registry v1.0.5 github.com/peterbourgon/diskv v2.0.1+incompatible // indirect github.com/pkg/errors v0.8.0 github.com/prometheus/client_golang v0.9.1 diff --git a/go.sum b/go.sum index ce2ee0beee0..0667dcc55d3 100644 --- a/go.sum +++ b/go.sum @@ -166,8 +166,8 @@ github.com/openshift/library-go v0.0.0-20190125204812-22b2ba2f485f/go.mod h1:NBt github.com/operator-framework/operator-lifecycle-manager v0.0.0-20181023032605-e838f7fb2186/go.mod h1:Ma5ZXd4S1vmMyewWlF7aO8CZiokR7Sd8dhSfkGkNU4U= github.com/operator-framework/operator-lifecycle-manager v0.0.0-20190105193533-81104ffdc4fb/go.mod h1:XMyE4n2opUK4N6L45YGQkXXi8F9fD7XDYFv/CsS6V5I= github.com/operator-framework/operator-registry v1.0.1/go.mod h1:1xEdZjjUg2hPEd52LG3YQ0jtwiwEGdm98S1TH5P4RAA= -github.com/operator-framework/operator-registry v1.0.4 h1:/xOuw0AFrnV/zjZQeEGtX/xH/ZoLOrNZqWaYU5bRQwM= -github.com/operator-framework/operator-registry v1.0.4/go.mod h1:hve6YwcjM2nGVlscLtNsp9sIIBkNZo6jlJgzWw7vP9s= +github.com/operator-framework/operator-registry v1.0.5 h1:LKhQvSeA3/PHSThchV6rquS8jy2ocvYRHqqCikkyumE= +github.com/operator-framework/operator-registry v1.0.5/go.mod h1:hve6YwcjM2nGVlscLtNsp9sIIBkNZo6jlJgzWw7vP9s= github.com/pborman/uuid v1.2.0 h1:J7Q5mO4ysT1dv8hyrUGHb9+ooztCXu1D8MY8DZYsu3g= github.com/pborman/uuid v1.2.0/go.mod h1:X/NO0urCmaxf9VXbdlT7C2Yzkj2IKimNn4k+gtPdI/k= github.com/petar/GoLLRB v0.0.0-20130427215148-53be0d36a84c/go.mod h1:HUpKUBZnpzkdx0kD/+Yfuft+uD3zHGtXF/XJB14TUr4= @@ -288,7 +288,7 @@ k8s.io/apimachinery v0.0.0-20190118094746-1525e4dadd2d/go.mod h1:ccL7Eh7zubPUSh9 k8s.io/apiserver v0.0.0-20181026151315-13cfe3978170 h1:CqI85nZvPaV+7JFono0nAOGOx2brocqefcOhDPVhHKI= k8s.io/apiserver v0.0.0-20181026151315-13cfe3978170/go.mod h1:6bqaTSOSJavUIXUtfaR9Os9JtTCm8ZqH2SUl2S60C4w= k8s.io/client-go v0.0.0-20180718001006-59698c7d9724/go.mod h1:7vJpHMYJwNQCWgzmNV+VYUl1zCObLyodBc8nIyt8L5s= -k8s.io/client-go v8.0.0+incompatible h1:2pUaSg2x6iEHr8cia6zmWhoCXG1EDG9TCx9s//Aq7HY= +k8s.io/client-go v8.0.0+incompatible h1:tTI4hRmb1DRMl4fG6Vclfdi6nTM82oIrTT7HfitmxC4= k8s.io/client-go v8.0.0+incompatible/go.mod h1:7vJpHMYJwNQCWgzmNV+VYUl1zCObLyodBc8nIyt8L5s= k8s.io/code-generator v0.0.0-20181203235156-f8cba74510f3 h1:f/Aa24HPnPEDWia884BCF94E1b29KYjOTVTHcBzvT2Q= k8s.io/code-generator v0.0.0-20181203235156-f8cba74510f3/go.mod h1:MYiN+ZJZ9HkETbgVZdWw2AsuAi9PZ4V80cwfuf2axe8= diff --git a/pkg/controller/operators/catalog/operator.go b/pkg/controller/operators/catalog/operator.go index ee61234b373..5ec3c8d6e58 100644 --- a/pkg/controller/operators/catalog/operator.go +++ b/pkg/controller/operators/catalog/operator.go @@ -530,14 +530,11 @@ func (o *Operator) syncResolvingNamespace(obj interface{}) error { // get the set of sources that should be used for resolution and best-effort get their connections working logger.Debug("resolving sources") resolverSources := o.ensureResolverSources(logger, namespace) + querier := resolver.NewNamespaceSourceQuerier(resolverSources) logger.Debug("checking if subscriptions need update") subs, err := o.lister.OperatorsV1alpha1().SubscriptionLister().Subscriptions(namespace).List(labels.Everything()) - if err != nil { - logger.WithError(err).Debug("couldn't list subscriptions") - return err - } // TODO: parallel subscriptionUpdated := false @@ -557,7 +554,7 @@ func (o *Operator) syncResolvingNamespace(obj interface{}) error { subscriptionUpdated = subscriptionUpdated || changedIp // record the current state of the desired corresponding CSV in the status. no-op if we don't know the csv yet. - sub, changedCSV, err := o.ensureSubscriptionCSVState(logger, sub) + sub, changedCSV, err := o.ensureSubscriptionCSVState(logger, sub, querier) if err != nil { return err } @@ -581,7 +578,7 @@ func (o *Operator) syncResolvingNamespace(obj interface{}) error { logger.Debug("resolving subscriptions in namespace") // resolve a set of steps to apply to a cluster, a set of subscriptions to create/update, and any errors - steps, updatedSubs, err := o.resolver.ResolveSteps(namespace, resolver.NewNamespaceSourceQuerier(resolverSources)) + steps, updatedSubs, err := o.resolver.ResolveSteps(namespace, querier) if err != nil { return err } @@ -721,7 +718,7 @@ func (o *Operator) ensureSubscriptionInstallPlanState(logger *logrus.Entry, sub return updated, true, nil } -func (o *Operator) ensureSubscriptionCSVState(logger *logrus.Entry, sub *v1alpha1.Subscription) (*v1alpha1.Subscription, bool, error) { +func (o *Operator) ensureSubscriptionCSVState(logger *logrus.Entry, sub *v1alpha1.Subscription, querier resolver.SourceQuerier) (*v1alpha1.Subscription, bool, error) { if sub.Status.CurrentCSV == "" { return sub, false, nil } @@ -732,7 +729,17 @@ func (o *Operator) ensureSubscriptionCSVState(logger *logrus.Entry, sub *v1alpha logger.WithError(err).WithField("currentCSV", sub.Status.CurrentCSV).Debug("error fetching csv listed in subscription status") out.Status.State = v1alpha1.SubscriptionStateUpgradePending } else { - out.Status.State = v1alpha1.SubscriptionStateAtLatest + // Check if an update is available for the current csv + if err := querier.Queryable(); err != nil { + return nil, false, err + } + bundle, _, _ := querier.FindReplacement(sub.Status.CurrentCSV, sub.Spec.Package, sub.Spec.Channel, resolver.CatalogKey{sub.Spec.CatalogSource, sub.Spec.CatalogSourceNamespace}) + if bundle != nil { + out.Status.State = v1alpha1.SubscriptionStateUpgradeAvailable + } else { + out.Status.State = v1alpha1.SubscriptionStateAtLatest + } + out.Status.InstalledCSV = sub.Status.CurrentCSV } diff --git a/pkg/controller/registry/resolver/evolver.go b/pkg/controller/registry/resolver/evolver.go index 8ddd9624c66..4b5800bb79e 100644 --- a/pkg/controller/registry/resolver/evolver.go +++ b/pkg/controller/registry/resolver/evolver.go @@ -60,7 +60,7 @@ func (e *NamespaceGenerationEvolver) checkForUpdates() error { continue } - o, err := NewOperatorFromBundle(bundle, *key) + o, err := NewOperatorFromBundle(bundle, op.SourceInfo().StartingCSV, *key) if err != nil { return errors.Wrap(err, "error parsing bundle") } @@ -76,14 +76,13 @@ func (e *NamespaceGenerationEvolver) checkForUpdates() error { func (e *NamespaceGenerationEvolver) addNewOperators(add map[OperatorSourceInfo]struct{}) error { for s := range add { - bundle, key, err := e.querier.FindPackage(s.Package, s.Channel, s.Catalog) - + bundle, key, err := e.querier.FindPackage(s.Package, s.Channel, s.StartingCSV, s.Catalog) if err != nil { // TODO: log or collect warnings return errors.Wrapf(err, "%s not found", s) } - o, err := NewOperatorFromBundle(bundle, *key) + o, err := NewOperatorFromBundle(bundle, s.StartingCSV, *key) if err != nil { return errors.Wrap(err, "error parsing bundle") } @@ -109,7 +108,7 @@ func (e *NamespaceGenerationEvolver) queryForRequiredAPIs() error { // attempt to find a bundle that provides that api if bundle, key, err := e.querier.FindProvider(*api); err == nil { // add a bundle that provides the api to the generation - o, err := NewOperatorFromBundle(bundle, *key) + o, err := NewOperatorFromBundle(bundle, "", *key) if err != nil { return errors.Wrap(err, "error parsing bundle") } diff --git a/pkg/controller/registry/resolver/evolver_test.go b/pkg/controller/registry/resolver/evolver_test.go index 02d3f8f1ad5..1c5377378db 100644 --- a/pkg/controller/registry/resolver/evolver_test.go +++ b/pkg/controller/registry/resolver/evolver_test.go @@ -55,7 +55,7 @@ func TestNamespaceGenerationEvolver(t *testing.T) { }, }), gen: NewGenerationFromOperators( - NewFakeOperatorSurface("op1", "pkgA", "c", "", "s", []opregistry.APIKey{{"g", "v", "k", "ks"}}, nil, nil, nil), + NewFakeOperatorSurface("op1", "pkgA", "c", "", "s", "", []opregistry.APIKey{{"g", "v", "k", "ks"}}, nil, nil, nil), ), }, args: args{ @@ -68,10 +68,67 @@ func TestNamespaceGenerationEvolver(t *testing.T) { }, }, wantGen: NewGenerationFromOperators( - NewFakeOperatorSurface("op1", "pkgA", "c", "", "s", []opregistry.APIKey{{"g", "v", "k", "ks"}}, nil, nil, nil), - NewFakeOperatorSurface("nothing.v1", "nothing", "channel", "", "catsrc", nil, nil, nil, nil), + NewFakeOperatorSurface("op1", "pkgA", "c", "", "s", "", []opregistry.APIKey{{"g", "v", "k", "ks"}}, nil, nil, nil), + NewFakeOperatorSurface("nothing.v1", "nothing", "channel", "", "catsrc", "", nil, nil, nil, nil), ), }, + { + name: "NoNewRequiredAPIs/StartingCSV", + fields: fields{ + querier: NewFakeSourceQuerier(map[CatalogKey][]*opregistry.Bundle{ + CatalogKey{"catsrc", "catsrc-namespace"}: { + bundle("csv1", "p", "c", "", EmptyAPISet(), EmptyAPISet(), EmptyAPISet(), EmptyAPISet()), + bundle("nothing.v1", "nothing", "channel", "", EmptyAPISet(), EmptyAPISet(), EmptyAPISet(), EmptyAPISet()), + bundle("nothing.v2", "nothing", "channel", "nothing.v1", EmptyAPISet(), EmptyAPISet(), EmptyAPISet(), EmptyAPISet()), + }, + }), + gen: NewGenerationFromOperators( + NewFakeOperatorSurface("op1", "pkgA", "c", "", "s", "", []opregistry.APIKey{{"g", "v", "k", "ks"}}, nil, nil, nil), + ), + }, + args: args{ + add: map[OperatorSourceInfo]struct{}{ + OperatorSourceInfo{ + Package: "nothing", + Channel: "channel", + StartingCSV: "nothing.v1", + Catalog: CatalogKey{"catsrc", "catsrc-namespace"}, + }: {}, + }, + }, + wantGen: NewGenerationFromOperators( + NewFakeOperatorSurface("op1", "pkgA", "c", "", "s", "", []opregistry.APIKey{{"g", "v", "k", "ks"}}, nil, nil, nil), + NewFakeOperatorSurface("nothing.v1", "nothing", "channel", "", "catsrc", "nothing.v1", nil, nil, nil, nil), + ), + }, + { + name: "NoNewRequiredAPIs/StartingCSV/NotFound", + fields: fields{ + querier: NewFakeSourceQuerier(map[CatalogKey][]*opregistry.Bundle{ + CatalogKey{"catsrc", "catsrc-namespace"}: { + bundle("csv1", "p", "c", "", EmptyAPISet(), EmptyAPISet(), EmptyAPISet(), EmptyAPISet()), + bundle("nothing.v2", "nothing", "channel", "", EmptyAPISet(), EmptyAPISet(), EmptyAPISet(), EmptyAPISet()), + }, + }), + gen: NewGenerationFromOperators( + NewFakeOperatorSurface("op1", "pkgA", "c", "", "s", "", []opregistry.APIKey{{"g", "v", "k", "ks"}}, nil, nil, nil), + ), + }, + args: args{ + add: map[OperatorSourceInfo]struct{}{ + OperatorSourceInfo{ + Package: "nothing", + Channel: "channel", + StartingCSV: "nothing.v1", + Catalog: CatalogKey{"catsrc", "catsrc-namespace"}, + }: {}, + }, + }, + wantGen: NewGenerationFromOperators( + NewFakeOperatorSurface("op1", "pkgA", "c", "", "s", "", []opregistry.APIKey{{"g", "v", "k", "ks"}}, nil, nil, nil), + ), + wantErr: fmt.Errorf("{nothing channel nothing.v1 {catsrc catsrc-namespace}} not found: no bundle found"), + }, { // the incoming subscription requires apis that can't be found // this should contract back to the original set @@ -106,7 +163,7 @@ func TestNamespaceGenerationEvolver(t *testing.T) { }, }), gen: NewGenerationFromOperators( - NewFakeOperatorSurface("op1", "pkgA", "c", "", "s", []opregistry.APIKey{{"g", "v", "k", "ks"}}, nil, nil, nil), + NewFakeOperatorSurface("op1", "pkgA", "c", "", "s", "", []opregistry.APIKey{{"g", "v", "k", "ks"}}, nil, nil, nil), ), }, args: args{ @@ -119,7 +176,7 @@ func TestNamespaceGenerationEvolver(t *testing.T) { }, }, wantGen: NewGenerationFromOperators( - NewFakeOperatorSurface("op1", "pkgA", "c", "", "s", []opregistry.APIKey{{"g", "v", "k", "ks"}}, nil, nil, nil), + NewFakeOperatorSurface("op1", "pkgA", "c", "", "s", "", []opregistry.APIKey{{"g", "v", "k", "ks"}}, nil, nil, nil), ), }, { @@ -145,8 +202,8 @@ func TestNamespaceGenerationEvolver(t *testing.T) { }, }, wantGen: NewGenerationFromOperators( - NewFakeOperatorSurface("depender.v1", "depender", "channel", "", "catsrc", nil, []opregistry.APIKey{{"g", "v", "k", "ks"}}, nil, nil), - NewFakeOperatorSurface("provider.v1", "provider", "channel", "", "catsrc", []opregistry.APIKey{{"g", "v", "k", "ks"}}, nil, nil, nil), + NewFakeOperatorSurface("depender.v1", "depender", "channel", "", "catsrc", "", nil, []opregistry.APIKey{{"g", "v", "k", "ks"}}, nil, nil), + NewFakeOperatorSurface("provider.v1", "provider", "channel", "", "catsrc", "", []opregistry.APIKey{{"g", "v", "k", "ks"}}, nil, nil, nil), ), }, { @@ -207,9 +264,9 @@ func TestNamespaceGenerationEvolver(t *testing.T) { }, }, wantGen: NewGenerationFromOperators( - NewFakeOperatorSurface("depender.v1", "depender", "channel", "", "catsrc", nil, []opregistry.APIKey{{"g", "v", "k", "ks"}}, nil, nil), - NewFakeOperatorSurface("provider.v1", "provider", "channel", "", "catsrc", []opregistry.APIKey{{"g", "v", "k", "ks"}}, []opregistry.APIKey{{"g2", "v2", "k2", "k2s"}}, nil, nil), - NewFakeOperatorSurface("provider2.v1", "provider2", "channel", "", "catsrc", []opregistry.APIKey{{"g2", "v2", "k2", "k2s"}}, nil, nil, nil), + NewFakeOperatorSurface("depender.v1", "depender", "channel", "", "catsrc", "", nil, []opregistry.APIKey{{"g", "v", "k", "ks"}}, nil, nil), + NewFakeOperatorSurface("provider.v1", "provider", "channel", "", "catsrc", "", []opregistry.APIKey{{"g", "v", "k", "ks"}}, []opregistry.APIKey{{"g2", "v2", "k2", "k2s"}}, nil, nil), + NewFakeOperatorSurface("provider2.v1", "provider2", "channel", "", "catsrc", "", []opregistry.APIKey{{"g2", "v2", "k2", "k2s"}}, nil, nil, nil), ), }, { @@ -243,9 +300,9 @@ func TestNamespaceGenerationEvolver(t *testing.T) { }, }, wantGen: NewGenerationFromOperators( - NewFakeOperatorSurface("depender.v1", "depender", "channel", "", "catsrc", nil, []opregistry.APIKey{{"g", "v", "k", "ks"}}, nil, nil), - NewFakeOperatorSurface("provider.v1", "provider", "channel", "", "catsrc", []opregistry.APIKey{{"g", "v", "k", "ks"}}, nil, nil, []opregistry.APIKey{{"g2", "v2", "k2", "k2s"}}), - NewFakeOperatorSurface("provider2.v1", "provider2", "channel", "", "catsrc", nil, nil, []opregistry.APIKey{{"g2", "v2", "k2", "k2s"}}, nil), + NewFakeOperatorSurface("depender.v1", "depender", "channel", "", "catsrc", "", nil, []opregistry.APIKey{{"g", "v", "k", "ks"}}, nil, nil), + NewFakeOperatorSurface("provider.v1", "provider", "channel", "", "catsrc", "", []opregistry.APIKey{{"g", "v", "k", "ks"}}, nil, nil, []opregistry.APIKey{{"g2", "v2", "k2", "k2s"}}), + NewFakeOperatorSurface("provider2.v1", "provider2", "channel", "", "catsrc", "", nil, nil, []opregistry.APIKey{{"g2", "v2", "k2", "k2s"}}, nil), ), }, { @@ -265,8 +322,7 @@ func TestNamespaceGenerationEvolver(t *testing.T) { }, }), gen: NewGenerationFromOperators( - NewFakeOperatorSurface("original", "o", "c", "", "s", - []opregistry.APIKey{{"g3", "v3", "k3", "k3s"}}, nil, nil, nil), + NewFakeOperatorSurface("original", "o", "c", "", "s", "", []opregistry.APIKey{{"g3", "v3", "k3", "k3s"}}, nil, nil, nil), ), }, args: args{ @@ -279,10 +335,10 @@ func TestNamespaceGenerationEvolver(t *testing.T) { }, }, wantGen: NewGenerationFromOperators( - NewFakeOperatorSurface("original", "o", "c", "", "s", []opregistry.APIKey{{"g3", "v3", "k3", "k3s"}}, nil, nil, nil), - NewFakeOperatorSurface("depender.v1", "depender", "channel", "", "catsrc", nil, []opregistry.APIKey{{"g", "v", "k", "ks"}}, nil, nil), - NewFakeOperatorSurface("provider.v1", "provider", "channel", "", "catsrc", []opregistry.APIKey{{"g", "v", "k", "ks"}}, []opregistry.APIKey{{"g2", "v2", "k2", "k2s"}}, nil, nil), - NewFakeOperatorSurface("provider2.v1", "provider2", "channel", "", "catsrc", []opregistry.APIKey{{"g2", "v2", "k2", "k2s"}}, []opregistry.APIKey{{"g3", "v3", "k3", "k3s"}}, nil, nil), + NewFakeOperatorSurface("original", "o", "c", "", "s", "", []opregistry.APIKey{{"g3", "v3", "k3", "k3s"}}, nil, nil, nil), + NewFakeOperatorSurface("depender.v1", "depender", "channel", "", "catsrc", "", nil, []opregistry.APIKey{{"g", "v", "k", "ks"}}, nil, nil), + NewFakeOperatorSurface("provider.v1", "provider", "channel", "", "catsrc", "", []opregistry.APIKey{{"g", "v", "k", "ks"}}, []opregistry.APIKey{{"g2", "v2", "k2", "k2s"}}, nil, nil), + NewFakeOperatorSurface("provider2.v1", "provider2", "channel", "", "catsrc", "", []opregistry.APIKey{{"g2", "v2", "k2", "k2s"}}, []opregistry.APIKey{{"g3", "v3", "k3", "k3s"}}, nil, nil), ), }, { @@ -299,7 +355,7 @@ func TestNamespaceGenerationEvolver(t *testing.T) { }, }), gen: NewGenerationFromOperators( - NewFakeOperatorSurface("original", "o", "c", "", "catsrc", nil, nil, nil, nil), + NewFakeOperatorSurface("original", "o", "c", "", "catsrc", "", nil, nil, nil, nil), ), }, args: args{ @@ -312,9 +368,9 @@ func TestNamespaceGenerationEvolver(t *testing.T) { }, }, wantGen: NewGenerationFromOperators( - NewFakeOperatorSurface("updated", "o", "c", "original", "catsrc", nil, nil, nil, nil), - NewFakeOperatorSurface("depender.v1", "depender", "channel", "", "catsrc", nil, []opregistry.APIKey{{"g", "v", "k", "ks"}}, nil, nil), - NewFakeOperatorSurface("provider.v1", "provider", "channel", "", "catsrc", []opregistry.APIKey{{"g", "v", "k", "ks"}}, nil, nil, nil), + NewFakeOperatorSurface("updated", "o", "c", "original", "catsrc", "", nil, nil, nil, nil), + NewFakeOperatorSurface("depender.v1", "depender", "channel", "", "catsrc", "", nil, []opregistry.APIKey{{"g", "v", "k", "ks"}}, nil, nil), + NewFakeOperatorSurface("provider.v1", "provider", "channel", "", "catsrc", "", []opregistry.APIKey{{"g", "v", "k", "ks"}}, nil, nil, nil), ), }, } diff --git a/pkg/controller/registry/resolver/fakes/fake_registry_client.go b/pkg/controller/registry/resolver/fakes/fake_registry_client.go index f9cd2b22080..44ad49eec03 100644 --- a/pkg/controller/registry/resolver/fakes/fake_registry_client.go +++ b/pkg/controller/registry/resolver/fakes/fake_registry_client.go @@ -10,6 +10,22 @@ import ( ) type FakeInterface struct { + GetBundleStub func(context.Context, string, string, string) (*registry.Bundle, error) + getBundleMutex sync.RWMutex + getBundleArgsForCall []struct { + arg1 context.Context + arg2 string + arg3 string + arg4 string + } + getBundleReturns struct { + result1 *registry.Bundle + result2 error + } + getBundleReturnsOnCall map[int]struct { + result1 *registry.Bundle + result2 error + } GetBundleInPackageChannelStub func(context.Context, string, string) (*registry.Bundle, error) getBundleInPackageChannelMutex sync.RWMutex getBundleInPackageChannelArgsForCall []struct { @@ -61,6 +77,72 @@ type FakeInterface struct { invocationsMutex sync.RWMutex } +func (fake *FakeInterface) GetBundle(arg1 context.Context, arg2 string, arg3 string, arg4 string) (*registry.Bundle, error) { + fake.getBundleMutex.Lock() + ret, specificReturn := fake.getBundleReturnsOnCall[len(fake.getBundleArgsForCall)] + fake.getBundleArgsForCall = append(fake.getBundleArgsForCall, struct { + arg1 context.Context + arg2 string + arg3 string + arg4 string + }{arg1, arg2, arg3, arg4}) + fake.recordInvocation("GetBundle", []interface{}{arg1, arg2, arg3, arg4}) + fake.getBundleMutex.Unlock() + if fake.GetBundleStub != nil { + return fake.GetBundleStub(arg1, arg2, arg3, arg4) + } + if specificReturn { + return ret.result1, ret.result2 + } + fakeReturns := fake.getBundleReturns + return fakeReturns.result1, fakeReturns.result2 +} + +func (fake *FakeInterface) GetBundleCallCount() int { + fake.getBundleMutex.RLock() + defer fake.getBundleMutex.RUnlock() + return len(fake.getBundleArgsForCall) +} + +func (fake *FakeInterface) GetBundleCalls(stub func(context.Context, string, string, string) (*registry.Bundle, error)) { + fake.getBundleMutex.Lock() + defer fake.getBundleMutex.Unlock() + fake.GetBundleStub = stub +} + +func (fake *FakeInterface) GetBundleArgsForCall(i int) (context.Context, string, string, string) { + fake.getBundleMutex.RLock() + defer fake.getBundleMutex.RUnlock() + argsForCall := fake.getBundleArgsForCall[i] + return argsForCall.arg1, argsForCall.arg2, argsForCall.arg3, argsForCall.arg4 +} + +func (fake *FakeInterface) GetBundleReturns(result1 *registry.Bundle, result2 error) { + fake.getBundleMutex.Lock() + defer fake.getBundleMutex.Unlock() + fake.GetBundleStub = nil + fake.getBundleReturns = struct { + result1 *registry.Bundle + result2 error + }{result1, result2} +} + +func (fake *FakeInterface) GetBundleReturnsOnCall(i int, result1 *registry.Bundle, result2 error) { + fake.getBundleMutex.Lock() + defer fake.getBundleMutex.Unlock() + fake.GetBundleStub = nil + if fake.getBundleReturnsOnCall == nil { + fake.getBundleReturnsOnCall = make(map[int]struct { + result1 *registry.Bundle + result2 error + }) + } + fake.getBundleReturnsOnCall[i] = struct { + result1 *registry.Bundle + result2 error + }{result1, result2} +} + func (fake *FakeInterface) GetBundleInPackageChannel(arg1 context.Context, arg2 string, arg3 string) (*registry.Bundle, error) { fake.getBundleInPackageChannelMutex.Lock() ret, specificReturn := fake.getBundleInPackageChannelReturnsOnCall[len(fake.getBundleInPackageChannelArgsForCall)] @@ -261,6 +343,8 @@ func (fake *FakeInterface) GetReplacementBundleInPackageChannelReturnsOnCall(i i func (fake *FakeInterface) Invocations() map[string][][]interface{} { fake.invocationsMutex.RLock() defer fake.invocationsMutex.RUnlock() + fake.getBundleMutex.RLock() + defer fake.getBundleMutex.RUnlock() fake.getBundleInPackageChannelMutex.RLock() defer fake.getBundleInPackageChannelMutex.RUnlock() fake.getBundleThatProvidesMutex.RLock() diff --git a/pkg/controller/registry/resolver/generation.go b/pkg/controller/registry/resolver/generation.go index 9a8ceb94a57..97d8ad2eacc 100644 --- a/pkg/controller/registry/resolver/generation.go +++ b/pkg/controller/registry/resolver/generation.go @@ -44,7 +44,7 @@ func NewGenerationFromCluster(csvs []*v1alpha1.ClusterServiceVersion, subs []*v1 subMap := map[string]*v1alpha1.Subscription{} for _, s := range subs { if s.Status.CurrentCSV != "" { - subMap[s.Status.CurrentCSV] = s + subMap[s.Status.CurrentCSV] = s.DeepCopy() } } for _, csv := range csvs { @@ -52,8 +52,9 @@ func NewGenerationFromCluster(csvs []*v1alpha1.ClusterServiceVersion, subs []*v1 if err != nil { return nil, err } - // if there's a subscription for this CSV, we add the sourceinfo for the subscription + // If there's a subscription for this CSV, we add the sourceinfo for the subscription if sub, ok := subMap[op.Identifier()]; ok { + // No need to enable starting csv search since a csv already exists. op.sourceInfo = &OperatorSourceInfo{ Package: sub.Spec.Package, Channel: sub.Spec.Channel, diff --git a/pkg/controller/registry/resolver/generation_test.go b/pkg/controller/registry/resolver/generation_test.go index aa4fd421c3a..f412d577d40 100644 --- a/pkg/controller/registry/resolver/generation_test.go +++ b/pkg/controller/registry/resolver/generation_test.go @@ -7,7 +7,6 @@ import ( opregistry "github.com/operator-framework/operator-registry/pkg/registry" "github.com/stretchr/testify/require" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" - "github.com/operator-framework/operator-registry/pkg/registry" "github.com/operator-framework/operator-lifecycle-manager/pkg/api/apis/operators/v1alpha1" diff --git a/pkg/controller/registry/resolver/operators.go b/pkg/controller/registry/resolver/operators.go index 1a46b3200c3..061386bb099 100644 --- a/pkg/controller/registry/resolver/operators.go +++ b/pkg/controller/registry/resolver/operators.go @@ -82,16 +82,17 @@ func (s APIMultiOwnerSet) PopAPIRequirers() OperatorSet { } type OperatorSourceInfo struct { - Package string - Channel string - Catalog CatalogKey + Package string + Channel string + StartingCSV string + Catalog CatalogKey } func (i *OperatorSourceInfo) String() string { return fmt.Sprintf("%s/%s in %s/%s", i.Package, i.Channel, i.Catalog.Name, i.Catalog.Namespace) } -var ExistingOperator = OperatorSourceInfo{"", "", CatalogKey{"", ""}} +var ExistingOperator = OperatorSourceInfo{"", "", "", CatalogKey{"", ""}} // OperatorSurface describes the API surfaces provided and required by an Operator. type OperatorSurface interface { @@ -114,7 +115,7 @@ type Operator struct { var _ OperatorSurface = &Operator{} -func NewOperatorFromBundle(bundle *opregistry.Bundle, sourceKey CatalogKey) (*Operator, error) { +func NewOperatorFromBundle(bundle *opregistry.Bundle, startingCSV string, sourceKey CatalogKey) (*Operator, error) { csv, err := bundle.ClusterServiceVersion() if err != nil { return nil, err @@ -134,9 +135,10 @@ func NewOperatorFromBundle(bundle *opregistry.Bundle, sourceKey CatalogKey) (*Op requiredAPIs: requiredAPIs, bundle: bundle, sourceInfo: &OperatorSourceInfo{ - Package: bundle.Package, - Channel: bundle.Channel, - Catalog: sourceKey, + Package: bundle.Package, + Channel: bundle.Channel, + StartingCSV: startingCSV, + Catalog: sourceKey, }, }, nil } diff --git a/pkg/controller/registry/resolver/operators_test.go b/pkg/controller/registry/resolver/operators_test.go index 6aa005d29fb..1ae4cfb7872 100644 --- a/pkg/controller/registry/resolver/operators_test.go +++ b/pkg/controller/registry/resolver/operators_test.go @@ -372,7 +372,7 @@ func TestNewOperatorFromBundle(t *testing.T) { } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { - got, err := NewOperatorFromBundle(tt.args.bundle, tt.args.sourceKey) + got, err := NewOperatorFromBundle(tt.args.bundle, "", tt.args.sourceKey) require.Equal(t, tt.wantErr, err) require.Equal(t, tt.want, got) }) diff --git a/pkg/controller/registry/resolver/querier.go b/pkg/controller/registry/resolver/querier.go index 335b602fd0f..07cf9028c67 100644 --- a/pkg/controller/registry/resolver/querier.go +++ b/pkg/controller/registry/resolver/querier.go @@ -5,10 +5,9 @@ import ( "context" "fmt" - metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" - "github.com/operator-framework/operator-registry/pkg/client" opregistry "github.com/operator-framework/operator-registry/pkg/registry" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" ) type SourceRef struct { @@ -20,7 +19,7 @@ type SourceRef struct { type SourceQuerier interface { FindProvider(api opregistry.APIKey) (*opregistry.Bundle, *CatalogKey, error) - FindPackage(pkgName, channelName string, initialSource CatalogKey) (*opregistry.Bundle, *CatalogKey, error) + FindPackage(pkgName, channelName, csvName string, initialSource CatalogKey) (*opregistry.Bundle, *CatalogKey, error) FindReplacement(bundleName, pkgName, channelName string, initialSource CatalogKey) (*opregistry.Bundle, *CatalogKey, error) Queryable() error } @@ -56,13 +55,21 @@ func (q *NamespaceSourceQuerier) FindProvider(api opregistry.APIKey) (*opregistr return nil, nil, fmt.Errorf("%s not provided by a package in any CatalogSource", api) } -func (q *NamespaceSourceQuerier) FindPackage(pkgName, channelName string, initialSource CatalogKey) (*opregistry.Bundle, *CatalogKey, error) { +func (q *NamespaceSourceQuerier) FindPackage(pkgName, channelName, csvName string, initialSource CatalogKey) (*opregistry.Bundle, *CatalogKey, error) { if initialSource.Name != "" && initialSource.Namespace != "" { source, ok := q.sources[initialSource] if !ok { return nil, nil, fmt.Errorf("CatalogSource %s not found", initialSource) } - bundle, err := source.GetBundleInPackageChannel(context.TODO(), pkgName, channelName) + + var bundle *opregistry.Bundle + var err error + if csvName != "" { + bundle, err = source.GetBundle(context.TODO(), pkgName, channelName, csvName) + } else { + bundle, err = source.GetBundleInPackageChannel(context.TODO(), pkgName, channelName) + } + if err != nil { return nil, nil, err } @@ -70,7 +77,13 @@ func (q *NamespaceSourceQuerier) FindPackage(pkgName, channelName string, initia } for key, source := range q.sources { - bundle, err := source.GetBundleInPackageChannel(context.TODO(), pkgName, channelName) + var bundle *opregistry.Bundle + var err error + if csvName != "" { + bundle, err = source.GetBundle(context.TODO(), pkgName, channelName, csvName) + } else { + bundle, err = source.GetBundleInPackageChannel(context.TODO(), pkgName, channelName) + } if err == nil { return bundle, &key, nil } diff --git a/pkg/controller/registry/resolver/querier_test.go b/pkg/controller/registry/resolver/querier_test.go index f264d0e617a..1450727266b 100644 --- a/pkg/controller/registry/resolver/querier_test.go +++ b/pkg/controller/registry/resolver/querier_test.go @@ -170,7 +170,14 @@ func TestNamespaceSourceQuerier_FindPackage(t *testing.T) { initialSource := fakes.FakeInterface{} otherSource := fakes.FakeInterface{} initalBundle := opregistry.NewBundle("test", "testPkg", "testChannel") + startingBundle := opregistry.NewBundle("starting-test", "testPkg", "testChannel") otherBundle := opregistry.NewBundle("other", "otherPkg", "otherChannel") + initialSource.GetBundleStub = func(ctx context.Context, pkgName, channelName, csvName string) (*opregistry.Bundle, error) { + if csvName != startingBundle.Name { + return nil, fmt.Errorf("not found") + } + return startingBundle, nil + } initialSource.GetBundleInPackageChannelStub = func(ctx context.Context, pkgName, channelName string) (*opregistry.Bundle, error) { if pkgName != initalBundle.Name { return nil, fmt.Errorf("not found") @@ -196,6 +203,7 @@ func TestNamespaceSourceQuerier_FindPackage(t *testing.T) { type args struct { pkgName string channelName string + startingCSV string initialSource CatalogKey } type out struct { @@ -210,27 +218,39 @@ func TestNamespaceSourceQuerier_FindPackage(t *testing.T) { out out }{ { - name: "inInitial", + name: "Initial/Found", fields: fields{sources: sources}, - args: args{"test", "testChannel", CatalogKey{"initial", "ns"}}, + args: args{"test", "testChannel", "", CatalogKey{"initial", "ns"}}, out: out{bundle: initalBundle, key: &initialKey, err: nil}, }, { - name: "inInitial", + name: "Initial/CatalogNotFound", fields: fields{sources: sources}, - args: args{"test", "testChannel", CatalogKey{"absent", "found"}}, + args: args{"test", "testChannel", "", CatalogKey{"absent", "found"}}, out: out{bundle: nil, key: nil, err: fmt.Errorf("CatalogSource {absent found} not found")}, }, { - name: "inOther", + name: "Initial/StartingCSVFound", + fields: fields{sources: sources}, + args: args{"test", "testChannel", "starting-test", CatalogKey{"initial", "ns"}}, + out: out{bundle: startingBundle, key: &initialKey, err: nil}, + }, + { + name: "Initial/StartingCSVNotFound", + fields: fields{sources: sources}, + args: args{"test", "testChannel", "non-existent", CatalogKey{"initial", "ns"}}, + out: out{bundle: nil, key: nil, err: fmt.Errorf("not found")}, + }, + { + name: "Other/Found", fields: fields{sources: sources}, - args: args{"other", "testChannel", CatalogKey{"", ""}}, + args: args{"other", "testChannel", "", CatalogKey{"", ""}}, out: out{bundle: otherBundle, key: &otherKey, err: nil}, }, { - name: "inNone", + name: "NotFound", fields: fields{sources: sources}, - args: args{"nope", "not", CatalogKey{"", ""}}, + args: args{"nope", "not", "", CatalogKey{"", ""}}, out: out{bundle: nil, err: fmt.Errorf("nope/not not found in any available CatalogSource")}, }, } @@ -239,7 +259,7 @@ func TestNamespaceSourceQuerier_FindPackage(t *testing.T) { q := &NamespaceSourceQuerier{ sources: tt.fields.sources, } - got, key, err := q.FindPackage(tt.args.pkgName, tt.args.channelName, tt.args.initialSource) + got, key, err := q.FindPackage(tt.args.pkgName, tt.args.channelName, tt.args.startingCSV, tt.args.initialSource) require.Equal(t, tt.out.bundle, got) require.Equal(t, tt.out.err, err) require.Equal(t, tt.out.key, key) diff --git a/pkg/controller/registry/resolver/resolver.go b/pkg/controller/registry/resolver/resolver.go index ab08ee477ec..7d1ac9a9eeb 100644 --- a/pkg/controller/registry/resolver/resolver.go +++ b/pkg/controller/registry/resolver/resolver.go @@ -40,7 +40,7 @@ func (r *OperatorsV1alpha1Resolver) ResolveSteps(namespace string, sourceQuerier return nil, nil, err } - // create a generation - an representation of the current set of installed operators and their provided/required apis + // create a generation - a representation of the current set of installed operators and their provided/required apis csvs, err := r.csvLister.ClusterServiceVersions(namespace).List(labels.Everything()) if err != nil { return nil, nil, err @@ -68,7 +68,6 @@ func (r *OperatorsV1alpha1Resolver) ResolveSteps(namespace string, sourceQuerier // if there's no error, we were able to satsify all constraints in the subscription set, so we calculate what // changes to persist to the cluster and write them out as `steps` - steps := []*v1alpha1.Step{} updatedSubs := []*v1alpha1.Subscription{} for name, op := range gen.Operators() { @@ -112,7 +111,6 @@ func (r *OperatorsV1alpha1Resolver) ResolveSteps(namespace string, sourceQuerier if subExists && existingSubscription.Status.CurrentCSV != op.Identifier() { existingSubscription.Status.CurrentCSV = op.Identifier() updatedSubs = append(updatedSubs, existingSubscription) - continue } } @@ -129,7 +127,6 @@ func (r *OperatorsV1alpha1Resolver) sourceInfoForNewSubscriptions(namespace stri csv, err := r.csvLister.ClusterServiceVersions(namespace).Get(sub.Status.CurrentCSV) if csv == nil || errors.IsNotFound(err) { add[key] = struct{}{} - continue } } return @@ -138,9 +135,16 @@ func (r *OperatorsV1alpha1Resolver) sourceInfoForNewSubscriptions(namespace stri func (r *OperatorsV1alpha1Resolver) sourceInfoToSubscriptions(subs []*v1alpha1.Subscription) (add map[OperatorSourceInfo]*v1alpha1.Subscription) { add = make(map[OperatorSourceInfo]*v1alpha1.Subscription) for _, s := range subs { + startingCSV := s.Spec.StartingCSV + if s.Status.CurrentCSV != "" { + // If a csv has previously been resolved for the operator, don't enable + // a starting csv search. + startingCSV = "" + } add[OperatorSourceInfo{ Package: s.Spec.Package, Channel: s.Spec.Channel, + StartingCSV: startingCSV, Catalog: CatalogKey{Name: s.Spec.CatalogSource, Namespace: s.Spec.CatalogSourceNamespace}, }] = s.DeepCopy() } diff --git a/pkg/controller/registry/resolver/util_test.go b/pkg/controller/registry/resolver/util_test.go index 8ee90dbc515..031d488a97f 100644 --- a/pkg/controller/registry/resolver/util_test.go +++ b/pkg/controller/registry/resolver/util_test.go @@ -44,7 +44,7 @@ func NewGenerationFromOperators(ops ...OperatorSurface) *NamespaceGeneration { return g } -func NewFakeOperatorSurface(name, pkg, channel, replaces, src string, providedCRDs, requiredCRDs, providedAPIServices, requiredAPIServices []opregistry.APIKey) *Operator { +func NewFakeOperatorSurface(name, pkg, channel, replaces, src, startingCSV string, providedCRDs, requiredCRDs, providedAPIServices, requiredAPIServices []opregistry.APIKey) *Operator { providedAPISet := EmptyAPISet() requiredAPISet := EmptyAPISet() providedCRDAPISet := EmptyAPISet() @@ -80,6 +80,7 @@ func NewFakeOperatorSurface(name, pkg, channel, replaces, src string, providedCR sourceInfo: &OperatorSourceInfo{ Package: pkg, Channel: channel, + StartingCSV: startingCSV, Catalog: CatalogKey{src, src + "-namespace"}, }, bundle: b, @@ -317,6 +318,15 @@ func NewFakeSourceQuerier(bundlesByCatalog map[CatalogKey][]*opregistry.Bundle) return nil, fmt.Errorf("no bundle found") } + source.GetBundleStub = func(ctx context.Context, packageName, channelName, csvName string) (*opregistry.Bundle, error) { + for _, b := range bundles { + if b.Channel == channelName && b.Package == packageName && b.Name == csvName { + return b, nil + } + } + return nil, fmt.Errorf("no bundle found") + } + source.GetReplacementBundleInPackageChannelStub = func(ctx context.Context, bundleName, packageName, channelName string) (*opregistry.Bundle, error) { for _, b := range bundles { csv, err := b.ClusterServiceVersion() diff --git a/pkg/package-server/client/fakes/fake_registry_client.go b/pkg/package-server/client/fakes/fake_registry_client.go index 8b1c33cff08..0e17307d0d5 100644 --- a/pkg/package-server/client/fakes/fake_registry_client.go +++ b/pkg/package-server/client/fakes/fake_registry_client.go @@ -10,6 +10,21 @@ import ( ) type FakeRegistryClient struct { + GetBundleStub func(context.Context, *api.GetBundleRequest, ...grpc.CallOption) (*api.Bundle, error) + getBundleMutex sync.RWMutex + getBundleArgsForCall []struct { + arg1 context.Context + arg2 *api.GetBundleRequest + arg3 []grpc.CallOption + } + getBundleReturns struct { + result1 *api.Bundle + result2 error + } + getBundleReturnsOnCall map[int]struct { + result1 *api.Bundle + result2 error + } GetBundleForChannelStub func(context.Context, *api.GetBundleInChannelRequest, ...grpc.CallOption) (*api.Bundle, error) getBundleForChannelMutex sync.RWMutex getBundleForChannelArgsForCall []struct { @@ -134,6 +149,71 @@ type FakeRegistryClient struct { invocationsMutex sync.RWMutex } +func (fake *FakeRegistryClient) GetBundle(arg1 context.Context, arg2 *api.GetBundleRequest, arg3 ...grpc.CallOption) (*api.Bundle, error) { + fake.getBundleMutex.Lock() + ret, specificReturn := fake.getBundleReturnsOnCall[len(fake.getBundleArgsForCall)] + fake.getBundleArgsForCall = append(fake.getBundleArgsForCall, struct { + arg1 context.Context + arg2 *api.GetBundleRequest + arg3 []grpc.CallOption + }{arg1, arg2, arg3}) + fake.recordInvocation("GetBundle", []interface{}{arg1, arg2, arg3}) + fake.getBundleMutex.Unlock() + if fake.GetBundleStub != nil { + return fake.GetBundleStub(arg1, arg2, arg3...) + } + if specificReturn { + return ret.result1, ret.result2 + } + fakeReturns := fake.getBundleReturns + return fakeReturns.result1, fakeReturns.result2 +} + +func (fake *FakeRegistryClient) GetBundleCallCount() int { + fake.getBundleMutex.RLock() + defer fake.getBundleMutex.RUnlock() + return len(fake.getBundleArgsForCall) +} + +func (fake *FakeRegistryClient) GetBundleCalls(stub func(context.Context, *api.GetBundleRequest, ...grpc.CallOption) (*api.Bundle, error)) { + fake.getBundleMutex.Lock() + defer fake.getBundleMutex.Unlock() + fake.GetBundleStub = stub +} + +func (fake *FakeRegistryClient) GetBundleArgsForCall(i int) (context.Context, *api.GetBundleRequest, []grpc.CallOption) { + fake.getBundleMutex.RLock() + defer fake.getBundleMutex.RUnlock() + argsForCall := fake.getBundleArgsForCall[i] + return argsForCall.arg1, argsForCall.arg2, argsForCall.arg3 +} + +func (fake *FakeRegistryClient) GetBundleReturns(result1 *api.Bundle, result2 error) { + fake.getBundleMutex.Lock() + defer fake.getBundleMutex.Unlock() + fake.GetBundleStub = nil + fake.getBundleReturns = struct { + result1 *api.Bundle + result2 error + }{result1, result2} +} + +func (fake *FakeRegistryClient) GetBundleReturnsOnCall(i int, result1 *api.Bundle, result2 error) { + fake.getBundleMutex.Lock() + defer fake.getBundleMutex.Unlock() + fake.GetBundleStub = nil + if fake.getBundleReturnsOnCall == nil { + fake.getBundleReturnsOnCall = make(map[int]struct { + result1 *api.Bundle + result2 error + }) + } + fake.getBundleReturnsOnCall[i] = struct { + result1 *api.Bundle + result2 error + }{result1, result2} +} + func (fake *FakeRegistryClient) GetBundleForChannel(arg1 context.Context, arg2 *api.GetBundleInChannelRequest, arg3 ...grpc.CallOption) (*api.Bundle, error) { fake.getBundleForChannelMutex.Lock() ret, specificReturn := fake.getBundleForChannelReturnsOnCall[len(fake.getBundleForChannelArgsForCall)] @@ -657,6 +737,8 @@ func (fake *FakeRegistryClient) ListPackagesReturnsOnCall(i int, result1 api.Reg func (fake *FakeRegistryClient) Invocations() map[string][][]interface{} { fake.invocationsMutex.RLock() defer fake.invocationsMutex.RUnlock() + fake.getBundleMutex.RLock() + defer fake.getBundleMutex.RUnlock() fake.getBundleForChannelMutex.RLock() defer fake.getBundleForChannelMutex.RUnlock() fake.getBundleThatReplacesMutex.RLock() diff --git a/pkg/package-server/provider/registry_test.go b/pkg/package-server/provider/registry_test.go index 1ec7ce284ad..040928cb07a 100644 --- a/pkg/package-server/provider/registry_test.go +++ b/pkg/package-server/provider/registry_test.go @@ -1,3 +1,4 @@ +//go:generate counterfeiter -o ../client/fakes/fake_registry_client.go ../../../vendor/github.com/operator-framework/operator-registry/pkg/api/registry.pb.go RegistryClient package provider import ( diff --git a/test/e2e/catalog_e2e_test.go b/test/e2e/catalog_e2e_test.go index ebf3e8201e1..6d35b49d1c1 100644 --- a/test/e2e/catalog_e2e_test.go +++ b/test/e2e/catalog_e2e_test.go @@ -214,7 +214,7 @@ func TestConfigMapUpdateTriggersRegistryPodRollout(t *testing.T) { // Create Subscription subscriptionName := genName("sub-") - createSubscriptionForCatalog(t, crc, testNamespace, subscriptionName, fetchedUpdatedCatalog.GetName(), mainPackageName, stableChannel, v1alpha1.ApprovalAutomatic) + createSubscriptionForCatalog(t, crc, testNamespace, subscriptionName, fetchedUpdatedCatalog.GetName(), mainPackageName, stableChannel, "", v1alpha1.ApprovalAutomatic) subscription, err := fetchSubscription(t, crc, testNamespace, subscriptionName, subscriptionStateAtLatestChecker) require.NoError(t, err) @@ -302,7 +302,7 @@ func TestConfigMapReplaceTriggersRegistryPodRollout(t *testing.T) { // Create Subscription subscriptionName := genName("sub-") - createSubscriptionForCatalog(t, crc, testNamespace, subscriptionName, mainCatalogName, mainPackageName, stableChannel, v1alpha1.ApprovalAutomatic) + createSubscriptionForCatalog(t, crc, testNamespace, subscriptionName, mainCatalogName, mainPackageName, stableChannel, "", v1alpha1.ApprovalAutomatic) subscription, err := fetchSubscription(t, crc, testNamespace, subscriptionName, subscriptionStateAtLatestChecker) require.NoError(t, err) diff --git a/test/e2e/csv_e2e_test.go b/test/e2e/csv_e2e_test.go index 908192ab99d..fb06571250e 100644 --- a/test/e2e/csv_e2e_test.go +++ b/test/e2e/csv_e2e_test.go @@ -221,6 +221,28 @@ func fetchCSV(t *testing.T, c versioned.Interface, name, namespace string, check return fetched, err } +func awaitCSV(t *testing.T, c versioned.Interface, namespace, name string, checker csvConditionChecker) (*v1alpha1.ClusterServiceVersion, error) { + var fetched *v1alpha1.ClusterServiceVersion + var err error + + err = wait.Poll(pollInterval, pollDuration, func() (bool, error) { + fetched, err = c.OperatorsV1alpha1().ClusterServiceVersions(namespace).Get(name, metav1.GetOptions{}) + if err != nil { + if k8serrors.IsNotFound(err) { + return false, nil + } + return false, err + } + t.Logf("%s (%s): %s", fetched.Status.Phase, fetched.Status.Reason, fetched.Status.Message) + return checker(fetched), nil + }) + + if err != nil { + t.Logf("never got correct status: %#v", fetched.Status) + } + return fetched, err +} + func waitForDeploymentToDelete(t *testing.T, c operatorclient.ClientInterface, name string) error { return wait.Poll(pollInterval, pollDuration, func() (bool, error) { t.Logf("waiting for deployment %s to delete", name) diff --git a/test/e2e/installplan_e2e_test.go b/test/e2e/installplan_e2e_test.go index 42a81c5a578..add9b2c856f 100644 --- a/test/e2e/installplan_e2e_test.go +++ b/test/e2e/installplan_e2e_test.go @@ -274,7 +274,7 @@ func TestInstallPlanWithCSVsAcrossMultipleCatalogSources(t *testing.T) { } subscriptionName := genName("sub-nginx-") - subscriptionCleanup := createSubscriptionForCatalog(t, crc, testNamespace, subscriptionName, mainCatalogName, mainPackageName, stableChannel, v1alpha1.ApprovalAutomatic) + subscriptionCleanup := createSubscriptionForCatalog(t, crc, testNamespace, subscriptionName, mainCatalogName, mainPackageName, stableChannel, "", v1alpha1.ApprovalAutomatic) defer subscriptionCleanup() subscription, err := fetchSubscription(t, crc, testNamespace, subscriptionName, subscriptionHasInstallPlanChecker) @@ -408,7 +408,7 @@ func TestCreateInstallPlanWithPreExistingCRDOwners(t *testing.T) { t.Log("Dependent CRD and preexisting CSV created") subscriptionName := genName("sub-nginx-") - subscriptionCleanup := createSubscriptionForCatalog(t, crc, testNamespace, subscriptionName, mainCatalogSourceName, mainPackageName, stableChannel, v1alpha1.ApprovalAutomatic) + subscriptionCleanup := createSubscriptionForCatalog(t, crc, testNamespace, subscriptionName, mainCatalogSourceName, mainPackageName, stableChannel, "", v1alpha1.ApprovalAutomatic) defer subscriptionCleanup() subscription, err := fetchSubscription(t, crc, testNamespace, subscriptionName, subscriptionHasInstallPlanChecker) @@ -518,7 +518,7 @@ func TestCreateInstallPlanWithPreExistingCRDOwners(t *testing.T) { require.NoError(t, err) subscriptionName := genName("sub-nginx-") - subscriptionCleanup := createSubscriptionForCatalog(t, crc, testNamespace, subscriptionName, mainCatalogSourceName, mainPackageName, stableChannel, v1alpha1.ApprovalAutomatic) + subscriptionCleanup := createSubscriptionForCatalog(t, crc, testNamespace, subscriptionName, mainCatalogSourceName, mainPackageName, stableChannel, "", v1alpha1.ApprovalAutomatic) defer subscriptionCleanup() subscription, err := fetchSubscription(t, crc, testNamespace, subscriptionName, subscriptionHasInstallPlanChecker) @@ -565,7 +565,7 @@ func TestCreateInstallPlanWithPreExistingCRDOwners(t *testing.T) { require.NoError(t, err) // existing cleanup should remove this - createSubscriptionForCatalog(t, crc, testNamespace, subscriptionName, mainCatalogSourceName, mainPackageName, betaChannel, v1alpha1.ApprovalAutomatic) + createSubscriptionForCatalog(t, crc, testNamespace, subscriptionName, mainCatalogSourceName, mainPackageName, betaChannel, "", v1alpha1.ApprovalAutomatic) subscription, err = fetchSubscription(t, crc, testNamespace, subscriptionName, subscriptionHasInstallPlanChecker) require.NoError(t, err) @@ -671,7 +671,7 @@ func TestCreateInstallPlanWithPermissions(t *testing.T) { require.NoError(t, err) subscriptionName := genName("sub-nginx-") - subscriptionCleanup := createSubscriptionForCatalog(t, crc, testNamespace, subscriptionName, mainCatalogSourceName, packageName, stableChannel, v1alpha1.ApprovalAutomatic) + subscriptionCleanup := createSubscriptionForCatalog(t, crc, testNamespace, subscriptionName, mainCatalogSourceName, packageName, stableChannel, "", v1alpha1.ApprovalAutomatic) defer subscriptionCleanup() subscription, err := fetchSubscription(t, crc, testNamespace, subscriptionName, subscriptionHasInstallPlanChecker) @@ -795,7 +795,7 @@ func TestInstallPlanCRDValidation(t *testing.T) { require.NoError(t, err) subscriptionName := genName("sub-nginx-") - cleanupSubscription := createSubscriptionForCatalog(t, crc, testNamespace, subscriptionName, catalogSourceName, packageName, stableChannel, v1alpha1.ApprovalAutomatic) + cleanupSubscription := createSubscriptionForCatalog(t, crc, testNamespace, subscriptionName, catalogSourceName, packageName, stableChannel, "", v1alpha1.ApprovalAutomatic) defer cleanupSubscription() subscription, err := fetchSubscription(t, crc, testNamespace, subscriptionName, subscriptionHasInstallPlanChecker) @@ -810,5 +810,4 @@ func TestInstallPlanCRDValidation(t *testing.T) { t.Logf("Install plan %s fetched with status %s", fetchedInstallPlan.GetName(), fetchedInstallPlan.Status.Phase) require.Equal(t, v1alpha1.InstallPlanPhaseComplete, fetchedInstallPlan.Status.Phase) - } diff --git a/test/e2e/subscription_e2e_test.go b/test/e2e/subscription_e2e_test.go index eb8f18f8717..ff82ff6e7cd 100644 --- a/test/e2e/subscription_e2e_test.go +++ b/test/e2e/subscription_e2e_test.go @@ -3,7 +3,7 @@ package e2e import ( "encoding/json" "testing" - + "github.com/coreos/go-semver/semver" "github.com/ghodss/yaml" "github.com/stretchr/testify/require" @@ -12,9 +12,9 @@ import ( k8serrors "k8s.io/apimachinery/pkg/api/errors" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/util/wait" + "k8s.io/apiextensions-apiserver/pkg/apis/apiextensions" "github.com/operator-framework/operator-lifecycle-manager/pkg/api/client/clientset/versioned" - "github.com/operator-framework/operator-lifecycle-manager/pkg/api/apis/operators/v1alpha1" "github.com/operator-framework/operator-lifecycle-manager/pkg/controller/install" "github.com/operator-framework/operator-lifecycle-manager/pkg/controller/registry" @@ -369,7 +369,7 @@ func createSubscription(t *testing.T, crc versioned.Interface, namespace, name, return buildSubscriptionCleanupFunc(t, crc, subscription) } -func createSubscriptionForCatalog(t *testing.T, crc versioned.Interface, namespace, name, catalog, packageName, channel string, approval v1alpha1.Approval) cleanupFunc { +func createSubscriptionForCatalog(t *testing.T, crc versioned.Interface, namespace, name, catalog, packageName, channel, startingCSV string, approval v1alpha1.Approval) cleanupFunc { subscription := &v1alpha1.Subscription{ TypeMeta: metav1.TypeMeta{ Kind: v1alpha1.SubscriptionKind, @@ -384,6 +384,7 @@ func createSubscriptionForCatalog(t *testing.T, crc versioned.Interface, namespa CatalogSourceNamespace: testNamespace, Package: packageName, Channel: channel, + StartingCSV: startingCSV, InstallPlanApproval: approval, }, } @@ -489,3 +490,118 @@ func TestCreateNewSubscriptionManualApproval(t *testing.T) { _, err = fetchCSV(t, crc, subscription.Status.CurrentCSV, testNamespace, buildCSVConditionChecker(v1alpha1.CSVPhaseSucceeded)) require.NoError(t, err) } + +func TestSusbcriptionWithStartingCSV(t *testing.T) { + defer cleaner.NotifyTestComplete(t, true) + + crdPlural := genName("ins") + crdName := crdPlural + ".cluster.com" + + crd := apiextensions.CustomResourceDefinition{ + ObjectMeta: metav1.ObjectMeta{ + Name: crdName, + }, + Spec: apiextensions.CustomResourceDefinitionSpec{ + Group: "cluster.com", + Version: "v1alpha1", + Names: apiextensions.CustomResourceDefinitionNames{ + Plural: crdPlural, + Singular: crdPlural, + Kind: crdPlural, + ListKind: "list" + crdPlural, + }, + Scope: "Namespaced", + }, + } + + // Create CSV + packageName := genName("nginx-") + stableChannel := "stable" + + namedStrategy := newNginxInstallStrategy(genName("dep-"), nil, nil) + csvA := newCSV("nginx-a", testNamespace, "", *semver.New("0.1.0"), []apiextensions.CustomResourceDefinition{crd}, nil, namedStrategy) + csvB := newCSV("nginx-b", testNamespace, "nginx-a", *semver.New("0.2.0"), []apiextensions.CustomResourceDefinition{crd}, nil, namedStrategy) + + // Create PackageManifests + manifests := []registry.PackageManifest{ + { + PackageName: packageName, + Channels: []registry.PackageChannel{ + {Name: stableChannel, CurrentCSVName: csvB.GetName()}, + }, + DefaultChannelName: stableChannel, + }, + } + + // Create the CatalogSource + c := newKubeClient(t) + crc := newCRClient(t) + catalogSourceName := genName("mock-nginx-") + _, cleanupCatalogSource := createInternalCatalogSource(t, c, crc, catalogSourceName, testNamespace, manifests, []apiextensions.CustomResourceDefinition{crd}, []v1alpha1.ClusterServiceVersion{csvA, csvB}) + defer cleanupCatalogSource() + + // Attempt to get the catalog source before creating install plan + _, err := fetchCatalogSource(t, crc, catalogSourceName, testNamespace, catalogSourceRegistryPodSynced) + require.NoError(t, err) + + subscriptionName := genName("sub-nginx-") + cleanupSubscription := createSubscriptionForCatalog(t, crc, testNamespace, subscriptionName, catalogSourceName, packageName, stableChannel, csvA.GetName(), v1alpha1.ApprovalManual) + defer cleanupSubscription() + + subscription, err := fetchSubscription(t, crc, testNamespace, subscriptionName, subscriptionHasInstallPlanChecker) + require.NoError(t, err) + require.NotNil(t, subscription) + + installPlanName := subscription.Status.Install.Name + + // Wait for InstallPlan to be status: Complete before checking resource presence + requiresApprovalChecker := buildInstallPlanPhaseCheckFunc(v1alpha1.InstallPlanPhaseRequiresApproval) + fetchedInstallPlan, err := fetchInstallPlan(t, crc, installPlanName, requiresApprovalChecker) + require.NoError(t, err) + + // Ensure that csvA and its crd are found in the plan + csvFound := false + crdFound := false + for _, s := range fetchedInstallPlan.Status.Plan { + require.Equal(t, csvA.GetName(), s.Resolving, "unexpected resolution found") + require.Equal(t, v1alpha1.StepStatusUnknown, s.Status, "status should be unknown") + require.Equal(t, catalogSourceName, s.Resource.CatalogSource, "incorrect catalogsource on step resource") + switch kind := s.Resource.Kind; kind { + case v1alpha1.ClusterServiceVersionKind: + require.Equal(t, csvA.GetName(), s.Resource.Name, "unexpected csv found") + csvFound = true + case "CustomResourceDefinition": + require.Equal(t, crdName, s.Resource.Name, "unexpected crd found") + crdFound = true + default: + t.Fatalf("unexpected resource kind found in installplan: %s", kind) + } + } + require.True(t, csvFound, "expected csv not found in installplan") + require.True(t, crdFound, "expected crd not found in installplan") + + // Approve the installplan and wait for csvA to be installed + fetchedInstallPlan.Spec.Approved = true + _, err = crc.OperatorsV1alpha1().InstallPlans(testNamespace).Update(fetchedInstallPlan) + require.NoError(t, err) + + _, err = awaitCSV(t, crc, testNamespace, csvA.GetName(), csvSucceededChecker) + require.NoError(t, err) + + // Wait for the subscription to begin upgrading to csvB + subscription, err = fetchSubscription(t, crc, testNamespace, subscriptionName, subscriptionStateUpgradePendingChecker) + require.NoError(t, err) + require.NotEqual(t, fetchedInstallPlan.GetName(), subscription.Status.Install.Name, "expected new installplan for upgraded csv") + + upgradeInstallPlan, err := fetchInstallPlan(t, crc, subscription.Status.Install.Name, requiresApprovalChecker) + require.NoError(t, err) + + // Approve the upgrade installplan and wait for + upgradeInstallPlan.Spec.Approved = true + _, err = crc.OperatorsV1alpha1().InstallPlans(testNamespace).Update(upgradeInstallPlan) + require.NoError(t, err) + + _, err = awaitCSV(t, crc, testNamespace, csvB.GetName(), csvSucceededChecker) + require.NoError(t, err) +} + diff --git a/test/e2e/util_test.go b/test/e2e/util_test.go index 3047c3cc91c..4cfcb9c4314 100644 --- a/test/e2e/util_test.go +++ b/test/e2e/util_test.go @@ -7,6 +7,7 @@ import ( "strings" "testing" "time" + "encoding/json" "github.com/ghodss/yaml" "github.com/operator-framework/operator-registry/pkg/api/grpc_health_v1" @@ -373,3 +374,11 @@ func serializeCRD(t *testing.T, crd apiextensions.CustomResourceDefinition) stri require.NoError(t, err) return manifest.String() } + +func serializeObject(obj interface{}) string { + bytes, err := json.Marshal(obj) + if err != nil { + return "" + } + return string(bytes) +} diff --git a/vendor/github.com/operator-framework/operator-registry/pkg/api/registry.pb.go b/vendor/github.com/operator-framework/operator-registry/pkg/api/registry.pb.go index e98927f25b7..9209b8cca5c 100644 --- a/vendor/github.com/operator-framework/operator-registry/pkg/api/registry.pb.go +++ b/vendor/github.com/operator-framework/operator-registry/pkg/api/registry.pb.go @@ -35,7 +35,7 @@ func (m *Channel) Reset() { *m = Channel{} } func (m *Channel) String() string { return proto.CompactTextString(m) } func (*Channel) ProtoMessage() {} func (*Channel) Descriptor() ([]byte, []int) { - return fileDescriptor_registry_02a3e470a3cc2f84, []int{0} + return fileDescriptor_registry_3b20cfe64d54b8f8, []int{0} } func (m *Channel) XXX_Unmarshal(b []byte) error { return xxx_messageInfo_Channel.Unmarshal(m, b) @@ -80,7 +80,7 @@ func (m *PackageName) Reset() { *m = PackageName{} } func (m *PackageName) String() string { return proto.CompactTextString(m) } func (*PackageName) ProtoMessage() {} func (*PackageName) Descriptor() ([]byte, []int) { - return fileDescriptor_registry_02a3e470a3cc2f84, []int{1} + return fileDescriptor_registry_3b20cfe64d54b8f8, []int{1} } func (m *PackageName) XXX_Unmarshal(b []byte) error { return xxx_messageInfo_PackageName.Unmarshal(m, b) @@ -120,7 +120,7 @@ func (m *Package) Reset() { *m = Package{} } func (m *Package) String() string { return proto.CompactTextString(m) } func (*Package) ProtoMessage() {} func (*Package) Descriptor() ([]byte, []int) { - return fileDescriptor_registry_02a3e470a3cc2f84, []int{2} + return fileDescriptor_registry_3b20cfe64d54b8f8, []int{2} } func (m *Package) XXX_Unmarshal(b []byte) error { return xxx_messageInfo_Package.Unmarshal(m, b) @@ -176,7 +176,7 @@ func (m *Bundle) Reset() { *m = Bundle{} } func (m *Bundle) String() string { return proto.CompactTextString(m) } func (*Bundle) ProtoMessage() {} func (*Bundle) Descriptor() ([]byte, []int) { - return fileDescriptor_registry_02a3e470a3cc2f84, []int{3} + return fileDescriptor_registry_3b20cfe64d54b8f8, []int{3} } func (m *Bundle) XXX_Unmarshal(b []byte) error { return xxx_messageInfo_Bundle.Unmarshal(m, b) @@ -245,7 +245,7 @@ func (m *ChannelEntry) Reset() { *m = ChannelEntry{} } func (m *ChannelEntry) String() string { return proto.CompactTextString(m) } func (*ChannelEntry) ProtoMessage() {} func (*ChannelEntry) Descriptor() ([]byte, []int) { - return fileDescriptor_registry_02a3e470a3cc2f84, []int{4} + return fileDescriptor_registry_3b20cfe64d54b8f8, []int{4} } func (m *ChannelEntry) XXX_Unmarshal(b []byte) error { return xxx_messageInfo_ChannelEntry.Unmarshal(m, b) @@ -303,7 +303,7 @@ func (m *ListPackageRequest) Reset() { *m = ListPackageRequest{} } func (m *ListPackageRequest) String() string { return proto.CompactTextString(m) } func (*ListPackageRequest) ProtoMessage() {} func (*ListPackageRequest) Descriptor() ([]byte, []int) { - return fileDescriptor_registry_02a3e470a3cc2f84, []int{5} + return fileDescriptor_registry_3b20cfe64d54b8f8, []int{5} } func (m *ListPackageRequest) XXX_Unmarshal(b []byte) error { return xxx_messageInfo_ListPackageRequest.Unmarshal(m, b) @@ -334,7 +334,7 @@ func (m *GetPackageRequest) Reset() { *m = GetPackageRequest{} } func (m *GetPackageRequest) String() string { return proto.CompactTextString(m) } func (*GetPackageRequest) ProtoMessage() {} func (*GetPackageRequest) Descriptor() ([]byte, []int) { - return fileDescriptor_registry_02a3e470a3cc2f84, []int{6} + return fileDescriptor_registry_3b20cfe64d54b8f8, []int{6} } func (m *GetPackageRequest) XXX_Unmarshal(b []byte) error { return xxx_messageInfo_GetPackageRequest.Unmarshal(m, b) @@ -362,7 +362,9 @@ func (m *GetPackageRequest) GetName() string { } type GetBundleRequest struct { - CsvName string `protobuf:"bytes,1,opt,name=csvName,proto3" json:"csvName,omitempty"` + PkgName string `protobuf:"bytes,1,opt,name=pkgName,proto3" json:"pkgName,omitempty"` + ChannelName string `protobuf:"bytes,2,opt,name=channelName,proto3" json:"channelName,omitempty"` + CsvName string `protobuf:"bytes,3,opt,name=csvName,proto3" json:"csvName,omitempty"` XXX_NoUnkeyedLiteral struct{} `json:"-"` XXX_unrecognized []byte `json:"-"` XXX_sizecache int32 `json:"-"` @@ -372,7 +374,7 @@ func (m *GetBundleRequest) Reset() { *m = GetBundleRequest{} } func (m *GetBundleRequest) String() string { return proto.CompactTextString(m) } func (*GetBundleRequest) ProtoMessage() {} func (*GetBundleRequest) Descriptor() ([]byte, []int) { - return fileDescriptor_registry_02a3e470a3cc2f84, []int{7} + return fileDescriptor_registry_3b20cfe64d54b8f8, []int{7} } func (m *GetBundleRequest) XXX_Unmarshal(b []byte) error { return xxx_messageInfo_GetBundleRequest.Unmarshal(m, b) @@ -392,6 +394,20 @@ func (m *GetBundleRequest) XXX_DiscardUnknown() { var xxx_messageInfo_GetBundleRequest proto.InternalMessageInfo +func (m *GetBundleRequest) GetPkgName() string { + if m != nil { + return m.PkgName + } + return "" +} + +func (m *GetBundleRequest) GetChannelName() string { + if m != nil { + return m.ChannelName + } + return "" +} + func (m *GetBundleRequest) GetCsvName() string { if m != nil { return m.CsvName @@ -411,7 +427,7 @@ func (m *GetBundleInChannelRequest) Reset() { *m = GetBundleInChannelReq func (m *GetBundleInChannelRequest) String() string { return proto.CompactTextString(m) } func (*GetBundleInChannelRequest) ProtoMessage() {} func (*GetBundleInChannelRequest) Descriptor() ([]byte, []int) { - return fileDescriptor_registry_02a3e470a3cc2f84, []int{8} + return fileDescriptor_registry_3b20cfe64d54b8f8, []int{8} } func (m *GetBundleInChannelRequest) XXX_Unmarshal(b []byte) error { return xxx_messageInfo_GetBundleInChannelRequest.Unmarshal(m, b) @@ -456,7 +472,7 @@ func (m *GetAllReplacementsRequest) Reset() { *m = GetAllReplacementsReq func (m *GetAllReplacementsRequest) String() string { return proto.CompactTextString(m) } func (*GetAllReplacementsRequest) ProtoMessage() {} func (*GetAllReplacementsRequest) Descriptor() ([]byte, []int) { - return fileDescriptor_registry_02a3e470a3cc2f84, []int{9} + return fileDescriptor_registry_3b20cfe64d54b8f8, []int{9} } func (m *GetAllReplacementsRequest) XXX_Unmarshal(b []byte) error { return xxx_messageInfo_GetAllReplacementsRequest.Unmarshal(m, b) @@ -496,7 +512,7 @@ func (m *GetReplacementRequest) Reset() { *m = GetReplacementRequest{} } func (m *GetReplacementRequest) String() string { return proto.CompactTextString(m) } func (*GetReplacementRequest) ProtoMessage() {} func (*GetReplacementRequest) Descriptor() ([]byte, []int) { - return fileDescriptor_registry_02a3e470a3cc2f84, []int{10} + return fileDescriptor_registry_3b20cfe64d54b8f8, []int{10} } func (m *GetReplacementRequest) XXX_Unmarshal(b []byte) error { return xxx_messageInfo_GetReplacementRequest.Unmarshal(m, b) @@ -551,7 +567,7 @@ func (m *GetAllProvidersRequest) Reset() { *m = GetAllProvidersRequest{} func (m *GetAllProvidersRequest) String() string { return proto.CompactTextString(m) } func (*GetAllProvidersRequest) ProtoMessage() {} func (*GetAllProvidersRequest) Descriptor() ([]byte, []int) { - return fileDescriptor_registry_02a3e470a3cc2f84, []int{11} + return fileDescriptor_registry_3b20cfe64d54b8f8, []int{11} } func (m *GetAllProvidersRequest) XXX_Unmarshal(b []byte) error { return xxx_messageInfo_GetAllProvidersRequest.Unmarshal(m, b) @@ -613,7 +629,7 @@ func (m *GetLatestProvidersRequest) Reset() { *m = GetLatestProvidersReq func (m *GetLatestProvidersRequest) String() string { return proto.CompactTextString(m) } func (*GetLatestProvidersRequest) ProtoMessage() {} func (*GetLatestProvidersRequest) Descriptor() ([]byte, []int) { - return fileDescriptor_registry_02a3e470a3cc2f84, []int{12} + return fileDescriptor_registry_3b20cfe64d54b8f8, []int{12} } func (m *GetLatestProvidersRequest) XXX_Unmarshal(b []byte) error { return xxx_messageInfo_GetLatestProvidersRequest.Unmarshal(m, b) @@ -675,7 +691,7 @@ func (m *GetDefaultProviderRequest) Reset() { *m = GetDefaultProviderReq func (m *GetDefaultProviderRequest) String() string { return proto.CompactTextString(m) } func (*GetDefaultProviderRequest) ProtoMessage() {} func (*GetDefaultProviderRequest) Descriptor() ([]byte, []int) { - return fileDescriptor_registry_02a3e470a3cc2f84, []int{13} + return fileDescriptor_registry_3b20cfe64d54b8f8, []int{13} } func (m *GetDefaultProviderRequest) XXX_Unmarshal(b []byte) error { return xxx_messageInfo_GetDefaultProviderRequest.Unmarshal(m, b) @@ -754,6 +770,7 @@ const _ = grpc.SupportPackageIsVersion4 type RegistryClient interface { ListPackages(ctx context.Context, in *ListPackageRequest, opts ...grpc.CallOption) (Registry_ListPackagesClient, error) GetPackage(ctx context.Context, in *GetPackageRequest, opts ...grpc.CallOption) (*Package, error) + GetBundle(ctx context.Context, in *GetBundleRequest, opts ...grpc.CallOption) (*Bundle, error) GetBundleForChannel(ctx context.Context, in *GetBundleInChannelRequest, opts ...grpc.CallOption) (*Bundle, error) GetChannelEntriesThatReplace(ctx context.Context, in *GetAllReplacementsRequest, opts ...grpc.CallOption) (Registry_GetChannelEntriesThatReplaceClient, error) GetBundleThatReplaces(ctx context.Context, in *GetReplacementRequest, opts ...grpc.CallOption) (*Bundle, error) @@ -811,6 +828,15 @@ func (c *registryClient) GetPackage(ctx context.Context, in *GetPackageRequest, return out, nil } +func (c *registryClient) GetBundle(ctx context.Context, in *GetBundleRequest, opts ...grpc.CallOption) (*Bundle, error) { + out := new(Bundle) + err := c.cc.Invoke(ctx, "/api.Registry/GetBundle", in, out, opts...) + if err != nil { + return nil, err + } + return out, nil +} + func (c *registryClient) GetBundleForChannel(ctx context.Context, in *GetBundleInChannelRequest, opts ...grpc.CallOption) (*Bundle, error) { out := new(Bundle) err := c.cc.Invoke(ctx, "/api.Registry/GetBundleForChannel", in, out, opts...) @@ -938,6 +964,7 @@ func (c *registryClient) GetDefaultBundleThatProvides(ctx context.Context, in *G type RegistryServer interface { ListPackages(*ListPackageRequest, Registry_ListPackagesServer) error GetPackage(context.Context, *GetPackageRequest) (*Package, error) + GetBundle(context.Context, *GetBundleRequest) (*Bundle, error) GetBundleForChannel(context.Context, *GetBundleInChannelRequest) (*Bundle, error) GetChannelEntriesThatReplace(*GetAllReplacementsRequest, Registry_GetChannelEntriesThatReplaceServer) error GetBundleThatReplaces(context.Context, *GetReplacementRequest) (*Bundle, error) @@ -989,6 +1016,24 @@ func _Registry_GetPackage_Handler(srv interface{}, ctx context.Context, dec func return interceptor(ctx, in, info, handler) } +func _Registry_GetBundle_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(GetBundleRequest) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(RegistryServer).GetBundle(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: "/api.Registry/GetBundle", + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(RegistryServer).GetBundle(ctx, req.(*GetBundleRequest)) + } + return interceptor(ctx, in, info, handler) +} + func _Registry_GetBundleForChannel_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { in := new(GetBundleInChannelRequest) if err := dec(in); err != nil { @@ -1114,6 +1159,10 @@ var _Registry_serviceDesc = grpc.ServiceDesc{ MethodName: "GetPackage", Handler: _Registry_GetPackage_Handler, }, + { + MethodName: "GetBundle", + Handler: _Registry_GetBundle_Handler, + }, { MethodName: "GetBundleForChannel", Handler: _Registry_GetBundleForChannel_Handler, @@ -1152,46 +1201,47 @@ var _Registry_serviceDesc = grpc.ServiceDesc{ Metadata: "registry.proto", } -func init() { proto.RegisterFile("registry.proto", fileDescriptor_registry_02a3e470a3cc2f84) } - -var fileDescriptor_registry_02a3e470a3cc2f84 = []byte{ - // 594 bytes of a gzipped FileDescriptorProto - 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xc4, 0x55, 0xcd, 0x6e, 0xd3, 0x40, - 0x10, 0x8e, 0x93, 0x34, 0x49, 0x27, 0x11, 0x6a, 0x97, 0x12, 0x8c, 0x41, 0x55, 0xd8, 0x0b, 0x39, - 0xa0, 0x08, 0x15, 0x10, 0x27, 0x0e, 0x94, 0x42, 0x04, 0x2a, 0xa8, 0xb2, 0x40, 0x1c, 0x38, 0x6d, - 0x9c, 0x25, 0x35, 0x71, 0xd6, 0x66, 0x77, 0x9d, 0xaa, 0x2f, 0xc1, 0x99, 0xc7, 0xe3, 0x51, 0x90, - 0xd7, 0x6b, 0x7b, 0xeb, 0x1f, 0x72, 0x83, 0x9b, 0x67, 0x66, 0xe7, 0x9b, 0x6f, 0x76, 0xbe, 0x1d, - 0xc3, 0x2d, 0x4e, 0x57, 0xbe, 0x90, 0xfc, 0x7a, 0x16, 0xf1, 0x50, 0x86, 0xa8, 0x43, 0x22, 0x1f, - 0xbf, 0x80, 0xfe, 0xeb, 0x4b, 0xc2, 0x18, 0x0d, 0x10, 0x82, 0x2e, 0x23, 0x1b, 0x6a, 0x5b, 0x13, - 0x6b, 0xba, 0xef, 0xaa, 0x6f, 0x64, 0x43, 0xdf, 0x13, 0xdb, 0x8f, 0x89, 0xbb, 0xad, 0xdc, 0x99, - 0x89, 0x1f, 0xc2, 0xf0, 0x82, 0x78, 0x6b, 0xb2, 0xa2, 0x89, 0x59, 0x97, 0x8c, 0xaf, 0xa0, 0xaf, - 0x8f, 0xd4, 0x62, 0x4f, 0x61, 0xe0, 0xa5, 0xa5, 0x85, 0xdd, 0x9e, 0x74, 0xa6, 0xc3, 0x93, 0xd1, - 0x8c, 0x44, 0xfe, 0x4c, 0xf3, 0x71, 0xf3, 0x28, 0x9a, 0x01, 0x5a, 0xd2, 0x6f, 0x24, 0x0e, 0xa4, - 0x8e, 0x29, 0x42, 0x1d, 0x85, 0x55, 0x13, 0xc1, 0xbf, 0x2c, 0xe8, 0x9d, 0xc6, 0x6c, 0x19, 0xdc, - 0x68, 0xc0, 0xba, 0xd1, 0x00, 0x9a, 0xc0, 0x30, 0x2a, 0x1a, 0xd0, 0xed, 0x99, 0xae, 0xe4, 0x84, - 0x57, 0xa9, 0x67, 0xba, 0x34, 0xfa, 0x7b, 0x11, 0x32, 0xbb, 0x9b, 0xa3, 0x27, 0x26, 0x1a, 0x43, - 0x2f, 0x5c, 0x7c, 0xa7, 0x9e, 0xb4, 0xf7, 0x26, 0x9d, 0xe9, 0xbe, 0xab, 0x2d, 0xfc, 0xd3, 0x82, - 0x91, 0xa6, 0xfa, 0x86, 0x49, 0x7e, 0x5d, 0xa6, 0x61, 0xed, 0xa4, 0xd1, 0xae, 0xd2, 0x38, 0x06, - 0x58, 0xa8, 0x76, 0x0d, 0x9e, 0x86, 0x07, 0x39, 0x30, 0xe0, 0x34, 0x0a, 0x88, 0x47, 0x85, 0xe6, - 0x99, 0xdb, 0xf8, 0x08, 0xd0, 0xb9, 0x2f, 0xa4, 0x1e, 0x94, 0x4b, 0x7f, 0xc4, 0x54, 0x48, 0xfc, - 0x08, 0x0e, 0xe7, 0xb4, 0xe4, 0xac, 0x9d, 0xf1, 0x63, 0x38, 0x98, 0x53, 0x99, 0x5e, 0x76, 0x76, - 0xae, 0xf1, 0xce, 0xf1, 0x17, 0xb8, 0x97, 0x9f, 0x7e, 0xc7, 0xb2, 0x41, 0x17, 0x69, 0xd1, 0x7a, - 0x65, 0xa6, 0x69, 0x73, 0xf7, 0x0d, 0xe0, 0xe7, 0x0a, 0xf8, 0x55, 0x10, 0xb8, 0x69, 0x5f, 0x1b, - 0xca, 0xa4, 0xd8, 0xcd, 0x67, 0x03, 0x77, 0xe6, 0x54, 0x1a, 0x39, 0x3b, 0x53, 0x4c, 0x96, 0xed, - 0xbf, 0xb2, 0xac, 0xca, 0x05, 0x4b, 0x18, 0xa7, 0x2c, 0x2f, 0x78, 0xb8, 0xf5, 0x97, 0x94, 0xe7, - 0x14, 0x8f, 0x60, 0x6f, 0xc5, 0xc3, 0x38, 0xd2, 0xd5, 0x52, 0x23, 0xa9, 0xb5, 0xa5, 0x5c, 0xf8, - 0x21, 0xcb, 0x6a, 0x69, 0x33, 0x19, 0xc5, 0xda, 0x67, 0x4b, 0x5d, 0x44, 0x7d, 0x27, 0x92, 0x8b, - 0x82, 0x98, 0x93, 0x40, 0xcf, 0x58, 0x5b, 0xf8, 0x4a, 0xdd, 0xcd, 0x39, 0x91, 0x54, 0xc8, 0xff, - 0x50, 0xf8, 0x2c, 0x7d, 0x9f, 0x59, 0xe5, 0x7f, 0x50, 0xf8, 0xe4, 0x77, 0x17, 0x06, 0xae, 0x5e, - 0x76, 0xe8, 0x25, 0x8c, 0x0c, 0x81, 0x0b, 0x74, 0x57, 0x2d, 0x99, 0xaa, 0xe6, 0x9d, 0x03, 0x15, - 0x30, 0x96, 0x1a, 0x6e, 0x3d, 0xb1, 0xd0, 0x33, 0x80, 0xe2, 0x25, 0xa0, 0xb1, 0x3a, 0x53, 0x79, - 0x1a, 0xce, 0xc8, 0xcc, 0xc5, 0x2d, 0x74, 0x06, 0xb7, 0x73, 0xa1, 0xbf, 0x0d, 0x79, 0xb6, 0x62, - 0x8f, 0xb3, 0xf4, 0xfa, 0x27, 0xe0, 0x0c, 0x55, 0x3c, 0x0d, 0xe2, 0x16, 0xfa, 0x0c, 0x0f, 0xe6, - 0x54, 0x1a, 0xeb, 0xc2, 0xa7, 0xe2, 0xd3, 0x25, 0xc9, 0x04, 0x5b, 0xc0, 0xd5, 0x0b, 0xdf, 0x39, - 0x34, 0xf7, 0xa9, 0x5a, 0x37, 0xaa, 0xa5, 0x53, 0xa5, 0xfa, 0xb4, 0x8a, 0x01, 0x27, 0x90, 0x93, - 0xe1, 0x55, 0x5f, 0x44, 0x99, 0x9a, 0xdb, 0x40, 0x4d, 0x8f, 0x19, 0xdd, 0x37, 0xa8, 0x95, 0x45, - 0xd7, 0xc4, 0xeb, 0x2b, 0xe0, 0x5c, 0xa8, 0xcd, 0xc8, 0x79, 0xd3, 0xf5, 0x8a, 0x6e, 0x02, 0xff, - 0xa0, 0x08, 0x6b, 0x31, 0x16, 0xbd, 0xeb, 0x74, 0x51, 0xc0, 0xd6, 0xeb, 0xb5, 0xd4, 0xff, 0xa2, - 0xa7, 0xfe, 0xa1, 0x4f, 0xff, 0x04, 0x00, 0x00, 0xff, 0xff, 0xe8, 0xd2, 0xdc, 0x71, 0x55, 0x07, - 0x00, 0x00, +func init() { proto.RegisterFile("registry.proto", fileDescriptor_registry_3b20cfe64d54b8f8) } + +var fileDescriptor_registry_3b20cfe64d54b8f8 = []byte{ + // 615 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xc4, 0x55, 0x4d, 0x6f, 0xd3, 0x40, + 0x10, 0x8d, 0x93, 0xe6, 0x6b, 0x12, 0xa1, 0x76, 0x69, 0x83, 0x31, 0xa8, 0x0a, 0x7b, 0x21, 0xa7, + 0x08, 0x0a, 0x88, 0x13, 0x07, 0x4a, 0x21, 0x02, 0x15, 0x54, 0x59, 0x20, 0x0e, 0x9c, 0x36, 0xce, + 0x92, 0x98, 0x38, 0x6b, 0xb3, 0xbb, 0x49, 0xd5, 0x3f, 0xc1, 0x85, 0x0b, 0x3f, 0x17, 0x79, 0xbd, + 0x76, 0xd6, 0x1f, 0xa1, 0x48, 0x48, 0xf4, 0x96, 0x19, 0xef, 0xbc, 0xf7, 0x66, 0xf7, 0xcd, 0x04, + 0x6e, 0x71, 0x3a, 0xf7, 0x85, 0xe4, 0x57, 0xe3, 0x88, 0x87, 0x32, 0x44, 0x0d, 0x12, 0xf9, 0xf8, + 0x39, 0xb4, 0x5f, 0x2d, 0x08, 0x63, 0x34, 0x40, 0x08, 0xf6, 0x18, 0x59, 0x51, 0xdb, 0x1a, 0x5a, + 0xa3, 0xae, 0xab, 0x7e, 0x23, 0x1b, 0xda, 0x9e, 0xd8, 0x7c, 0x88, 0xd3, 0x75, 0x95, 0x4e, 0x43, + 0xfc, 0x00, 0x7a, 0x17, 0xc4, 0x5b, 0x92, 0x39, 0x8d, 0xc3, 0xaa, 0x62, 0x7c, 0x09, 0x6d, 0x7d, + 0xa4, 0x12, 0x7b, 0x04, 0x1d, 0x2f, 0xa1, 0x16, 0x76, 0x7d, 0xd8, 0x18, 0xf5, 0x4e, 0xfa, 0x63, + 0x12, 0xf9, 0x63, 0xad, 0xc7, 0xcd, 0xbe, 0xa2, 0x31, 0xa0, 0x19, 0xfd, 0x4a, 0xd6, 0x81, 0xd4, + 0xdf, 0x94, 0xa0, 0x86, 0xc2, 0xaa, 0xf8, 0x82, 0x7f, 0x59, 0xd0, 0x3a, 0x5d, 0xb3, 0x59, 0x90, + 0x6b, 0xc0, 0xca, 0x35, 0x80, 0x86, 0xd0, 0x8b, 0xb6, 0x0d, 0xe8, 0xf6, 0xcc, 0x54, 0x7c, 0xc2, + 0x2b, 0xf1, 0x99, 0x29, 0x8d, 0xfe, 0x4e, 0x84, 0xcc, 0xde, 0xcb, 0xd0, 0xe3, 0x10, 0x0d, 0xa0, + 0x15, 0x4e, 0xbf, 0x51, 0x4f, 0xda, 0xcd, 0x61, 0x63, 0xd4, 0x75, 0x75, 0x84, 0x7f, 0x58, 0xd0, + 0xd7, 0x52, 0x5f, 0x33, 0xc9, 0xaf, 0x8a, 0x32, 0xac, 0x6b, 0x65, 0xd4, 0xcb, 0x32, 0x8e, 0x01, + 0xa6, 0xaa, 0x5d, 0x43, 0xa7, 0x91, 0x41, 0x0e, 0x74, 0x38, 0x8d, 0x02, 0xe2, 0x51, 0xa1, 0x75, + 0x66, 0x31, 0x3e, 0x04, 0x74, 0xee, 0x0b, 0xa9, 0x1f, 0xca, 0xa5, 0xdf, 0xd7, 0x54, 0x48, 0xfc, + 0x10, 0x0e, 0x26, 0xb4, 0x90, 0xac, 0x7c, 0xe3, 0x05, 0xec, 0x4f, 0xa8, 0x4c, 0x2e, 0x3b, 0x3d, + 0x67, 0x43, 0x3b, 0x5a, 0xce, 0xcd, 0x3b, 0xd7, 0xe1, 0x5f, 0xb4, 0x62, 0xbc, 0x57, 0x23, 0x6f, + 0xb8, 0xcf, 0x70, 0x37, 0x63, 0x7a, 0xcb, 0x52, 0x93, 0xfc, 0x3b, 0x25, 0x7e, 0xa6, 0x80, 0x5f, + 0x06, 0x81, 0x9b, 0xdc, 0xc9, 0x8a, 0x32, 0x29, 0x0c, 0xe0, 0x6a, 0xff, 0xe0, 0x15, 0x1c, 0x4d, + 0xa8, 0x34, 0x6a, 0xae, 0x2d, 0x31, 0x55, 0xd6, 0xff, 0xa8, 0xb2, 0x6c, 0x35, 0x2c, 0x61, 0x90, + 0xa8, 0xbc, 0xe0, 0xe1, 0xc6, 0x9f, 0x51, 0x9e, 0x49, 0x3c, 0x84, 0xe6, 0x9c, 0x87, 0xeb, 0x48, + 0xb3, 0x25, 0x41, 0xcc, 0xb5, 0xa1, 0x5c, 0xf8, 0x21, 0x4b, 0xb9, 0x74, 0x18, 0x3f, 0xe3, 0xd2, + 0x67, 0x33, 0x4d, 0xa2, 0x7e, 0xc7, 0x76, 0x8d, 0x82, 0x35, 0x27, 0x81, 0xf6, 0x87, 0x8e, 0xf0, + 0xa5, 0xba, 0x9b, 0x73, 0x22, 0xa9, 0x90, 0x37, 0x40, 0x7c, 0x96, 0xcc, 0x76, 0xca, 0xfc, 0x1f, + 0x88, 0x4f, 0x7e, 0x36, 0xa1, 0xe3, 0xea, 0x45, 0x89, 0x5e, 0x40, 0xdf, 0x18, 0x0e, 0x81, 0xee, + 0xa8, 0x05, 0x55, 0x9e, 0x17, 0x67, 0x5f, 0x7d, 0x30, 0x16, 0x22, 0xae, 0x3d, 0xb2, 0xd0, 0x53, + 0x80, 0xed, 0x14, 0xa1, 0x81, 0x3a, 0x53, 0x1a, 0x2b, 0xa7, 0x6f, 0xd6, 0xe2, 0x1a, 0x7a, 0x0c, + 0xdd, 0xcc, 0xe8, 0xe8, 0x28, 0x2d, 0xca, 0x8d, 0x98, 0xd3, 0x53, 0xe9, 0x24, 0x87, 0x6b, 0xe8, + 0x0c, 0x6e, 0x67, 0x47, 0xde, 0x84, 0x3c, 0xdd, 0xe8, 0xc7, 0xf9, 0xe2, 0xe2, 0xd4, 0x14, 0x51, + 0x3e, 0xc1, 0xfd, 0x09, 0x95, 0xc6, 0x76, 0xf2, 0xa9, 0xf8, 0xb8, 0x20, 0xa9, 0xc7, 0xb7, 0x70, + 0xd5, 0xb3, 0xe2, 0x1c, 0x98, 0xeb, 0x5b, 0x6d, 0x37, 0x75, 0x0b, 0xa7, 0x6a, 0x50, 0x12, 0x16, + 0x03, 0x4e, 0x20, 0x27, 0xc5, 0x2b, 0x0f, 0x51, 0x51, 0x9a, 0xbb, 0x43, 0x9a, 0x76, 0x06, 0xba, + 0x67, 0x48, 0x2b, 0xfa, 0x74, 0x97, 0xae, 0x2f, 0x80, 0x33, 0x6f, 0xef, 0x46, 0xce, 0x9a, 0xae, + 0x1e, 0x82, 0x5d, 0xe0, 0xef, 0x95, 0x60, 0xed, 0xdf, 0x6d, 0xef, 0xba, 0x5c, 0x6c, 0x61, 0xab, + 0x2d, 0x5e, 0xe8, 0x7f, 0xda, 0x52, 0x7f, 0xd9, 0x4f, 0x7e, 0x07, 0x00, 0x00, 0xff, 0xff, 0x11, + 0x0c, 0xe5, 0xa0, 0xc4, 0x07, 0x00, 0x00, } diff --git a/vendor/github.com/operator-framework/operator-registry/pkg/api/registry.proto b/vendor/github.com/operator-framework/operator-registry/pkg/api/registry.proto index 97e26b191f1..caf6b53faab 100644 --- a/vendor/github.com/operator-framework/operator-registry/pkg/api/registry.proto +++ b/vendor/github.com/operator-framework/operator-registry/pkg/api/registry.proto @@ -4,7 +4,8 @@ package api; service Registry { rpc ListPackages(ListPackageRequest) returns (stream PackageName) {} - rpc GetPackage(GetPackageRequest) returns (Package) {} + rpc GetPackage(GetPackageRequest) returns (Package) {} + rpc GetBundle(GetBundleRequest) returns (Bundle) {} rpc GetBundleForChannel(GetBundleInChannelRequest) returns (Bundle) {} rpc GetChannelEntriesThatReplace(GetAllReplacementsRequest) returns (stream ChannelEntry) {} rpc GetBundleThatReplaces(GetReplacementRequest) returns (Bundle) {} @@ -51,7 +52,9 @@ message GetPackageRequest{ } message GetBundleRequest{ - string csvName = 1; + string pkgName = 1; + string channelName = 2; + string csvName = 3; } message GetBundleInChannelRequest{ diff --git a/vendor/github.com/operator-framework/operator-registry/pkg/client/client.go b/vendor/github.com/operator-framework/operator-registry/pkg/client/client.go index a8bfba6f500..0556001dfcf 100644 --- a/vendor/github.com/operator-framework/operator-registry/pkg/client/client.go +++ b/vendor/github.com/operator-framework/operator-registry/pkg/client/client.go @@ -11,6 +11,7 @@ import ( ) type Interface interface { + GetBundle(ctx context.Context, packageName, channelName, csvName string) (*registry.Bundle, error) GetBundleInPackageChannel(ctx context.Context, packageName, channelName string) (*registry.Bundle, error) GetReplacementBundleInPackageChannel(ctx context.Context, currentName, packageName, channelName string) (*registry.Bundle, error) GetBundleThatProvides(ctx context.Context, group, version, kind string) (*registry.Bundle, error) @@ -24,6 +25,14 @@ type Client struct { var _ Interface = &Client{} +func (c *Client) GetBundle(ctx context.Context, packageName, channelName, csvName string) (*registry.Bundle, error) { + bundle, err := c.Registry.GetBundle(ctx, &api.GetBundleRequest{PkgName: packageName, ChannelName: channelName, CsvName: csvName}) + if err != nil { + return nil, err + } + return registry.NewBundleFromStrings(bundle.CsvName, bundle.PackageName, bundle.ChannelName, bundle.Object) +} + func (c *Client) GetBundleInPackageChannel(ctx context.Context, packageName, channelName string) (*registry.Bundle, error) { bundle, err := c.Registry.GetBundleForChannel(ctx, &api.GetBundleInChannelRequest{PkgName: packageName, ChannelName: channelName}) if err != nil { diff --git a/vendor/github.com/operator-framework/operator-registry/pkg/registry/interface.go b/vendor/github.com/operator-framework/operator-registry/pkg/registry/interface.go index acf0b69e3e3..4c1d0e74eac 100644 --- a/vendor/github.com/operator-framework/operator-registry/pkg/registry/interface.go +++ b/vendor/github.com/operator-framework/operator-registry/pkg/registry/interface.go @@ -14,6 +14,7 @@ type Query interface { ListTables(ctx context.Context) ([]string, error) ListPackages(ctx context.Context) ([]string, error) GetPackage(ctx context.Context, name string) (*PackageManifest, error) + GetBundle(ctx context.Context, pkgName, channelName, csvName string) (string, error) GetBundleForChannel(ctx context.Context, pkgName string, channelName string) (string, error) // Get all channel entries that say they replace this one GetChannelEntriesThatReplace(ctx context.Context, name string) (entries []*ChannelEntry, err error) diff --git a/vendor/github.com/operator-framework/operator-registry/pkg/server/server.go b/vendor/github.com/operator-framework/operator-registry/pkg/server/server.go index 8a6e617873d..2689b094885 100644 --- a/vendor/github.com/operator-framework/operator-registry/pkg/server/server.go +++ b/vendor/github.com/operator-framework/operator-registry/pkg/server/server.go @@ -38,6 +38,18 @@ func (s *RegistryServer) GetPackage(ctx context.Context, req *api.GetPackageRequ return api.PackageManifestToAPIPackage(packageManifest), nil } +func (s *RegistryServer) GetBundle(ctx context.Context, req *api.GetBundleRequest) (*api.Bundle, error) { + bundleString, err := s.store.GetBundle(ctx, req.GetPkgName(), req.GetChannelName(), req.GetCsvName()) + if err != nil { + return nil, err + } + entry := ®istry.ChannelEntry{ + PackageName: req.GetPkgName(), + ChannelName: req.GetChannelName(), + } + return api.BundleStringToAPIBundle(bundleString, entry) +} + func (s *RegistryServer) GetBundleForChannel(ctx context.Context, req *api.GetBundleInChannelRequest) (*api.Bundle, error) { bundleString, err := s.store.GetBundleForChannel(ctx, req.GetPkgName(), req.GetChannelName()) if err != nil { diff --git a/vendor/github.com/operator-framework/operator-registry/pkg/sqlite/query.go b/vendor/github.com/operator-framework/operator-registry/pkg/sqlite/query.go index 641c8b4e640..664517ebdf7 100644 --- a/vendor/github.com/operator-framework/operator-registry/pkg/sqlite/query.go +++ b/vendor/github.com/operator-framework/operator-registry/pkg/sqlite/query.go @@ -103,6 +103,25 @@ func (s *SQLQuerier) GetPackage(ctx context.Context, name string) (*registry.Pac return pkg, nil } +func (s *SQLQuerier) GetBundle(ctx context.Context, pkgName, channelName, csvName string) (string, error) { + query := `SELECT DISTINCT operatorbundle.bundle + FROM operatorbundle INNER JOIN channel_entry ON operatorbundle.name=channel_entry.operatorbundle_name + WHERE channel_entry.package_name=? AND channel_entry.channel_name=? AND operatorbundle.name=? LIMIT 1` + rows, err := s.db.QueryContext(ctx, query, pkgName, channelName, csvName) + if err != nil { + return "", err + } + + if !rows.Next() { + return "", fmt.Errorf("no bundle found for csv %s", csvName) + } + var bundleStringSQL sql.NullString + if err := rows.Scan(&bundleStringSQL); err != nil { + return "", err + } + return bundleStringSQL.String, nil +} + func (s *SQLQuerier) GetBundleForChannel(ctx context.Context, pkgName string, channelName string) (string, error) { query := `SELECT DISTINCT operatorbundle.bundle FROM channel INNER JOIN operatorbundle ON channel.head_operatorbundle_name=operatorbundle.name diff --git a/vendor/k8s.io/client-go/pkg/version/base.go b/vendor/k8s.io/client-go/pkg/version/base.go index b348f490ae6..9b4c79f8951 100644 --- a/vendor/k8s.io/client-go/pkg/version/base.go +++ b/vendor/k8s.io/client-go/pkg/version/base.go @@ -55,8 +55,8 @@ var ( // NOTE: The $Format strings are replaced during 'git archive' thanks to the // companion .gitattributes file containing 'export-subst' in this same // directory. See also https://git-scm.com/docs/gitattributes - gitVersion string = "v0.0.0-master+7d04d0e2" - gitCommit string = "7d04d0e2a0a1a4d4a1cd6baa432a2301492e4e65" // sha1 from git, output of $(git rev-parse HEAD) + gitVersion string = "v0.0.0-master+$Format:%h$" + gitCommit string = "$Format:%H$" // sha1 from git, output of $(git rev-parse HEAD) gitTreeState string = "" // state of git tree, either "clean" or "dirty" buildDate string = "1970-01-01T00:00:00Z" // build date in ISO8601 format, output of $(date -u +'%Y-%m-%dT%H:%M:%SZ') diff --git a/vendor/modules.txt b/vendor/modules.txt index 873e763fc27..cea9cde91b4 100644 --- a/vendor/modules.txt +++ b/vendor/modules.txt @@ -134,7 +134,7 @@ github.com/openshift/client-go/config/clientset/versioned/scheme # github.com/openshift/library-go v0.0.0-20190125204812-22b2ba2f485f github.com/openshift/library-go/pkg/config/clusteroperator/v1helpers github.com/openshift/library-go/pkg/operator/v1helpers -# github.com/operator-framework/operator-registry v1.0.4 +# github.com/operator-framework/operator-registry v1.0.5 github.com/operator-framework/operator-registry/pkg/api/grpc_health_v1 github.com/operator-framework/operator-registry/pkg/client github.com/operator-framework/operator-registry/pkg/registry