Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
36 commits
Select commit Hold shift + click to select a range
7cd75c1
feat: add create k0s setup from config.yaml
OliverTrautvetter Dec 10, 2025
cdd6ee8
Merge branch 'main' into deploy_k0s_install-config
OliverTrautvetter Dec 10, 2025
5a907ab
chore(docs): Auto-update docs and licenses
OliverTrautvetter Dec 10, 2025
3035990
ref: use deferred functions for cleanup in k0s and node installers
OliverTrautvetter Dec 10, 2025
8892ce0
Merge branch 'deploy_k0s_install-config' of https://github.com/codesp…
OliverTrautvetter Dec 10, 2025
ad86e8e
chore(docs): Auto-update docs and licenses
OliverTrautvetter Dec 10, 2025
c79fc3d
ref: refactor install-config integration tests for improved clarity a…
OliverTrautvetter Dec 15, 2025
071eea9
ref: cleanup
OliverTrautvetter Dec 16, 2025
9de5965
chore(docs): Auto-update docs and licenses
OliverTrautvetter Dec 16, 2025
01d6750
Update internal/installer/node/node.go
OliverTrautvetter Dec 16, 2025
b19ac3b
ref: enhance shell command safety
OliverTrautvetter Dec 16, 2025
41e61da
Merge branch 'deploy_k0s_install-config' of https://github.com/codesp…
OliverTrautvetter Dec 16, 2025
d4d1b5f
test: add tests for NodeManager and Node methods
OliverTrautvetter Dec 16, 2025
97bb3b8
fix: improve passphrase handling in getAuthMethods
OliverTrautvetter Dec 16, 2025
b07c0a8
fix: enforce required flags for remote installation and clean up test…
OliverTrautvetter Dec 16, 2025
8f56476
fix: update EnsureDirectoryExists to accept jumpbox IP
OliverTrautvetter Dec 16, 2025
f674352
test: add tests for InstallK0sCmd
OliverTrautvetter Dec 16, 2025
4e61092
fix: correct sed command syntax for enabling root login
OliverTrautvetter Dec 16, 2025
7a407f0
test: add mock expectations for SSH key file reading in InstallK0sCmd…
OliverTrautvetter Dec 16, 2025
52e8667
test: add tests for K0s configuration filtering
OliverTrautvetter Dec 16, 2025
ef0f96c
test: add tests for Reset functionality in K0s
OliverTrautvetter Dec 16, 2025
4b49bd6
test: add tests for SSH key file handling in InstallK0sRemote method
OliverTrautvetter Dec 16, 2025
e3a9e18
fix: fix k0s installation path and config handling
OliverTrautvetter Dec 17, 2025
e2192fe
fix: k0s config handling to support temporary paths in tests
OliverTrautvetter Dec 17, 2025
bb39c0e
feat: enhance remote k0s installation with user support and SSH instr…
OliverTrautvetter Dec 17, 2025
fdcb214
ref: minor
OliverTrautvetter Dec 17, 2025
2f6fa29
fix: error message for missing install-config in RunE method
OliverTrautvetter Dec 18, 2025
2ad0251
fix: appease make lint
OliverTrautvetter Dec 18, 2025
54ae71c
Update internal/installer/node/node.go
OliverTrautvetter Dec 18, 2025
a5faa2c
fix: improve regex for enabling root login in SSH configuration
OliverTrautvetter Dec 18, 2025
d120484
Update internal/installer/node/node.go
OliverTrautvetter Dec 18, 2025
8e92d3a
fix: update SSH installation notes and remove insecure host key warning
OliverTrautvetter Dec 18, 2025
bb05e55
Merge branch 'deploy_k0s_install-config' of https://github.com/codesp…
OliverTrautvetter Dec 18, 2025
6e80a78
refactor: standardize receiver names in NodeManager methods for consi…
OliverTrautvetter Dec 18, 2025
921e47c
fix: enhance k0s reset process by stopping service before reset and u…
OliverTrautvetter Dec 19, 2025
dfc9deb
ref: extract k0s ClusterConfig keys into constants for improved maint…
OliverTrautvetter Dec 19, 2025
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,9 @@ all: build-cli build-service
build-cli:
cd cli && go build -v && mv cli ../oms-cli

build-cli-linux:
GOOS=linux GOARCH=amd64 go build -C cli -o ../oms-cli

build-service:
cd service && go build -v && mv service ../oms-service

Expand Down
40 changes: 32 additions & 8 deletions NOTICE
Original file line number Diff line number Diff line change
Expand Up @@ -23,9 +23,9 @@ License URL: https://github.com/clipperhouse/uax29/blob/v2.3.0/LICENSE

----------
Module: github.com/codesphere-cloud/cs-go/pkg/io
Version: v0.14.1
Version: v0.15.0
License: Apache-2.0
License URL: https://github.com/codesphere-cloud/cs-go/blob/v0.14.1/LICENSE
License URL: https://github.com/codesphere-cloud/cs-go/blob/v0.15.0/LICENSE

----------
Module: github.com/codesphere-cloud/oms/internal/tmpl
Expand Down Expand Up @@ -77,16 +77,28 @@ License URL: https://github.com/inconshreveable/go-update/blob/8152e7eb6ccf/inte

----------
Module: github.com/jedib0t/go-pretty/v6
Version: v6.7.5
Version: v6.7.7
License: MIT
License URL: https://github.com/jedib0t/go-pretty/blob/v6.7.5/LICENSE
License URL: https://github.com/jedib0t/go-pretty/blob/v6.7.7/LICENSE

----------
Module: github.com/kr/fs
Version: v0.1.0
License: BSD-3-Clause
License URL: https://github.com/kr/fs/blob/v0.1.0/LICENSE

----------
Module: github.com/mattn/go-runewidth
Version: v0.0.19
License: MIT
License URL: https://github.com/mattn/go-runewidth/blob/v0.0.19/LICENSE

----------
Module: github.com/pkg/sftp
Version: v1.13.10
License: BSD-2-Clause
License URL: https://github.com/pkg/sftp/blob/v1.13.10/LICENSE

----------
Module: github.com/pmezard/go-difflib/difflib
Version: v1.0.1-0.20181226105442-5d4384ee4fb2
Expand Down Expand Up @@ -155,21 +167,33 @@ License URL: https://github.com/yaml/go-yaml/blob/v3.0.4/LICENSE

----------
Module: golang.org/x/crypto
Version: v0.45.0
Version: v0.46.0
License: BSD-3-Clause
License URL: https://cs.opensource.google/go/x/crypto/+/v0.45.0:LICENSE
License URL: https://cs.opensource.google/go/x/crypto/+/v0.46.0:LICENSE

----------
Module: golang.org/x/oauth2
Version: v0.33.0
License: BSD-3-Clause
License URL: https://cs.opensource.google/go/x/oauth2/+/v0.33.0:LICENSE

----------
Module: golang.org/x/sys/unix
Version: v0.39.0
License: BSD-3-Clause
License URL: https://cs.opensource.google/go/x/sys/+/v0.39.0:LICENSE

----------
Module: golang.org/x/term
Version: v0.38.0
License: BSD-3-Clause
License URL: https://cs.opensource.google/go/x/term/+/v0.38.0:LICENSE

----------
Module: golang.org/x/text
Version: v0.31.0
Version: v0.32.0
License: BSD-3-Clause
License URL: https://cs.opensource.google/go/x/text/+/v0.31.0:LICENSE
License URL: https://cs.opensource.google/go/x/text/+/v0.32.0:LICENSE

----------
Module: gopkg.in/yaml.v3
Expand Down
115 changes: 97 additions & 18 deletions cli/cmd/install_k0s.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,12 +5,17 @@ package cmd

import (
"fmt"
"log"
"os"
"path/filepath"

packageio "github.com/codesphere-cloud/cs-go/pkg/io"
"github.com/spf13/cobra"

"github.com/codesphere-cloud/oms/internal/env"
"github.com/codesphere-cloud/oms/internal/installer"
"github.com/codesphere-cloud/oms/internal/installer/files"
"github.com/codesphere-cloud/oms/internal/installer/node"
"github.com/codesphere-cloud/oms/internal/portal"
"github.com/codesphere-cloud/oms/internal/util"
)
Expand All @@ -25,10 +30,13 @@ type InstallK0sCmd struct {

type InstallK0sOpts struct {
*GlobalOptions
Version string
Package string
Config string
Force bool
Version string
Package string
InstallConfig string
SSHKeyPath string
RemoteHost string
RemoteUser string
Force bool
}

func (c *InstallK0sCmd) RunE(_ *cobra.Command, args []string) error {
Expand All @@ -37,12 +45,7 @@ func (c *InstallK0sCmd) RunE(_ *cobra.Command, args []string) error {
pm := installer.NewPackage(env.GetOmsWorkdir(), c.Opts.Package)
k0s := installer.NewK0s(hw, env, c.FileWriter)

err := c.InstallK0s(pm, k0s)
if err != nil {
return fmt.Errorf("failed to install k0s: %w", err)
}

return nil
return c.InstallK0s(pm, k0s)
}

func AddInstallK0sCmd(install *cobra.Command, opts *GlobalOptions) {
Expand All @@ -54,12 +57,16 @@ func AddInstallK0sCmd(install *cobra.Command, opts *GlobalOptions) {
This will either download the k0s binary directly to the OMS workdir, if not already present, and install it
or load the k0s binary from the provided package file and install it.
If no version is specified, the latest version will be downloaded.
If no install config is provided, k0s will be installed with the '--single' flag.`),

You must provide a Codesphere install-config file, which will:
- Generate a k0s configuration from the install-config
- Optionally install k0s on remote nodes via SSH`),
Example: formatExamplesWithBinary("install k0s", []packageio.Example{
{Cmd: "", Desc: "Install k0s using the Go-native implementation"},
{Cmd: "--install-config <path>", Desc: "Path to Codesphere install-config file to generate k0s config from"},
{Cmd: "--version <version>", Desc: "Version of k0s to install"},
{Cmd: "--package <file>", Desc: "Package file (e.g. codesphere-v1.2.3-installer.tar.gz) to load k0s from"},
{Cmd: "--k0s-config <path>", Desc: "Path to k0s configuration file, if not set k0s will be installed with the '--single' flag"},
{Cmd: "--remote-host <ip>", Desc: "Remote host IP to install k0s on (requires --ssh-key-path)"},
{Cmd: "--ssh-key-path <path>", Desc: "SSH private key path for remote installation"},
{Cmd: "--force", Desc: "Force new download and installation even if k0s binary exists or is already installed"},
}, "oms-cli"),
},
Expand All @@ -69,9 +76,15 @@ func AddInstallK0sCmd(install *cobra.Command, opts *GlobalOptions) {
}
k0s.cmd.Flags().StringVarP(&k0s.Opts.Version, "version", "v", "", "Version of k0s to install")
k0s.cmd.Flags().StringVarP(&k0s.Opts.Package, "package", "p", "", "Package file (e.g. codesphere-v1.2.3-installer.tar.gz) to load k0s from")
k0s.cmd.Flags().StringVar(&k0s.Opts.Config, "k0s-config", "", "Path to k0s configuration file")
k0s.cmd.Flags().StringVar(&k0s.Opts.InstallConfig, "install-config", "", "Path to Codesphere install-config file (required)")
k0s.cmd.Flags().StringVar(&k0s.Opts.SSHKeyPath, "ssh-key-path", "", "SSH private key path for remote installation")
k0s.cmd.Flags().StringVar(&k0s.Opts.RemoteHost, "remote-host", "", "Remote host IP to install k0s on")
k0s.cmd.Flags().StringVar(&k0s.Opts.RemoteUser, "remote-user", "root", "Remote user for SSH connection")
k0s.cmd.Flags().BoolVarP(&k0s.Opts.Force, "force", "f", false, "Force new download and installation")

_ = k0s.cmd.MarkFlagRequired("install-config")
k0s.cmd.MarkFlagsRequiredTogether("remote-host", "ssh-key-path")

install.AddCommand(k0s.cmd)

k0s.cmd.RunE = k0s.RunE
Expand All @@ -80,21 +93,87 @@ func AddInstallK0sCmd(install *cobra.Command, opts *GlobalOptions) {
const defaultK0sPath = "kubernetes/files/k0s"

func (c *InstallK0sCmd) InstallK0s(pm installer.PackageManager, k0s installer.K0sManager) error {
// Default dependency path for k0s binary within package
k0sPath := pm.GetDependencyPath(defaultK0sPath)
icg := installer.NewInstallConfigManager()
if err := icg.LoadInstallConfigFromFile(c.Opts.InstallConfig); err != nil {
return fmt.Errorf("failed to load install-config: %w", err)
}

config := icg.GetInstallConfig()

if !config.Kubernetes.ManagedByCodesphere {
return fmt.Errorf("install-config specifies external Kubernetes, k0s installation is only supported for Codesphere-managed Kubernetes")
}

log.Println("Generating k0s configuration from install-config...")
k0sConfig, err := installer.GenerateK0sConfig(config)
if err != nil {
return fmt.Errorf("failed to generate k0s config: %w", err)
}

k0sConfigData, err := k0sConfig.Marshal()
if err != nil {
return fmt.Errorf("failed to marshal k0s config: %w", err)
}

// allow temp directory in tests
k0sConfigPath := "/etc/k0s/k0s.yaml"

var err error
if err := os.MkdirAll(filepath.Dir(k0sConfigPath), 0755); err != nil {
tmpK0sConfigPath := filepath.Join(os.TempDir(), "k0s-config.yaml")
if err := os.WriteFile(tmpK0sConfigPath, k0sConfigData, 0644); err != nil {
return fmt.Errorf("failed to write k0s config: %w", err)
}
k0sConfigPath = tmpK0sConfigPath
// Clean up temp file on all exit paths
defer func() { _ = os.Remove(k0sConfigPath) }()
log.Printf("Generated k0s configuration at %s (using temp path due to permissions)", k0sConfigPath)
} else {
if err := os.WriteFile(k0sConfigPath, k0sConfigData, 0644); err != nil {
return fmt.Errorf("failed to write k0s config: %w", err)
}
log.Printf("Generated k0s configuration at %s", k0sConfigPath)
}

k0sPath := pm.GetDependencyPath(defaultK0sPath)
if c.Opts.Package == "" {
k0sPath, err = k0s.Download(c.Opts.Version, c.Opts.Force, false)
if err != nil {
return fmt.Errorf("failed to download k0s: %w", err)
}
}

err = k0s.Install(c.Opts.Config, k0sPath, c.Opts.Force)
if c.Opts.RemoteHost != "" {
return c.InstallK0sRemote(config, k0sPath, k0sConfigPath)
}

err = k0s.Install(k0sConfigPath, k0sPath, c.Opts.Force)
if err != nil {
return fmt.Errorf("failed to install k0s: %w", err)
}

log.Println("k0s installed successfully using configuration from install-config")
return nil
}

func (c *InstallK0sCmd) InstallK0sRemote(config *files.RootConfig, k0sBinaryPath string, k0sConfigPath string) error {
log.Printf("Installing k0s on remote host %s", c.Opts.RemoteHost)

nm := &node.NodeManager{
FileIO: c.FileWriter,
KeyPath: c.Opts.SSHKeyPath,
}

remoteNode := &node.Node{
ExternalIP: c.Opts.RemoteHost,
InternalIP: c.Opts.RemoteHost,
Name: "k0s-node",
User: c.Opts.RemoteUser,
}

if err := remoteNode.InstallK0s(nm, k0sBinaryPath, k0sConfigPath, c.Opts.Force); err != nil {
return fmt.Errorf("failed to install k0s on remote host: %w", err)
}

log.Printf("k0s successfully installed on remote host %s", c.Opts.RemoteHost)
return nil
}
Loading