mirror of
https://github.com/k3s-io/kubernetes.git
synced 2025-07-23 19:56:01 +00:00
Merge pull request #94879 from knight42/refactor/kubeadm-alpha-kubeconfig
kubeadm: make "alpha kubeconfig user" accept --config
This commit is contained in:
commit
9f32854099
@ -67,10 +67,12 @@ go_test(
|
|||||||
"//cmd/kubeadm/test:go_default_library",
|
"//cmd/kubeadm/test:go_default_library",
|
||||||
"//cmd/kubeadm/test/cmd:go_default_library",
|
"//cmd/kubeadm/test/cmd:go_default_library",
|
||||||
"//cmd/kubeadm/test/kubeconfig:go_default_library",
|
"//cmd/kubeadm/test/kubeconfig:go_default_library",
|
||||||
|
"//staging/src/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library",
|
||||||
"//staging/src/k8s.io/client-go/tools/clientcmd:go_default_library",
|
"//staging/src/k8s.io/client-go/tools/clientcmd:go_default_library",
|
||||||
"//vendor/github.com/spf13/cobra:go_default_library",
|
"//vendor/github.com/spf13/cobra:go_default_library",
|
||||||
"//vendor/github.com/spf13/pflag:go_default_library",
|
"//vendor/github.com/spf13/pflag:go_default_library",
|
||||||
"//vendor/github.com/stretchr/testify/assert:go_default_library",
|
"//vendor/github.com/stretchr/testify/assert:go_default_library",
|
||||||
"//vendor/github.com/stretchr/testify/require:go_default_library",
|
"//vendor/github.com/stretchr/testify/require:go_default_library",
|
||||||
|
"//vendor/sigs.k8s.io/yaml:go_default_library",
|
||||||
],
|
],
|
||||||
)
|
)
|
||||||
|
@ -19,9 +19,8 @@ package alpha
|
|||||||
import (
|
import (
|
||||||
"io"
|
"io"
|
||||||
|
|
||||||
"github.com/pkg/errors"
|
|
||||||
"github.com/spf13/cobra"
|
"github.com/spf13/cobra"
|
||||||
kubeadmscheme "k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm/scheme"
|
|
||||||
kubeadmapiv1beta2 "k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm/v1beta2"
|
kubeadmapiv1beta2 "k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm/v1beta2"
|
||||||
"k8s.io/kubernetes/cmd/kubeadm/app/cmd/options"
|
"k8s.io/kubernetes/cmd/kubeadm/app/cmd/options"
|
||||||
cmdutil "k8s.io/kubernetes/cmd/kubeadm/app/cmd/util"
|
cmdutil "k8s.io/kubernetes/cmd/kubeadm/app/cmd/util"
|
||||||
@ -39,8 +38,8 @@ var (
|
|||||||
` + cmdutil.AlphaDisclaimer)
|
` + cmdutil.AlphaDisclaimer)
|
||||||
|
|
||||||
userKubeconfigExample = cmdutil.Examples(`
|
userKubeconfigExample = cmdutil.Examples(`
|
||||||
# Output a kubeconfig file for an additional user named foo
|
# Output a kubeconfig file for an additional user named foo using a kubeadm config file bar
|
||||||
kubeadm alpha kubeconfig user --client-name=foo
|
kubeadm alpha kubeconfig user --client-name=foo --config=bar
|
||||||
`)
|
`)
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -62,12 +61,10 @@ func newCmdUserKubeConfig(out io.Writer) *cobra.Command {
|
|||||||
initCfg := &kubeadmapiv1beta2.InitConfiguration{}
|
initCfg := &kubeadmapiv1beta2.InitConfiguration{}
|
||||||
clusterCfg := &kubeadmapiv1beta2.ClusterConfiguration{}
|
clusterCfg := &kubeadmapiv1beta2.ClusterConfiguration{}
|
||||||
|
|
||||||
// Default values for the cobra help text
|
var (
|
||||||
kubeadmscheme.Scheme.Default(initCfg)
|
token, clientName, cfgPath string
|
||||||
kubeadmscheme.Scheme.Default(clusterCfg)
|
organizations []string
|
||||||
|
)
|
||||||
var token, clientName string
|
|
||||||
var organizations []string
|
|
||||||
|
|
||||||
// Creates the UX Command
|
// Creates the UX Command
|
||||||
cmd := &cobra.Command{
|
cmd := &cobra.Command{
|
||||||
@ -76,39 +73,31 @@ func newCmdUserKubeConfig(out io.Writer) *cobra.Command {
|
|||||||
Long: userKubeconfigLongDesc,
|
Long: userKubeconfigLongDesc,
|
||||||
Example: userKubeconfigExample,
|
Example: userKubeconfigExample,
|
||||||
RunE: func(cmd *cobra.Command, args []string) error {
|
RunE: func(cmd *cobra.Command, args []string) error {
|
||||||
if clientName == "" {
|
|
||||||
return errors.New("missing required argument --client-name")
|
|
||||||
}
|
|
||||||
|
|
||||||
// This call returns the ready-to-use configuration based on the defaults populated by flags
|
// This call returns the ready-to-use configuration based on the defaults populated by flags
|
||||||
internalcfg, err := configutil.DefaultedInitConfiguration(initCfg, clusterCfg)
|
internalCfg, err := configutil.LoadOrDefaultInitConfiguration(cfgPath, initCfg, clusterCfg)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
// if the kubeconfig file for an additional user has to use a token, use it
|
// if the kubeconfig file for an additional user has to use a token, use it
|
||||||
if token != "" {
|
if token != "" {
|
||||||
return kubeconfigphase.WriteKubeConfigWithToken(out, internalcfg, clientName, token)
|
return kubeconfigphase.WriteKubeConfigWithToken(out, internalCfg, clientName, token)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Otherwise, write a kubeconfig file with a generate client cert
|
// Otherwise, write a kubeconfig file with a generate client cert
|
||||||
return kubeconfigphase.WriteKubeConfigWithClientCert(out, internalcfg, clientName, organizations)
|
return kubeconfigphase.WriteKubeConfigWithClientCert(out, internalCfg, clientName, organizations)
|
||||||
},
|
},
|
||||||
Args: cobra.NoArgs,
|
Args: cobra.NoArgs,
|
||||||
}
|
}
|
||||||
|
|
||||||
// Add ClusterConfiguration backed flags to the command
|
options.AddConfigFlag(cmd.Flags(), &cfgPath)
|
||||||
cmd.Flags().StringVar(&clusterCfg.CertificatesDir, options.CertificatesDir, clusterCfg.CertificatesDir, "The path where certificates are stored")
|
|
||||||
cmd.Flags().StringVar(&clusterCfg.ClusterName, "cluster-name", clusterCfg.ClusterName, "Cluster name to be used in kubeconfig")
|
|
||||||
|
|
||||||
// Add InitConfiguration backed flags to the command
|
|
||||||
cmd.Flags().StringVar(&initCfg.LocalAPIEndpoint.AdvertiseAddress, options.APIServerAdvertiseAddress, initCfg.LocalAPIEndpoint.AdvertiseAddress, "The IP address the API server is accessible on")
|
|
||||||
cmd.Flags().Int32Var(&initCfg.LocalAPIEndpoint.BindPort, options.APIServerBindPort, initCfg.LocalAPIEndpoint.BindPort, "The port the API server is accessible on")
|
|
||||||
|
|
||||||
// Add command specific flags
|
// Add command specific flags
|
||||||
cmd.Flags().StringVar(&token, options.TokenStr, token, "The token that should be used as the authentication mechanism for this kubeconfig, instead of client certificates")
|
cmd.Flags().StringVar(&token, options.TokenStr, token, "The token that should be used as the authentication mechanism for this kubeconfig, instead of client certificates")
|
||||||
cmd.Flags().StringVar(&clientName, "client-name", clientName, "The name of user. It will be used as the CN if client certificates are created")
|
cmd.Flags().StringVar(&clientName, "client-name", clientName, "The name of user. It will be used as the CN if client certificates are created")
|
||||||
cmd.Flags().StringSliceVar(&organizations, "org", organizations, "The orgnizations of the client certificate. It will be used as the O if client certificates are created")
|
cmd.Flags().StringSliceVar(&organizations, "org", organizations, "The orgnizations of the client certificate. It will be used as the O if client certificates are created")
|
||||||
|
|
||||||
|
cmd.MarkFlagRequired(options.CfgPath)
|
||||||
|
cmd.MarkFlagRequired("client-name")
|
||||||
return cmd
|
return cmd
|
||||||
}
|
}
|
||||||
|
@ -19,16 +19,61 @@ package alpha
|
|||||||
import (
|
import (
|
||||||
"bytes"
|
"bytes"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"io/ioutil"
|
||||||
"os"
|
"os"
|
||||||
|
"path/filepath"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
|
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||||
"k8s.io/client-go/tools/clientcmd"
|
"k8s.io/client-go/tools/clientcmd"
|
||||||
|
"sigs.k8s.io/yaml"
|
||||||
|
|
||||||
|
kubeadmapiv1beta2 "k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm/v1beta2"
|
||||||
kubeadmconstants "k8s.io/kubernetes/cmd/kubeadm/app/constants"
|
kubeadmconstants "k8s.io/kubernetes/cmd/kubeadm/app/constants"
|
||||||
"k8s.io/kubernetes/cmd/kubeadm/app/util/pkiutil"
|
"k8s.io/kubernetes/cmd/kubeadm/app/util/pkiutil"
|
||||||
testutil "k8s.io/kubernetes/cmd/kubeadm/test"
|
testutil "k8s.io/kubernetes/cmd/kubeadm/test"
|
||||||
kubeconfigtestutil "k8s.io/kubernetes/cmd/kubeadm/test/kubeconfig"
|
kubeconfigtestutil "k8s.io/kubernetes/cmd/kubeadm/test/kubeconfig"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
func generateTestKubeadmConfig(dir, id, certDir, clusterName string) (string, error) {
|
||||||
|
cfgPath := filepath.Join(dir, id)
|
||||||
|
initCfg := kubeadmapiv1beta2.InitConfiguration{
|
||||||
|
TypeMeta: metav1.TypeMeta{
|
||||||
|
APIVersion: "kubeadm.k8s.io/v1beta2",
|
||||||
|
Kind: "InitConfiguration",
|
||||||
|
},
|
||||||
|
LocalAPIEndpoint: kubeadmapiv1beta2.APIEndpoint{
|
||||||
|
AdvertiseAddress: "1.2.3.4",
|
||||||
|
BindPort: 1234,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
clusterCfg := kubeadmapiv1beta2.ClusterConfiguration{
|
||||||
|
TypeMeta: metav1.TypeMeta{
|
||||||
|
APIVersion: "kubeadm.k8s.io/v1beta2",
|
||||||
|
Kind: "ClusterConfiguration",
|
||||||
|
},
|
||||||
|
CertificatesDir: certDir,
|
||||||
|
ClusterName: clusterName,
|
||||||
|
KubernetesVersion: "v1.19.0",
|
||||||
|
}
|
||||||
|
|
||||||
|
var buf bytes.Buffer
|
||||||
|
data, err := yaml.Marshal(&initCfg)
|
||||||
|
if err != nil {
|
||||||
|
return "", err
|
||||||
|
}
|
||||||
|
buf.Write(data)
|
||||||
|
buf.WriteString("---\n")
|
||||||
|
data, err = yaml.Marshal(&clusterCfg)
|
||||||
|
if err != nil {
|
||||||
|
return "", err
|
||||||
|
}
|
||||||
|
buf.Write(data)
|
||||||
|
|
||||||
|
err = ioutil.WriteFile(cfgPath, buf.Bytes(), 0644)
|
||||||
|
return cfgPath, err
|
||||||
|
}
|
||||||
|
|
||||||
func TestKubeConfigSubCommandsThatWritesToOut(t *testing.T) {
|
func TestKubeConfigSubCommandsThatWritesToOut(t *testing.T) {
|
||||||
|
|
||||||
// Temporary folders for the test case
|
// Temporary folders for the test case
|
||||||
@ -44,19 +89,12 @@ func TestKubeConfigSubCommandsThatWritesToOut(t *testing.T) {
|
|||||||
t.Fatalf("couldn't retrieve ca cert: %v", err)
|
t.Fatalf("couldn't retrieve ca cert: %v", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
commonFlags := []string{
|
|
||||||
"--apiserver-advertise-address=1.2.3.4",
|
|
||||||
"--apiserver-bind-port=1234",
|
|
||||||
"--client-name=myUser",
|
|
||||||
fmt.Sprintf("--cert-dir=%s", pkidir),
|
|
||||||
}
|
|
||||||
|
|
||||||
var tests = []struct {
|
var tests = []struct {
|
||||||
name string
|
name string
|
||||||
command string
|
command string
|
||||||
|
clusterName string
|
||||||
withClientCert bool
|
withClientCert bool
|
||||||
withToken bool
|
withToken bool
|
||||||
withClusterName bool
|
|
||||||
additionalFlags []string
|
additionalFlags []string
|
||||||
}{
|
}{
|
||||||
{
|
{
|
||||||
@ -65,11 +103,10 @@ func TestKubeConfigSubCommandsThatWritesToOut(t *testing.T) {
|
|||||||
withClientCert: true,
|
withClientCert: true,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "user subCommand withClientCert",
|
name: "user subCommand withClientCert",
|
||||||
command: "user",
|
command: "user",
|
||||||
withClientCert: true,
|
withClientCert: true,
|
||||||
withClusterName: true,
|
clusterName: "my-cluster",
|
||||||
additionalFlags: []string{"--cluster-name=my-cluster"},
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "user subCommand withToken",
|
name: "user subCommand withToken",
|
||||||
@ -81,8 +118,8 @@ func TestKubeConfigSubCommandsThatWritesToOut(t *testing.T) {
|
|||||||
name: "user subCommand withToken",
|
name: "user subCommand withToken",
|
||||||
withToken: true,
|
withToken: true,
|
||||||
command: "user",
|
command: "user",
|
||||||
withClusterName: true,
|
clusterName: "my-cluster-with-token",
|
||||||
additionalFlags: []string{"--token=123456", "--cluster-name=my-cluster"},
|
additionalFlags: []string{"--token=123456"},
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -93,18 +130,27 @@ func TestKubeConfigSubCommandsThatWritesToOut(t *testing.T) {
|
|||||||
// Get subcommands working in the temporary directory
|
// Get subcommands working in the temporary directory
|
||||||
cmd := newCmdUserKubeConfig(buf)
|
cmd := newCmdUserKubeConfig(buf)
|
||||||
|
|
||||||
|
cfgPath, err := generateTestKubeadmConfig(tmpdir, test.name, pkidir, test.clusterName)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("Failed to generate kubeadm config: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
commonFlags := []string{
|
||||||
|
"--client-name=myUser",
|
||||||
|
fmt.Sprintf("--config=%s", cfgPath),
|
||||||
|
}
|
||||||
|
|
||||||
// Execute the subcommand
|
// Execute the subcommand
|
||||||
allFlags := append(commonFlags, test.additionalFlags...)
|
allFlags := append(commonFlags, test.additionalFlags...)
|
||||||
cmd.SetArgs(allFlags)
|
cmd.SetArgs(allFlags)
|
||||||
if err := cmd.Execute(); err != nil {
|
if err := cmd.Execute(); err != nil {
|
||||||
t.Fatal("Could not execute subcommand")
|
t.Fatalf("Could not execute subcommand: %v", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
// reads kubeconfig written to stdout
|
// reads kubeconfig written to stdout
|
||||||
config, err := clientcmd.Load(buf.Bytes())
|
config, err := clientcmd.Load(buf.Bytes())
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Errorf("couldn't read kubeconfig file from buffer: %v", err)
|
t.Fatalf("couldn't read kubeconfig file from buffer: %v", err)
|
||||||
return
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// checks that CLI flags are properly propagated
|
// checks that CLI flags are properly propagated
|
||||||
@ -120,9 +166,9 @@ func TestKubeConfigSubCommandsThatWritesToOut(t *testing.T) {
|
|||||||
kubeconfigtestutil.AssertKubeConfigCurrentAuthInfoWithToken(t, config, "myUser", "123456")
|
kubeconfigtestutil.AssertKubeConfigCurrentAuthInfoWithToken(t, config, "myUser", "123456")
|
||||||
}
|
}
|
||||||
|
|
||||||
if test.withClusterName {
|
if len(test.clusterName) > 0 {
|
||||||
// checks that kubeconfig files have expected cluster name
|
// checks that kubeconfig files have expected cluster name
|
||||||
kubeconfigtestutil.AssertKubeConfigCurrentContextWithClusterName(t, config, "my-cluster")
|
kubeconfigtestutil.AssertKubeConfigCurrentContextWithClusterName(t, config, test.clusterName)
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user