Skip to content

Commit

Permalink
Fixed AllKeys() to include env values added with BindEnv()
Browse files Browse the repository at this point in the history
* Fixed: values bound with BindEnv added to AllKeys()

Cast was not working, and v.env wasn't used when merging keys.

Rewrote explicit and specific casts for maps storing strings or FlagValues.

* Added: test for BindEnv() and AllKeys()

To make sure AllSettings() and Unmarshal() will consider environment
variables added with BindEnv().
  • Loading branch information
benoitmasson authored and bep committed Oct 23, 2016
1 parent 50515b7 commit 285f151
Show file tree
Hide file tree
Showing 2 changed files with 28 additions and 12 deletions.
23 changes: 11 additions & 12 deletions viper.go
Expand Up @@ -1162,6 +1162,14 @@ func castMapStringToMapInterface(src map[string]string) map[string]interface{} {
return tgt
}

func castMapFlagToMapInterface(src map[string]FlagValue) map[string]interface{} {
tgt := map[string]interface{}{}
for k, v := range src {
tgt[k] = v
}
return tgt
}

// mergeMaps merges two maps. The `itgt` parameter is for handling go-yaml's
// insistence on parsing nested structures as `map[interface{}]interface{}`
// instead of using a `string` as the key for nest structures beyond one level
Expand Down Expand Up @@ -1307,8 +1315,8 @@ func (v *Viper) AllKeys() []string {
// add all paths, by order of descending priority to ensure correct shadowing
m = v.flattenAndMergeMap(m, castMapStringToMapInterface(v.aliases), "")
m = v.flattenAndMergeMap(m, v.override, "")
m = v.mergeFlatMap(m, v.pflags)
m = v.mergeFlatMap(m, v.env)
m = v.mergeFlatMap(m, castMapFlagToMapInterface(v.pflags))
m = v.mergeFlatMap(m, castMapStringToMapInterface(v.env))
m = v.flattenAndMergeMap(m, v.config, "")
m = v.flattenAndMergeMap(m, v.kvstore, "")
m = v.flattenAndMergeMap(m, v.defaults, "")
Expand Down Expand Up @@ -1360,16 +1368,7 @@ func (v *Viper) flattenAndMergeMap(shadow map[string]bool, m map[string]interfac

// mergeFlatMap merges the given maps, excluding values of the second map
// shadowed by values from the first map.
func (v *Viper) mergeFlatMap(shadow map[string]bool, mi interface{}) map[string]bool {
// unify input map
var m map[string]interface{}
switch mi.(type) {
case map[string]string, map[string]FlagValue:
m = cast.ToStringMap(mi)
default:
return shadow
}

func (v *Viper) mergeFlatMap(shadow map[string]bool, m map[string]interface{}) map[string]bool {
// scan keys
outer:
for k, _ := range m {
Expand Down
17 changes: 17 additions & 0 deletions viper_test.go
Expand Up @@ -445,6 +445,23 @@ func TestAllKeys(t *testing.T) {
assert.Equal(t, all, AllSettings())
}

func TestAllKeysWithEnv(t *testing.T) {
v := New()

// bind and define environment variables (including a nested one)
v.BindEnv("id")
v.BindEnv("foo.bar")
v.SetEnvKeyReplacer(strings.NewReplacer(".", "_"))
os.Setenv("ID", "13")
os.Setenv("FOO_BAR", "baz")

expectedKeys := sort.StringSlice{"id", "foo.bar"}
expectedKeys.Sort()
keys := sort.StringSlice(v.AllKeys())
keys.Sort()
assert.Equal(t, expectedKeys, keys)
}

func TestAliasesOfAliases(t *testing.T) {
Set("Title", "Checking Case")
RegisterAlias("Foo", "Bar")
Expand Down

0 comments on commit 285f151

Please sign in to comment.