From 9d95a9f0d2107cd19541593ac9bad4fe705fd731 Mon Sep 17 00:00:00 2001 From: guoxudong Date: Fri, 17 Jan 2020 15:48:56 +0800 Subject: [PATCH] code clean --- cmd/add.go | 84 ++++++++++++----------- cmd/cmd.go | 30 +++++++++ cmd/command.go | 45 +++++++++++++ cmd/completion.go | 50 +++++++------- cmd/delete.go | 86 +++++++++++++----------- cmd/merge.go | 162 +++++++++++++++++++++++--------------------- cmd/rename.go | 168 ++++++++++++++++++++++++---------------------- cmd/root.go | 79 ++++++++++++---------- cmd/switch.go | 102 +++++++++++----------------- cmd/utils.go | 27 ++++++++ cmd/version.go | 50 ++++++-------- main.go | 13 +++- 12 files changed, 508 insertions(+), 388 deletions(-) create mode 100644 cmd/cmd.go create mode 100644 cmd/command.go diff --git a/cmd/add.go b/cmd/add.go index bebeecc1..cab8f491 100644 --- a/cmd/add.go +++ b/cmd/add.go @@ -33,49 +33,55 @@ var file string var name string var cover bool -// addCmd represents the add command -var addCmd = &cobra.Command{ - Use: "add", - Short: "Merge configuration file with $HOME/.kube/config", - Example: addExample(), - Run: func(cmd *cobra.Command, args []string) { - if fileExists(file) { - err := configCheck(file) - if err != nil { - log.Fatal(err) - } - cover, _ = cmd.Flags().GetBool("cover") - config, err := getAddConfig(file) - if err != nil { - Error.Println(err) +type AddCommand struct { + baseCommand +} + +func (ac *AddCommand) Init() { + ac.command = &cobra.Command{ + Use: "add", + Short: "Merge configuration file with $HOME/.kube/config", + Example: addExample(), + RunE: func(cmd *cobra.Command, args []string) error { + return ac.runAdd(cmd, args) + }, + } + ac.command.Flags().StringVarP(&file, "file", "f", "", "Path to merge kubeconfig files") + ac.command.Flags().StringVarP(&name, "name", "n", "", "The name of contexts. if this field is null,it will be named with file name.") + ac.command.Flags().BoolP("cover", "c", false, "Overwrite the original kubeconfig file") + ac.command.MarkFlagRequired("file") +} + +func (ac *AddCommand) runAdd(command *cobra.Command, args []string) error { + if fileExists(file) { + err := configCheck(file) + if err != nil { + log.Fatal(err) + } + cover, _ = ac.command.Flags().GetBool("cover") + config, err := getAddConfig(file) + if err != nil { + Error.Println(err) + } + output := merge2Master(config) + err = WriteConfig(output) + if err != nil { + Error.Println(err.Error()) + } else { + if cover { + ac.command.Printf("「%s」 add successful!", file) + err = Formatable(nil) + } else { + ac.command.Println("generate ./config.yaml") } - output := merge2Master(config) - err = WriteConfig(output) if err != nil { - Error.Println(err.Error()) - } else { - if cover { - cmd.Printf("「%s」 add successful!", file) - err = Formatable(nil) - }else { - cmd.Println("generate ./config.yaml") - } - if err != nil { - log.Fatal(err) - } + log.Fatal(err) } - } else { - log.Fatalf("%s file does not exist", file) } - }, -} - -func init() { - rootCmd.AddCommand(addCmd) - addCmd.Flags().StringVarP(&file, "file", "f", "", "Path to merge kubeconfig files") - addCmd.Flags().StringVarP(&name, "name", "n", "", "The name of contexts. if this field is null,it will be named with file name.") - addCmd.Flags().BoolP("cover", "c", false, "Overwrite the original kubeconfig file") - addCmd.MarkFlagRequired("file") + } else { + log.Fatalf("%s file does not exist", file) + } + return nil } func getAddConfig(kubeconfig string) (*clientcmdapi.Config, error) { diff --git a/cmd/cmd.go b/cmd/cmd.go new file mode 100644 index 00000000..7685e0b3 --- /dev/null +++ b/cmd/cmd.go @@ -0,0 +1,30 @@ +package cmd + +func CmdInit() *baseCommand { + cli := NewCli() + baseCmd := &baseCommand{ + command: cli.rootCmd, + } + // add version command + baseCmd.AddCommand(&VersionCommand{}) + // add add command + addCommand := &AddCommand{} + baseCmd.AddCommand(addCommand) + // add completion command + completionCommand := &CompletionCommand{} + baseCmd.AddCommand(completionCommand) + // add delete command + deleteCommand := &DeleteCommand{} + baseCmd.AddCommand(deleteCommand) + // add merge command + mergeCommand := &MergeCommand{} + baseCmd.AddCommand(mergeCommand) + // add rename command + renameCommand := &RenameCommand{} + baseCmd.AddCommand(renameCommand) + // add switch command + switchCommand := &SwitchCommand{} + baseCmd.AddCommand(switchCommand) + + return baseCmd +} diff --git a/cmd/command.go b/cmd/command.go new file mode 100644 index 00000000..e9e58d4f --- /dev/null +++ b/cmd/command.go @@ -0,0 +1,45 @@ +package cmd + +import ( + "github.com/spf13/cobra" + "log" + "os" +) + +// Command is cli command interface +type Command interface { + // Init command + Init() + + // CobraCmd + CobraCmd() *cobra.Command + +} + +// baseCommand +type baseCommand struct { + command *cobra.Command +} + +func (bc *baseCommand) Init() { +} + +func (bc *baseCommand) CobraCmd() *cobra.Command { + return bc.command +} + +func (bc *baseCommand) Name() string { + return bc.command.Name() +} + +//AddCommand is add child command to the parent command +func (bc *baseCommand) AddCommand(child Command) { + child.Init() + childCmd := child.CobraCmd() + childCmd.PreRun = func(cmd *cobra.Command, args []string) { + Info = log.New(os.Stdout, "Info:", log.Ldate|log.Ltime|log.Lshortfile) + Warning = log.New(os.Stdout, "Warning:", log.Ldate|log.Ltime|log.Lshortfile) + Error = log.New(os.Stderr, "Error:", log.Ldate|log.Ltime|log.Lshortfile) + } + bc.CobraCmd().AddCommand(childCmd) +} diff --git a/cmd/completion.go b/cmd/completion.go index e13c2ede..0166665d 100644 --- a/cmd/completion.go +++ b/cmd/completion.go @@ -21,32 +21,36 @@ import ( "os" ) -// completionCmd represents the completion command -var completionCmd = &cobra.Command{ - Use: "completion", - Short: "Generates bash/zsh completion scripts", - Long: `Output shell completion code for the specified shell (bash or zsh).`, - Example: completionExample(), - Run: func(cmd *cobra.Command, args []string) { - if len(args) == 1 { - complet := args[0] - if complet == "bash" { - rootCmd.GenBashCompletion(os.Stdout) - } else if complet == "zsh" { - zsh.Wrap(rootCmd).GenZshCompletion(os.Stdout) - } else { - Warning.Println("Parameter error! Please input bash or zsh") - } - } else { - Warning.Println("Please input bash or zsh.") - } +type CompletionCommand struct { + baseCommand +} - }, +func (cc *CompletionCommand) Init() { + cc.command = &cobra.Command{ + Use: "completion", + Short: "Generates bash/zsh completion scripts", + Long: `Output shell completion code for the specified shell (bash or zsh).`, + Example: completionExample(), + RunE: func(cmd *cobra.Command, args []string) error { + return cc.runCompletion(cmd, args) + }, + } } -func init() { - rootCmd.AddCommand(completionCmd) - completionCmd.SetArgs([]string{""}) +func (cc *CompletionCommand) runCompletion(command *cobra.Command, args []string) error { + if len(args) == 1 { + complet := args[0] + if complet == "bash" { + cc.command.GenBashCompletion(os.Stdout) + } else if complet == "zsh" { + zsh.Wrap(cc.command).GenZshCompletion(os.Stdout) + } else { + Warning.Println("Parameter error! Please input bash or zsh") + } + } else { + Warning.Println("Please input bash or zsh.") + } + return nil } func completionExample() string { diff --git a/cmd/delete.go b/cmd/delete.go index 41898d3a..f1b1c6db 100644 --- a/cmd/delete.go +++ b/cmd/delete.go @@ -23,51 +23,57 @@ import ( "log" ) -// deleteCmd represents the delete command -var deleteCmd = &cobra.Command{ - Use: "delete", - Short: "Delete the specified context from the kubeconfig", - Long: `Delete the specified context from the kubeconfig`, - Example: deleteExample(), - Run: func(cmd *cobra.Command, args []string) { - config, err := LoadClientConfig(cfgFile) - if len(args) != 0 { - if err != nil { - log.Fatal(err) +type DeleteCommand struct { + baseCommand +} + +func (dc *DeleteCommand) Init() { + dc.command = &cobra.Command{ + Use: "delete", + Short: "Delete the specified context from the kubeconfig", + Long: `Delete the specified context from the kubeconfig`, + Example: deleteExample(), + RunE: func(cmd *cobra.Command, args []string) error { + return dc.runDelete(cmd, args) + }, + } + +} + +func (dc *DeleteCommand) runDelete(command *cobra.Command, args []string) error { + config, err := LoadClientConfig(cfgFile) + if len(args) != 0 { + if err != nil { + log.Fatal(err) + } + err = deleteContext(args, config) + if err != nil { + log.Fatal(err) + } + } 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...) } - err = deleteContext(args, config) + } + num := SelectUI(kubeItems, "Select The Delete Kube Context") + kubeName := kubeItems[num].Name + confirm := BoolUI(fmt.Sprintf("Are you sure you want to delete「%s」?", kubeName)) + if confirm == "True" { + err = deleteContext([]string{kubeName}, config) if err != nil { log.Fatal(err) } - } 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 - confirm := BoolUI(fmt.Sprintf("Are you sure you want to delete「%s」?", kubeName)) - if confirm == "True" { - err = deleteContext([]string{kubeName}, config) - if err != nil { - log.Fatal(err) - } - } else { - cmd.Println("Nothing deleted!") - } } else { - cmd.Println("Please enter the context you want to delete.") + dc.command.Println("Nothing deleted!") } - }, -} - -func init() { - rootCmd.AddCommand(deleteCmd) - deleteCmd.SetArgs([]string{""}) + } else { + dc.command.Println("Please enter the context you want to delete.") + } + return nil } func deleteContext(ctxs []string, config *clientcmdapi.Config) error { @@ -113,4 +119,4 @@ kubecm delete # Delete the context kubecm delete my-context ` -} \ No newline at end of file +} diff --git a/cmd/merge.go b/cmd/merge.go index 8fd6de57..3023d90c 100644 --- a/cmd/merge.go +++ b/cmd/merge.go @@ -29,92 +29,98 @@ import ( "github.com/spf13/cobra" ) +type MergeCommand struct { + baseCommand +} + var folder string -// mergeCmd represents the merge command -var mergeCmd = &cobra.Command{ - Use: "merge", - Short: "Merge the kubeconfig files in the specified directory", - Long: `Merge the kubeconfig files in the specified directory`, - Example: mergeExample(), - Run: func(cmd *cobra.Command, args []string) { - cover, _ = cmd.Flags().GetBool("cover") - files := listFile(folder) - cmd.Printf("Loading kubeconfig file: %v \n", files) - var loop []string - var defaultName string - for _, yaml := range files { - config, err := LoadClientConfig(yaml) - if err != nil { - fmt.Println(err) - os.Exit(-1) - } - name := nameHandle(yaml) - commandLineFile, _ := ioutil.TempFile("", "") - - suffix := HashSuf(config) - username := fmt.Sprintf("user-%v", suffix) - clustername := fmt.Sprintf("cluster-%v", suffix) - - for key, obj := range config.AuthInfos { - config.AuthInfos[username] = obj - delete(config.AuthInfos, key) - break - } - for key, obj := range config.Clusters { - config.Clusters[clustername] = obj - delete(config.Clusters, key) - break - } - for key, obj := range config.Contexts { - obj.AuthInfo = username - obj.Cluster = clustername - config.Contexts[name] = obj - delete(config.Contexts, key) - break - } - configType := clientcmdapi.Config{ - AuthInfos: config.AuthInfos, - Clusters: config.Clusters, - Contexts: config.Contexts, - } - _ = clientcmd.WriteToFile(configType, commandLineFile.Name()) - loop = append(loop, commandLineFile.Name()) - cmd.Printf("Context Add: %s \n", name) - defaultName = name - } - loadingRules := &clientcmd.ClientConfigLoadingRules{ - Precedence: loop, +func (mc *MergeCommand) Init() { + mc.command = &cobra.Command{ + Use: "merge", + Short: "Merge the kubeconfig files in the specified directory", + Long: `Merge the kubeconfig files in the specified directory`, + Example: mergeExample(), + RunE: func(cmd *cobra.Command, args []string) error { + return mc.runMerge(cmd, args) + }, + } + mc.command.Flags().StringVarP(&folder, "folder", "f", "", "Kubeconfig folder") + mc.command.Flags().BoolP("cover", "c", false, "Overwrite the original kubeconfig file") + mc.command.MarkFlagRequired("folder") +} + +func (mc MergeCommand) runMerge(command *cobra.Command, args []string) error { + cover, _ = mc.command.Flags().GetBool("cover") + files := listFile(folder) + mc.command.Printf("Loading kubeconfig file: %v \n", files) + var loop []string + var defaultName string + for _, yaml := range files { + config, err := LoadClientConfig(yaml) + if err != nil { + fmt.Println(err) + os.Exit(-1) } - mergedConfig, err := loadingRules.Load() - if mergedConfig != nil { - mergedConfig.CurrentContext = defaultName + name := nameHandle(yaml) + commandLineFile, _ := ioutil.TempFile("", "") + + suffix := HashSuf(config) + username := fmt.Sprintf("user-%v", suffix) + clustername := fmt.Sprintf("cluster-%v", suffix) + + for key, obj := range config.AuthInfos { + config.AuthInfos[username] = obj + delete(config.AuthInfos, key) + break } - json, err := runtime.Encode(clientcmdlatest.Codec, mergedConfig) - if err != nil { - Error.Printf("Unexpected error: %v", err) + for key, obj := range config.Clusters { + config.Clusters[clustername] = obj + delete(config.Clusters, key) + break } - output, err := yaml.JSONToYAML(json) - if err != nil { - Error.Printf("Unexpected error: %v", err) + for key, obj := range config.Contexts { + obj.AuthInfo = username + obj.Cluster = clustername + config.Contexts[name] = obj + delete(config.Contexts, key) + break } - - for _, name := range loop { - defer os.Remove(name) + configType := clientcmdapi.Config{ + AuthInfos: config.AuthInfos, + Clusters: config.Clusters, + Contexts: config.Contexts, } + _ = clientcmd.WriteToFile(configType, commandLineFile.Name()) + loop = append(loop, commandLineFile.Name()) + mc.command.Printf("Context Add: %s \n", name) + defaultName = name + } + loadingRules := &clientcmd.ClientConfigLoadingRules{ + Precedence: loop, + } + mergedConfig, err := loadingRules.Load() + if mergedConfig != nil { + mergedConfig.CurrentContext = defaultName + } + json, err := runtime.Encode(clientcmdlatest.Codec, mergedConfig) + if err != nil { + Error.Printf("Unexpected error: %v", err) + } + output, err := yaml.JSONToYAML(json) + if err != nil { + Error.Printf("Unexpected error: %v", err) + } - err = WriteConfig(output) - if err != nil { - Error.Println(err.Error()) - } - }, -} + for _, name := range loop { + defer os.Remove(name) + } -func init() { - rootCmd.AddCommand(mergeCmd) - mergeCmd.Flags().StringVarP(&folder, "folder", "f", "", "Kubeconfig folder") - mergeCmd.Flags().BoolP("cover", "c", false, "Overwrite the original kubeconfig file") - mergeCmd.MarkFlagRequired("folder") + err = WriteConfig(output) + if err != nil { + Error.Println(err.Error()) + } + return nil } func listFile(folder string) []string { @@ -144,4 +150,4 @@ kubecm merge -f test # Merge kubeconfig in the test directory and overwrite the original kubeconfig file kubecm merge -f test -c ` -} \ No newline at end of file +} diff --git a/cmd/rename.go b/cmd/rename.go index 7225f2c7..914ca336 100644 --- a/cmd/rename.go +++ b/cmd/rename.go @@ -23,102 +23,108 @@ import ( "os" ) +type RenameCommand struct { + baseCommand +} + var oldName string var newName string -// renameCmd represents the rename command -var renameCmd = &cobra.Command{ - Use: "rename", - Short: "Rename the contexts of kubeconfig", - Long: renameExample(), - Run: func(cmd *cobra.Command, args []string) { - 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) - if rename != kubeName { - if _, ok := config.Contexts[rename]; ok { - log.Fatal("Name: %s already exists", rename) - } else { - 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 { - log.Fatal(err) - } - } +func (rc *RenameCommand) Init() { + rc.command = &cobra.Command{ + Use: "rename", + Short: "Rename the contexts of kubeconfig", + Long: renameExample(), + RunE: func(cmd *cobra.Command, args []string) error { + return rc.runRename(cmd, args) + }, + } + rc.command.Flags().StringVarP(&oldName, "old", "o", "", "Old context name") + rc.command.Flags().StringVarP(&newName, "new", "n", "", "New context name") + rc.command.Flags().BoolP("cover", "c", false, "") +} + +func (rc *RenameCommand) runRename(command *cobra.Command, args []string) error { + 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 { - log.Fatalf("No name: %s changes", rename) + kubeItems = append([]needle{{Name: key, Cluster: obj.Cluster, User: obj.AuthInfo, Center: "(*)"}}, kubeItems...) } - } else { - cover, _ = cmd.Flags().GetBool("cover") - if cover && oldName != "" { - log.Fatalln("parameter `-c` and `-n` cannot be set at the same time") + } + num := SelectUI(kubeItems, "Select The Rename Kube Context") + kubeName := kubeItems[num].Name + rename := InputStr(kubeName) + if rename != kubeName { + if _, ok := config.Contexts[rename]; ok { + log.Fatal("Name: %s already exists", rename) } else { + 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 { log.Fatal(err) } - if _, ok := config.Contexts[newName]; ok { - log.Fatalf("the name:%s is exit.", newName) + } + } else { + log.Fatalf("No name: %s changes", rename) + } + } else { + cover, _ = rc.command.Flags().GetBool("cover") + if cover && oldName != "" { + log.Fatalln("parameter `-c` and `-n` cannot be set at the same time") + } else { + if err != nil { + log.Fatal(err) + } + if _, ok := config.Contexts[newName]; ok { + log.Fatalf("the name:%s is exit.", newName) + } + 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 + rc.command.Printf("Rename %s to %s", key, newName) + break + } } - 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 - cmd.Printf("Rename %s to %s", key, newName) - break - } + } else { + if obj, ok := config.Contexts[oldName]; ok { + config.Contexts[newName] = obj + delete(config.Contexts, oldName) + if config.CurrentContext == oldName { + config.CurrentContext = newName } } else { - if obj, ok := config.Contexts[oldName]; ok { - config.Contexts[newName] = obj - delete(config.Contexts, oldName) - if config.CurrentContext == oldName { - config.CurrentContext = newName - } - } else { - cmd.Printf("Can not find context: %s", oldName) - err := Formatable(nil) - if err != nil { - log.Fatal(err) - } - os.Exit(-1) + rc.command.Printf("Can not find context: %s", oldName) + err := Formatable(nil) + if err != nil { + log.Fatal(err) } - } - err = ModifyKubeConfig(config) - if err != nil { - log.Fatal(err) + os.Exit(-1) } } + err = ModifyKubeConfig(config) + if err != nil { + log.Fatal(err) + } } - err = Formatable(nil) - if err != nil { - log.Fatal(err) - } - }, -} - -func init() { - rootCmd.AddCommand(renameCmd) - renameCmd.Flags().StringVarP(&oldName, "old", "o", "", "Old context name") - renameCmd.Flags().StringVarP(&newName, "new", "n", "", "New context name") - renameCmd.Flags().BoolP("cover", "c", false, "") + } + err = Formatable(nil) + if err != nil { + log.Fatal(err) + } + return nil } func InputStr(name string) string { @@ -150,4 +156,4 @@ kubecm rename -o dev -n test # Renamed current-context name to dev kubecm rename -n dev -c ` -} \ No newline at end of file +} diff --git a/cmd/root.go b/cmd/root.go index f9aa7cfb..3e7a5a6f 100644 --- a/cmd/root.go +++ b/cmd/root.go @@ -31,10 +31,17 @@ var ( Error *log.Logger ) -var rootCmd = &cobra.Command{ - Use: "kubecm", - Short: "KubeConfig Manager.", - Long: ` +type Cli struct { + rootCmd *cobra.Command +} + +//NewCli returns the cli instance used to register and execute command +func NewCli() *Cli { + cli := &Cli{ + rootCmd: &cobra.Command{ + Use: "kubecm", + Short: "KubeConfig Manager.", + Long: ` KubeConfig Manager _ _ | | ___ _| |__ ___ ___ _ __ ___ @@ -44,42 +51,44 @@ KubeConfig Manager Find more information at: https://github.com/sunny0826/kubecm `, - Example: cliExample(), - Run: func(cmd *cobra.Command, args []string) { - if len(args) == 0 { - err := Formatable(nil) - if err != nil { - log.Fatal(err) - } - } else { - err := Formatable(args) - if err != nil { - log.Fatal(err) - } - } - err := ClusterStatus() - if err != nil { - log.Fatalf("Cluster check failure!\n%v", err) - } - }, + Example: cliExample(), + Run: func(cmd *cobra.Command, args []string) { + runCli(cmd, args) + }, + }, + } + cli.rootCmd.SetOutput(os.Stdout) + cli.setFlags() + return cli } -func Execute() { - if err := rootCmd.Execute(); err != nil { - log.Fatal(err) - } +func (cli *Cli) setFlags() { + kubeconfig := flag.String("kubeconfig", filepath.Join(homeDir(), ".kube", "config"), "(optional) absolute path to the kubeconfig file") + flags := cli.rootCmd.PersistentFlags() + flags.StringVar(&cfgFile, "config", *kubeconfig, "config.yaml file (default is $HOME/.kubecm.yaml)") } -func init() { - cobra.OnInitialize(initConfig) - Info = log.New(os.Stdout, "Info:", log.Ldate|log.Ltime|log.Lshortfile) - Warning = log.New(os.Stdout, "Warning:", log.Ldate|log.Ltime|log.Lshortfile) - Error = log.New(os.Stderr, "Error:", log.Ldate|log.Ltime|log.Lshortfile) +//Run command +func (cli *Cli) Run() error { + return cli.rootCmd.Execute() } -func initConfig() { - kubeconfig := flag.String("kubeconfig", filepath.Join(homeDir(), ".kube", "config"), "(optional) absolute path to the kubeconfig file") - rootCmd.Flags().StringVar(&cfgFile, "config", *kubeconfig, "config.yaml file (default is $HOME/.kubecm.yaml)") +func runCli(cmd *cobra.Command, args []string) { + if len(args) == 0 { + err := Formatable(nil) + if err != nil { + log.Fatal(err) + } + } else { + err := Formatable(args) + if err != nil { + log.Fatal(err) + } + } + err := ClusterStatus() + if err != nil { + log.Fatalf("Cluster check failure!\n%v", err) + } } func homeDir() string { @@ -94,4 +103,4 @@ func cliExample() string { # List all the contexts in your kubeconfig file kubecm ` -} \ No newline at end of file +} diff --git a/cmd/switch.go b/cmd/switch.go index 47993f66..abb9d097 100644 --- a/cmd/switch.go +++ b/cmd/switch.go @@ -16,17 +16,18 @@ limitations under the License. package cmd import ( - "fmt" "github.com/spf13/cobra" "io/ioutil" - metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" - "k8s.io/client-go/kubernetes" "k8s.io/client-go/tools/clientcmd" clientcmdapi "k8s.io/client-go/tools/clientcmd/api" "log" "os" ) +type SwitchCommand struct { + baseCommand +} + type needle struct { Name string Cluster string @@ -34,45 +35,47 @@ type needle struct { Center string } -// switchCmd represents the switch command -var switchCmd = &cobra.Command{ - Use: "switch", - Short: "Switch Kube Context interactively.", - Long: ` +func (sc *SwitchCommand) Init() { + sc.command = &cobra.Command{ + Use: "switch", + Short: "Switch Kube Context interactively.", + Long: ` Switch Kube Context interactively. `, - Example: switchExample(), - Run: func(cmd *cobra.Command, args []string) { - config, err := LoadClientConfig(cfgFile) - if err != nil { - log.Fatal(err) - } - 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, Center: "(*)"}}, kubeItems...) - } - } - num := SelectUI(kubeItems, "Select Kube Context") - kubeName := kubeItems[num].Name - config.CurrentContext = kubeName - err = ModifyKubeConfig(config) - if err != nil { - log.Fatal(err) - } - cmd.Printf("Switched to context 「%s」\n", config.CurrentContext) - err = Formatable(nil) - if err != nil { - log.Fatal(err) - } - }, + Example: switchExample(), + RunE: func(cmd *cobra.Command, args []string) error { + return sc.runSwitch(cmd, args) + }, + } } -func init() { - rootCmd.AddCommand(switchCmd) +func (sc *SwitchCommand) runSwitch(command *cobra.Command, args []string) error { + config, err := LoadClientConfig(cfgFile) + if err != nil { + log.Fatal(err) + } + 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, Center: "(*)"}}, kubeItems...) + } + } + num := SelectUI(kubeItems, "Select Kube Context") + kubeName := kubeItems[num].Name + config.CurrentContext = kubeName + err = ModifyKubeConfig(config) + if err != nil { + log.Fatal(err) + } + sc.command.Printf("Switched to context 「%s」\n", config.CurrentContext) + err = Formatable(nil) + if err != nil { + log.Fatal(err) + } + return nil } func ModifyKubeConfig(config *clientcmdapi.Config) error { @@ -93,29 +96,6 @@ func ModifyKubeConfig(config *clientcmdapi.Config) error { return nil } -func ClusterStatus() error { - config, err := clientcmd.BuildConfigFromFlags("", cfgFile) - if err != nil { - return fmt.Errorf(err.Error()) - } - - clientset, err := kubernetes.NewForConfig(config) - if err != nil { - return fmt.Errorf(err.Error()) - } - - cus, err := clientset.CoreV1().ComponentStatuses().List(metav1.ListOptions{}) - if err != nil { - return fmt.Errorf(err.Error()) - } - var names []string - for _, k := range cus.Items { - names = append(names, k.Name) - } - log.Printf("Cluster check succeeded!\nContains components: %v \n", names) - return nil -} - func switchExample() string { return ` # Switch Kube Context interactively diff --git a/cmd/utils.go b/cmd/utils.go index 0de7c442..5649bb23 100644 --- a/cmd/utils.go +++ b/cmd/utils.go @@ -20,7 +20,10 @@ import ( "fmt" "github.com/bndr/gotabulate" "github.com/manifoldco/promptui" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/runtime" + "k8s.io/client-go/kubernetes" + "k8s.io/client-go/tools/clientcmd" clientcmdapi "k8s.io/client-go/tools/clientcmd/api" clientcmdlatest "k8s.io/client-go/tools/clientcmd/api/latest" "log" @@ -147,4 +150,28 @@ func SelectUI(kubeItems []needle, label string) int { log.Fatalf("Prompt failed %v\n", err) } return i +} + +// ClusterStatus output cluster status +func ClusterStatus() error { + config, err := clientcmd.BuildConfigFromFlags("", cfgFile) + if err != nil { + return fmt.Errorf(err.Error()) + } + + clientset, err := kubernetes.NewForConfig(config) + if err != nil { + return fmt.Errorf(err.Error()) + } + + cus, err := clientset.CoreV1().ComponentStatuses().List(metav1.ListOptions{}) + if err != nil { + return fmt.Errorf(err.Error()) + } + var names []string + for _, k := range cus.Items { + names = append(names, k.Name) + } + log.Printf("Cluster check succeeded!\nContains components: %v \n", names) + return nil } \ No newline at end of file diff --git a/cmd/version.go b/cmd/version.go index 7ed32c6f..3ae63780 100644 --- a/cmd/version.go +++ b/cmd/version.go @@ -16,21 +16,21 @@ limitations under the License. package cmd import ( - "fmt" - "io" - "os" "runtime" "github.com/spf13/cobra" ) +type VersionCommand struct { + baseCommand +} + var ( kubecmVersion = "unknown" - goos = runtime.GOOS - goarch = runtime.GOARCH - gitCommit = "$Format:%H$" // sha1 from git, output of $(git rev-parse HEAD) - - buildDate = "1970-01-01T00:00:00Z" // build date in ISO8601 format, output of $(date -u +'%Y-%m-%dT%H:%M:%SZ') + goos = runtime.GOOS + goarch = runtime.GOARCH + gitCommit = "$Format:%H$" // sha1 from git, output of $(git rev-parse HEAD) + buildDate = "1970-01-01T00:00:00Z" // build date in ISO8601 format, output of $(date -u +'%Y-%m-%dT%H:%M:%SZ') ) // version returns the version of kustomize. @@ -47,9 +47,19 @@ type version struct { GoArch string `json:"goArch"` } -func init() { - stdOut := os.Stdout - rootCmd.AddCommand(Version(stdOut)) +func (vc *VersionCommand) Init() { + vc.command = &cobra.Command{ + Use: "version", + Short: "Prints the kubecm version", + Example: "kubecm version", + Run: func(cmd *cobra.Command, args []string) { + cmd.Printf("Version: %s\n", getVersion().kubecmVersion) + cmd.Printf("GitCommit: %s\n", getVersion().GitCommit) + cmd.Printf("BuildDate: %s\n", getVersion().BuildDate) + cmd.Printf("GoOs: %s\n", getVersion().GoOs) + cmd.Printf("GoArch: %s\n", getVersion().GoArch) + }, + } } // getVersion returns version. @@ -62,21 +72,3 @@ func getVersion() version { goarch, } } - -// Print prints version. -func (v version) Print(w io.Writer) { - fmt.Fprintf(w, "Version: %+v\n", v) -} - -// Version represents the version command -func Version(w io.Writer) *cobra.Command { - return &cobra.Command{ - Use: "version", - Short: "Prints the kubecm version", - Example: "kubecm version", - Run: func(cmd *cobra.Command, args []string) { - getVersion().Print(w) - }, - } -} - diff --git a/main.go b/main.go index d6aed7d4..8601cc3a 100644 --- a/main.go +++ b/main.go @@ -15,8 +15,17 @@ limitations under the License. */ package main -import "github.com/sunny0826/kubecm/cmd" +import ( + "fmt" + "os" + + "github.com/sunny0826/kubecm/cmd" +) func main() { - cmd.Execute() + baseCommand := cmd.CmdInit() + if err := baseCommand.CobraCmd().Execute(); err != nil { + _, _ = fmt.Fprintf(os.Stderr, "%s\n", err.Error()) + os.Exit(1) + } }