From cd7b4666b512b9b5165e4776195e26c7e79ac432 Mon Sep 17 00:00:00 2001 From: Tom Wieczorek Date: Tue, 7 Jan 2025 15:09:43 +0100 Subject: [PATCH] Provide several sub-commands only on Linux They won't work on non-Linux systems anyways. Use build flags to add platform-specific sub-commands instead of runtime checks. Also add build tag to files that only make sense on specific platforms. This includes Autopilot, as this relies on the status socket, which is not available on Windows at the moment. Signed-off-by: Tom Wieczorek --- cmd/controller/controller.go | 2 + cmd/controller/controller_test.go | 5 ++ cmd/install/controller.go | 2 + cmd/install/controller_test.go | 2 + cmd/install/install.go | 3 +- .../install_linux.go} | 18 ++---- cmd/install/install_other.go | 25 ++++++++ cmd/install/worker.go | 3 +- cmd/reset/reset.go | 2 + cmd/root.go | 19 +----- cmd/root_linux.go | 35 +++++++++++ .../bridge_other.go => cmd/root_other.go | 10 ++-- cmd/root_test.go | 9 ++- cmd/start/start.go | 3 +- cmd/status/status.go | 2 + cmd/stop/stop.go | 3 +- cmd/token/create.go | 2 + cmd/token/token.go | 3 +- cmd/token/token_other.go | 25 ++++++++ .../backup_windows.go => token/token_unix.go} | 21 ++----- cmd/worker/worker.go | 28 +-------- cmd/worker/worker_other.go | 31 ++++++++++ cmd/worker/worker_unix.go | 59 +++++++++++++++++++ internal/pkg/users/lookup_unix_test.go | 2 + pkg/autopilot/controller/root_controller.go | 2 + .../controller/root_controller_test.go | 2 + pkg/autopilot/controller/root_worker.go | 2 + pkg/autopilot/controller/setup.go | 2 + pkg/autopilot/controller/signal/init.go | 2 + pkg/autopilot/controller/signal/k0s/apply.go | 2 + pkg/autopilot/controller/signal/k0s/cordon.go | 17 ++++++ .../controller/signal/k0s/download.go | 2 + pkg/autopilot/controller/signal/k0s/init.go | 51 +++------------- .../{restart_windows.go => restart_other.go} | 4 ++ .../controller/signal/k0s/restart_unix.go | 13 ++++ pkg/autopilot/controller/signal/k0s/signal.go | 18 ++++-- .../controller/signal/k0s/signal_test.go | 2 + .../controller/signal/k0s/uncordon.go | 2 + .../controller/updates/periodicupdater.go | 2 + .../controller/updates/update_controller.go | 2 + pkg/autopilot/controller/updates/updater.go | 2 + pkg/cleanup/cleanup.go | 2 + pkg/cleanup/{cni.go => cni_linux.go} | 0 pkg/cleanup/{users.go => users_linux.go} | 0 pkg/component/controller/autopilot.go | 2 + pkg/component/status/client.go | 3 +- pkg/component/status/status.go | 3 + pkg/component/worker/autopilot.go | 2 + pkg/install/service.go | 27 +-------- pkg/install/service_linux.go | 43 ++++++++++++++ pkg/install/service_other.go | 25 ++++++++ pkg/install/{users.go => users_linux.go} | 2 + 52 files changed, 388 insertions(+), 162 deletions(-) rename cmd/{restore/restore_windows.go => install/install_linux.go} (59%) create mode 100644 cmd/install/install_other.go create mode 100644 cmd/root_linux.go rename pkg/cleanup/bridge_other.go => cmd/root_other.go (79%) create mode 100644 cmd/token/token_other.go rename cmd/{backup/backup_windows.go => token/token_unix.go} (60%) create mode 100644 cmd/worker/worker_other.go create mode 100644 cmd/worker/worker_unix.go rename pkg/autopilot/controller/signal/k0s/{restart_windows.go => restart_other.go} (97%) rename pkg/cleanup/{cni.go => cni_linux.go} (100%) rename pkg/cleanup/{users.go => users_linux.go} (100%) create mode 100644 pkg/install/service_linux.go create mode 100644 pkg/install/service_other.go rename pkg/install/{users.go => users_linux.go} (97%) diff --git a/cmd/controller/controller.go b/cmd/controller/controller.go index 87b05e795dd7..4bd2344f5cfe 100644 --- a/cmd/controller/controller.go +++ b/cmd/controller/controller.go @@ -1,3 +1,5 @@ +//go:build unix + /* Copyright 2021 k0s authors diff --git a/cmd/controller/controller_test.go b/cmd/controller/controller_test.go index 2f3f270775e8..16d05c94faca 100644 --- a/cmd/controller/controller_test.go +++ b/cmd/controller/controller_test.go @@ -17,6 +17,7 @@ limitations under the License. package controller_test import ( + "runtime" "strconv" "strings" "testing" @@ -28,6 +29,10 @@ import ( ) func TestControllerCmd_Help(t *testing.T) { + if runtime.GOOS != "linux" { + t.Skip("Running controllers is only supported on Linux") + } + defaultConfigPath := strconv.Quote(constant.K0sConfigPathDefault) defaultDataDir := strconv.Quote(constant.DataDirDefault) diff --git a/cmd/install/controller.go b/cmd/install/controller.go index d27ab6f94fa6..06f665237af2 100644 --- a/cmd/install/controller.go +++ b/cmd/install/controller.go @@ -1,3 +1,5 @@ +//go:build linux + /* Copyright 2021 k0s authors diff --git a/cmd/install/controller_test.go b/cmd/install/controller_test.go index bfab32f960c3..33abab182580 100644 --- a/cmd/install/controller_test.go +++ b/cmd/install/controller_test.go @@ -1,3 +1,5 @@ +//go:build linux + /* Copyright 2024 k0s authors diff --git a/cmd/install/install.go b/cmd/install/install.go index 1b2d89c49613..850c42cd7cee 100644 --- a/cmd/install/install.go +++ b/cmd/install/install.go @@ -37,8 +37,9 @@ func NewInstallCmd() *cobra.Command { Run: func(*cobra.Command, []string) { /* Enforce arg validation. */ }, } - cmd.AddCommand(installControllerCmd(&installFlags)) cmd.AddCommand(installWorkerCmd(&installFlags)) + addPlatformSpecificCommands(cmd, &installFlags) + cmd.PersistentFlags().BoolVar(&installFlags.force, "force", false, "force init script creation") cmd.PersistentFlags().StringArrayVarP(&installFlags.envVars, "env", "e", nil, "set environment variable") cmd.PersistentFlags().AddFlagSet(config.GetPersistentFlagSet()) diff --git a/cmd/restore/restore_windows.go b/cmd/install/install_linux.go similarity index 59% rename from cmd/restore/restore_windows.go rename to cmd/install/install_linux.go index a23e2e4cb6f2..6c306f7548cd 100644 --- a/cmd/restore/restore_windows.go +++ b/cmd/install/install_linux.go @@ -1,5 +1,5 @@ /* -Copyright 2021 k0s authors +Copyright 2025 k0s authors Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. @@ -14,22 +14,12 @@ See the License for the specific language governing permissions and limitations under the License. */ -package restore +package install import ( - "errors" - "github.com/spf13/cobra" ) -var restoredConfigPath string - -func NewRestoreCmd() *cobra.Command { - return &cobra.Command{ - Use: "restore", - Short: "restore k0s state from given backup archive. Not supported in Windows OS", - RunE: func(cmd *cobra.Command, args []string) error { - return errors.New("unsupported Operating System for this command") - }, - } +func addPlatformSpecificCommands(install *cobra.Command, installFlags *installFlags) { + install.AddCommand(installControllerCmd(installFlags)) } diff --git a/cmd/install/install_other.go b/cmd/install/install_other.go new file mode 100644 index 000000000000..8764e65a3c7b --- /dev/null +++ b/cmd/install/install_other.go @@ -0,0 +1,25 @@ +//go:build !linux + +/* +Copyright 2025 k0s authors + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package install + +import "github.com/spf13/cobra" + +func addPlatformSpecificCommands(*cobra.Command, *installFlags) { + // no-op +} diff --git a/cmd/install/worker.go b/cmd/install/worker.go index 30f693c02a6f..cbcd0649c688 100644 --- a/cmd/install/worker.go +++ b/cmd/install/worker.go @@ -20,6 +20,7 @@ import ( "errors" "fmt" "os" + "runtime" "github.com/spf13/cobra" @@ -37,7 +38,7 @@ All default values of worker command will be passed to the service stub unless o Windows flags like "--api-server", "--cidr-range" and "--cluster-dns" will be ignored since install command doesn't yet support Windows services`, Args: cobra.NoArgs, RunE: func(cmd *cobra.Command, _ []string) error { - if os.Geteuid() != 0 { + if runtime.GOOS != "windows" && os.Geteuid() != 0 { return errors.New("this command must be run as root") } diff --git a/cmd/reset/reset.go b/cmd/reset/reset.go index 908c1540f7c5..8fee8ae43f63 100644 --- a/cmd/reset/reset.go +++ b/cmd/reset/reset.go @@ -1,3 +1,5 @@ +//go:build linux + /* Copyright 2021 k0s authors diff --git a/cmd/root.go b/cmd/root.go index 18f3d4c779bd..37037c14df60 100644 --- a/cmd/root.go +++ b/cmd/root.go @@ -20,22 +20,16 @@ import ( "errors" "net/http" "os" - "runtime" "github.com/k0sproject/k0s/cmd/airgap" "github.com/k0sproject/k0s/cmd/api" - "github.com/k0sproject/k0s/cmd/backup" configcmd "github.com/k0sproject/k0s/cmd/config" - "github.com/k0sproject/k0s/cmd/controller" "github.com/k0sproject/k0s/cmd/ctr" "github.com/k0sproject/k0s/cmd/etcd" "github.com/k0sproject/k0s/cmd/install" "github.com/k0sproject/k0s/cmd/kubeconfig" "github.com/k0sproject/k0s/cmd/kubectl" - "github.com/k0sproject/k0s/cmd/reset" - "github.com/k0sproject/k0s/cmd/restore" "github.com/k0sproject/k0s/cmd/start" - "github.com/k0sproject/k0s/cmd/status" "github.com/k0sproject/k0s/cmd/stop" "github.com/k0sproject/k0s/cmd/sysinfo" "github.com/k0sproject/k0s/cmd/token" @@ -82,24 +76,13 @@ func NewRootCmd() *cobra.Command { cmd.AddCommand(airgap.NewAirgapCmd()) cmd.AddCommand(api.NewAPICmd()) - cmd.AddCommand(backup.NewBackupCmd()) - cmd.AddCommand(controller.NewControllerCmd()) cmd.AddCommand(ctr.NewCtrCommand()) cmd.AddCommand(configcmd.NewConfigCmd()) cmd.AddCommand(etcd.NewEtcdCmd()) cmd.AddCommand(install.NewInstallCmd()) cmd.AddCommand(kubeconfig.NewKubeConfigCmd()) cmd.AddCommand(kubectl.NewK0sKubectlCmd()) - if runtime.GOOS == "linux" { - // Currently only supported on Linux - cmd.AddCommand(reset.NewResetCmd()) - } - cmd.AddCommand(restore.NewRestoreCmd()) cmd.AddCommand(start.NewStartCmd()) - if runtime.GOOS == "linux" { - // Currently only supported on Linux - cmd.AddCommand(status.NewStatusCmd()) - } cmd.AddCommand(stop.NewStopCmd()) cmd.AddCommand(sysinfo.NewSysinfoCmd()) cmd.AddCommand(token.NewTokenCmd()) @@ -109,6 +92,8 @@ func NewRootCmd() *cobra.Command { cmd.AddCommand(newCompletionCmd()) cmd.AddCommand(newDocsCmd()) + addPlatformSpecificCommands(cmd) + cmd.DisableAutoGenTag = true longDesc = "k0s - The zero friction Kubernetes - https://k0sproject.io" if build.EulaNotice != "" { diff --git a/cmd/root_linux.go b/cmd/root_linux.go new file mode 100644 index 000000000000..ed88c3d69c17 --- /dev/null +++ b/cmd/root_linux.go @@ -0,0 +1,35 @@ +/* +Copyright 2025 k0s authors + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package cmd + +import ( + "github.com/k0sproject/k0s/cmd/backup" + "github.com/k0sproject/k0s/cmd/controller" + "github.com/k0sproject/k0s/cmd/reset" + "github.com/k0sproject/k0s/cmd/restore" + "github.com/k0sproject/k0s/cmd/status" + + "github.com/spf13/cobra" +) + +func addPlatformSpecificCommands(root *cobra.Command) { + root.AddCommand(backup.NewBackupCmd()) + root.AddCommand(controller.NewControllerCmd()) + root.AddCommand(reset.NewResetCmd()) + root.AddCommand(restore.NewRestoreCmd()) + root.AddCommand(status.NewStatusCmd()) +} diff --git a/pkg/cleanup/bridge_other.go b/cmd/root_other.go similarity index 79% rename from pkg/cleanup/bridge_other.go rename to cmd/root_other.go index 215f255e2395..24b49be8ba17 100644 --- a/pkg/cleanup/bridge_other.go +++ b/cmd/root_other.go @@ -1,7 +1,7 @@ //go:build !linux /* -Copyright 2021 k0s authors +Copyright 2025 k0s authors Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. @@ -16,8 +16,8 @@ See the License for the specific language governing permissions and limitations under the License. */ -package cleanup +package cmd -func newBridgeStep() Step { - return nil -} +import "github.com/spf13/cobra" + +func addPlatformSpecificCommands(root *cobra.Command) { /* no-op */ } diff --git a/cmd/root_test.go b/cmd/root_test.go index 263c45c80ca8..e3bc7eec7327 100644 --- a/cmd/root_test.go +++ b/cmd/root_test.go @@ -21,6 +21,7 @@ import ( "errors" "fmt" "io" + "runtime" "slices" "strings" "testing" @@ -75,12 +76,16 @@ func TestRootCmd_Flags(t *testing.T) { func TestUnknownSubCommandsAreRejected(t *testing.T) { commandsWithArguments := []string{ - "controller", "kubeconfig create", - "restore", "token invalidate", "worker", } + if runtime.GOOS == "linux" { + commandsWithArguments = append(commandsWithArguments, + "controller", + "restore", + ) + } t.Cleanup(func() { if !t.Failed() { assert.Empty(t, commandsWithArguments, "Some sub-commands are listed unnecessarily") diff --git a/cmd/start/start.go b/cmd/start/start.go index c0e511e04bb8..46197c08a0f7 100644 --- a/cmd/start/start.go +++ b/cmd/start/start.go @@ -19,6 +19,7 @@ package start import ( "errors" "os" + "runtime" "github.com/k0sproject/k0s/pkg/install" @@ -32,7 +33,7 @@ func NewStartCmd() *cobra.Command { Short: "Start the k0s service configured on this host. Must be run as root (or with sudo)", Args: cobra.NoArgs, RunE: func(cmd *cobra.Command, _ []string) error { - if os.Geteuid() != 0 { + if runtime.GOOS != "windows" && os.Geteuid() != 0 { return errors.New("this command must be run as root") } svc, err := install.InstalledService() diff --git a/cmd/status/status.go b/cmd/status/status.go index e2294b9c483b..258ab2adffdc 100644 --- a/cmd/status/status.go +++ b/cmd/status/status.go @@ -1,3 +1,5 @@ +//go:build unix + /* Copyright 2021 k0s authors diff --git a/cmd/stop/stop.go b/cmd/stop/stop.go index 69429b9d26c0..7c1368505186 100644 --- a/cmd/stop/stop.go +++ b/cmd/stop/stop.go @@ -19,6 +19,7 @@ package stop import ( "errors" "os" + "runtime" "github.com/k0sproject/k0s/pkg/install" @@ -32,7 +33,7 @@ func NewStopCmd() *cobra.Command { Short: "Stop the k0s service configured on this host. Must be run as root (or with sudo)", Args: cobra.NoArgs, RunE: func(cmd *cobra.Command, _ []string) error { - if os.Geteuid() != 0 { + if runtime.GOOS != "windows" && os.Geteuid() != 0 { return errors.New("this command must be run as root") } svc, err := install.InstalledService() diff --git a/cmd/token/create.go b/cmd/token/create.go index 05e24e45ae2c..724870c19fe0 100644 --- a/cmd/token/create.go +++ b/cmd/token/create.go @@ -1,3 +1,5 @@ +//go:build unix + /* Copyright 2021 k0s authors diff --git a/cmd/token/token.go b/cmd/token/token.go index dee7086113d7..1c1dc674ca71 100644 --- a/cmd/token/token.go +++ b/cmd/token/token.go @@ -32,10 +32,11 @@ func NewTokenCmd() *cobra.Command { Run: func(*cobra.Command, []string) { /* Enforce arg validation. */ }, } - cmd.AddCommand(tokenCreateCmd()) cmd.AddCommand(tokenListCmd()) cmd.AddCommand(tokenInvalidateCmd()) cmd.AddCommand(preSharedCmd()) + addPlatformSpecificCommands(cmd) + return cmd } diff --git a/cmd/token/token_other.go b/cmd/token/token_other.go new file mode 100644 index 000000000000..9ff8da998678 --- /dev/null +++ b/cmd/token/token_other.go @@ -0,0 +1,25 @@ +//go:build !unix + +/* +Copyright 2025 k0s authors + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package token + +import ( + "github.com/spf13/cobra" +) + +func addPlatformSpecificCommands(*cobra.Command) { /* no-op */ } diff --git a/cmd/backup/backup_windows.go b/cmd/token/token_unix.go similarity index 60% rename from cmd/backup/backup_windows.go rename to cmd/token/token_unix.go index bd2a43661168..c203937b3aa6 100644 --- a/cmd/backup/backup_windows.go +++ b/cmd/token/token_unix.go @@ -1,5 +1,7 @@ +//go:build unix + /* -Copyright 2021 k0s authors +Copyright 2025 k0s authors Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. @@ -14,23 +16,12 @@ See the License for the specific language governing permissions and limitations under the License. */ -package backup +package token import ( - "errors" - "github.com/spf13/cobra" ) -var savePath string - -func NewBackupCmd() *cobra.Command { - return &cobra.Command{ - Use: "backup", - Short: "Back-Up k0s configuration. Not supported on Windows OS", - Args: cobra.NoArgs, - RunE: func(cmd *cobra.Command, args []string) error { - return errors.New("unsupported Operating System for this command") - }, - } +func addPlatformSpecificCommands(token *cobra.Command) { + token.AddCommand(tokenCreateCmd()) } diff --git a/cmd/worker/worker.go b/cmd/worker/worker.go index 8c9e34d249df..a4afef316a1f 100644 --- a/cmd/worker/worker.go +++ b/cmd/worker/worker.go @@ -27,11 +27,9 @@ import ( k0slog "github.com/k0sproject/k0s/internal/pkg/log" "github.com/k0sproject/k0s/internal/pkg/sysinfo" - "github.com/k0sproject/k0s/pkg/build" "github.com/k0sproject/k0s/pkg/component/iptables" "github.com/k0sproject/k0s/pkg/component/manager" "github.com/k0sproject/k0s/pkg/component/prober" - "github.com/k0sproject/k0s/pkg/component/status" "github.com/k0sproject/k0s/pkg/component/worker" workerconfig "github.com/k0sproject/k0s/pkg/component/worker/config" "github.com/k0sproject/k0s/pkg/component/worker/containerd" @@ -172,31 +170,7 @@ func (c *Command) Start(ctx context.Context) error { certManager := worker.NewCertificateManager(kubeletKubeconfigPath) - // if running inside a controller, status component is already running - if !c.SingleNode && !c.EnableWorker { - componentManager.Add(ctx, &status.Status{ - Prober: prober.DefaultProber, - StatusInformation: status.K0sStatus{ - Pid: os.Getpid(), - Role: "worker", - Args: os.Args, - Version: build.Version, - Workloads: true, - SingleNode: false, - K0sVars: c.K0sVars, - // worker does not have cluster config. this is only shown in "k0s status -o json". - // todo: if it's needed, a worker side config client can be set up and used to load the config - ClusterConfig: nil, - }, - CertManager: certManager, - Socket: c.K0sVars.StatusSocketPath, - }) - } - - componentManager.Add(ctx, &worker.Autopilot{ - K0sVars: c.K0sVars, - CertManager: certManager, - }) + addPlatformSpecificComponents(ctx, componentManager, c.K0sVars, &c.ControllerOptions, certManager) // extract needed components if err := componentManager.Init(ctx); err != nil { diff --git a/cmd/worker/worker_other.go b/cmd/worker/worker_other.go new file mode 100644 index 000000000000..2f0ef1153dc8 --- /dev/null +++ b/cmd/worker/worker_other.go @@ -0,0 +1,31 @@ +//go:build !unix + +/* +Copyright 2025 k0s authors + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package worker + +import ( + "context" + + "github.com/k0sproject/k0s/pkg/component/manager" + "github.com/k0sproject/k0s/pkg/component/worker" + "github.com/k0sproject/k0s/pkg/config" +) + +func addPlatformSpecificComponents(context.Context, *manager.Manager, *config.CfgVars, *config.ControllerOptions, *worker.CertificateManager) { + // no-op +} diff --git a/cmd/worker/worker_unix.go b/cmd/worker/worker_unix.go new file mode 100644 index 000000000000..0f4908f9cd5c --- /dev/null +++ b/cmd/worker/worker_unix.go @@ -0,0 +1,59 @@ +//go:build unix + +/* +Copyright 2025 k0s authors + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package worker + +import ( + "context" + "os" + + "github.com/k0sproject/k0s/pkg/build" + "github.com/k0sproject/k0s/pkg/component/manager" + "github.com/k0sproject/k0s/pkg/component/prober" + "github.com/k0sproject/k0s/pkg/component/status" + "github.com/k0sproject/k0s/pkg/component/worker" + "github.com/k0sproject/k0s/pkg/config" +) + +func addPlatformSpecificComponents(ctx context.Context, m *manager.Manager, k0sVars *config.CfgVars, opts *config.ControllerOptions, certManager *worker.CertificateManager) { + // if running inside a controller, status component is already running + if !opts.SingleNode && !opts.EnableWorker { + m.Add(ctx, &status.Status{ + Prober: prober.DefaultProber, + StatusInformation: status.K0sStatus{ + Pid: os.Getpid(), + Role: "worker", + Args: os.Args, + Version: build.Version, + Workloads: true, + SingleNode: false, + K0sVars: k0sVars, + // worker does not have cluster config. this is only shown in "k0s status -o json". + // todo: if it's needed, a worker side config client can be set up and used to load the config + ClusterConfig: nil, + }, + CertManager: certManager, + Socket: k0sVars.StatusSocketPath, + }) + } + + m.Add(ctx, &worker.Autopilot{ + K0sVars: k0sVars, + CertManager: certManager, + }) +} diff --git a/internal/pkg/users/lookup_unix_test.go b/internal/pkg/users/lookup_unix_test.go index 1bf444bc429c..a240d173887a 100644 --- a/internal/pkg/users/lookup_unix_test.go +++ b/internal/pkg/users/lookup_unix_test.go @@ -1,3 +1,5 @@ +//go:build unix + /* Copyright 2022 k0s authors diff --git a/pkg/autopilot/controller/root_controller.go b/pkg/autopilot/controller/root_controller.go index b332a7439d8a..13290b2ff4bb 100644 --- a/pkg/autopilot/controller/root_controller.go +++ b/pkg/autopilot/controller/root_controller.go @@ -1,3 +1,5 @@ +//go:build unix + // Copyright 2021 k0s authors // // Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/pkg/autopilot/controller/root_controller_test.go b/pkg/autopilot/controller/root_controller_test.go index 9c778fd10194..2c3d2d3697d7 100644 --- a/pkg/autopilot/controller/root_controller_test.go +++ b/pkg/autopilot/controller/root_controller_test.go @@ -1,3 +1,5 @@ +//go:build unix + // Copyright 2021 k0s authors // // Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/pkg/autopilot/controller/root_worker.go b/pkg/autopilot/controller/root_worker.go index 8bb43c670700..531e556cb64c 100644 --- a/pkg/autopilot/controller/root_worker.go +++ b/pkg/autopilot/controller/root_worker.go @@ -1,3 +1,5 @@ +//go:build unix + // Copyright 2022 k0s authors // // Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/pkg/autopilot/controller/setup.go b/pkg/autopilot/controller/setup.go index d39075e0fe12..fa6d4f0e36f4 100644 --- a/pkg/autopilot/controller/setup.go +++ b/pkg/autopilot/controller/setup.go @@ -1,3 +1,5 @@ +//go:build unix + // Copyright 2022 k0s authors // // Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/pkg/autopilot/controller/signal/init.go b/pkg/autopilot/controller/signal/init.go index 4c51c1315b3b..980cf7bd42cf 100644 --- a/pkg/autopilot/controller/signal/init.go +++ b/pkg/autopilot/controller/signal/init.go @@ -1,3 +1,5 @@ +//go:build unix + // Copyright 2022 k0s authors // // Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/pkg/autopilot/controller/signal/k0s/apply.go b/pkg/autopilot/controller/signal/k0s/apply.go index 003792f7fc77..c25910db5e3b 100644 --- a/pkg/autopilot/controller/signal/k0s/apply.go +++ b/pkg/autopilot/controller/signal/k0s/apply.go @@ -36,6 +36,8 @@ import ( crpred "sigs.k8s.io/controller-runtime/pkg/predicate" ) +const ApplyingUpdate = "ApplyingUpdate" + // applyingUpdateEventFilter creates a controller-runtime predicate that governs which // objects will make it into reconciliation, and which will be ignored. func applyingUpdateEventFilter(hostname string, handler apsigpred.ErrorHandler) crpred.Predicate { diff --git a/pkg/autopilot/controller/signal/k0s/cordon.go b/pkg/autopilot/controller/signal/k0s/cordon.go index d449990284f0..8c132b5b7d91 100644 --- a/pkg/autopilot/controller/signal/k0s/cordon.go +++ b/pkg/autopilot/controller/signal/k0s/cordon.go @@ -22,11 +22,13 @@ import ( autopilotv1beta2 "github.com/k0sproject/k0s/pkg/apis/autopilot/v1beta2" apcomm "github.com/k0sproject/k0s/pkg/autopilot/common" + apconst "github.com/k0sproject/k0s/pkg/autopilot/constant" apdel "github.com/k0sproject/k0s/pkg/autopilot/controller/delegate" apsigpred "github.com/k0sproject/k0s/pkg/autopilot/controller/signal/common/predicate" apsigv2 "github.com/k0sproject/k0s/pkg/autopilot/signaling/v2" cr "sigs.k8s.io/controller-runtime" + "sigs.k8s.io/controller-runtime/pkg/client" crcli "sigs.k8s.io/controller-runtime/pkg/client" crev "sigs.k8s.io/controller-runtime/pkg/event" crman "sigs.k8s.io/controller-runtime/pkg/manager" @@ -38,6 +40,8 @@ import ( "k8s.io/kubectl/pkg/drain" ) +const Cordoning = "Cordoning" + // cordoningEventFilter creates a controller-runtime predicate that governs which objects // will make it into reconciliation, and which will be ignored. func cordoningEventFilter(hostname string, handler apsigpred.ErrorHandler) crpred.Predicate { @@ -204,3 +208,16 @@ func (r *cordoning) drainNode(ctx context.Context, signalNode crcli.Object) erro return nil } + +func needsCordoning(signalNode client.Object) bool { + kind := signalNode.GetObjectKind().GroupVersionKind().Kind + if kind == "Node" { + return true + } + for k, v := range signalNode.GetAnnotations() { + if k == apconst.K0SControlNodeModeAnnotation && v == apconst.K0SControlNodeModeControllerWorker { + return true + } + } + return false +} diff --git a/pkg/autopilot/controller/signal/k0s/download.go b/pkg/autopilot/controller/signal/k0s/download.go index 721d7f7877eb..36c1048e7bd1 100644 --- a/pkg/autopilot/controller/signal/k0s/download.go +++ b/pkg/autopilot/controller/signal/k0s/download.go @@ -33,6 +33,8 @@ import ( crpred "sigs.k8s.io/controller-runtime/pkg/predicate" ) +const Downloading = "Downloading" + // downloadEventFilter creates a controller-runtime predicate that governs which objects // will make it into reconciliation, and which will be ignored. func downloadEventFilter(hostname string, handler apsigpred.ErrorHandler) crpred.Predicate { diff --git a/pkg/autopilot/controller/signal/k0s/init.go b/pkg/autopilot/controller/signal/k0s/init.go index 82b5fa21dfe4..aafb5f074d4f 100644 --- a/pkg/autopilot/controller/signal/k0s/init.go +++ b/pkg/autopilot/controller/signal/k0s/init.go @@ -1,3 +1,5 @@ +//go:build unix + // Copyright 2021 k0s authors // // Licensed under the Apache License, Version 2.0 (the "License"); @@ -21,26 +23,14 @@ import ( "path/filepath" apcomm "github.com/k0sproject/k0s/pkg/autopilot/common" - apconst "github.com/k0sproject/k0s/pkg/autopilot/constant" apdel "github.com/k0sproject/k0s/pkg/autopilot/controller/delegate" apsigpred "github.com/k0sproject/k0s/pkg/autopilot/controller/signal/common/predicate" - apsigv2 "github.com/k0sproject/k0s/pkg/autopilot/signaling/v2" "github.com/k0sproject/k0s/pkg/component/status" "github.com/sirupsen/logrus" - "sigs.k8s.io/controller-runtime/pkg/client" crman "sigs.k8s.io/controller-runtime/pkg/manager" ) -const ( - Downloading = "Downloading" - Cordoning = "Cordoning" - CordoningFailed = "CordoningFailed" - UnCordoning = "UnCordoning" - ApplyingUpdate = "ApplyingUpdate" - Restart = "Restart" -) - // RegisterControllers registers all of the autopilot controllers used for updating `k0s` // to the controller-runtime manager. func RegisterControllers(ctx context.Context, logger *logrus.Entry, mgr crman.Manager, delegate apdel.ControllerDelegate, clusterID string) error { @@ -59,7 +49,11 @@ func RegisterControllers(ctx context.Context, logger *logrus.Entry, mgr crman.Ma logger.Infof("Using effective hostname = '%v'", hostname) - if err := registerSignalController(logger, mgr, signalControllerEventFilter(hostname, apsigpred.DefaultErrorHandler(logger, "k0s signal")), delegate, clusterID); err != nil { + k0sVersionHandler := func() (string, error) { + return getK0sVersion(DefaultK0sStatusSocketPath) + } + + if err := registerSignalController(logger, mgr, signalControllerEventFilter(hostname, apsigpred.DefaultErrorHandler(logger, "k0s signal")), delegate, clusterID, k0sVersionHandler); err != nil { return fmt.Errorf("unable to register k0s 'signal' controller: %w", err) } @@ -100,34 +94,3 @@ func getK0sVersion(statusSocketPath string) (string, error) { return status.Version, nil } - -// getK0sPid returns the PID of a running k0s based on its status socket. -func getK0sPid(statusSocketPath string) (int, error) { - status, err := status.GetStatusInfo(statusSocketPath) - if err != nil { - return -1, err - } - - return status.Pid, nil -} - -// signalDataUpdateCommandK0sPredicate creates a predicate that ensures that the -// provided SignalData is an 'k0s' update. -func signalDataUpdateCommandK0sPredicate() apsigpred.SignalDataPredicate { - return func(signalData apsigv2.SignalData) bool { - return signalData.Command.K0sUpdate != nil - } -} - -func needsCordoning(signalNode client.Object) bool { - kind := signalNode.GetObjectKind().GroupVersionKind().Kind - if kind == "Node" { - return true - } - for k, v := range signalNode.GetAnnotations() { - if k == apconst.K0SControlNodeModeAnnotation && v == apconst.K0SControlNodeModeControllerWorker { - return true - } - } - return false -} diff --git a/pkg/autopilot/controller/signal/k0s/restart_windows.go b/pkg/autopilot/controller/signal/k0s/restart_other.go similarity index 97% rename from pkg/autopilot/controller/signal/k0s/restart_windows.go rename to pkg/autopilot/controller/signal/k0s/restart_other.go index 9c32a1a665e9..1c151bf09aee 100644 --- a/pkg/autopilot/controller/signal/k0s/restart_windows.go +++ b/pkg/autopilot/controller/signal/k0s/restart_other.go @@ -1,3 +1,5 @@ +//go:build !unix + // Copyright 2022 k0s authors // // Licensed under the Apache License, Version 2.0 (the "License"); @@ -22,6 +24,8 @@ import ( crpred "sigs.k8s.io/controller-runtime/pkg/predicate" ) +const Restart = "Restart" + // restartEventFilter creates a controller-runtime predicate that governs which // objects will make it into reconciliation, and which will be ignored. func restartEventFilter(hostname string, handler apsigpred.ErrorHandler) crpred.Predicate { diff --git a/pkg/autopilot/controller/signal/k0s/restart_unix.go b/pkg/autopilot/controller/signal/k0s/restart_unix.go index 4059b0f35166..44e6010edb15 100644 --- a/pkg/autopilot/controller/signal/k0s/restart_unix.go +++ b/pkg/autopilot/controller/signal/k0s/restart_unix.go @@ -26,6 +26,7 @@ import ( apdel "github.com/k0sproject/k0s/pkg/autopilot/controller/delegate" apsigpred "github.com/k0sproject/k0s/pkg/autopilot/controller/signal/common/predicate" apsigv2 "github.com/k0sproject/k0s/pkg/autopilot/signaling/v2" + "github.com/k0sproject/k0s/pkg/component/status" "github.com/sirupsen/logrus" cr "sigs.k8s.io/controller-runtime" @@ -35,6 +36,8 @@ import ( crpred "sigs.k8s.io/controller-runtime/pkg/predicate" ) +const Restart = "Restart" + const ( restartRequeueDuration = 5 * time.Second ) @@ -149,3 +152,13 @@ func (r *restart) Reconcile(ctx context.Context, req cr.Request) (cr.Result, err return cr.Result{}, nil } + +// getK0sPid returns the PID of a running k0s based on its status socket. +func getK0sPid(statusSocketPath string) (int, error) { + status, err := status.GetStatusInfo(statusSocketPath) + if err != nil { + return -1, err + } + + return status.Pid, nil +} diff --git a/pkg/autopilot/controller/signal/k0s/signal.go b/pkg/autopilot/controller/signal/k0s/signal.go index 63c4741f6770..379241ce9aa8 100644 --- a/pkg/autopilot/controller/signal/k0s/signal.go +++ b/pkg/autopilot/controller/signal/k0s/signal.go @@ -40,6 +40,14 @@ const ( type k0sVersionHandlerFunc func() (string, error) +// signalDataUpdateCommandK0sPredicate creates a predicate that ensures that the +// provided SignalData is an 'k0s' update. +func signalDataUpdateCommandK0sPredicate() apsigpred.SignalDataPredicate { + return func(signalData apsigv2.SignalData) bool { + return signalData.Command.K0sUpdate != nil + } +} + // signalControllerEventFilter creates a controller-runtime predicate that governs which objects // will make it into reconciliation, and which will be ignored. func signalControllerEventFilter(hostname string, handler apsigpred.ErrorHandler) crpred.Predicate { @@ -71,7 +79,7 @@ type signalControllerHandler struct { // // This controller is only interested in changes to its own annotations, and is the main // mechanism in identifying incoming autopilot k0s signaling updates. -func registerSignalController(logger *logrus.Entry, mgr crman.Manager, eventFilter crpred.Predicate, delegate apdel.ControllerDelegate, clusterID string) error { +func registerSignalController(logger *logrus.Entry, mgr crman.Manager, eventFilter crpred.Predicate, delegate apdel.ControllerDelegate, clusterID string, k0sVersionHandler k0sVersionHandlerFunc) error { logr := logger.WithFields(logrus.Fields{"updatetype": "k0s"}) logr.Infof("Registering 'signal' reconciler for '%s'", delegate.Name()) @@ -86,11 +94,9 @@ func registerSignalController(logger *logrus.Entry, mgr crman.Manager, eventFilt mgr.GetClient(), delegate, &signalControllerHandler{ - timeout: SignalResponseProcessingTimeout, - clusterID: clusterID, - k0sVersionHandler: func() (string, error) { - return getK0sVersion(DefaultK0sStatusSocketPath) - }, + timeout: SignalResponseProcessingTimeout, + clusterID: clusterID, + k0sVersionHandler: k0sVersionHandler, }, ), ) diff --git a/pkg/autopilot/controller/signal/k0s/signal_test.go b/pkg/autopilot/controller/signal/k0s/signal_test.go index 88aaaeb59a8f..2a4726c0ac29 100644 --- a/pkg/autopilot/controller/signal/k0s/signal_test.go +++ b/pkg/autopilot/controller/signal/k0s/signal_test.go @@ -1,3 +1,5 @@ +//go:build unix + // Copyright 2021 k0s authors // // Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/pkg/autopilot/controller/signal/k0s/uncordon.go b/pkg/autopilot/controller/signal/k0s/uncordon.go index 0f03fa9316f4..ee8a3290d966 100644 --- a/pkg/autopilot/controller/signal/k0s/uncordon.go +++ b/pkg/autopilot/controller/signal/k0s/uncordon.go @@ -38,6 +38,8 @@ import ( crpred "sigs.k8s.io/controller-runtime/pkg/predicate" ) +const UnCordoning = "UnCordoning" + // unCordoningEventFilter creates a controller-runtime predicate that governs which objects // will make it into reconciliation, and which will be ignored. func unCordoningEventFilter(hostname string, handler apsigpred.ErrorHandler) crpred.Predicate { diff --git a/pkg/autopilot/controller/updates/periodicupdater.go b/pkg/autopilot/controller/updates/periodicupdater.go index fae29196b6ac..0332c0b2afe9 100644 --- a/pkg/autopilot/controller/updates/periodicupdater.go +++ b/pkg/autopilot/controller/updates/periodicupdater.go @@ -1,3 +1,5 @@ +//go:build unix + // Copyright 2023 k0s authors // // Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/pkg/autopilot/controller/updates/update_controller.go b/pkg/autopilot/controller/updates/update_controller.go index ab574a9efd92..4ccfa70ab8cc 100644 --- a/pkg/autopilot/controller/updates/update_controller.go +++ b/pkg/autopilot/controller/updates/update_controller.go @@ -1,3 +1,5 @@ +//go:build unix + // Copyright 2021 k0s authors // // Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/pkg/autopilot/controller/updates/updater.go b/pkg/autopilot/controller/updates/updater.go index 89fadaa3c725..6ad3ccadc86c 100644 --- a/pkg/autopilot/controller/updates/updater.go +++ b/pkg/autopilot/controller/updates/updater.go @@ -1,3 +1,5 @@ +//go:build unix + // Copyright 2021 k0s authors // // Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/pkg/cleanup/cleanup.go b/pkg/cleanup/cleanup.go index a2d97571ac97..756a1819d417 100644 --- a/pkg/cleanup/cleanup.go +++ b/pkg/cleanup/cleanup.go @@ -1,3 +1,5 @@ +//go:build linux + /* Copyright 2021 k0s authors diff --git a/pkg/cleanup/cni.go b/pkg/cleanup/cni_linux.go similarity index 100% rename from pkg/cleanup/cni.go rename to pkg/cleanup/cni_linux.go diff --git a/pkg/cleanup/users.go b/pkg/cleanup/users_linux.go similarity index 100% rename from pkg/cleanup/users.go rename to pkg/cleanup/users_linux.go diff --git a/pkg/component/controller/autopilot.go b/pkg/component/controller/autopilot.go index 04c95249af12..4794393a0865 100644 --- a/pkg/component/controller/autopilot.go +++ b/pkg/component/controller/autopilot.go @@ -1,3 +1,5 @@ +//go:build unix + /* Copyright 2022 k0s authors diff --git a/pkg/component/status/client.go b/pkg/component/status/client.go index f2278a170e92..9c37736d41e0 100644 --- a/pkg/component/status/client.go +++ b/pkg/component/status/client.go @@ -1,3 +1,5 @@ +//go:build unix + /* Copyright 2022 k0s authors @@ -43,7 +45,6 @@ type K0sStatus struct { ClusterConfig *v1beta1.ClusterConfig K0sVars *config.CfgVars } - type ProbeStatus struct { Message string Success bool diff --git a/pkg/component/status/status.go b/pkg/component/status/status.go index 888f42ce4326..1ac61fab7b03 100644 --- a/pkg/component/status/status.go +++ b/pkg/component/status/status.go @@ -1,3 +1,5 @@ +//go:build unix + /* Copyright 2021 k0s authors @@ -41,6 +43,7 @@ import ( type Stater interface { State(maxCount int) prober.State } + type Status struct { StatusInformation K0sStatus Prober Stater diff --git a/pkg/component/worker/autopilot.go b/pkg/component/worker/autopilot.go index d6bcc772c86e..44a7a2ac22b0 100644 --- a/pkg/component/worker/autopilot.go +++ b/pkg/component/worker/autopilot.go @@ -1,3 +1,5 @@ +//go:build unix + /* Copyright 2022 k0s authors diff --git a/pkg/install/service.go b/pkg/install/service.go index dd3c75238dcc..531b11031c23 100644 --- a/pkg/install/service.go +++ b/pkg/install/service.go @@ -66,7 +66,6 @@ func InstalledService() (service.Service, error) { // InstallService installs the k0s service, per the given arguments, and the detected platform func InstallService(args []string, envVars []string, force bool) error { - var deps []string var svcConfig *service.Config prg := &Program{} @@ -82,36 +81,12 @@ func InstallService(args []string, envVars []string, force bool) error { return err } - // fetch service type - svcType := s.Platform() - switch svcType { - case "linux-openrc": - deps = []string{"need cgroups", "need net", "use dns", "after firewall"} - svcConfig.Option = map[string]interface{}{ - "OpenRCScript": openRCScript, - } - case "linux-upstart": - svcConfig.Option = map[string]interface{}{ - "UpstartScript": upstartScript, - } - case "unix-systemv": - svcConfig.Option = map[string]interface{}{ - "SysVScript": sysvScript, - } - case "linux-systemd": - deps = []string{"After=network-online.target", "Wants=network-online.target"} - svcConfig.Option = map[string]interface{}{ - "SystemdScript": systemdScript, - "LimitNOFILE": 999999, - } - default: - } + configureServicePlatform(s, svcConfig) if len(envVars) > 0 { svcConfig.Option["Environment"] = envVars } - svcConfig.Dependencies = deps svcConfig.Arguments = args if force { diff --git a/pkg/install/service_linux.go b/pkg/install/service_linux.go new file mode 100644 index 000000000000..641ab957c011 --- /dev/null +++ b/pkg/install/service_linux.go @@ -0,0 +1,43 @@ +/* +Copyright 2025 k0s authors + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package install + +import "github.com/kardianos/service" + +func configureServicePlatform(s service.Service, svcConfig *service.Config) { + switch s.Platform() { + case "linux-openrc": + svcConfig.Dependencies = []string{"need cgroups", "need net", "use dns", "after firewall"} + svcConfig.Option = map[string]interface{}{ + "OpenRCScript": openRCScript, + } + case "linux-upstart": + svcConfig.Option = map[string]interface{}{ + "UpstartScript": upstartScript, + } + case "unix-systemv": + svcConfig.Option = map[string]interface{}{ + "SysVScript": sysvScript, + } + case "linux-systemd": + svcConfig.Dependencies = []string{"After=network-online.target", "Wants=network-online.target"} + svcConfig.Option = map[string]interface{}{ + "SystemdScript": systemdScript, + "LimitNOFILE": 999999, + } + } +} diff --git a/pkg/install/service_other.go b/pkg/install/service_other.go new file mode 100644 index 000000000000..0c3c6b7f0acc --- /dev/null +++ b/pkg/install/service_other.go @@ -0,0 +1,25 @@ +//go:build !linux + +/* +Copyright 2025 k0s authors + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package install + +import "github.com/kardianos/service" + +func configureServicePlatform(s service.Service, svcConfig *service.Config) { + // no-op +} diff --git a/pkg/install/users.go b/pkg/install/users_linux.go similarity index 97% rename from pkg/install/users.go rename to pkg/install/users_linux.go index 9a85ec83aeaf..ebe83d7689d6 100644 --- a/pkg/install/users.go +++ b/pkg/install/users_linux.go @@ -65,6 +65,8 @@ func DeleteControllerUsers(systemUsers *v1beta1.SystemUser) error { if err := deleteUser(userName); err != nil { errs = append(errs, err) } + } else if !errors.Is(err, users.ErrNotExist) { + errs = append(errs, err) } }