feat(kubens): added force flag to switch namespaces even if it doesn't exist

This commit is contained in:
Suleiman Dibirov 2024-01-21 21:16:15 +02:00
parent 4997a261dc
commit 287c2409a6
5 changed files with 34 additions and 12 deletions

View File

@ -46,6 +46,15 @@ Active namespace is "kube-system".
$ kubens - $ kubens -
Context "test" set. Context "test" set.
Active namespace is "default". Active namespace is "default".
# change the active namespace even if it doesn't exist
$ kubens not-found-namespace --force
Context "test" set.
Active namespace is "not-found-namespace".
---
$ kubens not-found-namespace --f
Context "test" set.
Active namespace is "not-found-namespace".
``` ```
If you have [`fzf`](https://github.com/junegunn/fzf) installed, you can also If you have [`fzf`](https://github.com/junegunn/fzf) installed, you can also

View File

@ -33,15 +33,23 @@ func (op UnsupportedOp) Run(_, _ io.Writer) error {
// parseArgs looks at flags (excl. executable name, i.e. argv[0]) // parseArgs looks at flags (excl. executable name, i.e. argv[0])
// and decides which operation should be taken. // and decides which operation should be taken.
func parseArgs(argv []string) Op { func parseArgs(argv []string) Op {
if len(argv) == 0 { n := len(argv)
if n == 0 {
if cmdutil.IsInteractiveMode(os.Stdout) { if cmdutil.IsInteractiveMode(os.Stdout) {
return InteractiveSwitchOp{SelfCmd: os.Args[0]} return InteractiveSwitchOp{SelfCmd: os.Args[0]}
} }
return ListOp{} return ListOp{}
} }
if len(argv) == 1 { if n == 1 || n == 2 {
v := argv[0] v := argv[0]
force := false
if n == 2 {
force = argv[1] == "--force" || argv[1] == "-f"
}
if v == "--help" || v == "-h" { if v == "--help" || v == "-h" {
return HelpOp{} return HelpOp{}
} }
@ -54,7 +62,7 @@ func parseArgs(argv []string) Op {
if strings.HasPrefix(v, "-") && v != "-" { if strings.HasPrefix(v, "-") && v != "-" {
return UnsupportedOp{Err: fmt.Errorf("unsupported option '%s'", v)} return UnsupportedOp{Err: fmt.Errorf("unsupported option '%s'", v)}
} }
return SwitchOp{Target: argv[0]} return SwitchOp{Target: argv[0], Force: force}
} }
return UnsupportedOp{Err: fmt.Errorf("too many arguments")} return UnsupportedOp{Err: fmt.Errorf("too many arguments")}
} }

View File

@ -65,7 +65,7 @@ func (op InteractiveSwitchOp) Run(_, stderr io.Writer) error {
if choice == "" { if choice == "" {
return errors.New("you did not choose any of the options") return errors.New("you did not choose any of the options")
} }
name, err := switchNamespace(kc, choice) name, err := switchNamespace(kc, choice, false)
if err != nil { if err != nil {
return errors.Wrap(err, "failed to switch namespace") return errors.Wrap(err, "failed to switch namespace")
} }

View File

@ -35,6 +35,8 @@ func printUsage(out io.Writer) error {
help := `USAGE: help := `USAGE:
%PROG% : list the namespaces in the current context %PROG% : list the namespaces in the current context
%PROG% <NAME> : change the active namespace of current context %PROG% <NAME> : change the active namespace of current context
%PROG% <NAME> --force : force change the active namespace of current context (even if it doesn't exist)
%PROG% <NAME> --f : force change the active namespace of current context (even if it doesn't exist)
%PROG% - : switch to the previous namespace in this context %PROG% - : switch to the previous namespace in this context
%PROG% -c, --current : show the current namespace %PROG% -c, --current : show the current namespace
%PROG% -h,--help : show this message %PROG% -h,--help : show this message

View File

@ -29,6 +29,7 @@ import (
type SwitchOp struct { type SwitchOp struct {
Target string // '-' for back and forth, or NAME Target string // '-' for back and forth, or NAME
Force bool // force switch even if the namespace doesn't exist
} }
func (s SwitchOp) Run(_, stderr io.Writer) error { func (s SwitchOp) Run(_, stderr io.Writer) error {
@ -38,7 +39,7 @@ func (s SwitchOp) Run(_, stderr io.Writer) error {
return errors.Wrap(err, "kubeconfig error") return errors.Wrap(err, "kubeconfig error")
} }
toNS, err := switchNamespace(kc, s.Target) toNS, err := switchNamespace(kc, s.Target, s.Force)
if err != nil { if err != nil {
return err return err
} }
@ -46,7 +47,7 @@ func (s SwitchOp) Run(_, stderr io.Writer) error {
return err return err
} }
func switchNamespace(kc *kubeconfig.Kubeconfig, ns string) (string, error) { func switchNamespace(kc *kubeconfig.Kubeconfig, ns string, force bool) (string, error) {
ctx := kc.GetCurrentContext() ctx := kc.GetCurrentContext()
if ctx == "" { if ctx == "" {
return "", errors.New("current-context is not set") return "", errors.New("current-context is not set")
@ -69,12 +70,14 @@ func switchNamespace(kc *kubeconfig.Kubeconfig, ns string) (string, error) {
ns = prev ns = prev
} }
ok, err := namespaceExists(kc, ns) if !force {
if err != nil { ok, err := namespaceExists(kc, ns)
return "", errors.Wrap(err, "failed to query if namespace exists (is cluster accessible?)") if err != nil {
} return "", errors.Wrap(err, "failed to query if namespace exists (is cluster accessible?)")
if !ok { }
return "", errors.Errorf("no namespace exists with name \"%s\"", ns) if !ok {
return "", errors.Errorf("no namespace exists with name \"%s\"", ns)
}
} }
if err := kc.SetNamespace(ctx, ns); err != nil { if err := kc.SetNamespace(ctx, ns); err != nil {