Skip to content

Commit 92fa7be

Browse files
committed
fbc: promote bundle version from property to first-class field
Signed-off-by: Joe Lanford <[email protected]>
1 parent 8d87866 commit 92fa7be

File tree

8 files changed

+73
-20
lines changed

8 files changed

+73
-20
lines changed
Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
package migrations
2+
3+
import (
4+
"encoding/json"
5+
"slices"
6+
7+
"github.com/Masterminds/semver/v3"
8+
9+
"github.com/operator-framework/operator-registry/alpha/declcfg"
10+
"github.com/operator-framework/operator-registry/alpha/property"
11+
)
12+
13+
func promoteBundleVersion(cfg *declcfg.DeclarativeConfig) error {
14+
promoteVersion := func(b *declcfg.Bundle) error {
15+
// Promote the version from the olm.package property to the bundle field.
16+
for _, p := range b.Properties {
17+
if p.Type != property.TypePackage {
18+
continue
19+
}
20+
var pkg property.Package
21+
if err := json.Unmarshal(p.Value, &pkg); err != nil {
22+
return err
23+
}
24+
version, err := semver.StrictNewVersion(pkg.Version)
25+
if err != nil {
26+
return err
27+
}
28+
b.Version = version
29+
}
30+
31+
// Delete the olm.package properties
32+
b.Properties = slices.DeleteFunc(b.Properties, func(p property.Property) bool {
33+
return p.Type == property.TypePackage
34+
})
35+
return nil
36+
}
37+
38+
for i := range cfg.Bundles {
39+
if err := promoteVersion(&cfg.Bundles[i]); err != nil {
40+
return err
41+
}
42+
}
43+
return nil
44+
}

alpha/action/migrations/migrations.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,7 @@ 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),
5757
newMigration("split-icon", `split package icon out into separate "olm.icon" blob`, splitIcon),
58+
newMigration("promote-bundle-version", `promote bundle version into first-class bundle field, remove olm.package properties`, promoteBundleVersion),
5859
}
5960

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

alpha/declcfg/declcfg.go

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ import (
66
"errors"
77
"fmt"
88

9+
"github.com/Masterminds/semver/v3"
910
"golang.org/x/text/cases"
1011
utilerrors "k8s.io/apimachinery/pkg/util/errors"
1112
"k8s.io/apimachinery/pkg/util/sets"
@@ -90,8 +91,9 @@ type ChannelEntry struct {
9091
// evaluation in bundlesEqual().
9192
type Bundle struct {
9293
Schema string `json:"schema"`
93-
Name string `json:"name,omitempty"`
94-
Package string `json:"package,omitempty"`
94+
Name string `json:"name"`
95+
Package string `json:"package"`
96+
Version *semver.Version `json:"version,omitempty"`
9597
Image string `json:"image"`
9698
Properties []property.Property `json:"properties,omitempty" hash:"set"`
9799
RelatedImages []RelatedImage `json:"relatedImages,omitempty" hash:"set"`

alpha/declcfg/declcfg_to_model.go

Lines changed: 10 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -140,16 +140,18 @@ func ConvertToModel(cfg DeclarativeConfig) (model.Model, error) {
140140
return nil, fmt.Errorf("parse properties for bundle %q: %v", b.Name, err)
141141
}
142142

143-
if len(props.Packages) != 1 {
144-
return nil, fmt.Errorf("package %q bundle %q must have exactly 1 %q property, found %d", b.Package, b.Name, property.TypePackage, len(props.Packages))
145-
}
146-
147-
if b.Package != props.Packages[0].PackageName {
148-
return nil, fmt.Errorf("package %q does not match %q property %q", b.Package, property.TypePackage, props.Packages[0].PackageName)
143+
var rawVersion string
144+
if b.Version != nil {
145+
rawVersion = b.Version.String()
146+
} else if len(props.Packages) == 1 {
147+
if b.Package != props.Packages[0].PackageName {
148+
return nil, fmt.Errorf("package %q does not match %q property %q", b.Package, property.TypePackage, props.Packages[0].PackageName)
149+
}
150+
rawVersion = props.Packages[0].Version
151+
} else {
152+
return nil, fmt.Errorf("package %q bundle %q requires either version being set or exactly one property with type %q", b.Package, b.Name, props.Packages[0].PackageName)
149153
}
150154

151-
// Parse version from the package property.
152-
rawVersion := props.Packages[0].Version
153155
ver, err := semver.Parse(rawVersion)
154156
if err != nil {
155157
return nil, fmt.Errorf("error parsing bundle %q version %q: %v", b.Name, rawVersion, err)

alpha/model/model.go

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -338,6 +338,7 @@ type Bundle struct {
338338
Package *Package
339339
Channel *Channel
340340
Name string
341+
Version semver.Version
341342
Image string
342343
Replaces string
343344
Skips []string
@@ -354,7 +355,6 @@ type Bundle struct {
354355

355356
// These fields are used to compare bundles in a diff.
356357
PropertiesP *property.Properties
357-
Version semver.Version
358358
}
359359

360360
func (b *Bundle) Validate() error {
@@ -372,7 +372,7 @@ func (b *Bundle) Validate() error {
372372
if b.Channel != nil && b.Package != nil && b.Package != b.Channel.Package {
373373
result.subErrors = append(result.subErrors, errors.New("package does not match channel's package"))
374374
}
375-
props, err := property.Parse(b.Properties)
375+
_, err := property.Parse(b.Properties)
376376
if err != nil {
377377
result.subErrors = append(result.subErrors, err)
378378
}
@@ -391,8 +391,8 @@ func (b *Bundle) Validate() error {
391391
// }
392392
//}
393393

394-
if props != nil && len(props.Packages) != 1 {
395-
result.subErrors = append(result.subErrors, fmt.Errorf("must be exactly one property with type %q", property.TypePackage))
394+
if b.Version.String() == "0.0.0" {
395+
result.subErrors = append(result.subErrors, errors.New("version must be set"))
396396
}
397397

398398
if b.Image == "" && len(b.Objects) == 0 {

go.mod

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ go 1.23.3
55
toolchain go1.23.6
66

77
require (
8+
github.com/Masterminds/semver/v3 v3.3.1
89
github.com/akrylysov/pogreb v0.10.2
910
github.com/blang/semver/v4 v4.0.0
1011
github.com/containerd/containerd v1.7.27

go.sum

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,8 @@ github.com/BurntSushi/toml v1.5.0 h1:W5quZX/G/csjUnuI8SUYlsHs9M38FC7znL0lIO+DvMg
1414
github.com/BurntSushi/toml v1.5.0/go.mod h1:ukJfTF/6rtPPRCnwkur4qwRxa8vTRFBF0uk2lLoLwho=
1515
github.com/MakeNowJust/heredoc v1.0.0 h1:cXCdzVdstXyiTqTvfqk9SDHpKNjxuom+DOlyEeQ4pzQ=
1616
github.com/MakeNowJust/heredoc v1.0.0/go.mod h1:mG5amYoWBHf8vpLOuehzbGGw0EHxpZZ6lCpQ4fNJ8LE=
17+
github.com/Masterminds/semver/v3 v3.3.1 h1:QtNSWtVZ3nBfk8mAOu/B6v7FMJ+NHTIgUPi7rj+4nv4=
18+
github.com/Masterminds/semver/v3 v3.3.1/go.mod h1:4V+yj/TJE1HU9XfppCwVMZq3I84lprf4nC11bSS5beM=
1719
github.com/Microsoft/go-winio v0.6.2 h1:F2VQgta7ecxGYO8k3ZZz3RS8fVIXVxONVUPlNERoyfY=
1820
github.com/Microsoft/go-winio v0.6.2/go.mod h1:yd8OoFMLzJbo9gZq8j5qaps8bJ9aShtEA8Ipt1oGCvU=
1921
github.com/Microsoft/hcsshim v0.12.9 h1:2zJy5KA+l0loz1HzEGqyNnjd3fyZA31ZBCGKacp6lLg=

pkg/api/model_to_api.go

Lines changed: 7 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -64,17 +64,22 @@ func ConvertModelBundleToAPIBundle(b model.Bundle) (*Bundle, error) {
6464
if err != nil {
6565
return nil, fmt.Errorf("convert model properties to api dependencies: %v", err)
6666
}
67+
68+
properties := b.Properties
69+
if len(props.Packages) == 0 {
70+
properties = append(properties, property.MustBuildPackage(b.Package.Name, b.Version.String()))
71+
}
6772
return &Bundle{
6873
CsvName: b.Name,
6974
PackageName: b.Package.Name,
7075
ChannelName: b.Channel.Name,
7176
BundlePath: b.Image,
7277
ProvidedApis: gvksProvidedtoAPIGVKs(props.GVKs),
7378
RequiredApis: gvksRequirestoAPIGVKs(props.GVKsRequired),
74-
Version: props.Packages[0].Version,
79+
Version: b.Version.String(),
7580
SkipRange: b.SkipRange,
7681
Dependencies: apiDeps,
77-
Properties: convertModelPropertiesToAPIProperties(b.Properties),
82+
Properties: convertModelPropertiesToAPIProperties(properties),
7883
Replaces: b.Replaces,
7984
Skips: b.Skips,
8085
CsvJson: csvJSON,
@@ -89,10 +94,6 @@ func parseProperties(in []property.Property) (*property.Properties, error) {
8994
return nil, err
9095
}
9196

92-
if len(props.Packages) != 1 {
93-
return nil, fmt.Errorf("expected exactly 1 property of type %q, found %d", property.TypePackage, len(props.Packages))
94-
}
95-
9697
if len(props.CSVMetadatas) > 1 {
9798
return nil, fmt.Errorf("expected at most 1 property of type %q, found %d", property.TypeCSVMetadata, len(props.CSVMetadatas))
9899
}

0 commit comments

Comments
 (0)