I didn't see this in the README about the usage of the config file aside from the flag option of it being there. Does Cobra automatically read the config file from the location specified in the root.go, or is that for us to read and parse on our own?
Does Cobra automatically read the config file from the location specified in the root.go
Yes
These lines read config with name .cobra.yaml/.cobra.toml/.cobra.json from the home directory:
if err := viper.ReadInConfig(); err == nil {
fmt.Println("Using config file:", viper.ConfigFileUsed())
}
I was going to start a similar issue because there is no explanation of how to go about using the config file.
How do I call a command from the config?
How do I set a flag from the config?
Which things get nested or indented in the YAML?
I am trying to figure out how to do all of these right now
How do I call a command from the config?
Sorry, but can you explain better, what do you mean?
How do I set a flag from the config?
From README
You will additionally define flags and handle configuration in your init() function.
for example cmd/root.go:
func init() {
cobra.OnInitialize(initConfig)
RootCmd.PersistentFlags().StringVar(&cfgFile, "config", "", "config file (default is $HOME/.cobra.yaml)")
RootCmd.PersistentFlags().StringVarP(&projectBase, "projectbase", "b", "", "base project directory eg. github.com/spf13/")
RootCmd.PersistentFlags().StringP("author", "a", "YOUR NAME", "Author name for copyright attribution")
RootCmd.PersistentFlags().StringVarP(&userLicense, "license", "l", "", "Name of license for the project (can provide `licensetext` in config)")
RootCmd.PersistentFlags().Bool("viper", true, "Use Viper for configuration")
viper.BindPFlag("author", RootCmd.PersistentFlags().Lookup("author"))
viper.BindPFlag("projectbase", RootCmd.PersistentFlags().Lookup("projectbase"))
viper.BindPFlag("useViper", RootCmd.PersistentFlags().Lookup("viper"))
viper.SetDefault("author", "NAME HERE <EMAIL ADDRESS>")
viper.SetDefault("license", "apache")
}
viper.BindPFlag binds flag with config.
Which things get nested or indented in the YAML?
Answer is same as for first question.
@bogem, I see that the config is being parsed there, but the problem I am having is that I don't know what the config file is capable of doing. From playing with it I would suspect that it is only for declaring flag values, but I am left wondering:
config declares some commands and flags so that when I run...
./cli-tool
it parses the config and runs as
./cli-tool cmd1 --flag foo
What the readme is saying now might be clear to those who are very familiar with the code, but confusing to me when I am first looking at it. I think all of the main features (config file being one of them) should have a direct example rather than an indirect example through code which basically says "config is here, deal with it."
I am left with the questions...
init()?I have an idea of how to present the information, I will make a PR to show you after I hear back from this comment
config declares some commands and flags so that when I run...
Config file doesn't declare any commands. Cobra declares commands and flags and viper (config) reads the values from config and sets them to binded flags.
is this example showcasing the extent of the possibilities with the config file?
Not all possibilities. More about viper.
After reading the Viper README and looking at the first comment @bogem posted, it seems the configuration file is loaded into viper and is used as viper.GetString or whatever the option is set to.
https://github.com/spf13/viper/blob/master/README.md#getting-values-from-viper
This has sufficiently answer my question. Thank you @bogem
I think I have figured out what is confusing about this now...
viper.BindPFlag() is called, you should retrieve the flag value by calling viper.Get[type]() methodsPersistentFlag().[type]Var() method then the variable which had its value set by the RootCmd.PersistentFlags() method call will not have its value changed, and must be reset elsewhere if that variable is still to be used.Do I have the thought process correct? I can suggest some changes to the docs if my thinking is on track...
If I take the example from the readme...
func init() {
cobra.OnInitialize(initConfig)
RootCmd.PersistentFlags().StringVar(&cfgFile, "config", "", "config file (default is $HOME/.cobra.yaml)")
RootCmd.PersistentFlags().StringVarP(&projectBase, "projectbase", "b", "", "base project directory eg. github.com/spf13/")
RootCmd.PersistentFlags().StringP("author", "a", "YOUR NAME", "Author name for copyright attribution")
RootCmd.PersistentFlags().StringVarP(&userLicense, "license", "l", "", "Name of license for the project (can provide `licensetext` in config)")
RootCmd.PersistentFlags().Bool("viper", true, "Use Viper for configuration")
viper.BindPFlag("author", RootCmd.PersistentFlags().Lookup("author"))
viper.BindPFlag("projectbase", RootCmd.PersistentFlags().Lookup("projectbase"))
viper.BindPFlag("useViper", RootCmd.PersistentFlags().Lookup("viper"))
viper.SetDefault("author", "NAME HERE <EMAIL ADDRESS>")
viper.SetDefault("license", "apache")
}
the pointer referred to by &projectBase will not store the value from the config file unless I do this somewhere down the line after the above code...
projectBase = viper.GetString("projectbase")
Yes
Most helpful comment
If I take the example from the readme...
the pointer referred to by
&projectBasewill not store the value from the config file unless I do this somewhere down the line after the above code...