Skip to content

Commit 78826e7

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

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
}
@@ -327,6 +328,47 @@ type Bundle struct {
327328
// These fields are used to compare bundles in a diff.
328329
PropertiesP *property.Properties
329330
Version semver.Version
331+
Release property.Release
332+
}
333+
334+
func (b *Bundle) VersionString() string {
335+
if b.Release.Label != "" || (b.Release.Version.Major != 0 || b.Release.Version.Minor != 0 || b.Release.Version.Patch != 0) {
336+
return strings.Join([]string{b.Version.String(), b.Release.String()}, "-")
337+
} else {
338+
return b.Version.String()
339+
}
340+
}
341+
342+
func (b *Bundle) normalizeName() string {
343+
// if the bundle has release versioning, then the name must include this in standard form:
344+
// <package-name>-<version>-<release label>-<release version>
345+
// if no release versioning exists, then just return the bundle name
346+
if b.Release.Label != "" || (b.Release.Version.Major != 0 || b.Release.Version.Minor != 0 || b.Release.Version.Patch != 0) {
347+
return strings.Join([]string{b.Package.Name, b.Version.String(), b.Release.String()}, "-")
348+
} else {
349+
return b.Name
350+
}
351+
}
352+
353+
// order by release, if present
354+
// - label first, if present;
355+
// - then version, if present;
356+
//
357+
// then version
358+
func (b *Bundle) Compare(other *Bundle) int {
359+
if b.Name == other.Name {
360+
return 0
361+
}
362+
if b.Release.Label != other.Release.Label {
363+
return strings.Compare(b.Release.Label, other.Release.Label)
364+
}
365+
if b.Release.Version.NE(other.Release.Version) {
366+
return b.Release.Version.Compare(other.Release.Version)
367+
}
368+
if b.Version.NE(other.Version) {
369+
return b.Version.Compare(other.Version)
370+
}
371+
return 0
330372
}
331373

332374
func (b *Bundle) Validate() error {
@@ -335,6 +377,9 @@ func (b *Bundle) Validate() error {
335377
if b.Name == "" {
336378
result.subErrors = append(result.subErrors, errors.New("name must be set"))
337379
}
380+
if b.Name != b.normalizeName() {
381+
result.subErrors = append(result.subErrors, fmt.Errorf("name %q does not match normalized name %q", b.Name, b.normalizeName()))
382+
}
338383
if b.Channel == nil {
339384
result.subErrors = append(result.subErrors, errors.New("channel must be set"))
340385
}

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)