Hi,
I maybe mistaken here but i'm currently under the assumption that viper takes care of the order of precedence when it comes to where the value comes from: config file -> env var -> flag.
I'm finding that the default value that is used in the flag always overrides the env var. To overcome this i have to set the default value to be empty and then i have to check to see if the value is empty before using the env var value. Is this correct?
Here's the test code:
package cmd
import (
"fmt"
"os"
"github.com/mitchellh/go-homedir"
"github.com/spf13/cobra"
"github.com/spf13/viper"
)
var defaultConfigFilename = "abc-config"
var defaultConfigExt = "json"
var defaultLogPath = "/var/logs/abc/"
func NewRootCommand() *cobra.Command {
configFile := ""
rootCmd := &cobra.Command{
Use: "test",
Short: "Test",
Long: `Test`,
Run: func(cmd *cobra.Command, args []string) {
fmt.Println(configFile)
},
}
initConfig := func() {
if configFile == "" {
// Try and get from env
configFile = viper.GetString("configFile")
}
// Don't forget to read config either from configFile or from home directory!
if configFile != "" {
// Use config file from the flag.
viper.SetConfigFile(configFile)
} else {
// Find home directory.
home, err := homedir.Dir()
if err != nil {
fmt.Println(err)
os.Exit(1)
}
// Search config in home directory with name "abc-config" (without extension).
viper.AddConfigPath(home)
viper.SetConfigName(defaultConfigFilename)
}
if err := viper.ReadInConfig(); err != nil {
fmt.Println("Can't read config:", err)
os.Exit(1)
}
}
cobra.OnInitialize(initConfig)
viper.SetEnvPrefix("ABC")
viper.AutomaticEnv()
rootCmd.Flags().StringVarP(&configFile, "configFile", "c", "", fmt.Sprintf("config file (default is ~/%s.%s)", defaultConfigFilename, defaultConfigExt))
viper.BindPFlag("configFile", rootCmd.Flags().Lookup("configFile"))
return rootCmd
}
Thanks,
Ankur
Yup, currently you can't really do anything else, but not define a default value for flags.
Thank you for the quick response. I'll close this ticket since it's known. It might be worth mentioning in the readme... i guess i could change it and open a pull request too :)
Why is this a known accepted behavior?!
Cobra integration with Viper is broken and can't be used with environment variable - it should be in big bold letters on the README
I've been using viper and cobra together on multiple CLIs for a couple years now and with a bit of custom code you can get them to integrate such that the config stacks:
flags > environment variables > configuration files > flag defaults
I wrote a sample working app with tests that demonstrates how to integrate them and a blog post that explains it in a bit more detail. Apologies if I am misunderstanding the OP (if I did, let me know and I'll remove/edit this), but hopefully the sample helps them out.
@carolynvs Great works! Thanks!
Most helpful comment
Why is this a known accepted behavior?!
Cobra integration with Viper is broken and can't be used with environment variable - it should be in big bold letters on the README