Skip to content

Commit

Permalink
Move k0s version defaulting into a phase
Browse files Browse the repository at this point in the history
Signed-off-by: Kimmo Lehto <[email protected]>
  • Loading branch information
kke committed Oct 13, 2023
1 parent 0214bdd commit 1fb8338
Show file tree
Hide file tree
Showing 8 changed files with 90 additions and 35 deletions.
6 changes: 6 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -571,6 +571,12 @@ If set to `true` k0sctl will remove the node from kubernetes and reset k0s on th

The version of k0s to deploy. When left out, k0sctl will default to using the latest released version of k0s or the version already running on the cluster.

##### `spec.k0s.versionChannel` &lt;string&gt; (optional) (default: `stable`)

Possible values are `stable` and `latest`.

When `spec.k0s.version` is left undefined, this setting can be set to `latest` to allow k0sctl to include k0s pre-releases when looking for the latest version. The default is to only look for stable releases.

##### `spec.k0s.dynamicConfig` &lt;boolean&gt; (optional) (default: false)

Enable k0s dynamic config. The setting will be automatically set to true if:
Expand Down
1 change: 1 addition & 0 deletions action/apply.go
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@ func (a Apply) Run() error {
lockPhase := &phase.Lock{}

a.Manager.AddPhase(
&phase.DefaultK0sVersion{},
&phase.Connect{},
&phase.DetectOS{},
lockPhase,
Expand Down
43 changes: 43 additions & 0 deletions phase/default_k0s_version.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
package phase

import (
"fmt"

"github.com/k0sproject/version"

log "github.com/sirupsen/logrus"
)

type DefaultK0sVersion struct {
GenericPhase
}

func (p *DefaultK0sVersion) ShouldRun() bool {
return p.Config.Spec.K0s.Version == nil || p.Config.Spec.K0s.Version.IsZero()
}

func (p *DefaultK0sVersion) Title() string {
return "Set k0s version"
}

func (p *DefaultK0sVersion) Run() error {
isStable := p.Config.Spec.K0s.VersionChannel == "stable"

var msg string
if isStable {
msg = "latest stable k0s version"
} else {
msg = "latest k0s version including pre-releases"
}

log.Info("Looking up ", msg)
latest, err := version.LatestByPrerelease(!isStable)
if err != nil {
return fmt.Errorf("failed to look up k0s version online - try setting spec.k0s.version manually: %w", err)
}
log.Infof("Using k0s version %s", latest)
p.Config.Spec.K0s.Version = latest
p.Config.Spec.K0s.Metadata.VersionDefaulted = true

return nil
}
2 changes: 1 addition & 1 deletion phase/prepare_hosts.go
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,7 @@ func (p *PrepareHosts) prepareHost(h *cluster.Host) error {
}

// iptables is only required for very old versions of k0s
if !iptablesEmbeddedSince.Check(p.Config.Spec.K0s.Version) && h.NeedIPTables() { //nolint:staticcheck
if p.Config.Spec.K0s.Version != nil && !iptablesEmbeddedSince.Check(p.Config.Spec.K0s.Version) && h.NeedIPTables() { //nolint:staticcheck
pkgs = append(pkgs, "iptables")
}

Expand Down
7 changes: 7 additions & 0 deletions pkg/apis/k0sctl.k0sproject.io/v1beta1/cluster.go
Original file line number Diff line number Diff line change
@@ -1,6 +1,9 @@
package v1beta1

import (
"fmt"

"github.com/creasty/defaults"
validation "github.com/go-ozzo/ozzo-validation/v4"
"github.com/k0sproject/k0sctl/pkg/apis/k0sctl.k0sproject.io/v1beta1/cluster"
)
Expand Down Expand Up @@ -36,6 +39,10 @@ func (c *Cluster) UnmarshalYAML(unmarshal func(interface{}) error) error {
return err
}

if err := defaults.Set(c); err != nil {
return fmt.Errorf("failed to set defaults: %w", err)
}

return nil
}

Expand Down
45 changes: 24 additions & 21 deletions pkg/apis/k0sctl.k0sproject.io/v1beta1/cluster/k0s.go
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,6 @@ import (
validation "github.com/go-ozzo/ozzo-validation/v4"
"github.com/k0sproject/dig"
"github.com/k0sproject/k0sctl/pkg/retry"
k0sctl "github.com/k0sproject/k0sctl/version"
"github.com/k0sproject/rig/exec"
"github.com/k0sproject/version"
"gopkg.in/yaml.v2"
Expand All @@ -30,10 +29,11 @@ var (

// K0s holds configuration for bootstraping a k0s cluster
type K0s struct {
Version *version.Version `yaml:"version"`
DynamicConfig bool `yaml:"dynamicConfig"`
Config dig.Mapping `yaml:"config"`
Metadata K0sMetadata `yaml:"-"`
Version *version.Version `yaml:"version"`
VersionChannel string `yaml:"versionChannel" default:"stable"`
DynamicConfig bool `yaml:"dynamicConfig"`
Config dig.Mapping `yaml:"config"`
Metadata K0sMetadata `yaml:"-"`
}

// K0sMetadata contains gathered information about k0s cluster
Expand All @@ -53,13 +53,29 @@ func (k *K0s) UnmarshalYAML(unmarshal func(interface{}) error) error {

return defaults.Set(k)
}

// SetDefaults sets default values
func (k *K0s) SetDefaults() {
if k.Version == nil {
return
}

if k.Version.IsZero() {
k.Version = nil
}
}

func validateVersion(value interface{}) error {
v, ok := value.(*version.Version)
if !ok {
return fmt.Errorf("not a version")
}

if v != nil && !k0sSupportedVersion.Check(v) {
if v == nil || v.IsZero() {
return nil
}

if !k0sSupportedVersion.Check(v) {
return fmt.Errorf("minimum supported k0s version is %s", k0sSupportedVersion)
}

Expand All @@ -68,9 +84,9 @@ func validateVersion(value interface{}) error {

func (k *K0s) Validate() error {
return validation.ValidateStruct(k,
validation.Field(&k.Version, validation.Required),
validation.Field(&k.Version, validation.By(validateVersion)),
validation.Field(&k.DynamicConfig, validation.By(k.validateMinDynamic())),
validation.Field(&k.VersionChannel, validation.In("stable", "latest")),
)
}

Expand All @@ -84,27 +100,14 @@ func (k *K0s) validateMinDynamic() func(interface{}) error {
return nil
}

if k.Version != nil && !k0sDynamicConfigSince.Check(k.Version) {
if k.Version != nil && !k.Version.IsZero() && !k0sDynamicConfigSince.Check(k.Version) {
return fmt.Errorf("dynamic config only available since k0s version %s", k0sDynamicConfigSince)
}

return nil
}
}

// SetDefaults (implements defaults Setter interface) defaults the version to latest k0s version
func (k *K0s) SetDefaults() {
if k.Version != nil && !k.Version.IsZero() {
return
}

latest, err := version.LatestByPrerelease(k0sctl.IsPre() || k0sctl.Version == "0.0.0")
if err == nil {
k.Version = latest
k.Metadata.VersionDefaulted = true
}
}

func (k *K0s) NodeConfig() dig.Mapping {
return dig.Mapping{
"apiVersion": k.Config.DigString("apiVersion"),
Expand Down
13 changes: 0 additions & 13 deletions pkg/apis/k0sctl.k0sproject.io/v1beta1/cluster/k0s_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -39,18 +39,5 @@ func TestVersionDefaulting(t *testing.T) {
k0s := &K0s{Version: version.MustParse("v0.11.0-rc1")}
require.NoError(t, defaults.Set(k0s))
require.NoError(t, k0s.Validate())
require.False(t, k0s.Metadata.VersionDefaulted)
})

t.Run("version not given", func(t *testing.T) {
k0s := &K0s{}
require.NoError(t, defaults.Set(k0s))
require.NoError(t, k0s.Validate())
require.NotEmpty(t, k0s.Version.String())
require.True(t, len(k0s.Version.String()) > 6, "version too short")
newV, err := version.NewVersion(k0s.Version.String())
require.NoError(t, err)
require.Equal(t, newV.String(), k0s.Version.String())
require.True(t, k0s.Metadata.VersionDefaulted)
})
}
8 changes: 8 additions & 0 deletions pkg/apis/k0sctl.k0sproject.io/v1beta1/cluster/spec.go
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,14 @@ func (s *Spec) UnmarshalYAML(unmarshal func(interface{}) error) error {
return defaults.Set(s)
}

// SetDefaults sets defaults
func (s *Spec) SetDefaults() {
if s.K0s == nil {
s.K0s = &K0s{}
_ = defaults.Set(s.K0s)
}
}

// K0sLeader returns a controller host that is selected to be a "leader",
// or an initial node, a node that creates join tokens for other controllers.
func (s *Spec) K0sLeader() *Host {
Expand Down

0 comments on commit 1fb8338

Please sign in to comment.