From 58a5c4693e56ef6cd4640209ff23299d5f5126a1 Mon Sep 17 00:00:00 2001 From: Yankee <13623913+yankeexe@users.noreply.github.com> Date: Thu, 8 Jul 2021 00:33:32 +0545 Subject: [PATCH] Add interactive delete op (#304) --- cmd/kubectx/flags.go | 6 ++++- cmd/kubectx/fzf.go | 55 ++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 60 insertions(+), 1 deletion(-) diff --git a/cmd/kubectx/flags.go b/cmd/kubectx/flags.go index d7c5df2..060cd1c 100644 --- a/cmd/kubectx/flags.go +++ b/cmd/kubectx/flags.go @@ -42,7 +42,11 @@ func parseArgs(argv []string) Op { if argv[0] == "-d" { if len(argv) == 1 { - return UnsupportedOp{Err: fmt.Errorf("'-d' needs arguments")} + if cmdutil.IsInteractiveMode(os.Stdout) { + return InteractiveDeleteOp{SelfCmd: os.Args[0]} + } else { + return UnsupportedOp{Err: fmt.Errorf("'-d' needs arguments")} + } } return DeleteOp{Contexts: argv[1:]} } diff --git a/cmd/kubectx/fzf.go b/cmd/kubectx/fzf.go index 58b334a..5006129 100644 --- a/cmd/kubectx/fzf.go +++ b/cmd/kubectx/fzf.go @@ -34,6 +34,10 @@ type InteractiveSwitchOp struct { SelfCmd string } +type InteractiveDeleteOp struct { + SelfCmd string +} + func (op InteractiveSwitchOp) Run(_, stderr io.Writer) error { // parse kubeconfig just to see if it can be loaded kc := new(kubeconfig.Kubeconfig).WithLoader(kubeconfig.DefaultLoader) @@ -71,3 +75,54 @@ func (op InteractiveSwitchOp) Run(_, stderr io.Writer) error { printer.Success(stderr, "Switched to context \"%s\".", printer.SuccessColor.Sprint(name)) return nil } + +func (op InteractiveDeleteOp) Run(_, stderr io.Writer) error { + // parse kubeconfig just to see if it can be loaded + kc := new(kubeconfig.Kubeconfig).WithLoader(kubeconfig.DefaultLoader) + if err := kc.Parse(); err != nil { + if cmdutil.IsNotFoundErr(err) { + printer.Warning(stderr, "kubeconfig file not found") + return nil + } + return errors.Wrap(err, "kubeconfig error") + } + kc.Close() + + if len(kc.ContextNames()) == 0 { + return errors.New("no contexts found in config") + } + + cmd := exec.Command("fzf", "--ansi", "--no-preview") + var out bytes.Buffer + cmd.Stdin = os.Stdin + cmd.Stderr = stderr + cmd.Stdout = &out + + cmd.Env = append(os.Environ(), + fmt.Sprintf("FZF_DEFAULT_COMMAND=%s", op.SelfCmd), + fmt.Sprintf("%s=1", env.EnvForceColor)) + if err := cmd.Run(); err != nil { + if _, ok := err.(*exec.ExitError); !ok { + return err + } + } + + choice := strings.TrimSpace(out.String()) + if choice == "" { + return errors.New("you did not choose any of the options") + } + + name, wasActiveContext, err := deleteContext(choice) + if err != nil { + return errors.Wrap(err, "failed to delete context") + } + + if wasActiveContext { + printer.Warning(stderr, "You deleted the current context. Use \"%s\" to select a new context.", + selfName()) + } + + printer.Success(stderr, `Deleted context %s.`, printer.SuccessColor.Sprint(name)) + + return nil +}