From fc5725e7a3ba0d082b97e3d163a7d0ded53add9a Mon Sep 17 00:00:00 2001 From: Matei-Marius Micu Date: Fri, 1 May 2020 23:56:50 +0300 Subject: [PATCH] Simulate cascading PersistPreRunE calls Because cobra will only call the last PersistPreRunE we need to simulate a cascading run. https://github.com/spf13/cobra/issues/252 We also switches every function to `...E` alternative --- cmd/aws.go | 26 ++++++++++++++++------ cmd/aws_list.go | 4 +++- cmd/aws_update.go | 9 ++++---- cmd/root.go | 55 +++++++++++++++++++++++++++++++++++++---------- 4 files changed, 70 insertions(+), 24 deletions(-) diff --git a/cmd/aws.go b/cmd/aws.go index 574dda2..cd018d2 100644 --- a/cmd/aws.go +++ b/cmd/aws.go @@ -3,7 +3,6 @@ package cmd import ( "fmt" - "os" "github.com/mateimicu/kdiscover/internal" "github.com/spf13/cobra" @@ -20,7 +19,20 @@ func newAWSCommand() *cobra.Command { AWSCommand := &cobra.Command{ Use: "aws", Short: "Work with AWS EKS clusters", - PersistentPreRun: func(cmd *cobra.Command, args []string) { + PersistentPreRunE: func(cmd *cobra.Command, args []string) error { + // Because cobra will only run the last PersistentPreRunE + // we need to search for the root and run the function. + // This is not a robust solution as there may be multiple + // PersistentPreRunE function between the leaf command and root + // also this assumes that this is the root one + // An issue about this https://github.com/spf13/cobra/issues/252 + root := cmd + for ; root.HasParent(); root = root.Parent() { + } + err := root.PersistentPreRunE(cmd, args) + if err != nil { + return err + } log.WithFields(log.Fields{ "partitions": awsPartitions, }).Debug("Search regions for partitions") @@ -31,15 +43,17 @@ func newAWSCommand() *cobra.Command { log.WithFields(log.Fields{ "partitions": awsPartitions, }).Error("Can't find regions for partitions") - os.Exit(errorExitCode) + return fmt.Errorf("Can't find regions for partitions %v", awsPartitions) } log.WithFields(log.Fields{ "regions": awsRegions, }).Info("Founds regions") + return nil }, - Run: func(cmd *cobra.Command, args []string) { + RunE: func(cmd *cobra.Command, args []string) error { cmd.HelpFunc()(cmd, args) + return nil }, } @@ -55,8 +69,6 @@ func newAWSCommand() *cobra.Command { internal.GetDefaultKubeconfigPath(), "Path to the kubeconfig to work with") - AWSCommand.AddCommand(newListCommand()) - AWSCommand.AddCommand(newUpdateCommand()) - + AWSCommand.AddCommand(newListCommand(), newUpdateCommand()) return AWSCommand } diff --git a/cmd/aws_list.go b/cmd/aws_list.go index a9115b0..58a317e 100644 --- a/cmd/aws_list.go +++ b/cmd/aws_list.go @@ -15,7 +15,7 @@ func newListCommand() *cobra.Command { listCommand := &cobra.Command{ Use: "list", Short: "List all EKS Clusters", - Run: func(cmd *cobra.Command, args []string) { + RunE: func(cmd *cobra.Command, args []string) error { remoteEKSClusters := internal.GetEKSClusters(awsRegions) log.Info(remoteEKSClusters) @@ -45,6 +45,8 @@ func newListCommand() *cobra.Command { }) // render it fmt.Println(tw.Render()) + + return nil }, } diff --git a/cmd/aws_update.go b/cmd/aws_update.go index 0501cbc..b426aeb 100644 --- a/cmd/aws_update.go +++ b/cmd/aws_update.go @@ -24,7 +24,7 @@ func newUpdateCommand() *cobra.Command { updateCommand := &cobra.Command{ Use: "update", Short: "Update all EKS Clusters", - Run: func(cmd *cobra.Command, args []string) { + RunE: func(cmd *cobra.Command, args []string) error { fmt.Println(cmd.Short) remoteEKSClusters := internal.GetEKSClusters(awsRegions) log.Info(remoteEKSClusters) @@ -39,15 +39,14 @@ func newUpdateCommand() *cobra.Command { fmt.Printf("Backup kubeconfig to %v\n", bName) err = copy(kubeconfigPath, bName) if err != nil { - fmt.Println(err.Error()) - return + return err } } err := internal.UpdateKubeconfig(remoteEKSClusters, kubeconfigPath, contextName{templateValue: alias}) if err != nil { - fmt.Println(err.Error()) - return + return err } + return nil }, } updateCommand.Flags().BoolVar(&backupKubeconfig, "backup-kubeconfig", true, "Backup cubeconfig before update") diff --git a/cmd/root.go b/cmd/root.go index e2bc78e..eaa8c42 100644 --- a/cmd/root.go +++ b/cmd/root.go @@ -15,32 +15,50 @@ import ( const errorExitCode int = 1 var ( + loggingLevels map[string]log.Level = map[string]log.Level{ + "none": 0, + "panic": log.PanicLevel, + "fatal": log.FatalLevel, + "error": log.ErrorLevel, + "warn": log.WarnLevel, + "info": log.InfoLevel, + "debug": log.DebugLevel, + "trace": log.TraceLevel, + } kubeconfigPath string - debug bool - rootCmd = &cobra.Command{ + logLevel string +) + +func NewRootCommand() *cobra.Command { + rootCmd := &cobra.Command{ Use: "kdiscover", Short: "Discover all EKS clusters on an account.", Long: `kdiscover is a simple utility that can search all regions on an AWS account and try to find all EKS clsuters. It will try to upgrade the kube-config for each cluster.`, - PersistentPreRun: func(cmd *cobra.Command, args []string) { - if debug { - log.SetLevel(log.DebugLevel) - } else { + PersistentPreRunE: func(cmd *cobra.Command, args []string) error { + fmt.Println("root") + if logLevel == "none" { log.SetOutput(ioutil.Discard) + return nil + } + + if v, ok := loggingLevels[logLevel]; ok { + log.SetLevel(v) + return nil } + + return fmt.Errorf("Can't find logging level %v", logLevel) }, - Run: func(cmd *cobra.Command, args []string) { + RunE: func(cmd *cobra.Command, args []string) error { cmd.HelpFunc()(cmd, args) + return nil }, } -) -// Execute will create the tree of commands and will start parsing and execution -func Execute() { - rootCmd.PersistentFlags().BoolVar(&debug, "debug", false, "set log level to debug") + rootCmd.PersistentFlags().StringVar(&logLevel, "log-level", "none", fmt.Sprintf("Set logging lvl. Supported %v", getAllLogglingLevels())) rootCmd.PersistentFlags().StringVar( &kubeconfigPath, @@ -49,9 +67,24 @@ func Execute() { "Path to the kubeconfig to work with") rootCmd.AddCommand(newAWSCommand()) + return rootCmd +} + +// Execute will create the tree of commands and will start parsing and execution +func Execute() { + rootCmd := NewRootCommand() if err := rootCmd.Execute(); err != nil { fmt.Println(err) os.Exit(errorExitCode) } } + +func getAllLogglingLevels() []string { + keys := make([]string, 0, len(loggingLevels)) + for k := range loggingLevels { + keys = append(keys, k) + } + + return keys +}