-
Notifications
You must be signed in to change notification settings - Fork 22
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Add global --verbose flag #691
base: main
Are you sure you want to change the base?
Add global --verbose flag #691
Conversation
8065426
to
fa4fae6
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks for this. This may seem like a small change, but it is quite tricky.
Nit: can you fix the commit message? One title line, then an empty line, then a description.
I noticed that the style guide recommends plugins support a --verbose
flag. Could you update that section of the doc?
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") |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think it should be relatively easy to write a unit test to verify the new global flag.
Then you can use that test instead of these printouts 😄
log.SetVerbosity(int32(verbosity)) | ||
|
||
// Set the TANZU_CLI_LOG_LEVEL env with the verbosity value | ||
_ = os.Setenv(log.EnvTanzuCLILogLevel, strconv.Itoa(verbosity)) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
For plugins to consume transparently. Nice!
In the unit test you write, can you check that this variable is set as expected?
43e08d9
to
889c768
Compare
pkg/command/root.go
Outdated
*/ | ||
for i := 0; i < len(args); i++ { | ||
arg := args[i] | ||
if arg == "--verbose" { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It is important to remove this flag and not pass it to plugins that don't support it, or else the plugin execution will fail because it does not know this flag:
$ tz --verbose 5 builder version
[...]
Error: unknown flag: --verbose
Usage:
tanzu builder version [flags]
Flags:
-h, --help help for version
2024-03-12T12:51:45-04:00 [x] : unknown flag: --verbose
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Helm does this for its global flags when it calls plugins.
The code is a bit hard to read so we can discuss together if you want.
This is the code in question: https://github.com/helm/helm/blob/fa47752b892c05697ba54392ccc4fea0ba7397ce/cmd/helm/load_plugins.go#L154
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks @marckhouzam Added logic to verify the plugin flags and filter out verbose flag if plugin doesnt support
// 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 |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
IIUC, we are honouring the --verbose
flag AND we are passing it to the plugins that accept it for processing.
I'm hesitant to do this. Maybe it is ok. I'm not sure. The flag would technically be affecting two behaviours (the CLI and the plugin). We are just assuming the behaviours impacted are the same. Let's discuss.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Current Behaviour
Use Case 1 -> Plugin with --verbose int - Tanzu CLI only processes the --verbose flag of type int and then passes it to plugin if it supports --verbose flag.
Use Case 2 -> Plugin with --verbose bool/string - Tanzu CLI will not process the flag and passes the flag arg directly to plugin
280d857
to
4cc09fe
Compare
and if plugin root command already implement a verbose flag pass the flag value down to plugin
ab57246
to
61a35e0
Compare
@@ -148,6 +153,97 @@ func getCmdForPluginEx(p *PluginInfo, cmdGroupName string) *cobra.Command { | |||
return cmd | |||
} | |||
|
|||
// processArgs retrieves all plugin flags and filters out the verbose flag if the plugin doesn't support it. | |||
// It returns a slice of known arguments and an error if any occurred during the process. | |||
func processArgs(p *PluginInfo, args []string) (known []string, err error) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Nit: the term known
seems contradictory to me. What the CLI "knows" about is the --verbose
flag. Whatever we pass to plugins, arguments or flags, the CLI does not know about: they could be anything.
Instead of known
you can use pluginArgs
known = append(known, args[i]) | ||
} | ||
} else { | ||
// If the plugin does not support the verbose flag, skip it. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I suggest: // If the plugin does not support the verbose flag, also skip its value.
// Iterate over all the arguments. | ||
for i := 0; i < len(args); i++ { | ||
// If the current argument is the verbose flag... | ||
if args[i] == "--verbose" { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We also have to consider the form --verbose=5
, so here we should use HasPrefix
and when skipping the flag value, we should only skip if it is not the --verbose=
case.
return known, err | ||
} | ||
|
||
// Iterate over all the arguments. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If I may suggest a general approach to comments.
There is not as much value in saying the "what" in a comment; what we want is the "why".
So // Iterate over all the arguments.
is "what" is being done. This can be easily understood from the next line of code so has little value.
What would be interesting to put in a comment is the "why" we are doing something.
So, in this case, why are we iterating over all the arguments
?
// It returns a map where the keys are the supported flags and the values are all set to true. | ||
func getPluginFlags(plugin *PluginInfo) (map[string]bool, error) { | ||
// Create a new runner with the plugin's name, installation path, and the help command. | ||
runner := NewRunner(plugin.Name, plugin.InstallationPath, []string{"-h"}) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This only checks the flags on the root plugin command I believe.
What if there is a --verbose
flag under a sub-command?
But I now realize this is probably not something we can do easily since we don't know the plugin sub-commands.
Let's discuss.
// determineVerbosityFromPluginCommandArgs processes the command line arguments for plugin commands. | ||
// It specifically looks for the '--verbose' flag and validates its value. | ||
// The function returns an error if the verbose flag is missing its value or the value is not an integer between 0 and 9. | ||
func determineVerbosityFromPluginCommandArgs(args []string) error { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This logic is similar to what we are doing in plugin_cmd.go
.
I wonder if we could consolidate it in plugin_cmd.go
and call Cobra's ParseFlags
on the --verbose
flag args like helm does.
That way Cobra would fill the verbose
variable instead of us having to do it here.
And we'll be prepared for any other future global flag we may add later on.
@@ -145,6 +145,8 @@ func Test_createAndListDiscoverySources(t *testing.T) { | |||
testSource2 := "localhost:9876/tanzu-cli/plugins/sandbox1:small" | |||
os.Setenv(constants.ConfigVariableAdditionalDiscoveryForTesting, testSource1+","+testSource2) | |||
|
|||
rootCmd, err = NewRootCmd() | |||
assert.Nil(err) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
What broke that we need this?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
we should not merge this until we figure out what to do for existing plugins that may already have such a flag
What this PR does / why we need it
--verbose
of type int with values 0-9 to set the log verbosity level for a tanzu command.--verbose
flag the CLI would send the flag args to plugin.If a plugin implement
--verbose
flag of any type int, bool, string that flag args are passed to plugin by the Tanzu CLIFor Example :- When user runs
Which issue(s) this PR fixes
Fixes #
Describe testing done for PR
For Tanzu CLI Commands with different test log levels
Created test plugins logb with boolean verbose flag, logi with int verbose flag
With existing plugin that doesn't support verbose flag
Invalid verbose flag values
Release note
Additional information
Special notes for your reviewer