Skip to content

Commit 8ca0525

Browse files
committed
Introduce Masterminds/semver
Add support for Masterminds/semver for .spec.Version This is a bit more entangled into the code than I expected, most instances of bsemver were replaced. Signed-off-by: Todd Short <[email protected]>
1 parent 8bce29c commit 8ca0525

File tree

11 files changed

+75
-31
lines changed

11 files changed

+75
-31
lines changed

go.mod

+1
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ module github.com/operator-framework/operator-controller
33
go 1.20
44

55
require (
6+
github.com/Masterminds/semver/v3 v3.2.0
67
github.com/blang/semver/v4 v4.0.0
78
github.com/go-logr/logr v1.2.4
89
github.com/onsi/ginkgo/v2 v2.11.0

go.sum

+2
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,8 @@ github.com/Azure/go-autorest/logger v0.2.0/go.mod h1:T9E3cAhj2VqvPOtCYAvby9aBXkZ
4848
github.com/Azure/go-autorest/tracing v0.6.0/go.mod h1:+vhtPC754Xsa23ID7GlGsrdKBpUA79WCAKPPZVC2DeU=
4949
github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU=
5050
github.com/BurntSushi/xgb v0.0.0-20160522181843-27f122750802/go.mod h1:IVnqGOEym/WlBOVXweHU+Q+/VP0lqqI8lqeDx9IjBqo=
51+
github.com/Masterminds/semver/v3 v3.2.0 h1:3MEsd0SM6jqZojhjLWWeBY+Kcjy9i6MQAeY7YgDP83g=
52+
github.com/Masterminds/semver/v3 v3.2.0/go.mod h1:qvl/7zhW3nngYb5+80sSMF+FG2BjYrf8m9wsX0PNOMQ=
5153
github.com/Microsoft/go-winio v0.4.11/go.mod h1:VhR8bwka0BXejwEJY73c50VrPtXAaKcyvVC4A4RozmA=
5254
github.com/Microsoft/go-winio v0.4.14/go.mod h1:qXqCSQ3Xa7+6tgxaGTIe4Kpcdsi+P8jBhyzoq1bpyYA=
5355
github.com/Microsoft/go-winio v0.4.15-0.20190919025122-fc70bd9a86b5/go.mod h1:tTuCMEN+UleMWgg9dVx4Hu52b1bJo+59jBh3ajtinzw=

internal/controllers/validators/validators.go

+2-2
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ package validators
33
import (
44
"fmt"
55

6-
bsemver "github.com/blang/semver/v4"
6+
mmsemver "github.com/Masterminds/semver/v3"
77

88
operatorsv1alpha1 "github.com/operator-framework/operator-controller/api/v1alpha1"
99
)
@@ -18,7 +18,7 @@ func validateSemver(operator *operatorsv1alpha1.Operator) error {
1818
if operator.Spec.Version == "" {
1919
return nil
2020
}
21-
if _, err := bsemver.Parse(operator.Spec.Version); err != nil {
21+
if _, err := mmsemver.NewConstraint(operator.Spec.Version); err != nil {
2222
return fmt.Errorf("invalid .spec.version: %w", err)
2323
}
2424
return nil

internal/resolution/entities/bundle_entity.go

+22-6
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ import (
55
"fmt"
66
"sync"
77

8+
mmsemver "github.com/Masterminds/semver/v3"
89
bsemver "github.com/blang/semver/v4"
910
"github.com/operator-framework/deppy/pkg/deppy/input"
1011
"github.com/operator-framework/operator-registry/alpha/property"
@@ -67,7 +68,8 @@ type BundleEntity struct {
6768
requiredPackages []PackageRequired
6869
channel *property.Channel
6970
channelEntry *ChannelEntry
70-
semVersion *bsemver.Version
71+
bSemVersion *bsemver.Version
72+
mmSemVersion *mmsemver.Version
7173
bundlePath string
7274
mediaType string
7375
mu sync.RWMutex
@@ -87,11 +89,18 @@ func (b *BundleEntity) PackageName() (string, error) {
8789
return b.bundlePackage.PackageName, nil
8890
}
8991

90-
func (b *BundleEntity) Version() (*bsemver.Version, error) {
92+
func (b *BundleEntity) VersionBlang() (*bsemver.Version, error) {
9193
if err := b.loadPackage(); err != nil {
9294
return nil, err
9395
}
94-
return b.semVersion, nil
96+
return b.bSemVersion, nil
97+
}
98+
99+
func (b *BundleEntity) VersionMasterminds() (*mmsemver.Version, error) {
100+
if err := b.loadPackage(); err != nil {
101+
return nil, err
102+
}
103+
return b.mmSemVersion, nil
95104
}
96105

97106
func (b *BundleEntity) ProvidedGVKs() ([]GVK, error) {
@@ -186,12 +195,19 @@ func (b *BundleEntity) loadPackage() error {
186195
return fmt.Errorf("error determining package for entity '%s': %w", b.ID, err)
187196
}
188197
b.bundlePackage = &bundlePackage
189-
if b.semVersion == nil {
198+
if b.bSemVersion == nil {
190199
semVer, err := bsemver.Parse(b.bundlePackage.Version)
191200
if err != nil {
192-
return fmt.Errorf("could not parse semver (%s) for entity '%s': %w", b.bundlePackage.Version, b.ID, err)
201+
return fmt.Errorf("could not parse bsemver (%s) for entity '%s': %w", b.bundlePackage.Version, b.ID, err)
202+
}
203+
b.bSemVersion = &semVer
204+
}
205+
if b.mmSemVersion == nil {
206+
semVer, err := mmsemver.NewVersion(b.bundlePackage.Version)
207+
if err != nil {
208+
return fmt.Errorf("could not parse mmsemver (%s) for entity '%s': %w", b.bundlePackage.Version, b.ID, err)
193209
}
194-
b.semVersion = &semVer
210+
b.mmSemVersion = semVer
195211
}
196212
}
197213
return nil

internal/resolution/entities/bundle_entity_test.go

+16-6
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ import (
44
"fmt"
55
"testing"
66

7+
mmsemver "github.com/Masterminds/semver/v3"
78
bsemver "github.com/blang/semver/v4"
89
. "github.com/onsi/ginkgo/v2"
910
. "github.com/onsi/gomega"
@@ -48,19 +49,28 @@ var _ = Describe("BundleEntity", func() {
4849
})
4950

5051
Describe("Version", func() {
51-
It("should return the bundle version if present", func() {
52+
It("should return the bundle blang version if present", func() {
5253
entity := input.NewEntity("operatorhub/prometheus/0.14.0", map[string]string{
5354
"olm.package": "{\"packageName\":\"prometheus\",\"version\":\"0.14.0\"}",
5455
})
5556
bundleEntity := olmentity.NewBundleEntity(entity)
56-
version, err := bundleEntity.Version()
57+
version, err := bundleEntity.VersionBlang()
5758
Expect(err).ToNot(HaveOccurred())
5859
Expect(*version).To(Equal(bsemver.MustParse("0.14.0")))
5960
})
61+
It("should return the bundle Masterminds version if present", func() {
62+
entity := input.NewEntity("operatorhub/prometheus/0.14.0", map[string]string{
63+
"olm.package": "{\"packageName\":\"prometheus\",\"version\":\"0.14.0\"}",
64+
})
65+
bundleEntity := olmentity.NewBundleEntity(entity)
66+
version, err := bundleEntity.VersionMasterminds()
67+
Expect(err).ToNot(HaveOccurred())
68+
Expect(*version).To(Equal(*mmsemver.MustParse("0.14.0")))
69+
})
6070
It("should return an error if the property is not found", func() {
6171
entity := input.NewEntity("operatorhub/prometheus/0.14.0", map[string]string{})
6272
bundleEntity := olmentity.NewBundleEntity(entity)
63-
version, err := bundleEntity.Version()
73+
version, err := bundleEntity.VersionBlang()
6474
Expect(version).To(BeNil())
6575
Expect(err.Error()).To(Equal("error determining package for entity 'operatorhub/prometheus/0.14.0': required property 'olm.package' not found"))
6676
})
@@ -69,7 +79,7 @@ var _ = Describe("BundleEntity", func() {
6979
"olm.package": "badPackageStructure",
7080
})
7181
bundleEntity := olmentity.NewBundleEntity(entity)
72-
version, err := bundleEntity.Version()
82+
version, err := bundleEntity.VersionBlang()
7383
Expect(version).To(BeNil())
7484
Expect(err.Error()).To(Equal("error determining package for entity 'operatorhub/prometheus/0.14.0': property 'olm.package' ('badPackageStructure') could not be parsed: invalid character 'b' looking for beginning of value"))
7585
})
@@ -78,9 +88,9 @@ var _ = Describe("BundleEntity", func() {
7888
"olm.package": "{\"packageName\":\"prometheus\",\"version\":\"badversion\"}",
7989
})
8090
bundleEntity := olmentity.NewBundleEntity(entity)
81-
version, err := bundleEntity.Version()
91+
version, err := bundleEntity.VersionBlang()
8292
Expect(version).To(BeNil())
83-
Expect(err.Error()).To(Equal("could not parse semver (badversion) for entity 'operatorhub/prometheus/0.14.0': No Major.Minor.Patch elements found"))
93+
Expect(err.Error()).To(Equal("could not parse bsemver (badversion) for entity 'operatorhub/prometheus/0.14.0': No Major.Minor.Patch elements found"))
8494
})
8595
})
8696

internal/resolution/util/predicates/predicates.go

+14-2
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
package predicates
22

33
import (
4+
mmsemver "github.com/Masterminds/semver/v3"
45
bsemver "github.com/blang/semver/v4"
56
"github.com/operator-framework/deppy/pkg/deppy/input"
67

@@ -18,10 +19,21 @@ func WithPackageName(packageName string) input.Predicate {
1819
}
1920
}
2021

21-
func InSemverRange(semverRange bsemver.Range) input.Predicate {
22+
func InMastermindsSemverRange(semverRange *mmsemver.Constraints) input.Predicate {
2223
return func(entity *input.Entity) bool {
2324
bundleEntity := olmentity.NewBundleEntity(entity)
24-
bundleVersion, err := bundleEntity.Version()
25+
bundleVersion, err := bundleEntity.VersionMasterminds()
26+
if err != nil {
27+
return false
28+
}
29+
return semverRange.Check(bundleVersion)
30+
}
31+
}
32+
33+
func InBlangSemverRange(semverRange bsemver.Range) input.Predicate {
34+
return func(entity *input.Entity) bool {
35+
bundleEntity := olmentity.NewBundleEntity(entity)
36+
bundleVersion, err := bundleEntity.VersionBlang()
2537
if err != nil {
2638
return false
2739
}

internal/resolution/util/predicates/predicates_test.go

+10-7
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ package predicates_test
33
import (
44
"testing"
55

6-
bsemver "github.com/blang/semver/v4"
6+
mmsemver "github.com/Masterminds/semver/v3"
77
. "github.com/onsi/ginkgo/v2"
88
. "github.com/onsi/gomega"
99
"github.com/operator-framework/deppy/pkg/deppy/input"
@@ -38,15 +38,18 @@ var _ = Describe("Predicates", func() {
3838
entity := input.NewEntity("test", map[string]string{
3939
property.TypePackage: `{"packageName": "mypackage", "version": "1.0.0"}`,
4040
})
41-
inRange := bsemver.MustParseRange(">=1.0.0")
42-
notInRange := bsemver.MustParseRange(">=2.0.0")
43-
Expect(predicates.InSemverRange(inRange)(entity)).To(BeTrue())
44-
Expect(predicates.InSemverRange(notInRange)(entity)).To(BeFalse())
41+
inRange, err := mmsemver.NewConstraint(">=1.0.0")
42+
Expect(err).NotTo(HaveOccurred())
43+
notInRange, err := mmsemver.NewConstraint(">=2.0.0")
44+
Expect(err).NotTo(HaveOccurred())
45+
Expect(predicates.InMastermindsSemverRange(inRange)(entity)).To(BeTrue())
46+
Expect(predicates.InMastermindsSemverRange(notInRange)(entity)).To(BeFalse())
4547
})
4648
It("should return false when the entity does not have a version", func() {
4749
entity := input.NewEntity("test", map[string]string{})
48-
inRange := bsemver.MustParseRange(">=1.0.0")
49-
Expect(predicates.InSemverRange(inRange)(entity)).To(BeFalse())
50+
inRange, err := mmsemver.NewConstraint(">=1.0.0")
51+
Expect(err).NotTo(HaveOccurred())
52+
Expect(predicates.InMastermindsSemverRange(inRange)(entity)).To(BeFalse())
5053
})
5154
})
5255

internal/resolution/util/sort/sort.go

+2-2
Original file line numberDiff line numberDiff line change
@@ -68,8 +68,8 @@ func channelOrder(e1, e2 *entities.BundleEntity) int {
6868
}
6969

7070
func versionOrder(e1, e2 *entities.BundleEntity) int {
71-
ver1, err1 := e1.Version()
72-
ver2, err2 := e2.Version()
71+
ver1, err1 := e1.VersionBlang()
72+
ver2, err2 := e2.VersionBlang()
7373
errComp := compareErrors(err1, err2)
7474
if errComp != 0 {
7575
// the sign gets inverted because version is sorted

internal/resolution/variablesources/bundles_and_dependencies.go

+1-1
Original file line numberDiff line numberDiff line change
@@ -91,7 +91,7 @@ func (b *BundlesAndDepsVariableSource) getEntityDependencies(ctx context.Context
9191
if err != nil {
9292
return nil, err
9393
}
94-
packageDependencyBundles, err := entitySource.Filter(ctx, input.And(predicates.WithPackageName(requiredPackage.PackageName), predicates.InSemverRange(semverRange)))
94+
packageDependencyBundles, err := entitySource.Filter(ctx, input.And(predicates.WithPackageName(requiredPackage.PackageName), predicates.InBlangSemverRange(semverRange)))
9595
if err != nil {
9696
return nil, err
9797
}

internal/resolution/variablesources/required_package.go

+4-4
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ import (
44
"context"
55
"fmt"
66

7-
bsemver "github.com/blang/semver/v4"
7+
mmsemver "github.com/Masterminds/semver/v3"
88
"github.com/operator-framework/deppy/pkg/deppy"
99
"github.com/operator-framework/deppy/pkg/deppy/input"
1010

@@ -21,14 +21,14 @@ type RequiredPackageVariableSourceOption func(*RequiredPackageVariableSource) er
2121
func InVersionRange(versionRange string) RequiredPackageVariableSourceOption {
2222
return func(r *RequiredPackageVariableSource) error {
2323
if versionRange != "" {
24-
vr, err := bsemver.ParseRange(versionRange)
24+
vr, err := mmsemver.NewConstraint(versionRange)
2525
if err == nil {
2626
r.versionRange = versionRange
27-
r.predicates = append(r.predicates, predicates.InSemverRange(vr))
27+
r.predicates = append(r.predicates, predicates.InMastermindsSemverRange(vr))
2828
return nil
2929
}
3030

31-
return fmt.Errorf("invalid version range '%s': %v", versionRange, err)
31+
return fmt.Errorf("invalid version range '%s': %w", versionRange, err)
3232
}
3333
return nil
3434
}

internal/resolution/variablesources/required_package_test.go

+1-1
Original file line numberDiff line numberDiff line change
@@ -80,7 +80,7 @@ var _ = Describe("RequiredPackageVariableSource", func() {
8080
It("should filter by version range", func() {
8181
// recreate source with version range option
8282
var err error
83-
rpvs, err = variablesources.NewRequiredPackageVariableSource(packageName, variablesources.InVersionRange(">=1.0.0 !2.0.0 <3.0.0"))
83+
rpvs, err = variablesources.NewRequiredPackageVariableSource(packageName, variablesources.InVersionRange(">=1.0.0 !=2.0.0 <3.0.0"))
8484
Expect(err).NotTo(HaveOccurred())
8585

8686
variables, err := rpvs.GetVariables(context.TODO(), mockEntitySource)

0 commit comments

Comments
 (0)