From b471968625ada70010f398203732f481ea9e49ea Mon Sep 17 00:00:00 2001 From: Kimmo Lehto Date: Wed, 9 Feb 2022 14:05:48 +0200 Subject: [PATCH] Fix k0s version sorting (#317) Signed-off-by: Kimmo Lehto --- cmd/flags.go | 12 ++-- go.mod | 3 +- go.sum | 6 +- integration/github/github.go | 71 ++++--------------- phase/gather_k0s_facts.go | 6 +- phase/validate_facts.go | 10 +-- .../v1beta1/cluster/k0s.go | 21 +++--- 7 files changed, 41 insertions(+), 88 deletions(-) diff --git a/cmd/flags.go b/cmd/flags.go index b5ad693a..e960d7c4 100644 --- a/cmd/flags.go +++ b/cmd/flags.go @@ -18,7 +18,7 @@ import ( "github.com/k0sproject/k0sctl/integration/segment" "github.com/k0sproject/k0sctl/phase" "github.com/k0sproject/k0sctl/pkg/apis/k0sctl.k0sproject.io/v1beta1" - "github.com/k0sproject/k0sctl/version" + k0sctl "github.com/k0sproject/k0sctl/version" "github.com/k0sproject/rig" "github.com/k0sproject/rig/exec" "github.com/logrusorgru/aurora" @@ -131,7 +131,7 @@ func initConfig(ctx *cli.Context) error { } func displayCopyright(ctx *cli.Context) error { - fmt.Printf("k0sctl %s Copyright 2021, k0sctl authors.\n", version.Version) + fmt.Printf("k0sctl %s Copyright 2021, k0sctl authors.\n", k0sctl.Version) if !ctx.Bool("disable-telemetry") { fmt.Println("Anonymized telemetry of usage will be sent to the authors.") } @@ -361,7 +361,7 @@ func githubOrCachedRelease() (*github.Release, error) { } } log.Tracef("starting online k0sctl upgrade check") - latest, err := github.LatestRelease("k0sproject/k0sctl", version.IsPre()) + latest, err := github.LatestRelease(k0sctl.IsPre()) if err != nil { return nil, err } @@ -379,7 +379,7 @@ func githubOrCachedRelease() (*github.Release, error) { } func startCheckUpgrade(ctx *cli.Context) error { - if ctx.Bool("disable-upgrade-check") || version.Environment == "development" { + if ctx.Bool("disable-upgrade-check") || k0sctl.Environment == "development" { return nil } @@ -392,7 +392,7 @@ func startCheckUpgrade(ctx *cli.Context) error { upgradeChan <- nil return } - if latest.IsNewer(version.Version) { + if latest.IsNewer(k0sctl.Version) { upgradeChan <- latest } else { upgradeChan <- nil @@ -403,7 +403,7 @@ func startCheckUpgrade(ctx *cli.Context) error { } func reportCheckUpgrade(ctx *cli.Context) error { - if ctx.Bool("disable-upgrade-check") || version.Environment == "development" { + if ctx.Bool("disable-upgrade-check") || k0sctl.Environment == "development" { return nil } diff --git a/go.mod b/go.mod index 8f04da21..757ca4aa 100644 --- a/go.mod +++ b/go.mod @@ -15,7 +15,7 @@ require ( github.com/denisbrodbeck/machineid v1.0.1 github.com/gammazero/workerpool v1.1.2 github.com/gofrs/uuid v4.0.0+incompatible // indirect - github.com/hashicorp/go-version v1.3.0 + github.com/hashicorp/go-version v1.4.0 // indirect github.com/k0sproject/dig v0.2.0 github.com/k0sproject/rig v0.4.7 github.com/logrusorgru/aurora v2.0.3+incompatible @@ -42,6 +42,7 @@ require ( github.com/alessio/shellescape v1.4.1 github.com/go-ozzo/ozzo-validation/v4 v4.3.0 github.com/go-playground/validator/v10 v10.9.0 + github.com/k0sproject/version v0.1.3 ) require ( diff --git a/go.sum b/go.sum index e851b103..35c05a48 100644 --- a/go.sum +++ b/go.sum @@ -193,8 +193,8 @@ github.com/googleapis/gnostic v0.5.1/go.mod h1:6U4PtQXGIEt/Z3h5MAT7FNofLnw9vXk2c github.com/googleapis/gnostic v0.5.5/go.mod h1:7+EbHbldMins07ALC74bsA81Ovc97DwqyJO1AENw9kA= github.com/gorilla/websocket v1.4.2/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE= github.com/gregjones/httpcache v0.0.0-20180305231024-9cad4c3443a7/go.mod h1:FecbI9+v66THATjSRHfNgh1IVFe/9kFxbXtjV0ctIMA= -github.com/hashicorp/go-version v1.3.0 h1:McDWVJIU/y+u1BRV06dPaLfLCaT7fUTJLp5r04x7iNw= -github.com/hashicorp/go-version v1.3.0/go.mod h1:fltr4n8CU8Ke44wwGCBoEymUuxUHl09ZGVZPK5anwXA= +github.com/hashicorp/go-version v1.4.0 h1:aAQzgqIrRKRa7w75CKpbBxYsmUoPjzVm1W59ca1L0J4= +github.com/hashicorp/go-version v1.4.0/go.mod h1:fltr4n8CU8Ke44wwGCBoEymUuxUHl09ZGVZPK5anwXA= github.com/hashicorp/golang-lru v0.5.0/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8= github.com/hashicorp/golang-lru v0.5.1/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8= github.com/hinshun/vt10x v0.0.0-20180616224451-1954e6464174 h1:WlZsjVhE8Af9IcZDGgJGQpNflI3+MJSBhsgT5PCtzBQ= @@ -214,6 +214,8 @@ github.com/k0sproject/dig v0.2.0 h1:cNxEIl96g9kqSMfPSZLhpnZ0P8bWXKv08nxvsMHop5w= github.com/k0sproject/dig v0.2.0/go.mod h1:rBcqaQlJpcKdt2x/OE/lPvhGU50u/e95CSm5g/r4s78= github.com/k0sproject/rig v0.4.7 h1:ijTypz6X8HwZIpV2csrLTYhtZvpOrYpP3evv08jVwMg= github.com/k0sproject/rig v0.4.7/go.mod h1:4FKfoqz5HOE8v8pJ0K8BCvWw3ypB2vJINkAY4P+yTpo= +github.com/k0sproject/version v0.1.3 h1:md6jfYT28VtUGe7qE8Fd/sxvtaCnlnLR3t0mnRneyIk= +github.com/k0sproject/version v0.1.3/go.mod h1:oEjuz2ItQQtAnGyRgwEV9m5R6/9rjoFC6EiEEzbkFdI= github.com/kballard/go-shellquote v0.0.0-20180428030007-95032a82bc51 h1:Z9n2FFNUXsshfwJMBgNA0RU6/i7WVaAegv3PtuIHPMs= github.com/kballard/go-shellquote v0.0.0-20180428030007-95032a82bc51/go.mod h1:CzGEWj7cYgsdH8dAjBGEr58BoE7ScuLd+fwFZ44+/x8= github.com/kisielk/errcheck v1.5.0/go.mod h1:pFxgyoBC7bSaBwPgfKdkLd5X25qrDl4LWUI2bnpBCr8= diff --git a/integration/github/github.go b/integration/github/github.go index 151c0150..459ee1ac 100644 --- a/integration/github/github.go +++ b/integration/github/github.go @@ -9,7 +9,7 @@ import ( "strings" "time" - "github.com/hashicorp/go-version" + k0sversion "github.com/k0sproject/version" ) const timeOut = time.Second * 10 @@ -29,11 +29,11 @@ type Release struct { } func (r *Release) IsNewer(b string) bool { - this, err := version.NewVersion(r.TagName) + this, err := k0sversion.NewVersion(r.TagName) if err != nil { return false } - other, err := version.NewVersion(b) + other, err := k0sversion.NewVersion(b) if err != nil { return false } @@ -42,7 +42,7 @@ func (r *Release) IsNewer(b string) bool { // LatestK0sBinaryURL returns the url for the latest k0s release by arch and os func LatestK0sBinaryURL(arch, osKind string, preok bool) (string, error) { - r, err := LatestRelease("k0sproject/k0s", preok) + r, err := k0sversion.LatestReleaseByPrerelease(preok) if err != nil { return "", err } @@ -66,82 +66,35 @@ func LatestK0sBinaryURL(arch, osKind string, preok bool) (string, error) { // LatestK0sVersion returns the latest k0s version number (without v prefix) func LatestK0sVersion(preok bool) (string, error) { - r, err := LatestRelease("k0sproject/k0s", preok) + r, err := k0sversion.LatestReleaseByPrerelease(preok) if err != nil { return "", err } return strings.TrimPrefix(r.TagName, "v"), nil } -// versionCollection is a type that implements the sort.Interface interface -// so that versions can be sorted. -type versionCollection []*version.Version - -func (v versionCollection) Len() int { - return len(v) -} - -func (v versionCollection) Less(i, j int) bool { - return vCompare(v[i], v[j]) < 0 -} - -func (v versionCollection) Swap(i, j int) { - v[i], v[j] = v[j], v[i] -} - -// vCompare compares this version to another version. This -// returns -1, 0, or 1 if this version is smaller, equal, -// or larger than the other version, respectively. -func vCompare(a, b *version.Version) int { - c := a.Compare(b) - if c != 0 { - // versions already differ enough to use the version pkg result - return c - } - - vA := a.String() - - // go to plain string comparison - s := []string{vA, b.String()} - sort.Strings(s) - - if vA == s[0] { - return -1 - } - - return 1 -} - -// LatestRelease returns the semantically sorted latest version from github releases page for a repo. -// Set preok true to allow returning pre-release versions. Assumes the repository has release tags with -// semantic version numbers (optionally v-prefixed). -func LatestRelease(repo string, preok bool) (Release, error) { - var gotV bool +// LatestRelease returns the semantically sorted latest k0sctl version from github +func LatestRelease(preok bool) (Release, error) { var releases []Release - if err := unmarshalURLBody(fmt.Sprintf("https://api.github.com/repos/%s/releases?per_page=20&page=1", repo), &releases); err != nil { + if err := unmarshalURLBody("https://api.github.com/repos/k0sproject/k0sctl/releases?per_page=20&page=1", &releases); err != nil { return Release{}, err } - var versions []*version.Version + var versions k0sversion.Collection for _, v := range releases { if v.PreRelease && !preok { continue } - if version, err := version.NewVersion(strings.TrimPrefix(v.TagName, "v")); err == nil { - gotV = strings.HasPrefix(v.TagName, "v") + if version, err := k0sversion.NewVersion(strings.TrimPrefix(v.TagName, "v")); err == nil { versions = append(versions, version) } } - vc := versionCollection(versions) - sort.Sort(vc) + sort.Sort(versions) latest := versions[len(versions)-1].String() - if gotV { - latest = "v" + latest - } for _, v := range releases { - if v.TagName == latest { + if strings.TrimPrefix(v.TagName, "v") == latest { return v, nil } } diff --git a/phase/gather_k0s_facts.go b/phase/gather_k0s_facts.go index 872e7a74..535ddd83 100644 --- a/phase/gather_k0s_facts.go +++ b/phase/gather_k0s_facts.go @@ -5,10 +5,10 @@ import ( "fmt" "strings" - "github.com/Masterminds/semver" "github.com/k0sproject/dig" "github.com/k0sproject/k0sctl/pkg/apis/k0sctl.k0sproject.io/v1beta1/cluster" "github.com/k0sproject/rig/exec" + "github.com/k0sproject/version" log "github.com/sirupsen/logrus" "gopkg.in/yaml.v2" ) @@ -157,12 +157,12 @@ func (p *GatherK0sFacts) needsUpgrade(h *cluster.Host) bool { } log.Debugf("%s: checking if %s is an upgrade from %s", h, p.Config.Spec.K0s.Version, h.Metadata.K0sRunningVersion) - target, err := semver.NewVersion(p.Config.Spec.K0s.Version) + target, err := version.NewVersion(p.Config.Spec.K0s.Version) if err != nil { log.Warnf("%s: failed to parse target version: %s", h, err.Error()) return false } - current, err := semver.NewVersion(h.Metadata.K0sRunningVersion) + current, err := version.NewVersion(h.Metadata.K0sRunningVersion) if err != nil { log.Warnf("%s: failed to parse running version: %s", h, err.Error()) return false diff --git a/phase/validate_facts.go b/phase/validate_facts.go index 619eb211..1474a48c 100644 --- a/phase/validate_facts.go +++ b/phase/validate_facts.go @@ -3,7 +3,7 @@ package phase import ( "fmt" - "github.com/Masterminds/semver" + "github.com/k0sproject/version" log "github.com/sirupsen/logrus" ) @@ -39,12 +39,12 @@ func (p *ValidateFacts) validateDowngrade() error { return nil } - cfgV, err := semver.NewVersion(p.Config.Spec.K0s.Version) + cfgV, err := version.NewVersion(p.Config.Spec.K0s.Version) if err != nil { return err } - runV, err := semver.NewVersion(p.Config.Spec.K0sLeader().Metadata.K0sRunningVersion) + runV, err := version.NewVersion(p.Config.Spec.K0sLeader().Metadata.K0sRunningVersion) if err != nil { return err } @@ -67,12 +67,12 @@ func (p *ValidateFacts) validateDefaultVersion() error { return nil } - cfgV, err := semver.NewVersion(p.Config.Spec.K0s.Version) + cfgV, err := version.NewVersion(p.Config.Spec.K0s.Version) if err != nil { return err } - runV, err := semver.NewVersion(p.Config.Spec.K0sLeader().Metadata.K0sRunningVersion) + runV, err := version.NewVersion(p.Config.Spec.K0sLeader().Metadata.K0sRunningVersion) if err != nil { return err } diff --git a/pkg/apis/k0sctl.k0sproject.io/v1beta1/cluster/k0s.go b/pkg/apis/k0sctl.k0sproject.io/v1beta1/cluster/k0s.go index 35583d48..6d4fb0b5 100644 --- a/pkg/apis/k0sctl.k0sproject.io/v1beta1/cluster/k0s.go +++ b/pkg/apis/k0sctl.k0sproject.io/v1beta1/cluster/k0s.go @@ -8,15 +8,14 @@ import ( "strings" "time" - "github.com/Masterminds/semver" "github.com/alessio/shellescape" "github.com/avast/retry-go" "github.com/creasty/defaults" validation "github.com/go-ozzo/ozzo-validation/v4" "github.com/k0sproject/dig" - "github.com/k0sproject/k0sctl/integration/github" - "github.com/k0sproject/k0sctl/version" + k0sctl "github.com/k0sproject/k0sctl/version" "github.com/k0sproject/rig/exec" + "github.com/k0sproject/version" "gopkg.in/yaml.v2" ) @@ -54,17 +53,17 @@ func validateVersion(value interface{}) error { return fmt.Errorf("not a string") } - v, err := semver.NewVersion(vs) + v, err := version.NewVersion(vs) if err != nil { return err } - min, err := semver.NewVersion(K0sMinVersion) + min, err := version.NewVersion(K0sMinVersion) if err != nil { return fmt.Errorf("internal error: k0sminversion can't be parsed: %s", err) } - if min.GreaterThan(v) { + if v.LessThan(min) { return fmt.Errorf("version: minimum supported k0s version is %s", K0sMinVersion) } @@ -80,12 +79,10 @@ func (k *K0s) Validate() error { // SetDefaults (implements defaults Setter interface) defaults the version to latest k0s version func (k *K0s) SetDefaults() { - if defaults.CanUpdate(k.Version) { - preok := version.IsPre() || version.Version == "0.0.0" - if latest, err := github.LatestK0sVersion(preok); err == nil { - k.Version = latest - k.Metadata.VersionDefaulted = true - } + latest, err := version.LatestReleaseByPrerelease(k0sctl.IsPre() || k0sctl.Version == "0.0.0") + if err == nil { + k.Version = latest.String() + k.Metadata.VersionDefaulted = true } k.Version = strings.TrimPrefix(k.Version, "v")