Skip to content

Commit

Permalink
Fix: AllSettings() includes nested values overridden by env variables
Browse files Browse the repository at this point in the history
This commit replaces and enhances
6457afe  Fix: AllSettings() includes nested values overridden by flags

The solution is now more general and AllSettings() takes into account
values overridden by env variables, as well as flags, and probably others.
  • Loading branch information
benoitmasson committed Aug 25, 2016
1 parent 2b7b6ce commit 9141a0a
Show file tree
Hide file tree
Showing 2 changed files with 19 additions and 19 deletions.
36 changes: 18 additions & 18 deletions viper.go
Original file line number Diff line number Diff line change
Expand Up @@ -1225,31 +1225,31 @@ func (v *Viper) AllKeys() []string {
// Return all settings as a map[string]interface{}
func AllSettings() map[string]interface{} { return v.AllSettings() }
func (v *Viper) AllSettings() map[string]interface{} {
nestedFlags := make([]string, 0)
m := map[string]interface{}{}
for _, x := range v.AllKeys() {
if strings.Contains(x, v.keyDelim) {
nestedFlags = append(nestedFlags, x)
continue
}
m[x] = v.Get(x)
m[x] = v.deepGet(v.Get(x), x)
}
return m
}

// build (or replace) inner maps, for nested flag values
for _, k := range nestedFlags {
val := v.Get(k)
path := strings.Split(k, v.keyDelim)
lastKey := path[len(path)-1]
deepestMap := deepSearch(m, path[0:len(path)-1])

// set innermost value
deepestMap[lastKey] = val
// deepGet recursively performs a deep scan of a map[string]interface{},
// and updates any "final" value with the value returned by v.Get().
// Useful to retrieve real values overridden by flags or environment variables,
// for example.
func (v *Viper) deepGet(val interface{}, fullPath string) interface{} {
m, ok := val.(map[string]interface{})
if !ok {
// retrieve and return the real, potentially overridden, value
return v.Get(fullPath)
}

return m
for k, innerVal := range m {
// recursive scan and update
m[k] = v.deepGet(innerVal, fullPath+v.keyDelim+k)
}
return val // "final" values were changed in the process
}

// Se the filesystem to use to read configuration.
// Set the filesystem to use to read configuration.
func SetFs(fs afero.Fs) { v.SetFs(fs) }
func (v *Viper) SetFs(fs afero.Fs) {
v.fs = fs
Expand Down
2 changes: 1 addition & 1 deletion viper_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -422,7 +422,7 @@ func TestAllKeys(t *testing.T) {

ks := sort.StringSlice{"title", "newkey", "owner", "name", "beard", "ppu", "batters", "hobbies", "clothing", "age", "hacker", "id", "type", "eyes", "p_id", "p_ppu", "p_batters.batter.type", "p_type", "p_name", "foos"}
dob, _ := time.Parse(time.RFC3339, "1979-05-27T07:32:00Z")
all := map[string]interface{}{"owner": map[string]interface{}{"organization": "MongoDB", "Bio": "MongoDB Chief Developer Advocate & Hacker at Large", "dob": dob}, "title": "TOML Example", "ppu": 0.55, "eyes": "brown", "clothing": map[interface{}]interface{}{"trousers": "denim", "jacket": "leather", "pants": map[interface{}]interface{}{"size": "large"}}, "id": "0001", "batters": map[string]interface{}{"batter": []interface{}{map[string]interface{}{"type": "Regular"}, map[string]interface{}{"type": "Chocolate"}, map[string]interface{}{"type": "Blueberry"}, map[string]interface{}{"type": "Devil's Food"}}}, "hacker": true, "beard": true, "hobbies": []interface{}{"skateboarding", "snowboarding", "go"}, "age": 35, "type": "donut", "newkey": "remote", "name": "Cake", "p_id": "0001", "p_ppu": "0.55", "p_name": "Cake", "p_batters": map[string]interface{}{"batter": map[string]interface{}{"type": "Regular"}}, "p_type": "donut", "foos": []map[string]interface{}{map[string]interface{}{"foo": []map[string]interface{}{map[string]interface{}{"key": 1}, map[string]interface{}{"key": 2}, map[string]interface{}{"key": 3}, map[string]interface{}{"key": 4}}}}}
all := map[string]interface{}{"owner": map[string]interface{}{"organization": "MongoDB", "Bio": "MongoDB Chief Developer Advocate & Hacker at Large", "dob": dob}, "title": "TOML Example", "ppu": 0.55, "eyes": "brown", "clothing": map[interface{}]interface{}{"trousers": "denim", "jacket": "leather", "pants": map[interface{}]interface{}{"size": "large"}}, "id": "0001", "batters": map[string]interface{}{"batter": []interface{}{map[string]interface{}{"type": "Regular"}, map[string]interface{}{"type": "Chocolate"}, map[string]interface{}{"type": "Blueberry"}, map[string]interface{}{"type": "Devil's Food"}}}, "hacker": true, "beard": true, "hobbies": []interface{}{"skateboarding", "snowboarding", "go"}, "age": 35, "type": "donut", "newkey": "remote", "name": "Cake", "p_id": "0001", "p_ppu": "0.55", "p_name": "Cake", "p_batters.batter.type": "Regular", "p_type": "donut", "foos": []map[string]interface{}{map[string]interface{}{"foo": []map[string]interface{}{map[string]interface{}{"key": 1}, map[string]interface{}{"key": 2}, map[string]interface{}{"key": 3}, map[string]interface{}{"key": 4}}}}}

var allkeys sort.StringSlice
allkeys = AllKeys()
Expand Down

0 comments on commit 9141a0a

Please sign in to comment.