Skip to content

Commit 4a43091

Browse files
author
Mikalai Radchuk
committed
Switch to catalogd's CatalogMetadata APIs
Signed-off-by: Mikalai Radchuk <[email protected]>
1 parent fd7cfb5 commit 4a43091

File tree

5 files changed

+119
-105
lines changed

5 files changed

+119
-105
lines changed

cmd/resolutioncli/entity_source.go

Lines changed: 3 additions & 49 deletions
Original file line numberDiff line numberDiff line change
@@ -18,17 +18,13 @@ package main
1818

1919
import (
2020
"context"
21-
"encoding/json"
22-
"fmt"
2321

2422
"github.com/operator-framework/deppy/pkg/deppy"
2523
"github.com/operator-framework/deppy/pkg/deppy/input"
2624
"github.com/operator-framework/operator-registry/alpha/action"
2725
"github.com/operator-framework/operator-registry/alpha/declcfg"
28-
"github.com/operator-framework/operator-registry/alpha/model"
29-
"github.com/operator-framework/operator-registry/alpha/property"
3026

31-
olmentity "github.com/operator-framework/operator-controller/internal/resolution/entities"
27+
"github.com/operator-framework/operator-controller/internal/resolution/entitysources"
3228
)
3329

3430
type indexRefEntitySource struct {
@@ -106,7 +102,8 @@ func (es *indexRefEntitySource) entities(ctx context.Context) (input.EntityList,
106102
return nil, err
107103
}
108104

109-
entities, err := modelToEntities(model)
105+
// TODO: update empty catalog name string to be catalog name once we support multiple catalogs in CLI
106+
entities, err := entitysources.ModelToEntities(model, "")
110107
if err != nil {
111108
return nil, err
112109
}
@@ -116,46 +113,3 @@ func (es *indexRefEntitySource) entities(ctx context.Context) (input.EntityList,
116113

117114
return es.entitiesCache, nil
118115
}
119-
120-
// TODO: Reduce code duplication: share a function with catalogdEntitySource (see getEntities)
121-
// We don't want to maintain two functions performing conversion into input.EntityList.
122-
// For this we need some common format. So we need a package which will be able
123-
// to convert from declfcg structs into CRD structs directly or via model.Model.
124-
// One option would be to make this piece of code from catalogd reusable and exportable:
125-
// https://github.com/operator-framework/catalogd/blob/9fe45a628de2e74d9cd73c3650fa2582aaac5213/pkg/controllers/core/catalog_controller.go#L200-L360
126-
func modelToEntities(model model.Model) (input.EntityList, error) {
127-
entities := input.EntityList{}
128-
129-
for _, pkg := range model {
130-
for _, ch := range pkg.Channels {
131-
for _, bundle := range ch.Bundles {
132-
props := map[string]string{}
133-
134-
for _, prop := range bundle.Properties {
135-
switch prop.Type {
136-
case property.TypePackage:
137-
// this is already a json marshalled object, so it doesn't need to be marshalled
138-
// like the other ones
139-
props[property.TypePackage] = string(prop.Value)
140-
}
141-
}
142-
143-
imgValue, err := json.Marshal(bundle.Image)
144-
if err != nil {
145-
return nil, err
146-
}
147-
props[olmentity.PropertyBundlePath] = string(imgValue)
148-
149-
channelValue, _ := json.Marshal(property.Channel{ChannelName: ch.Name, Priority: 0})
150-
props[property.TypeChannel] = string(channelValue)
151-
entity := input.Entity{
152-
ID: deppy.IdentifierFromString(fmt.Sprintf("%s%s%s", bundle.Name, bundle.Package.Name, ch.Name)),
153-
Properties: props,
154-
}
155-
entities = append(entities, entity)
156-
}
157-
}
158-
}
159-
160-
return entities, nil
161-
}

config/rbac/role.yaml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ rules:
77
- apiGroups:
88
- catalogd.operatorframework.io
99
resources:
10-
- bundlemetadata
10+
- catalogmetadata
1111
verbs:
1212
- list
1313
- watch

internal/controllers/operator_controller.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -58,9 +58,9 @@ type OperatorReconciler struct {
5858

5959
//+kubebuilder:rbac:groups=core.rukpak.io,resources=bundledeployments,verbs=get;list;watch;create;update;patch
6060

61-
//+kubebuilder:rbac:groups=catalogd.operatorframework.io,resources=bundlemetadata,verbs=list;watch
6261
//+kubebuilder:rbac:groups=catalogd.operatorframework.io,resources=packages,verbs=list;watch
6362
//+kubebuilder:rbac:groups=catalogd.operatorframework.io,resources=catalogs,verbs=list;watch
63+
//+kubebuilder:rbac:groups=catalogd.operatorframework.io,resources=catalogmetadata,verbs=list;watch
6464

6565
func (r *OperatorReconciler) Reconcile(ctx context.Context, req ctrl.Request) (ctrl.Result, error) {
6666
l := log.FromContext(ctx).WithName("operator-controller")

internal/resolution/entitysources/catalogdsource.go

Lines changed: 108 additions & 53 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,8 @@ import (
88
catalogd "github.com/operator-framework/catalogd/api/core/v1alpha1"
99
"github.com/operator-framework/deppy/pkg/deppy"
1010
"github.com/operator-framework/deppy/pkg/deppy/input"
11+
"github.com/operator-framework/operator-registry/alpha/declcfg"
12+
"github.com/operator-framework/operator-registry/alpha/model"
1113
"github.com/operator-framework/operator-registry/alpha/property"
1214
"sigs.k8s.io/controller-runtime/pkg/client"
1315

@@ -71,70 +73,123 @@ func (es *CatalogdEntitySource) Iterate(ctx context.Context, fn input.IteratorFu
7173
return nil
7274
}
7375

74-
func getEntities(ctx context.Context, client client.Client) (input.EntityList, error) {
75-
entityList := input.EntityList{}
76-
bundleMetadatas, packageMetdatas, err := fetchMetadata(ctx, client)
77-
if err != nil {
76+
func getEntities(ctx context.Context, cl client.Client) (input.EntityList, error) {
77+
allEntitiesList := input.EntityList{}
78+
79+
var catalogList catalogd.CatalogList
80+
if err := cl.List(ctx, &catalogList); err != nil {
7881
return nil, err
7982
}
80-
for _, bundle := range bundleMetadatas.Items {
81-
props := map[string]string{}
82-
83-
// TODO: We should make sure all properties are forwarded
84-
// through and avoid a lossy translation from FBC --> entity
85-
for _, prop := range bundle.Spec.Properties {
86-
switch prop.Type {
87-
case property.TypePackage:
88-
// this is already a json marshalled object, so it doesn't need to be marshalled
89-
// like the other ones
90-
props[property.TypePackage] = string(prop.Value)
91-
case entities.PropertyBundleMediaType:
92-
props[entities.PropertyBundleMediaType] = string(prop.Value)
93-
}
83+
for _, catalog := range catalogList.Items {
84+
model, err := fetchCatalogModel(ctx, cl, catalog.Name)
85+
if err != nil {
86+
return nil, err
9487
}
9588

96-
imgValue, err := json.Marshal(bundle.Spec.Image)
89+
catalogEntitiesList, err := ModelToEntities(model, catalog.Name)
9790
if err != nil {
9891
return nil, err
9992
}
100-
props[entities.PropertyBundlePath] = string(imgValue)
101-
catalogScopedPkgName := fmt.Sprintf("%s-%s", bundle.Spec.Catalog.Name, bundle.Spec.Package)
102-
bundlePkg := packageMetdatas[catalogScopedPkgName]
103-
for _, ch := range bundlePkg.Spec.Channels {
104-
for _, b := range ch.Entries {
105-
catalogScopedEntryName := fmt.Sprintf("%s-%s", bundle.Spec.Catalog.Name, b.Name)
106-
if catalogScopedEntryName == bundle.Name {
107-
channelValue, _ := json.Marshal(property.Channel{ChannelName: ch.Name, Priority: 0})
108-
props[property.TypeChannel] = string(channelValue)
109-
replacesValue, _ := json.Marshal(entities.ChannelEntry{
110-
Name: b.Name,
111-
Replaces: b.Replaces,
112-
})
113-
props[entities.PropertyBundleChannelEntry] = string(replacesValue)
114-
entity := input.Entity{
115-
ID: deppy.IdentifierFromString(fmt.Sprintf("%s%s%s", bundle.Name, bundle.Spec.Package, ch.Name)),
116-
Properties: props,
117-
}
118-
entityList = append(entityList, entity)
119-
}
120-
}
121-
}
93+
94+
allEntitiesList = append(allEntitiesList, catalogEntitiesList...)
12295
}
123-
return entityList, nil
96+
97+
return allEntitiesList, nil
12498
}
12599

126-
func fetchMetadata(ctx context.Context, client client.Client) (catalogd.BundleMetadataList, map[string]catalogd.Package, error) {
127-
packageMetdatas := catalogd.PackageList{}
128-
if err := client.List(ctx, &packageMetdatas); err != nil {
129-
return catalogd.BundleMetadataList{}, nil, err
100+
func fetchCatalogModel(ctx context.Context, cl client.Client, catalogName string) (model.Model, error) {
101+
packages, err := fetch[declcfg.Package](ctx, cl, declcfg.SchemaPackage, catalogName)
102+
if err != nil {
103+
return nil, err
130104
}
131-
bundleMetadatas := catalogd.BundleMetadataList{}
132-
if err := client.List(ctx, &bundleMetadatas); err != nil {
133-
return catalogd.BundleMetadataList{}, nil, err
105+
channels, err := fetch[declcfg.Channel](ctx, cl, declcfg.SchemaChannel, catalogName)
106+
if err != nil {
107+
return nil, err
134108
}
135-
packages := map[string]catalogd.Package{}
136-
for _, pkg := range packageMetdatas.Items {
137-
packages[pkg.Name] = pkg
109+
bundles, err := fetch[declcfg.Bundle](ctx, cl, declcfg.SchemaBundle, catalogName)
110+
if err != nil {
111+
return nil, err
112+
}
113+
114+
cfg := &declcfg.DeclarativeConfig{
115+
Packages: packages,
116+
Channels: channels,
117+
Bundles: bundles,
138118
}
139-
return bundleMetadatas, packages, nil
119+
model, err := declcfg.ConvertToModel(*cfg)
120+
if err != nil {
121+
return nil, err
122+
}
123+
124+
return model, nil
125+
}
126+
127+
type declcfgSchemas interface {
128+
declcfg.Package | declcfg.Bundle | declcfg.Channel
129+
}
130+
131+
// TODO: Cleanup once https://github.com/golang/go/issues/45380 implemented
132+
// We should be able to get rid of the schema arg and switch based on the type based to this generic
133+
func fetch[T declcfgSchemas](ctx context.Context, cl client.Client, schema, catalogName string) ([]T, error) {
134+
cmList := catalogd.CatalogMetadataList{}
135+
if err := cl.List(ctx, &cmList, client.MatchingLabels{"schema": schema, "catalog": catalogName}); err != nil {
136+
return nil, err
137+
}
138+
139+
contents := []T{}
140+
for _, cm := range cmList.Items {
141+
var content T
142+
if err := json.Unmarshal(cm.Spec.Content, &content); err != nil {
143+
return nil, err
144+
}
145+
contents = append(contents, content)
146+
}
147+
148+
return contents, nil
149+
}
150+
151+
func ModelToEntities(model model.Model, catalogName string) (input.EntityList, error) {
152+
entityList := input.EntityList{}
153+
154+
for _, pkg := range model {
155+
for _, ch := range pkg.Channels {
156+
for _, bundle := range ch.Bundles {
157+
props := map[string]string{}
158+
159+
for _, prop := range bundle.Properties {
160+
switch prop.Type {
161+
case property.TypePackage:
162+
// this is already a json marshalled object, so it doesn't need to be marshalled
163+
// like the other ones
164+
props[property.TypePackage] = string(prop.Value)
165+
case entities.PropertyBundleMediaType:
166+
props[entities.PropertyBundleMediaType] = string(prop.Value)
167+
}
168+
}
169+
170+
imgValue, err := json.Marshal(bundle.Image)
171+
if err != nil {
172+
return nil, err
173+
}
174+
props[entities.PropertyBundlePath] = string(imgValue)
175+
176+
channelValue, _ := json.Marshal(property.Channel{ChannelName: ch.Name, Priority: 0})
177+
props[property.TypeChannel] = string(channelValue)
178+
replacesValue, _ := json.Marshal(entities.ChannelEntry{
179+
Name: bundle.Name,
180+
Replaces: bundle.Replaces,
181+
})
182+
props[entities.PropertyBundleChannelEntry] = string(replacesValue)
183+
184+
catalogScopedEntryName := fmt.Sprintf("%s-%s", catalogName, bundle.Name)
185+
entity := input.Entity{
186+
ID: deppy.IdentifierFromString(fmt.Sprintf("%s%s%s", catalogScopedEntryName, bundle.Package.Name, ch.Name)),
187+
Properties: props,
188+
}
189+
entityList = append(entityList, entity)
190+
}
191+
}
192+
}
193+
194+
return entityList, nil
140195
}

test/e2e/e2e_suite_test.go

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -95,8 +95,9 @@ var _ = AfterSuite(func() {
9595
}).Should(Succeed())
9696

9797
// speed up delete without waiting for gc
98-
Expect(c.DeleteAllOf(ctx, &catalogd.BundleMetadata{})).To(Succeed())
9998
Expect(c.DeleteAllOf(ctx, &catalogd.Package{})).To(Succeed())
99+
Expect(c.DeleteAllOf(ctx, &catalogd.BundleMetadata{})).To(Succeed())
100+
Expect(c.DeleteAllOf(ctx, &catalogd.CatalogMetadata{})).To(Succeed())
100101

101102
Eventually(func(g Gomega) {
102103
// ensure resource cleanup
@@ -107,6 +108,10 @@ var _ = AfterSuite(func() {
107108
bmd := &catalogd.BundleMetadataList{}
108109
g.Expect(c.List(ctx, bmd)).To(Succeed())
109110
g.Expect(bmd.Items).To(BeEmpty())
111+
112+
cmd := &catalogd.CatalogMetadataList{}
113+
g.Expect(c.List(ctx, cmd)).To(Succeed())
114+
g.Expect(bmd.Items).To(BeEmpty())
110115
}).Should(Succeed())
111116
})
112117

0 commit comments

Comments
 (0)