From bd947c0fcb188d94b2bd79349e98a904fb8ba5d6 Mon Sep 17 00:00:00 2001 From: Enrico Candino Date: Wed, 26 Mar 2025 14:53:41 +0100 Subject: [PATCH] Create dedicated namespace for new clusters (#314) * create dedicated namespace for new clusters * porcelain test * use --exit-code instead of test and shell for escaping issue * update go.mod --- Makefile | 5 ++--- cli/cmds/cluster.go | 2 +- cli/cmds/cluster_create.go | 45 ++++++++++++++++++-------------------- cli/cmds/cluster_delete.go | 6 +++-- cli/cmds/kubeconfig.go | 38 ++++++++++++++++++-------------- cli/cmds/root.go | 16 +++++--------- go.mod | 2 +- 7 files changed, 57 insertions(+), 57 deletions(-) diff --git a/Makefile b/Makefile index 24b98e58..f260fc2b 100644 --- a/Makefile +++ b/Makefile @@ -89,9 +89,8 @@ lint: ## Find any linting issues in the project validate: build-crds docs ## Validate the project checking for any dependency or doc mismatch $(GINKGO) unfocus go mod tidy - git --no-pager diff go.mod go.sum - test -z "$(shell git status --porcelain)" - + git status --porcelain + git --no-pager diff --exit-code .PHONY: install install: ## Install K3k with Helm on the targeted Kubernetes cluster diff --git a/cli/cmds/cluster.go b/cli/cmds/cluster.go index 6bbbc6d0..d8e68309 100644 --- a/cli/cmds/cluster.go +++ b/cli/cmds/cluster.go @@ -4,7 +4,7 @@ import ( "github.com/urfave/cli/v2" ) -func NewClusterCommand() *cli.Command { +func NewClusterCmd() *cli.Command { return &cli.Command{ Name: "cluster", Usage: "cluster command", diff --git a/cli/cmds/cluster_create.go b/cli/cmds/cluster_create.go index 8f430169..2aae540e 100644 --- a/cli/cmds/cluster_create.go +++ b/cli/cmds/cluster_create.go @@ -4,8 +4,6 @@ import ( "context" "errors" "net/url" - "os" - "path/filepath" "strings" "time" @@ -17,8 +15,8 @@ import ( v1 "k8s.io/api/core/v1" apierrors "k8s.io/apimachinery/pkg/api/errors" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/apimachinery/pkg/types" "k8s.io/apimachinery/pkg/util/wait" - "k8s.io/client-go/tools/clientcmd" clientcmdapi "k8s.io/client-go/tools/clientcmd/api" "k8s.io/client-go/util/retry" "k8s.io/utils/ptr" @@ -79,6 +77,21 @@ func createAction(config *CreateConfig) cli.ActionFunc { return err } + namespace := Namespace(name) + + ns := &v1.Namespace{ObjectMeta: metav1.ObjectMeta{Name: namespace}} + if err := ctrlClient.Get(ctx, types.NamespacedName{Name: namespace}, ns); err != nil { + if !apierrors.IsNotFound(err) { + return err + } + + logrus.Infof(`Creating namespace [%s]`, namespace) + + if err := ctrlClient.Create(ctx, ns); err != nil { + return err + } + } + if strings.Contains(config.version, "+") { orig := config.version config.version = strings.Replace(config.version, "+", "-", -1) @@ -86,18 +99,18 @@ func createAction(config *CreateConfig) cli.ActionFunc { } if config.token != "" { - logrus.Infof("Creating cluster token secret") + logrus.Info("Creating cluster token secret") - obj := k3kcluster.TokenSecretObj(config.token, name, Namespace()) + obj := k3kcluster.TokenSecretObj(config.token, name, namespace) if err := ctrlClient.Create(ctx, &obj); err != nil { return err } } - logrus.Infof("Creating a new cluster [%s]", name) + logrus.Infof("Creating cluster [%s] in namespace [%s]", name, namespace) - cluster := newCluster(name, Namespace(), config) + cluster := newCluster(name, namespace, config) cluster.Spec.Expose = &v1alpha1.ExposeConfig{ NodePort: &v1alpha1.NodePortConfig{}, @@ -146,23 +159,7 @@ func createAction(config *CreateConfig) cli.ActionFunc { return err } - pwd, err := os.Getwd() - if err != nil { - return err - } - - logrus.Infof(`You can start using the cluster with: - - export KUBECONFIG=%s - kubectl cluster-info - `, filepath.Join(pwd, cluster.Name+"-kubeconfig.yaml")) - - kubeconfigData, err := clientcmd.Write(*kubeconfig) - if err != nil { - return err - } - - return os.WriteFile(cluster.Name+"-kubeconfig.yaml", kubeconfigData, 0644) + return writeKubeconfigFile(cluster, kubeconfig) } } diff --git a/cli/cmds/cluster_delete.go b/cli/cmds/cluster_delete.go index 0ca2d0b8..6454e626 100644 --- a/cli/cmds/cluster_delete.go +++ b/cli/cmds/cluster_delete.go @@ -58,12 +58,14 @@ func delete(clx *cli.Context) error { return err } - logrus.Infof("deleting [%s] cluster", name) + namespace := Namespace(name) + + logrus.Infof("Deleting [%s] cluster in namespace [%s]", name, namespace) cluster := v1alpha1.Cluster{ ObjectMeta: metav1.ObjectMeta{ Name: name, - Namespace: Namespace(), + Namespace: namespace, }, } // keep bootstrap secrets and tokens if --keep-data flag is passed diff --git a/cli/cmds/kubeconfig.go b/cli/cmds/kubeconfig.go index 89355b5a..40604a5b 100644 --- a/cli/cmds/kubeconfig.go +++ b/cli/cmds/kubeconfig.go @@ -73,21 +73,23 @@ var ( } ) -var subcommands = []*cli.Command{ - { +func NewKubeconfigCmd() *cli.Command { + return &cli.Command{ + Name: "kubeconfig", + Usage: "Manage kubeconfig for clusters", + Subcommands: []*cli.Command{ + NewKubeconfigGenerateCmd(), + }, + } +} + +func NewKubeconfigGenerateCmd() *cli.Command { + return &cli.Command{ Name: "generate", Usage: "Generate kubeconfig for clusters", SkipFlagParsing: false, Action: generate, Flags: append(CommonFlags, generateKubeconfigFlags...), - }, -} - -func NewKubeconfigCommand() *cli.Command { - return &cli.Command{ - Name: "kubeconfig", - Usage: "Manage kubeconfig for clusters", - Subcommands: subcommands, } } @@ -106,7 +108,7 @@ func generate(clx *cli.Context) error { clusterKey := types.NamespacedName{ Name: name, - Namespace: Namespace(), + Namespace: Namespace(name), } var cluster v1alpha1.Cluster @@ -155,16 +157,20 @@ func generate(clx *cli.Context) error { return err } + return writeKubeconfigFile(&cluster, kubeconfig) +} + +func writeKubeconfigFile(cluster *v1alpha1.Cluster, kubeconfig *clientcmdapi.Config) error { + if configName == "" { + configName = cluster.Namespace + "-" + cluster.Name + "-kubeconfig.yaml" + } + pwd, err := os.Getwd() if err != nil { return err } - if configName == "" { - configName = cluster.Name + "-kubeconfig.yaml" - } - - logrus.Infof(`You can start using the cluster with: + logrus.Infof(`You can start using the cluster with: export KUBECONFIG=%s kubectl cluster-info diff --git a/cli/cmds/root.go b/cli/cmds/root.go index 05b24a74..01e85fb7 100644 --- a/cli/cmds/root.go +++ b/cli/cmds/root.go @@ -13,10 +13,6 @@ import ( "k8s.io/client-go/tools/clientcmd" ) -const ( - defaultNamespace = "default" -) - var ( Scheme = runtime.NewScheme() @@ -71,19 +67,19 @@ func NewApp() *cli.App { } app.Commands = []*cli.Command{ - NewClusterCommand(), - NewKubeconfigCommand(), + NewClusterCmd(), + NewKubeconfigCmd(), } return app } -func Namespace() string { - if namespace == "" { - return defaultNamespace +func Namespace(clusterName string) string { + if namespace != "" { + return namespace } - return namespace + return "k3k-" + clusterName } func loadRESTConfig() (*rest.Config, error) { diff --git a/go.mod b/go.mod index 153fd71b..eb3be3ef 100644 --- a/go.mod +++ b/go.mod @@ -33,6 +33,7 @@ require ( k8s.io/client-go v0.29.11 k8s.io/component-base v0.29.11 k8s.io/component-helpers v0.29.11 + k8s.io/kubectl v0.29.11 k8s.io/utils v0.0.0-20241104100929-3ea5e8cea738 sigs.k8s.io/controller-runtime v0.17.5 ) @@ -207,7 +208,6 @@ require ( k8s.io/klog/v2 v2.130.1 // indirect k8s.io/kms v0.29.11 // indirect k8s.io/kube-openapi v0.0.0-20241105132330-32ad38e42d3f // indirect - k8s.io/kubectl v0.29.11 // indirect oras.land/oras-go v1.2.5 // indirect sigs.k8s.io/apiserver-network-proxy/konnectivity-client v0.31.0 // indirect sigs.k8s.io/json v0.0.0-20241010143419-9aa6b5e7a4b3 // indirect