mirror of
https://github.com/spf13/viper
synced 2024-12-23 12:07:02 +00:00
Added indexing of nested config values
This commit is contained in:
parent
39ab3ca72e
commit
7b841dc66d
1 changed files with 81 additions and 9 deletions
90
viper.go
90
viper.go
|
@ -38,6 +38,9 @@ import (
|
|||
crypt "github.com/xordataexchange/crypt/config"
|
||||
)
|
||||
|
||||
const INDEX_DELIM = "."
|
||||
const ENV_INDEX_DELIM = "__"
|
||||
|
||||
var v *Viper
|
||||
|
||||
func init() {
|
||||
|
@ -121,7 +124,10 @@ type Viper struct {
|
|||
|
||||
automaticEnvApplied bool
|
||||
envKeyReplacer *strings.Replacer
|
||||
envToIndex *strings.Replacer
|
||||
indexToEnv *strings.Replacer
|
||||
|
||||
index map[string]interface{}
|
||||
config map[string]interface{}
|
||||
override map[string]interface{}
|
||||
defaults map[string]interface{}
|
||||
|
@ -135,6 +141,7 @@ type Viper struct {
|
|||
func New() *Viper {
|
||||
v := new(Viper)
|
||||
v.configName = "config"
|
||||
v.index = make(map[string]interface{})
|
||||
v.config = make(map[string]interface{})
|
||||
v.override = make(map[string]interface{})
|
||||
v.defaults = make(map[string]interface{})
|
||||
|
@ -149,6 +156,8 @@ func New() *Viper {
|
|||
} else {
|
||||
v.AddConfigPath(wd)
|
||||
}
|
||||
v.indexToEnv = strings.NewReplacer(ENV_INDEX_DELIM, INDEX_DELIM)
|
||||
v.envToIndex = strings.NewReplacer(INDEX_DELIM, ENV_INDEX_DELIM)
|
||||
|
||||
return v
|
||||
}
|
||||
|
@ -214,6 +223,8 @@ func (v *Viper) mergeWithEnvPrefix(in string) string {
|
|||
// key. This allows env vars which have different keys then the config object
|
||||
// keys
|
||||
func (v *Viper) getEnv(key string) string {
|
||||
key = v.indexToEnv.Replace(key)
|
||||
|
||||
if v.envKeyReplacer != nil {
|
||||
key = v.envKeyReplacer.Replace(key)
|
||||
}
|
||||
|
@ -317,12 +328,23 @@ func (v *Viper) providerPathExists(p *remoteProvider) bool {
|
|||
func Get(key string) interface{} { return v.Get(key) }
|
||||
func (v *Viper) Get(key string) interface{} {
|
||||
key = strings.ToLower(key)
|
||||
val := v.find(key)
|
||||
var val interface{}
|
||||
v.buildIndex()
|
||||
|
||||
if val = v.findIndex(key); val == nil {
|
||||
val = v.find(key)
|
||||
}
|
||||
|
||||
if val == nil {
|
||||
return nil
|
||||
}
|
||||
|
||||
val = castVal(val)
|
||||
|
||||
return val
|
||||
}
|
||||
|
||||
func castVal(val interface{}) interface{} {
|
||||
switch val.(type) {
|
||||
case bool:
|
||||
return cast.ToBool(val)
|
||||
|
@ -339,6 +361,7 @@ func (v *Viper) Get(key string) interface{} {
|
|||
case []string:
|
||||
return val
|
||||
}
|
||||
|
||||
return val
|
||||
}
|
||||
|
||||
|
@ -483,7 +506,7 @@ func (v *Viper) BindEnv(input ...string) (err error) {
|
|||
return fmt.Errorf("BindEnv missing key to bind to")
|
||||
}
|
||||
|
||||
key = strings.ToLower(input[0])
|
||||
key = v.envToIndex.Replace(strings.ToLower(input[0]))
|
||||
|
||||
if len(input) == 1 {
|
||||
envkey = v.mergeWithEnvPrefix(key)
|
||||
|
@ -496,6 +519,18 @@ func (v *Viper) BindEnv(input ...string) (err error) {
|
|||
return nil
|
||||
}
|
||||
|
||||
func (v *Viper) findIndex(key string) interface{} {
|
||||
// Check index - it is safe ot check it first
|
||||
// as the paths there should be materialized
|
||||
// according to their priority
|
||||
val, exists := v.index[key]
|
||||
if exists {
|
||||
jww.TRACE.Println(key, "found in index:", val)
|
||||
return val
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// Given a key, find the value
|
||||
// Viper will check in the following order:
|
||||
// flag, env, config file, key/value store, default
|
||||
|
@ -507,6 +542,12 @@ func (v *Viper) find(key string) interface{} {
|
|||
// if the requested key is an alias, then return the proper key
|
||||
key = v.realKey(key)
|
||||
|
||||
val, exists = v.override[key]
|
||||
if exists {
|
||||
jww.TRACE.Println(key, "found in override:", val)
|
||||
return val
|
||||
}
|
||||
|
||||
// PFlag Override first
|
||||
flag, exists := v.pflags[key]
|
||||
if exists {
|
||||
|
@ -516,12 +557,6 @@ func (v *Viper) find(key string) interface{} {
|
|||
}
|
||||
}
|
||||
|
||||
val, exists = v.override[key]
|
||||
if exists {
|
||||
jww.TRACE.Println(key, "found in override:", val)
|
||||
return val
|
||||
}
|
||||
|
||||
if v.automaticEnvApplied {
|
||||
// even if it hasn't been registered, if automaticEnv is used,
|
||||
// check any Get request
|
||||
|
@ -563,6 +598,29 @@ func (v *Viper) find(key string) interface{} {
|
|||
return nil
|
||||
}
|
||||
|
||||
func (v *Viper) buildIndex() {
|
||||
v.index = make(map[string]interface{})
|
||||
v.indexMap(v.AllSettings(), "")
|
||||
}
|
||||
|
||||
func (v *Viper) indexMap(source map[string]interface{}, prefix string) {
|
||||
if len(prefix) > 0 {
|
||||
prefix = prefix + INDEX_DELIM
|
||||
}
|
||||
|
||||
for key, val := range source {
|
||||
|
||||
indexPath := prefix + key
|
||||
|
||||
v.index[indexPath] = val
|
||||
|
||||
if reflect.TypeOf(val).Kind() == reflect.Map {
|
||||
v.indexMap(cast.ToStringMap(val), indexPath)
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// Check to see if the key has been set in any of the data locations
|
||||
func IsSet(key string) bool { return v.IsSet(key) }
|
||||
func (v *Viper) IsSet(key string) bool {
|
||||
|
@ -782,12 +840,24 @@ func (v *Viper) AllKeys() []string {
|
|||
return a
|
||||
}
|
||||
|
||||
func AllIndexes() []string { return v.AllIndexes() }
|
||||
func (v *Viper) AllIndexes() []string {
|
||||
v.buildIndex()
|
||||
|
||||
var indexes []string
|
||||
for key, _ := range v.index {
|
||||
indexes = append(indexes, key)
|
||||
}
|
||||
|
||||
return indexes
|
||||
}
|
||||
|
||||
// Return all settings as a map[string]interface{}
|
||||
func AllSettings() map[string]interface{} { return v.AllSettings() }
|
||||
func (v *Viper) AllSettings() map[string]interface{} {
|
||||
m := map[string]interface{}{}
|
||||
for _, x := range v.AllKeys() {
|
||||
m[x] = v.Get(x)
|
||||
m[x] = castVal(v.find(x))
|
||||
}
|
||||
|
||||
return m
|
||||
|
@ -879,6 +949,8 @@ func (v *Viper) findConfigFile() (string, error) {
|
|||
// purposes.
|
||||
func Debug() { v.Debug() }
|
||||
func (v *Viper) Debug() {
|
||||
fmt.Println("Index:")
|
||||
pretty.Print(v.index)
|
||||
fmt.Println("Config:")
|
||||
pretty.Println(v.config)
|
||||
fmt.Println("Key/Value Store:")
|
||||
|
|
Loading…
Reference in a new issue