From 5f8a763c33c4d4ff1da89e5f3c272824c9c7dc0c Mon Sep 17 00:00:00 2001 From: Etienne Audet-Cobello Date: Thu, 7 Nov 2024 19:03:48 -0500 Subject: [PATCH 1/9] feat: check if microk8s is installed on bootstrap --- src/k8s/pkg/client/snapd/snap_info.go | 31 +++++++++++++++++++++++++ src/k8s/pkg/k8sd/app/hooks_bootstrap.go | 14 +++++++++++ 2 files changed, 45 insertions(+) create mode 100644 src/k8s/pkg/client/snapd/snap_info.go diff --git a/src/k8s/pkg/client/snapd/snap_info.go b/src/k8s/pkg/client/snapd/snap_info.go new file mode 100644 index 000000000..4c843d101 --- /dev/null +++ b/src/k8s/pkg/client/snapd/snap_info.go @@ -0,0 +1,31 @@ +package snapd + +import ( + "encoding/json" + "fmt" + "io" +) + +type snapdSnapInfoResponse struct { + StatusCode int `json:"status-code"` +} + +func (c *Client) GetSnapInfo(snap string) (*snapdSnapInfoResponse, error) { + resp, err := c.client.Get(fmt.Sprintf("http://localhost/v2/snaps/%s", snap)) + if err != nil { + return nil, fmt.Errorf("failed to get snapd snap info: %w", err) + } + defer resp.Body.Close() + + resBody, err := io.ReadAll(resp.Body) + if err != nil { + return nil, fmt.Errorf("client: could not read response body: %w", err) + } + + var snapInfoResponse snapdSnapInfoResponse + if err := json.Unmarshal(resBody, &snapInfoResponse); err != nil { + return nil, fmt.Errorf("client: could not unmarshal response body: %w", err) + } + + return &snapInfoResponse, nil +} diff --git a/src/k8s/pkg/k8sd/app/hooks_bootstrap.go b/src/k8s/pkg/k8sd/app/hooks_bootstrap.go index 9e1b05798..067089fbe 100644 --- a/src/k8s/pkg/k8sd/app/hooks_bootstrap.go +++ b/src/k8s/pkg/k8sd/app/hooks_bootstrap.go @@ -15,6 +15,7 @@ import ( "time" apiv1 "github.com/canonical/k8s-snap-api/api/v1" + "github.com/canonical/k8s/pkg/client/snapd" "github.com/canonical/k8s/pkg/k8sd/database" "github.com/canonical/k8s/pkg/k8sd/pki" "github.com/canonical/k8s/pkg/k8sd/setup" @@ -38,6 +39,19 @@ func (a *App) onBootstrap(ctx context.Context, s state.State, initConfig map[str defer cancel() } + snapdClient, err := snapd.NewClient() + if err != nil { + return fmt.Errorf("failed to create snapd client: %w", err) + } + + microk8sInfo, err := snapdClient.GetSnapInfo("microk8s") + if err != nil { + return fmt.Errorf("failed to check if microk8s is installed: %w", err) + } + if microk8sInfo.StatusCode == 200 { + return fmt.Errorf("microk8s snap is installed, please remove it and try again") + } + if workerToken, ok := initConfig["workerToken"]; ok { workerConfig, err := utils.MicroclusterWorkerJoinConfigFromMap(initConfig) if err != nil { From c5ea1aded00ec21cd5a92d4660047145ee3e60c8 Mon Sep 17 00:00:00 2001 From: Etienne Audet-Cobello Date: Fri, 8 Nov 2024 14:12:00 -0500 Subject: [PATCH 2/9] feat: check microk8s and port 6400 --- src/k8s/cmd/k8s/k8s_bootstrap.go | 29 +++++++++++++++++++++++++++++ 1 file changed, 29 insertions(+) diff --git a/src/k8s/cmd/k8s/k8s_bootstrap.go b/src/k8s/cmd/k8s/k8s_bootstrap.go index 5510ed34e..69c19fd7c 100644 --- a/src/k8s/cmd/k8s/k8s_bootstrap.go +++ b/src/k8s/cmd/k8s/k8s_bootstrap.go @@ -5,6 +5,7 @@ import ( "bytes" "fmt" "io" + "net" "os" "slices" "strings" @@ -13,6 +14,7 @@ import ( apiv1 "github.com/canonical/k8s-snap-api/api/v1" cmdutil "github.com/canonical/k8s/cmd/util" + "github.com/canonical/k8s/pkg/client/snapd" "github.com/canonical/k8s/pkg/config" "github.com/canonical/k8s/pkg/k8sd/features" "github.com/canonical/k8s/pkg/utils" @@ -47,6 +49,24 @@ func newBootstrapCmd(env cmdutil.ExecutionEnvironment) *cobra.Command { Long: "Generate certificates, configure service arguments and start the Kubernetes services.", PreRun: chainPreRunHooks(hookRequireRoot(env), hookInitializeFormatter(env, &opts.outputFormat), hookCheckLXD()), Run: func(cmd *cobra.Command, args []string) { + snapdClient, err := snapd.NewClient() + if err != nil { + cmd.PrintErrln("Error: failed to create snapd client: %w", err) + env.Exit(1) + return + } + microk8sInfo, err := snapdClient.GetSnapInfo("microk8s") + if err != nil { + cmd.PrintErrln("Error: failed to check if microk8s is installed: %w", err) + env.Exit(1) + return + } + if microk8sInfo.StatusCode == 200 { + cmd.PrintErrln("Error: microk8s snap is installed, please remove it and try again.") + env.Exit(1) + return + } + if opts.interactive && opts.configFile != "" { cmd.PrintErrln("Error: --interactive and --file flags cannot be set at the same time.") env.Exit(1) @@ -79,6 +99,15 @@ func newBootstrapCmd(env cmdutil.ExecutionEnvironment) *cobra.Command { return } + a := fmt.Sprintf("%s:%d", opts.address, config.DefaultPort) + ln, err := net.Listen("tcp", a) + if err != nil { + cmd.PrintErrf("Error: Failed to bind to required port %d. Please make sure the port is not in use.\n", config.DefaultPort) + env.Exit(1) + return + } + _ = ln.Close() + client, err := env.Snap.K8sdClient("") if err != nil { cmd.PrintErrf("Error: Failed to create a k8sd client. Make sure that the k8sd service is running.\n\nThe error was: %v\n", err) From 2fd242444df16c3e981759ae939e876a57dc2372 Mon Sep 17 00:00:00 2001 From: Etienne Audet-Cobello Date: Fri, 8 Nov 2024 17:22:17 -0500 Subject: [PATCH 3/9] revert hook changes --- src/k8s/pkg/k8sd/app/hooks_bootstrap.go | 14 -------------- 1 file changed, 14 deletions(-) diff --git a/src/k8s/pkg/k8sd/app/hooks_bootstrap.go b/src/k8s/pkg/k8sd/app/hooks_bootstrap.go index 067089fbe..9e1b05798 100644 --- a/src/k8s/pkg/k8sd/app/hooks_bootstrap.go +++ b/src/k8s/pkg/k8sd/app/hooks_bootstrap.go @@ -15,7 +15,6 @@ import ( "time" apiv1 "github.com/canonical/k8s-snap-api/api/v1" - "github.com/canonical/k8s/pkg/client/snapd" "github.com/canonical/k8s/pkg/k8sd/database" "github.com/canonical/k8s/pkg/k8sd/pki" "github.com/canonical/k8s/pkg/k8sd/setup" @@ -39,19 +38,6 @@ func (a *App) onBootstrap(ctx context.Context, s state.State, initConfig map[str defer cancel() } - snapdClient, err := snapd.NewClient() - if err != nil { - return fmt.Errorf("failed to create snapd client: %w", err) - } - - microk8sInfo, err := snapdClient.GetSnapInfo("microk8s") - if err != nil { - return fmt.Errorf("failed to check if microk8s is installed: %w", err) - } - if microk8sInfo.StatusCode == 200 { - return fmt.Errorf("microk8s snap is installed, please remove it and try again") - } - if workerToken, ok := initConfig["workerToken"]; ok { workerConfig, err := utils.MicroclusterWorkerJoinConfigFromMap(initConfig) if err != nil { From e52598579d9258d059e4d2577e6d0232c9029687 Mon Sep 17 00:00:00 2001 From: Etienne Audet-Cobello Date: Mon, 11 Nov 2024 09:20:53 -0500 Subject: [PATCH 4/9] revert port check --- src/k8s/cmd/k8s/k8s_bootstrap.go | 10 ---------- 1 file changed, 10 deletions(-) diff --git a/src/k8s/cmd/k8s/k8s_bootstrap.go b/src/k8s/cmd/k8s/k8s_bootstrap.go index 69c19fd7c..c43450723 100644 --- a/src/k8s/cmd/k8s/k8s_bootstrap.go +++ b/src/k8s/cmd/k8s/k8s_bootstrap.go @@ -5,7 +5,6 @@ import ( "bytes" "fmt" "io" - "net" "os" "slices" "strings" @@ -99,15 +98,6 @@ func newBootstrapCmd(env cmdutil.ExecutionEnvironment) *cobra.Command { return } - a := fmt.Sprintf("%s:%d", opts.address, config.DefaultPort) - ln, err := net.Listen("tcp", a) - if err != nil { - cmd.PrintErrf("Error: Failed to bind to required port %d. Please make sure the port is not in use.\n", config.DefaultPort) - env.Exit(1) - return - } - _ = ln.Close() - client, err := env.Snap.K8sdClient("") if err != nil { cmd.PrintErrf("Error: Failed to create a k8sd client. Make sure that the k8sd service is running.\n\nThe error was: %v\n", err) From 08064e9b249e18595038d9042ae7e7a6b51ac4f3 Mon Sep 17 00:00:00 2001 From: Etienne Audet-Cobello Date: Mon, 11 Nov 2024 11:29:00 -0500 Subject: [PATCH 5/9] add integration test --- tests/integration/tests/test_util/test_bootstrap.py | 12 ++++++++++++ 1 file changed, 12 insertions(+) create mode 100644 tests/integration/tests/test_util/test_bootstrap.py diff --git a/tests/integration/tests/test_util/test_bootstrap.py b/tests/integration/tests/test_util/test_bootstrap.py new file mode 100644 index 000000000..bbdfc6f65 --- /dev/null +++ b/tests/integration/tests/test_util/test_bootstrap.py @@ -0,0 +1,12 @@ +from typing import List + +import pytest +from test_util import harness + +@pytest.mark.node_count(1) +@pytest.mark.disable_k8s_bootstrapping() +def test_microk8s_installed(instances: List[harness.Instance]): + instance = instances[0] + instance.exec("snap install microk8s --classic".split()) + result = instance.exec("k8s bootstrap".split(), capture_output=True, check=False) + assert "Error: microk8s snap is installed" in result.stderr.decode() From 6803416cd3d3a2409ec693745b69a4cda64dba8f Mon Sep 17 00:00:00 2001 From: Etienne Audet-Cobello Date: Mon, 11 Nov 2024 11:33:39 -0500 Subject: [PATCH 6/9] tox -e format --- tests/integration/tests/test_util/test_bootstrap.py | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/tests/integration/tests/test_util/test_bootstrap.py b/tests/integration/tests/test_util/test_bootstrap.py index bbdfc6f65..1bcc688dd 100644 --- a/tests/integration/tests/test_util/test_bootstrap.py +++ b/tests/integration/tests/test_util/test_bootstrap.py @@ -1,8 +1,12 @@ +# +# Copyright 2024 Canonical, Ltd. +# from typing import List import pytest from test_util import harness + @pytest.mark.node_count(1) @pytest.mark.disable_k8s_bootstrapping() def test_microk8s_installed(instances: List[harness.Instance]): From e19af9f61e4165a63dddcc90b31d5d4d1630cdc7 Mon Sep 17 00:00:00 2001 From: Etienne Audet-Cobello Date: Thu, 14 Nov 2024 09:17:15 -0500 Subject: [PATCH 7/9] revert --- src/k8s/go.mod | 2 +- src/k8s/go.sum | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/k8s/go.mod b/src/k8s/go.mod index 48562f653..68d3f1cde 100644 --- a/src/k8s/go.mod +++ b/src/k8s/go.mod @@ -5,7 +5,7 @@ go 1.22.6 require ( dario.cat/mergo v1.0.0 github.com/canonical/go-dqlite v1.22.0 - github.com/canonical/k8s-snap-api v1.0.12 + github.com/canonical/k8s-snap-api v1.0.13 github.com/canonical/lxd v0.0.0-20240822122218-e7b2a7a83230 github.com/canonical/microcluster/v3 v3.0.0-20240827143335-f7a4d3984970 github.com/go-logr/logr v1.4.2 diff --git a/src/k8s/go.sum b/src/k8s/go.sum index fb5671c2b..20f296a62 100644 --- a/src/k8s/go.sum +++ b/src/k8s/go.sum @@ -99,8 +99,8 @@ github.com/bugsnag/panicwrap v0.0.0-20151223152923-e2c28503fcd0 h1:nvj0OLI3YqYXe github.com/bugsnag/panicwrap v0.0.0-20151223152923-e2c28503fcd0/go.mod h1:D/8v3kj0zr8ZAKg1AQ6crr+5VwKN5eIywRkfhyM/+dE= github.com/canonical/go-dqlite v1.22.0 h1:DuJmfcREl4gkQJyvZzjl2GHFZROhbPyfdjDRQXpkOyw= github.com/canonical/go-dqlite v1.22.0/go.mod h1:Uvy943N8R4CFUAs59A1NVaziWY9nJ686lScY7ywurfg= -github.com/canonical/k8s-snap-api v1.0.12 h1:ofS2+JRlPMnpWgHLmnE4QEUqWv9Dgrmsv3hrjI0O4zQ= -github.com/canonical/k8s-snap-api v1.0.12/go.mod h1:LDPoIYCeYnfgOFrwVPJ/4edGU264w7BB7g0GsVi36AY= +github.com/canonical/k8s-snap-api v1.0.13 h1:Z+IW6Knvycu+DrkmH+9qB1UNyYiHfL+rFvT9DtSO2+g= +github.com/canonical/k8s-snap-api v1.0.13/go.mod h1:LDPoIYCeYnfgOFrwVPJ/4edGU264w7BB7g0GsVi36AY= github.com/canonical/lxd v0.0.0-20240822122218-e7b2a7a83230 h1:YOqZ+/14OPZ+/TOXpRHIX3KLT0C+wZVpewKIwlGUmW0= github.com/canonical/lxd v0.0.0-20240822122218-e7b2a7a83230/go.mod h1:YVGI7HStOKsV+cMyXWnJ7RaMPaeWtrkxyIPvGWbgACc= github.com/canonical/microcluster/v3 v3.0.0-20240827143335-f7a4d3984970 h1:UrnpglbXELlxtufdk6DGDytu2JzyzuS3WTsOwPrkQLI= From dee060364d6b8cbcf83d01841122f80791af114a Mon Sep 17 00:00:00 2001 From: Etienne Audet-Cobello Date: Thu, 14 Nov 2024 09:56:07 -0500 Subject: [PATCH 8/9] improve error msg, check content of response --- src/k8s/cmd/k8s/k8s_bootstrap.go | 4 ++-- src/k8s/pkg/client/snapd/snap_info.go | 14 ++++++++++---- 2 files changed, 12 insertions(+), 6 deletions(-) diff --git a/src/k8s/cmd/k8s/k8s_bootstrap.go b/src/k8s/cmd/k8s/k8s_bootstrap.go index c43450723..e8b2b3371 100644 --- a/src/k8s/cmd/k8s/k8s_bootstrap.go +++ b/src/k8s/cmd/k8s/k8s_bootstrap.go @@ -60,8 +60,8 @@ func newBootstrapCmd(env cmdutil.ExecutionEnvironment) *cobra.Command { env.Exit(1) return } - if microk8sInfo.StatusCode == 200 { - cmd.PrintErrln("Error: microk8s snap is installed, please remove it and try again.") + if microk8sInfo.StatusCode == 200 && !microk8sInfo.Result.InstallDate.IsZero() { + cmd.PrintErrln("Error: microk8s snap is installed. Please remove it using the following command and try again:\n\n sudo snap remove microk8s") env.Exit(1) return } diff --git a/src/k8s/pkg/client/snapd/snap_info.go b/src/k8s/pkg/client/snapd/snap_info.go index 4c843d101..b78eda0bc 100644 --- a/src/k8s/pkg/client/snapd/snap_info.go +++ b/src/k8s/pkg/client/snapd/snap_info.go @@ -4,13 +4,19 @@ import ( "encoding/json" "fmt" "io" + "time" ) -type snapdSnapInfoResponse struct { - StatusCode int `json:"status-code"` +type SnapInfoResult struct { + InstallDate time.Time `json:"install-date"` } -func (c *Client) GetSnapInfo(snap string) (*snapdSnapInfoResponse, error) { +type SnapInfoResponse struct { + StatusCode int `json:"status-code"` + Result SnapInfoResult `json:"result"` +} + +func (c *Client) GetSnapInfo(snap string) (*SnapInfoResponse, error) { resp, err := c.client.Get(fmt.Sprintf("http://localhost/v2/snaps/%s", snap)) if err != nil { return nil, fmt.Errorf("failed to get snapd snap info: %w", err) @@ -22,7 +28,7 @@ func (c *Client) GetSnapInfo(snap string) (*snapdSnapInfoResponse, error) { return nil, fmt.Errorf("client: could not read response body: %w", err) } - var snapInfoResponse snapdSnapInfoResponse + var snapInfoResponse SnapInfoResponse if err := json.Unmarshal(resBody, &snapInfoResponse); err != nil { return nil, fmt.Errorf("client: could not unmarshal response body: %w", err) } From cf0ddec316a4537fd70beb1a53c9ad2d385be8fc Mon Sep 17 00:00:00 2001 From: Etienne Audet-Cobello Date: Thu, 14 Nov 2024 10:10:05 -0500 Subject: [PATCH 9/9] check install date is set --- src/k8s/cmd/k8s/k8s_bootstrap.go | 2 +- src/k8s/pkg/client/snapd/snap_info.go | 4 ++++ 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/src/k8s/cmd/k8s/k8s_bootstrap.go b/src/k8s/cmd/k8s/k8s_bootstrap.go index e8b2b3371..9ba6525d3 100644 --- a/src/k8s/cmd/k8s/k8s_bootstrap.go +++ b/src/k8s/cmd/k8s/k8s_bootstrap.go @@ -60,7 +60,7 @@ func newBootstrapCmd(env cmdutil.ExecutionEnvironment) *cobra.Command { env.Exit(1) return } - if microk8sInfo.StatusCode == 200 && !microk8sInfo.Result.InstallDate.IsZero() { + if microk8sInfo.StatusCode == 200 && microk8sInfo.HasInstallDate() { cmd.PrintErrln("Error: microk8s snap is installed. Please remove it using the following command and try again:\n\n sudo snap remove microk8s") env.Exit(1) return diff --git a/src/k8s/pkg/client/snapd/snap_info.go b/src/k8s/pkg/client/snapd/snap_info.go index b78eda0bc..b09f61ec4 100644 --- a/src/k8s/pkg/client/snapd/snap_info.go +++ b/src/k8s/pkg/client/snapd/snap_info.go @@ -35,3 +35,7 @@ func (c *Client) GetSnapInfo(snap string) (*SnapInfoResponse, error) { return &snapInfoResponse, nil } + +func (s SnapInfoResponse) HasInstallDate() bool { + return !s.Result.InstallDate.IsZero() +}