From d1fc8501ca1d36e603fc0f168ff70596d2d57e75 Mon Sep 17 00:00:00 2001 From: Ben Luddy Date: Wed, 4 Aug 2021 12:16:10 -0400 Subject: [PATCH] Move operator caching from resolver into a new package. Signed-off-by: Ben Luddy --- pkg/controller/operators/olm/operator.go | 5 +- pkg/controller/operators/olm/operator_test.go | 9 +- pkg/controller/operators/olm/operatorgroup.go | 23 +- .../registry/resolver/{ => cache}/cache.go | 96 +-- .../resolver/{ => cache}/cache_test.go | 42 +- .../resolver/{ => cache}/operators.go | 217 ++++--- .../resolver/{ => cache}/operators_test.go | 156 ++--- .../resolver/{ => cache}/predicates.go | 24 +- .../resolver/{ => cache}/predicates_test.go | 12 +- pkg/controller/registry/resolver/groups.go | 19 +- .../registry/resolver/groups_test.go | 75 +-- .../registry/resolver/installabletypes.go | 14 +- pkg/controller/registry/resolver/labeler.go | 15 +- .../registry/resolver/labeler_test.go | 11 +- pkg/controller/registry/resolver/resolver.go | 167 ++--- .../registry/resolver/resolver_test.go | 591 +++++++++--------- .../registry/resolver/step_resolver.go | 27 +- .../registry/resolver/step_resolver_test.go | 39 +- pkg/controller/registry/resolver/steps.go | 3 +- pkg/controller/registry/resolver/util_test.go | 112 +--- pkg/fakes/fake_api_intersection_reconciler.go | 13 +- 21 files changed, 837 insertions(+), 833 deletions(-) rename pkg/controller/registry/resolver/{ => cache}/cache.go (82%) rename pkg/controller/registry/resolver/{ => cache}/cache_test.go (93%) rename pkg/controller/registry/resolver/{ => cache}/operators.go (75%) rename pkg/controller/registry/resolver/{ => cache}/operators_test.go (92%) rename pkg/controller/registry/resolver/{ => cache}/predicates.go (95%) rename pkg/controller/registry/resolver/{ => cache}/predicates_test.go (80%) diff --git a/pkg/controller/operators/olm/operator.go b/pkg/controller/operators/olm/operator.go index 94d3339f50..b71abe2115 100644 --- a/pkg/controller/operators/olm/operator.go +++ b/pkg/controller/operators/olm/operator.go @@ -38,6 +38,7 @@ import ( "github.com/operator-framework/operator-lifecycle-manager/pkg/controller/operators/internal/pruning" "github.com/operator-framework/operator-lifecycle-manager/pkg/controller/operators/olm/overrides" "github.com/operator-framework/operator-lifecycle-manager/pkg/controller/registry/resolver" + resolvercache "github.com/operator-framework/operator-lifecycle-manager/pkg/controller/registry/resolver/cache" "github.com/operator-framework/operator-lifecycle-manager/pkg/lib/clients" csvutility "github.com/operator-framework/operator-lifecycle-manager/pkg/lib/csv" "github.com/operator-framework/operator-lifecycle-manager/pkg/lib/event" @@ -1364,7 +1365,7 @@ func (a *Operator) transitionCSVState(in v1alpha1.ClusterServiceVersion) (out *v out = in.DeepCopy() now := a.now() - operatorSurface, err := resolver.NewOperatorFromV1Alpha1CSV(out) + operatorSurface, err := resolvercache.NewOperatorFromV1Alpha1CSV(out) if err != nil { // If the resolver is unable to retrieve the operator info from the CSV the CSV requires changes, a syncError should not be returned. logger.WithError(err).Warn("Unable to retrieve operator information from CSV") @@ -1428,7 +1429,7 @@ func (a *Operator) transitionCSVState(in v1alpha1.ClusterServiceVersion) (out *v groupSurface := resolver.NewOperatorGroup(operatorGroup) otherGroupSurfaces := resolver.NewOperatorGroupSurfaces(otherGroups...) - providedAPIs := operatorSurface.ProvidedAPIs().StripPlural() + providedAPIs := operatorSurface.GetProvidedAPIs().StripPlural() switch result := a.apiReconciler.Reconcile(providedAPIs, groupSurface, otherGroupSurfaces...); { case operatorGroup.Spec.StaticProvidedAPIs && (result == resolver.AddAPIs || result == resolver.RemoveAPIs): diff --git a/pkg/controller/operators/olm/operator_test.go b/pkg/controller/operators/olm/operator_test.go index 5f6eae41a4..f7d9abbded 100644 --- a/pkg/controller/operators/olm/operator_test.go +++ b/pkg/controller/operators/olm/operator_test.go @@ -55,6 +55,7 @@ import ( olmerrors "github.com/operator-framework/operator-lifecycle-manager/pkg/controller/errors" "github.com/operator-framework/operator-lifecycle-manager/pkg/controller/install" "github.com/operator-framework/operator-lifecycle-manager/pkg/controller/registry/resolver" + resolvercache "github.com/operator-framework/operator-lifecycle-manager/pkg/controller/registry/resolver/cache" "github.com/operator-framework/operator-lifecycle-manager/pkg/fakes" "github.com/operator-framework/operator-lifecycle-manager/pkg/lib/clientfake" csvutility "github.com/operator-framework/operator-lifecycle-manager/pkg/lib/csv" @@ -872,7 +873,7 @@ func TestTransitionCSV(t *testing.T) { logrus.SetLevel(logrus.DebugLevel) namespace := "ns" - apiHash, err := resolver.APIKeyToGVKHash(opregistry.APIKey{Group: "g1", Version: "v1", Kind: "c1"}) + apiHash, err := resolvercache.APIKeyToGVKHash(opregistry.APIKey{Group: "g1", Version: "v1", Kind: "c1"}) require.NoError(t, err) defaultOperatorGroup := &v1.OperatorGroup{ @@ -3693,7 +3694,7 @@ func TestSyncOperatorGroups(t *testing.T) { v1alpha1.CSVPhaseNone, ), labels.Set{resolver.APILabelKeyPrefix + "9f4c46c37bdff8d0": "provided"}) - operatorCSV.Spec.InstallStrategy.StrategySpec.DeploymentSpecs[0].Spec.Template.Spec.Containers[0].Env = []corev1.EnvVar{corev1.EnvVar{ + operatorCSV.Spec.InstallStrategy.StrategySpec.DeploymentSpecs[0].Spec.Template.Spec.Containers[0].Env = []corev1.EnvVar{{ Name: "OPERATOR_CONDITION_NAME", Value: operatorCSV.GetName(), }} @@ -4631,7 +4632,7 @@ func TestOperatorGroupConditions(t *testing.T) { }, expectError: true, expectedConditions: []metav1.Condition{ - metav1.Condition{ + { Type: v1.OperatorGroupServiceAccountCondition, Status: metav1.ConditionTrue, Reason: v1.OperatorGroupServiceAccountReason, @@ -4674,7 +4675,7 @@ func TestOperatorGroupConditions(t *testing.T) { }, expectError: true, expectedConditions: []metav1.Condition{ - metav1.Condition{ + { Type: v1.MutlipleOperatorGroupCondition, Status: metav1.ConditionTrue, Reason: v1.MultipleOperatorGroupsReason, diff --git a/pkg/controller/operators/olm/operatorgroup.go b/pkg/controller/operators/olm/operatorgroup.go index bef31bbb08..8c28ef0d1e 100644 --- a/pkg/controller/operators/olm/operatorgroup.go +++ b/pkg/controller/operators/olm/operatorgroup.go @@ -22,6 +22,7 @@ import ( "github.com/operator-framework/operator-lifecycle-manager/pkg/controller/install" "github.com/operator-framework/operator-lifecycle-manager/pkg/controller/operators/decorators" "github.com/operator-framework/operator-lifecycle-manager/pkg/controller/registry/resolver" + "github.com/operator-framework/operator-lifecycle-manager/pkg/controller/registry/resolver/cache" hashutil "github.com/operator-framework/operator-lifecycle-manager/pkg/lib/kubernetes/pkg/util/hash" "github.com/operator-framework/operator-lifecycle-manager/pkg/lib/ownerutil" opregistry "github.com/operator-framework/operator-registry/pkg/registry" @@ -46,7 +47,7 @@ var ( ) func aggregationLabelFromAPIKey(k opregistry.APIKey, suffix string) (string, error) { - hash, err := resolver.APIKeyToGVKHash(k) + hash, err := cache.APIKeyToGVKHash(k) if err != nil { return "", err } @@ -188,7 +189,7 @@ func (a *Operator) syncOperatorGroups(obj interface{}) error { groupSurface := resolver.NewOperatorGroup(op) groupProvidedAPIs := groupSurface.ProvidedAPIs() providedAPIsForCSVs := a.providedAPIsFromCSVs(op, logger) - providedAPIsForGroup := make(resolver.APISet) + providedAPIsForGroup := make(cache.APISet) for api := range providedAPIsForCSVs { providedAPIsForGroup[api] = struct{}{} } @@ -309,26 +310,26 @@ func (a *Operator) providedAPIsFromCSVs(group *v1.OperatorGroup, logger *logrus. // TODO: Throw out CSVs that aren't members of the group due to group related failures? // Union the providedAPIsFromCSVs from existing members of the group - operatorSurface, err := resolver.NewOperatorFromV1Alpha1CSV(csv) + operatorSurface, err := cache.NewOperatorFromV1Alpha1CSV(csv) if err != nil { logger.WithError(err).Warn("could not create OperatorSurface from csv") continue } - for providedAPI := range operatorSurface.ProvidedAPIs().StripPlural() { + for providedAPI := range operatorSurface.GetProvidedAPIs().StripPlural() { providedAPIsFromCSVs[providedAPI] = csv } } return providedAPIsFromCSVs } -func (a *Operator) pruneProvidedAPIs(group *v1.OperatorGroup, groupProvidedAPIs resolver.APISet, providedAPIsFromCSVs map[opregistry.APIKey]*v1alpha1.ClusterServiceVersion, logger *logrus.Entry) { +func (a *Operator) pruneProvidedAPIs(group *v1.OperatorGroup, groupProvidedAPIs cache.APISet, providedAPIsFromCSVs map[opregistry.APIKey]*v1alpha1.ClusterServiceVersion, logger *logrus.Entry) { // Don't prune providedAPIsFromCSVs if static if group.Spec.StaticProvidedAPIs { a.logger.Debug("group has static provided apis. skipping provided api pruning") return } - intersection := make(resolver.APISet) + intersection := make(cache.APISet) for api := range providedAPIsFromCSVs { if _, ok := groupProvidedAPIs[api]; ok { intersection[api] = struct{}{} @@ -978,7 +979,7 @@ func (a *Operator) updateNamespaceList(op *v1.OperatorGroup) ([]string, error) { return namespaceList, nil } -func (a *Operator) ensureOpGroupClusterRole(op *v1.OperatorGroup, suffix string, apis resolver.APISet) error { +func (a *Operator) ensureOpGroupClusterRole(op *v1.OperatorGroup, suffix string, apis cache.APISet) error { clusterRole := &rbacv1.ClusterRole{ ObjectMeta: metav1.ObjectMeta{ Name: strings.Join([]string{op.GetName(), suffix}, "-"), @@ -1029,7 +1030,7 @@ func (a *Operator) ensureOpGroupClusterRole(op *v1.OperatorGroup, suffix string, return nil } -func (a *Operator) ensureOpGroupClusterRoles(op *v1.OperatorGroup, apis resolver.APISet) error { +func (a *Operator) ensureOpGroupClusterRoles(op *v1.OperatorGroup, apis cache.APISet) error { for _, suffix := range Suffices { if err := a.ensureOpGroupClusterRole(op, suffix, apis); err != nil { return err @@ -1038,7 +1039,7 @@ func (a *Operator) ensureOpGroupClusterRoles(op *v1.OperatorGroup, apis resolver return nil } -func (a *Operator) findCSVsThatProvideAnyOf(provide resolver.APISet) ([]*v1alpha1.ClusterServiceVersion, error) { +func (a *Operator) findCSVsThatProvideAnyOf(provide cache.APISet) ([]*v1alpha1.ClusterServiceVersion, error) { csvs, err := a.lister.OperatorsV1alpha1().ClusterServiceVersionLister().ClusterServiceVersions(metav1.NamespaceAll).List(labels.Everything()) if err != nil { return nil, err @@ -1051,12 +1052,12 @@ func (a *Operator) findCSVsThatProvideAnyOf(provide resolver.APISet) ([]*v1alpha continue } - operatorSurface, err := resolver.NewOperatorFromV1Alpha1CSV(csv) + operatorSurface, err := cache.NewOperatorFromV1Alpha1CSV(csv) if err != nil { continue } - if len(operatorSurface.ProvidedAPIs().StripPlural().Intersection(provide)) > 0 { + if len(operatorSurface.GetProvidedAPIs().StripPlural().Intersection(provide)) > 0 { providers = append(providers, csv) } } diff --git a/pkg/controller/registry/resolver/cache.go b/pkg/controller/registry/resolver/cache/cache.go similarity index 82% rename from pkg/controller/registry/resolver/cache.go rename to pkg/controller/registry/resolver/cache/cache.go index d713f5018e..c26f30d434 100644 --- a/pkg/controller/registry/resolver/cache.go +++ b/pkg/controller/registry/resolver/cache/cache.go @@ -1,4 +1,4 @@ -package resolver +package cache import ( "context" @@ -76,14 +76,14 @@ func NewOperatorCache(rcp RegistryClientProvider, log logrus.FieldLogger, catsrc } type NamespacedOperatorCache struct { - namespaces []string + Namespaces []string existing *registry.CatalogKey - snapshots map[registry.CatalogKey]*CatalogSnapshot + Snapshots map[registry.CatalogKey]*CatalogSnapshot } func (c *NamespacedOperatorCache) Error() error { var errs []error - for key, snapshot := range c.snapshots { + for key, snapshot := range c.Snapshots { snapshot.m.Lock() err := snapshot.err snapshot.m.Unlock() @@ -113,8 +113,8 @@ func (c *OperatorCache) Namespaced(namespaces ...string) MultiCatalogOperatorFin clients := c.rcp.ClientsForNamespaces(namespaces...) result := NamespacedOperatorCache{ - namespaces: namespaces, - snapshots: make(map[registry.CatalogKey]*CatalogSnapshot), + Namespaces: namespaces, + Snapshots: make(map[registry.CatalogKey]*CatalogSnapshot), } var misses []registry.CatalogKey @@ -127,8 +127,8 @@ func (c *OperatorCache) Namespaced(namespaces ...string) MultiCatalogOperatorFin func() { snapshot.m.RLock() defer snapshot.m.RUnlock() - if !snapshot.Expired(now) && snapshot.operators != nil && len(snapshot.operators) > 0 { - result.snapshots[key] = snapshot + if !snapshot.Expired(now) && snapshot.Operators != nil && len(snapshot.Operators) > 0 { + result.Snapshots[key] = snapshot } else { misses = append(misses, key) } @@ -162,8 +162,8 @@ func (c *OperatorCache) Namespaced(namespaces ...string) MultiCatalogOperatorFin // Check for any snapshots that were populated while waiting to acquire the lock. var found int for i := range misses { - if snapshot, ok := c.snapshots[misses[i]]; ok && !snapshot.Expired(now) && snapshot.operators != nil && len(snapshot.operators) > 0 { - result.snapshots[misses[i]] = snapshot + if snapshot, ok := c.snapshots[misses[i]]; ok && !snapshot.Expired(now) && snapshot.Operators != nil && len(snapshot.Operators) > 0 { + result.Snapshots[misses[i]] = snapshot misses[found], misses[i] = misses[i], misses[found] found++ } @@ -182,14 +182,14 @@ func (c *OperatorCache) Namespaced(namespaces ...string) MultiCatalogOperatorFin s := CatalogSnapshot{ logger: c.logger.WithField("catalog", miss), - key: miss, + Key: miss, expiry: now.Add(c.ttl), pop: cancel, - priority: catalogSourcePriority(catsrcPriority), + Priority: catalogSourcePriority(catsrcPriority), } s.m.Lock() c.snapshots[miss] = &s - result.snapshots[miss] = &s + result.Snapshots[miss] = &s go c.populate(ctx, &s, clients[miss]) } @@ -219,7 +219,7 @@ func (c *OperatorCache) populate(ctx context.Context, snapshot *CatalogSnapshot, snapshot.err = err return } - c.logger.WithField("catalog", snapshot.key.String()).Debug("updating cache") + c.logger.WithField("catalog", snapshot.Key.String()).Debug("updating cache") var operators []*Operator for b := it.Next(); b != nil; b = it.Next() { defaultChannel, ok := defaultChannels[b.PackageName] @@ -232,26 +232,26 @@ func (c *OperatorCache) populate(ctx context.Context, snapshot *CatalogSnapshot, defaultChannel = p.DefaultChannelName } } - o, err := NewOperatorFromBundle(b, "", snapshot.key, defaultChannel) + o, err := NewOperatorFromBundle(b, "", snapshot.Key, defaultChannel) if err != nil { snapshot.logger.Warnf("failed to construct operator from bundle, continuing: %v", err) continue } - o.providedAPIs = o.ProvidedAPIs().StripPlural() - o.requiredAPIs = o.RequiredAPIs().StripPlural() - o.replaces = b.Replaces - ensurePackageProperty(o, b.PackageName, b.Version) + o.ProvidedAPIs = o.ProvidedAPIs.StripPlural() + o.RequiredAPIs = o.RequiredAPIs.StripPlural() + o.Replaces = b.Replaces + EnsurePackageProperty(o, b.PackageName, b.Version) operators = append(operators, o) } if err := it.Error(); err != nil { snapshot.logger.Warnf("error encountered while listing bundles: %s", err.Error()) snapshot.err = err } - snapshot.operators = operators + snapshot.Operators = operators } -func ensurePackageProperty(o *Operator, name, version string) { - for _, p := range o.Properties() { +func EnsurePackageProperty(o *Operator, name, version string) { + for _, p := range o.Properties { if p.Type == opregistry.PackageType { return } @@ -264,7 +264,7 @@ func ensurePackageProperty(o *Operator, name, version string) { if err != nil { return } - o.properties = append(o.properties, &api.Property{ + o.Properties = append(o.Properties, &api.Property{ Type: opregistry.PackageType, Value: string(bytes), }) @@ -275,7 +275,7 @@ func (c *NamespacedOperatorCache) Catalog(k registry.CatalogKey) OperatorFinder if k.Empty() { return c } - if snapshot, ok := c.snapshots[k]; ok { + if snapshot, ok := c.Snapshots[k]; ok { return snapshot } return EmptyOperatorFinder{} @@ -286,7 +286,7 @@ func (c *NamespacedOperatorCache) FindPreferred(preferred *registry.CatalogKey, if preferred != nil && preferred.Empty() { preferred = nil } - sorted := NewSortableSnapshots(c.existing, preferred, c.namespaces, c.snapshots) + sorted := NewSortableSnapshots(c.existing, preferred, c.Namespaces, c.Snapshots) sort.Sort(sorted) for _, snapshot := range sorted.snapshots { result = append(result, snapshot.Find(p...)...) @@ -296,11 +296,11 @@ func (c *NamespacedOperatorCache) FindPreferred(preferred *registry.CatalogKey, func (c *NamespacedOperatorCache) WithExistingOperators(snapshot *CatalogSnapshot) MultiCatalogOperatorFinder { o := &NamespacedOperatorCache{ - namespaces: c.namespaces, - existing: &snapshot.key, - snapshots: c.snapshots, + Namespaces: c.Namespaces, + existing: &snapshot.Key, + Snapshots: c.Snapshots, } - o.snapshots[snapshot.key] = snapshot + o.Snapshots[snapshot.Key] = snapshot return o } @@ -310,12 +310,12 @@ func (c *NamespacedOperatorCache) Find(p ...OperatorPredicate) []*Operator { type CatalogSnapshot struct { logger logrus.FieldLogger - key registry.CatalogKey + Key registry.CatalogKey expiry time.Time - operators []*Operator + Operators []*Operator m sync.RWMutex pop context.CancelFunc - priority catalogSourcePriority + Priority catalogSourcePriority err error } @@ -332,8 +332,8 @@ func (s *CatalogSnapshot) Expired(at time.Time) bool { func NewRunningOperatorSnapshot(logger logrus.FieldLogger, key registry.CatalogKey, o []*Operator) *CatalogSnapshot { return &CatalogSnapshot{ logger: logger, - key: key, - operators: o, + Key: key, + Operators: o, } } @@ -372,37 +372,37 @@ func (s SortableSnapshots) Len() int { func (s SortableSnapshots) Less(i, j int) bool { // existing operators are preferred over catalog operators if s.existing != nil && - s.snapshots[i].key.Name == s.existing.Name && - s.snapshots[i].key.Namespace == s.existing.Namespace { + s.snapshots[i].Key.Name == s.existing.Name && + s.snapshots[i].Key.Namespace == s.existing.Namespace { return true } if s.existing != nil && - s.snapshots[j].key.Name == s.existing.Name && - s.snapshots[j].key.Namespace == s.existing.Namespace { + s.snapshots[j].Key.Name == s.existing.Name && + s.snapshots[j].Key.Namespace == s.existing.Namespace { return false } // preferred catalog is less than all other catalogs if s.preferred != nil && - s.snapshots[i].key.Name == s.preferred.Name && - s.snapshots[i].key.Namespace == s.preferred.Namespace { + s.snapshots[i].Key.Name == s.preferred.Name && + s.snapshots[i].Key.Namespace == s.preferred.Namespace { return true } if s.preferred != nil && - s.snapshots[j].key.Name == s.preferred.Name && - s.snapshots[j].key.Namespace == s.preferred.Namespace { + s.snapshots[j].Key.Name == s.preferred.Name && + s.snapshots[j].Key.Namespace == s.preferred.Namespace { return false } // the rest are sorted first on priority, namespace and then by name - if s.snapshots[i].priority != s.snapshots[j].priority { - return s.snapshots[i].priority > s.snapshots[j].priority + if s.snapshots[i].Priority != s.snapshots[j].Priority { + return s.snapshots[i].Priority > s.snapshots[j].Priority } - if s.snapshots[i].key.Namespace != s.snapshots[j].key.Namespace { - return s.namespaces[s.snapshots[i].key.Namespace] < s.namespaces[s.snapshots[j].key.Namespace] + if s.snapshots[i].Key.Namespace != s.snapshots[j].Key.Namespace { + return s.namespaces[s.snapshots[i].Key.Namespace] < s.namespaces[s.snapshots[j].Key.Namespace] } - return s.snapshots[i].key.Name < s.snapshots[j].key.Name + return s.snapshots[i].Key.Name < s.snapshots[j].Key.Name } // Swap swaps the elements with indexes i and j. @@ -413,7 +413,7 @@ func (s SortableSnapshots) Swap(i, j int) { func (s *CatalogSnapshot) Find(p ...OperatorPredicate) []*Operator { s.m.RLock() defer s.m.RUnlock() - return Filter(s.operators, p...) + return Filter(s.Operators, p...) } type OperatorFinder interface { diff --git a/pkg/controller/registry/resolver/cache_test.go b/pkg/controller/registry/resolver/cache/cache_test.go similarity index 93% rename from pkg/controller/registry/resolver/cache_test.go rename to pkg/controller/registry/resolver/cache/cache_test.go index 1d86cacc78..ecb4f14b24 100644 --- a/pkg/controller/registry/resolver/cache_test.go +++ b/pkg/controller/registry/resolver/cache/cache_test.go @@ -1,4 +1,4 @@ -package resolver +package cache import ( "context" @@ -240,9 +240,9 @@ func TestCatalogSnapshotFind(t *testing.T) { return false }), Operators: []*Operator{ - {name: "a"}, - {name: "b"}, - {name: "c"}, + {Name: "a"}, + {Name: "b"}, + {Name: "c"}, }, Expected: nil, }, @@ -260,34 +260,34 @@ func TestCatalogSnapshotFind(t *testing.T) { return true }), Operators: []*Operator{ - {name: "a"}, - {name: "b"}, - {name: "c"}, + {Name: "a"}, + {Name: "b"}, + {Name: "c"}, }, Expected: []*Operator{ - {name: "a"}, - {name: "b"}, - {name: "c"}, + {Name: "a"}, + {Name: "b"}, + {Name: "c"}, }, }, { Name: "some satisfy predicate", Predicate: OperatorPredicateTestFunc(func(o *Operator) bool { - return o.name != "a" + return o.Name != "a" }), Operators: []*Operator{ - {name: "a"}, - {name: "b"}, - {name: "c"}, + {Name: "a"}, + {Name: "b"}, + {Name: "c"}, }, Expected: []*Operator{ - {name: "b"}, - {name: "c"}, + {Name: "b"}, + {Name: "c"}, }, }, } { t.Run(tt.Name, func(t *testing.T) { - s := CatalogSnapshot{operators: tt.Operators} + s := CatalogSnapshot{Operators: tt.Operators} assert.Equal(t, tt.Expected, s.Find(tt.Predicate)) }) } @@ -314,7 +314,7 @@ func TestStripPluralRequiredAndProvidedAPIKeys(t *testing.T) { Kind: "K2", Plural: "ks2", }}, - Properties: apiSetToProperties(map[opregistry.APIKey]struct{}{ + Properties: APISetToProperties(map[opregistry.APIKey]struct{}{ { Group: "g", Version: "v1", @@ -322,7 +322,7 @@ func TestStripPluralRequiredAndProvidedAPIKeys(t *testing.T) { Plural: "ks", }: {}, }, nil, false), - Dependencies: apiSetToDependencies(map[opregistry.APIKey]struct{}{ + Dependencies: APISetToDependencies(map[opregistry.APIKey]struct{}{ { Group: "g2", Version: "v2", @@ -340,8 +340,8 @@ func TestStripPluralRequiredAndProvidedAPIKeys(t *testing.T) { result, err := AtLeast(1, nc.Find(ProvidingAPIPredicate(opregistry.APIKey{Group: "g", Version: "v1", Kind: "K"}))) assert.NoError(t, err) assert.Equal(t, 1, len(result)) - assert.Equal(t, "K.v1.g", result[0].providedAPIs.String()) - assert.Equal(t, "K2.v2.g2", result[0].requiredAPIs.String()) + assert.Equal(t, "K.v1.g", result[0].ProvidedAPIs.String()) + assert.Equal(t, "K2.v2.g2", result[0].RequiredAPIs.String()) } func TestNamespaceOperatorCacheError(t *testing.T) { diff --git a/pkg/controller/registry/resolver/operators.go b/pkg/controller/registry/resolver/cache/operators.go similarity index 75% rename from pkg/controller/registry/resolver/operators.go rename to pkg/controller/registry/resolver/cache/operators.go index 32c38b3f09..7b85124133 100644 --- a/pkg/controller/registry/resolver/operators.go +++ b/pkg/controller/registry/resolver/cache/operators.go @@ -1,4 +1,4 @@ -package resolver +package cache import ( "encoding/json" @@ -208,28 +208,28 @@ var ExistingOperator = OperatorSourceInfo{Package: "", Channel: "", StartingCSV: // OperatorSurface describes the API surfaces provided and required by an Operator. type OperatorSurface interface { - ProvidedAPIs() APISet - RequiredAPIs() APISet + GetProvidedAPIs() APISet + GetRequiredAPIs() APISet Identifier() string - Replaces() string - Version() *semver.Version - SourceInfo() *OperatorSourceInfo - Bundle() *api.Bundle + GetReplaces() string + GetVersion() *semver.Version + GetSourceInfo() *OperatorSourceInfo + GetBundle() *api.Bundle Inline() bool - Properties() []*api.Property - Skips() []string + GetProperties() []*api.Property + GetSkips() []string } type Operator struct { - name string - replaces string - providedAPIs APISet - requiredAPIs APISet - version *semver.Version - bundle *api.Bundle - sourceInfo *OperatorSourceInfo - properties []*api.Property - skips []string + Name string + Replaces string + ProvidedAPIs APISet + RequiredAPIs APISet + Version *semver.Version + Bundle *api.Bundle + SourceInfo *OperatorSourceInfo + Properties []*api.Property + Skips []string } var _ OperatorSurface = &Operator{} @@ -265,13 +265,13 @@ func NewOperatorFromBundle(bundle *api.Bundle, startingCSV string, sourceKey reg } } if len(bundle.Dependencies) > 0 { - ps, err := legacyDependenciesToProperties(bundle.Dependencies) + ps, err := LegacyDependenciesToProperties(bundle.Dependencies) if err != nil { return nil, fmt.Errorf("failed to translate legacy dependencies to properties: %w", err) } properties = append(properties, ps...) } else { - ps, err := requiredAPIsToProperties(required) + ps, err := RequiredAPIsToProperties(required) if err != nil { return nil, err } @@ -279,15 +279,15 @@ func NewOperatorFromBundle(bundle *api.Bundle, startingCSV string, sourceKey reg } o := &Operator{ - name: bundle.CsvName, - replaces: bundle.Replaces, - version: version, - providedAPIs: provided, - requiredAPIs: required, - bundle: bundle, - sourceInfo: sourceInfo, - properties: properties, - skips: bundle.Skips, + Name: bundle.CsvName, + Replaces: bundle.Replaces, + Version: version, + ProvidedAPIs: provided, + RequiredAPIs: required, + Bundle: bundle, + SourceInfo: sourceInfo, + Properties: properties, + Skips: bundle.Skips, } if !o.Inline() { @@ -331,91 +331,83 @@ func NewOperatorFromV1Alpha1CSV(csv *v1alpha1.ClusterServiceVersion) (*Operator, if err != nil { return nil, err } - dependencies, err := requiredAPIsToProperties(requiredAPIs) + dependencies, err := RequiredAPIsToProperties(requiredAPIs) if err != nil { return nil, err } properties = append(properties, dependencies...) return &Operator{ - name: csv.GetName(), - version: &csv.Spec.Version.Version, - providedAPIs: providedAPIs, - requiredAPIs: requiredAPIs, - sourceInfo: &ExistingOperator, - properties: properties, + Name: csv.GetName(), + Version: &csv.Spec.Version.Version, + ProvidedAPIs: providedAPIs, + RequiredAPIs: requiredAPIs, + SourceInfo: &ExistingOperator, + Properties: properties, }, nil } -func (o *Operator) Name() string { - return o.name +func (o *Operator) GetProvidedAPIs() APISet { + return o.ProvidedAPIs } -func (o *Operator) ProvidedAPIs() APISet { - return o.providedAPIs -} - -func (o *Operator) RequiredAPIs() APISet { - return o.requiredAPIs +func (o *Operator) GetRequiredAPIs() APISet { + return o.RequiredAPIs } func (o *Operator) Identifier() string { - return o.name + return o.Name } -func (o *Operator) Replaces() string { - return o.replaces +func (o *Operator) GetReplaces() string { + return o.Replaces } -func (o *Operator) Skips() []string { - return o.skips -} - -func (o *Operator) SetReplaces(replacing string) { - o.replaces = replacing +func (o *Operator) GetSkips() []string { + return o.Skips } func (o *Operator) Package() string { - if o.bundle != nil { - return o.bundle.PackageName + if o.Bundle != nil { + return o.Bundle.PackageName } return "" } func (o *Operator) Channel() string { - if o.bundle != nil { - return o.bundle.ChannelName + if o.Bundle != nil { + return o.Bundle.ChannelName } return "" } -func (o *Operator) SourceInfo() *OperatorSourceInfo { - return o.sourceInfo +func (o *Operator) GetSourceInfo() *OperatorSourceInfo { + return o.SourceInfo } -func (o *Operator) Bundle() *api.Bundle { - return o.bundle +func (o *Operator) GetBundle() *api.Bundle { + return o.Bundle } -func (o *Operator) Version() *semver.Version { - return o.version +func (o *Operator) GetVersion() *semver.Version { + return o.Version } func (o *Operator) SemverRange() (semver.Range, error) { - return semver.ParseRange(o.Bundle().SkipRange) + return semver.ParseRange(o.Bundle.SkipRange) } func (o *Operator) Inline() bool { - return o.bundle != nil && o.bundle.GetBundlePath() == "" + return o.Bundle != nil && o.Bundle.GetBundlePath() == "" } -func (o *Operator) Properties() []*api.Property { - return o.properties +func (o *Operator) GetProperties() []*api.Property { + return o.Properties } func (o *Operator) DependencyPredicates() (predicates []OperatorPredicate, err error) { predicates = make([]OperatorPredicate, 0) - for _, property := range o.Properties() { + for _, property := range o.Properties { predicate, err := PredicateForProperty(property) if err != nil { return nil, err @@ -428,7 +420,7 @@ func (o *Operator) DependencyPredicates() (predicates []OperatorPredicate, err e return } -func requiredAPIsToProperties(apis APISet) (out []*api.Property, err error) { +func RequiredAPIsToProperties(apis APISet) (out []*api.Property, err error) { if len(apis) == 0 { return } @@ -479,7 +471,7 @@ func providedAPIsToProperties(apis APISet) (out []*api.Property, err error) { return nil, nil } -func legacyDependenciesToProperties(dependencies []*api.Dependency) ([]*api.Property, error) { +func LegacyDependenciesToProperties(dependencies []*api.Dependency) ([]*api.Property, error) { var result []*api.Property for _, dependency := range dependencies { switch dependency.Type { @@ -538,3 +530,88 @@ func legacyDependenciesToProperties(dependencies []*api.Dependency) ([]*api.Prop } return result, nil } + +func APISetToProperties(crds, apis APISet, deprecated bool) (out []*api.Property) { + out = make([]*api.Property, 0) + for a := range crds { + val, err := json.Marshal(opregistry.GVKProperty{ + Group: a.Group, + Kind: a.Kind, + Version: a.Version, + }) + if err != nil { + panic(err) + } + out = append(out, &api.Property{ + Type: opregistry.GVKType, + Value: string(val), + }) + } + for a := range apis { + val, err := json.Marshal(opregistry.GVKProperty{ + Group: a.Group, + Kind: a.Kind, + Version: a.Version, + }) + if err != nil { + panic(err) + } + out = append(out, &api.Property{ + Type: opregistry.GVKType, + Value: string(val), + }) + } + if deprecated { + val, err := json.Marshal(opregistry.DeprecatedProperty{}) + if err != nil { + panic(err) + } + out = append(out, &api.Property{ + Type: opregistry.DeprecatedType, + Value: string(val), + }) + } + if len(out) == 0 { + return nil + } + return +} + +func APISetToDependencies(crds, apis APISet) (out []*api.Dependency) { + if len(crds)+len(apis) == 0 { + return nil + } + out = make([]*api.Dependency, 0) + for a := range crds { + val, err := json.Marshal(opregistry.GVKDependency{ + Group: a.Group, + Kind: a.Kind, + Version: a.Version, + }) + if err != nil { + panic(err) + } + out = append(out, &api.Dependency{ + Type: opregistry.GVKType, + Value: string(val), + }) + } + for a := range apis { + val, err := json.Marshal(opregistry.GVKDependency{ + Group: a.Group, + Kind: a.Kind, + Version: a.Version, + }) + if err != nil { + panic(err) + } + out = append(out, &api.Dependency{ + Type: opregistry.GVKType, + Value: string(val), + }) + } + if len(out) == 0 { + return nil + } + return +} diff --git a/pkg/controller/registry/resolver/operators_test.go b/pkg/controller/registry/resolver/cache/operators_test.go similarity index 92% rename from pkg/controller/registry/resolver/operators_test.go rename to pkg/controller/registry/resolver/cache/operators_test.go index eb295deec4..5e08f8b089 100644 --- a/pkg/controller/registry/resolver/operators_test.go +++ b/pkg/controller/registry/resolver/cache/operators_test.go @@ -1,4 +1,4 @@ -package resolver +package cache import ( "encoding/json" @@ -737,7 +737,7 @@ func TestAPIMultiOwnerSet_PopAPIKey(t *testing.T) { name: "OneApi/OneOwner", s: map[opregistry.APIKey]OperatorSet{ {Group: "g", Version: "v", Kind: "k", Plural: "p"}: map[string]OperatorSurface{ - "owner1": &Operator{name: "op1"}, + "owner1": &Operator{Name: "op1"}, }, }, }, @@ -745,8 +745,8 @@ func TestAPIMultiOwnerSet_PopAPIKey(t *testing.T) { name: "OneApi/MultiOwner", s: map[opregistry.APIKey]OperatorSet{ {Group: "g", Version: "v", Kind: "k", Plural: "p"}: map[string]OperatorSurface{ - "owner1": &Operator{name: "op1"}, - "owner2": &Operator{name: "op2"}, + "owner1": &Operator{Name: "op1"}, + "owner2": &Operator{Name: "op2"}, }, }, }, @@ -754,12 +754,12 @@ func TestAPIMultiOwnerSet_PopAPIKey(t *testing.T) { name: "MultipleApi/MultiOwner", s: map[opregistry.APIKey]OperatorSet{ {Group: "g", Version: "v", Kind: "k", Plural: "p"}: map[string]OperatorSurface{ - "owner1": &Operator{name: "op1"}, - "owner2": &Operator{name: "op2"}, + "owner1": &Operator{Name: "op1"}, + "owner2": &Operator{Name: "op2"}, }, {Group: "g2", Version: "v2", Kind: "k2", Plural: "p2"}: map[string]OperatorSurface{ - "owner1": &Operator{name: "op1"}, - "owner2": &Operator{name: "op2"}, + "owner1": &Operator{Name: "op1"}, + "owner2": &Operator{Name: "op2"}, }, }, }, @@ -797,41 +797,41 @@ func TestAPIMultiOwnerSet_PopAPIRequirers(t *testing.T) { name: "OneApi/OneOwner", s: map[opregistry.APIKey]OperatorSet{ {Group: "g", Version: "v", Kind: "k", Plural: "p"}: map[string]OperatorSurface{ - "owner1": &Operator{name: "op1"}, + "owner1": &Operator{Name: "op1"}, }, }, want: map[string]OperatorSurface{ - "owner1": &Operator{name: "op1"}, + "owner1": &Operator{Name: "op1"}, }, }, { name: "OneApi/MultiOwner", s: map[opregistry.APIKey]OperatorSet{ {Group: "g", Version: "v", Kind: "k", Plural: "p"}: map[string]OperatorSurface{ - "owner1": &Operator{name: "op1"}, - "owner2": &Operator{name: "op2"}, + "owner1": &Operator{Name: "op1"}, + "owner2": &Operator{Name: "op2"}, }, }, want: map[string]OperatorSurface{ - "owner1": &Operator{name: "op1"}, - "owner2": &Operator{name: "op2"}, + "owner1": &Operator{Name: "op1"}, + "owner2": &Operator{Name: "op2"}, }, }, { name: "MultipleApi/MultiOwner", s: map[opregistry.APIKey]OperatorSet{ {Group: "g", Version: "v", Kind: "k", Plural: "p"}: map[string]OperatorSurface{ - "owner1": &Operator{name: "op1"}, - "owner2": &Operator{name: "op2"}, + "owner1": &Operator{Name: "op1"}, + "owner2": &Operator{Name: "op2"}, }, {Group: "g2", Version: "v2", Kind: "k2", Plural: "p2"}: map[string]OperatorSurface{ - "owner1": &Operator{name: "op1"}, - "owner2": &Operator{name: "op2"}, + "owner1": &Operator{Name: "op1"}, + "owner2": &Operator{Name: "op2"}, }, }, want: map[string]OperatorSurface{ - "owner1": &Operator{name: "op1"}, - "owner2": &Operator{name: "op2"}, + "owner1": &Operator{Name: "op1"}, + "owner2": &Operator{Name: "op2"}, }, }, } @@ -1077,12 +1077,12 @@ func TestNewOperatorFromBundle(t *testing.T) { sourceKey: registry.CatalogKey{Name: "source", Namespace: "testNamespace"}, }, want: &Operator{ - name: "testBundle", - version: &version.Version, - providedAPIs: EmptyAPISet(), - requiredAPIs: EmptyAPISet(), - bundle: bundleNoAPIs, - sourceInfo: &OperatorSourceInfo{ + Name: "testBundle", + Version: &version.Version, + ProvidedAPIs: EmptyAPISet(), + RequiredAPIs: EmptyAPISet(), + Bundle: bundleNoAPIs, + SourceInfo: &OperatorSourceInfo{ Package: "testPackage", Channel: "testChannel", Catalog: registry.CatalogKey{Name: "source", Namespace: "testNamespace"}, @@ -1096,9 +1096,9 @@ func TestNewOperatorFromBundle(t *testing.T) { sourceKey: registry.CatalogKey{Name: "source", Namespace: "testNamespace"}, }, want: &Operator{ - name: "testBundle", - version: &version.Version, - providedAPIs: APISet{ + Name: "testBundle", + Version: &version.Version, + ProvidedAPIs: APISet{ opregistry.APIKey{ Group: "crd.group.com", Version: "v1", @@ -1112,7 +1112,7 @@ func TestNewOperatorFromBundle(t *testing.T) { Plural: "ownedapis", }: struct{}{}, }, - requiredAPIs: APISet{ + RequiredAPIs: APISet{ opregistry.APIKey{ Group: "crd.group.com", Version: "v1", @@ -1126,7 +1126,7 @@ func TestNewOperatorFromBundle(t *testing.T) { Plural: "requiredapis", }: struct{}{}, }, - properties: []*api.Property{ + Properties: []*api.Property{ { Type: "olm.gvk", Value: "{\"group\":\"crd.group.com\",\"kind\":\"OwnedCRD\",\"version\":\"v1\"}", @@ -1144,8 +1144,8 @@ func TestNewOperatorFromBundle(t *testing.T) { Value: "{\"group\":\"apis.group.com\",\"kind\":\"RequiredAPI\",\"version\":\"v1\"}", }, }, - bundle: bundleWithAPIs, - sourceInfo: &OperatorSourceInfo{ + Bundle: bundleWithAPIs, + SourceInfo: &OperatorSourceInfo{ Package: "testPackage", Channel: "testChannel", Catalog: registry.CatalogKey{Name: "source", Namespace: "testNamespace"}, @@ -1159,11 +1159,11 @@ func TestNewOperatorFromBundle(t *testing.T) { sourceKey: registry.CatalogKey{Name: "source", Namespace: "testNamespace"}, }, want: &Operator{ - name: "testBundle", - providedAPIs: EmptyAPISet(), - requiredAPIs: EmptyAPISet(), - bundle: bundleWithAPIsUnextracted, - sourceInfo: &OperatorSourceInfo{ + Name: "testBundle", + ProvidedAPIs: EmptyAPISet(), + RequiredAPIs: EmptyAPISet(), + Bundle: bundleWithAPIsUnextracted, + SourceInfo: &OperatorSourceInfo{ Package: "testPackage", Channel: "testChannel", Catalog: registry.CatalogKey{Name: "source", Namespace: "testNamespace"}, @@ -1178,12 +1178,12 @@ func TestNewOperatorFromBundle(t *testing.T) { defaultChannel: "testChannel", }, want: &Operator{ - name: "testBundle", - version: &version.Version, - providedAPIs: EmptyAPISet(), - requiredAPIs: EmptyAPISet(), - bundle: bundleNoAPIs, - sourceInfo: &OperatorSourceInfo{ + Name: "testBundle", + Version: &version.Version, + ProvidedAPIs: EmptyAPISet(), + RequiredAPIs: EmptyAPISet(), + Bundle: bundleNoAPIs, + SourceInfo: &OperatorSourceInfo{ Package: "testPackage", Channel: "testChannel", Catalog: registry.CatalogKey{Name: "source", Namespace: "testNamespace"}, @@ -1198,11 +1198,11 @@ func TestNewOperatorFromBundle(t *testing.T) { sourceKey: registry.CatalogKey{Name: "source", Namespace: "testNamespace"}, }, want: &Operator{ - name: "testBundle", - version: &version.Version, - providedAPIs: EmptyAPISet(), - requiredAPIs: EmptyAPISet(), - properties: []*api.Property{ + Name: "testBundle", + Version: &version.Version, + ProvidedAPIs: EmptyAPISet(), + RequiredAPIs: EmptyAPISet(), + Properties: []*api.Property{ { Type: "olm.gvk", Value: "{\"group\":\"crd.group.com\",\"kind\":\"OwnedCRD\",\"version\":\"v1\"}", @@ -1220,8 +1220,8 @@ func TestNewOperatorFromBundle(t *testing.T) { Value: "{\"group\":\"apis.group.com\",\"kind\":\"RequiredAPI\",\"version\":\"v1\"}", }, }, - bundle: bundleWithPropsAndDeps, - sourceInfo: &OperatorSourceInfo{ + Bundle: bundleWithPropsAndDeps, + SourceInfo: &OperatorSourceInfo{ Package: "testPackage", Channel: "testChannel", Catalog: registry.CatalogKey{Name: "source", Namespace: "testNamespace"}, @@ -1233,8 +1233,8 @@ func TestNewOperatorFromBundle(t *testing.T) { t.Run(tt.name, func(t *testing.T) { got, err := NewOperatorFromBundle(tt.args.bundle, "", tt.args.sourceKey, tt.args.defaultChannel) require.Equal(t, tt.wantErr, err) - requirePropertiesEqual(t, tt.want.properties, got.properties) - tt.want.properties, got.properties = nil, nil + requirePropertiesEqual(t, tt.want.Properties, got.Properties) + tt.want.Properties, got.Properties = nil, nil require.Equal(t, tt.want, got) }) } @@ -1264,11 +1264,11 @@ func TestNewOperatorFromCSV(t *testing.T) { }, }, want: &Operator{ - name: "operator.v1", - providedAPIs: EmptyAPISet(), - requiredAPIs: EmptyAPISet(), - sourceInfo: &ExistingOperator, - version: &version.Version, + Name: "operator.v1", + ProvidedAPIs: EmptyAPISet(), + RequiredAPIs: EmptyAPISet(), + SourceInfo: &ExistingOperator, + Version: &version.Version, }, }, { @@ -1303,12 +1303,12 @@ func TestNewOperatorFromCSV(t *testing.T) { }, }, want: &Operator{ - name: "operator.v1", - providedAPIs: map[opregistry.APIKey]struct{}{ + Name: "operator.v1", + ProvidedAPIs: map[opregistry.APIKey]struct{}{ {Group: "g", Version: "v1", Kind: "APIKind", Plural: "apikinds"}: {}, {Group: "g", Version: "v1", Kind: "CRDKind", Plural: "crdkinds"}: {}, }, - properties: []*api.Property{ + Properties: []*api.Property{ { Type: "olm.gvk", Value: "{\"group\":\"g\",\"kind\":\"APIKind\",\"version\":\"v1\"}", @@ -1318,9 +1318,9 @@ func TestNewOperatorFromCSV(t *testing.T) { Value: "{\"group\":\"g\",\"kind\":\"CRDKind\",\"version\":\"v1\"}", }, }, - requiredAPIs: EmptyAPISet(), - sourceInfo: &ExistingOperator, - version: &version.Version, + RequiredAPIs: EmptyAPISet(), + SourceInfo: &ExistingOperator, + Version: &version.Version, }, }, { @@ -1355,13 +1355,13 @@ func TestNewOperatorFromCSV(t *testing.T) { }, }, want: &Operator{ - name: "operator.v1", - providedAPIs: EmptyAPISet(), - requiredAPIs: map[opregistry.APIKey]struct{}{ + Name: "operator.v1", + ProvidedAPIs: EmptyAPISet(), + RequiredAPIs: map[opregistry.APIKey]struct{}{ {Group: "g", Version: "v1", Kind: "APIKind", Plural: "apikinds"}: {}, {Group: "g", Version: "v1", Kind: "CRDKind", Plural: "crdkinds"}: {}, }, - properties: []*api.Property{ + Properties: []*api.Property{ { Type: "olm.gvk.required", Value: "{\"group\":\"g\",\"kind\":\"APIKind\",\"version\":\"v1\"}", @@ -1371,8 +1371,8 @@ func TestNewOperatorFromCSV(t *testing.T) { Value: "{\"group\":\"g\",\"kind\":\"CRDKind\",\"version\":\"v1\"}", }, }, - sourceInfo: &ExistingOperator, - version: &version.Version, + SourceInfo: &ExistingOperator, + Version: &version.Version, }, }, { @@ -1422,16 +1422,16 @@ func TestNewOperatorFromCSV(t *testing.T) { }, }, want: &Operator{ - name: "operator.v1", - providedAPIs: map[opregistry.APIKey]struct{}{ + Name: "operator.v1", + ProvidedAPIs: map[opregistry.APIKey]struct{}{ {Group: "g", Version: "v1", Kind: "APIOwnedKind", Plural: "apiownedkinds"}: {}, {Group: "g", Version: "v1", Kind: "CRDOwnedKind", Plural: "crdownedkinds"}: {}, }, - requiredAPIs: map[opregistry.APIKey]struct{}{ + RequiredAPIs: map[opregistry.APIKey]struct{}{ {Group: "g2", Version: "v1", Kind: "APIReqKind", Plural: "apireqkinds"}: {}, {Group: "g2", Version: "v1", Kind: "CRDReqKind", Plural: "crdreqkinds"}: {}, }, - properties: []*api.Property{ + Properties: []*api.Property{ { Type: "olm.gvk", Value: "{\"group\":\"g\",\"kind\":\"APIOwnedKind\",\"version\":\"v1\"}", @@ -1449,8 +1449,8 @@ func TestNewOperatorFromCSV(t *testing.T) { Value: "{\"group\":\"g2\",\"kind\":\"CRDReqKind\",\"version\":\"v1\"}", }, }, - sourceInfo: &ExistingOperator, - version: &version.Version, + SourceInfo: &ExistingOperator, + Version: &version.Version, }, }, } @@ -1458,8 +1458,8 @@ func TestNewOperatorFromCSV(t *testing.T) { t.Run(tt.name, func(t *testing.T) { got, err := NewOperatorFromV1Alpha1CSV(tt.args.csv) require.Equal(t, tt.wantErr, err) - requirePropertiesEqual(t, tt.want.properties, got.properties) - tt.want.properties, got.properties = nil, nil + requirePropertiesEqual(t, tt.want.Properties, got.Properties) + tt.want.Properties, got.Properties = nil, nil require.Equal(t, tt.want, got) }) } diff --git a/pkg/controller/registry/resolver/predicates.go b/pkg/controller/registry/resolver/cache/predicates.go similarity index 95% rename from pkg/controller/registry/resolver/predicates.go rename to pkg/controller/registry/resolver/cache/predicates.go index 4e731dd412..171ee5ac91 100644 --- a/pkg/controller/registry/resolver/predicates.go +++ b/pkg/controller/registry/resolver/cache/predicates.go @@ -1,4 +1,4 @@ -package resolver +package cache import ( "bytes" @@ -24,7 +24,7 @@ func CSVNamePredicate(name string) OperatorPredicate { } func (c csvNamePredicate) Test(o *Operator) bool { - return o.Name() == string(c) + return o.Name == string(c) } func (c csvNamePredicate) String() string { @@ -42,10 +42,10 @@ func (ch channelPredicate) Test(o *Operator) bool { if string(ch) == "" { return true } - if o.Bundle() == nil { + if o.Bundle == nil { return false } - return o.Bundle().ChannelName == string(ch) + return o.Bundle.ChannelName == string(ch) } func (ch channelPredicate) String() string { @@ -59,7 +59,7 @@ func PkgPredicate(pkg string) OperatorPredicate { } func (pkg pkgPredicate) Test(o *Operator) bool { - for _, p := range o.Properties() { + for _, p := range o.Properties { if p.Type != opregistry.PackageType { continue } @@ -89,7 +89,7 @@ func VersionInRangePredicate(r semver.Range, version string) OperatorPredicate { } func (v versionInRangePredicate) Test(o *Operator) bool { - for _, p := range o.Properties() { + for _, p := range o.Properties { if p.Type != opregistry.PackageType { continue } @@ -106,7 +106,7 @@ func (v versionInRangePredicate) Test(o *Operator) bool { return true } } - return o.Version() != nil && v.r(*o.Version()) + return o.Version != nil && v.r(*o.Version) } func (v versionInRangePredicate) String() string { @@ -119,7 +119,7 @@ func LabelPredicate(label string) OperatorPredicate { return labelPredicate(label) } func (l labelPredicate) Test(o *Operator) bool { - for _, p := range o.Properties() { + for _, p := range o.Properties { if p.Type != opregistry.LabelType { continue } @@ -148,7 +148,7 @@ func CatalogPredicate(key registry.CatalogKey) OperatorPredicate { } func (c catalogPredicate) Test(o *Operator) bool { - return c.key.Equal(o.SourceInfo().Catalog) + return c.key.Equal(o.SourceInfo.Catalog) } func (c catalogPredicate) String() string { @@ -166,7 +166,7 @@ func ProvidingAPIPredicate(api opregistry.APIKey) OperatorPredicate { } func (g gvkPredicate) Test(o *Operator) bool { - for _, p := range o.Properties() { + for _, p := range o.Properties { if p.Type != opregistry.GVKType { continue } @@ -210,10 +210,10 @@ func ReplacesPredicate(replaces string) OperatorPredicate { } func (r replacesPredicate) Test(o *Operator) bool { - if o.Replaces() == string(r) { + if o.Replaces == string(r) { return true } - for _, s := range o.Skips() { + for _, s := range o.Skips { if s == string(r) { return true } diff --git a/pkg/controller/registry/resolver/predicates_test.go b/pkg/controller/registry/resolver/cache/predicates_test.go similarity index 80% rename from pkg/controller/registry/resolver/predicates_test.go rename to pkg/controller/registry/resolver/cache/predicates_test.go index 97947a7364..ad493b0a7d 100644 --- a/pkg/controller/registry/resolver/predicates_test.go +++ b/pkg/controller/registry/resolver/cache/predicates_test.go @@ -1,4 +1,4 @@ -package resolver +package cache import ( "testing" @@ -6,6 +6,16 @@ import ( "github.com/stretchr/testify/assert" ) +type OperatorPredicateTestFunc func(*Operator) bool + +func (opf OperatorPredicateTestFunc) Test(o *Operator) bool { + return opf(o) +} + +func (opf OperatorPredicateTestFunc) String() string { + return "" +} + func TestCountingPredicate(t *testing.T) { for _, tc := range []struct { Name string diff --git a/pkg/controller/registry/resolver/groups.go b/pkg/controller/registry/resolver/groups.go index 2dcc276e08..72f3e68ebf 100644 --- a/pkg/controller/registry/resolver/groups.go +++ b/pkg/controller/registry/resolver/groups.go @@ -5,6 +5,7 @@ import ( "strings" v1 "github.com/operator-framework/api/pkg/operators/v1" + "github.com/operator-framework/operator-lifecycle-manager/pkg/controller/registry/resolver/cache" ) type NamespaceSet map[string]struct{} @@ -93,7 +94,7 @@ type OperatorGroupSurface interface { Identifier() string Namespace() string Targets() NamespaceSet - ProvidedAPIs() APISet + ProvidedAPIs() cache.APISet GroupIntersection(groups ...OperatorGroupSurface) []OperatorGroupSurface } @@ -103,7 +104,7 @@ type OperatorGroup struct { namespace string name string targets NamespaceSet - providedAPIs APISet + providedAPIs cache.APISet } func NewOperatorGroup(group *v1.OperatorGroup) *OperatorGroup { @@ -119,7 +120,7 @@ func NewOperatorGroup(group *v1.OperatorGroup) *OperatorGroup { namespace: group.GetNamespace(), name: group.GetName(), targets: NewNamespaceSet(namespaces), - providedAPIs: GVKStringToProvidedAPISet(gvksStr), + providedAPIs: cache.GVKStringToProvidedAPISet(gvksStr), } } @@ -144,7 +145,7 @@ func (g *OperatorGroup) Targets() NamespaceSet { return g.targets } -func (g *OperatorGroup) ProvidedAPIs() APISet { +func (g *OperatorGroup) ProvidedAPIs() cache.APISet { return g.providedAPIs } @@ -174,18 +175,18 @@ const ( ) type APIIntersectionReconciler interface { - Reconcile(add APISet, group OperatorGroupSurface, otherGroups ...OperatorGroupSurface) APIReconciliationResult + Reconcile(add cache.APISet, group OperatorGroupSurface, otherGroups ...OperatorGroupSurface) APIReconciliationResult } -type APIIntersectionReconcileFunc func(add APISet, group OperatorGroupSurface, otherGroups ...OperatorGroupSurface) APIReconciliationResult +type APIIntersectionReconcileFunc func(add cache.APISet, group OperatorGroupSurface, otherGroups ...OperatorGroupSurface) APIReconciliationResult -func (a APIIntersectionReconcileFunc) Reconcile(add APISet, group OperatorGroupSurface, otherGroups ...OperatorGroupSurface) APIReconciliationResult { +func (a APIIntersectionReconcileFunc) Reconcile(add cache.APISet, group OperatorGroupSurface, otherGroups ...OperatorGroupSurface) APIReconciliationResult { return a(add, group, otherGroups...) } -func ReconcileAPIIntersection(add APISet, group OperatorGroupSurface, otherGroups ...OperatorGroupSurface) APIReconciliationResult { +func ReconcileAPIIntersection(add cache.APISet, group OperatorGroupSurface, otherGroups ...OperatorGroupSurface) APIReconciliationResult { groupIntersection := group.GroupIntersection(otherGroups...) - providedAPIIntersection := make(APISet) + providedAPIIntersection := make(cache.APISet) for _, g := range groupIntersection { providedAPIIntersection = providedAPIIntersection.Union(g.ProvidedAPIs()) } diff --git a/pkg/controller/registry/resolver/groups_test.go b/pkg/controller/registry/resolver/groups_test.go index 20fbc56a56..6b2be428d4 100644 --- a/pkg/controller/registry/resolver/groups_test.go +++ b/pkg/controller/registry/resolver/groups_test.go @@ -8,7 +8,8 @@ import ( "github.com/stretchr/testify/require" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" - "github.com/operator-framework/api/pkg/operators/v1" + v1 "github.com/operator-framework/api/pkg/operators/v1" + "github.com/operator-framework/operator-lifecycle-manager/pkg/controller/registry/resolver/cache" ) func buildAPIOperatorGroup(namespace, name string, targets []string, gvks []string) *v1.OperatorGroup { @@ -38,7 +39,7 @@ func TestNewOperatorGroup(t *testing.T) { namespace: "ns", name: "empty-group", targets: make(NamespaceSet), - providedAPIs: make(APISet), + providedAPIs: make(cache.APISet), }, }, { @@ -51,7 +52,7 @@ func TestNewOperatorGroup(t *testing.T) { "ns": {}, "ns-1": {}, }, - providedAPIs: make(APISet), + providedAPIs: make(cache.APISet), }, }, { @@ -63,7 +64,7 @@ func TestNewOperatorGroup(t *testing.T) { targets: NamespaceSet{ "ns": {}, }, - providedAPIs: make(APISet), + providedAPIs: make(cache.APISet), }, }, { @@ -77,7 +78,7 @@ func TestNewOperatorGroup(t *testing.T) { "ns-1": {}, "ns-2": {}, }, - providedAPIs: make(APISet), + providedAPIs: make(cache.APISet), }, }, { @@ -89,7 +90,7 @@ func TestNewOperatorGroup(t *testing.T) { targets: NamespaceSet{ metav1.NamespaceAll: {}, }, - providedAPIs: make(APISet), + providedAPIs: make(cache.APISet), }, }, { @@ -102,7 +103,7 @@ func TestNewOperatorGroup(t *testing.T) { "ns": {}, "ns-1": {}, }, - providedAPIs: APISet{ + providedAPIs: cache.APISet{ opregistry.APIKey{Group: "birds.com", Version: "v1alpha1", Kind: "Goose"}: {}, }, }, @@ -117,7 +118,7 @@ func TestNewOperatorGroup(t *testing.T) { "ns": {}, "ns-1": {}, }, - providedAPIs: make(APISet), + providedAPIs: make(cache.APISet), }, }, { @@ -130,7 +131,7 @@ func TestNewOperatorGroup(t *testing.T) { "ns": {}, "ns-1": {}, }, - providedAPIs: APISet{ + providedAPIs: cache.APISet{ opregistry.APIKey{Group: "mammals.com", Version: "v1alpha1", Kind: "Moose"}: {}, }, }, @@ -145,7 +146,7 @@ func TestNewOperatorGroup(t *testing.T) { "ns": {}, "ns-1": {}, }, - providedAPIs: APISet{ + providedAPIs: cache.APISet{ opregistry.APIKey{Group: "birds.com", Version: "v1alpha1", Kind: "Goose"}: {}, opregistry.APIKey{Group: "mammals.com", Version: "v1alpha1", Kind: "Moose"}: {}, }, @@ -804,21 +805,21 @@ func TestGroupIntersection(t *testing.T) { func apiIntersectionReconcilerSuite(t *testing.T, reconciler APIIntersectionReconciler) { tests := []struct { name string - add APISet + add cache.APISet group OperatorGroupSurface otherGroups []OperatorGroupSurface want APIReconciliationResult }{ { name: "Empty/NoAPIConflict", - add: make(APISet), + add: make(cache.APISet), group: buildOperatorGroup("ns", "g1", []string{"ns"}, nil), otherGroups: nil, want: NoAPIConflict, }, { name: "NoNamespaceIntersection/APIIntersection/NoAPIConflict", - add: APISet{ + add: cache.APISet{ opregistry.APIKey{Group: "birds.com", Version: "v1alpha1", Kind: "Goose"}: {}, }, group: buildOperatorGroup("ns", "g1", []string{"ns-1"}, []string{"Goose.v1alpha1.birds.com"}), @@ -829,7 +830,7 @@ func apiIntersectionReconcilerSuite(t *testing.T, reconciler APIIntersectionReco }, { name: "NamespaceIntersection/NoAPIIntersection/NoAPIConflict", - add: APISet{ + add: cache.APISet{ opregistry.APIKey{Group: "birds.com", Version: "v1alpha1", Kind: "Goose"}: {}, }, group: buildOperatorGroup("ns", "g1", []string{"ns-1"}, []string{"Goose.v1alpha1.birds.com"}), @@ -840,7 +841,7 @@ func apiIntersectionReconcilerSuite(t *testing.T, reconciler APIIntersectionReco }, { name: "MultipleNamespaceIntersections/NoAPIIntersection/NoAPIConflict", - add: APISet{ + add: cache.APISet{ opregistry.APIKey{Group: "birds.com", Version: "v1alpha1", Kind: "Goose"}: {}, }, group: buildOperatorGroup("ns", "g1", []string{"ns-1"}, []string{"Goose.v1alpha1.birds.com"}), @@ -852,7 +853,7 @@ func apiIntersectionReconcilerSuite(t *testing.T, reconciler APIIntersectionReco }, { name: "SomeNamespaceIntersection/NoAPIIntersection/NoAPIConflict", - add: APISet{ + add: cache.APISet{ opregistry.APIKey{Group: "birds.com", Version: "v1alpha1", Kind: "Goose"}: {}, opregistry.APIKey{Group: "mammals.com", Version: "v1alpha1", Kind: "Moose"}: {}, }, @@ -866,7 +867,7 @@ func apiIntersectionReconcilerSuite(t *testing.T, reconciler APIIntersectionReco }, { name: "AllNamespaceIntersection/NoAPIIntersection/NoAPIConflict", - add: APISet{ + add: cache.APISet{ opregistry.APIKey{Group: "birds.com", Version: "v1alpha1", Kind: "Goose"}: {}, }, group: buildOperatorGroup("ns", "g1", []string{""}, []string{"Goose.v1alpha1.birds.com"}), @@ -877,7 +878,7 @@ func apiIntersectionReconcilerSuite(t *testing.T, reconciler APIIntersectionReco }, { name: "AllNamespaceIntersectionOnOther/NoAPIIntersection/NoAPIConflict", - add: APISet{ + add: cache.APISet{ opregistry.APIKey{Group: "birds.com", Version: "v1alpha1", Kind: "Goose"}: {}, }, group: buildOperatorGroup("ns", "g1", []string{"ns-1"}, []string{"Goose.v1alpha1.birds.com"}), @@ -888,7 +889,7 @@ func apiIntersectionReconcilerSuite(t *testing.T, reconciler APIIntersectionReco }, { name: "AllNamespaceInstersectionOnOther/NoAPIIntersection/NoAPIConflict", - add: APISet{ + add: cache.APISet{ opregistry.APIKey{Group: "birds.com", Version: "v1alpha1", Kind: "Goose"}: {}, }, group: buildOperatorGroup("ns", "g1", []string{""}, []string{"Goose.v1alpha1.birds.com"}), @@ -899,7 +900,7 @@ func apiIntersectionReconcilerSuite(t *testing.T, reconciler APIIntersectionReco }, { name: "NamespaceIntersection/NoAPIIntersection/NoAPIConflict", - add: APISet{ + add: cache.APISet{ opregistry.APIKey{Group: "birds.com", Version: "v1alpha1", Kind: "Goose"}: {}, }, group: buildOperatorGroup("ns", "g1", []string{"ns-1"}, []string{"Goose.v1alpha1.birds.com"}), @@ -910,7 +911,7 @@ func apiIntersectionReconcilerSuite(t *testing.T, reconciler APIIntersectionReco }, { name: "NamespaceIntersection/APIIntersection/APIConflict", - add: APISet{ + add: cache.APISet{ opregistry.APIKey{Group: "birds.com", Version: "v1alpha1", Kind: "Goose"}: {}, }, group: buildOperatorGroup("ns", "g1", []string{"ns-1"}, nil), @@ -921,7 +922,7 @@ func apiIntersectionReconcilerSuite(t *testing.T, reconciler APIIntersectionReco }, { name: "AllNamespaceIntersection/APIIntersection/APIConflict", - add: APISet{ + add: cache.APISet{ opregistry.APIKey{Group: "birds.com", Version: "v1alpha1", Kind: "Goose"}: {}, }, group: buildOperatorGroup("ns", "g1", []string{""}, nil), @@ -932,7 +933,7 @@ func apiIntersectionReconcilerSuite(t *testing.T, reconciler APIIntersectionReco }, { name: "AllNamespaceIntersectionOnOther/APIIntersection/APIConflict", - add: APISet{ + add: cache.APISet{ opregistry.APIKey{Group: "birds.com", Version: "v1alpha1", Kind: "Goose"}: {}, }, group: buildOperatorGroup("ns", "g1", []string{"ns-1"}, nil), @@ -943,7 +944,7 @@ func apiIntersectionReconcilerSuite(t *testing.T, reconciler APIIntersectionReco }, { name: "AllNamespaceIntersectionOnBoth/APIIntersection/APIConflict", - add: APISet{ + add: cache.APISet{ opregistry.APIKey{Group: "birds.com", Version: "v1alpha1", Kind: "Goose"}: {}, }, group: buildOperatorGroup("ns", "g1", []string{""}, nil), @@ -954,7 +955,7 @@ func apiIntersectionReconcilerSuite(t *testing.T, reconciler APIIntersectionReco }, { name: "NamespaceIntersection/SomeAPIIntersection/APIConflict", - add: APISet{ + add: cache.APISet{ opregistry.APIKey{Group: "birds.com", Version: "v1alpha1", Kind: "Goose"}: {}, }, group: buildOperatorGroup("ns", "g1", []string{"ns-1"}, nil), @@ -966,7 +967,7 @@ func apiIntersectionReconcilerSuite(t *testing.T, reconciler APIIntersectionReco }, { name: "NamespaceIntersectionOnOperatorNamespace/SomeAPIIntersection/APIConflict", - add: APISet{ + add: cache.APISet{ opregistry.APIKey{Group: "birds.com", Version: "v1alpha1", Kind: "Goose"}: {}, }, group: buildOperatorGroup("ns", "g1", []string{"ns-1"}, nil), @@ -978,7 +979,7 @@ func apiIntersectionReconcilerSuite(t *testing.T, reconciler APIIntersectionReco { name: "NoNamespaceIntersection/NoAPIIntersection/AddAPIs", - add: APISet{ + add: cache.APISet{ opregistry.APIKey{Group: "birds.com", Version: "v1alpha1", Kind: "Goose"}: {}, }, group: buildOperatorGroup("ns", "g1", []string{"ns-1"}, nil), @@ -989,7 +990,7 @@ func apiIntersectionReconcilerSuite(t *testing.T, reconciler APIIntersectionReco }, { name: "NamespaceIntersection/NoAPIIntersection/AddAPIs", - add: APISet{ + add: cache.APISet{ opregistry.APIKey{Group: "birds.com", Version: "v1alpha1", Kind: "Goose"}: {}, }, group: buildOperatorGroup("ns", "g1", []string{"ns-1"}, nil), @@ -1000,7 +1001,7 @@ func apiIntersectionReconcilerSuite(t *testing.T, reconciler APIIntersectionReco }, { name: "OperatorNamespaceIntersection/NoAPIIntersection/AddAPIs", - add: APISet{ + add: cache.APISet{ opregistry.APIKey{Group: "birds.com", Version: "v1alpha1", Kind: "Goose"}: {}, }, group: buildOperatorGroup("ns", "g1", []string{"ns-1"}, nil), @@ -1011,7 +1012,7 @@ func apiIntersectionReconcilerSuite(t *testing.T, reconciler APIIntersectionReco }, { name: "AllNamespaceIntersection/NoAPIIntersection/AddAPIs", - add: APISet{ + add: cache.APISet{ opregistry.APIKey{Group: "birds.com", Version: "v1alpha1", Kind: "Goose"}: {}, }, group: buildOperatorGroup("ns", "g1", []string{""}, nil), @@ -1023,7 +1024,7 @@ func apiIntersectionReconcilerSuite(t *testing.T, reconciler APIIntersectionReco }, { name: "AllNamespaceIntersectionOnOthers/NoAPIIntersection/AddAPIs", - add: APISet{ + add: cache.APISet{ opregistry.APIKey{Group: "birds.com", Version: "v1alpha1", Kind: "Goose"}: {}, }, group: buildOperatorGroup("ns", "g1", []string{"ns-1"}, nil), @@ -1035,7 +1036,7 @@ func apiIntersectionReconcilerSuite(t *testing.T, reconciler APIIntersectionReco }, { name: "AllNamespaceIntersectionOnOthers/NoAPIIntersection/AddAPIs/PrexistingAddition", - add: APISet{ + add: cache.APISet{ opregistry.APIKey{Group: "birds.com", Version: "v1alpha1", Kind: "Goose"}: {}, opregistry.APIKey{Group: "mammals.com", Version: "v1alpha1", Kind: "Cow"}: {}, }, @@ -1048,7 +1049,7 @@ func apiIntersectionReconcilerSuite(t *testing.T, reconciler APIIntersectionReco }, { name: "NamespaceInstersection/APIIntersection/RemoveAPIs", - add: APISet{ + add: cache.APISet{ opregistry.APIKey{Group: "birds.com", Version: "v1alpha1", Kind: "Goose"}: {}, }, group: buildOperatorGroup("ns", "g1", []string{"ns-1"}, []string{"Goose.v1alpha1.birds.com"}), @@ -1059,7 +1060,7 @@ func apiIntersectionReconcilerSuite(t *testing.T, reconciler APIIntersectionReco }, { name: "AllNamespaceInstersection/APIIntersection/RemoveAPIs", - add: APISet{ + add: cache.APISet{ opregistry.APIKey{Group: "birds.com", Version: "v1alpha1", Kind: "Goose"}: {}, }, group: buildOperatorGroup("ns", "g1", []string{""}, []string{"Goose.v1alpha1.birds.com"}), @@ -1070,7 +1071,7 @@ func apiIntersectionReconcilerSuite(t *testing.T, reconciler APIIntersectionReco }, { name: "AllNamespaceInstersectionOnOther/APIIntersection/RemoveAPIs", - add: APISet{ + add: cache.APISet{ opregistry.APIKey{Group: "birds.com", Version: "v1alpha1", Kind: "Goose"}: {}, }, group: buildOperatorGroup("ns", "g1", []string{""}, []string{"Goose.v1alpha1.birds.com"}), @@ -1081,7 +1082,7 @@ func apiIntersectionReconcilerSuite(t *testing.T, reconciler APIIntersectionReco }, { name: "MultipleNamespaceIntersections/APIIntersection/RemoveAPIs", - add: APISet{ + add: cache.APISet{ opregistry.APIKey{Group: "birds.com", Version: "v1alpha1", Kind: "Goose"}: {}, }, group: buildOperatorGroup("ns", "g1", []string{"ns-1"}, []string{"Goose.v1alpha1.birds.com"}), @@ -1093,7 +1094,7 @@ func apiIntersectionReconcilerSuite(t *testing.T, reconciler APIIntersectionReco }, { name: "SomeNamespaceIntersection/APIIntersection/RemoveAPIs", - add: APISet{ + add: cache.APISet{ opregistry.APIKey{Group: "birds.com", Version: "v1alpha1", Kind: "Goose"}: {}, opregistry.APIKey{Group: "mammals.com", Version: "v1alpha1", Kind: "Moose"}: {}, }, diff --git a/pkg/controller/registry/resolver/installabletypes.go b/pkg/controller/registry/resolver/installabletypes.go index a76361d3f2..94302d53ee 100644 --- a/pkg/controller/registry/resolver/installabletypes.go +++ b/pkg/controller/registry/resolver/installabletypes.go @@ -5,6 +5,7 @@ import ( "strings" "github.com/operator-framework/operator-lifecycle-manager/pkg/controller/registry" + "github.com/operator-framework/operator-lifecycle-manager/pkg/controller/registry/resolver/cache" "github.com/operator-framework/operator-lifecycle-manager/pkg/controller/registry/resolver/solver" operatorregistry "github.com/operator-framework/operator-registry/pkg/registry" ) @@ -55,14 +56,13 @@ func bundleId(bundle, channel string, catalog registry.CatalogKey) solver.Identi return solver.IdentifierFromString(fmt.Sprintf("%s/%s/%s", catalog.String(), channel, bundle)) } -func NewBundleInstallableFromOperator(o *Operator) (BundleInstallable, error) { - src := o.SourceInfo() - if src == nil { - return BundleInstallable{}, fmt.Errorf("unable to resolve the source of bundle %s", o.Identifier()) +func NewBundleInstallableFromOperator(o *cache.Operator) (BundleInstallable, error) { + if o.SourceInfo == nil { + return BundleInstallable{}, fmt.Errorf("unable to resolve the source of bundle %s", o.Name) } - id := bundleId(o.Identifier(), o.Channel(), src.Catalog) + id := bundleId(o.Identifier(), o.Channel(), o.SourceInfo.Catalog) var constraints []solver.Constraint - if src.Catalog.Virtual() && src.Subscription == nil { + if o.SourceInfo.Catalog.Virtual() && o.SourceInfo.Subscription == nil { // CSVs already associated with a Subscription // may be replaced, but freestanding CSVs must // appear in any solution. @@ -71,7 +71,7 @@ func NewBundleInstallableFromOperator(o *Operator) (BundleInstallable, error) { fmt.Sprintf("clusterserviceversion %s exists and is not referenced by a subscription", o.Identifier()), )) } - for _, p := range o.bundle.GetProperties() { + for _, p := range o.Properties { if p.GetType() == operatorregistry.DeprecatedType { constraints = append(constraints, PrettyConstraint( solver.Prohibited(), diff --git a/pkg/controller/registry/resolver/labeler.go b/pkg/controller/registry/resolver/labeler.go index cf408ef00d..9b10eb2d6d 100644 --- a/pkg/controller/registry/resolver/labeler.go +++ b/pkg/controller/registry/resolver/labeler.go @@ -1,6 +1,7 @@ package resolver import ( + "github.com/operator-framework/operator-lifecycle-manager/pkg/controller/registry/resolver/cache" "github.com/operator-framework/operator-registry/pkg/registry" extv1beta1 "k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1beta1" "k8s.io/apimachinery/pkg/labels" @@ -15,7 +16,7 @@ const ( // Concrete types other than OperatorSurface and CustomResource definition no-op. func LabelSetsFor(obj interface{}) ([]labels.Set, error) { switch v := obj.(type) { - case OperatorSurface: + case cache.OperatorSurface: return labelSetsForOperatorSurface(v) case *extv1beta1.CustomResourceDefinition: return labelSetsForCRD(v) @@ -24,17 +25,17 @@ func LabelSetsFor(obj interface{}) ([]labels.Set, error) { } } -func labelSetsForOperatorSurface(surface OperatorSurface) ([]labels.Set, error) { +func labelSetsForOperatorSurface(surface cache.OperatorSurface) ([]labels.Set, error) { labelSet := labels.Set{} - for key := range surface.ProvidedAPIs().StripPlural() { - hash, err := APIKeyToGVKHash(key) + for key := range surface.GetProvidedAPIs().StripPlural() { + hash, err := cache.APIKeyToGVKHash(key) if err != nil { return nil, err } labelSet[APILabelKeyPrefix+hash] = "provided" } - for key := range surface.RequiredAPIs().StripPlural() { - hash, err := APIKeyToGVKHash(key) + for key := range surface.GetRequiredAPIs().StripPlural() { + hash, err := cache.APIKeyToGVKHash(key) if err != nil { return nil, err } @@ -52,7 +53,7 @@ func labelSetsForCRD(crd *extv1beta1.CustomResourceDefinition) ([]labels.Set, er // Add label sets for each version for _, version := range crd.Spec.Versions { - hash, err := APIKeyToGVKHash(registry.APIKey{ + hash, err := cache.APIKeyToGVKHash(registry.APIKey{ Group: crd.Spec.Group, Version: version.Name, Kind: crd.Spec.Names.Kind, diff --git a/pkg/controller/registry/resolver/labeler_test.go b/pkg/controller/registry/resolver/labeler_test.go index 2c26a7dece..caf16f972e 100644 --- a/pkg/controller/registry/resolver/labeler_test.go +++ b/pkg/controller/registry/resolver/labeler_test.go @@ -3,6 +3,7 @@ package resolver import ( "testing" + "github.com/operator-framework/operator-lifecycle-manager/pkg/controller/registry/resolver/cache" opregistry "github.com/operator-framework/operator-registry/pkg/registry" "github.com/stretchr/testify/require" "k8s.io/apimachinery/pkg/labels" @@ -43,8 +44,8 @@ func TestLabelSetsFor(t *testing.T) { }, { name: "OperatorSurface/Provided", - obj: &Operator{ - providedAPIs: map[opregistry.APIKey]struct{}{ + obj: &cache.Operator{ + ProvidedAPIs: map[opregistry.APIKey]struct{}{ opregistry.APIKey{Group: "ghouls", Version: "v1alpha1", Kind: "Ghost", Plural: "Ghosts"}: {}, }, }, @@ -56,11 +57,11 @@ func TestLabelSetsFor(t *testing.T) { }, { name: "OperatorSurface/ProvidedAndRequired", - obj: &Operator{ - providedAPIs: map[opregistry.APIKey]struct{}{ + obj: &cache.Operator{ + ProvidedAPIs: map[opregistry.APIKey]struct{}{ opregistry.APIKey{Group: "ghouls", Version: "v1alpha1", Kind: "Ghost", Plural: "Ghosts"}: {}, }, - requiredAPIs: map[opregistry.APIKey]struct{}{ + RequiredAPIs: map[opregistry.APIKey]struct{}{ opregistry.APIKey{Group: "ghouls", Version: "v1alpha1", Kind: "Goblin", Plural: "Goblins"}: {}, }, }, diff --git a/pkg/controller/registry/resolver/resolver.go b/pkg/controller/registry/resolver/resolver.go index 96201146a7..a8eeaf51bf 100644 --- a/pkg/controller/registry/resolver/resolver.go +++ b/pkg/controller/registry/resolver/resolver.go @@ -14,6 +14,7 @@ import ( "github.com/operator-framework/api/pkg/operators/v1alpha1" v1alpha1listers "github.com/operator-framework/operator-lifecycle-manager/pkg/api/client/listers/operators/v1alpha1" "github.com/operator-framework/operator-lifecycle-manager/pkg/controller/registry" + "github.com/operator-framework/operator-lifecycle-manager/pkg/controller/registry/resolver/cache" "github.com/operator-framework/operator-lifecycle-manager/pkg/controller/registry/resolver/projection" "github.com/operator-framework/operator-lifecycle-manager/pkg/controller/registry/resolver/solver" "github.com/operator-framework/operator-registry/pkg/api" @@ -21,17 +22,17 @@ import ( ) type OperatorResolver interface { - SolveOperators(csvs []*v1alpha1.ClusterServiceVersion, subs []*v1alpha1.Subscription, add map[OperatorSourceInfo]struct{}) (OperatorSet, error) + SolveOperators(csvs []*v1alpha1.ClusterServiceVersion, subs []*v1alpha1.Subscription, add map[cache.OperatorSourceInfo]struct{}) (cache.OperatorSet, error) } type SatResolver struct { - cache OperatorCacheProvider + cache cache.OperatorCacheProvider log logrus.FieldLogger } -func NewDefaultSatResolver(rcp RegistryClientProvider, catsrcLister v1alpha1listers.CatalogSourceLister, log logrus.FieldLogger) *SatResolver { +func NewDefaultSatResolver(rcp cache.RegistryClientProvider, catsrcLister v1alpha1listers.CatalogSourceLister, log logrus.FieldLogger) *SatResolver { return &SatResolver{ - cache: NewOperatorCache(rcp, log, catsrcLister), + cache: cache.NewOperatorCache(rcp, log, catsrcLister), log: log, } } @@ -46,11 +47,11 @@ func (w *debugWriter) Write(b []byte) (int, error) { return n, nil } -func (r *SatResolver) SolveOperators(namespaces []string, csvs []*v1alpha1.ClusterServiceVersion, subs []*v1alpha1.Subscription) (OperatorSet, error) { +func (r *SatResolver) SolveOperators(namespaces []string, csvs []*v1alpha1.ClusterServiceVersion, subs []*v1alpha1.Subscription) (cache.OperatorSet, error) { var errs []error installables := make(map[solver.Identifier]solver.Installable, 0) - visited := make(map[OperatorSurface]*BundleInstallable, 0) + visited := make(map[cache.OperatorSurface]*BundleInstallable, 0) // TODO: better abstraction startingCSVs := make(map[string]struct{}) @@ -73,10 +74,10 @@ func (r *SatResolver) SolveOperators(namespaces []string, csvs []*v1alpha1.Clust // build constraints for each Subscription for _, sub := range subs { // find the currently installed operator (if it exists) - var current *Operator + var current *cache.Operator for _, csv := range csvs { if csv.Name == sub.Status.InstalledCSV { - op, err := NewOperatorFromV1Alpha1CSV(csv) + op, err := cache.NewOperatorFromV1Alpha1CSV(csv) if err != nil { return nil, err } @@ -140,7 +141,7 @@ func (r *SatResolver) SolveOperators(namespaces []string, csvs []*v1alpha1.Clust } } - operators := make(map[string]OperatorSurface, 0) + operators := make(map[string]cache.OperatorSurface, 0) for _, installableOperator := range operatorInstallables { csvName, channel, catalog, err := installableOperator.BundleSourceInfo() if err != nil { @@ -148,18 +149,18 @@ func (r *SatResolver) SolveOperators(namespaces []string, csvs []*v1alpha1.Clust continue } - op, err := ExactlyOne(namespacedCache.Catalog(catalog).Find(CSVNamePredicate(csvName), ChannelPredicate(channel))) + op, err := cache.ExactlyOne(namespacedCache.Catalog(catalog).Find(cache.CSVNamePredicate(csvName), cache.ChannelPredicate(channel))) if err != nil { errs = append(errs, err) continue } if len(installableOperator.Replaces) > 0 { - op.replaces = installableOperator.Replaces + op.Replaces = installableOperator.Replaces // TODO: Don't mutate object from cache! } // lookup if this installable came from a starting CSV if _, ok := startingCSVs[csvName]; ok { - op.sourceInfo.StartingCSV = csvName + op.SourceInfo.StartingCSV = csvName // TODO: Don't mutate object from cache! } operators[csvName] = op @@ -172,8 +173,8 @@ func (r *SatResolver) SolveOperators(namespaces []string, csvs []*v1alpha1.Clust return operators, nil } -func (r *SatResolver) getSubscriptionInstallables(sub *v1alpha1.Subscription, current *Operator, namespacedCache MultiCatalogOperatorFinder, visited map[OperatorSurface]*BundleInstallable) (map[solver.Identifier]solver.Installable, error) { - var cachePredicates, channelPredicates []OperatorPredicate +func (r *SatResolver) getSubscriptionInstallables(sub *v1alpha1.Subscription, current *cache.Operator, namespacedCache cache.MultiCatalogOperatorFinder, visited map[cache.OperatorSurface]*BundleInstallable) (map[solver.Identifier]solver.Installable, error) { + var cachePredicates, channelPredicates []cache.OperatorPredicate installables := make(map[solver.Identifier]solver.Installable, 0) catalog := registry.CatalogKey{ @@ -181,24 +182,24 @@ func (r *SatResolver) getSubscriptionInstallables(sub *v1alpha1.Subscription, cu Namespace: sub.Spec.CatalogSourceNamespace, } - var bundles []*Operator + var bundles []*cache.Operator { var nall, npkg, nch, ncsv int - csvPredicate := True() + csvPredicate := cache.True() if current != nil { // if we found an existing installed operator, we should filter the channel by operators that can replace it - channelPredicates = append(channelPredicates, Or(SkipRangeIncludesPredicate(*current.Version()), ReplacesPredicate(current.Identifier()))) + channelPredicates = append(channelPredicates, cache.Or(cache.SkipRangeIncludesPredicate(*current.Version), cache.ReplacesPredicate(current.Identifier()))) } else if sub.Spec.StartingCSV != "" { // if no operator is installed and we have a startingCSV, filter for it - csvPredicate = CSVNamePredicate(sub.Spec.StartingCSV) + csvPredicate = cache.CSVNamePredicate(sub.Spec.StartingCSV) } - cachePredicates = append(cachePredicates, And( - CountingPredicate(True(), &nall), - CountingPredicate(PkgPredicate(sub.Spec.Package), &npkg), - CountingPredicate(ChannelPredicate(sub.Spec.Channel), &nch), - CountingPredicate(csvPredicate, &ncsv), + cachePredicates = append(cachePredicates, cache.And( + cache.CountingPredicate(cache.True(), &nall), + cache.CountingPredicate(cache.PkgPredicate(sub.Spec.Package), &npkg), + cache.CountingPredicate(cache.ChannelPredicate(sub.Spec.Channel), &nch), + cache.CountingPredicate(csvPredicate, &ncsv), )) bundles = namespacedCache.Catalog(catalog).Find(cachePredicates...) @@ -223,23 +224,23 @@ func (r *SatResolver) getSubscriptionInstallables(sub *v1alpha1.Subscription, cu // bundles in the default channel appear first, then lexicographically order by channel name sort.SliceStable(bundles, func(i, j int) bool { var idef bool - if isrc := bundles[i].SourceInfo(); isrc != nil { + if isrc := bundles[i].SourceInfo; isrc != nil { idef = isrc.DefaultChannel } var jdef bool - if jsrc := bundles[j].SourceInfo(); jsrc != nil { + if jsrc := bundles[j].SourceInfo; jsrc != nil { jdef = jsrc.DefaultChannel } if idef == jdef { - return bundles[i].bundle.ChannelName < bundles[j].bundle.ChannelName + return bundles[i].Bundle.ChannelName < bundles[j].Bundle.ChannelName } return idef }) - var sortedBundles []*Operator + var sortedBundles []*cache.Operator lastChannel, lastIndex := "", 0 for i := 0; i <= len(bundles); i++ { - if i != len(bundles) && bundles[i].bundle.ChannelName == lastChannel { + if i != len(bundles) && bundles[i].Bundle.ChannelName == lastChannel { continue } channel, err := sortChannel(bundles[lastIndex:i]) @@ -249,14 +250,14 @@ func (r *SatResolver) getSubscriptionInstallables(sub *v1alpha1.Subscription, cu sortedBundles = append(sortedBundles, channel...) if i != len(bundles) { - lastChannel = bundles[i].bundle.ChannelName + lastChannel = bundles[i].Bundle.ChannelName lastIndex = i } } candidates := make([]*BundleInstallable, 0) - for _, o := range Filter(sortedBundles, channelPredicates...) { - predicates := append(cachePredicates, CSVNamePredicate(o.Identifier())) + for _, o := range cache.Filter(sortedBundles, channelPredicates...) { + predicates := append(cachePredicates, cache.CSVNamePredicate(o.Identifier())) stack := namespacedCache.Catalog(catalog).Find(predicates...) id, installable, err := r.getBundleInstallables(catalog, stack, namespacedCache, visited) if err != nil { @@ -302,12 +303,12 @@ func (r *SatResolver) getSubscriptionInstallables(sub *v1alpha1.Subscription, cu return installables, nil } -func (r *SatResolver) getBundleInstallables(catalog registry.CatalogKey, bundleStack []*Operator, namespacedCache MultiCatalogOperatorFinder, visited map[OperatorSurface]*BundleInstallable) (map[solver.Identifier]struct{}, map[solver.Identifier]*BundleInstallable, error) { +func (r *SatResolver) getBundleInstallables(catalog registry.CatalogKey, bundleStack []*cache.Operator, namespacedCache cache.MultiCatalogOperatorFinder, visited map[cache.OperatorSurface]*BundleInstallable) (map[solver.Identifier]struct{}, map[solver.Identifier]*BundleInstallable, error) { errs := make([]error, 0) installables := make(map[solver.Identifier]*BundleInstallable, 0) // all installables, including dependencies // track the first layer of installable ids - var initial = make(map[*Operator]struct{}) + var initial = make(map[*cache.Operator]struct{}) for _, o := range bundleStack { initial[o] = struct{}{} } @@ -340,15 +341,15 @@ func (r *SatResolver) getBundleInstallables(catalog registry.CatalogKey, bundleS } for _, d := range dependencyPredicates { - sourcePredicate := False() + sourcePredicate := cache.False() // Build a filter matching all (catalog, // package, channel) combinations that contain // at least one candidate bundle, even if only // a subset of those bundles actually satisfy // the dependency. - sources := map[OperatorSourceInfo]struct{}{} + sources := map[cache.OperatorSourceInfo]struct{}{} for _, b := range namespacedCache.Find(d) { - si := b.SourceInfo() + si := b.SourceInfo if _, ok := sources[*si]; ok { // Predicate already covers this source. @@ -357,19 +358,19 @@ func (r *SatResolver) getBundleInstallables(catalog registry.CatalogKey, bundleS sources[*si] = struct{}{} if si.Catalog.Virtual() { - sourcePredicate = Or(sourcePredicate, And( - CSVNamePredicate(b.Identifier()), - CatalogPredicate(si.Catalog), + sourcePredicate = cache.Or(sourcePredicate, cache.And( + cache.CSVNamePredicate(b.Identifier()), + cache.CatalogPredicate(si.Catalog), )) } else { - sourcePredicate = Or(sourcePredicate, And( - PkgPredicate(si.Package), - ChannelPredicate(si.Channel), - CatalogPredicate(si.Catalog), + sourcePredicate = cache.Or(sourcePredicate, cache.And( + cache.PkgPredicate(si.Package), + cache.ChannelPredicate(si.Channel), + cache.CatalogPredicate(si.Catalog), )) } } - sortedBundles, err := r.sortBundles(namespacedCache.FindPreferred(&bundle.sourceInfo.Catalog, sourcePredicate)) + sortedBundles, err := r.sortBundles(namespacedCache.FindPreferred(&bundle.SourceInfo.Catalog, sourcePredicate)) if err != nil { errs = append(errs, err) continue @@ -378,7 +379,7 @@ func (r *SatResolver) getBundleInstallables(catalog registry.CatalogKey, bundleS // The dependency predicate is applied here // (after sorting) to remove all bundles that // don't satisfy the dependency. - for _, b := range Filter(sortedBundles, d) { + for _, b := range cache.Filter(sortedBundles, d) { i, err := NewBundleInstallableFromOperator(b) if err != nil { errs = append(errs, err) @@ -390,7 +391,7 @@ func (r *SatResolver) getBundleInstallables(catalog registry.CatalogKey, bundleS } bundleInstallable.AddConstraint(PrettyConstraint( solver.Dependency(bundleDependencies...), - fmt.Sprintf("bundle %s requires an operator %s", bundle.name, d.String()), + fmt.Sprintf("bundle %s requires an operator %s", bundle.Name, d.String()), )) } @@ -421,7 +422,7 @@ func (r *SatResolver) inferProperties(csv *v1alpha1.ClusterServiceVersion, subs // package against catalog contents, updates to the // Subscription spec could result in a bad package // inference. - for _, entry := range r.cache.Namespaced(sub.Namespace).Catalog(registry.CatalogKey{Namespace: sub.Spec.CatalogSourceNamespace, Name: sub.Spec.CatalogSource}).Find(And(CSVNamePredicate(csv.Name), PkgPredicate(sub.Spec.Package))) { + for _, entry := range r.cache.Namespaced(sub.Namespace).Catalog(registry.CatalogKey{Namespace: sub.Spec.CatalogSourceNamespace, Name: sub.Spec.CatalogSource}).Find(cache.And(cache.CSVNamePredicate(csv.Name), cache.PkgPredicate(sub.Spec.Package))) { if pkg := entry.Package(); pkg != "" { packages[pkg] = struct{}{} } @@ -454,7 +455,7 @@ func (r *SatResolver) inferProperties(csv *v1alpha1.ClusterServiceVersion, subs return properties, nil } -func (r *SatResolver) newSnapshotForNamespace(namespace string, subs []*v1alpha1.Subscription, csvs []*v1alpha1.ClusterServiceVersion) (*CatalogSnapshot, error) { +func (r *SatResolver) newSnapshotForNamespace(namespace string, subs []*v1alpha1.Subscription, csvs []*v1alpha1.ClusterServiceVersion) (*cache.CatalogSnapshot, error) { existingOperatorCatalog := registry.NewVirtualCatalogKey(namespace) // build a catalog snapshot of CSVs without subscriptions csvSubscriptions := make(map[*v1alpha1.ClusterServiceVersion]*v1alpha1.Subscription) @@ -467,9 +468,9 @@ func (r *SatResolver) newSnapshotForNamespace(namespace string, subs []*v1alpha1 } } var csvsMissingProperties []*v1alpha1.ClusterServiceVersion - standaloneOperators := make([]*Operator, 0) + standaloneOperators := make([]*cache.Operator, 0) for _, csv := range csvs { - op, err := NewOperatorFromV1Alpha1CSV(csv) + op, err := cache.NewOperatorFromV1Alpha1CSV(csv) if err != nil { return nil, err } @@ -479,20 +480,20 @@ func (r *SatResolver) newSnapshotForNamespace(namespace string, subs []*v1alpha1 if inferred, err := r.inferProperties(csv, subs); err != nil { r.log.Warnf("unable to infer properties for csv %q: %w", csv.Name, err) } else { - op.properties = append(op.properties, inferred...) + op.Properties = append(op.Properties, inferred...) } } else if props, err := projection.PropertyListFromPropertiesAnnotation(anno); err != nil { return nil, fmt.Errorf("failed to retrieve properties of csv %q: %w", csv.GetName(), err) } else { - op.properties = props + op.Properties = props } - op.sourceInfo = &OperatorSourceInfo{ + op.SourceInfo = &cache.OperatorSourceInfo{ Catalog: existingOperatorCatalog, Subscription: csvSubscriptions[csv], } // Try to determine source package name from properties and add to SourceInfo. - for _, p := range op.properties { + for _, p := range op.Properties { if p.Type != opregistry.PackageType { continue } @@ -502,7 +503,7 @@ func (r *SatResolver) newSnapshotForNamespace(namespace string, subs []*v1alpha1 r.log.Warnf("failed to unmarshal package property of csv %q: %w", csv.Name, err) continue } - op.sourceInfo.Package = pp.PackageName + op.SourceInfo.Package = pp.PackageName } standaloneOperators = append(standaloneOperators, op) @@ -516,10 +517,10 @@ func (r *SatResolver) newSnapshotForNamespace(namespace string, subs []*v1alpha1 r.log.Infof("considered csvs without properties annotation during resolution: %v", names) } - return NewRunningOperatorSnapshot(r.log, existingOperatorCatalog, standaloneOperators), nil + return cache.NewRunningOperatorSnapshot(r.log, existingOperatorCatalog, standaloneOperators), nil } -func (r *SatResolver) addInvariants(namespacedCache MultiCatalogOperatorFinder, installables map[solver.Identifier]solver.Installable) { +func (r *SatResolver) addInvariants(namespacedCache cache.MultiCatalogOperatorFinder, installables map[solver.Identifier]solver.Installable) { // no two operators may provide the same GVK or Package in a namespace gvkConflictToInstallable := make(map[opregistry.GVKProperty][]solver.Identifier) packageConflictToInstallable := make(map[string][]solver.Identifier) @@ -533,13 +534,13 @@ func (r *SatResolver) addInvariants(namespacedCache MultiCatalogOperatorFinder, continue } - op, err := ExactlyOne(namespacedCache.Catalog(catalog).Find(CSVNamePredicate(csvName), ChannelPredicate(channel))) + op, err := cache.ExactlyOne(namespacedCache.Catalog(catalog).Find(cache.CSVNamePredicate(csvName), cache.ChannelPredicate(channel))) if err != nil { continue } // cannot provide the same GVK - for _, p := range op.Properties() { + for _, p := range op.Properties { if p.Type != opregistry.GVKType { continue } @@ -552,7 +553,7 @@ func (r *SatResolver) addInvariants(namespacedCache MultiCatalogOperatorFinder, } // cannot have the same package - for _, p := range op.Properties() { + for _, p := range op.Properties { if p.Type != opregistry.PackageType { continue } @@ -576,7 +577,7 @@ func (r *SatResolver) addInvariants(namespacedCache MultiCatalogOperatorFinder, } } -func (r *SatResolver) sortBundles(bundles []*Operator) ([]*Operator, error) { +func (r *SatResolver) sortBundles(bundles []*cache.Operator) ([]*cache.Operator, error) { // assume bundles have been passed in sorted by catalog already catalogOrder := make([]registry.CatalogKey, 0) @@ -588,22 +589,22 @@ func (r *SatResolver) sortBundles(bundles []*Operator) ([]*Operator, error) { channelOrder := make(map[registry.CatalogKey][]PackageChannel) // partition by catalog -> channel -> bundle - partitionedBundles := map[registry.CatalogKey]map[PackageChannel][]*Operator{} + partitionedBundles := map[registry.CatalogKey]map[PackageChannel][]*cache.Operator{} for _, b := range bundles { pc := PackageChannel{ Package: b.Package(), Channel: b.Channel(), - DefaultChannel: b.SourceInfo().DefaultChannel, + DefaultChannel: b.SourceInfo.DefaultChannel, } - if _, ok := partitionedBundles[b.sourceInfo.Catalog]; !ok { - catalogOrder = append(catalogOrder, b.sourceInfo.Catalog) - partitionedBundles[b.sourceInfo.Catalog] = make(map[PackageChannel][]*Operator) + if _, ok := partitionedBundles[b.SourceInfo.Catalog]; !ok { + catalogOrder = append(catalogOrder, b.SourceInfo.Catalog) + partitionedBundles[b.SourceInfo.Catalog] = make(map[PackageChannel][]*cache.Operator) } - if _, ok := partitionedBundles[b.sourceInfo.Catalog][pc]; !ok { - channelOrder[b.sourceInfo.Catalog] = append(channelOrder[b.sourceInfo.Catalog], pc) - partitionedBundles[b.sourceInfo.Catalog][pc] = make([]*Operator, 0) + if _, ok := partitionedBundles[b.SourceInfo.Catalog][pc]; !ok { + channelOrder[b.SourceInfo.Catalog] = append(channelOrder[b.SourceInfo.Catalog], pc) + partitionedBundles[b.SourceInfo.Catalog][pc] = make([]*cache.Operator, 0) } - partitionedBundles[b.sourceInfo.Catalog][pc] = append(partitionedBundles[b.sourceInfo.Catalog][pc], b) + partitionedBundles[b.SourceInfo.Catalog][pc] = append(partitionedBundles[b.SourceInfo.Catalog][pc], b) } for catalog := range partitionedBundles { @@ -625,7 +626,7 @@ func (r *SatResolver) sortBundles(bundles []*Operator) ([]*Operator, error) { partitionedBundles[catalog][channel] = sorted } } - all := make([]*Operator, 0) + all := make([]*cache.Operator, 0) for _, catalog := range catalogOrder { for _, channel := range channelOrder[catalog] { all = append(all, partitionedBundles[catalog][channel]...) @@ -636,7 +637,7 @@ func (r *SatResolver) sortBundles(bundles []*Operator) ([]*Operator, error) { // Sorts bundle in a channel by replaces. All entries in the argument // are assumed to have the same Package and Channel. -func sortChannel(bundles []*Operator) ([]*Operator, error) { +func sortChannel(bundles []*cache.Operator) ([]*cache.Operator, error) { if len(bundles) < 1 { return bundles, nil } @@ -644,25 +645,25 @@ func sortChannel(bundles []*Operator) ([]*Operator, error) { packageName := bundles[0].Package() channelName := bundles[0].Channel() - bundleLookup := map[string]*Operator{} + bundleLookup := map[string]*cache.Operator{} // if a replaces b, then replacedBy[b] = a - replacedBy := map[*Operator]*Operator{} - replaces := map[*Operator]*Operator{} - skipped := map[string]*Operator{} + replacedBy := map[*cache.Operator]*cache.Operator{} + replaces := map[*cache.Operator]*cache.Operator{} + skipped := map[string]*cache.Operator{} for _, b := range bundles { bundleLookup[b.Identifier()] = b } for _, b := range bundles { - if b.replaces != "" { - if r, ok := bundleLookup[b.replaces]; ok { + if b.Replaces != "" { + if r, ok := bundleLookup[b.Replaces]; ok { replacedBy[r] = b replaces[b] = r } } - for _, skip := range b.skips { + for _, skip := range b.Skips { if r, ok := bundleLookup[skip]; ok { replacedBy[r] = b skipped[skip] = r @@ -672,7 +673,7 @@ func sortChannel(bundles []*Operator) ([]*Operator, error) { // a bundle without a replacement is a channel head, but if we // find more than one of those something is weird - headCandidates := []*Operator{} + headCandidates := []*cache.Operator{} for _, b := range bundles { if _, ok := replacedBy[b]; !ok { headCandidates = append(headCandidates, b) @@ -682,10 +683,10 @@ func sortChannel(bundles []*Operator) ([]*Operator, error) { return nil, fmt.Errorf("no channel heads (entries not replaced by another entry) found in channel %q of package %q", channelName, packageName) } - var chains [][]*Operator + var chains [][]*cache.Operator for _, head := range headCandidates { - var chain []*Operator - visited := make(map[*Operator]struct{}) + var chain []*cache.Operator + visited := make(map[*cache.Operator]struct{}) current := head for { visited[current] = struct{}{} diff --git a/pkg/controller/registry/resolver/resolver_test.go b/pkg/controller/registry/resolver/resolver_test.go index b954425930..fc9b3eb336 100644 --- a/pkg/controller/registry/resolver/resolver_test.go +++ b/pkg/controller/registry/resolver/resolver_test.go @@ -16,13 +16,14 @@ import ( "github.com/operator-framework/api/pkg/lib/version" "github.com/operator-framework/api/pkg/operators/v1alpha1" "github.com/operator-framework/operator-lifecycle-manager/pkg/controller/registry" + "github.com/operator-framework/operator-lifecycle-manager/pkg/controller/registry/resolver/cache" "github.com/operator-framework/operator-lifecycle-manager/pkg/controller/registry/resolver/solver" "github.com/operator-framework/operator-registry/pkg/api" opregistry "github.com/operator-framework/operator-registry/pkg/registry" ) func TestSolveOperators(t *testing.T) { - APISet := APISet{opregistry.APIKey{Group: "g", Version: "v", Kind: "k", Plural: "ks"}: struct{}{}} + APISet := cache.APISet{opregistry.APIKey{Group: "g", Version: "v", Kind: "k", Plural: "ks"}: struct{}{}} Provides := APISet const namespace = "test-namespace" @@ -34,11 +35,11 @@ func TestSolveOperators(t *testing.T) { newSub := newSub(namespace, "packageB", "alpha", catalog) subs := []*v1alpha1.Subscription{sub, newSub} - fakeNamespacedOperatorCache := NamespacedOperatorCache{ - snapshots: map[registry.CatalogKey]*CatalogSnapshot{ + fakeNamespacedOperatorCache := cache.NamespacedOperatorCache{ + Snapshots: map[registry.CatalogKey]*cache.CatalogSnapshot{ catalog: { - key: catalog, - operators: []*Operator{ + Key: catalog, + Operators: []*cache.Operator{ genOperator("packageA.v1", "0.0.1", "", "packageA", "alpha", catalog.Name, catalog.Namespace, nil, nil, nil, "", false), genOperator("packageB.v1", "1.0.1", "", "packageB", "alpha", catalog.Name, catalog.Namespace, nil, nil, nil, "", false), }, @@ -53,7 +54,7 @@ func TestSolveOperators(t *testing.T) { operators, err := satResolver.SolveOperators([]string{namespace}, csvs, subs) assert.NoError(t, err) - expected := OperatorSet{ + expected := cache.OperatorSet{ "packageB.v1": genOperator("packageB.v1", "1.0.1", "", "packageB", "alpha", catalog.Name, catalog.Namespace, nil, nil, nil, "", false), } require.EqualValues(t, expected, operators) @@ -66,11 +67,11 @@ func TestDisjointChannelGraph(t *testing.T) { newSub := newSub(namespace, "packageA", "alpha", catalog) subs := []*v1alpha1.Subscription{newSub} - fakeNamespacedOperatorCache := NamespacedOperatorCache{ - snapshots: map[registry.CatalogKey]*CatalogSnapshot{ + fakeNamespacedOperatorCache := cache.NamespacedOperatorCache{ + Snapshots: map[registry.CatalogKey]*cache.CatalogSnapshot{ catalog: { - key: catalog, - operators: []*Operator{ + Key: catalog, + Operators: []*cache.Operator{ genOperator("packageA.side1.v1", "0.0.1", "", "packageA", "alpha", catalog.Name, catalog.Namespace, nil, nil, nil, "", false), genOperator("packageA.side1.v2", "0.0.2", "packageA.side1.v1", "packageA", "alpha", catalog.Name, catalog.Namespace, nil, nil, nil, "", false), genOperator("packageA.side2.v1", "1.0.0", "", "packageA", "alpha", catalog.Name, catalog.Namespace, nil, nil, nil, "", false), @@ -103,11 +104,11 @@ func TestPropertiesAnnotationHonored(t *testing.T) { b := genOperator("packageB.v1", "1.0.1", "", "packageB", "alpha", "community", "olm", nil, nil, []*api.Dependency{{Type: "olm.package", Value: `{"packageName":"packageA","version":"1.0.0"}`}}, "", false) - fakeNamespacedOperatorCache := NamespacedOperatorCache{ - snapshots: map[registry.CatalogKey]*CatalogSnapshot{ + fakeNamespacedOperatorCache := cache.NamespacedOperatorCache{ + Snapshots: map[registry.CatalogKey]*cache.CatalogSnapshot{ community: { - key: community, - operators: []*Operator{b}, + Key: community, + Operators: []*cache.Operator{b}, }, }, } @@ -119,14 +120,14 @@ func TestPropertiesAnnotationHonored(t *testing.T) { operators, err := satResolver.SolveOperators([]string{"olm"}, csvs, subs) assert.NoError(t, err) - expected := OperatorSet{ + expected := cache.OperatorSet{ "packageB.v1": b, } require.EqualValues(t, expected, operators) } func TestSolveOperators_MultipleChannels(t *testing.T) { - APISet := APISet{opregistry.APIKey{"g", "v", "k", "ks"}: struct{}{}} + APISet := cache.APISet{opregistry.APIKey{"g", "v", "k", "ks"}: struct{}{}} Provides := APISet namespace := "olm" @@ -138,11 +139,11 @@ func TestSolveOperators_MultipleChannels(t *testing.T) { newSub := newSub(namespace, "packageB", "alpha", catalog) subs := []*v1alpha1.Subscription{sub, newSub} - fakeNamespacedOperatorCache := NamespacedOperatorCache{ - snapshots: map[registry.CatalogKey]*CatalogSnapshot{ + fakeNamespacedOperatorCache := cache.NamespacedOperatorCache{ + Snapshots: map[registry.CatalogKey]*cache.CatalogSnapshot{ catalog: { - key: catalog, - operators: []*Operator{ + Key: catalog, + Operators: []*cache.Operator{ genOperator("packageA.v1", "0.0.1", "", "packageA", "alpha", "community", "olm", nil, nil, nil, "", false), genOperator("packageB.v1", "1.0.0", "", "packageB", "alpha", "community", "olm", nil, nil, nil, "", false), genOperator("packageB.v1", "1.0.0", "", "packageB", "beta", "community", "olm", nil, nil, nil, "", false), @@ -157,7 +158,7 @@ func TestSolveOperators_MultipleChannels(t *testing.T) { operators, err := satResolver.SolveOperators([]string{"olm"}, csvs, subs) assert.NoError(t, err) - expected := OperatorSet{ + expected := cache.OperatorSet{ "packageB.v1": genOperator("packageB.v1", "1.0.0", "", "packageB", "alpha", "community", "olm", nil, nil, nil, "", false), } assert.Len(t, operators, 1) @@ -167,7 +168,7 @@ func TestSolveOperators_MultipleChannels(t *testing.T) { } func TestSolveOperators_FindLatestVersion(t *testing.T) { - APISet := APISet{opregistry.APIKey{"g", "v", "k", "ks"}: struct{}{}} + APISet := cache.APISet{opregistry.APIKey{"g", "v", "k", "ks"}: struct{}{}} Provides := APISet namespace := "olm" @@ -179,17 +180,17 @@ func TestSolveOperators_FindLatestVersion(t *testing.T) { newSub := newSub(namespace, "packageB", "alpha", catalog) subs := []*v1alpha1.Subscription{sub, newSub} - fakeNamespacedOperatorCache := NamespacedOperatorCache{ - snapshots: map[registry.CatalogKey]*CatalogSnapshot{ + fakeNamespacedOperatorCache := cache.NamespacedOperatorCache{ + Snapshots: map[registry.CatalogKey]*cache.CatalogSnapshot{ registry.CatalogKey{ Namespace: "olm", Name: "community", }: { - key: registry.CatalogKey{ + Key: registry.CatalogKey{ Namespace: "olm", Name: "community", }, - operators: []*Operator{ + Operators: []*cache.Operator{ genOperator("packageA.v1.0.1", "1.0.1", "packageA.v1", "packageA", "alpha", "community", "olm", nil, nil, nil, "", false), genOperator("packageB.v0.9.0", "0.9.0", "", "packageB", "alpha", "community", "olm", nil, nil, nil, "", false), genOperator("packageB.v1.0.0", "1.0.0", "packageB.v0.9.0", "packageB", "alpha", "community", "olm", nil, nil, nil, "", false), @@ -207,10 +208,10 @@ func TestSolveOperators_FindLatestVersion(t *testing.T) { assert.NoError(t, err) assert.Equal(t, 2, len(operators)) for _, op := range operators { - assert.Equal(t, "1.0.1", op.Version().String()) + assert.Equal(t, "1.0.1", op.GetVersion().String()) } - expected := OperatorSet{ + expected := cache.OperatorSet{ "packageA.v1.0.1": genOperator("packageA.v1.0.1", "1.0.1", "packageA.v1", "packageA", "alpha", "community", "olm", nil, nil, nil, "", false), "packageB.v1.0.1": genOperator("packageB.v1.0.1", "1.0.1", "packageB.v1.0.0", "packageB", "alpha", "community", "olm", nil, nil, nil, "", false), } @@ -221,7 +222,7 @@ func TestSolveOperators_FindLatestVersion(t *testing.T) { } func TestSolveOperators_FindLatestVersionWithDependencies(t *testing.T) { - APISet := APISet{opregistry.APIKey{"g", "v", "k", "ks"}: struct{}{}} + APISet := cache.APISet{opregistry.APIKey{"g", "v", "k", "ks"}: struct{}{}} Provides := APISet namespace := "olm" @@ -244,17 +245,17 @@ func TestSolveOperators_FindLatestVersionWithDependencies(t *testing.T) { }, } - fakeNamespacedOperatorCache := NamespacedOperatorCache{ - snapshots: map[registry.CatalogKey]*CatalogSnapshot{ + fakeNamespacedOperatorCache := cache.NamespacedOperatorCache{ + Snapshots: map[registry.CatalogKey]*cache.CatalogSnapshot{ registry.CatalogKey{ Namespace: "olm", Name: "community", }: { - key: registry.CatalogKey{ + Key: registry.CatalogKey{ Namespace: "olm", Name: "community", }, - operators: []*Operator{ + Operators: []*cache.Operator{ genOperator("packageA.v1.0.1", "1.0.1", "packageA.v1", "packageA", "alpha", "community", "olm", nil, nil, nil, "", false), genOperator("packageB.v0.9.0", "0.9.0", "", "packageB", "alpha", "community", "olm", nil, nil, nil, "", false), genOperator("packageB.v1.0.0", "1.0.0", "packageB.v0.9.0", "packageB", "alpha", "community", "olm", nil, nil, nil, "", false), @@ -277,7 +278,7 @@ func TestSolveOperators_FindLatestVersionWithDependencies(t *testing.T) { assert.NoError(t, err) assert.Equal(t, 4, len(operators)) - expected := OperatorSet{ + expected := cache.OperatorSet{ "packageA.v1.0.1": genOperator("packageA.v1.0.1", "1.0.1", "packageA.v1", "packageA", "alpha", "community", "olm", nil, nil, nil, "", false), "packageB.v1.0.1": genOperator("packageB.v1.0.1", "1.0.1", "packageB.v1.0.0", "packageB", "alpha", "community", "olm", nil, nil, opToAddVersionDeps, "", false), "packageC.v1.0.1": genOperator("packageC.v1.0.1", "1.0.1", "packageC.v1.0.0", "packageC", "alpha", "community", "olm", nil, nil, nil, "", false), @@ -290,7 +291,7 @@ func TestSolveOperators_FindLatestVersionWithDependencies(t *testing.T) { } func TestSolveOperators_FindLatestVersionWithNestedDependencies(t *testing.T) { - APISet := APISet{opregistry.APIKey{"g", "v", "k", "ks"}: struct{}{}} + APISet := cache.APISet{opregistry.APIKey{"g", "v", "k", "ks"}: struct{}{}} Provides := APISet namespace := "olm" @@ -319,17 +320,17 @@ func TestSolveOperators_FindLatestVersionWithNestedDependencies(t *testing.T) { }, } - fakeNamespacedOperatorCache := NamespacedOperatorCache{ - snapshots: map[registry.CatalogKey]*CatalogSnapshot{ + fakeNamespacedOperatorCache := cache.NamespacedOperatorCache{ + Snapshots: map[registry.CatalogKey]*cache.CatalogSnapshot{ registry.CatalogKey{ Namespace: "olm", Name: "community", }: { - key: registry.CatalogKey{ + Key: registry.CatalogKey{ Namespace: "olm", Name: "community", }, - operators: []*Operator{ + Operators: []*cache.Operator{ genOperator("packageA.v1.0.1", "1.0.1", "packageA.v1", "packageA", "alpha", "community", "olm", nil, nil, nil, "", false), genOperator("packageB.v0.9.0", "0.9.0", "", "packageB", "alpha", "community", "olm", nil, nil, nil, "", false), genOperator("packageB.v1.0.0", "1.0.0", "packageB.v0.9.0", "packageB", "alpha", "community", "olm", nil, nil, nil, "", false), @@ -352,7 +353,7 @@ func TestSolveOperators_FindLatestVersionWithNestedDependencies(t *testing.T) { assert.NoError(t, err) assert.Equal(t, 5, len(operators)) - expected := OperatorSet{ + expected := cache.OperatorSet{ "packageA.v1.0.1": genOperator("packageA.v1.0.1", "1.0.1", "packageA.v1", "packageA", "alpha", "community", "olm", nil, nil, nil, "", false), "packageB.v1.0.1": genOperator("packageB.v1.0.1", "1.0.1", "packageB.v1.0.0", "packageB", "alpha", "community", "olm", nil, nil, opToAddVersionDeps, "", false), "packageC.v1.0.1": genOperator("packageC.v1.0.1", "1.0.1", "packageC.v1.0.0", "packageC", "alpha", "community", "olm", nil, nil, nil, "", false), @@ -378,17 +379,17 @@ func TestSolveOperators_CatsrcPrioritySorting(t *testing.T) { newSub := newSub(namespace, "packageA", "alpha", customCatalog) subs := []*v1alpha1.Subscription{newSub} - fakeNamespacedOperatorCache := NamespacedOperatorCache{ - snapshots: map[registry.CatalogKey]*CatalogSnapshot{ + fakeNamespacedOperatorCache := cache.NamespacedOperatorCache{ + Snapshots: map[registry.CatalogKey]*cache.CatalogSnapshot{ registry.CatalogKey{ Namespace: "olm", Name: "community", }: { - key: registry.CatalogKey{ + Key: registry.CatalogKey{ Namespace: "olm", Name: "community", }, - operators: []*Operator{ + Operators: []*cache.Operator{ genOperator("packageA.v1", "0.0.1", "", "packageA", "alpha", "community", namespace, nil, nil, opToAddVersionDeps, "", false), }, @@ -397,11 +398,11 @@ func TestSolveOperators_CatsrcPrioritySorting(t *testing.T) { Namespace: "olm", Name: "community-operator", }: { - key: registry.CatalogKey{ + Key: registry.CatalogKey{ Namespace: "olm", Name: "community-operator", }, - operators: []*Operator{ + Operators: []*cache.Operator{ genOperator("packageB.v1", "0.0.1", "", "packageB", "alpha", "community-operator", namespace, nil, nil, nil, "", false), }, @@ -410,12 +411,12 @@ func TestSolveOperators_CatsrcPrioritySorting(t *testing.T) { Namespace: "olm", Name: "high-priority-operator", }: { - key: registry.CatalogKey{ + Key: registry.CatalogKey{ Namespace: "olm", Name: "high-priority-operator", }, - priority: catalogSourcePriority(100), - operators: []*Operator{ + Priority: 100, + Operators: []*cache.Operator{ genOperator("packageB.v1", "0.0.1", "", "packageB", "alpha", "high-priority-operator", namespace, nil, nil, nil, "", false), }, @@ -430,7 +431,7 @@ func TestSolveOperators_CatsrcPrioritySorting(t *testing.T) { operators, err := satResolver.SolveOperators([]string{"olm"}, []*v1alpha1.ClusterServiceVersion{}, subs) assert.NoError(t, err) - expected := OperatorSet{ + expected := cache.OperatorSet{ "packageA.v1": genOperator("packageA.v1", "0.0.1", "", "packageA", "alpha", "community", "olm", nil, nil, opToAddVersionDeps, "", false), "packageB.v1": genOperator("packageB.v1", "0.0.1", "", "packageB", "alpha", "high-priority-operator", "olm", @@ -442,16 +443,16 @@ func TestSolveOperators_CatsrcPrioritySorting(t *testing.T) { } // Catsrc with the same priority, ns, different name - fakeNamespacedOperatorCache.snapshots[registry.CatalogKey{ + fakeNamespacedOperatorCache.Snapshots[registry.CatalogKey{ Namespace: "olm", Name: "community-operator", - }] = &CatalogSnapshot{ - key: registry.CatalogKey{ + }] = &cache.CatalogSnapshot{ + Key: registry.CatalogKey{ Namespace: "olm", Name: "community-operator", }, - priority: catalogSourcePriority(100), - operators: []*Operator{ + Priority: 100, + Operators: []*cache.Operator{ genOperator("packageB.v1", "0.0.1", "", "packageB", "alpha", "community-operator", namespace, nil, nil, nil, "", false), }, @@ -463,7 +464,7 @@ func TestSolveOperators_CatsrcPrioritySorting(t *testing.T) { operators, err = satResolver.SolveOperators([]string{"olm"}, []*v1alpha1.ClusterServiceVersion{}, subs) assert.NoError(t, err) - expected = OperatorSet{ + expected = cache.OperatorSet{ "packageA.v1": genOperator("packageA.v1", "0.0.1", "", "packageA", "alpha", "community", "olm", nil, nil, opToAddVersionDeps, "", false), "packageB.v1": genOperator("packageB.v1", "0.0.1", "", "packageB", "alpha", "community-operator", "olm", @@ -475,15 +476,15 @@ func TestSolveOperators_CatsrcPrioritySorting(t *testing.T) { } // operators from the same catalogs source should be prioritized. - fakeNamespacedOperatorCache.snapshots[registry.CatalogKey{ + fakeNamespacedOperatorCache.Snapshots[registry.CatalogKey{ Namespace: "olm", Name: "community", - }] = &CatalogSnapshot{ - key: registry.CatalogKey{ + }] = &cache.CatalogSnapshot{ + Key: registry.CatalogKey{ Namespace: "olm", Name: "community", }, - operators: []*Operator{ + Operators: []*cache.Operator{ genOperator("packageA.v1", "0.0.1", "", "packageA", "alpha", "community", namespace, nil, nil, opToAddVersionDeps, "", false), genOperator("packageB.v1", "0.0.1", "", "packageB", "alpha", "community", @@ -497,7 +498,7 @@ func TestSolveOperators_CatsrcPrioritySorting(t *testing.T) { operators, err = satResolver.SolveOperators([]string{"olm"}, []*v1alpha1.ClusterServiceVersion{}, subs) assert.NoError(t, err) - expected = OperatorSet{ + expected = cache.OperatorSet{ "packageA.v1": genOperator("packageA.v1", "0.0.1", "", "packageA", "alpha", "community", "olm", nil, nil, opToAddVersionDeps, "", false), "packageB.v1": genOperator("packageB.v1", "0.0.1", "", "packageB", "alpha", "community", "olm", @@ -511,7 +512,7 @@ func TestSolveOperators_CatsrcPrioritySorting(t *testing.T) { } func TestSolveOperators_WithDependencies(t *testing.T) { - APISet := APISet{opregistry.APIKey{"g", "v", "k", "ks"}: struct{}{}} + APISet := cache.APISet{opregistry.APIKey{"g", "v", "k", "ks"}: struct{}{}} Provides := APISet namespace := "olm" @@ -530,17 +531,17 @@ func TestSolveOperators_WithDependencies(t *testing.T) { }, } - fakeNamespacedOperatorCache := NamespacedOperatorCache{ - snapshots: map[registry.CatalogKey]*CatalogSnapshot{ + fakeNamespacedOperatorCache := cache.NamespacedOperatorCache{ + Snapshots: map[registry.CatalogKey]*cache.CatalogSnapshot{ registry.CatalogKey{ Namespace: "olm", Name: "community", }: { - key: registry.CatalogKey{ + Key: registry.CatalogKey{ Namespace: "olm", Name: "community", }, - operators: []*Operator{ + Operators: []*cache.Operator{ genOperator("packageA.v1.0.1", "1.0.1", "packageA.v1", "packageA", "alpha", "community", "olm", nil, nil, nil, "", false), genOperator("packageB.v1", "1.0.0", "", "packageB", "alpha", "community", "olm", nil, nil, opToAddVersionDeps, "", false), genOperator("packageC.v1", "0.1.0", "", "packageC", "alpha", "community", "olm", nil, nil, nil, "", false), @@ -557,7 +558,7 @@ func TestSolveOperators_WithDependencies(t *testing.T) { assert.NoError(t, err) assert.Equal(t, 3, len(operators)) - expected := OperatorSet{ + expected := cache.OperatorSet{ "packageA.v1.0.1": genOperator("packageA.v1.0.1", "1.0.1", "packageA.v1", "packageA", "alpha", "community", "olm", nil, nil, nil, "", false), "packageB.v1": genOperator("packageB.v1", "1.0.0", "", "packageB", "alpha", "community", "olm", nil, nil, opToAddVersionDeps, "", false), "packageC.v1": genOperator("packageC.v1", "0.1.0", "", "packageC", "alpha", "community", "olm", nil, nil, nil, "", false), @@ -569,7 +570,7 @@ func TestSolveOperators_WithDependencies(t *testing.T) { } func TestSolveOperators_WithGVKDependencies(t *testing.T) { - APISet := APISet{opregistry.APIKey{"g", "v", "k", "ks"}: struct{}{}} + APISet := cache.APISet{opregistry.APIKey{"g", "v", "k", "ks"}: struct{}{}} Provides := APISet namespace := "olm" @@ -590,11 +591,11 @@ func TestSolveOperators_WithGVKDependencies(t *testing.T) { }, } - fakeNamespacedOperatorCache := NamespacedOperatorCache{ - snapshots: map[registry.CatalogKey]*CatalogSnapshot{ + fakeNamespacedOperatorCache := cache.NamespacedOperatorCache{ + Snapshots: map[registry.CatalogKey]*cache.CatalogSnapshot{ community: { - key: community, - operators: []*Operator{ + Key: community, + Operators: []*cache.Operator{ genOperator("packageA.v1", "0.0.1", "", "packageA", "alpha", "community", "olm", nil, nil, nil, "", false), genOperator("packageB.v1", "1.0.0", "", "packageB", "alpha", "community", "olm", Provides, nil, deps, "", false), genOperator("packageC.v1", "0.1.0", "", "packageC", "alpha", "community", "olm", nil, Provides, nil, "", false), @@ -610,7 +611,7 @@ func TestSolveOperators_WithGVKDependencies(t *testing.T) { operators, err := satResolver.SolveOperators([]string{"olm"}, csvs, subs) assert.NoError(t, err) - expected := OperatorSet{ + expected := cache.OperatorSet{ "packageB.v1": genOperator("packageB.v1", "1.0.0", "", "packageB", "alpha", "community", "olm", Provides, nil, deps, "", false), "packageC.v1": genOperator("packageC.v1", "0.1.0", "", "packageC", "alpha", "community", "olm", nil, Provides, nil, "", false), } @@ -644,20 +645,20 @@ func TestSolveOperators_WithLabelDependencies(t *testing.T) { operatorBv1 := genOperator("packageB.v1", "1.0.0", "", "packageB", "beta", "community", "olm", nil, nil, nil, "", false) for _, p := range props { - operatorBv1.properties = append(operatorBv1.properties, p) + operatorBv1.Properties = append(operatorBv1.Properties, p) } - fakeNamespacedOperatorCache := NamespacedOperatorCache{ - snapshots: map[registry.CatalogKey]*CatalogSnapshot{ + fakeNamespacedOperatorCache := cache.NamespacedOperatorCache{ + Snapshots: map[registry.CatalogKey]*cache.CatalogSnapshot{ registry.CatalogKey{ Namespace: "olm", Name: "community", }: { - key: registry.CatalogKey{ + Key: registry.CatalogKey{ Namespace: "olm", Name: "community", }, - operators: []*Operator{ + Operators: []*cache.Operator{ genOperator("packageA", "0.0.1", "", "packageA", "alpha", "community", "olm", nil, nil, deps, "", false), operatorBv1, }, @@ -672,7 +673,7 @@ func TestSolveOperators_WithLabelDependencies(t *testing.T) { assert.NoError(t, err) assert.Equal(t, 2, len(operators)) - expected := OperatorSet{ + expected := cache.OperatorSet{ "packageA": genOperator("packageA", "0.0.1", "", "packageA", "alpha", "community", "olm", nil, nil, deps, "", false), "packageB.v1": operatorBv1, } @@ -696,17 +697,17 @@ func TestSolveOperators_WithUnsatisfiableLabelDependencies(t *testing.T) { }, } - fakeNamespacedOperatorCache := NamespacedOperatorCache{ - snapshots: map[registry.CatalogKey]*CatalogSnapshot{ + fakeNamespacedOperatorCache := cache.NamespacedOperatorCache{ + Snapshots: map[registry.CatalogKey]*cache.CatalogSnapshot{ registry.CatalogKey{ Namespace: "olm", Name: "community", }: { - key: registry.CatalogKey{ + Key: registry.CatalogKey{ Namespace: "olm", Name: "community", }, - operators: []*Operator{ + Operators: []*cache.Operator{ genOperator("packageA", "0.0.1", "", "packageA", "alpha", "community", "olm", nil, nil, deps, "", false), genOperator("packageB.v1", "1.0.0", "", "packageB", "alpha", "community", "olm", nil, nil, nil, "", false), }, @@ -723,7 +724,7 @@ func TestSolveOperators_WithUnsatisfiableLabelDependencies(t *testing.T) { } func TestSolveOperators_WithNestedGVKDependencies(t *testing.T) { - APISet := APISet{opregistry.APIKey{"g", "v", "k", "ks"}: struct{}{}} + APISet := cache.APISet{opregistry.APIKey{"g", "v", "k", "ks"}: struct{}{}} Provides := APISet namespace := "olm" @@ -749,17 +750,17 @@ func TestSolveOperators_WithNestedGVKDependencies(t *testing.T) { }, } - fakeNamespacedOperatorCache := NamespacedOperatorCache{ - snapshots: map[registry.CatalogKey]*CatalogSnapshot{ + fakeNamespacedOperatorCache := cache.NamespacedOperatorCache{ + Snapshots: map[registry.CatalogKey]*cache.CatalogSnapshot{ registry.CatalogKey{ Namespace: "olm", Name: "community", }: { - key: registry.CatalogKey{ + Key: registry.CatalogKey{ Namespace: "olm", Name: "community", }, - operators: []*Operator{ + Operators: []*cache.Operator{ genOperator("packageA.v1.0.1", "1.0.1", "packageA.v1", "packageA", "alpha", "community", "olm", nil, nil, nil, "", false), genOperator("packageB.v1.0.0", "1.0.0", "", "packageB", "alpha", "community", "olm", Provides, nil, deps, "", false), genOperator("packageB.v1.0.1", "1.0.1", "packageB.v1.0.0", "packageB", "alpha", "community", "olm", Provides, nil, deps, "", false), @@ -772,11 +773,11 @@ func TestSolveOperators_WithNestedGVKDependencies(t *testing.T) { Namespace: "olm", Name: "certified", }: { - key: registry.CatalogKey{ + Key: registry.CatalogKey{ Namespace: "olm", Name: "certified", }, - operators: []*Operator{ + Operators: []*cache.Operator{ genOperator("packageC.v1.0.0", "1.0.0", "", "packageC", "alpha", "certified", "olm", Provides2, Provides, deps2, "", false), genOperator("packageC.v1.0.1", "1.0.1", "packageC.v1.0.0", "packageC", "alpha", "certified", "olm", Provides2, Provides, deps2, "", false), genOperator("packageD.v1.0.1", "1.0.1", "", "packageD", "alpha", "certified", "olm", nil, Provides2, nil, "", false), @@ -792,7 +793,7 @@ func TestSolveOperators_WithNestedGVKDependencies(t *testing.T) { operators, err := satResolver.SolveOperators([]string{"olm"}, csvs, subs) assert.NoError(t, err) assert.Equal(t, 4, len(operators)) - expected := OperatorSet{ + expected := cache.OperatorSet{ "packageA.v1.0.1": genOperator("packageA.v1.0.1", "1.0.1", "packageA.v1", "packageA", "alpha", "community", "olm", nil, nil, nil, "", false), "packageB.v1.0.1": genOperator("packageB.v1.0.1", "1.0.1", "packageB.v1.0.0", "packageB", "alpha", "community", "olm", Provides, nil, deps, "", false), "packageC.v1.0.1": genOperator("packageC.v1.0.1", "1.0.1", "packageC.v1.0.0", "packageC", "alpha", "community", "olm", Provides2, Provides, deps2, "", false), @@ -813,7 +814,7 @@ func TestSolveOperators_WithNestedGVKDependencies(t *testing.T) { func TestSolveOperators_IgnoreUnsatisfiableDependencies(t *testing.T) { const namespace = "olm" - Provides := APISet{opregistry.APIKey{Group: "g", Version: "v", Kind: "k", Plural: "ks"}: struct{}{}} + Provides := cache.APISet{opregistry.APIKey{Group: "g", Version: "v", Kind: "k", Plural: "ks"}: struct{}{}} community := registry.CatalogKey{Name: "community", Namespace: namespace} csvs := []*v1alpha1.ClusterServiceVersion{ existingOperator(namespace, "packageA.v1", "packageA", "alpha", "", Provides, nil, nil, nil), @@ -836,11 +837,11 @@ func TestSolveOperators_IgnoreUnsatisfiableDependencies(t *testing.T) { }, } - fakeNamespacedOperatorCache := NamespacedOperatorCache{ - snapshots: map[registry.CatalogKey]*CatalogSnapshot{ + fakeNamespacedOperatorCache := cache.NamespacedOperatorCache{ + Snapshots: map[registry.CatalogKey]*cache.CatalogSnapshot{ community: { - key: community, - operators: []*Operator{ + Key: community, + Operators: []*cache.Operator{ genOperator("packageA.v1", "0.0.1", "", "packageA", "alpha", "community", "olm", nil, nil, nil, "", false), genOperator("packageB.v1", "1.0.0", "", "packageB", "alpha", "community", "olm", nil, nil, opToAddVersionDeps, "", false), genOperator("packageC.v1", "0.1.0", "", "packageC", "alpha", "community", "olm", nil, nil, unsatisfiableVersionDeps, "", false), @@ -850,11 +851,11 @@ func TestSolveOperators_IgnoreUnsatisfiableDependencies(t *testing.T) { Namespace: "olm", Name: "certified", }: { - key: registry.CatalogKey{ + Key: registry.CatalogKey{ Namespace: "olm", Name: "certified", }, - operators: []*Operator{ + Operators: []*cache.Operator{ genOperator("packageA.v1", "0.0.1", "", "packageA", "alpha", "certified", "olm", nil, nil, nil, "", false), genOperator("packageB.v1", "1.0.0", "", "packageB", "alpha", "certified", "olm", nil, nil, opToAddVersionDeps, "", false), genOperator("packageC.v1", "0.1.0", "", "packageC", "alpha", "certified", "olm", nil, nil, nil, "", false), @@ -869,7 +870,7 @@ func TestSolveOperators_IgnoreUnsatisfiableDependencies(t *testing.T) { operators, err := satResolver.SolveOperators([]string{"olm"}, csvs, subs) assert.NoError(t, err) - expected := OperatorSet{ + expected := cache.OperatorSet{ "packageB.v1": genOperator("packageB.v1", "1.0.0", "", "packageB", "alpha", "community", "olm", nil, nil, opToAddVersionDeps, "", false), "packageC.v1": genOperator("packageC.v1", "0.1.0", "", "packageC", "alpha", "certified", "olm", nil, nil, nil, "", false), } @@ -883,7 +884,7 @@ func TestSolveOperators_IgnoreUnsatisfiableDependencies(t *testing.T) { // Behavior: The resolver should prefer catalogs in the same namespace as the subscription. // It should also prefer the same catalog over global catalogs in terms of the operator cache. func TestSolveOperators_PreferCatalogInSameNamespace(t *testing.T) { - APISet := APISet{opregistry.APIKey{"g", "v", "k", "ks"}: struct{}{}} + APISet := cache.APISet{opregistry.APIKey{"g", "v", "k", "ks"}: struct{}{}} Provides := APISet namespace := "olm" @@ -896,20 +897,20 @@ func TestSolveOperators_PreferCatalogInSameNamespace(t *testing.T) { sub := existingSub(namespace, "packageA.v1", "packageA", "alpha", catalog) subs := []*v1alpha1.Subscription{sub} - fakeNamespacedOperatorCache := NamespacedOperatorCache{ - snapshots: map[registry.CatalogKey]*CatalogSnapshot{ + fakeNamespacedOperatorCache := cache.NamespacedOperatorCache{ + Snapshots: map[registry.CatalogKey]*cache.CatalogSnapshot{ catalog: { - operators: []*Operator{ + Operators: []*cache.Operator{ genOperator("packageA.v0.0.1", "0.0.1", "packageA.v1", "packageA", "alpha", catalog.Name, catalog.Namespace, nil, Provides, nil, "", false), }, }, altnsCatalog: { - operators: []*Operator{ + Operators: []*cache.Operator{ genOperator("packageA.v0.0.1", "0.0.1", "packageA.v1", "packageA", "alpha", altnsCatalog.Name, altnsCatalog.Namespace, nil, Provides, nil, "", false), }, }, }, - namespaces: []string{namespace, altNamespace}, + Namespaces: []string{namespace, altNamespace}, } satResolver := SatResolver{ cache: getFakeOperatorCache(fakeNamespacedOperatorCache), @@ -919,7 +920,7 @@ func TestSolveOperators_PreferCatalogInSameNamespace(t *testing.T) { operators, err := satResolver.SolveOperators([]string{namespace}, csvs, subs) assert.NoError(t, err) - expected := OperatorSet{ + expected := cache.OperatorSet{ "packageA.v0.0.1": genOperator("packageA.v0.0.1", "0.0.1", "packageA.v1", "packageA", "alpha", catalog.Name, catalog.Namespace, nil, Provides, nil, "", false), } require.EqualValues(t, expected, operators) @@ -928,7 +929,7 @@ func TestSolveOperators_PreferCatalogInSameNamespace(t *testing.T) { // Behavior: The resolver should not look in catalogs not in the same namespace or the global catalog namespace when resolving the subscription. // This test should not result in a successful resolution because the catalog fulfilling the subscription is not in the operator cache. func TestSolveOperators_ResolveOnlyInCachedNamespaces(t *testing.T) { - APISet := APISet{opregistry.APIKey{"g", "v", "k", "ks"}: struct{}{}} + APISet := cache.APISet{opregistry.APIKey{"g", "v", "k", "ks"}: struct{}{}} Provides := APISet namespace := "olm" @@ -940,15 +941,15 @@ func TestSolveOperators_ResolveOnlyInCachedNamespaces(t *testing.T) { newSub := newSub(namespace, "packageA", "alpha", catalog) subs := []*v1alpha1.Subscription{newSub} - fakeNamespacedOperatorCache := NamespacedOperatorCache{ - snapshots: map[registry.CatalogKey]*CatalogSnapshot{ + fakeNamespacedOperatorCache := cache.NamespacedOperatorCache{ + Snapshots: map[registry.CatalogKey]*cache.CatalogSnapshot{ catalog: { - operators: []*Operator{ + Operators: []*cache.Operator{ genOperator("packageA.v0.0.1", "0.0.1", "packageA.v1", "packageA", "alpha", otherCatalog.Name, otherCatalog.Namespace, nil, Provides, nil, "", false), }, }, }, - namespaces: []string{otherCatalog.Namespace}, + Namespaces: []string{otherCatalog.Namespace}, } satResolver := SatResolver{ cache: getFakeOperatorCache(fakeNamespacedOperatorCache), @@ -963,7 +964,7 @@ func TestSolveOperators_ResolveOnlyInCachedNamespaces(t *testing.T) { // Behavior: the resolver should always prefer the default channel for the subscribed bundle (unless we implement ordering for channels) func TestSolveOperators_PreferDefaultChannelInResolution(t *testing.T) { - APISet := APISet{opregistry.APIKey{"g", "v", "k", "ks"}: struct{}{}} + APISet := cache.APISet{opregistry.APIKey{"g", "v", "k", "ks"}: struct{}{}} Provides := APISet namespace := "olm" @@ -976,10 +977,10 @@ func TestSolveOperators_PreferDefaultChannelInResolution(t *testing.T) { newSub := newSub(namespace, "packageA", "", catalog) subs := []*v1alpha1.Subscription{newSub} - fakeNamespacedOperatorCache := NamespacedOperatorCache{ - snapshots: map[registry.CatalogKey]*CatalogSnapshot{ + fakeNamespacedOperatorCache := cache.NamespacedOperatorCache{ + Snapshots: map[registry.CatalogKey]*cache.CatalogSnapshot{ catalog: { - operators: []*Operator{ + Operators: []*cache.Operator{ // Default channel is stable in this case genOperator("packageA.v0.0.2", "0.0.2", "packageA.v1", "packageA", "alpha", catalog.Name, catalog.Namespace, nil, Provides, nil, defaultChannel, false), genOperator("packageA.v0.0.1", "0.0.1", "packageA.v1", "packageA", "stable", catalog.Name, catalog.Namespace, nil, Provides, nil, defaultChannel, false), @@ -997,7 +998,7 @@ func TestSolveOperators_PreferDefaultChannelInResolution(t *testing.T) { assert.NoError(t, err) // operator should be from the default stable channel - expected := OperatorSet{ + expected := cache.OperatorSet{ "packageA.v0.0.1": genOperator("packageA.v0.0.1", "0.0.1", "packageA.v1", "packageA", "stable", catalog.Name, catalog.Namespace, nil, Provides, nil, defaultChannel, false), } require.EqualValues(t, expected, operators) @@ -1005,7 +1006,7 @@ func TestSolveOperators_PreferDefaultChannelInResolution(t *testing.T) { // Behavior: the resolver should always prefer the default channel for bundles satisfying transitive dependencies func TestSolveOperators_PreferDefaultChannelInResolutionForTransitiveDependencies(t *testing.T) { - APISet := APISet{opregistry.APIKey{"g", "v", "k", "ks"}: struct{}{}} + APISet := cache.APISet{opregistry.APIKey{"g", "v", "k", "ks"}: struct{}{}} Provides := APISet namespace := "olm" @@ -1017,11 +1018,11 @@ func TestSolveOperators_PreferDefaultChannelInResolutionForTransitiveDependencie subs := []*v1alpha1.Subscription{newSub} const defaultChannel = "stable" - fakeNamespacedOperatorCache := NamespacedOperatorCache{ - snapshots: map[registry.CatalogKey]*CatalogSnapshot{ + fakeNamespacedOperatorCache := cache.NamespacedOperatorCache{ + Snapshots: map[registry.CatalogKey]*cache.CatalogSnapshot{ catalog: { - operators: []*Operator{ - genOperator("packageA.v0.0.1", "0.0.1", "packageA.v1", "packageA", "alpha", catalog.Name, catalog.Namespace, Provides, nil, apiSetToDependencies(nil, Provides), defaultChannel, false), + Operators: []*cache.Operator{ + genOperator("packageA.v0.0.1", "0.0.1", "packageA.v1", "packageA", "alpha", catalog.Name, catalog.Namespace, Provides, nil, cache.APISetToDependencies(nil, Provides), defaultChannel, false), genOperator("packageB.v0.0.1", "0.0.1", "packageB.v1", "packageB", defaultChannel, catalog.Name, catalog.Namespace, nil, Provides, nil, defaultChannel, false), genOperator("packageB.v0.0.2", "0.0.2", "packageB.v0.0.1", "packageB", "alpha", catalog.Name, catalog.Namespace, nil, Provides, nil, defaultChannel, false), }, @@ -1038,15 +1039,15 @@ func TestSolveOperators_PreferDefaultChannelInResolutionForTransitiveDependencie assert.NoError(t, err) // operator should be from the default stable channel - expected := OperatorSet{ - "packageA.v0.0.1": genOperator("packageA.v0.0.1", "0.0.1", "packageA.v1", "packageA", "alpha", catalog.Name, catalog.Namespace, Provides, nil, apiSetToDependencies(nil, Provides), defaultChannel, false), + expected := cache.OperatorSet{ + "packageA.v0.0.1": genOperator("packageA.v0.0.1", "0.0.1", "packageA.v1", "packageA", "alpha", catalog.Name, catalog.Namespace, Provides, nil, cache.APISetToDependencies(nil, Provides), defaultChannel, false), "packageB.v0.0.1": genOperator("packageB.v0.0.1", "0.0.1", "packageB.v1", "packageB", defaultChannel, catalog.Name, catalog.Namespace, nil, Provides, nil, defaultChannel, false), } require.EqualValues(t, expected, operators) } func TestSolveOperators_SubscriptionlessOperatorsSatisfyDependencies(t *testing.T) { - APISet := APISet{opregistry.APIKey{"g", "v", "k", "ks"}: struct{}{}} + APISet := cache.APISet{opregistry.APIKey{"g", "v", "k", "ks"}: struct{}{}} Provides := APISet namespace := "olm" @@ -1064,17 +1065,17 @@ func TestSolveOperators_SubscriptionlessOperatorsSatisfyDependencies(t *testing. }, } - fakeNamespacedOperatorCache := NamespacedOperatorCache{ - snapshots: map[registry.CatalogKey]*CatalogSnapshot{ + fakeNamespacedOperatorCache := cache.NamespacedOperatorCache{ + Snapshots: map[registry.CatalogKey]*cache.CatalogSnapshot{ registry.CatalogKey{ Namespace: "olm", Name: "community", }: { - key: registry.CatalogKey{ + Key: registry.CatalogKey{ Namespace: "olm", Name: "community", }, - operators: []*Operator{ + Operators: []*cache.Operator{ genOperator("packageB.v1.0.0", "1.0.0", "", "packageB", "alpha", "community", "olm", Provides, nil, deps, "", false), genOperator("packageB.v1.0.1", "1.0.1", "packageB.v1.0.0", "packageB", "alpha", "community", "olm", Provides, nil, deps, "", false), }, @@ -1088,8 +1089,8 @@ func TestSolveOperators_SubscriptionlessOperatorsSatisfyDependencies(t *testing. operators, err := satResolver.SolveOperators([]string{"olm"}, csvs, subs) assert.NoError(t, err) - expected := OperatorSet{ - "packageB.v1.0.1": genOperator("packageB.v1.0.1", "1.0.1", "packageB.v1.0.0", "packageB", "alpha", catalog.Name, catalog.Namespace, Provides, nil, apiSetToDependencies(Provides, nil), "", false), + expected := cache.OperatorSet{ + "packageB.v1.0.1": genOperator("packageB.v1.0.1", "1.0.1", "packageB.v1.0.0", "packageB", "alpha", catalog.Name, catalog.Namespace, Provides, nil, cache.APISetToDependencies(Provides, nil), "", false), } assert.Equal(t, len(expected), len(operators)) for k := range expected { @@ -1099,7 +1100,7 @@ func TestSolveOperators_SubscriptionlessOperatorsSatisfyDependencies(t *testing. } func TestSolveOperators_SubscriptionlessOperatorsCanConflict(t *testing.T) { - APISet := APISet{opregistry.APIKey{"g", "v", "k", "ks"}: struct{}{}} + APISet := cache.APISet{opregistry.APIKey{"g", "v", "k", "ks"}: struct{}{}} Provides := APISet namespace := "olm" @@ -1110,17 +1111,17 @@ func TestSolveOperators_SubscriptionlessOperatorsCanConflict(t *testing.T) { newSub := newSub(namespace, "packageB", "alpha", catalog) subs := []*v1alpha1.Subscription{newSub} - fakeNamespacedOperatorCache := NamespacedOperatorCache{ - snapshots: map[registry.CatalogKey]*CatalogSnapshot{ + fakeNamespacedOperatorCache := cache.NamespacedOperatorCache{ + Snapshots: map[registry.CatalogKey]*cache.CatalogSnapshot{ registry.CatalogKey{ Namespace: "olm", Name: "community", }: { - key: registry.CatalogKey{ + Key: registry.CatalogKey{ Namespace: "olm", Name: "community", }, - operators: []*Operator{ + Operators: []*cache.Operator{ genOperator("packageB.v1.0.0", "1.0.0", "", "packageB", "alpha", "community", "olm", nil, Provides, nil, "", false), genOperator("packageB.v1.0.1", "1.0.1", "packageB.v1.0.0", "packageB", "alpha", "community", "olm", nil, Provides, nil, "", false), }, @@ -1137,10 +1138,10 @@ func TestSolveOperators_SubscriptionlessOperatorsCanConflict(t *testing.T) { } func TestSolveOperators_PackageCannotSelfSatisfy(t *testing.T) { - Provides1 := APISet{opregistry.APIKey{"g", "v", "k", "ks"}: struct{}{}} - Requires1 := APISet{opregistry.APIKey{"g", "v", "k", "ks"}: struct{}{}} - Provides2 := APISet{opregistry.APIKey{"g2", "v", "k", "ks"}: struct{}{}} - Requires2 := APISet{opregistry.APIKey{"g2", "v", "k", "ks"}: struct{}{}} + Provides1 := cache.APISet{opregistry.APIKey{"g", "v", "k", "ks"}: struct{}{}} + Requires1 := cache.APISet{opregistry.APIKey{"g", "v", "k", "ks"}: struct{}{}} + Provides2 := cache.APISet{opregistry.APIKey{"g2", "v", "k", "ks"}: struct{}{}} + Requires2 := cache.APISet{opregistry.APIKey{"g2", "v", "k", "ks"}: struct{}{}} ProvidesBoth := Provides1.Union(Provides2) RequiresBoth := Requires1.Union(Requires2) @@ -1151,11 +1152,11 @@ func TestSolveOperators_PackageCannotSelfSatisfy(t *testing.T) { newSub := newSub(namespace, "packageA", "stable", catalog) subs := []*v1alpha1.Subscription{newSub} - fakeNamespacedOperatorCache := NamespacedOperatorCache{ - snapshots: map[registry.CatalogKey]*CatalogSnapshot{ + fakeNamespacedOperatorCache := cache.NamespacedOperatorCache{ + Snapshots: map[registry.CatalogKey]*cache.CatalogSnapshot{ catalog: { - key: catalog, - operators: []*Operator{ + Key: catalog, + Operators: []*cache.Operator{ genOperator("opA.v1.0.0", "1.0.0", "", "packageA", "stable", catalog.Name, catalog.Namespace, RequiresBoth, nil, nil, "", false), // Despite satisfying dependencies of opA, this is not chosen because it is in the same package genOperator("opABC.v1.0.0", "1.0.0", "", "packageA", "alpha", catalog.Name, catalog.Namespace, nil, ProvidesBoth, nil, "", false), @@ -1165,8 +1166,8 @@ func TestSolveOperators_PackageCannotSelfSatisfy(t *testing.T) { }, }, secondaryCatalog: { - key: secondaryCatalog, - operators: []*Operator{ + Key: secondaryCatalog, + Operators: []*cache.Operator{ genOperator("opC.v1.0.0", "1.0.0", "", "packageB", "stable", secondaryCatalog.Name, secondaryCatalog.Namespace, nil, Provides2, nil, "stable", false), genOperator("opE.v1.0.0", "1.0.0", "", "packageC", "stable", secondaryCatalog.Name, secondaryCatalog.Namespace, nil, Provides2, nil, "", false), @@ -1181,7 +1182,7 @@ func TestSolveOperators_PackageCannotSelfSatisfy(t *testing.T) { operators, err := satResolver.SolveOperators([]string{"olm"}, nil, subs) assert.NoError(t, err) - expected := OperatorSet{ + expected := cache.OperatorSet{ "opA.v1.0.0": genOperator("opA.v1.0.0", "1.0.0", "", "packageA", "stable", catalog.Name, catalog.Namespace, RequiresBoth, nil, nil, "", false), "opB.v1.0.0": genOperator("opB.v1.0.0", "1.0.0", "", "packageB", "stable", catalog.Name, catalog.Namespace, nil, Provides1, nil, "stable", false), "opE.v1.0.0": genOperator("opE.v1.0.0", "1.0.0", "", "packageC", "stable", secondaryCatalog.Name, secondaryCatalog.Namespace, nil, Provides2, nil, "", false), @@ -1194,9 +1195,9 @@ func TestSolveOperators_PackageCannotSelfSatisfy(t *testing.T) { } func TestSolveOperators_TransferApiOwnership(t *testing.T) { - Provides1 := APISet{opregistry.APIKey{"g", "v", "k", "ks"}: struct{}{}} - Requires1 := APISet{opregistry.APIKey{"g", "v", "k", "ks"}: struct{}{}} - Provides2 := APISet{opregistry.APIKey{"g2", "v", "k", "ks"}: struct{}{}} + Provides1 := cache.APISet{opregistry.APIKey{"g", "v", "k", "ks"}: struct{}{}} + Requires1 := cache.APISet{opregistry.APIKey{"g", "v", "k", "ks"}: struct{}{}} + Provides2 := cache.APISet{opregistry.APIKey{"g2", "v", "k", "ks"}: struct{}{}} ProvidesBoth := Provides1.Union(Provides2) namespace := "olm" @@ -1204,19 +1205,19 @@ func TestSolveOperators_TransferApiOwnership(t *testing.T) { phases := []struct { subs []*v1alpha1.Subscription - catalog *CatalogSnapshot - expected OperatorSet + catalog *cache.CatalogSnapshot + expected cache.OperatorSet }{ { subs: []*v1alpha1.Subscription{newSub(namespace, "packageB", "stable", catalog)}, - catalog: &CatalogSnapshot{ - key: catalog, - operators: []*Operator{ + catalog: &cache.CatalogSnapshot{ + Key: catalog, + Operators: []*cache.Operator{ genOperator("opA.v1.0.0", "1.0.0", "", "packageA", "stable", catalog.Name, catalog.Namespace, nil, Provides1, nil, "", false), genOperator("opB.v1.0.0", "1.0.0", "", "packageB", "stable", catalog.Name, catalog.Namespace, Requires1, Provides2, nil, "stable", false), }, }, - expected: OperatorSet{ + expected: cache.OperatorSet{ "opA.v1.0.0": genOperator("opA.v1.0.0", "1.0.0", "", "packageA", "stable", catalog.Name, catalog.Namespace, nil, Provides1, nil, "", false), "opB.v1.0.0": genOperator("opB.v1.0.0", "1.0.0", "", "packageB", "stable", catalog.Name, catalog.Namespace, Requires1, Provides2, nil, "stable", false), }, @@ -1227,16 +1228,16 @@ func TestSolveOperators_TransferApiOwnership(t *testing.T) { existingSub(namespace, "opA.v1.0.0", "packageA", "stable", catalog), existingSub(namespace, "opB.v1.0.0", "packageB", "stable", catalog), }, - catalog: &CatalogSnapshot{ - key: catalog, - operators: []*Operator{ + catalog: &cache.CatalogSnapshot{ + Key: catalog, + Operators: []*cache.Operator{ genOperator("opA.v1.0.0", "1.0.0", "", "packageA", "stable", catalog.Name, catalog.Namespace, nil, Provides1, nil, "", false), genOperator("opA.v1.0.1", "1.0.1", "opA.v1.0.0", "packageA", "stable", catalog.Name, catalog.Namespace, Requires1, nil, nil, "", false), genOperator("opB.v1.0.0", "1.0.0", "", "packageB", "stable", catalog.Name, catalog.Namespace, Requires1, Provides2, nil, "stable", false), }, }, // nothing new to do here - expected: OperatorSet{}, + expected: cache.OperatorSet{}, }, { // will have two existing subs after resolving once @@ -1244,27 +1245,27 @@ func TestSolveOperators_TransferApiOwnership(t *testing.T) { existingSub(namespace, "opA.v1.0.0", "packageA", "stable", catalog), existingSub(namespace, "opB.v1.0.0", "packageB", "stable", catalog), }, - catalog: &CatalogSnapshot{ - key: catalog, - operators: []*Operator{ + catalog: &cache.CatalogSnapshot{ + Key: catalog, + Operators: []*cache.Operator{ genOperator("opA.v1.0.0", "1.0.0", "", "packageA", "stable", catalog.Name, catalog.Namespace, nil, Provides1, nil, "", false), genOperator("opA.v1.0.1", "1.0.1", "opA.v1.0.0", "packageA", "stable", catalog.Name, catalog.Namespace, Requires1, nil, nil, "", false), genOperator("opB.v1.0.0", "1.0.0", "", "packageB", "stable", catalog.Name, catalog.Namespace, Requires1, Provides2, nil, "stable", false), genOperator("opB.v1.0.1", "1.0.1", "opB.v1.0.0", "packageB", "stable", catalog.Name, catalog.Namespace, nil, ProvidesBoth, nil, "stable", false), }, }, - expected: OperatorSet{ + expected: cache.OperatorSet{ "opA.v1.0.1": genOperator("opA.v1.0.1", "1.0.1", "opA.v1.0.0", "packageA", "stable", catalog.Name, catalog.Namespace, Requires1, nil, nil, "", false), "opB.v1.0.1": genOperator("opB.v1.0.1", "1.0.1", "opB.v1.0.0", "packageB", "stable", catalog.Name, catalog.Namespace, nil, ProvidesBoth, nil, "stable", false), }, }, } - var operators OperatorSet + var operators cache.OperatorSet for i, p := range phases { t.Run(fmt.Sprintf("phase %d", i+1), func(t *testing.T) { - fakeNamespacedOperatorCache := NamespacedOperatorCache{ - snapshots: map[registry.CatalogKey]*CatalogSnapshot{ + fakeNamespacedOperatorCache := cache.NamespacedOperatorCache{ + Snapshots: map[registry.CatalogKey]*cache.CatalogSnapshot{ catalog: p.catalog, }, } @@ -1275,11 +1276,11 @@ func TestSolveOperators_TransferApiOwnership(t *testing.T) { csvs := make([]*v1alpha1.ClusterServiceVersion, 0) for _, o := range operators { var pkg, channel string - if b := o.Bundle(); b != nil { + if b := o.GetBundle(); b != nil { pkg = b.PackageName channel = b.ChannelName } - csvs = append(csvs, existingOperator(namespace, o.Identifier(), pkg, channel, o.Replaces(), o.ProvidedAPIs(), o.RequiredAPIs(), nil, nil)) + csvs = append(csvs, existingOperator(namespace, o.Identifier(), pkg, channel, o.GetReplaces(), o.GetProvidedAPIs(), o.GetRequiredAPIs(), nil, nil)) } var err error @@ -1295,10 +1296,10 @@ func TestSolveOperators_TransferApiOwnership(t *testing.T) { } type FakeOperatorCache struct { - fakedNamespacedOperatorCache NamespacedOperatorCache + fakedNamespacedOperatorCache cache.NamespacedOperatorCache } -func (f *FakeOperatorCache) Namespaced(namespaces ...string) MultiCatalogOperatorFinder { +func (f *FakeOperatorCache) Namespaced(namespaces ...string) cache.MultiCatalogOperatorFinder { return &f.fakedNamespacedOperatorCache } @@ -1306,40 +1307,40 @@ func (f *FakeOperatorCache) Expire(key registry.CatalogKey) { return } -func getFakeOperatorCache(fakedNamespacedOperatorCache NamespacedOperatorCache) OperatorCacheProvider { +func getFakeOperatorCache(fakedNamespacedOperatorCache cache.NamespacedOperatorCache) cache.OperatorCacheProvider { return &FakeOperatorCache{ fakedNamespacedOperatorCache: fakedNamespacedOperatorCache, } } -func genOperator(name, version, replaces, pkg, channel, catalogName, catalogNamespace string, requiredAPIs, providedAPIs APISet, dependencies []*api.Dependency, defaultChannel string, deprecated bool) *Operator { +func genOperator(name, version, replaces, pkg, channel, catalogName, catalogNamespace string, requiredAPIs, providedAPIs cache.APISet, dependencies []*api.Dependency, defaultChannel string, deprecated bool) *cache.Operator { semversion, _ := semver.Make(version) - properties := apiSetToProperties(providedAPIs, nil, deprecated) + properties := cache.APISetToProperties(providedAPIs, nil, deprecated) if len(dependencies) == 0 { - ps, err := requiredAPIsToProperties(requiredAPIs) + ps, err := cache.RequiredAPIsToProperties(requiredAPIs) if err != nil { panic(err) } properties = append(properties, ps...) } else { - ps, err := legacyDependenciesToProperties(dependencies) + ps, err := cache.LegacyDependenciesToProperties(dependencies) if err != nil { panic(err) } properties = append(properties, ps...) } - o := &Operator{ - name: name, - version: &semversion, - replaces: replaces, - bundle: &api.Bundle{ + o := &cache.Operator{ + Name: name, + Version: &semversion, + Replaces: replaces, + Bundle: &api.Bundle{ PackageName: pkg, ChannelName: channel, Dependencies: dependencies, Properties: properties, }, - properties: properties, - sourceInfo: &OperatorSourceInfo{ + Properties: properties, + SourceInfo: &cache.OperatorSourceInfo{ Catalog: registry.CatalogKey{ Name: catalogName, Namespace: catalogNamespace, @@ -1348,15 +1349,15 @@ func genOperator(name, version, replaces, pkg, channel, catalogName, catalogName Package: pkg, Channel: channel, }, - providedAPIs: providedAPIs, - requiredAPIs: requiredAPIs, + ProvidedAPIs: providedAPIs, + RequiredAPIs: requiredAPIs, } - ensurePackageProperty(o, pkg, version) + cache.EnsurePackageProperty(o, pkg, version) return o } -func stripBundle(o *Operator) *Operator { - o.bundle = nil +func stripBundle(o *cache.Operator) *cache.Operator { + o.Bundle = nil return o } @@ -1367,11 +1368,11 @@ func TestSolveOperators_WithoutDeprecated(t *testing.T) { newSub(catalog.Namespace, "packageA", "alpha", catalog), } - fakeNamespacedOperatorCache := NamespacedOperatorCache{ - snapshots: map[registry.CatalogKey]*CatalogSnapshot{ + fakeNamespacedOperatorCache := cache.NamespacedOperatorCache{ + Snapshots: map[registry.CatalogKey]*cache.CatalogSnapshot{ catalog: { - key: catalog, - operators: []*Operator{ + Key: catalog, + Operators: []*cache.Operator{ genOperator("packageA.v1", "0.0.1", "", "packageA", "alpha", catalog.Name, catalog.Namespace, nil, nil, nil, "", true), }, }, @@ -1395,11 +1396,11 @@ func TestSolveOperatorsWithDeprecatedInnerChannelEntry(t *testing.T) { } logger, _ := test.NewNullLogger() resolver := SatResolver{ - cache: getFakeOperatorCache(NamespacedOperatorCache{ - snapshots: map[registry.CatalogKey]*CatalogSnapshot{ + cache: getFakeOperatorCache(cache.NamespacedOperatorCache{ + Snapshots: map[registry.CatalogKey]*cache.CatalogSnapshot{ catalog: { - key: catalog, - operators: []*Operator{ + Key: catalog, + Operators: []*cache.Operator{ genOperator("a-1", "1.0.0", "", "a", "c", catalog.Name, catalog.Namespace, nil, nil, nil, "", false), genOperator("a-2", "2.0.0", "a-1", "a", "c", catalog.Name, catalog.Namespace, nil, nil, nil, "", true), genOperator("a-3", "3.0.0", "a-2", "a", "c", catalog.Name, catalog.Namespace, nil, nil, nil, "", false), @@ -1417,7 +1418,7 @@ func TestSolveOperatorsWithDeprecatedInnerChannelEntry(t *testing.T) { } func TestSolveOperators_WithSkipsAndStartingCSV(t *testing.T) { - APISet := APISet{opregistry.APIKey{"g", "v", "k", "ks"}: struct{}{}} + APISet := cache.APISet{opregistry.APIKey{"g", "v", "k", "ks"}: struct{}{}} Provides := APISet namespace := "olm" @@ -1435,27 +1436,27 @@ func TestSolveOperators_WithSkipsAndStartingCSV(t *testing.T) { opB := genOperator("packageB.v1", "1.0.0", "", "packageB", "alpha", "community", "olm", nil, nil, opToAddVersionDeps, "", false) opB2 := genOperator("packageB.v2", "2.0.0", "", "packageB", "alpha", "community", "olm", nil, nil, opToAddVersionDeps, "", false) - opB2.skips = []string{"packageB.v1"} + opB2.Skips = []string{"packageB.v1"} op1 := genOperator("packageA.v1", "1.0.0", "", "packageA", "alpha", "community", "olm", nil, Provides, nil, "", false) op2 := genOperator("packageA.v2", "2.0.0", "packageA.v1", "packageA", "alpha", "community", "olm", nil, Provides, nil, "", false) op3 := genOperator("packageA.v3", "3.0.0", "packageA.v2", "packageA", "alpha", "community", "olm", nil, Provides, nil, "", false) op4 := genOperator("packageA.v4", "4.0.0", "packageA.v3", "packageA", "alpha", "community", "olm", nil, Provides, nil, "", false) - op4.skips = []string{"packageA.v3"} + op4.Skips = []string{"packageA.v3"} op5 := genOperator("packageA.v5", "5.0.0", "packageA.v4", "packageA", "alpha", "community", "olm", nil, Provides, nil, "", false) - op5.skips = []string{"packageA.v2", "packageA.v3", "packageA.v4"} + op5.Skips = []string{"packageA.v2", "packageA.v3", "packageA.v4"} op6 := genOperator("packageA.v6", "6.0.0", "packageA.v5", "packageA", "alpha", "community", "olm", nil, Provides, nil, "", false) - fakeNamespacedOperatorCache := NamespacedOperatorCache{ - snapshots: map[registry.CatalogKey]*CatalogSnapshot{ + fakeNamespacedOperatorCache := cache.NamespacedOperatorCache{ + Snapshots: map[registry.CatalogKey]*cache.CatalogSnapshot{ registry.CatalogKey{ Namespace: "olm", Name: "community", }: { - key: registry.CatalogKey{ + Key: registry.CatalogKey{ Namespace: "olm", Name: "community", }, - operators: []*Operator{ + Operators: []*cache.Operator{ opB, opB2, op1, op2, op3, op4, op5, op6, }, }, @@ -1468,8 +1469,8 @@ func TestSolveOperators_WithSkipsAndStartingCSV(t *testing.T) { operators, err := satResolver.SolveOperators([]string{"olm"}, nil, subs) assert.NoError(t, err) - opB.SourceInfo().StartingCSV = "packageB.v1" - expected := OperatorSet{ + opB.SourceInfo.StartingCSV = "packageB.v1" + expected := cache.OperatorSet{ "packageB.v1": opB, "packageA.v6": op6, } @@ -1485,13 +1486,13 @@ func TestSolveOperators_WithSkips(t *testing.T) { opB := genOperator("packageB.v1", "1.0.0", "", "packageB", "alpha", catalog.Name, catalog.Namespace, nil, nil, nil, "", false) opB2 := genOperator("packageB.v2", "2.0.0", "", "packageB", "alpha", catalog.Name, catalog.Namespace, nil, nil, nil, "", false) - opB2.skips = []string{"packageB.v1"} + opB2.Skips = []string{"packageB.v1"} - fakeNamespacedOperatorCache := NamespacedOperatorCache{ - snapshots: map[registry.CatalogKey]*CatalogSnapshot{ + fakeNamespacedOperatorCache := cache.NamespacedOperatorCache{ + Snapshots: map[registry.CatalogKey]*cache.CatalogSnapshot{ catalog: { - key: catalog, - operators: []*Operator{ + Key: catalog, + Operators: []*cache.Operator{ opB, opB2, }, }, @@ -1504,7 +1505,7 @@ func TestSolveOperators_WithSkips(t *testing.T) { operators, err := satResolver.SolveOperators([]string{namespace}, nil, subs) assert.NoError(t, err) - expected := OperatorSet{ + expected := cache.OperatorSet{ "packageB.v2": opB2, } require.EqualValues(t, expected, operators) @@ -1513,7 +1514,7 @@ func TestSolveOperators_WithSkips(t *testing.T) { func TestSolveOperatorsWithSkipsPreventingSelection(t *testing.T) { const namespace = "test-namespace" catalog := registry.CatalogKey{Name: "test-catalog", Namespace: namespace} - gvks := APISet{opregistry.APIKey{Group: "g", Version: "v", Kind: "k", Plural: "ks"}: struct{}{}} + gvks := cache.APISet{opregistry.APIKey{Group: "g", Version: "v", Kind: "k", Plural: "ks"}: struct{}{}} // Subscription candidate a-1 requires a GVK provided // exclusively by b-1, but b-1 is skipped by b-3 and can't be @@ -1521,17 +1522,17 @@ func TestSolveOperatorsWithSkipsPreventingSelection(t *testing.T) { subs := []*v1alpha1.Subscription{newSub(namespace, "a", "channel", catalog)} a1 := genOperator("a-1", "1.0.0", "", "a", "channel", catalog.Name, catalog.Namespace, gvks, nil, nil, "", false) b3 := genOperator("b-3", "3.0.0", "b-2", "b", "channel", catalog.Name, catalog.Namespace, nil, nil, nil, "", false) - b3.skips = []string{"b-1"} + b3.Skips = []string{"b-1"} b2 := genOperator("b-2", "2.0.0", "b-1", "b", "channel", catalog.Name, catalog.Namespace, nil, nil, nil, "", false) b1 := genOperator("b-1", "1.0.0", "", "b", "channel", catalog.Name, catalog.Namespace, nil, gvks, nil, "", false) logger, _ := test.NewNullLogger() satResolver := SatResolver{ - cache: getFakeOperatorCache(NamespacedOperatorCache{ - snapshots: map[registry.CatalogKey]*CatalogSnapshot{ + cache: getFakeOperatorCache(cache.NamespacedOperatorCache{ + Snapshots: map[registry.CatalogKey]*cache.CatalogSnapshot{ catalog: { - key: catalog, - operators: []*Operator{a1, b3, b2, b1}, + Key: catalog, + Operators: []*cache.Operator{a1, b3, b2, b1}, }, }, }), @@ -1563,11 +1564,11 @@ func TestSolveOperatorsWithClusterServiceVersionHavingDependency(t *testing.T) { log, _ := test.NewNullLogger() r := SatResolver{ - cache: getFakeOperatorCache(NamespacedOperatorCache{ - snapshots: map[registry.CatalogKey]*CatalogSnapshot{ + cache: getFakeOperatorCache(cache.NamespacedOperatorCache{ + Snapshots: map[registry.CatalogKey]*cache.CatalogSnapshot{ catalog: { - key: catalog, - operators: []*Operator{ + Key: catalog, + Operators: []*cache.Operator{ genOperator("b-2", "2.0.0", "b-1", "b", "default", catalog.Name, catalog.Namespace, nil, nil, nil, "", false), }, }, @@ -1586,7 +1587,7 @@ func TestInferProperties(t *testing.T) { for _, tc := range []struct { Name string - Cache NamespacedOperatorCache + Cache cache.NamespacedOperatorCache CSV *v1alpha1.ClusterServiceVersion Subscriptions []*v1alpha1.Subscription Expected []*api.Property @@ -1663,14 +1664,14 @@ func TestInferProperties(t *testing.T) { }, { Name: "one matching subscription infers package property", - Cache: NamespacedOperatorCache{ - snapshots: map[registry.CatalogKey]*CatalogSnapshot{ + Cache: cache.NamespacedOperatorCache{ + Snapshots: map[registry.CatalogKey]*cache.CatalogSnapshot{ catalog: { - key: catalog, - operators: []*Operator{ + Key: catalog, + Operators: []*cache.Operator{ { - name: "a", - bundle: &api.Bundle{ + Name: "a", + Bundle: &api.Bundle{ PackageName: "x", }, }, @@ -1728,14 +1729,14 @@ func TestInferProperties(t *testing.T) { }, { Name: "one matching subscription infers package property without csv version", - Cache: NamespacedOperatorCache{ - snapshots: map[registry.CatalogKey]*CatalogSnapshot{ + Cache: cache.NamespacedOperatorCache{ + Snapshots: map[registry.CatalogKey]*cache.CatalogSnapshot{ catalog: { - key: catalog, - operators: []*Operator{ + Key: catalog, + Operators: []*cache.Operator{ { - name: "a", - bundle: &api.Bundle{ + Name: "a", + Bundle: &api.Bundle{ PackageName: "x", }, }, @@ -1787,41 +1788,41 @@ func TestInferProperties(t *testing.T) { func TestSortChannel(t *testing.T) { for _, tc := range []struct { Name string - In []*Operator - Out []*Operator + In []*cache.Operator + Out []*cache.Operator Err error }{ { Name: "wrinkle-free", - In: []*Operator{ + In: []*cache.Operator{ { - name: "b", - bundle: &api.Bundle{ + Name: "b", + Bundle: &api.Bundle{ PackageName: "package", ChannelName: "channel", }, }, { - name: "a", - replaces: "b", - bundle: &api.Bundle{ + Name: "a", + Replaces: "b", + Bundle: &api.Bundle{ PackageName: "package", ChannelName: "channel", }, }, }, - Out: []*Operator{ + Out: []*cache.Operator{ { - name: "a", - replaces: "b", - bundle: &api.Bundle{ + Name: "a", + Replaces: "b", + Bundle: &api.Bundle{ PackageName: "package", ChannelName: "channel", }, }, { - name: "b", - bundle: &api.Bundle{ + Name: "b", + Bundle: &api.Bundle{ PackageName: "package", ChannelName: "channel", }, @@ -1835,19 +1836,19 @@ func TestSortChannel(t *testing.T) { }, { Name: "replacement cycle", - In: []*Operator{ + In: []*cache.Operator{ { - name: "a", - replaces: "b", - bundle: &api.Bundle{ + Name: "a", + Replaces: "b", + Bundle: &api.Bundle{ PackageName: "package", ChannelName: "channel", }, }, { - name: "b", - replaces: "a", - bundle: &api.Bundle{ + Name: "b", + Replaces: "a", + Bundle: &api.Bundle{ PackageName: "package", ChannelName: "channel", }, @@ -1857,27 +1858,27 @@ func TestSortChannel(t *testing.T) { }, { Name: "replacement cycle", - In: []*Operator{ + In: []*cache.Operator{ { - name: "a", - replaces: "b", - bundle: &api.Bundle{ + Name: "a", + Replaces: "b", + Bundle: &api.Bundle{ PackageName: "package", ChannelName: "channel", }, }, { - name: "b", - replaces: "c", - bundle: &api.Bundle{ + Name: "b", + Replaces: "c", + Bundle: &api.Bundle{ PackageName: "package", ChannelName: "channel", }, }, { - name: "c", - replaces: "b", - bundle: &api.Bundle{ + Name: "c", + Replaces: "b", + Bundle: &api.Bundle{ PackageName: "package", ChannelName: "channel", }, @@ -1887,73 +1888,73 @@ func TestSortChannel(t *testing.T) { }, { Name: "skipped and replaced entry omitted", - In: []*Operator{ + In: []*cache.Operator{ { - name: "a", - replaces: "b", - skips: []string{"b"}, + Name: "a", + Replaces: "b", + Skips: []string{"b"}, }, { - name: "b", + Name: "b", }, }, - Out: []*Operator{ + Out: []*cache.Operator{ { - name: "a", - replaces: "b", - skips: []string{"b"}, + Name: "a", + Replaces: "b", + Skips: []string{"b"}, }, }, }, { Name: "skipped entry omitted", - In: []*Operator{ + In: []*cache.Operator{ { - name: "a", - replaces: "b", - skips: []string{"c"}, + Name: "a", + Replaces: "b", + Skips: []string{"c"}, }, { - name: "b", - replaces: "c", + Name: "b", + Replaces: "c", }, { - name: "c", + Name: "c", }, }, - Out: []*Operator{ + Out: []*cache.Operator{ { - name: "a", - replaces: "b", - skips: []string{"c"}, + Name: "a", + Replaces: "b", + Skips: []string{"c"}, }, { - name: "b", - replaces: "c", + Name: "b", + Replaces: "c", }, }, }, { Name: "two replaces chains", - In: []*Operator{ + In: []*cache.Operator{ { - name: "a", - bundle: &api.Bundle{ + Name: "a", + Bundle: &api.Bundle{ PackageName: "package", ChannelName: "channel", }, }, { - name: "b", - replaces: "c", - bundle: &api.Bundle{ + Name: "b", + Replaces: "c", + Bundle: &api.Bundle{ PackageName: "package", ChannelName: "channel", }, }, { - name: "c", - bundle: &api.Bundle{ + Name: "c", + Bundle: &api.Bundle{ PackageName: "package", ChannelName: "channel", }, diff --git a/pkg/controller/registry/resolver/step_resolver.go b/pkg/controller/registry/resolver/step_resolver.go index 6f211e1bd4..9fb369ca32 100644 --- a/pkg/controller/registry/resolver/step_resolver.go +++ b/pkg/controller/registry/resolver/step_resolver.go @@ -19,6 +19,7 @@ import ( v1alpha1listers "github.com/operator-framework/operator-lifecycle-manager/pkg/api/client/listers/operators/v1alpha1" controllerbundle "github.com/operator-framework/operator-lifecycle-manager/pkg/controller/bundle" "github.com/operator-framework/operator-lifecycle-manager/pkg/controller/registry" + "github.com/operator-framework/operator-lifecycle-manager/pkg/controller/registry/resolver/cache" "github.com/operator-framework/operator-lifecycle-manager/pkg/controller/registry/resolver/projection" "github.com/operator-framework/operator-lifecycle-manager/pkg/lib/operatorlister" ) @@ -48,7 +49,7 @@ type OperatorStepResolver struct { var _ StepResolver = &OperatorStepResolver{} func NewOperatorStepResolver(lister operatorlister.OperatorLister, client versioned.Interface, kubeclient kubernetes.Interface, - globalCatalogNamespace string, provider RegistryClientProvider, log logrus.FieldLogger) *OperatorStepResolver { + globalCatalogNamespace string, provider cache.RegistryClientProvider, log logrus.FieldLogger) *OperatorStepResolver { return &OperatorStepResolver{ subLister: lister.OperatorsV1alpha1().SubscriptionLister(), csvLister: lister.OperatorsV1alpha1().ClusterServiceVersionLister(), @@ -56,7 +57,7 @@ func NewOperatorStepResolver(lister operatorlister.OperatorLister, client versio client: client, kubeclient: kubeclient, globalCatalogNamespace: globalCatalogNamespace, - satResolver: NewDefaultSatResolver(NewDefaultRegistryClientProvider(log, provider), lister.OperatorsV1alpha1().CatalogSourceLister(), log), + satResolver: NewDefaultSatResolver(cache.NewDefaultRegistryClientProvider(log, provider), lister.OperatorsV1alpha1().CatalogSourceLister(), log), log: log, } } @@ -86,7 +87,7 @@ func (r *OperatorStepResolver) ResolveSteps(namespace string, _ SourceQuerier) ( return nil, nil, nil, err } - var operators OperatorSet + var operators cache.OperatorSet namespaces := []string{namespace, r.globalCatalogNamespace} operators, err = r.satResolver.SolveOperators(namespaces, csvs, subs) if err != nil { @@ -101,7 +102,7 @@ func (r *OperatorStepResolver) ResolveSteps(namespace string, _ SourceQuerier) ( for name, op := range operators { // Find any existing subscriptions that resolve to this operator. existingSubscriptions := make(map[*v1alpha1.Subscription]bool) - sourceInfo := *op.SourceInfo() + sourceInfo := *op.GetSourceInfo() for _, sub := range subs { if sub.Spec.Package != sourceInfo.Package { continue @@ -137,21 +138,21 @@ func (r *OperatorStepResolver) ResolveSteps(namespace string, _ SourceQuerier) ( } // add steps for any new bundle - if op.Bundle() != nil { + if op.GetBundle() != nil { if op.Inline() { - bundleSteps, err := NewStepsFromBundle(op.Bundle(), namespace, op.Replaces(), op.SourceInfo().Catalog.Name, op.SourceInfo().Catalog.Namespace) + bundleSteps, err := NewStepsFromBundle(op.GetBundle(), namespace, op.GetReplaces(), op.GetSourceInfo().Catalog.Name, op.GetSourceInfo().Catalog.Namespace) if err != nil { return nil, nil, nil, fmt.Errorf("failed to turn bundle into steps: %s", err.Error()) } steps = append(steps, bundleSteps...) } else { lookup := v1alpha1.BundleLookup{ - Path: op.Bundle().GetBundlePath(), + Path: op.GetBundle().GetBundlePath(), Identifier: op.Identifier(), - Replaces: op.Replaces(), + Replaces: op.GetReplaces(), CatalogSourceRef: &corev1.ObjectReference{ - Namespace: op.SourceInfo().Catalog.Namespace, - Name: op.SourceInfo().Catalog.Name, + Namespace: op.GetSourceInfo().Catalog.Namespace, + Name: op.GetSourceInfo().Catalog.Name, }, Conditions: []v1alpha1.BundleLookupCondition{ { @@ -168,7 +169,7 @@ func (r *OperatorStepResolver) ResolveSteps(namespace string, _ SourceQuerier) ( }, }, } - if anno, err := projection.PropertiesAnnotationFromPropertyList(op.Properties()); err != nil { + if anno, err := projection.PropertiesAnnotationFromPropertyList(op.GetProperties()); err != nil { return nil, nil, nil, fmt.Errorf("failed to serialize operator properties for %q: %w", op.Identifier(), err) } else { lookup.Properties = anno @@ -178,8 +179,8 @@ func (r *OperatorStepResolver) ResolveSteps(namespace string, _ SourceQuerier) ( if len(existingSubscriptions) == 0 { // explicitly track the resolved CSV as the starting CSV on the resolved subscriptions - op.SourceInfo().StartingCSV = op.Identifier() - subStep, err := NewSubscriptionStepResource(namespace, *op.SourceInfo()) + op.GetSourceInfo().StartingCSV = op.Identifier() + subStep, err := NewSubscriptionStepResource(namespace, *op.GetSourceInfo()) if err != nil { return nil, nil, nil, err } diff --git a/pkg/controller/registry/resolver/step_resolver_test.go b/pkg/controller/registry/resolver/step_resolver_test.go index 1aa6af0780..27225f556b 100644 --- a/pkg/controller/registry/resolver/step_resolver_test.go +++ b/pkg/controller/registry/resolver/step_resolver_test.go @@ -14,7 +14,6 @@ import ( metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/runtime" k8sfake "k8s.io/client-go/kubernetes/fake" - "k8s.io/client-go/tools/cache" "github.com/operator-framework/api/pkg/operators/v1alpha1" "github.com/operator-framework/operator-registry/pkg/api" @@ -25,24 +24,26 @@ import ( "github.com/operator-framework/operator-lifecycle-manager/pkg/api/client/informers/externalversions" controllerbundle "github.com/operator-framework/operator-lifecycle-manager/pkg/controller/bundle" "github.com/operator-framework/operator-lifecycle-manager/pkg/controller/registry" + resolvercache "github.com/operator-framework/operator-lifecycle-manager/pkg/controller/registry/resolver/cache" "github.com/operator-framework/operator-lifecycle-manager/pkg/controller/registry/resolver/solver" "github.com/operator-framework/operator-lifecycle-manager/pkg/lib/operatorlister" + "k8s.io/client-go/tools/cache" ) var ( // conventions for tests: packages are letters (a,b,c) and apis are numbers (1,2,3) // APISets used for tests - APISet1 = APISet{opregistry.APIKey{"g", "v", "k", "ks"}: struct{}{}} + APISet1 = resolvercache.APISet{opregistry.APIKey{"g", "v", "k", "ks"}: struct{}{}} Provides1 = APISet1 Requires1 = APISet1 - APISet2 = APISet{opregistry.APIKey{"g2", "v2", "k2", "k2s"}: struct{}{}} + APISet2 = resolvercache.APISet{opregistry.APIKey{"g2", "v2", "k2", "k2s"}: struct{}{}} Provides2 = APISet2 Requires2 = APISet2 - APISet3 = APISet{opregistry.APIKey{"g3", "v3", "k3", "k3s"}: struct{}{}} + APISet3 = resolvercache.APISet{opregistry.APIKey{"g3", "v3", "k3", "k3s"}: struct{}{}} Provides3 = APISet3 Requires3 = APISet3 - APISet4 = APISet{opregistry.APIKey{"g4", "v4", "k4", "k4s"}: struct{}{}} + APISet4 = resolvercache.APISet{opregistry.APIKey{"g4", "v4", "k4", "k4s"}: struct{}{}} Provides4 = APISet4 Requires4 = APISet4 ) @@ -826,20 +827,19 @@ func TestResolver(t *testing.T) { lister.OperatorsV1alpha1().RegisterClusterServiceVersionLister(namespace, informerFactory.Operators().V1alpha1().ClusterServiceVersions().Lister()) kClientFake := k8sfake.NewSimpleClientset() - stubSnapshot := &CatalogSnapshot{} + stubSnapshot := &resolvercache.CatalogSnapshot{} for _, bundles := range tt.bundlesByCatalog { for _, bundle := range bundles { - op, err := NewOperatorFromBundle(bundle, "", catalog, "") + op, err := resolvercache.NewOperatorFromBundle(bundle, "", catalog, "") if err != nil { t.Fatalf("unexpected error: %v", err) } - op.replaces = bundle.Replaces - stubSnapshot.operators = append(stubSnapshot.operators, op) + stubSnapshot.Operators = append(stubSnapshot.Operators, op) } } stubCache := &stubOperatorCacheProvider{ - noc: &NamespacedOperatorCache{ - snapshots: map[registry.CatalogKey]*CatalogSnapshot{ + noc: &resolvercache.NamespacedOperatorCache{ + Snapshots: map[registry.CatalogKey]*resolvercache.CatalogSnapshot{ catalog: stubSnapshot, }, }, @@ -880,10 +880,10 @@ func TestResolver(t *testing.T) { } type stubOperatorCacheProvider struct { - noc *NamespacedOperatorCache + noc *resolvercache.NamespacedOperatorCache } -func (stub *stubOperatorCacheProvider) Namespaced(namespaces ...string) MultiCatalogOperatorFinder { +func (stub *stubOperatorCacheProvider) Namespaced(namespaces ...string) resolvercache.MultiCatalogOperatorFinder { return stub.noc } @@ -979,18 +979,17 @@ func TestNamespaceResolverRBAC(t *testing.T) { lister.OperatorsV1alpha1().RegisterSubscriptionLister(namespace, informerFactory.Operators().V1alpha1().Subscriptions().Lister()) lister.OperatorsV1alpha1().RegisterClusterServiceVersionLister(namespace, informerFactory.Operators().V1alpha1().ClusterServiceVersions().Lister()) - stubSnapshot := &CatalogSnapshot{} + stubSnapshot := &resolvercache.CatalogSnapshot{} for _, bundle := range tt.bundlesInCatalog { - op, err := NewOperatorFromBundle(bundle, "", catalog, "") + op, err := resolvercache.NewOperatorFromBundle(bundle, "", catalog, "") if err != nil { t.Fatalf("unexpected error: %v", err) } - op.replaces = bundle.Replaces - stubSnapshot.operators = append(stubSnapshot.operators, op) + stubSnapshot.Operators = append(stubSnapshot.Operators, op) } stubCache := &stubOperatorCacheProvider{ - noc: &NamespacedOperatorCache{ - snapshots: map[registry.CatalogKey]*CatalogSnapshot{ + noc: &resolvercache.NamespacedOperatorCache{ + Snapshots: map[registry.CatalogKey]*resolvercache.CatalogSnapshot{ catalog: stubSnapshot, }, }, @@ -1102,7 +1101,7 @@ func existingSub(namespace, operatorName, pkg, channel string, catalog registry. } } -func existingOperator(namespace, operatorName, pkg, channel, replaces string, providedCRDs, requiredCRDs, providedAPIs, requiredAPIs APISet) *v1alpha1.ClusterServiceVersion { +func existingOperator(namespace, operatorName, pkg, channel, replaces string, providedCRDs, requiredCRDs, providedAPIs, requiredAPIs resolvercache.APISet) *v1alpha1.ClusterServiceVersion { bundleForOperator := bundle(operatorName, pkg, channel, replaces, providedCRDs, requiredCRDs, providedAPIs, requiredAPIs) csv, err := V1alpha1CSVFromBundle(bundleForOperator) if err != nil { diff --git a/pkg/controller/registry/resolver/steps.go b/pkg/controller/registry/resolver/steps.go index d800dff869..7f2270881b 100644 --- a/pkg/controller/registry/resolver/steps.go +++ b/pkg/controller/registry/resolver/steps.go @@ -17,6 +17,7 @@ import ( k8sscheme "k8s.io/client-go/kubernetes/scheme" "github.com/operator-framework/api/pkg/operators/v1alpha1" + "github.com/operator-framework/operator-lifecycle-manager/pkg/controller/registry/resolver/cache" "github.com/operator-framework/operator-lifecycle-manager/pkg/controller/registry/resolver/projection" "github.com/operator-framework/operator-lifecycle-manager/pkg/lib/ownerutil" ) @@ -86,7 +87,7 @@ func NewStepResourceFromObject(obj runtime.Object, catalogSourceName, catalogSou return resource, nil } -func NewSubscriptionStepResource(namespace string, info OperatorSourceInfo) (v1alpha1.StepResource, error) { +func NewSubscriptionStepResource(namespace string, info cache.OperatorSourceInfo) (v1alpha1.StepResource, error) { return NewStepResourceFromObject(&v1alpha1.Subscription{ ObjectMeta: metav1.ObjectMeta{ Namespace: namespace, diff --git a/pkg/controller/registry/resolver/util_test.go b/pkg/controller/registry/resolver/util_test.go index 3580a3f32d..533013a38d 100644 --- a/pkg/controller/registry/resolver/util_test.go +++ b/pkg/controller/registry/resolver/util_test.go @@ -19,6 +19,7 @@ import ( "github.com/operator-framework/api/pkg/operators/v1alpha1" "github.com/operator-framework/operator-lifecycle-manager/pkg/controller/registry" + "github.com/operator-framework/operator-lifecycle-manager/pkg/controller/registry/resolver/cache" "github.com/operator-framework/operator-lifecycle-manager/pkg/controller/registry/resolver/fakes" ) @@ -32,7 +33,7 @@ func RequireStepsEqual(t *testing.T, expectedSteps, steps []*v1alpha1.Step) { } } -func csv(name, replaces string, ownedCRDs, requiredCRDs, ownedAPIServices, requiredAPIServices APISet, permissions, clusterPermissions []v1alpha1.StrategyDeploymentPermissions) *v1alpha1.ClusterServiceVersion { +func csv(name, replaces string, ownedCRDs, requiredCRDs, ownedAPIServices, requiredAPIServices cache.APISet, permissions, clusterPermissions []v1alpha1.StrategyDeploymentPermissions) *v1alpha1.ClusterServiceVersion { var singleInstance = int32(1) strategy := v1alpha1.StrategyDetailsDeployment{ Permissions: permissions, @@ -155,7 +156,7 @@ func u(object runtime.Object) *unstructured.Unstructured { return &unstructured.Unstructured{Object: unst} } -func apiSetToGVK(crds, apis APISet) (out []*api.GroupVersionKind) { +func apiSetToGVK(crds, apis cache.APISet) (out []*api.GroupVersionKind) { out = make([]*api.GroupVersionKind, 0) for a := range crds { out = append(out, &api.GroupVersionKind{ @@ -176,91 +177,6 @@ func apiSetToGVK(crds, apis APISet) (out []*api.GroupVersionKind) { return } -func apiSetToDependencies(crds, apis APISet) (out []*api.Dependency) { - if len(crds)+len(apis) == 0 { - return nil - } - out = make([]*api.Dependency, 0) - for a := range crds { - val, err := json.Marshal(opregistry.GVKDependency{ - Group: a.Group, - Kind: a.Kind, - Version: a.Version, - }) - if err != nil { - panic(err) - } - out = append(out, &api.Dependency{ - Type: opregistry.GVKType, - Value: string(val), - }) - } - for a := range apis { - val, err := json.Marshal(opregistry.GVKDependency{ - Group: a.Group, - Kind: a.Kind, - Version: a.Version, - }) - if err != nil { - panic(err) - } - out = append(out, &api.Dependency{ - Type: opregistry.GVKType, - Value: string(val), - }) - } - if len(out) == 0 { - return nil - } - return -} - -func apiSetToProperties(crds, apis APISet, deprecated bool) (out []*api.Property) { - out = make([]*api.Property, 0) - for a := range crds { - val, err := json.Marshal(opregistry.GVKProperty{ - Group: a.Group, - Kind: a.Kind, - Version: a.Version, - }) - if err != nil { - panic(err) - } - out = append(out, &api.Property{ - Type: opregistry.GVKType, - Value: string(val), - }) - } - for a := range apis { - val, err := json.Marshal(opregistry.GVKProperty{ - Group: a.Group, - Kind: a.Kind, - Version: a.Version, - }) - if err != nil { - panic(err) - } - out = append(out, &api.Property{ - Type: opregistry.GVKType, - Value: string(val), - }) - } - if deprecated { - val, err := json.Marshal(opregistry.DeprecatedProperty{}) - if err != nil { - panic(err) - } - out = append(out, &api.Property{ - Type: opregistry.DeprecatedType, - Value: string(val), - }) - } - if len(out) == 0 { - return nil - } - return -} - func packageNameToProperty(packageName, version string) (out *api.Property) { val, err := json.Marshal(opregistry.PackageProperty{ PackageName: packageName, @@ -303,7 +219,7 @@ func withVersion(version string) bundleOpt { } } -func bundle(name, pkg, channel, replaces string, providedCRDs, requiredCRDs, providedAPIServices, requiredAPIServices APISet, opts ...bundleOpt) *api.Bundle { +func bundle(name, pkg, channel, replaces string, providedCRDs, requiredCRDs, providedAPIServices, requiredAPIServices cache.APISet, opts ...bundleOpt) *api.Bundle { csvJson, err := json.Marshal(csv(name, replaces, providedCRDs, requiredCRDs, providedAPIServices, requiredAPIServices, nil, nil)) if err != nil { panic(err) @@ -328,8 +244,8 @@ func bundle(name, pkg, channel, replaces string, providedCRDs, requiredCRDs, pro ProvidedApis: apiSetToGVK(providedCRDs, providedAPIServices), RequiredApis: apiSetToGVK(requiredCRDs, requiredAPIServices), Replaces: replaces, - Dependencies: apiSetToDependencies(requiredCRDs, requiredAPIServices), - Properties: append(apiSetToProperties(providedCRDs, providedAPIServices, false), + Dependencies: cache.APISetToDependencies(requiredCRDs, requiredAPIServices), + Properties: append(cache.APISetToProperties(providedCRDs, providedAPIServices, false), packageNameToProperty(pkg, "0.0.0"), ), } @@ -359,7 +275,7 @@ func withBundlePath(bundle *api.Bundle, path string) *api.Bundle { return bundle } -func bundleWithPermissions(name, pkg, channel, replaces string, providedCRDs, requiredCRDs, providedAPIServices, requiredAPIServices APISet, permissions, clusterPermissions []v1alpha1.StrategyDeploymentPermissions) *api.Bundle { +func bundleWithPermissions(name, pkg, channel, replaces string, providedCRDs, requiredCRDs, providedAPIServices, requiredAPIServices cache.APISet, permissions, clusterPermissions []v1alpha1.StrategyDeploymentPermissions) *api.Bundle { csvJson, err := json.Marshal(csv(name, replaces, providedCRDs, requiredCRDs, providedAPIServices, requiredAPIServices, permissions, clusterPermissions)) if err != nil { panic(err) @@ -385,8 +301,8 @@ func bundleWithPermissions(name, pkg, channel, replaces string, providedCRDs, re } } -func withReplaces(operator *Operator, replaces string) *Operator { - operator.replaces = replaces +func withReplaces(operator *cache.Operator, replaces string) *cache.Operator { + operator.Replaces = replaces return operator } @@ -518,13 +434,3 @@ func getPkgName(pkgChan string) string { s := strings.Split(pkgChan, "/") return s[0] } - -type OperatorPredicateTestFunc func(*Operator) bool - -func (opf OperatorPredicateTestFunc) Test(o *Operator) bool { - return opf(o) -} - -func (opf OperatorPredicateTestFunc) String() string { - return "" -} diff --git a/pkg/fakes/fake_api_intersection_reconciler.go b/pkg/fakes/fake_api_intersection_reconciler.go index 7ce13e21a8..1cfbf3d137 100644 --- a/pkg/fakes/fake_api_intersection_reconciler.go +++ b/pkg/fakes/fake_api_intersection_reconciler.go @@ -5,13 +5,14 @@ import ( "sync" "github.com/operator-framework/operator-lifecycle-manager/pkg/controller/registry/resolver" + "github.com/operator-framework/operator-lifecycle-manager/pkg/controller/registry/resolver/cache" ) type FakeAPIIntersectionReconciler struct { - ReconcileStub func(resolver.APISet, resolver.OperatorGroupSurface, ...resolver.OperatorGroupSurface) resolver.APIReconciliationResult + ReconcileStub func(cache.APISet, resolver.OperatorGroupSurface, ...resolver.OperatorGroupSurface) resolver.APIReconciliationResult reconcileMutex sync.RWMutex reconcileArgsForCall []struct { - arg1 resolver.APISet + arg1 cache.APISet arg2 resolver.OperatorGroupSurface arg3 []resolver.OperatorGroupSurface } @@ -25,11 +26,11 @@ type FakeAPIIntersectionReconciler struct { invocationsMutex sync.RWMutex } -func (fake *FakeAPIIntersectionReconciler) Reconcile(arg1 resolver.APISet, arg2 resolver.OperatorGroupSurface, arg3 ...resolver.OperatorGroupSurface) resolver.APIReconciliationResult { +func (fake *FakeAPIIntersectionReconciler) Reconcile(arg1 cache.APISet, arg2 resolver.OperatorGroupSurface, arg3 ...resolver.OperatorGroupSurface) resolver.APIReconciliationResult { fake.reconcileMutex.Lock() ret, specificReturn := fake.reconcileReturnsOnCall[len(fake.reconcileArgsForCall)] fake.reconcileArgsForCall = append(fake.reconcileArgsForCall, struct { - arg1 resolver.APISet + arg1 cache.APISet arg2 resolver.OperatorGroupSurface arg3 []resolver.OperatorGroupSurface }{arg1, arg2, arg3}) @@ -51,13 +52,13 @@ func (fake *FakeAPIIntersectionReconciler) ReconcileCallCount() int { return len(fake.reconcileArgsForCall) } -func (fake *FakeAPIIntersectionReconciler) ReconcileCalls(stub func(resolver.APISet, resolver.OperatorGroupSurface, ...resolver.OperatorGroupSurface) resolver.APIReconciliationResult) { +func (fake *FakeAPIIntersectionReconciler) ReconcileCalls(stub func(cache.APISet, resolver.OperatorGroupSurface, ...resolver.OperatorGroupSurface) resolver.APIReconciliationResult) { fake.reconcileMutex.Lock() defer fake.reconcileMutex.Unlock() fake.ReconcileStub = stub } -func (fake *FakeAPIIntersectionReconciler) ReconcileArgsForCall(i int) (resolver.APISet, resolver.OperatorGroupSurface, []resolver.OperatorGroupSurface) { +func (fake *FakeAPIIntersectionReconciler) ReconcileArgsForCall(i int) (cache.APISet, resolver.OperatorGroupSurface, []resolver.OperatorGroupSurface) { fake.reconcileMutex.RLock() defer fake.reconcileMutex.RUnlock() argsForCall := fake.reconcileArgsForCall[i]