mirror of https://github.com/k3s-io/k3s
Allow modifying current context with kubectl set-context
parent
82c986ecbc
commit
fe53c618e8
|
@ -34,6 +34,7 @@ import (
|
||||||
type createContextOptions struct {
|
type createContextOptions struct {
|
||||||
configAccess clientcmd.ConfigAccess
|
configAccess clientcmd.ConfigAccess
|
||||||
name string
|
name string
|
||||||
|
currContext bool
|
||||||
cluster flag.StringFlag
|
cluster flag.StringFlag
|
||||||
authInfo flag.StringFlag
|
authInfo flag.StringFlag
|
||||||
namespace flag.StringFlag
|
namespace flag.StringFlag
|
||||||
|
@ -54,23 +55,24 @@ func NewCmdConfigSetContext(out io.Writer, configAccess clientcmd.ConfigAccess)
|
||||||
options := &createContextOptions{configAccess: configAccess}
|
options := &createContextOptions{configAccess: configAccess}
|
||||||
|
|
||||||
cmd := &cobra.Command{
|
cmd := &cobra.Command{
|
||||||
Use: fmt.Sprintf("set-context NAME [--%v=cluster_nickname] [--%v=user_nickname] [--%v=namespace]", clientcmd.FlagClusterName, clientcmd.FlagAuthInfoName, clientcmd.FlagNamespace),
|
Use: fmt.Sprintf("set-context [NAME | --current] [--%v=cluster_nickname] [--%v=user_nickname] [--%v=namespace]", clientcmd.FlagClusterName, clientcmd.FlagAuthInfoName, clientcmd.FlagNamespace),
|
||||||
DisableFlagsInUseLine: true,
|
DisableFlagsInUseLine: true,
|
||||||
Short: i18n.T("Sets a context entry in kubeconfig"),
|
Short: i18n.T("Sets a context entry in kubeconfig"),
|
||||||
Long: create_context_long,
|
Long: create_context_long,
|
||||||
Example: create_context_example,
|
Example: create_context_example,
|
||||||
Run: func(cmd *cobra.Command, args []string) {
|
Run: func(cmd *cobra.Command, args []string) {
|
||||||
cmdutil.CheckErr(options.complete(cmd))
|
cmdutil.CheckErr(options.complete(cmd))
|
||||||
exists, err := options.run()
|
name, exists, err := options.run()
|
||||||
cmdutil.CheckErr(err)
|
cmdutil.CheckErr(err)
|
||||||
if exists {
|
if exists {
|
||||||
fmt.Fprintf(out, "Context %q modified.\n", options.name)
|
fmt.Fprintf(out, "Context %q modified.\n", name)
|
||||||
} else {
|
} else {
|
||||||
fmt.Fprintf(out, "Context %q created.\n", options.name)
|
fmt.Fprintf(out, "Context %q created.\n", name)
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
|
cmd.Flags().BoolVar(&options.currContext, "current", options.currContext, "Modify the current context")
|
||||||
cmd.Flags().Var(&options.cluster, clientcmd.FlagClusterName, clientcmd.FlagClusterName+" for the context entry in kubeconfig")
|
cmd.Flags().Var(&options.cluster, clientcmd.FlagClusterName, clientcmd.FlagClusterName+" for the context entry in kubeconfig")
|
||||||
cmd.Flags().Var(&options.authInfo, clientcmd.FlagAuthInfoName, clientcmd.FlagAuthInfoName+" for the context entry in kubeconfig")
|
cmd.Flags().Var(&options.authInfo, clientcmd.FlagAuthInfoName, clientcmd.FlagAuthInfoName+" for the context entry in kubeconfig")
|
||||||
cmd.Flags().Var(&options.namespace, clientcmd.FlagNamespace, clientcmd.FlagNamespace+" for the context entry in kubeconfig")
|
cmd.Flags().Var(&options.namespace, clientcmd.FlagNamespace, clientcmd.FlagNamespace+" for the context entry in kubeconfig")
|
||||||
|
@ -78,29 +80,37 @@ func NewCmdConfigSetContext(out io.Writer, configAccess clientcmd.ConfigAccess)
|
||||||
return cmd
|
return cmd
|
||||||
}
|
}
|
||||||
|
|
||||||
func (o createContextOptions) run() (bool, error) {
|
func (o createContextOptions) run() (string, bool, error) {
|
||||||
err := o.validate()
|
err := o.validate()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return false, err
|
return "", false, err
|
||||||
}
|
}
|
||||||
|
|
||||||
config, err := o.configAccess.GetStartingConfig()
|
config, err := o.configAccess.GetStartingConfig()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return false, err
|
return "", false, err
|
||||||
}
|
}
|
||||||
|
|
||||||
startingStanza, exists := config.Contexts[o.name]
|
name := o.name
|
||||||
|
if o.currContext {
|
||||||
|
if len(config.CurrentContext) == 0 {
|
||||||
|
return "", false, errors.New("no current context is set")
|
||||||
|
}
|
||||||
|
name = config.CurrentContext
|
||||||
|
}
|
||||||
|
|
||||||
|
startingStanza, exists := config.Contexts[name]
|
||||||
if !exists {
|
if !exists {
|
||||||
startingStanza = clientcmdapi.NewContext()
|
startingStanza = clientcmdapi.NewContext()
|
||||||
}
|
}
|
||||||
context := o.modifyContext(*startingStanza)
|
context := o.modifyContext(*startingStanza)
|
||||||
config.Contexts[o.name] = &context
|
config.Contexts[name] = &context
|
||||||
|
|
||||||
if err := clientcmd.ModifyConfig(o.configAccess, *config, true); err != nil {
|
if err := clientcmd.ModifyConfig(o.configAccess, *config, true); err != nil {
|
||||||
return exists, err
|
return name, exists, err
|
||||||
}
|
}
|
||||||
|
|
||||||
return exists, nil
|
return name, exists, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (o *createContextOptions) modifyContext(existingContext clientcmdapi.Context) clientcmdapi.Context {
|
func (o *createContextOptions) modifyContext(existingContext clientcmdapi.Context) clientcmdapi.Context {
|
||||||
|
@ -121,17 +131,21 @@ func (o *createContextOptions) modifyContext(existingContext clientcmdapi.Contex
|
||||||
|
|
||||||
func (o *createContextOptions) complete(cmd *cobra.Command) error {
|
func (o *createContextOptions) complete(cmd *cobra.Command) error {
|
||||||
args := cmd.Flags().Args()
|
args := cmd.Flags().Args()
|
||||||
if len(args) != 1 {
|
if len(args) > 1 {
|
||||||
return helpErrorf(cmd, "Unexpected args: %v", args)
|
return helpErrorf(cmd, "Unexpected args: %v", args)
|
||||||
}
|
}
|
||||||
|
if len(args) == 1 {
|
||||||
o.name = args[0]
|
o.name = args[0]
|
||||||
|
}
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (o createContextOptions) validate() error {
|
func (o createContextOptions) validate() error {
|
||||||
if len(o.name) == 0 {
|
if len(o.name) == 0 && !o.currContext {
|
||||||
return errors.New("you must specify a non-empty context name")
|
return errors.New("you must specify a non-empty context name or --current-context")
|
||||||
|
}
|
||||||
|
if len(o.name) > 0 && o.currContext {
|
||||||
|
return errors.New("you cannot specify a context name and --current-context")
|
||||||
}
|
}
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
|
|
|
@ -28,6 +28,7 @@ import (
|
||||||
|
|
||||||
type createContextTest struct {
|
type createContextTest struct {
|
||||||
description string
|
description string
|
||||||
|
testContext string // name of the context being modified
|
||||||
config clientcmdapi.Config //initiate kubectl config
|
config clientcmdapi.Config //initiate kubectl config
|
||||||
args []string //kubectl set-context args
|
args []string //kubectl set-context args
|
||||||
flags []string //kubectl set-context flags
|
flags []string //kubectl set-context flags
|
||||||
|
@ -38,6 +39,7 @@ type createContextTest struct {
|
||||||
func TestCreateContext(t *testing.T) {
|
func TestCreateContext(t *testing.T) {
|
||||||
conf := clientcmdapi.Config{}
|
conf := clientcmdapi.Config{}
|
||||||
test := createContextTest{
|
test := createContextTest{
|
||||||
|
testContext: "shaker-context",
|
||||||
description: "Testing for create a new context",
|
description: "Testing for create a new context",
|
||||||
config: conf,
|
config: conf,
|
||||||
args: []string{"shaker-context"},
|
args: []string{"shaker-context"},
|
||||||
|
@ -60,6 +62,7 @@ func TestModifyContext(t *testing.T) {
|
||||||
"shaker-context": {AuthInfo: "blue-user", Cluster: "big-cluster", Namespace: "saw-ns"},
|
"shaker-context": {AuthInfo: "blue-user", Cluster: "big-cluster", Namespace: "saw-ns"},
|
||||||
"not-this": {AuthInfo: "blue-user", Cluster: "big-cluster", Namespace: "saw-ns"}}}
|
"not-this": {AuthInfo: "blue-user", Cluster: "big-cluster", Namespace: "saw-ns"}}}
|
||||||
test := createContextTest{
|
test := createContextTest{
|
||||||
|
testContext: "shaker-context",
|
||||||
description: "Testing for modify a already exist context",
|
description: "Testing for modify a already exist context",
|
||||||
config: conf,
|
config: conf,
|
||||||
args: []string{"shaker-context"},
|
args: []string{"shaker-context"},
|
||||||
|
@ -77,6 +80,32 @@ func TestModifyContext(t *testing.T) {
|
||||||
test.run(t)
|
test.run(t)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestModifyCurrentContext(t *testing.T) {
|
||||||
|
conf := clientcmdapi.Config{
|
||||||
|
CurrentContext: "shaker-context",
|
||||||
|
Contexts: map[string]*clientcmdapi.Context{
|
||||||
|
"shaker-context": {AuthInfo: "blue-user", Cluster: "big-cluster", Namespace: "saw-ns"},
|
||||||
|
"not-this": {AuthInfo: "blue-user", Cluster: "big-cluster", Namespace: "saw-ns"}}}
|
||||||
|
test := createContextTest{
|
||||||
|
testContext: "shaker-context",
|
||||||
|
description: "Testing for modify a current context",
|
||||||
|
config: conf,
|
||||||
|
args: []string{},
|
||||||
|
flags: []string{
|
||||||
|
"--current",
|
||||||
|
"--cluster=cluster_nickname",
|
||||||
|
"--user=user_nickname",
|
||||||
|
"--namespace=namespace",
|
||||||
|
},
|
||||||
|
expected: `Context "shaker-context" modified.` + "\n",
|
||||||
|
expectedConfig: clientcmdapi.Config{
|
||||||
|
Contexts: map[string]*clientcmdapi.Context{
|
||||||
|
"shaker-context": {AuthInfo: "user_nickname", Cluster: "cluster_nickname", Namespace: "namespace"},
|
||||||
|
"not-this": {AuthInfo: "blue-user", Cluster: "big-cluster", Namespace: "saw-ns"}}},
|
||||||
|
}
|
||||||
|
test.run(t)
|
||||||
|
}
|
||||||
|
|
||||||
func (test createContextTest) run(t *testing.T) {
|
func (test createContextTest) run(t *testing.T) {
|
||||||
fakeKubeFile, err := ioutil.TempFile(os.TempDir(), "")
|
fakeKubeFile, err := ioutil.TempFile(os.TempDir(), "")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -108,8 +137,8 @@ func (test createContextTest) run(t *testing.T) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if test.expectedConfig.Contexts != nil {
|
if test.expectedConfig.Contexts != nil {
|
||||||
expectContext := test.expectedConfig.Contexts[test.args[0]]
|
expectContext := test.expectedConfig.Contexts[test.testContext]
|
||||||
actualContext := config.Contexts[test.args[0]]
|
actualContext := config.Contexts[test.testContext]
|
||||||
if expectContext.AuthInfo != actualContext.AuthInfo || expectContext.Cluster != actualContext.Cluster ||
|
if expectContext.AuthInfo != actualContext.AuthInfo || expectContext.Cluster != actualContext.Cluster ||
|
||||||
expectContext.Namespace != actualContext.Namespace {
|
expectContext.Namespace != actualContext.Namespace {
|
||||||
t.Errorf("Fail in %q:\n expected Context %v\n but found %v in kubeconfig\n", test.description, expectContext, actualContext)
|
t.Errorf("Fail in %q:\n expected Context %v\n but found %v in kubeconfig\n", test.description, expectContext, actualContext)
|
||||||
|
|
Loading…
Reference in New Issue