| 
8 | 8 | 	catalogd "github.com/operator-framework/catalogd/api/core/v1alpha1"  | 
9 | 9 | 	"github.com/operator-framework/deppy/pkg/deppy"  | 
10 | 10 | 	"github.com/operator-framework/deppy/pkg/deppy/input"  | 
 | 11 | +	"github.com/operator-framework/operator-registry/alpha/declcfg"  | 
11 | 12 | 	"github.com/operator-framework/operator-registry/alpha/property"  | 
12 | 13 | 	"sigs.k8s.io/controller-runtime/pkg/client"  | 
13 | 14 | 
 
  | 
@@ -71,70 +72,119 @@ func (es *CatalogdEntitySource) Iterate(ctx context.Context, fn input.IteratorFu  | 
71 | 72 | 	return nil  | 
72 | 73 | }  | 
73 | 74 | 
 
  | 
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 {  | 
 | 75 | +func getEntities(ctx context.Context, cl client.Client) (input.EntityList, error) {  | 
 | 76 | +	allEntitiesList := input.EntityList{}  | 
 | 77 | + | 
 | 78 | +	var catalogList catalogd.CatalogList  | 
 | 79 | +	if err := cl.List(ctx, &catalogList); err != nil {  | 
78 | 80 | 		return nil, err  | 
79 | 81 | 	}  | 
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 |  | -			}  | 
 | 82 | +	for _, catalog := range catalogList.Items {  | 
 | 83 | +		channels, bundles, err := fetchCatalogMetadata(ctx, cl, catalog.Name)  | 
 | 84 | +		if err != nil {  | 
 | 85 | +			return nil, err  | 
94 | 86 | 		}  | 
95 | 87 | 
 
  | 
96 |  | -		imgValue, err := json.Marshal(bundle.Spec.Image)  | 
 | 88 | +		catalogEntitiesList, err := MetadataToEntities(catalog.Name, channels, bundles)  | 
97 | 89 | 		if err != nil {  | 
98 | 90 | 			return nil, err  | 
99 | 91 | 		}  | 
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)  | 
 | 92 | + | 
 | 93 | +		allEntitiesList = append(allEntitiesList, catalogEntitiesList...)  | 
 | 94 | +	}  | 
 | 95 | + | 
 | 96 | +	return allEntitiesList, nil  | 
 | 97 | +}  | 
 | 98 | + | 
 | 99 | +func MetadataToEntities(catalogName string, channels []declcfg.Channel, bundles []declcfg.Bundle) (input.EntityList, error) {  | 
 | 100 | +	entityList := input.EntityList{}  | 
 | 101 | + | 
 | 102 | +	bundlesMap := map[string]*declcfg.Bundle{}  | 
 | 103 | +	for i := range bundles {  | 
 | 104 | +		bundleKey := fmt.Sprintf("%s-%s", bundles[i].Package, bundles[i].Name)  | 
 | 105 | +		bundlesMap[bundleKey] = &bundles[i]  | 
 | 106 | +	}  | 
 | 107 | + | 
 | 108 | +	for _, ch := range channels {  | 
 | 109 | +		for _, chEntry := range ch.Entries {  | 
 | 110 | +			bundleKey := fmt.Sprintf("%s-%s", ch.Package, chEntry.Name)  | 
 | 111 | +			bundle, ok := bundlesMap[bundleKey]  | 
 | 112 | +			if !ok {  | 
 | 113 | +				return nil, fmt.Errorf("bundle %q not found in catalog %q (package %q, channel %q)", chEntry.Name, catalogName, ch.Package, ch.Name)  | 
 | 114 | +			}  | 
 | 115 | + | 
 | 116 | +			props := map[string]string{}  | 
 | 117 | + | 
 | 118 | +			for _, prop := range bundle.Properties {  | 
 | 119 | +				switch prop.Type {  | 
 | 120 | +				case property.TypePackage:  | 
 | 121 | +					// this is already a json marshalled object, so it doesn't need to be marshalled  | 
 | 122 | +					// like the other ones  | 
 | 123 | +					props[property.TypePackage] = string(prop.Value)  | 
 | 124 | +				case entities.PropertyBundleMediaType:  | 
 | 125 | +					props[entities.PropertyBundleMediaType] = string(prop.Value)  | 
119 | 126 | 				}  | 
120 | 127 | 			}  | 
 | 128 | + | 
 | 129 | +			imgValue, err := json.Marshal(bundle.Image)  | 
 | 130 | +			if err != nil {  | 
 | 131 | +				return nil, err  | 
 | 132 | +			}  | 
 | 133 | +			props[entities.PropertyBundlePath] = string(imgValue)  | 
 | 134 | + | 
 | 135 | +			channelValue, _ := json.Marshal(property.Channel{ChannelName: ch.Name, Priority: 0})  | 
 | 136 | +			props[property.TypeChannel] = string(channelValue)  | 
 | 137 | +			replacesValue, _ := json.Marshal(entities.ChannelEntry{  | 
 | 138 | +				Name:     bundle.Name,  | 
 | 139 | +				Replaces: chEntry.Replaces,  | 
 | 140 | +			})  | 
 | 141 | +			props[entities.PropertyBundleChannelEntry] = string(replacesValue)  | 
 | 142 | + | 
 | 143 | +			catalogScopedEntryName := fmt.Sprintf("%s-%s", catalogName, bundle.Name)  | 
 | 144 | +			entity := input.Entity{  | 
 | 145 | +				ID:         deppy.IdentifierFromString(fmt.Sprintf("%s%s%s", catalogScopedEntryName, bundle.Package, ch.Name)),  | 
 | 146 | +				Properties: props,  | 
 | 147 | +			}  | 
 | 148 | +			entityList = append(entityList, entity)  | 
121 | 149 | 		}  | 
122 | 150 | 	}  | 
 | 151 | + | 
123 | 152 | 	return entityList, nil  | 
124 | 153 | }  | 
125 | 154 | 
 
  | 
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  | 
 | 155 | +func fetchCatalogMetadata(ctx context.Context, cl client.Client, catalogName string) ([]declcfg.Channel, []declcfg.Bundle, error) {  | 
 | 156 | +	channels, err := fetchCatalogMetadataByScheme[declcfg.Channel](ctx, cl, declcfg.SchemaChannel, catalogName)  | 
 | 157 | +	if err != nil {  | 
 | 158 | +		return nil, nil, err  | 
 | 159 | +	}  | 
 | 160 | +	bundles, err := fetchCatalogMetadataByScheme[declcfg.Bundle](ctx, cl, declcfg.SchemaBundle, catalogName)  | 
 | 161 | +	if err != nil {  | 
 | 162 | +		return nil, nil, err  | 
130 | 163 | 	}  | 
131 |  | -	bundleMetadatas := catalogd.BundleMetadataList{}  | 
132 |  | -	if err := client.List(ctx, &bundleMetadatas); err != nil {  | 
133 |  | -		return catalogd.BundleMetadataList{}, nil, err  | 
 | 164 | + | 
 | 165 | +	return channels, bundles, nil  | 
 | 166 | +}  | 
 | 167 | + | 
 | 168 | +type declcfgSchema interface {  | 
 | 169 | +	declcfg.Package | declcfg.Bundle | declcfg.Channel  | 
 | 170 | +}  | 
 | 171 | + | 
 | 172 | +// TODO: Cleanup once https://github.com/golang/go/issues/45380 implemented  | 
 | 173 | +// We should be able to get rid of the schema arg and switch based on the type passed to this generic  | 
 | 174 | +func fetchCatalogMetadataByScheme[T declcfgSchema](ctx context.Context, cl client.Client, schema, catalogName string) ([]T, error) {  | 
 | 175 | +	cmList := catalogd.CatalogMetadataList{}  | 
 | 176 | +	if err := cl.List(ctx, &cmList, client.MatchingLabels{"schema": schema, "catalog": catalogName}); err != nil {  | 
 | 177 | +		return nil, err  | 
134 | 178 | 	}  | 
135 |  | -	packages := map[string]catalogd.Package{}  | 
136 |  | -	for _, pkg := range packageMetdatas.Items {  | 
137 |  | -		packages[pkg.Name] = pkg  | 
 | 179 | + | 
 | 180 | +	contents := []T{}  | 
 | 181 | +	for _, cm := range cmList.Items {  | 
 | 182 | +		var content T  | 
 | 183 | +		if err := json.Unmarshal(cm.Spec.Content, &content); err != nil {  | 
 | 184 | +			return nil, err  | 
 | 185 | +		}  | 
 | 186 | +		contents = append(contents, content)  | 
138 | 187 | 	}  | 
139 |  | -	return bundleMetadatas, packages, nil  | 
 | 188 | + | 
 | 189 | +	return contents, nil  | 
140 | 190 | }  | 
0 commit comments