From ee305fd9433651949fefd071c69c46614336d2f1 Mon Sep 17 00:00:00 2001 From: Todd Short Date: Tue, 29 Aug 2023 15:31:36 -0400 Subject: [PATCH] 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 --- go.mod | 1 + go.sum | 2 ++ internal/controllers/validators/validators.go | 4 ++-- internal/resolution/entities/bundle_entity.go | 9 +++++---- internal/resolution/entities/bundle_entity_test.go | 6 +++--- internal/resolution/util/predicates/predicates.go | 6 +++--- .../resolution/util/predicates/predicates_test.go | 11 +++++++---- internal/resolution/util/sort/sort.go | 2 +- .../variablesources/bundles_and_dependencies.go | 4 ++-- .../resolution/variablesources/required_package.go | 6 +++--- .../variablesources/required_package_test.go | 2 +- 11 files changed, 30 insertions(+), 23 deletions(-) diff --git a/go.mod b/go.mod index 445daa2e3..dce8fd0ce 100644 --- a/go.mod +++ b/go.mod @@ -3,6 +3,7 @@ module github.com/operator-framework/operator-controller go 1.20 require ( + github.com/Masterminds/semver/v3 v3.2.0 github.com/blang/semver/v4 v4.0.0 github.com/go-logr/logr v1.2.4 github.com/onsi/ginkgo/v2 v2.11.0 diff --git a/go.sum b/go.sum index 25b504b25..794b9c01c 100644 --- a/go.sum +++ b/go.sum @@ -48,6 +48,8 @@ github.com/Azure/go-autorest/logger v0.2.0/go.mod h1:T9E3cAhj2VqvPOtCYAvby9aBXkZ github.com/Azure/go-autorest/tracing v0.6.0/go.mod h1:+vhtPC754Xsa23ID7GlGsrdKBpUA79WCAKPPZVC2DeU= github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= github.com/BurntSushi/xgb v0.0.0-20160522181843-27f122750802/go.mod h1:IVnqGOEym/WlBOVXweHU+Q+/VP0lqqI8lqeDx9IjBqo= +github.com/Masterminds/semver/v3 v3.2.0 h1:3MEsd0SM6jqZojhjLWWeBY+Kcjy9i6MQAeY7YgDP83g= +github.com/Masterminds/semver/v3 v3.2.0/go.mod h1:qvl/7zhW3nngYb5+80sSMF+FG2BjYrf8m9wsX0PNOMQ= github.com/Microsoft/go-winio v0.4.11/go.mod h1:VhR8bwka0BXejwEJY73c50VrPtXAaKcyvVC4A4RozmA= github.com/Microsoft/go-winio v0.4.14/go.mod h1:qXqCSQ3Xa7+6tgxaGTIe4Kpcdsi+P8jBhyzoq1bpyYA= github.com/Microsoft/go-winio v0.4.15-0.20190919025122-fc70bd9a86b5/go.mod h1:tTuCMEN+UleMWgg9dVx4Hu52b1bJo+59jBh3ajtinzw= diff --git a/internal/controllers/validators/validators.go b/internal/controllers/validators/validators.go index 3caa3f934..f71a7897d 100644 --- a/internal/controllers/validators/validators.go +++ b/internal/controllers/validators/validators.go @@ -3,7 +3,7 @@ package validators import ( "fmt" - bsemver "github.com/blang/semver/v4" + mmsemver "github.com/Masterminds/semver/v3" operatorsv1alpha1 "github.com/operator-framework/operator-controller/api/v1alpha1" ) @@ -18,7 +18,7 @@ func validateSemver(operator *operatorsv1alpha1.Operator) error { if operator.Spec.Version == "" { return nil } - if _, err := bsemver.Parse(operator.Spec.Version); err != nil { + if _, err := mmsemver.NewConstraint(operator.Spec.Version); err != nil { return fmt.Errorf("invalid .spec.version: %w", err) } return nil diff --git a/internal/resolution/entities/bundle_entity.go b/internal/resolution/entities/bundle_entity.go index b9ccf4cce..41a2c8f6a 100644 --- a/internal/resolution/entities/bundle_entity.go +++ b/internal/resolution/entities/bundle_entity.go @@ -5,6 +5,7 @@ import ( "fmt" "sync" + mmsemver "github.com/Masterminds/semver/v3" bsemver "github.com/blang/semver/v4" "github.com/operator-framework/deppy/pkg/deppy/input" "github.com/operator-framework/operator-registry/alpha/property" @@ -67,7 +68,7 @@ type BundleEntity struct { requiredPackages []PackageRequired channel *property.Channel channelEntry *ChannelEntry - semVersion *bsemver.Version + semVersion *mmsemver.Version bundlePath string mediaType string mu sync.RWMutex @@ -87,7 +88,7 @@ func (b *BundleEntity) PackageName() (string, error) { return b.bundlePackage.PackageName, nil } -func (b *BundleEntity) Version() (*bsemver.Version, error) { +func (b *BundleEntity) Version() (*mmsemver.Version, error) { if err := b.loadPackage(); err != nil { return nil, err } @@ -187,11 +188,11 @@ func (b *BundleEntity) loadPackage() error { } b.bundlePackage = &bundlePackage if b.semVersion == nil { - semVer, err := bsemver.Parse(b.bundlePackage.Version) + semVer, err := mmsemver.NewVersion(b.bundlePackage.Version) if err != nil { return fmt.Errorf("could not parse semver (%s) for entity '%s': %w", b.bundlePackage.Version, b.ID, err) } - b.semVersion = &semVer + b.semVersion = semVer } } return nil diff --git a/internal/resolution/entities/bundle_entity_test.go b/internal/resolution/entities/bundle_entity_test.go index 087575970..36e989c7a 100644 --- a/internal/resolution/entities/bundle_entity_test.go +++ b/internal/resolution/entities/bundle_entity_test.go @@ -4,7 +4,7 @@ import ( "fmt" "testing" - bsemver "github.com/blang/semver/v4" + mmsemver "github.com/Masterminds/semver/v3" . "github.com/onsi/ginkgo/v2" . "github.com/onsi/gomega" "github.com/operator-framework/deppy/pkg/deppy/input" @@ -55,7 +55,7 @@ var _ = Describe("BundleEntity", func() { bundleEntity := olmentity.NewBundleEntity(entity) version, err := bundleEntity.Version() Expect(err).ToNot(HaveOccurred()) - Expect(*version).To(Equal(bsemver.MustParse("0.14.0"))) + Expect(version).To(Equal(mmsemver.MustParse("0.14.0"))) }) It("should return an error if the property is not found", func() { entity := input.NewEntity("operatorhub/prometheus/0.14.0", map[string]string{}) @@ -80,7 +80,7 @@ var _ = Describe("BundleEntity", func() { bundleEntity := olmentity.NewBundleEntity(entity) version, err := bundleEntity.Version() Expect(version).To(BeNil()) - Expect(err.Error()).To(Equal("could not parse semver (badversion) for entity 'operatorhub/prometheus/0.14.0': No Major.Minor.Patch elements found")) + Expect(err.Error()).To(Equal("could not parse semver (badversion) for entity 'operatorhub/prometheus/0.14.0': Invalid Semantic Version")) }) }) diff --git a/internal/resolution/util/predicates/predicates.go b/internal/resolution/util/predicates/predicates.go index aa351b9e8..e24cec5f3 100644 --- a/internal/resolution/util/predicates/predicates.go +++ b/internal/resolution/util/predicates/predicates.go @@ -1,7 +1,7 @@ package predicates import ( - bsemver "github.com/blang/semver/v4" + mmsemver "github.com/Masterminds/semver/v3" "github.com/operator-framework/deppy/pkg/deppy/input" olmentity "github.com/operator-framework/operator-controller/internal/resolution/entities" @@ -18,14 +18,14 @@ func WithPackageName(packageName string) input.Predicate { } } -func InSemverRange(semverRange bsemver.Range) input.Predicate { +func InSemverRange(semverRange *mmsemver.Constraints) input.Predicate { return func(entity *input.Entity) bool { bundleEntity := olmentity.NewBundleEntity(entity) bundleVersion, err := bundleEntity.Version() if err != nil { return false } - return semverRange(*bundleVersion) + return semverRange.Check(bundleVersion) } } diff --git a/internal/resolution/util/predicates/predicates_test.go b/internal/resolution/util/predicates/predicates_test.go index 3c9c12796..6ade1fbdc 100644 --- a/internal/resolution/util/predicates/predicates_test.go +++ b/internal/resolution/util/predicates/predicates_test.go @@ -3,7 +3,7 @@ package predicates_test import ( "testing" - bsemver "github.com/blang/semver/v4" + mmsemver "github.com/Masterminds/semver/v3" . "github.com/onsi/ginkgo/v2" . "github.com/onsi/gomega" "github.com/operator-framework/deppy/pkg/deppy/input" @@ -38,14 +38,17 @@ var _ = Describe("Predicates", func() { entity := input.NewEntity("test", map[string]string{ property.TypePackage: `{"packageName": "mypackage", "version": "1.0.0"}`, }) - inRange := bsemver.MustParseRange(">=1.0.0") - notInRange := bsemver.MustParseRange(">=2.0.0") + inRange, err := mmsemver.NewConstraint(">=1.0.0") + Expect(err).NotTo(HaveOccurred()) + notInRange, err := mmsemver.NewConstraint(">=2.0.0") + Expect(err).NotTo(HaveOccurred()) Expect(predicates.InSemverRange(inRange)(entity)).To(BeTrue()) Expect(predicates.InSemverRange(notInRange)(entity)).To(BeFalse()) }) It("should return false when the entity does not have a version", func() { entity := input.NewEntity("test", map[string]string{}) - inRange := bsemver.MustParseRange(">=1.0.0") + inRange, err := mmsemver.NewConstraint(">=1.0.0") + Expect(err).NotTo(HaveOccurred()) Expect(predicates.InSemverRange(inRange)(entity)).To(BeFalse()) }) }) diff --git a/internal/resolution/util/sort/sort.go b/internal/resolution/util/sort/sort.go index d013b982f..e3e9cc08b 100644 --- a/internal/resolution/util/sort/sort.go +++ b/internal/resolution/util/sort/sort.go @@ -76,5 +76,5 @@ func versionOrder(e1, e2 *entities.BundleEntity) int { // from highest to lowest return -1 * errComp } - return ver1.Compare(*ver2) + return ver1.Compare(ver2) } diff --git a/internal/resolution/variablesources/bundles_and_dependencies.go b/internal/resolution/variablesources/bundles_and_dependencies.go index 0301487e4..4b46965b1 100644 --- a/internal/resolution/variablesources/bundles_and_dependencies.go +++ b/internal/resolution/variablesources/bundles_and_dependencies.go @@ -5,7 +5,7 @@ import ( "fmt" "sort" - bsemver "github.com/blang/semver/v4" + mmsemver "github.com/Masterminds/semver/v3" "github.com/operator-framework/deppy/pkg/deppy" "github.com/operator-framework/deppy/pkg/deppy/input" @@ -87,7 +87,7 @@ func (b *BundlesAndDepsVariableSource) getEntityDependencies(ctx context.Context // todo(perdasilva): disambiguate between not found and actual errors requiredPackages, _ := bundleEntity.RequiredPackages() for _, requiredPackage := range requiredPackages { - semverRange, err := bsemver.ParseRange(requiredPackage.VersionRange) + semverRange, err := mmsemver.NewConstraint(requiredPackage.VersionRange) if err != nil { return nil, err } diff --git a/internal/resolution/variablesources/required_package.go b/internal/resolution/variablesources/required_package.go index 229e34c7e..3f9091441 100644 --- a/internal/resolution/variablesources/required_package.go +++ b/internal/resolution/variablesources/required_package.go @@ -4,7 +4,7 @@ import ( "context" "fmt" - bsemver "github.com/blang/semver/v4" + mmsemver "github.com/Masterminds/semver/v3" "github.com/operator-framework/deppy/pkg/deppy" "github.com/operator-framework/deppy/pkg/deppy/input" @@ -21,14 +21,14 @@ type RequiredPackageVariableSourceOption func(*RequiredPackageVariableSource) er func InVersionRange(versionRange string) RequiredPackageVariableSourceOption { return func(r *RequiredPackageVariableSource) error { if versionRange != "" { - vr, err := bsemver.ParseRange(versionRange) + vr, err := mmsemver.NewConstraint(versionRange) if err == nil { r.versionRange = versionRange r.predicates = append(r.predicates, predicates.InSemverRange(vr)) return nil } - return fmt.Errorf("invalid version range '%s': %v", versionRange, err) + return fmt.Errorf("invalid version range '%s': %w", versionRange, err) } return nil } diff --git a/internal/resolution/variablesources/required_package_test.go b/internal/resolution/variablesources/required_package_test.go index 19c14824b..834054c70 100644 --- a/internal/resolution/variablesources/required_package_test.go +++ b/internal/resolution/variablesources/required_package_test.go @@ -80,7 +80,7 @@ var _ = Describe("RequiredPackageVariableSource", func() { It("should filter by version range", func() { // recreate source with version range option var err error - rpvs, err = variablesources.NewRequiredPackageVariableSource(packageName, variablesources.InVersionRange(">=1.0.0 !2.0.0 <3.0.0")) + rpvs, err = variablesources.NewRequiredPackageVariableSource(packageName, variablesources.InVersionRange(">=1.0.0 !=2.0.0 <3.0.0")) Expect(err).NotTo(HaveOccurred()) variables, err := rpvs.GetVariables(context.TODO(), mockEntitySource)