mirror of
https://github.com/rancher/k3k.git
synced 2026-08-23 22:36:17 +00:00
feat: update kubeconfig generate command (#1158)
* feat: update kubeconfig generate command * improve messages and docs
This commit is contained in:
@@ -144,7 +144,7 @@ EOF
|
||||
and use the `k3kcli` to retrieve the kubeconfig:
|
||||
|
||||
```bash
|
||||
k3kcli kubeconfig generate --namespace k3k-mycluster --name mycluster
|
||||
k3kcli kubeconfig generate mycluster
|
||||
```
|
||||
|
||||
|
||||
|
||||
+40
-6
@@ -1,6 +1,8 @@
|
||||
package cmds
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"net/url"
|
||||
"os"
|
||||
"path/filepath"
|
||||
@@ -49,12 +51,15 @@ func NewKubeconfigGenerateCmd(appCtx *AppContext) *cobra.Command {
|
||||
cfg := &GenerateKubeconfigConfig{}
|
||||
|
||||
cmd := &cobra.Command{
|
||||
Use: "generate",
|
||||
Short: "Generate kubeconfig for clusters.",
|
||||
RunE: generate(appCtx, cfg),
|
||||
Args: cobra.NoArgs,
|
||||
Use: "generate",
|
||||
Short: "Generate kubeconfig for clusters.",
|
||||
Example: "k3kcli kubeconfig generate [command options] NAME",
|
||||
RunE: generate(appCtx, cfg),
|
||||
Args: cobra.MaximumNArgs(1),
|
||||
}
|
||||
|
||||
cmd.ValidArgsFunction = completeClusterNames
|
||||
|
||||
CobraFlagNamespace(appCtx, cmd, completeClusterNamespaces)
|
||||
|
||||
generateKubeconfigFlags(cmd, cfg)
|
||||
@@ -64,6 +69,11 @@ func NewKubeconfigGenerateCmd(appCtx *AppContext) *cobra.Command {
|
||||
|
||||
func generateKubeconfigFlags(cmd *cobra.Command, cfg *GenerateKubeconfigConfig) {
|
||||
cmd.Flags().StringVar(&cfg.name, "name", "", "cluster name")
|
||||
|
||||
if err := cmd.Flags().MarkDeprecated("name", "it will be removed in a future release, use the NAME argument instead"); err != nil {
|
||||
logrus.Fatal(err)
|
||||
}
|
||||
|
||||
cmd.Flags().StringVar(&cfg.configName, "config-name", "", "the name of the generated kubeconfig file")
|
||||
cmd.Flags().StringVar(&cfg.cn, "cn", controller.AdminCommonName, "Common name (CN) of the generated certificates for the kubeconfig")
|
||||
cmd.Flags().StringSliceVar(&cfg.org, "org", nil, "Organization name (ORG) of the generated certificates for the kubeconfig")
|
||||
@@ -77,14 +87,38 @@ func generate(appCtx *AppContext, cfg *GenerateKubeconfigConfig) func(cmd *cobra
|
||||
ctx := cmd.Context()
|
||||
client := appCtx.Client
|
||||
|
||||
name, namespace := cfg.name, appCtx.Namespace(cfg.name)
|
||||
|
||||
switch {
|
||||
case len(args) == 1:
|
||||
if cfg.name != "" {
|
||||
logrus.Warnf("the --name flag is deprecated and will be removed in a future release, ignoring it in favor of the '%s' argument", args[0])
|
||||
}
|
||||
|
||||
var err error
|
||||
if namespace, name, err = resolveClusterArg(appCtx, args[0]); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
case name != "":
|
||||
logrus.Warn("the --name flag is deprecated and will be removed in a future release, use the NAME argument instead")
|
||||
|
||||
default:
|
||||
return errors.New("expected exactly one cluster name")
|
||||
}
|
||||
|
||||
clusterKey := types.NamespacedName{
|
||||
Name: cfg.name,
|
||||
Namespace: appCtx.Namespace(cfg.name),
|
||||
Name: name,
|
||||
Namespace: namespace,
|
||||
}
|
||||
|
||||
var cluster v1beta1.Cluster
|
||||
|
||||
if err := client.Get(ctx, clusterKey, &cluster); err != nil {
|
||||
if apierrors.IsNotFound(err) {
|
||||
return fmt.Errorf("cluster %q not found in namespace %q", name, namespace)
|
||||
}
|
||||
|
||||
return err
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,111 @@
|
||||
package cmds
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"github.com/sirupsen/logrus"
|
||||
"github.com/sirupsen/logrus/hooks/test"
|
||||
"github.com/spf13/cobra"
|
||||
"github.com/stretchr/testify/assert"
|
||||
"github.com/stretchr/testify/require"
|
||||
"k8s.io/apimachinery/pkg/runtime"
|
||||
"sigs.k8s.io/controller-runtime/pkg/client/fake"
|
||||
|
||||
"github.com/rancher/k3k/pkg/apis/k3k.io/v1beta1"
|
||||
)
|
||||
|
||||
// Test_generate_clusterKey checks how the cluster name and namespace are resolved from the
|
||||
// NAME argument and the deprecated --name flag. The cluster is always missing, so the
|
||||
// "not found" error reports the resolved key without going through the kubeconfig generation.
|
||||
func Test_generate_clusterKey(t *testing.T) {
|
||||
tests := []struct {
|
||||
name string
|
||||
flagNamespace string
|
||||
flagName string
|
||||
args []string
|
||||
wantErr string
|
||||
wantWarn string
|
||||
}{
|
||||
{
|
||||
name: "bare name argument defaults to k3k-<name>",
|
||||
args: []string{"mycluster"},
|
||||
wantErr: `cluster "mycluster" not found in namespace "k3k-mycluster"`,
|
||||
},
|
||||
{
|
||||
name: "namespace/name argument is split",
|
||||
args: []string{"myns/mycluster"},
|
||||
wantErr: `cluster "mycluster" not found in namespace "myns"`,
|
||||
},
|
||||
{
|
||||
name: "bare name argument respects the namespace flag",
|
||||
flagNamespace: "myns",
|
||||
args: []string{"mycluster"},
|
||||
wantErr: `cluster "mycluster" not found in namespace "myns"`,
|
||||
},
|
||||
{
|
||||
name: "namespace/name argument conflicting with the namespace flag errors",
|
||||
flagNamespace: "otherns",
|
||||
args: []string{"myns/mycluster"},
|
||||
wantErr: `namespace mismatch: flag --namespace "otherns" conflicts with argument namespace "myns"`,
|
||||
},
|
||||
{
|
||||
name: "deprecated name flag is still supported",
|
||||
flagName: "mycluster",
|
||||
wantErr: `cluster "mycluster" not found in namespace "k3k-mycluster"`,
|
||||
wantWarn: "the --name flag is deprecated and will be removed in a future release, use the NAME argument instead",
|
||||
},
|
||||
{
|
||||
name: "deprecated name flag respects the namespace flag",
|
||||
flagNamespace: "myns",
|
||||
flagName: "mycluster",
|
||||
wantErr: `cluster "mycluster" not found in namespace "myns"`,
|
||||
wantWarn: "the --name flag is deprecated and will be removed in a future release, use the NAME argument instead",
|
||||
},
|
||||
{
|
||||
name: "the argument wins over the deprecated name flag",
|
||||
flagName: "ignored",
|
||||
args: []string{"myns/mycluster"},
|
||||
wantErr: `cluster "mycluster" not found in namespace "myns"`,
|
||||
wantWarn: "the --name flag is deprecated and will be removed in a future release, ignoring it in favor of the 'myns/mycluster' argument",
|
||||
},
|
||||
{
|
||||
name: "no cluster name at all errors",
|
||||
wantErr: "expected exactly one cluster name",
|
||||
},
|
||||
}
|
||||
|
||||
scheme := runtime.NewScheme()
|
||||
require.NoError(t, v1beta1.AddToScheme(scheme))
|
||||
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
logs := test.NewGlobal()
|
||||
defer logs.Reset()
|
||||
|
||||
appCtx := &AppContext{
|
||||
Client: fake.NewClientBuilder().WithScheme(scheme).Build(),
|
||||
namespace: tt.flagNamespace,
|
||||
}
|
||||
cfg := &GenerateKubeconfigConfig{name: tt.flagName}
|
||||
|
||||
err := generate(appCtx, cfg)(&cobra.Command{}, tt.args)
|
||||
|
||||
assert.EqualError(t, err, tt.wantErr)
|
||||
|
||||
var warnings []string
|
||||
|
||||
for _, entry := range logs.AllEntries() {
|
||||
if entry.Level == logrus.WarnLevel {
|
||||
warnings = append(warnings, entry.Message)
|
||||
}
|
||||
}
|
||||
|
||||
if tt.wantWarn == "" {
|
||||
assert.Empty(t, warnings)
|
||||
return
|
||||
}
|
||||
|
||||
assert.Equal(t, []string{tt.wantWarn}, warnings)
|
||||
})
|
||||
}
|
||||
}
|
||||
@@ -151,7 +151,7 @@ Add `my-cluster.example.com` to `spec.tlsSANs` so the API server certificate cov
|
||||
the kubeconfig with the matching endpoint:
|
||||
|
||||
```bash
|
||||
k3kcli kubeconfig generate --namespace my-namespace --name my-virtual-cluster \
|
||||
k3kcli kubeconfig generate my-namespace/my-virtual-cluster \
|
||||
--kubeconfig-server https://my-cluster.example.com
|
||||
```
|
||||
|
||||
|
||||
@@ -194,6 +194,12 @@ Generate kubeconfig for clusters.
|
||||
k3kcli kubeconfig generate [flags]
|
||||
----
|
||||
|
||||
=== Examples
|
||||
|
||||
----
|
||||
k3kcli kubeconfig generate [command options] NAME
|
||||
----
|
||||
|
||||
=== Options
|
||||
|
||||
----
|
||||
@@ -203,7 +209,6 @@ k3kcli kubeconfig generate [flags]
|
||||
--expiration-days int Expiration date of the certificates used for the kubeconfig (default 365)
|
||||
-h, --help help for generate
|
||||
--kubeconfig-server string override the kubeconfig server host
|
||||
--name string cluster name
|
||||
-n, --namespace string namespace of the k3k cluster
|
||||
--org strings Organization name (ORG) of the generated certificates for the kubeconfig
|
||||
----
|
||||
|
||||
@@ -6,6 +6,12 @@ Generate kubeconfig for clusters.
|
||||
k3kcli kubeconfig generate [flags]
|
||||
```
|
||||
|
||||
### Examples
|
||||
|
||||
```
|
||||
k3kcli kubeconfig generate [command options] NAME
|
||||
```
|
||||
|
||||
### Options
|
||||
|
||||
```
|
||||
@@ -15,7 +21,6 @@ k3kcli kubeconfig generate [flags]
|
||||
--expiration-days int Expiration date of the certificates used for the kubeconfig (default 365)
|
||||
-h, --help help for generate
|
||||
--kubeconfig-server string override the kubeconfig server host
|
||||
--name string cluster name
|
||||
-n, --namespace string namespace of the k3k cluster
|
||||
--org strings Organization name (ORG) of the generated certificates for the kubeconfig
|
||||
```
|
||||
|
||||
+1
-1
@@ -177,7 +177,7 @@ kubectl get po -n k3k-mycluster
|
||||
Last thing to do is to get the kubeconfig to connect to the virtual cluster we've just created:
|
||||
|
||||
```bash
|
||||
k3kcli kubeconfig generate --name mycluster --namespace k3k-mycluster --kubeconfig-server localhost:30001
|
||||
k3kcli kubeconfig generate mycluster --kubeconfig-server localhost:30001
|
||||
```
|
||||
|
||||
|
||||
|
||||
@@ -294,8 +294,8 @@ Once the virtual cluster is running, you can connect to it using the CLI:
|
||||
### CLI Method
|
||||
|
||||
```sh
|
||||
k3kcli kubeconfig generate --namespace k3k-mycluster --name mycluster
|
||||
export KUBECONFIG=$PWD/mycluster-kubeconfig.yaml
|
||||
k3kcli kubeconfig generate mycluster
|
||||
export KUBECONFIG=$PWD/k3k-mycluster-mycluster-kubeconfig.yaml
|
||||
kubectl get nodes
|
||||
```
|
||||
|
||||
|
||||
@@ -535,7 +535,7 @@ var _ = When("using the k3kcli", Label("cli"), func() {
|
||||
|
||||
By("Generating the kubeconfig")
|
||||
|
||||
_, stderr, err = K3kcli("kubeconfig", "generate", "--namespace", clusterNamespace, "--name", clusterName)
|
||||
_, stderr, err = K3kcli("kubeconfig", "generate", clusterNamespace+"/"+clusterName)
|
||||
Expect(err).To(Not(HaveOccurred()), string(stderr))
|
||||
Expect(stderr).To(ContainSubstring("You can start using the cluster"))
|
||||
|
||||
|
||||
Reference in New Issue
Block a user