Hi,
I already mentioned this here: https://github.com/spf13/cobra/pull/502 and @dixudx properly pointed that environment variables were out of the scope of Cobra.
However, we are using AutomaticEnv and we have a CLI that is using flags that can be set with environment variables. We did a hacky function shown in the previously mentioned issue to support required flags, however, after upgrading cobra, pflag et al we are getting an error because the required flags are not being set. That's not fully true because we were setting them with environment variables.
So, my question is, are we using Cobra and Viper right and this is a bug that should be fixed or are we doing something wrong? In case it's a bug, could you point me out how to help to fix and where it should be fixed? I suppose that here, in viper.
Thanks!
after upgrading cobra, pflag et al we are getting an error because the required flags are not being set.
@agonzalezro Kindly share the error logs here?
Error: Required flag(s) "cassandra_hosts", "cassandra_keyspace" have/has not been set
And the help of the command printed after that error message.
Is this what you mean?
@agonzalezro This means you've markded cassandra_hosts and cassandra_keyspace as required flags, but not setting them in the cli calling.
@dixudx I understand, but as I told before (sorry if I didn't explain myself properly) I was previously setting those flags as environment variables:
CASSANDRA_HOSTS=xxx CASSANDRA_KEYSPACE=yyy ./mycli
But since the flag value isn't set when Cobra reaches your code this fails. It shouldn't fail because the value is there, but in an environment variable that viper AutomaticEnv's understand and will set later on.
My question is more about where to place the fix or this in case it's a bug, and in case it's a bug what should be the proper approach to solve the issue.
I agree with @agonzalezro - the current behaviour is confusing. Flags may be set via environment variables, so required flags should count as "present" if the environment variable is present.
This is difficult to work around cleanly because Viper.IsSet returns true even if the flag is only set via a default value.
are there any clean ways around this issue? any suggested patterns to follow? is anything going to change with the library so that becomes a supported feature?
@trobert2 I switched to kingpin, which I found simpler and doesn't have this issue.
I use the following snippet to use the required flag functionallity with viper environment support:
func init() {
cobra.OnInitialize(func() {
viper.AutomaticEnv()
postInitCommands(root.Commands())
})
}
func postInitCommands(commands []*cobra.Command) {
for _, cmd := range commands {
presetRequiredFlags(cmd)
if cmd.HasSubCommands() {
postInitCommands(cmd.Commands())
}
}
}
func presetRequiredFlags(cmd *cobra.Command) {
viper.BindPFlags(cmd.Flags())
cmd.Flags().VisitAll(func(f *pflag.Flag) {
if viper.IsSet(f.Name) && viper.GetString(f.Name) != "" {
cmd.Flags().Set(f.Name, viper.GetString(f.Name))
}
})
}
Hey all, it's 2020 now. Do we now have a proper fix for this?
Any updates?
Most helpful comment
Hey all, it's 2020 now. Do we now have a proper fix for this?