Skip to content

Commit b1a7ca3

Browse files
committed
add olm.icon blob and migration
Signed-off-by: Joe Lanford <joe.lanford@gmail.com>
1 parent ef3bfdf commit b1a7ca3

File tree

14 files changed

+153
-19
lines changed

14 files changed

+153
-19
lines changed

alpha/action/init.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -43,7 +43,7 @@ func (i Init) Run() (*declcfg.Package, error) {
4343
if iconType.MIME.Type != "image" {
4444
return nil, fmt.Errorf("detected invalid type %q: not an image", iconType.MIME.Value)
4545
}
46-
pkg.Icon = &declcfg.Icon{
46+
pkg.Icon = &declcfg.PackageIcon{ //nolint:staticcheck
4747
Data: iconData,
4848
MediaType: iconType.MIME.Value,
4949
}

alpha/action/init_test.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -73,7 +73,7 @@ func TestInit(t *testing.T) {
7373
},
7474
expectPkg: &declcfg.Package{
7575
Schema: "olm.package",
76-
Icon: &declcfg.Icon{
76+
Icon: &declcfg.PackageIcon{
7777
Data: bytes.NewBufferString(svgIcon).Bytes(),
7878
MediaType: "image/svg+xml",
7979
},
@@ -93,7 +93,7 @@ func TestInit(t *testing.T) {
9393
Name: "a",
9494
DefaultChannel: "b",
9595
Description: "c",
96-
Icon: &declcfg.Icon{
96+
Icon: &declcfg.PackageIcon{
9797
Data: bytes.NewBufferString(svgIcon).Bytes(),
9898
MediaType: "image/svg+xml",
9999
},
Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
package migrations
2+
3+
import (
4+
"github.com/operator-framework/operator-registry/alpha/declcfg"
5+
)
6+
7+
func splitIcon(cfg *declcfg.DeclarativeConfig) error {
8+
splitIconFromPackage := func(p *declcfg.Package) error {
9+
if p.Icon == nil { //nolint:staticcheck
10+
return nil
11+
}
12+
13+
// Make separate olm.icon object
14+
cfg.Icons = append(cfg.Icons, declcfg.Icon{
15+
Schema: declcfg.SchemaIcon,
16+
Package: p.Name,
17+
MediaType: p.Icon.MediaType, //nolint:staticcheck
18+
Data: p.Icon.Data, //nolint:staticcheck
19+
})
20+
21+
// Delete original icon from olm.package object
22+
p.Icon = nil //nolint:staticcheck
23+
return nil
24+
}
25+
26+
for i := range cfg.Packages {
27+
if err := splitIconFromPackage(&cfg.Packages[i]); err != nil {
28+
return err
29+
}
30+
}
31+
return nil
32+
}

alpha/action/migrations/migrations.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,7 @@ type Migrations struct {
5454
var allMigrations = []Migration{
5555
newMigration(NoMigrations, "do nothing", func(_ *declcfg.DeclarativeConfig) error { return nil }),
5656
newMigration("bundle-object-to-csv-metadata", `migrates bundles' "olm.bundle.object" to "olm.csv.metadata"`, bundleObjectToCSVMetadata),
57+
newMigration("split-icon", `split package icon out into separate "olm.icon" blob`, splitIcon),
5758
}
5859

5960
func NewMigrations(name string) (*Migrations, error) {

alpha/action/migrations/migrations_test.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,7 @@ func TestMigrations(t *testing.T) {
3737
}
3838
return nil
3939
},
40+
MigrationToken("split-icon"): func(d *declcfg.DeclarativeConfig) error { return nil },
4041
}
4142

4243
tests := []struct {

alpha/declcfg/declcfg.go

Lines changed: 21 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -16,29 +16,43 @@ import (
1616

1717
const (
1818
SchemaPackage = "olm.package"
19+
SchemaIcon = "olm.icon"
1920
SchemaChannel = "olm.channel"
2021
SchemaBundle = "olm.bundle"
2122
SchemaDeprecation = "olm.deprecations"
2223
)
2324

2425
type DeclarativeConfig struct {
2526
Packages []Package
27+
Icons []Icon
2628
Channels []Channel
2729
Bundles []Bundle
2830
Deprecations []Deprecation
2931
Others []Meta
3032
}
3133

3234
type Package struct {
33-
Schema string `json:"schema"`
34-
Name string `json:"name"`
35-
DefaultChannel string `json:"defaultChannel"`
36-
Icon *Icon `json:"icon,omitempty"`
37-
Description string `json:"description,omitempty"`
38-
Properties []property.Property `json:"properties,omitempty" hash:"set"`
35+
Schema string `json:"schema"`
36+
Name string `json:"name"`
37+
DefaultChannel string `json:"defaultChannel"`
38+
39+
// Deprecated: It is no longer recommended to embed an icon in the package.
40+
// Instead, use separate a Icon item alongside the Package.
41+
Icon *PackageIcon `json:"icon,omitempty"`
42+
43+
Description string `json:"description,omitempty"`
44+
Properties []property.Property `json:"properties,omitempty" hash:"set"`
3945
}
4046

4147
type Icon struct {
48+
Schema string `json:"schema"`
49+
Package string `json:"package"`
50+
51+
MediaType string `json:"mediaType"`
52+
Data []byte `json:"data"`
53+
}
54+
55+
type PackageIcon struct {
4256
Data []byte `json:"base64data"`
4357
MediaType string `json:"mediatype"`
4458
}
@@ -201,6 +215,7 @@ func extractUniqueMetaKeys(blobMap map[string]any, m *Meta) error {
201215

202216
func (destination *DeclarativeConfig) Merge(src *DeclarativeConfig) {
203217
destination.Packages = append(destination.Packages, src.Packages...)
218+
destination.Icons = append(destination.Icons, src.Icons...)
204219
destination.Channels = append(destination.Channels, src.Channels...)
205220
destination.Bundles = append(destination.Bundles, src.Bundles...)
206221
destination.Others = append(destination.Others, src.Others...)

alpha/declcfg/declcfg_to_model.go

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,13 @@ func ConvertToModel(cfg DeclarativeConfig) (model.Model, error) {
3131
Name: p.Name,
3232
Description: p.Description,
3333
Channels: map[string]*model.Channel{},
34+
35+
//DisplayName: p.DisplayName,
36+
//ShortDescription: p.ShortDescription,
37+
//Provider: p.Provider,
38+
//Maintainers: p.Maintainers,
39+
//Links: p.Links,
40+
//Keywords: p.Keywords,
3441
}
3542
if p.Icon != nil {
3643
mpkg.Icon = &model.Icon{
@@ -41,6 +48,19 @@ func ConvertToModel(cfg DeclarativeConfig) (model.Model, error) {
4148
defaultChannels[p.Name] = p.DefaultChannel
4249
mpkgs[p.Name] = mpkg
4350
}
51+
for _, i := range cfg.Icons {
52+
mpkg, ok := mpkgs[i.Package]
53+
if !ok {
54+
return nil, fmt.Errorf("unknown package %q found in olm.icon", i.Package)
55+
}
56+
if mpkg.Icon != nil {
57+
return nil, fmt.Errorf("duplicate icon found for package %q; expecting no more than one icon per package", i.Package)
58+
}
59+
mpkg.Icon = &model.Icon{
60+
MediaType: i.MediaType,
61+
Data: i.Data,
62+
}
63+
}
4464

4565
channelDefinedEntries := map[string]sets.Set[string]{}
4666
for _, c := range cfg.Channels {

alpha/declcfg/helpers_test.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -191,7 +191,7 @@ func newTestPackage(packageName, defaultChannel, svgData string) Package {
191191
Schema: SchemaPackage,
192192
Name: packageName,
193193
DefaultChannel: defaultChannel,
194-
Icon: &Icon{Data: []byte(svgData), MediaType: "image/svg+xml"},
194+
Icon: &PackageIcon{Data: []byte(svgData), MediaType: "image/svg+xml"},
195195
Description: testPackageDescription(packageName),
196196
}
197197
return p

alpha/declcfg/load.go

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -279,6 +279,7 @@ type fbcBuilder struct {
279279
cfg DeclarativeConfig
280280

281281
packagesMu sync.Mutex
282+
iconsMu sync.Mutex
282283
channelsMu sync.Mutex
283284
bundlesMu sync.Mutex
284285
deprecationsMu sync.Mutex
@@ -295,6 +296,14 @@ func (c *fbcBuilder) addMeta(in *Meta) error {
295296
c.packagesMu.Lock()
296297
c.cfg.Packages = append(c.cfg.Packages, p)
297298
c.packagesMu.Unlock()
299+
case SchemaIcon:
300+
var i Icon
301+
if err := json.Unmarshal(in.Blob, &i); err != nil {
302+
return fmt.Errorf("parse icon: %v", err)
303+
}
304+
c.iconsMu.Lock()
305+
c.cfg.Icons = append(c.cfg.Icons, i)
306+
c.iconsMu.Unlock()
298307
case SchemaChannel:
299308
var ch Channel
300309
if err := json.Unmarshal(in.Blob, &ch); err != nil {

alpha/declcfg/load_benchmark_test.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -59,7 +59,7 @@ func generateFBC(b *testing.B, numPackages, numChannels, numBundles int) *declcf
5959
Schema: declcfg.SchemaPackage,
6060
Name: pkgName,
6161
Description: fmt.Sprintf("%s description", pkgName),
62-
Icon: &declcfg.Icon{
62+
Icon: &declcfg.PackageIcon{
6363
Data: pngData,
6464
MediaType: "image/png",
6565
},

alpha/declcfg/load_test.go

Lines changed: 2 additions & 2 deletions
Large diffs are not rendered by default.

alpha/declcfg/model_to_declcfg.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -12,9 +12,9 @@ func ConvertFromModel(mpkgs model.Model) DeclarativeConfig {
1212
for _, mpkg := range mpkgs {
1313
channels, bundles := traverseModelChannels(*mpkg)
1414

15-
var i *Icon
15+
var i *PackageIcon
1616
if mpkg.Icon != nil {
17-
i = &Icon{
17+
i = &PackageIcon{
1818
Data: mpkg.Icon.Data,
1919
MediaType: mpkg.Icon.MediaType,
2020
}

alpha/declcfg/write.go

Lines changed: 31 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -405,6 +405,12 @@ func writeToEncoder(cfg DeclarativeConfig, enc encoder) error {
405405
pkgNames.Insert(pkgName)
406406
packagesByName[pkgName] = append(packagesByName[pkgName], p)
407407
}
408+
iconsByPackage := map[string][]Icon{}
409+
for _, i := range cfg.Icons {
410+
pkgName := i.Package
411+
pkgNames.Insert(pkgName)
412+
iconsByPackage[pkgName] = append(iconsByPackage[pkgName], i)
413+
}
408414
channelsByPackage := map[string][]Channel{}
409415
for _, c := range cfg.Channels {
410416
pkgName := c.Package
@@ -441,6 +447,13 @@ func writeToEncoder(cfg DeclarativeConfig, enc encoder) error {
441447
}
442448
}
443449

450+
icons := iconsByPackage[pName]
451+
for _, i := range icons {
452+
if err := enc.Encode(i); err != nil {
453+
return err
454+
}
455+
}
456+
444457
channels := channelsByPackage[pName]
445458
sort.Slice(channels, func(i, j int) bool {
446459
return channels[i].Name < channels[j].Name
@@ -501,6 +514,10 @@ func writeToEncoder(cfg DeclarativeConfig, enc encoder) error {
501514
type WriteFunc func(config DeclarativeConfig, w io.Writer) error
502515

503516
func WriteFS(cfg DeclarativeConfig, rootDir string, writeFunc WriteFunc, fileExt string) error {
517+
iconsByPackage := map[string][]Icon{}
518+
for _, i := range cfg.Icons {
519+
iconsByPackage[i.Package] = append(iconsByPackage[i.Package], i)
520+
}
504521
channelsByPackage := map[string][]Channel{}
505522
for _, c := range cfg.Channels {
506523
channelsByPackage[c.Package] = append(channelsByPackage[c.Package], c)
@@ -509,16 +526,27 @@ func WriteFS(cfg DeclarativeConfig, rootDir string, writeFunc WriteFunc, fileExt
509526
for _, b := range cfg.Bundles {
510527
bundlesByPackage[b.Package] = append(bundlesByPackage[b.Package], b)
511528
}
529+
deprecationsByPackage := map[string][]Deprecation{}
530+
for _, d := range cfg.Deprecations {
531+
deprecationsByPackage[d.Package] = append(deprecationsByPackage[d.Package], d)
532+
}
533+
othersByPackage := map[string][]Meta{}
534+
for _, o := range cfg.Others {
535+
othersByPackage[o.Package] = append(othersByPackage[o.Package], o)
536+
}
512537

513538
if err := os.MkdirAll(rootDir, 0777); err != nil {
514539
return err
515540
}
516541

517542
for _, p := range cfg.Packages {
518543
fcfg := DeclarativeConfig{
519-
Packages: []Package{p},
520-
Channels: channelsByPackage[p.Name],
521-
Bundles: bundlesByPackage[p.Name],
544+
Packages: []Package{p},
545+
Icons: iconsByPackage[p.Name],
546+
Channels: channelsByPackage[p.Name],
547+
Bundles: bundlesByPackage[p.Name],
548+
Deprecations: deprecationsByPackage[p.Name],
549+
Others: othersByPackage[p.Name],
522550
}
523551
pkgDir := filepath.Join(rootDir, p.Name)
524552
if err := os.MkdirAll(pkgDir, 0777); err != nil {

alpha/model/model.go

Lines changed: 29 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -44,12 +44,20 @@ func (m Model) Validate() error {
4444
}
4545

4646
type Package struct {
47-
Name string
47+
Name string
48+
4849
Description string
4950
Icon *Icon
5051
DefaultChannel *Channel
5152
Channels map[string]*Channel
5253
Deprecation *Deprecation
54+
55+
//DisplayName string
56+
//ShortDescription string
57+
//Provider v1alpha1.AppLink
58+
//Maintainers []v1alpha1.Maintainer
59+
//Links []v1alpha1.AppLink
60+
//Keywords []string
5361
}
5462

5563
func (m *Package) Validate() error {
@@ -59,6 +67,26 @@ func (m *Package) Validate() error {
5967
result.subErrors = append(result.subErrors, errors.New("package name must not be empty"))
6068
}
6169

70+
//if len(m.ShortDescription) > 128 {
71+
// result.subErrors = append(result.subErrors, errors.New("short description must not be more than 128 characters"))
72+
//}
73+
//
74+
//for i, maintainer := range m.Maintainers {
75+
// if maintainer.Name == "" && maintainer.Email == "" {
76+
// result.subErrors = append(result.subErrors, fmt.Errorf("maintainer at index %d must not be empty", i))
77+
// }
78+
//}
79+
//for i, link := range m.Links {
80+
// if link.Name == "" && link.URL == "" {
81+
// result.subErrors = append(result.subErrors, fmt.Errorf("link at index %d must not be empty", i))
82+
// }
83+
//}
84+
//for i, keyword := range m.Keywords {
85+
// if keyword == "" {
86+
// result.subErrors = append(result.subErrors, fmt.Errorf("keyword at index %d must not be empty", i))
87+
// }
88+
//}
89+
6290
if err := m.Icon.Validate(); err != nil {
6391
result.subErrors = append(result.subErrors, err)
6492
}

0 commit comments

Comments
 (0)