How do i parse the following yaml with viper ?
dbInstance:
name: pg-instance
id: test-db
storageGB: 5
dbInstanceClass: db.t2.small
multiAZ: true
publiclyAccessible: false
engineVersion: "9.6"
storageType: gp2
region: eu-central-1
whiteList:
- 127.0.0.1
- 127.0.0.2
clothing:
jacket: leather
trousers: denim
I am parsing as follows
// Configurations exported
type Configurations struct {
DBInstance DBInstanceConfigurations
}
type DBInstanceConfigurations struct {
Name string
Id string
StorageGB string
DBInstanceClass string
EngineVersion string
StorageType string
Region string
MultiAZ bool
PubliclyAccessible bool
whiteList string `mapstructure:"path_map"`
}
func main() {
viper.SetConfigName("config")
// Set the path to look for the configurations file
viper.AddConfigPath(".")
// Enable VIPER to read Environment Variables
viper.AutomaticEnv()
viper.SetConfigType("yaml")
var configuration Configurations
if err := viper.ReadInConfig(); err != nil {
fmt.Printf("Error reading config file, %s", err)
}
err := viper.Unmarshal(&configuration)
if err != nil {
fmt.Printf("Unable to decode into struct, %v", err)
}
fmt.Println("DBInstanceName is\t", configuration.DBInstance.Name)
fmt.Println("DBInstanceID is\t", configuration.DBInstance.Id)
fmt.Println("Storage is\t", configuration.DBInstance.StorageGB)
fmt.Println("DBInstanceClass is\t", configuration.DBInstance.DBInstanceClass)
fmt.Println("EngineVersion is\t", configuration.DBInstance.EngineVersion)
fmt.Println("MultiAZ is\t", configuration.DBInstance.MultiAZ)
fmt.Println("PubliclyAccessible is\t", configuration.DBInstance.PubliclyAccessible)
fmt.Println("StorageType is\t", configuration.DBInstance.StorageType)
fmt.Println("Region is\t", configuration.DBInstance.Region)
fmt.Println("Whitelist is\t", configuration.DBInstance.whiteList)
}
I would like to parse that whiteList IPs for looping and also the clothing key with the struct way ?
With a configuration file like:
command1:
foo: value
bar: value
and using Cobra and Viper together I understand how to access the nested keys viper.GetString("command1.foo")
. What I cannot understand is how to bind flags of a subcommand correctly. Both of:
viper.BindPFlag("command1.foo", command1Cmd.Flags().Lookup("foo"))
viper.Sub("command1").BindPFlag("foo", command1Cmd.Flags().Lookup("foo"))
produce a segment violation. I am sure there must be a way to bind into a nested structure but I cannot understand how. This seems like a fairly common thing one would want to do with a Cobra program consisting of many subcommands but I cannot find any prior art. Any help appreciated.
if merge {
fmt.Fprintf(os.Stderr, "merge config \n")
// get remote provider
// provider was ok, now we use our own!
provider := tipsterRemoteProvider{
provider: remoteProviderName,
endpoint: consulEndpoint,
path: key,
}
fmt.Fprintf(os.Stderr, "trying to read viper from remote provider: %+v \n", provider)
ioReader, err := realViper.RemoteConfig.Get(provider)
if err != nil {
fmt.Printf("Can't get remote config from consul: %s\n", err)
os.Exit(1)
}
err = viper.MergeConfig(ioReader)
I think this is the interesting part.
github.com/spf13/viper
func init() {
cobra.OnInitialize(func() {
config_viper.Setup(config.ServiceName, config.File, config.ConfigFileType, config.ConsulEndpoint)
subKey := "risk.userbeteventrisk.limits"
err := config_viper.SetupSubViper(subKey, config.ServiceName+"_limits", config.LimitsFile, config.ConfigFileType, config.ConsulEndpoint)
if err != nil {
log.Fatal().Err(err).Msg("could not configure limits")
}
config.Config = config.Load(viper.GetViper())
logging.Setup(config.Config.Logging)
})
rootCmd.PersistentFlags().StringVar(&config.File, "config", "", "config file")
rootCmd.PersistentFlags().StringVar(&config.LimitsFile, "config-limits", "", "config file for limits")
rootCmd.PersistentFlags().StringVar(&config.ConsulEndpoint, "consul", "", "consul endpoint")
}
viper.BindPFlags(rootCmd.PersistentFlags()
. when reading from a config file however, the values are not being populated to the variables. is there a way of keeping things in sync with the variable rather than doing viper.Get... ?
Hey all! I'm a big fan of viper but am in a situation where we have an app that sources config from several different files on the filesystem and needs to get a single merged config from all of them, plus update that merged config (with appropriate, deterministic priority given to each file) on file-system events. Since viper currently only supports a single config file, I made a very thin synchronization layer on top of viper that allows you to manage and merge an infinite number of viper instances in a thread-safe way, and computes and delivers the updated config as a viper instance every time one of the sub-instances receives an update from the fs. Code is available here:
https://github.com/ajpauwels/pit-of-vipers
Happy to work with dev team if this is something that you feel should be integrated directly into the upstream, otherwise hope the code helps others in a similar situation of wanting to manage multiple files at once :)
Hey folks, is there anyway to mark viper values as "don't write this to the config when calling WriteConfig?" I'm using viper to store state for my CLI application, which includes some values read from the config and some generated at a run time. My application supports writing to the config file, and I would like to omit the runtime values from my WriteConfig
call. I currently accomplish this by unmarshalling into a struct that only has the fields that I want to write then writing that struct. Is there a better way to do that? As an aside, is using viper as an intermediary to store runtime values an anti-pattern? Here's an example of what I'm doing. This entire subcommand tree relies on an age Identity parsed from an ssh-key, which the user provides a path to via a flag:
cobra.Command{
Use: "mysubcmd"
PersistentPreRun: func(cmd *cobra.Command, args []string) {
sskKeyPath := viper.GetString("mysubcmd.ssk-key")
id, err := loadSshKey(sshKeyPath)
if err != nil {
log.Fatalf("uh-oh: %s", err.Error())
}
viper.Set("mysubcmd.id", id)
}
}
I'd like to be able to tell Viper to omit `mysubcmd.id" when writing the config back to a file.