Skip to content

Commit fd20c2f

Browse files
committed
poc release bundle attribute in version property
Signed-off-by: grokspawn <jordan@nimblewidget.com>
1 parent 24737fb commit fd20c2f

File tree

6 files changed

+103
-14
lines changed

6 files changed

+103
-14
lines changed

alpha/declcfg/declcfg_to_model.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -147,6 +147,7 @@ func ConvertToModel(cfg DeclarativeConfig) (model.Model, error) {
147147
mb.Objects = b.Objects
148148
mb.PropertiesP = props
149149
mb.Version = ver
150+
mb.Release = props.Packages[0].Release
150151
}
151152
}
152153
if !found {

alpha/declcfg/helpers_test.go

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -145,6 +145,16 @@ func withNoBundleData() func(*Bundle) {
145145
}
146146
}
147147

148+
func withReleaseVersion(packageName, version string, rel property.Release) func(*Bundle) {
149+
return func(b *Bundle) {
150+
for i, p := range b.Properties {
151+
if p.Type == property.TypePackage {
152+
b.Properties[i] = property.MustBuildPackageRelease(packageName, version, rel.Label, rel.Version.String())
153+
}
154+
}
155+
}
156+
}
157+
148158
func newTestBundle(packageName, version string, opts ...bundleOpt) Bundle {
149159
csvJSON := fmt.Sprintf(`{"kind": "ClusterServiceVersion", "apiVersion": "operators.coreos.com/v1alpha1", "metadata":{"name":%q}}`, testBundleName(packageName, version))
150160
b := Bundle{

alpha/model/model.go

Lines changed: 52 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ package model
33
import (
44
"errors"
55
"fmt"
6+
"slices"
67
"sort"
78
"strings"
89

@@ -103,24 +104,24 @@ func (m *Package) Validate() error {
103104
}
104105

105106
func (m *Package) validateUniqueBundleVersions() error {
106-
versionsMap := map[string]semver.Version{}
107+
versionsMap := map[string]string{}
107108
bundlesWithVersion := map[string]sets.Set[string]{}
108109
for _, ch := range m.Channels {
109110
for _, b := range ch.Bundles {
110-
versionsMap[b.Version.String()] = b.Version
111-
if bundlesWithVersion[b.Version.String()] == nil {
112-
bundlesWithVersion[b.Version.String()] = sets.New[string]()
111+
versionsMap[b.VersionString()] = b.VersionString()
112+
if bundlesWithVersion[b.VersionString()] == nil {
113+
bundlesWithVersion[b.VersionString()] = sets.New[string]()
113114
}
114-
bundlesWithVersion[b.Version.String()].Insert(b.Name)
115+
bundlesWithVersion[b.VersionString()].Insert(b.Name)
115116
}
116117
}
117118

118119
versionsSlice := maps.Values(versionsMap)
119-
semver.Sort(versionsSlice)
120+
slices.Sort(versionsSlice)
120121

121122
var errs []error
122123
for _, v := range versionsSlice {
123-
bundles := sets.List(bundlesWithVersion[v.String()])
124+
bundles := sets.List(bundlesWithVersion[v])
124125
if len(bundles) > 1 {
125126
errs = append(errs, fmt.Errorf("{%s: [%s]}", v, strings.Join(bundles, ", ")))
126127
}
@@ -331,6 +332,47 @@ type Bundle struct {
331332
// These fields are used to compare bundles in a diff.
332333
PropertiesP *property.Properties
333334
Version semver.Version
335+
Release property.Release
336+
}
337+
338+
func (b *Bundle) VersionString() string {
339+
if b.Release.Label != "" || (b.Release.Version.Major != 0 || b.Release.Version.Minor != 0 || b.Release.Version.Patch != 0) {
340+
return strings.Join([]string{b.Version.String(), b.Release.String()}, "-")
341+
} else {
342+
return b.Version.String()
343+
}
344+
}
345+
346+
func (b *Bundle) normalizeName() string {
347+
// if the bundle has release versioning, then the name must include this in standard form:
348+
// <package-name>-<version>-<release label>-<release version>
349+
// if no release versioning exists, then just return the bundle name
350+
if b.Release.Label != "" || (b.Release.Version.Major != 0 || b.Release.Version.Minor != 0 || b.Release.Version.Patch != 0) {
351+
return strings.Join([]string{b.Package.Name, b.Version.String(), b.Release.String()}, "-")
352+
} else {
353+
return b.Name
354+
}
355+
}
356+
357+
// order by release, if present
358+
// - label first, if present;
359+
// - then version, if present;
360+
//
361+
// then version
362+
func (b *Bundle) Compare(other *Bundle) int {
363+
if b.Name == other.Name {
364+
return 0
365+
}
366+
if b.Release.Label != other.Release.Label {
367+
return strings.Compare(b.Release.Label, other.Release.Label)
368+
}
369+
if b.Release.Version.NE(other.Release.Version) {
370+
return b.Release.Version.Compare(other.Release.Version)
371+
}
372+
if b.Version.NE(other.Version) {
373+
return b.Version.Compare(other.Version)
374+
}
375+
return 0
334376
}
335377

336378
func (b *Bundle) Validate() error {
@@ -339,6 +381,9 @@ func (b *Bundle) Validate() error {
339381
if b.Name == "" {
340382
result.subErrors = append(result.subErrors, errors.New("name must be set"))
341383
}
384+
if b.Name != b.normalizeName() {
385+
result.subErrors = append(result.subErrors, fmt.Errorf("name %q does not match normalized name %q", b.Name, b.normalizeName()))
386+
}
342387
if b.Channel == nil {
343388
result.subErrors = append(result.subErrors, errors.New("channel must be set"))
344389
}

alpha/property/property.go

Lines changed: 24 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,9 +6,11 @@ import (
66
"errors"
77
"fmt"
88
"reflect"
9+
"strings"
910

1011
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
1112

13+
"github.com/blang/semver/v4"
1214
"github.com/operator-framework/api/pkg/operators/v1alpha1"
1315
)
1416

@@ -35,9 +37,15 @@ func (p Property) String() string {
3537
return fmt.Sprintf("type: %q, value: %q", p.Type, p.Value)
3638
}
3739

40+
type Release struct {
41+
Label string `json:"label"`
42+
Version semver.Version `json:"version"`
43+
}
44+
3845
type Package struct {
39-
PackageName string `json:"packageName"`
40-
Version string `json:"version"`
46+
PackageName string `json:"packageName"`
47+
Version string `json:"version"`
48+
Release Release `json:"release,omitzero"`
4149
}
4250

4351
// NOTICE: The Channel properties are for internal use only.
@@ -247,6 +255,9 @@ func jsonMarshal(p interface{}) ([]byte, error) {
247255
func MustBuildPackage(name, version string) Property {
248256
return MustBuild(&Package{PackageName: name, Version: version})
249257
}
258+
func MustBuildPackageRelease(name, version, relLabel, relVersion string) Property {
259+
return MustBuild(&Package{PackageName: name, Version: version, Release: Release{Label: relLabel, Version: semver.MustParse(relVersion)}})
260+
}
250261
func MustBuildPackageRequired(name, versionRange string) Property {
251262
return MustBuild(&PackageRequired{name, versionRange})
252263
}
@@ -286,3 +297,14 @@ func MustBuildCSVMetadata(csv v1alpha1.ClusterServiceVersion) Property {
286297
func MustBuildChannelPriority(name string, priority int) Property {
287298
return MustBuild(&Channel{ChannelName: name, Priority: priority})
288299
}
300+
301+
func (r *Release) String() string {
302+
segments := []string{}
303+
if r.Label != "" {
304+
segments = append(segments, r.Label)
305+
}
306+
if r.Version.Major != 0 || r.Version.Minor != 0 || r.Version.Patch != 0 {
307+
segments = append(segments, r.Version.String())
308+
}
309+
return strings.Join(segments, "-")
310+
}

alpha/property/property_test.go

Lines changed: 12 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ import (
44
"encoding/json"
55
"testing"
66

7+
"github.com/blang/semver/v4"
78
"github.com/stretchr/testify/assert"
89
"github.com/stretchr/testify/require"
910
)
@@ -132,12 +133,12 @@ func TestParse(t *testing.T) {
132133
},
133134
expectProps: &Properties{
134135
Packages: []Package{
135-
{"package1", "0.1.0"},
136-
{"package2", "0.2.0"},
136+
{PackageName: "package1", Version: "0.1.0"},
137+
{PackageName: "package2", Version: "0.2.0"},
137138
},
138139
PackagesRequired: []PackageRequired{
139-
{"package3", ">=1.0.0 <2.0.0-0"},
140-
{"package4", ">=2.0.0 <3.0.0-0"},
140+
{PackageName: "package3", VersionRange: ">=1.0.0 <2.0.0-0"},
141+
{PackageName: "package4", VersionRange: ">=2.0.0 <3.0.0-0"},
141142
},
142143
GVKs: []GVK{
143144
{"group", "Kind1", "v1"},
@@ -206,10 +207,16 @@ func TestBuild(t *testing.T) {
206207
specs := []spec{
207208
{
208209
name: "Success/Package",
209-
input: &Package{"name", "0.1.0"},
210+
input: &Package{PackageName: "name", Version: "0.1.0"},
210211
assertion: require.NoError,
211212
expectedProperty: propPtr(MustBuildPackage("name", "0.1.0")),
212213
},
214+
{
215+
name: "Success/Package-ReleaseVersion",
216+
input: &Package{PackageName: "name", Version: "0.1.0", Release: Release{Label: "alpha-whatsit", Version: semver.MustParse("1.1.0-bluefoot")}},
217+
assertion: require.NoError,
218+
expectedProperty: propPtr(MustBuildPackageRelease("name", "0.1.0", "alpha-whatsit", "1.1.0-bluefoot")),
219+
},
213220
{
214221
name: "Success/PackageRequired",
215222
input: &PackageRequired{"name", ">=0.1.0"},

pkg/cache/cache.go

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -367,6 +367,10 @@ func (c *cache) processPackage(ctx context.Context, reader io.Reader) (packageIn
367367
if err != nil {
368368
return nil, err
369369
}
370+
371+
// TODO: for each input channel, adjust the entries to respect re-ordering by release attributes as required
372+
// do so as FBC so that the routine may be made common, and re-used for OLMv1
373+
370374
pkgModel, err := declcfg.ConvertToModel(*pkgFbc)
371375
if err != nil {
372376
return nil, err

0 commit comments

Comments
 (0)