From 80e9df056f11fe0b534bbdcf8e7cc9bd0d875e88 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20Wei=C3=9Fe?= Date: Tue, 15 Aug 2023 13:54:05 +0200 Subject: [PATCH] Parse image and K8s versions as semver MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Daniel Weiße --- cli/internal/cmd/upgradecheck.go | 50 +++++++++++++++------------ cli/internal/cmd/upgradecheck_test.go | 27 ++++++++------- internal/semver/semver.go | 1 + 3 files changed, 43 insertions(+), 35 deletions(-) diff --git a/cli/internal/cmd/upgradecheck.go b/cli/internal/cmd/upgradecheck.go index 9534b23545d..252ad963e3f 100644 --- a/cli/internal/cmd/upgradecheck.go +++ b/cli/internal/cmd/upgradecheck.go @@ -286,10 +286,10 @@ func sortedMapKeys[T any](a map[string]T) []string { } // filterImageUpgrades filters out image versions that are not valid upgrades. -func filterImageUpgrades(currentVersion string, newVersions []versionsapi.Version) []versionsapi.Version { +func filterImageUpgrades(currentVersion consemver.Semver, newVersions []versionsapi.Version) []versionsapi.Version { newImages := []versionsapi.Version{} for i := range newVersions { - if err := compatibility.IsValidUpgrade(currentVersion, newVersions[i].Version()); err != nil { + if err := compatibility.IsValidUpgrade(currentVersion.String(), newVersions[i].Version()); err != nil { continue } newImages = append(newImages, newVersions[i]) @@ -298,10 +298,10 @@ func filterImageUpgrades(currentVersion string, newVersions []versionsapi.Versio } // filterK8sUpgrades filters out K8s versions that are not valid upgrades. -func filterK8sUpgrades(currentVersion string, newVersions []string) []string { +func filterK8sUpgrades(currentVersion consemver.Semver, newVersions []string) []string { result := []string{} for i := range newVersions { - if err := compatibility.IsValidUpgrade(currentVersion, newVersions[i]); err != nil { + if err := compatibility.IsValidUpgrade(currentVersion.String(), newVersions[i]); err != nil { continue } result = append(result, newVersions[i]) @@ -312,12 +312,12 @@ func filterK8sUpgrades(currentVersion string, newVersions []string) []string { type collector interface { currentVersions(ctx context.Context) (currentVersionInfo, error) - supportedVersions(ctx context.Context, currentImageVersion, currentK8sVersion string) (supportedVersionInfo, error) - newImages(ctx context.Context, currentImageVersion string) ([]versionsapi.Version, error) + supportedVersions(ctx context.Context, currentImageVersion, currentK8sVersion consemver.Semver) (supportedVersionInfo, error) + newImages(ctx context.Context, currentImageVersion consemver.Semver) ([]versionsapi.Version, error) newMeasurements(ctx context.Context, csp cloudprovider.Provider, attestationVariant variant.Variant, images []versionsapi.Version) (map[string]measurements.M, error) newerVersions(ctx context.Context, allowedVersions []string) ([]versionsapi.Version, error) newCLIVersions(ctx context.Context) ([]consemver.Semver, error) - filterCompatibleCLIVersions(ctx context.Context, cliPatchVersions []consemver.Semver, currentK8sVersion string) ([]consemver.Semver, error) + filterCompatibleCLIVersions(ctx context.Context, cliPatchVersions []consemver.Semver, currentK8sVersion consemver.Semver) ([]consemver.Semver, error) } type versionCollector struct { @@ -365,8 +365,8 @@ func (v *versionCollector) newMeasurements(ctx context.Context, csp cloudprovide type currentVersionInfo struct { service consemver.Semver - image string - k8s string + image consemver.Semver + k8s consemver.Semver cli consemver.Semver } @@ -385,17 +385,19 @@ func (v *versionCollector) currentVersions(ctx context.Context) (currentVersionI if err != nil { return currentVersionInfo{}, fmt.Errorf("getting cluster versions: %w", err) } - if !semver.IsValid(clusterVersions.ImageVersion()) { - return currentVersionInfo{}, fmt.Errorf("checking image for valid semantic version: %w", err) + imageVersion, err := consemver.New(clusterVersions.ImageVersion()) + if err != nil { + return currentVersionInfo{}, fmt.Errorf("parsing image semantic version: %w", err) } - if !semver.IsValid(clusterVersions.KubernetesVersion()) { - return currentVersionInfo{}, fmt.Errorf("checking Kubernetes for valid semantic version: %w", err) + k8sVersion, err := consemver.New(clusterVersions.KubernetesVersion()) + if err != nil { + return currentVersionInfo{}, fmt.Errorf("parsing Kubernetes semantic version: %w", err) } return currentVersionInfo{ service: serviceVersions.ConstellationServices(), - image: clusterVersions.ImageVersion(), - k8s: clusterVersions.KubernetesVersion(), + image: imageVersion, + k8s: k8sVersion, cli: v.cliVersion, }, nil } @@ -411,7 +413,7 @@ type supportedVersionInfo struct { } // supportedVersions returns slices of supported versions. -func (v *versionCollector) supportedVersions(ctx context.Context, currentImageVersion, currentK8sVersion string) (supportedVersionInfo, error) { +func (v *versionCollector) supportedVersions(ctx context.Context, currentImageVersion, currentK8sVersion consemver.Semver) (supportedVersionInfo, error) { k8sVersions := versions.SupportedK8sVersions() imageVersions, err := v.newImages(ctx, currentImageVersion) @@ -437,13 +439,13 @@ func (v *versionCollector) supportedVersions(ctx context.Context, currentImageVe }, nil } -func (v *versionCollector) newImages(ctx context.Context, currentImageVersion string) ([]versionsapi.Version, error) { +func (v *versionCollector) newImages(ctx context.Context, currentImageVersion consemver.Semver) ([]versionsapi.Version, error) { // find compatible images // image updates should always be possible for the current minor version of the cluster // (e.g. 0.1.0 -> 0.1.1, 0.1.2, 0.1.3, etc.) // additionally, we allow updates to the next minor version (e.g. 0.1.0 -> 0.2.0) // if the CLI minor version is newer than the cluster minor version - currentImageMinorVer := semver.MajorMinor(currentImageVersion) + currentImageMinorVer := semver.MajorMinor(currentImageVersion.String()) currentCLIMinorVer := semver.MajorMinor(v.cliVersion.String()) nextImageMinorVer, err := compatibility.NextMinorVersion(currentImageMinorVer) if err != nil { @@ -510,8 +512,8 @@ type versionUpgrade struct { newCLI []consemver.Semver newCompatibleCLI []consemver.Semver currentServices consemver.Semver - currentImage string - currentKubernetes string + currentImage consemver.Semver + currentKubernetes consemver.Semver currentCLI consemver.Semver } @@ -678,7 +680,7 @@ func (v *versionCollector) newCLIVersions(ctx context.Context) ([]consemver.Semv } // filterCompatibleCLIVersions filters a list of CLI versions which are compatible with the current Kubernetes version. -func (v *versionCollector) filterCompatibleCLIVersions(ctx context.Context, cliPatchVersions []consemver.Semver, currentK8sVersion string, +func (v *versionCollector) filterCompatibleCLIVersions(ctx context.Context, cliPatchVersions []consemver.Semver, currentK8sVersion consemver.Semver, ) ([]consemver.Semver, error) { // filter out invalid upgrades and versions which are not compatible with the current Kubernetes version var compatibleVersions []consemver.Semver @@ -698,7 +700,11 @@ func (v *versionCollector) filterCompatibleCLIVersions(ctx context.Context, cliP } for _, k8sVersion := range info.Kubernetes { - if k8sVersion == currentK8sVersion { + k8sVersionSem, err := consemver.New(k8sVersion) + if err != nil { + return nil, fmt.Errorf("parsing Kubernetes version %s: %w", k8sVersion, err) + } + if k8sVersionSem.Compare(currentK8sVersion) == 0 { compatibleVersions = append(compatibleVersions, version) } } diff --git a/cli/internal/cmd/upgradecheck_test.go b/cli/internal/cmd/upgradecheck_test.go index 1b4e5601faf..816be5f0ab6 100644 --- a/cli/internal/cmd/upgradecheck_test.go +++ b/cli/internal/cmd/upgradecheck_test.go @@ -24,6 +24,7 @@ import ( "github.com/edgelesssys/constellation/v2/internal/constants" "github.com/edgelesssys/constellation/v2/internal/file" "github.com/edgelesssys/constellation/v2/internal/logger" + "github.com/edgelesssys/constellation/v2/internal/semver" consemver "github.com/edgelesssys/constellation/v2/internal/semver" "github.com/spf13/afero" "github.com/stretchr/testify/assert" @@ -46,8 +47,8 @@ func TestBuildString(t *testing.T) { newKubernetes: []string{"v1.24.12", "v1.25.6"}, newCLI: []consemver.Semver{consemver.NewFromInt(2, 5, 0, ""), consemver.NewFromInt(2, 6, 0, "")}, currentServices: consemver.NewFromInt(2, 4, 0, ""), - currentImage: "v2.4.0", - currentKubernetes: "v1.24.5", + currentImage: semver.NewFromInt(2, 4, 0, ""), + currentKubernetes: semver.NewFromInt(1, 24, 5, ""), currentCLI: consemver.NewFromInt(2, 4, 0, ""), }, expected: "The following updates are available with this CLI:\n Kubernetes: v1.24.5 --> v1.24.12 v1.25.6\n Images:\n v2.4.0 --> v2.5.0\n Includes these measurements:\n 4:\n expected: \"1234123412341234123412341234123412341234123412341234123412341234\"\n warnOnly: false\n 8:\n expected: \"0000000000000000000000000000000000000000000000000000000000000000\"\n warnOnly: false\n 9:\n expected: \"1234123412341234123412341234123412341234123412341234123412341234\"\n warnOnly: false\n 11:\n expected: \"0000000000000000000000000000000000000000000000000000000000000000\"\n warnOnly: false\n 12:\n expected: \"1234123412341234123412341234123412341234123412341234123412341234\"\n warnOnly: false\n 13:\n expected: \"0000000000000000000000000000000000000000000000000000000000000000\"\n warnOnly: false\n 15:\n expected: \"0000000000000000000000000000000000000000000000000000000000000000\"\n warnOnly: false\n \n Services: v2.4.0 --> v2.5.0\n", @@ -69,7 +70,7 @@ func TestBuildString(t *testing.T) { "k8s only": { upgrade: versionUpgrade{ newKubernetes: []string{"v1.24.12", "v1.25.6"}, - currentKubernetes: "v1.24.5", + currentKubernetes: semver.NewFromInt(1, 24, 5, ""), }, expected: "The following updates are available with this CLI:\n Kubernetes: v1.24.5 --> v1.24.12 v1.25.6\n", }, @@ -80,8 +81,8 @@ func TestBuildString(t *testing.T) { newKubernetes: []string{}, newCLI: []consemver.Semver{}, currentServices: consemver.NewFromInt(2, 5, 0, ""), - currentImage: "v2.5.0", - currentKubernetes: "v1.25.6", + currentImage: semver.NewFromInt(2, 5, 0, ""), + currentKubernetes: semver.NewFromInt(1, 25, 6, ""), currentCLI: consemver.NewFromInt(2, 5, 0, ""), }, expected: "You are up to date.\n", @@ -164,8 +165,8 @@ func TestUpgradeCheck(t *testing.T) { }, supportedK8sVersions: []string{"v1.24.5", "v1.24.12", "v1.25.6"}, currentServicesVersions: consemver.NewFromInt(2, 4, 0, ""), - currentImageVersion: "v2.4.0", - currentK8sVersion: "v1.24.5", + currentImageVersion: semver.NewFromInt(2, 4, 0, ""), + currentK8sVersion: semver.NewFromInt(1, 24, 5, ""), currentCLIVersion: consemver.NewFromInt(2, 4, 0, ""), images: []versionsapi.Version{v2_5}, newCLIVersionsList: []consemver.Semver{consemver.NewFromInt(2, 5, 0, ""), consemver.NewFromInt(2, 6, 0, "")}, @@ -230,8 +231,8 @@ type stubVersionCollector struct { supportedK8sVersions []string supportedCLIVersions []consemver.Semver currentServicesVersions consemver.Semver - currentImageVersion string - currentK8sVersion string + currentImageVersion consemver.Semver + currentK8sVersion consemver.Semver currentCLIVersion consemver.Semver images []versionsapi.Version newCLIVersionsList []consemver.Semver @@ -252,7 +253,7 @@ func (s *stubVersionCollector) currentVersions(_ context.Context) (currentVersio }, s.someErr } -func (s *stubVersionCollector) supportedVersions(_ context.Context, _, _ string) (supportedVersionInfo, error) { +func (s *stubVersionCollector) supportedVersions(_ context.Context, _, _ consemver.Semver) (supportedVersionInfo, error) { return supportedVersionInfo{ service: s.supportedServicesVersions, image: s.supportedImages, @@ -261,7 +262,7 @@ func (s *stubVersionCollector) supportedVersions(_ context.Context, _, _ string) }, s.someErr } -func (s *stubVersionCollector) newImages(_ context.Context, _ string) ([]versionsapi.Version, error) { +func (s *stubVersionCollector) newImages(_ context.Context, _ consemver.Semver) ([]versionsapi.Version, error) { return s.images, nil } @@ -273,7 +274,7 @@ func (s *stubVersionCollector) newCLIVersions(_ context.Context) ([]consemver.Se return s.newCLIVersionsList, nil } -func (s *stubVersionCollector) filterCompatibleCLIVersions(_ context.Context, _ []consemver.Semver, _ string) ([]consemver.Semver, error) { +func (s *stubVersionCollector) filterCompatibleCLIVersions(_ context.Context, _ []consemver.Semver, _ consemver.Semver) ([]consemver.Semver, error) { return s.newCompatibleCLIVersionsList, nil } @@ -373,7 +374,7 @@ func TestFilterCompatibleCLIVersions(t *testing.T) { t.Run(name, func(t *testing.T) { require := require.New(t) - _, err := tc.verCollector.filterCompatibleCLIVersions(context.Background(), tc.cliPatchVersions, "v1.24.5") + _, err := tc.verCollector.filterCompatibleCLIVersions(context.Background(), tc.cliPatchVersions, semver.NewFromInt(1, 24, 5, "")) if tc.wantErr { require.Error(err) return diff --git a/internal/semver/semver.go b/internal/semver/semver.go index 206d01a9e57..72dc19f514a 100644 --- a/internal/semver/semver.go +++ b/internal/semver/semver.go @@ -131,6 +131,7 @@ func (v Semver) String() string { } // Compare compares two versions. It relies on the semver.Compare function internally. +// The result will be 0 if v == w, -1 if v < w, or +1 if v > w. func (v Semver) Compare(other Semver) int { return semver.Compare(v.String(), other.String()) }