mirror of
https://github.com/spf13/viper
synced 2025-05-06 12:17:18 +00:00
Add a AllSettingsWithoutDefault method
We want the ability to pull the entire configuration without the default to know what a user explicitly configured
This commit is contained in:
parent
7e5da050b1
commit
3801ce6375
2 changed files with 83 additions and 15 deletions
47
viper.go
47
viper.go
|
@ -609,15 +609,36 @@ func (v *Viper) Get(key string) interface{} {
|
||||||
return val
|
return val
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// GetSkipDefault returns an interface. For a specific value use one of the Get____ methods.
|
||||||
|
func GetSkipDefault(key string) interface{} { return v.GetSkipDefault(key) }
|
||||||
|
func (v *Viper) GetSkipDefault(key string) interface{} {
|
||||||
|
val, _ := v.GetESkipDefault(key)
|
||||||
|
return val
|
||||||
|
}
|
||||||
|
|
||||||
// GetE is like Get but also returns parsing errors.
|
// GetE is like Get but also returns parsing errors.
|
||||||
func GetE(key string) (interface{}, error) { return v.GetE(key) }
|
func GetE(key string) (interface{}, error) { return v.GetE(key) }
|
||||||
func (v *Viper) GetE(key string) (interface{}, error) {
|
func (v *Viper) GetE(key string) (interface{}, error) {
|
||||||
lcaseKey := strings.ToLower(key)
|
lcaseKey := strings.ToLower(key)
|
||||||
val := v.find(lcaseKey)
|
val := v.find(lcaseKey, false)
|
||||||
if val == nil {
|
if val == nil {
|
||||||
return nil, nil
|
return nil, nil
|
||||||
}
|
}
|
||||||
|
return v.castByDefValue(lcaseKey, val)
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetESkipDefault is like GetE but ignors defaults.
|
||||||
|
func GetESkipDefault(key string) (interface{}, error) { return v.GetESkipDefault(key) }
|
||||||
|
func (v *Viper) GetESkipDefault(key string) (interface{}, error) {
|
||||||
|
lcaseKey := strings.ToLower(key)
|
||||||
|
val := v.find(lcaseKey, true)
|
||||||
|
if val == nil {
|
||||||
|
return nil, nil
|
||||||
|
}
|
||||||
|
return v.castByDefValue(lcaseKey, val)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (v *Viper) castByDefValue(lcaseKey string, val interface{}) (interface{}, error) {
|
||||||
if v.typeByDefValue {
|
if v.typeByDefValue {
|
||||||
// TODO(bep) this branch isn't covered by a single test.
|
// TODO(bep) this branch isn't covered by a single test.
|
||||||
valType := val
|
valType := val
|
||||||
|
@ -654,7 +675,7 @@ func (v *Viper) GetE(key string) (interface{}, error) {
|
||||||
func GetRaw(key string) interface{} { return v.GetRaw(key) }
|
func GetRaw(key string) interface{} { return v.GetRaw(key) }
|
||||||
func (v *Viper) GetRaw(key string) interface{} {
|
func (v *Viper) GetRaw(key string) interface{} {
|
||||||
lcaseKey := strings.ToLower(key)
|
lcaseKey := strings.ToLower(key)
|
||||||
return v.find(lcaseKey)
|
return v.find(lcaseKey, false)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Sub returns new Viper instance representing a sub tree of this instance.
|
// Sub returns new Viper instance representing a sub tree of this instance.
|
||||||
|
@ -983,9 +1004,10 @@ func (v *Viper) BindEnv(input ...string) error {
|
||||||
// Given a key, find the value.
|
// Given a key, find the value.
|
||||||
// Viper will check in the following order:
|
// Viper will check in the following order:
|
||||||
// flag, env, config file, key/value store, default.
|
// flag, env, config file, key/value store, default.
|
||||||
|
// If skipDefault is set to true, find will ignore default values.
|
||||||
// Viper will check to see if an alias exists first.
|
// Viper will check to see if an alias exists first.
|
||||||
// Note: this assumes a lower-cased key given.
|
// Note: this assumes a lower-cased key given.
|
||||||
func (v *Viper) find(lcaseKey string) interface{} {
|
func (v *Viper) find(lcaseKey string, skipDefault bool) interface{} {
|
||||||
|
|
||||||
var (
|
var (
|
||||||
val interface{}
|
val interface{}
|
||||||
|
@ -1079,6 +1101,7 @@ func (v *Viper) find(lcaseKey string) interface{} {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Default next
|
// Default next
|
||||||
|
if !skipDefault {
|
||||||
val = v.searchMap(v.defaults, path)
|
val = v.searchMap(v.defaults, path)
|
||||||
if val != nil {
|
if val != nil {
|
||||||
return val
|
return val
|
||||||
|
@ -1086,6 +1109,7 @@ func (v *Viper) find(lcaseKey string) interface{} {
|
||||||
if nested && v.isPathShadowedInDeepMap(path, v.defaults) != "" {
|
if nested && v.isPathShadowedInDeepMap(path, v.defaults) != "" {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// last chance: if no other value is returned and a flag does exist for the value,
|
// last chance: if no other value is returned and a flag does exist for the value,
|
||||||
// get the flag's value even if the flag's value has not changed
|
// get the flag's value even if the flag's value has not changed
|
||||||
|
@ -1123,7 +1147,7 @@ func readAsCSV(val string) ([]string, error) {
|
||||||
func IsSet(key string) bool { return v.IsSet(key) }
|
func IsSet(key string) bool { return v.IsSet(key) }
|
||||||
func (v *Viper) IsSet(key string) bool {
|
func (v *Viper) IsSet(key string) bool {
|
||||||
lcaseKey := strings.ToLower(key)
|
lcaseKey := strings.ToLower(key)
|
||||||
val := v.find(lcaseKey)
|
val := v.find(lcaseKey, false)
|
||||||
return val != nil
|
return val != nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1820,13 +1844,22 @@ outer:
|
||||||
// AllSettings merges all settings and returns them as a map[string]interface{}.
|
// AllSettings merges all settings and returns them as a map[string]interface{}.
|
||||||
func AllSettings() map[string]interface{} { return v.AllSettings() }
|
func AllSettings() map[string]interface{} { return v.AllSettings() }
|
||||||
func (v *Viper) AllSettings() map[string]interface{} {
|
func (v *Viper) AllSettings() map[string]interface{} {
|
||||||
|
return v.allSettings(v.Get)
|
||||||
|
}
|
||||||
|
|
||||||
|
// AllSettingsWithoutDefault merges all settings and returns them as a map[string]interface{}.
|
||||||
|
func AllSettingsWithoutDefault() map[string]interface{} { return v.AllSettingsWithoutDefault() }
|
||||||
|
func (v *Viper) AllSettingsWithoutDefault() map[string]interface{} {
|
||||||
|
return v.allSettings(v.GetSkipDefault)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (v *Viper) allSettings(getter func(string) interface{}) map[string]interface{} {
|
||||||
m := map[string]interface{}{}
|
m := map[string]interface{}{}
|
||||||
// start from the list of keys, and construct the map one value at a time
|
// start from the list of keys, and construct the map one value at a time
|
||||||
for _, k := range v.AllKeys() {
|
for _, k := range v.AllKeys() {
|
||||||
value := v.Get(k)
|
value := getter(k)
|
||||||
if value == nil {
|
if value == nil {
|
||||||
// should not happen, since AllKeys() returns only keys holding a value,
|
// should only happens if we `getter` ignors defaults
|
||||||
// check just in case anything changes
|
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -561,6 +561,41 @@ clothing.winter:
|
||||||
`
|
`
|
||||||
v := New()
|
v := New()
|
||||||
v.SetConfigType("yaml")
|
v.SetConfigType("yaml")
|
||||||
|
v.SetDefault("test", "example")
|
||||||
|
r := strings.NewReader(exampleYaml)
|
||||||
|
|
||||||
|
if err := v.unmarshalReader(r, v.config); err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
expectedAll := map[string]interface{}{"hacker": true, "name": "steve", "test": "example", "hobbies": []interface{}{"skate.boarding", "snowboarding"}, "clothing.summer": map[string]interface{}{"jacket": "leather", "pants": map[string]interface{}{"size": "large"}}, "clothing.winter": map[string]interface{}{"jacket": "wool", "pants": map[string]interface{}{"size": "medium"}}}
|
||||||
|
expectedKeys := sort.StringSlice{"hacker", "name", "test", "hobbies", "clothing.summer.jacket", "clothing.summer.pants.size", "clothing.winter.jacket", "clothing.winter.pants.size"}
|
||||||
|
expectedKeys.Sort()
|
||||||
|
keys := sort.StringSlice(v.AllKeys())
|
||||||
|
keys.Sort()
|
||||||
|
|
||||||
|
assert.Equal(t, expectedKeys, keys)
|
||||||
|
assert.Equal(t, expectedAll, v.AllSettings())
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestAllSettingsWithDelimiterInKeysWithoutDefault(t *testing.T) {
|
||||||
|
exampleYaml := `Hacker: true
|
||||||
|
name: steve
|
||||||
|
hobbies:
|
||||||
|
- skate.boarding
|
||||||
|
- snowboarding
|
||||||
|
clothing.summer:
|
||||||
|
jacket: leather
|
||||||
|
pants:
|
||||||
|
size: large
|
||||||
|
clothing.winter:
|
||||||
|
jacket: wool
|
||||||
|
pants:
|
||||||
|
size: medium
|
||||||
|
`
|
||||||
|
v := New()
|
||||||
|
v.SetConfigType("yaml")
|
||||||
|
v.SetDefault("test", "example")
|
||||||
r := strings.NewReader(exampleYaml)
|
r := strings.NewReader(exampleYaml)
|
||||||
|
|
||||||
if err := v.unmarshalReader(r, v.config); err != nil {
|
if err := v.unmarshalReader(r, v.config); err != nil {
|
||||||
|
@ -568,13 +603,13 @@ clothing.winter:
|
||||||
}
|
}
|
||||||
|
|
||||||
expectedAll := map[string]interface{}{"hacker": true, "name": "steve", "hobbies": []interface{}{"skate.boarding", "snowboarding"}, "clothing.summer": map[string]interface{}{"jacket": "leather", "pants": map[string]interface{}{"size": "large"}}, "clothing.winter": map[string]interface{}{"jacket": "wool", "pants": map[string]interface{}{"size": "medium"}}}
|
expectedAll := map[string]interface{}{"hacker": true, "name": "steve", "hobbies": []interface{}{"skate.boarding", "snowboarding"}, "clothing.summer": map[string]interface{}{"jacket": "leather", "pants": map[string]interface{}{"size": "large"}}, "clothing.winter": map[string]interface{}{"jacket": "wool", "pants": map[string]interface{}{"size": "medium"}}}
|
||||||
expectedKeys := sort.StringSlice{"hacker", "name", "hobbies", "clothing.summer.jacket", "clothing.summer.pants.size", "clothing.winter.jacket", "clothing.winter.pants.size"}
|
expectedKeys := sort.StringSlice{"hacker", "name", "test", "hobbies", "clothing.summer.jacket", "clothing.summer.pants.size", "clothing.winter.jacket", "clothing.winter.pants.size"}
|
||||||
expectedKeys.Sort()
|
expectedKeys.Sort()
|
||||||
keys := sort.StringSlice(v.AllKeys())
|
keys := sort.StringSlice(v.AllKeys())
|
||||||
keys.Sort()
|
keys.Sort()
|
||||||
|
|
||||||
assert.Equal(t, expectedKeys, keys)
|
assert.Equal(t, expectedKeys, keys)
|
||||||
assert.Equal(t, expectedAll, v.AllSettings())
|
assert.Equal(t, expectedAll, v.AllSettingsWithoutDefault())
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestAliasesOfAliases(t *testing.T) {
|
func TestAliasesOfAliases(t *testing.T) {
|
||||||
|
|
Loading…
Add table
Reference in a new issue