Viper: How to merge two config files

Created on 29 Apr 2016  路  5Comments  路  Source: spf13/viper

Starting to use viper but would like to read in a default.yaml and then based in the Environment and role
merge /env/role/default.yaml so we keep the main command common, but db and locations in the enviornment. base yaml. Tried MergeInConf but not seeing the enviro variables.

Most helpful comment

Even after #199, MergeInConfig does not behave how I was expecting it to. My use case is that I would like to have multiple config file locations, that merges in runtime into one. Something like global location in the user home, then a file in the current directory (if exists) merged on top of that, then some custom user specified location on top of that, etc...
Which is useful, lets say, for some CLI tool that the user will want to configure/adjust per project/directory (still having the ability to provide some baseline configuration globally). Which sounds like a common use case.

The workaround I've came up with is to define a totally separate viper instance for each location, and then use MergeConfigMap:

...
viper.ReadInConfig()
...
v := viper.New()
...
viper.MergeConfigMap(v.AllSettings())

I omitted all configurations and error handling for simplicity, this is just to demonstrate the idea.

All 5 comments

This probably could be seen as a shameless plug, but take a look at this which is doing what you want do, just with files / directories. I would assume something very similar is possible.

From my experience, Merge overwrites the previous values (it is using a map[string]interface{} after all.

You might have to manually do this by creating multiple vipers and manually applying in the order you wish.

This what I expected the behaviour of MergeInConfig to have, that if multiple config files were found in the set paths it merge them in order, i.e top overrides bottom. I'm not entirely sure what MergeInConfig does over ReadInConfig.

I proposed a PR #199 to allow consecutive SetConfigName() and MergeInConfig() calls w/o a workaround.

One workaround in the meantime could be to call SetConfigFile("path/to/file.yml") explicitly instead of SetConfigName()

Even after #199, MergeInConfig does not behave how I was expecting it to. My use case is that I would like to have multiple config file locations, that merges in runtime into one. Something like global location in the user home, then a file in the current directory (if exists) merged on top of that, then some custom user specified location on top of that, etc...
Which is useful, lets say, for some CLI tool that the user will want to configure/adjust per project/directory (still having the ability to provide some baseline configuration globally). Which sounds like a common use case.

The workaround I've came up with is to define a totally separate viper instance for each location, and then use MergeConfigMap:

...
viper.ReadInConfig()
...
v := viper.New()
...
viper.MergeConfigMap(v.AllSettings())

I omitted all configurations and error handling for simplicity, this is just to demonstrate the idea.

@dee-kryvenko your workaround works well for our use case :)

Was this page helpful?
0 / 5 - 0 ratings

Related issues

TWinsnes picture TWinsnes  路  3Comments

alfmos picture alfmos  路  3Comments

therealfakemoot picture therealfakemoot  路  5Comments

TimJones picture TimJones  路  4Comments

TheHackerDev picture TheHackerDev  路  3Comments