From 839ee78c0d475c5bfabf04231444ce17db9f8073 Mon Sep 17 00:00:00 2001 From: guoxudong Date: Mon, 2 Dec 2019 19:20:11 +0800 Subject: [PATCH] add interactively cmd --- README.md | 4 ++ cmd/delete.go | 24 ++++++++-- cmd/rename.go | 130 +++++++++++++++++++++++++++++++++++--------------- cmd/switch.go | 77 +++++++++++++++--------------- 4 files changed, 154 insertions(+), 81 deletions(-) diff --git a/README.md b/README.md index db015954..bb80d37f 100644 --- a/README.md +++ b/README.md @@ -129,12 +129,16 @@ kubecm delete my-context ### Delete context ```bash +# Delete the context interactively +kubecm delete # Delete the context kubecm delete my-context ``` ### Rename context ```bash +# Renamed the context interactively +kubecm rename # Renamed dev to test kubecm rename -o dev -n test # Renamed current-context name to dev diff --git a/cmd/delete.go b/cmd/delete.go index cb41f6a7..d1a4e7a3 100644 --- a/cmd/delete.go +++ b/cmd/delete.go @@ -29,12 +29,14 @@ var deleteCmd = &cobra.Command{ Short: "Delete the specified context from the kubeconfig", Long: `Delete the specified context from the kubeconfig`, Example: ` - # Delete the context - kubecm delete my-context +# Delete the context interactively +kubecm delete +# Delete the context +kubecm delete my-context `, Run: func(cmd *cobra.Command, args []string) { + config, err := LoadClientConfig(cfgFile) if len(args) != 0 { - config, err := LoadClientConfig(cfgFile) if err != nil { fmt.Println(err) os.Exit(-1) @@ -44,6 +46,22 @@ var deleteCmd = &cobra.Command{ Error.Println(err) os.Exit(-1) } + } else if len(args) == 0 { + var kubeItems []needle + for key, obj := range config.Contexts { + if key != config.CurrentContext { + kubeItems = append(kubeItems, needle{Name: key, Cluster: obj.Cluster, User: obj.AuthInfo}) + } else { + kubeItems = append([]needle{{Name: key, Cluster: obj.Cluster, User: obj.AuthInfo, Center: "(*)"}}, kubeItems...) + } + } + num := SelectUI(kubeItems, "Select The Delete Kube Context") + kubeName := kubeItems[num].Name + err = deleteContext([]string{kubeName}, config) + if err != nil { + Error.Println(err) + os.Exit(-1) + } } else { fmt.Println("Please enter the context you want to delete.") } diff --git a/cmd/rename.go b/cmd/rename.go index 72a2f1cd..cae19cbd 100644 --- a/cmd/rename.go +++ b/cmd/rename.go @@ -16,6 +16,9 @@ limitations under the License. package cmd import ( + "errors" + "fmt" + "github.com/manifoldco/promptui" "github.com/spf13/cobra" "log" "os" @@ -29,60 +32,89 @@ var renameCmd = &cobra.Command{ Use: "rename", Short: "Rename the contexts of kubeconfig", Long: ` +# Renamed the context interactively +kubecm rename # Renamed dev to test kubecm rename -o dev -n test # Renamed current-context name to dev kubecm rename -n dev -c `, Run: func(cmd *cobra.Command, args []string) { - cover, _ = cmd.Flags().GetBool("cover") - if cover && oldName != "" { - log.Println("parameter `-c` and `-n` cannot be set at the same time") - os.Exit(1) - } else { - config, err := LoadClientConfig(cfgFile) + config, err := LoadClientConfig(cfgFile) + if newName == "" && oldName == "" { + var kubeItems []needle + for key, obj := range config.Contexts { + if key != config.CurrentContext { + kubeItems = append(kubeItems, needle{Name: key, Cluster: obj.Cluster, User: obj.AuthInfo}) + } else { + kubeItems = append([]needle{{Name: key, Cluster: obj.Cluster, User: obj.AuthInfo, Center: "(*)"}}, kubeItems...) + } + } + num := SelectUI(kubeItems, "Select The Rename Kube Context") + kubeName := kubeItems[num].Name + rename := InputStr(kubeName) + fmt.Println(rename) + if obj, ok := config.Contexts[kubeName]; ok { + config.Contexts[rename] = obj + delete(config.Contexts, kubeName) + if config.CurrentContext == kubeName { + config.CurrentContext = rename + } + } + err = ModifyKubeConfig(config) if err != nil { Error.Println(err) - os.Exit(-1) - } - if _, ok := config.Contexts[newName]; ok { - Error.Printf("the name:%s is exit.",newName) - os.Exit(-1) + os.Exit(1) } - if cover { - for key, obj := range config.Contexts { - if current := config.CurrentContext; key == current { - config.Contexts[newName] = obj - delete(config.Contexts, key) - config.CurrentContext = newName - log.Printf("Rename %s to %s", key, newName) - break - } - } + } else { + cover, _ = cmd.Flags().GetBool("cover") + if cover && oldName != "" { + log.Println("parameter `-c` and `-n` cannot be set at the same time") + os.Exit(1) } else { - if obj, ok := config.Contexts[oldName]; ok { - config.Contexts[newName] = obj - delete(config.Contexts, oldName) - if config.CurrentContext == oldName { - config.CurrentContext = newName + if err != nil { + Error.Println(err) + os.Exit(-1) + } + if _, ok := config.Contexts[newName]; ok { + Error.Printf("the name:%s is exit.", newName) + os.Exit(-1) + } + if cover { + for key, obj := range config.Contexts { + if current := config.CurrentContext; key == current { + config.Contexts[newName] = obj + delete(config.Contexts, key) + config.CurrentContext = newName + log.Printf("Rename %s to %s", key, newName) + break + } } } else { - log.Printf("Can not find context: %s", oldName) - err := Formatable(nil) - if err != nil { - Error.Println(err) - os.Exit(1) + if obj, ok := config.Contexts[oldName]; ok { + config.Contexts[newName] = obj + delete(config.Contexts, oldName) + if config.CurrentContext == oldName { + config.CurrentContext = newName + } + } else { + log.Printf("Can not find context: %s", oldName) + err := Formatable(nil) + if err != nil { + Error.Println(err) + os.Exit(1) + } + os.Exit(-1) } - os.Exit(-1) } - } - err = ModifyKubeConfig(config) - if err != nil { - Error.Println(err) - os.Exit(1) + err = ModifyKubeConfig(config) + if err != nil { + Error.Println(err) + os.Exit(1) + } } } - err := Formatable(nil) + err = Formatable(nil) if err != nil { Error.Println(err) os.Exit(1) @@ -95,5 +127,25 @@ func init() { renameCmd.Flags().StringVarP(&oldName, "old", "o", "", "Old context name") renameCmd.Flags().StringVarP(&newName, "new", "n", "", "New context name") renameCmd.Flags().BoolP("cover", "c", false, "") - renameCmd.MarkFlagRequired("new") +} + +func InputStr(name string) string { + validate := func(input string) error { + if len(input) < 3 { + return errors.New("Context name must have more than 3 characters") + } + return nil + } + prompt := promptui.Prompt{ + Label: "Rename", + Validate: validate, + Default: name, + } + result, err := prompt.Run() + + if err != nil { + fmt.Printf("Prompt failed %v\n", err) + os.Exit(-1) + } + return result } diff --git a/cmd/switch.go b/cmd/switch.go index 1c5a4cdf..167418d3 100644 --- a/cmd/switch.go +++ b/cmd/switch.go @@ -33,6 +33,7 @@ type needle struct { Name string Cluster string User string + Center string } // switchCmd represents the switch command @@ -52,59 +53,24 @@ Switch Kube Context interactively. Error.Println(err) os.Exit(-1) } - var kubeItems []needle current := config.CurrentContext for key, obj := range config.Contexts { if key != current { kubeItems = append(kubeItems, needle{Name: key, Cluster: obj.Cluster, User: obj.AuthInfo}) } else { - kubeItems = append([]needle{{Name: key, Cluster: obj.Cluster, User: obj.AuthInfo}}, kubeItems...) + kubeItems = append([]needle{{Name: key, Cluster: obj.Cluster, User: obj.AuthInfo, Center: "(*)"}}, kubeItems...) } } - - templates := &promptui.SelectTemplates{ - Label: "{{ . }}", - Active: "\U0001F63C {{ .Name | red }}", - Inactive: " {{ .Name | cyan }}", - Selected: "\U0001F638 {{ .Name | green }}", - Details: ` ---------- Info ---------- -{{ "Name:" | faint }} {{ .Name }} -{{ "Cluster:" | faint }} {{ .Cluster }} -{{ "User:" | faint }} {{ .User }}`, - } - - searcher := func(input string, index int) bool { - pepper := kubeItems[index] - name := strings.Replace(strings.ToLower(pepper.Name), " ", "", -1) - input = strings.Replace(strings.ToLower(input), " ", "", -1) - - return strings.Contains(name, input) - } - - prompt := promptui.Select{ - Label: "Select Kube Context", - Items: kubeItems, - Templates: templates, - Size: 4, - Searcher: searcher, - } - - i, _, err := prompt.Run() - kubeName := kubeItems[i].Name - if err != nil { - log.Printf("Prompt failed %v\n", err) - return - } + num := SelectUI(kubeItems, "Select Kube Context") + kubeName := kubeItems[num].Name config.CurrentContext = kubeName - err = ModifyKubeConfig(config) if err != nil { Error.Println(err) os.Exit(1) } - log.Printf("Switched to context %s\n", kubeName) + log.Printf("Switched to context 「%s」\n", config.CurrentContext) err = Formatable(nil) if err != nil { Error.Println(err) @@ -157,3 +123,36 @@ func ClusterStatus() error { log.Printf("Cluster check succeeded!\nContains components: %v \n", names) return nil } + +func SelectUI(kubeItems []needle, label string) int { + templates := &promptui.SelectTemplates{ + Label: "{{ . }}", + Active: "\U0001F63C {{ .Name | red }}{{ .Center | red}}", + Inactive: " {{ .Name | cyan }}{{ .Center | red}}", + Selected: "\U0001F638 {{ .Name | green }}", + Details: ` +--------- Info ---------- +{{ "Name:" | faint }} {{ .Name }} +{{ "Cluster:" | faint }} {{ .Cluster }} +{{ "User:" | faint }} {{ .User }}`, + } + searcher := func(input string, index int) bool { + pepper := kubeItems[index] + name := strings.Replace(strings.ToLower(pepper.Name), " ", "", -1) + input = strings.Replace(strings.ToLower(input), " ", "", -1) + return strings.Contains(name, input) + } + prompt := promptui.Select{ + Label: label, + Items: kubeItems, + Templates: templates, + Size: 4, + Searcher: searcher, + } + i, _, err := prompt.Run() + if err != nil { + Error.Printf("Prompt failed %v\n", err) + os.Exit(-1) + } + return i +}