diff --git a/docs/plugindev/style_guide.md b/docs/plugindev/style_guide.md index 10602f48a..77bdb2177 100644 --- a/docs/plugindev/style_guide.md +++ b/docs/plugindev/style_guide.md @@ -208,9 +208,6 @@ Available input components: ### Feedback principles -Useful for everyone, critical to the usability of screen-readers and automation -Support verbosity flags (`-v`, `--verbose`). - `--format` to define preferred output * Useful for humans and machine users, ie table, value, json, csv, yaml, etc diff --git a/pkg/command/root.go b/pkg/command/root.go index 87243dc0d..ef4070a9c 100644 --- a/pkg/command/root.go +++ b/pkg/command/root.go @@ -33,6 +33,9 @@ import ( "github.com/vmware-tanzu/tanzu-plugin-runtime/plugin" ) +// verbose flag to set the log level +var verbose int + // NewRootCmd creates a root command. func NewRootCmd() (*cobra.Command, error) { //nolint: gocyclo,funlen var rootCmd = newRootCmd() @@ -42,6 +45,9 @@ func NewRootCmd() (*cobra.Command, error) { //nolint: gocyclo,funlen // Configure defined environment variables found in the config file cliconfig.ConfigureEnvVariables() + // Initialize the global verbose flag to set the log level verbosity (acceptable values 1 - 9) + rootCmd.PersistentFlags().IntVar(&verbose, "verbose", 0, "number for the log level verbosity(acceptable values 1 - 9)") + rootCmd.AddCommand( newVersionCmd(), newPluginCmd(), @@ -58,6 +64,7 @@ func NewRootCmd() (*cobra.Command, error) { //nolint: gocyclo,funlen newCEIPParticipationCmd(), newGenAllDocsCmd(), ) + if _, err := ensureCLIInstanceID(); err != nil { return nil, errors.Wrap(err, "failed to ensure CLI ID") } @@ -240,8 +247,40 @@ func newRootCmd() *cobra.Command { // silencing usage for now as we are getting double usage from plugins on errors SilenceUsage: true, PersistentPreRunE: func(cmd *cobra.Command, args []string) error { - // Sets the verbosity of the logger if TANZU_CLI_LOG_LEVEL is set - setLoggerVerbosity() + fmt.Println(args, "args", verbose) + // Validate the verbose flag + if verbose < 0 { + log.Errorf("Invalid value for verbose flag. It should be 0 or greater") + os.Exit(1) + } + + // For CLI commands: Default the verbose value to -1 If the flag is not set by user + // For Plugin commands: This won't be executed since flags are not parsed by cli but send to plugin as args + if !cmd.Flags().Changed("verbose") { + verbose = -1 + } + + /** + Manually parse the flags when plugin command is triggered + 1. For CLI commands; all flags have been parsed and removed from the list of args and this loop will not run + 2. For Plugin commands; Since CLI doesn't parse args and sends all args to plugin this loop will run to verify if verbose flag is set by the user and then passes to plugin. + */ + parseFlagsForPluginCommands(args) + + log.Infof("verbose %v", verbose) + + // Sets the verbosity of the logger + setLoggerVerbosity(verbose) + + //TODO: Remove test logs + log.Info("I am level default") + log.V(0).Info("I am level 0") + log.V(1).Info("I am level 1") + log.V(2).Info("I am level 2") + log.V(3).Info("I am level 3") + log.V(4).Info("I am level 4") + log.V(5).Info("I am level 5") + log.V(6).Info("I am level 6") // Ensure mutual exclusion in current contexts just in case if any plugins with old // plugin-runtime sets k8s context as current when tanzu context is already set as current @@ -290,14 +329,49 @@ func newRootCmd() *cobra.Command { return rootCmd } +func parseFlagsForPluginCommands(args []string) { + for i := 0; i < len(args); i++ { + arg := args[i] + if arg == "--verbose" { + if i+1 < len(args) { + nextArg := args[i+1] + // Check if the next argument is another flag + if strings.HasPrefix(nextArg, "-") { + log.Errorf("Missing value for verbose flag") + os.Exit(1) + } + // Try to convert the next argument to an integer + // If it's not an integer, CLI doesn't parse the verbose flag + if v, err := strconv.Atoi(nextArg); err == nil { + verbose = v + } + // Skip the next argument + i++ + } else { + log.Errorf("Missing value for verbose flag") + os.Exit(1) + } + } + } +} + // setLoggerVerbosity sets the verbosity of the logger if TANZU_CLI_LOG_LEVEL is set -func setLoggerVerbosity() { - // Configure the log level if env variable TANZU_CLI_LOG_LEVEL is set - logLevel := os.Getenv(log.EnvTanzuCLILogLevel) - if logLevel != "" { - logValue, err := strconv.ParseInt(logLevel, 10, 32) - if err == nil { - log.SetVerbosity(int32(logValue)) +func setLoggerVerbosity(verbosity int) { + // If verbose global flag is passed set the log level verbosity if not then check if env variable TANZU_CLI_LOG_LEVEL is set + if verbosity >= 0 { + // Set the log level verbosity with the verbosity value + log.SetVerbosity(int32(verbosity)) + + // Set the TANZU_CLI_LOG_LEVEL env with the verbosity value + _ = os.Setenv(log.EnvTanzuCLILogLevel, strconv.Itoa(verbosity)) + } else { + // Configure the log level if env variable TANZU_CLI_LOG_LEVEL is set + logLevel := os.Getenv(log.EnvTanzuCLILogLevel) + if logLevel != "" { + logValue, err := strconv.ParseInt(logLevel, 10, 32) + if err == nil { + log.SetVerbosity(int32(logValue)) + } } } }