Esempio n. 1
0
func (v *Viper) searchMap(source map[string]interface{}, path []string) interface{} {

	if len(path) == 0 {
		return source
	}

	if next, ok := source[path[0]]; ok {
		switch next.(type) {
		case map[interface{}]interface{}:
			return v.searchMap(cast.ToStringMap(next), path[1:])
		case map[string]interface{}:
			// Type assertion is safe here since it is only reached
			// if the type of `next` is the same as the type being asserted
			return v.searchMap(next.(map[string]interface{}), path[1:])
		default:
			return next
		}
	} else {
		return nil
	}
}
Esempio n. 2
0
// Given a key, find the value
// Viper will check in the following order:
// flag, env, config file, key/value store, default
// Viper will check to see if an alias exists first
func (v *Viper) find(key string) interface{} {
	var val interface{}
	var exists bool

	// if the requested key is an alias, then return the proper key
	key = v.realKey(key)

	// PFlag Override first
	flag, exists := v.pflags[key]
	if exists && flag.Changed {
		jww.TRACE.Println(key, "found in override (via pflag):", flag.Value)
		switch flag.Value.Type() {
		case "int", "int8", "int16", "int32", "int64":
			return cast.ToInt(flag.Value.String())
		case "bool":
			return cast.ToBool(flag.Value.String())
		default:
			return flag.Value.String()
		}
	}

	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
		if val = v.getEnv(v.mergeWithEnvPrefix(key)); val != "" {
			jww.TRACE.Println(key, "found in environment with val:", val)
			return val
		}
	}

	envkey, exists := v.env[key]
	if exists {
		jww.TRACE.Println(key, "registered as env var", envkey)
		if val = v.getEnv(envkey); val != "" {
			jww.TRACE.Println(envkey, "found in environment with val:", val)
			return val
		} else {
			jww.TRACE.Println(envkey, "env value unset:")
		}
	}

	val, exists = v.config[key]
	if exists {
		jww.TRACE.Println(key, "found in config:", val)
		return val
	}

	// Test for nested config parameter
	if strings.Contains(key, v.keyDelim) {
		path := strings.Split(key, v.keyDelim)

		source := v.find(path[0])
		if source != nil {
			if reflect.TypeOf(source).Kind() == reflect.Map {
				val := v.searchMap(cast.ToStringMap(source), path[1:])
				jww.TRACE.Println(key, "found in nested config:", val)
				return val
			}
		}
	}

	val, exists = v.kvstore[key]
	if exists {
		jww.TRACE.Println(key, "found in key/value store:", val)
		return val
	}

	val, exists = v.defaults[key]
	if exists {
		jww.TRACE.Println(key, "found in defaults:", val)
		return val
	}

	return nil
}
Esempio n. 3
0
func (v *Viper) GetStringMap(key string) map[string]interface{} {
	return cast.ToStringMap(v.Get(key))
}
Esempio n. 4
0
func (v *Viper) Get(key string) interface{} {
	path := strings.Split(key, v.keyDelim)

	lcaseKey := strings.ToLower(key)
	val := v.find(lcaseKey)

	if val == nil {
		source := v.find(path[0])
		if source != nil {
			if reflect.TypeOf(source).Kind() == reflect.Map {
				val = v.searchMap(cast.ToStringMap(source), path[1:])
			}
		}
	}

	// 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
	if val == nil {
		if flag, exists := v.pflags[lcaseKey]; exists {
			jww.TRACE.Println(key, "get pflag default", val)
			switch flag.Value.Type() {
			case "int", "int8", "int16", "int32", "int64":
				val = cast.ToInt(flag.Value.String())
			case "bool":
				val = cast.ToBool(flag.Value.String())
			default:
				val = flag.Value.String()
			}
		}
	}

	if val == nil {
		return nil
	}

	var valType interface{}
	if !v.typeByDefValue {
		valType = val
	} else {
		defVal, defExists := v.defaults[lcaseKey]
		if defExists {
			valType = defVal
		} else {
			valType = val
		}
	}

	switch valType.(type) {
	case bool:
		return cast.ToBool(val)
	case string:
		return cast.ToString(val)
	case int64, int32, int16, int8, int:
		return cast.ToInt(val)
	case float64, float32:
		return cast.ToFloat64(val)
	case time.Time:
		return cast.ToTime(val)
	case time.Duration:
		return cast.ToDuration(val)
	case []string:
		return cast.ToStringSlice(val)
	}
	return val
}