Skip to content
Merged
Show file tree
Hide file tree
Changes from 6 commits
Commits
Show all changes
25 commits
Select commit Hold shift + click to select a range
14bc6e3
feat: add download and install k0s command
siherrmann Nov 4, 2025
5cb3517
update: update logs with oms workdir for k0s start command
siherrmann Nov 5, 2025
b41ce6c
fix: fix lint errors
siherrmann Nov 5, 2025
2e333c6
fix: fix lint errors
siherrmann Nov 5, 2025
66a7ed3
chore(docs): Auto-update docs and licenses
siherrmann Nov 5, 2025
69495fa
Merge branch 'main' into install-k0s
siherrmann Nov 5, 2025
43e5f95
update: update install k0s command to also use package
siherrmann Nov 10, 2025
b670405
feat: add download and install k0s command
siherrmann Nov 4, 2025
2644abf
update: update logs with oms workdir for k0s start command
siherrmann Nov 5, 2025
d31b396
fix: fix lint errors
siherrmann Nov 5, 2025
716a765
fix: fix lint errors
siherrmann Nov 5, 2025
e2197ba
chore(docs): Auto-update docs and licenses
siherrmann Nov 5, 2025
8c6186b
update: update install k0s command to also use package
siherrmann Nov 10, 2025
3c8f6c0
Merge branch 'install-k0s' of https://github.com/codesphere-cloud/oms…
siherrmann Nov 11, 2025
15c182b
chore(docs): Auto-update docs and licenses
siherrmann Nov 11, 2025
c9b6530
fix: fix portal tests
siherrmann Nov 11, 2025
a009027
Merge branch 'install-k0s' of https://github.com/codesphere-cloud/oms…
siherrmann Nov 11, 2025
ad10f12
fix: fix lint error omit type
siherrmann Nov 11, 2025
e08a7c1
fix: remove tests with real network calls
siherrmann Nov 11, 2025
adeac05
Merge branch 'main' into install-k0s
NautiluX Nov 13, 2025
1580667
chore(docs): Auto-update docs and licenses
siherrmann Nov 13, 2025
500ebcf
update: small updates for pr
siherrmann Nov 17, 2025
1894f59
Merge branch 'main' into install-k0s
siherrmann Nov 17, 2025
873ebbc
update: update mocks after merge
siherrmann Nov 17, 2025
b0b1aee
chore(docs): Auto-update docs and licenses
siherrmann Nov 17, 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
1 change: 1 addition & 0 deletions cli/cmd/download.go
Original file line number Diff line number Diff line change
Expand Up @@ -25,4 +25,5 @@ func AddDownloadCmd(rootCmd *cobra.Command, opts *GlobalOptions) {
rootCmd.AddCommand(download.cmd)

AddDownloadPackageCmd(download.cmd, opts)
AddDownloadK0sCmd(download.cmd, opts)
}
69 changes: 69 additions & 0 deletions cli/cmd/download_k0s.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
// Copyright (c) Codesphere Inc.
// SPDX-License-Identifier: Apache-2.0

package cmd

import (
"fmt"

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/portal"
"github.com/codesphere-cloud/oms/internal/util"
)

// DownloadK0sCmd represents the k0s download command
type DownloadK0sCmd struct {
cmd *cobra.Command
Opts DownloadK0sOpts
Env env.Env
FileWriter util.FileIO
}

type DownloadK0sOpts struct {
*GlobalOptions
Force bool
Quiet bool
}

func (c *DownloadK0sCmd) RunE(_ *cobra.Command, args []string) error {
hw := portal.NewHttpWrapper()
env := c.Env
k0s := installer.NewK0s(hw, env, c.FileWriter)

err := k0s.Download(c.Opts.Force, c.Opts.Quiet)
if err != nil {
return fmt.Errorf("failed to download k0s: %w", err)
}

return nil
}

func AddDownloadK0sCmd(download *cobra.Command, opts *GlobalOptions) {
k0s := DownloadK0sCmd{
cmd: &cobra.Command{
Use: "k0s",
Short: "Download k0s Kubernetes distribution",
Long: packageio.Long(`Download k0s, a zero friction Kubernetes distribution,
using a Go-native implementation. This will download the k0s
binary directly to the OMS workdir.`),
Example: formatExamplesWithBinary("download k0s", []packageio.Example{
{Cmd: "", Desc: "Download k0s using the Go-native implementation"},
{Cmd: "--quiet", Desc: "Download k0s with minimal output"},
{Cmd: "--force", Desc: "Force download even if k0s binary exists"},
}, "oms-cli"),
},
Opts: DownloadK0sOpts{GlobalOptions: opts},
Env: env.NewEnv(),
FileWriter: util.NewFilesystemWriter(),
}
k0s.cmd.Flags().BoolVarP(&k0s.Opts.Force, "force", "f", false, "Force download even if k0s binary exists")
k0s.cmd.Flags().BoolVarP(&k0s.Opts.Quiet, "quiet", "q", false, "Suppress progress output during download")

download.AddCommand(k0s.cmd)

k0s.cmd.RunE = k0s.RunE
}
119 changes: 119 additions & 0 deletions cli/cmd/download_k0s_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,119 @@
// Copyright (c) Codesphere Inc.
// SPDX-License-Identifier: Apache-2.0

package cmd_test

import (
"errors"
"runtime"

. "github.com/onsi/ginkgo/v2"
. "github.com/onsi/gomega"
"github.com/spf13/cobra"

"github.com/codesphere-cloud/oms/cli/cmd"
"github.com/codesphere-cloud/oms/internal/env"
"github.com/codesphere-cloud/oms/internal/util"
)

var _ = Describe("DownloadK0sCmd", func() {
var (
downloadK0sCmd *cmd.DownloadK0sCmd
mockEnv *env.MockEnv
mockFileWriter *util.MockFileIO
)

BeforeEach(func() {
mockEnv = env.NewMockEnv(GinkgoT())
mockFileWriter = util.NewMockFileIO(GinkgoT())

downloadK0sCmd = &cmd.DownloadK0sCmd{
Opts: cmd.DownloadK0sOpts{
GlobalOptions: &cmd.GlobalOptions{},
Force: false,
Quiet: false,
},
Env: mockEnv,
FileWriter: mockFileWriter,
}
})

AfterEach(func() {
mockEnv.AssertExpectations(GinkgoT())
mockFileWriter.AssertExpectations(GinkgoT())
})

Context("RunE", func() {
It("should successfully handle k0s download integration", func() {
// Add mock expectations for the download functionality, intentionally causing create to fail
mockEnv.EXPECT().GetOmsWorkdir().Return("/test/workdir").Maybe()
mockFileWriter.EXPECT().Exists("/test/workdir/k0s").Return(false).Maybe()
mockFileWriter.EXPECT().Create("/test/workdir/k0s").Return(nil, errors.New("mock create error")).Maybe()

err := downloadK0sCmd.RunE(nil, nil)

Expect(err).To(HaveOccurred())
Expect(err.Error()).To(ContainSubstring("failed to download k0s"))
if runtime.GOOS != "linux" || runtime.GOARCH != "amd64" {
// Should fail with platform error on non-Linux amd64 platforms
Expect(err.Error()).To(ContainSubstring("codesphere installation is only supported on Linux amd64"))
} else {
// On Linux amd64, it should fail on network/version fetch since we don't have real network access
Expect(err.Error()).To(ContainSubstring("mock create error"))
}
})
})
})

var _ = Describe("AddDownloadK0sCmd", func() {
var (
parentCmd *cobra.Command
globalOpts *cmd.GlobalOptions
)

BeforeEach(func() {
parentCmd = &cobra.Command{Use: "download"}
globalOpts = &cmd.GlobalOptions{}
})

It("adds the k0s command with correct properties and flags", func() {
cmd.AddDownloadK0sCmd(parentCmd, globalOpts)

var k0sCmd *cobra.Command
for _, c := range parentCmd.Commands() {
if c.Use == "k0s" {
k0sCmd = c
break
}
}

Expect(k0sCmd).NotTo(BeNil())
Expect(k0sCmd.Use).To(Equal("k0s"))
Expect(k0sCmd.Short).To(Equal("Download k0s Kubernetes distribution"))
Expect(k0sCmd.Long).To(ContainSubstring("Download k0s, a zero friction Kubernetes distribution"))
Expect(k0sCmd.Long).To(ContainSubstring("using a Go-native implementation"))
Expect(k0sCmd.RunE).NotTo(BeNil())

Expect(k0sCmd.Parent()).To(Equal(parentCmd))
Expect(parentCmd.Commands()).To(ContainElement(k0sCmd))

// Check flags
forceFlag := k0sCmd.Flags().Lookup("force")
Expect(forceFlag).NotTo(BeNil())
Expect(forceFlag.Shorthand).To(Equal("f"))
Expect(forceFlag.DefValue).To(Equal("false"))
Expect(forceFlag.Usage).To(Equal("Force download even if k0s binary exists"))

quietFlag := k0sCmd.Flags().Lookup("quiet")
Expect(quietFlag).NotTo(BeNil())
Expect(quietFlag.Shorthand).To(Equal("q"))
Expect(quietFlag.DefValue).To(Equal("false"))
Expect(quietFlag.Usage).To(Equal("Suppress progress output during download"))

// Check examples
Expect(k0sCmd.Example).NotTo(BeEmpty())
Expect(k0sCmd.Example).To(ContainSubstring("oms-cli download k0s"))
Expect(k0sCmd.Example).To(ContainSubstring("--quiet"))
Expect(k0sCmd.Example).To(ContainSubstring("--force"))
})
})
2 changes: 2 additions & 0 deletions cli/cmd/install.go
Original file line number Diff line number Diff line change
Expand Up @@ -22,5 +22,7 @@ func AddInstallCmd(rootCmd *cobra.Command, opts *GlobalOptions) {
},
}
rootCmd.AddCommand(install.cmd)

AddInstallCodesphereCmd(install.cmd, opts)
AddInstallK0sCmd(install.cmd, opts)
}
76 changes: 76 additions & 0 deletions cli/cmd/install_k0s.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,76 @@
// Copyright (c) Codesphere Inc.
// SPDX-License-Identifier: Apache-2.0

package cmd

import (
"fmt"

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/portal"
"github.com/codesphere-cloud/oms/internal/util"
)

// InstallK0sCmd represents the k0s download command
type InstallK0sCmd struct {
cmd *cobra.Command
Opts InstallK0sOpts
Env env.Env
FileWriter util.FileIO
}

type InstallK0sOpts struct {
*GlobalOptions
Config string
Force bool
}

func (c *InstallK0sCmd) RunE(_ *cobra.Command, args []string) error {
hw := portal.NewHttpWrapper()
env := c.Env
k0s := installer.NewK0s(hw, env, c.FileWriter)

if !k0s.BinaryExists() || c.Opts.Force {
err := k0s.Download(c.Opts.Force, false)
if err != nil {
return fmt.Errorf("failed to download k0s: %w", err)
}
}

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

return nil
}

func AddInstallK0sCmd(install *cobra.Command, opts *GlobalOptions) {
k0s := InstallK0sCmd{
cmd: &cobra.Command{
Use: "k0s",
Short: "Install k0s Kubernetes distribution",
Long: packageio.Long(`Install k0s, a zero friction Kubernetes distribution,
using a Go-native implementation. This will download the k0s
binary directly to the OMS workdir, if not already present, and install it.`),
Example: formatExamplesWithBinary("install k0s", []packageio.Example{
{Cmd: "", Desc: "Install k0s using the Go-native implementation"},
{Cmd: "--config <path>", Desc: "Path to k0s configuration file, if not set k0s will be installed with the '--single' flag"},
{Cmd: "--force", Desc: "Force new download and installation even if k0s binary exists or is already installed"},
}, "oms-cli"),
},
Opts: InstallK0sOpts{GlobalOptions: opts},
Env: env.NewEnv(),
FileWriter: util.NewFilesystemWriter(),
}
k0s.cmd.Flags().StringVarP(&k0s.Opts.Config, "config", "c", "", "Path to k0s configuration file")
k0s.cmd.Flags().BoolVarP(&k0s.Opts.Force, "force", "f", false, "Force new download and installation")

install.AddCommand(k0s.cmd)

k0s.cmd.RunE = k0s.RunE
}
Loading