diff --git a/phase/initialize_k0s.go b/phase/initialize_k0s.go index 74dd66d0..a9398d26 100644 --- a/phase/initialize_k0s.go +++ b/phase/initialize_k0s.go @@ -54,7 +54,11 @@ func (p *InitializeK0s) Run() error { } log.Infof("%s: installing k0s controller", h) - if err := h.Exec(h.K0sInstallCommand()); err != nil { + cmd, err := h.K0sInstallCommand() + if err != nil { + return err + } + if err = h.Exec(cmd); err != nil { return err } diff --git a/phase/install_controllers.go b/phase/install_controllers.go index 03b2e40c..5e08c98b 100644 --- a/phase/install_controllers.go +++ b/phase/install_controllers.go @@ -84,7 +84,11 @@ func (p *InstallControllers) Run() error { }() log.Infof("%s: installing k0s controller", h) - if err := h.Exec(h.K0sInstallCommand()); err != nil { + cmd, err := h.K0sInstallCommand() + if err != nil { + return err + } + if err = h.Exec(cmd); err != nil { return err } diff --git a/phase/install_workers.go b/phase/install_workers.go index d5b9d7e4..bdeb1563 100644 --- a/phase/install_workers.go +++ b/phase/install_workers.go @@ -121,7 +121,11 @@ func (p *InstallWorkers) Run() error { } log.Infof("%s: installing k0s worker", h) - if err := h.Exec(h.K0sInstallCommand()); err != nil { + cmd, err := h.K0sInstallCommand() + if err != nil { + return err + } + if err = h.Exec(cmd); err != nil { return err } diff --git a/pkg/apis/k0sctl.k0sproject.io/v1beta1/cluster/flags.go b/pkg/apis/k0sctl.k0sproject.io/v1beta1/cluster/flags.go index db515ed1..5095a6e8 100644 --- a/pkg/apis/k0sctl.k0sproject.io/v1beta1/cluster/flags.go +++ b/pkg/apis/k0sctl.k0sproject.io/v1beta1/cluster/flags.go @@ -88,6 +88,23 @@ func (f Flags) GetValue(s string) string { return val } +// GetValue returns the boolean value part of a flag such as true for a flag like "--san" +// If the flag is not defined returns false. If the flag is defined without a value, returns true +// If no value is set, returns true +func (f Flags) GetBoolean(s string) (bool, error) { + idx := f.Index(s) + if idx < 0 { + return false, nil + } + + fl := f.GetValue(s) + if fl == "" { + return true, nil + } + + return strconv.ParseBool(fl) +} + // Delete removes a matching flag from the list func (f *Flags) Delete(s string) { idx := f.Index(s) diff --git a/pkg/apis/k0sctl.k0sproject.io/v1beta1/cluster/flags_test.go b/pkg/apis/k0sctl.k0sproject.io/v1beta1/cluster/flags_test.go index 95376127..fd29610a 100644 --- a/pkg/apis/k0sctl.k0sproject.io/v1beta1/cluster/flags_test.go +++ b/pkg/apis/k0sctl.k0sproject.io/v1beta1/cluster/flags_test.go @@ -49,3 +49,56 @@ func TestString(t *testing.T) { flags := Flags{"--help", "--setting=false"} require.Equal(t, "--help --setting=false", flags.Join()) } + +func TestGetBoolean(t *testing.T) { + t.Run("Valid flags", func(t *testing.T) { + testsValid := []struct { + flag string + expect bool + }{ + {"--flag", true}, + {"--flag=true", true}, + {"--flag=false", false}, + {"--flag=1", true}, + {"--flag=TRUE", true}, + } + for _, test := range testsValid { + flags := Flags{test.flag} + result, err := flags.GetBoolean(test.flag) + require.NoError(t, err) + require.Equal(t, test.expect, result) + + flags = Flags{"--unrelated-flag1", "--unrelated-flag2=foo", test.flag} + result, err = flags.GetBoolean(test.flag) + require.NoError(t, err) + require.Equal(t, test.expect, result) + } + }) + + t.Run("Invalid flags", func(t *testing.T) { + testsInvalid := []string{ + "--flag=foo", + "--flag=2", + "--flag=TrUe", + "--flag=-4", + "--flag=FalSe", + } + for _, test := range testsInvalid { + flags := Flags{test} + _, err := flags.GetBoolean(test) + require.Error(t, err) + + flags = Flags{"--unrelated-flag1", "--unrelated-flag2=foo", test} + _, err = flags.GetBoolean(test) + require.Error(t, err) + } + }) + + t.Run("Unknown flags", func(t *testing.T) { + flags := Flags{"--flag1=1", "--flag2"} + result, err := flags.GetBoolean("--flag3") + require.NoError(t, err) + require.Equal(t, result, false) + + }) +} diff --git a/pkg/apis/k0sctl.k0sproject.io/v1beta1/cluster/host.go b/pkg/apis/k0sctl.k0sproject.io/v1beta1/cluster/host.go index 253a022b..90a680fc 100644 --- a/pkg/apis/k0sctl.k0sproject.io/v1beta1/cluster/host.go +++ b/pkg/apis/k0sctl.k0sproject.io/v1beta1/cluster/host.go @@ -239,7 +239,7 @@ func unQE(s string) string { } // K0sInstallCommand returns a full command that will install k0s service with necessary flags -func (h *Host) K0sInstallCommand() string { +func (h *Host) K0sInstallCommand() (string, error) { role := h.Role flags := h.InstallFlags @@ -268,10 +268,15 @@ func (h *Host) K0sInstallCommand() string { if old := flags.GetValue("--kubelet-extra-args"); old != "" { extra = Flags{unQE(old)} } - // set worker's private address to --node-ip in --extra-kubelet-args - if h.PrivateAddress != "" { + // set worker's private address to --node-ip in --extra-kubelet-args if cloud ins't enabled + enableCloudProvider, err := h.InstallFlags.GetBoolean("--enable-cloud-provider") + if err != nil { + return "", fmt.Errorf("--enable-cloud-provider flag is set to invalid value: %s. (%v)", h.InstallFlags.GetValue("--enable-cloud-provider"), err) + } + if !enableCloudProvider && h.PrivateAddress != "" { extra.AddUnlessExist(fmt.Sprintf("--node-ip=%s", h.PrivateAddress)) } + if h.HostnameOverride != "" { extra.AddOrReplace(fmt.Sprintf("--hostname-override=%s", h.HostnameOverride)) } @@ -284,9 +289,9 @@ func (h *Host) K0sInstallCommand() string { sudocmd, err := h.Sudo(cmd) if err != nil { log.Warnf("%s: %s", h, err.Error()) - return cmd + return cmd, nil } - return sudocmd + return sudocmd, nil } // K0sBackupCommand returns a full command to be used as run k0s backup diff --git a/pkg/apis/k0sctl.k0sproject.io/v1beta1/cluster/host_test.go b/pkg/apis/k0sctl.k0sproject.io/v1beta1/cluster/host_test.go index bd39fc6e..e1563630 100644 --- a/pkg/apis/k0sctl.k0sproject.io/v1beta1/cluster/host_test.go +++ b/pkg/apis/k0sctl.k0sproject.io/v1beta1/cluster/host_test.go @@ -78,23 +78,44 @@ func TestK0sInstallCommand(t *testing.T) { h := Host{Role: "worker"} h.Configurer = &mockconfigurer{} - require.Equal(t, `k0s install worker --token-file "from-configurer"`, h.K0sInstallCommand()) + cmd, err := h.K0sInstallCommand() + require.NoError(t, err) + require.Equal(t, `k0s install worker --token-file "from-configurer"`, cmd) h.Role = "controller" h.Metadata.IsK0sLeader = true - require.Equal(t, `k0s install controller --config "from-configurer"`, h.K0sInstallCommand()) + cmd, err = h.K0sInstallCommand() + require.NoError(t, err) + require.Equal(t, `k0s install controller --config "from-configurer"`, cmd) + h.Metadata.IsK0sLeader = false - require.Equal(t, `k0s install controller --token-file "from-configurer" --config "from-configurer"`, h.K0sInstallCommand()) + cmd, err = h.K0sInstallCommand() + require.NoError(t, err) + require.Equal(t, `k0s install controller --token-file "from-configurer" --config "from-configurer"`, cmd) h.Role = "controller+worker" h.Metadata.IsK0sLeader = true - require.Equal(t, `k0s install controller --enable-worker --config "from-configurer"`, h.K0sInstallCommand()) + cmd, err = h.K0sInstallCommand() + require.NoError(t, err) + require.Equal(t, `k0s install controller --enable-worker --config "from-configurer"`, cmd) h.Metadata.IsK0sLeader = false - require.Equal(t, `k0s install controller --enable-worker --token-file "from-configurer" --config "from-configurer"`, h.K0sInstallCommand()) + cmd, err = h.K0sInstallCommand() + require.NoError(t, err) + require.Equal(t, `k0s install controller --enable-worker --token-file "from-configurer" --config "from-configurer"`, cmd) h.Role = "worker" h.PrivateAddress = "10.0.0.9" - require.Equal(t, `k0s install worker --token-file "from-configurer" --kubelet-extra-args="--node-ip=10.0.0.9"`, h.K0sInstallCommand()) + cmd, err = h.K0sInstallCommand() + require.NoError(t, err) + require.Equal(t, `k0s install worker --token-file "from-configurer" --kubelet-extra-args="--node-ip=10.0.0.9"`, cmd) + h.InstallFlags = []string{`--kubelet-extra-args="--foo bar"`} - require.Equal(t, `k0s install worker --kubelet-extra-args="--foo bar --node-ip=10.0.0.9" --token-file "from-configurer"`, h.K0sInstallCommand()) + cmd, err = h.K0sInstallCommand() + require.NoError(t, err) + require.Equal(t, `k0s install worker --kubelet-extra-args="--foo bar --node-ip=10.0.0.9" --token-file "from-configurer"`, cmd) + + h.InstallFlags = []string{`--enable-cloud-provider`} + cmd, err = h.K0sInstallCommand() + require.NoError(t, err) + require.Equal(t, `k0s install worker --enable-cloud-provider --token-file "from-configurer"`, cmd) }