github.com/fzambia/viper-lite@v0.0.0-20171108064948-d5a31e6aa18b/viper.go (about)

     1  // Copyright © 2014 Steve Francia <spf@spf13.com>.
     2  //
     3  // Use of this source code is governed by an MIT-style
     4  // license that can be found in the LICENSE file.
     5  
     6  // Viper is a application configuration system.
     7  // It believes that applications can be configured a variety of ways
     8  // via flags, ENVIRONMENT variables, configuration files retrieved
     9  // from the file system, or a remote key/value store.
    10  
    11  // Each item takes precedence over the item below it:
    12  
    13  // overrides
    14  // flag
    15  // env
    16  // config
    17  // key/value store
    18  // default
    19  
    20  package viper
    21  
    22  import (
    23  	"bytes"
    24  	"encoding/csv"
    25  	"fmt"
    26  	"io"
    27  	"io/ioutil"
    28  	"os"
    29  	"path/filepath"
    30  	"reflect"
    31  	"strings"
    32  	"time"
    33  
    34  	"github.com/mitchellh/mapstructure"
    35  	"github.com/spf13/cast"
    36  	jww "github.com/spf13/jwalterweatherman"
    37  	"github.com/spf13/pflag"
    38  )
    39  
    40  var v *Viper
    41  
    42  type RemoteResponse struct {
    43  	Value []byte
    44  	Error error
    45  }
    46  
    47  func init() {
    48  	v = New()
    49  }
    50  
    51  // UnsupportedConfigError denotes encountering an unsupported
    52  // configuration filetype.
    53  type UnsupportedConfigError string
    54  
    55  // Error returns the formatted configuration error.
    56  func (str UnsupportedConfigError) Error() string {
    57  	return fmt.Sprintf("Unsupported Config Type %q", string(str))
    58  }
    59  
    60  // ConfigFileNotFoundError denotes failing to find configuration file.
    61  type ConfigFileNotFoundError struct {
    62  	name, locations string
    63  }
    64  
    65  // Error returns the formatted configuration error.
    66  func (fnfe ConfigFileNotFoundError) Error() string {
    67  	return fmt.Sprintf("Config File %q Not Found in %q", fnfe.name, fnfe.locations)
    68  }
    69  
    70  // Viper is a prioritized configuration registry. It
    71  // maintains a set of configuration sources, fetches
    72  // values to populate those, and provides them according
    73  // to the source's priority.
    74  // The priority of the sources is the following:
    75  // 1. overrides
    76  // 2. flags
    77  // 3. env. variables
    78  // 4. config file
    79  // 5. defaults
    80  //
    81  // For example, if values from the following sources were loaded:
    82  //
    83  //  Defaults : {
    84  //  	"secret": "",
    85  //  	"user": "default",
    86  //  	"endpoint": "https://localhost"
    87  //  }
    88  //  Config : {
    89  //  	"user": "root"
    90  //  	"secret": "defaultsecret"
    91  //  }
    92  //  Env : {
    93  //  	"secret": "somesecretkey"
    94  //  }
    95  //
    96  // The resulting config will have the following values:
    97  //
    98  //	{
    99  //		"secret": "somesecretkey",
   100  //		"user": "root",
   101  //		"endpoint": "https://localhost"
   102  //	}
   103  type Viper struct {
   104  	// Delimiter that separates a list of keys
   105  	// used to access a nested value in one go
   106  	keyDelim string
   107  
   108  	// A set of paths to look for the config file in
   109  	configPaths []string
   110  
   111  	// Name of file to look for inside the path
   112  	configName string
   113  	configFile string
   114  	configType string
   115  	envPrefix  string
   116  
   117  	automaticEnvApplied bool
   118  	envKeyReplacer      *strings.Replacer
   119  
   120  	config         map[string]interface{}
   121  	override       map[string]interface{}
   122  	defaults       map[string]interface{}
   123  	pflags         map[string]FlagValue
   124  	env            map[string]string
   125  	aliases        map[string]string
   126  	typeByDefValue bool
   127  }
   128  
   129  // New returns an initialized Viper instance.
   130  func New() *Viper {
   131  	v := new(Viper)
   132  	v.keyDelim = "."
   133  	v.configName = "config"
   134  	v.config = make(map[string]interface{})
   135  	v.override = make(map[string]interface{})
   136  	v.defaults = make(map[string]interface{})
   137  	v.pflags = make(map[string]FlagValue)
   138  	v.env = make(map[string]string)
   139  	v.aliases = make(map[string]string)
   140  	v.typeByDefValue = false
   141  
   142  	return v
   143  }
   144  
   145  // Intended for testing, will reset all to default settings.
   146  // In the public interface for the viper package so applications
   147  // can use it in their testing as well.
   148  func Reset() {
   149  	v = New()
   150  	SupportedExts = []string{"json", "toml", "yaml", "yml"}
   151  }
   152  
   153  // Universally supported extensions.
   154  var SupportedExts []string = []string{"json", "toml", "yaml", "yml"}
   155  
   156  // SetConfigFile explicitly defines the path, name and extension of the config file.
   157  // Viper will use this and not check any of the config paths.
   158  func SetConfigFile(in string) { v.SetConfigFile(in) }
   159  func (v *Viper) SetConfigFile(in string) {
   160  	if in != "" {
   161  		v.configFile = in
   162  	}
   163  }
   164  
   165  // SetEnvPrefix defines a prefix that ENVIRONMENT variables will use.
   166  // E.g. if your prefix is "spf", the env registry will look for env
   167  // variables that start with "SPF_".
   168  func SetEnvPrefix(in string) { v.SetEnvPrefix(in) }
   169  func (v *Viper) SetEnvPrefix(in string) {
   170  	if in != "" {
   171  		v.envPrefix = in
   172  	}
   173  }
   174  
   175  func (v *Viper) mergeWithEnvPrefix(in string) string {
   176  	if v.envPrefix != "" {
   177  		return strings.ToUpper(v.envPrefix + "_" + in)
   178  	}
   179  
   180  	return strings.ToUpper(in)
   181  }
   182  
   183  // TODO: should getEnv logic be moved into find(). Can generalize the use of
   184  // rewriting keys many things, Ex: Get('someKey') -> some_key
   185  // (camel case to snake case for JSON keys perhaps)
   186  
   187  // getEnv is a wrapper around os.Getenv which replaces characters in the original
   188  // key. This allows env vars which have different keys than the config object
   189  // keys.
   190  func (v *Viper) getEnv(key string) string {
   191  	if v.envKeyReplacer != nil {
   192  		key = v.envKeyReplacer.Replace(key)
   193  	}
   194  	return os.Getenv(key)
   195  }
   196  
   197  // ConfigFileUsed returns the file used to populate the config registry.
   198  func ConfigFileUsed() string            { return v.ConfigFileUsed() }
   199  func (v *Viper) ConfigFileUsed() string { return v.configFile }
   200  
   201  // AddConfigPath adds a path for Viper to search for the config file in.
   202  // Can be called multiple times to define multiple search paths.
   203  func AddConfigPath(in string) { v.AddConfigPath(in) }
   204  func (v *Viper) AddConfigPath(in string) {
   205  	if in != "" {
   206  		absin := absPathify(in)
   207  		jww.INFO.Println("adding", absin, "to paths to search")
   208  		if !stringInSlice(absin, v.configPaths) {
   209  			v.configPaths = append(v.configPaths, absin)
   210  		}
   211  	}
   212  }
   213  
   214  // searchMap recursively searches for a value for path in source map.
   215  // Returns nil if not found.
   216  // Note: This assumes that the path entries and map keys are lower cased.
   217  func (v *Viper) searchMap(source map[string]interface{}, path []string) interface{} {
   218  	if len(path) == 0 {
   219  		return source
   220  	}
   221  
   222  	next, ok := source[path[0]]
   223  	if ok {
   224  		// Fast path
   225  		if len(path) == 1 {
   226  			return next
   227  		}
   228  
   229  		// Nested case
   230  		switch next.(type) {
   231  		case map[interface{}]interface{}:
   232  			return v.searchMap(cast.ToStringMap(next), path[1:])
   233  		case map[string]interface{}:
   234  			// Type assertion is safe here since it is only reached
   235  			// if the type of `next` is the same as the type being asserted
   236  			return v.searchMap(next.(map[string]interface{}), path[1:])
   237  		default:
   238  			// got a value but nested key expected, return "nil" for not found
   239  			return nil
   240  		}
   241  	}
   242  	return nil
   243  }
   244  
   245  // searchMapWithPathPrefixes recursively searches for a value for path in source map.
   246  //
   247  // While searchMap() considers each path element as a single map key, this
   248  // function searches for, and prioritizes, merged path elements.
   249  // e.g., if in the source, "foo" is defined with a sub-key "bar", and "foo.bar"
   250  // is also defined, this latter value is returned for path ["foo", "bar"].
   251  //
   252  // This should be useful only at config level (other maps may not contain dots
   253  // in their keys).
   254  //
   255  // Note: This assumes that the path entries and map keys are lower cased.
   256  func (v *Viper) searchMapWithPathPrefixes(source map[string]interface{}, path []string) interface{} {
   257  	if len(path) == 0 {
   258  		return source
   259  	}
   260  
   261  	// search for path prefixes, starting from the longest one
   262  	for i := len(path); i > 0; i-- {
   263  		prefixKey := strings.ToLower(strings.Join(path[0:i], v.keyDelim))
   264  
   265  		next, ok := source[prefixKey]
   266  		if ok {
   267  			// Fast path
   268  			if i == len(path) {
   269  				return next
   270  			}
   271  
   272  			// Nested case
   273  			var val interface{}
   274  			switch next.(type) {
   275  			case map[interface{}]interface{}:
   276  				val = v.searchMapWithPathPrefixes(cast.ToStringMap(next), path[i:])
   277  			case map[string]interface{}:
   278  				// Type assertion is safe here since it is only reached
   279  				// if the type of `next` is the same as the type being asserted
   280  				val = v.searchMapWithPathPrefixes(next.(map[string]interface{}), path[i:])
   281  			default:
   282  				// got a value but nested key expected, do nothing and look for next prefix
   283  			}
   284  			if val != nil {
   285  				return val
   286  			}
   287  		}
   288  	}
   289  
   290  	// not found
   291  	return nil
   292  }
   293  
   294  // isPathShadowedInDeepMap makes sure the given path is not shadowed somewhere
   295  // on its path in the map.
   296  // e.g., if "foo.bar" has a value in the given map, it “shadows”
   297  //       "foo.bar.baz" in a lower-priority map
   298  func (v *Viper) isPathShadowedInDeepMap(path []string, m map[string]interface{}) string {
   299  	var parentVal interface{}
   300  	for i := 1; i < len(path); i++ {
   301  		parentVal = v.searchMap(m, path[0:i])
   302  		if parentVal == nil {
   303  			// not found, no need to add more path elements
   304  			return ""
   305  		}
   306  		switch parentVal.(type) {
   307  		case map[interface{}]interface{}:
   308  			continue
   309  		case map[string]interface{}:
   310  			continue
   311  		default:
   312  			// parentVal is a regular value which shadows "path"
   313  			return strings.Join(path[0:i], v.keyDelim)
   314  		}
   315  	}
   316  	return ""
   317  }
   318  
   319  // isPathShadowedInFlatMap makes sure the given path is not shadowed somewhere
   320  // in a sub-path of the map.
   321  // e.g., if "foo.bar" has a value in the given map, it “shadows”
   322  //       "foo.bar.baz" in a lower-priority map
   323  func (v *Viper) isPathShadowedInFlatMap(path []string, mi interface{}) string {
   324  	// unify input map
   325  	var m map[string]interface{}
   326  	switch mi.(type) {
   327  	case map[string]string, map[string]FlagValue:
   328  		m = cast.ToStringMap(mi)
   329  	default:
   330  		return ""
   331  	}
   332  
   333  	// scan paths
   334  	var parentKey string
   335  	for i := 1; i < len(path); i++ {
   336  		parentKey = strings.Join(path[0:i], v.keyDelim)
   337  		if _, ok := m[parentKey]; ok {
   338  			return parentKey
   339  		}
   340  	}
   341  	return ""
   342  }
   343  
   344  // isPathShadowedInAutoEnv makes sure the given path is not shadowed somewhere
   345  // in the environment, when automatic env is on.
   346  // e.g., if "foo.bar" has a value in the environment, it “shadows”
   347  //       "foo.bar.baz" in a lower-priority map
   348  func (v *Viper) isPathShadowedInAutoEnv(path []string) string {
   349  	var parentKey string
   350  	var val string
   351  	for i := 1; i < len(path); i++ {
   352  		parentKey = strings.Join(path[0:i], v.keyDelim)
   353  		if val = v.getEnv(v.mergeWithEnvPrefix(parentKey)); val != "" {
   354  			return parentKey
   355  		}
   356  	}
   357  	return ""
   358  }
   359  
   360  // SetTypeByDefaultValue enables or disables the inference of a key value's
   361  // type when the Get function is used based upon a key's default value as
   362  // opposed to the value returned based on the normal fetch logic.
   363  //
   364  // For example, if a key has a default value of []string{} and the same key
   365  // is set via an environment variable to "a b c", a call to the Get function
   366  // would return a string slice for the key if the key's type is inferred by
   367  // the default value and the Get function would return:
   368  //
   369  //   []string {"a", "b", "c"}
   370  //
   371  // Otherwise the Get function would return:
   372  //
   373  //   "a b c"
   374  func SetTypeByDefaultValue(enable bool) { v.SetTypeByDefaultValue(enable) }
   375  func (v *Viper) SetTypeByDefaultValue(enable bool) {
   376  	v.typeByDefValue = enable
   377  }
   378  
   379  // GetViper gets the global Viper instance.
   380  func GetViper() *Viper {
   381  	return v
   382  }
   383  
   384  // Get can retrieve any value given the key to use.
   385  // Get is case-insensitive for a key.
   386  // Get has the behavior of returning the value associated with the first
   387  // place from where it is set. Viper will check in the following order:
   388  // override, flag, env, config file, key/value store, default
   389  //
   390  // Get returns an interface. For a specific value use one of the Get____ methods.
   391  func Get(key string) interface{} { return v.Get(key) }
   392  func (v *Viper) Get(key string) interface{} {
   393  	lcaseKey := strings.ToLower(key)
   394  	val := v.find(lcaseKey)
   395  	if val == nil {
   396  		return nil
   397  	}
   398  
   399  	if v.typeByDefValue {
   400  		// TODO(bep) this branch isn't covered by a single test.
   401  		valType := val
   402  		path := strings.Split(lcaseKey, v.keyDelim)
   403  		defVal := v.searchMap(v.defaults, path)
   404  		if defVal != nil {
   405  			valType = defVal
   406  		}
   407  
   408  		switch valType.(type) {
   409  		case bool:
   410  			return cast.ToBool(val)
   411  		case string:
   412  			return cast.ToString(val)
   413  		case int64, int32, int16, int8, int:
   414  			return cast.ToInt(val)
   415  		case float64, float32:
   416  			return cast.ToFloat64(val)
   417  		case time.Time:
   418  			return cast.ToTime(val)
   419  		case time.Duration:
   420  			return cast.ToDuration(val)
   421  		case []string:
   422  			return cast.ToStringSlice(val)
   423  		}
   424  	}
   425  
   426  	return val
   427  }
   428  
   429  // Sub returns new Viper instance representing a sub tree of this instance.
   430  // Sub is case-insensitive for a key.
   431  func Sub(key string) *Viper { return v.Sub(key) }
   432  func (v *Viper) Sub(key string) *Viper {
   433  	subv := New()
   434  	data := v.Get(key)
   435  	if data == nil {
   436  		return nil
   437  	}
   438  
   439  	if reflect.TypeOf(data).Kind() == reflect.Map {
   440  		subv.config = cast.ToStringMap(data)
   441  		return subv
   442  	}
   443  	return nil
   444  }
   445  
   446  // GetString returns the value associated with the key as a string.
   447  func GetString(key string) string { return v.GetString(key) }
   448  func (v *Viper) GetString(key string) string {
   449  	return cast.ToString(v.Get(key))
   450  }
   451  
   452  // GetBool returns the value associated with the key as a boolean.
   453  func GetBool(key string) bool { return v.GetBool(key) }
   454  func (v *Viper) GetBool(key string) bool {
   455  	return cast.ToBool(v.Get(key))
   456  }
   457  
   458  // GetInt returns the value associated with the key as an integer.
   459  func GetInt(key string) int { return v.GetInt(key) }
   460  func (v *Viper) GetInt(key string) int {
   461  	return cast.ToInt(v.Get(key))
   462  }
   463  
   464  // GetInt64 returns the value associated with the key as an integer.
   465  func GetInt64(key string) int64 { return v.GetInt64(key) }
   466  func (v *Viper) GetInt64(key string) int64 {
   467  	return cast.ToInt64(v.Get(key))
   468  }
   469  
   470  // GetFloat64 returns the value associated with the key as a float64.
   471  func GetFloat64(key string) float64 { return v.GetFloat64(key) }
   472  func (v *Viper) GetFloat64(key string) float64 {
   473  	return cast.ToFloat64(v.Get(key))
   474  }
   475  
   476  // GetTime returns the value associated with the key as time.
   477  func GetTime(key string) time.Time { return v.GetTime(key) }
   478  func (v *Viper) GetTime(key string) time.Time {
   479  	return cast.ToTime(v.Get(key))
   480  }
   481  
   482  // GetDuration returns the value associated with the key as a duration.
   483  func GetDuration(key string) time.Duration { return v.GetDuration(key) }
   484  func (v *Viper) GetDuration(key string) time.Duration {
   485  	return cast.ToDuration(v.Get(key))
   486  }
   487  
   488  // GetStringSlice returns the value associated with the key as a slice of strings.
   489  func GetStringSlice(key string) []string { return v.GetStringSlice(key) }
   490  func (v *Viper) GetStringSlice(key string) []string {
   491  	return cast.ToStringSlice(v.Get(key))
   492  }
   493  
   494  // GetStringMap returns the value associated with the key as a map of interfaces.
   495  func GetStringMap(key string) map[string]interface{} { return v.GetStringMap(key) }
   496  func (v *Viper) GetStringMap(key string) map[string]interface{} {
   497  	return cast.ToStringMap(v.Get(key))
   498  }
   499  
   500  // GetStringMapString returns the value associated with the key as a map of strings.
   501  func GetStringMapString(key string) map[string]string { return v.GetStringMapString(key) }
   502  func (v *Viper) GetStringMapString(key string) map[string]string {
   503  	return cast.ToStringMapString(v.Get(key))
   504  }
   505  
   506  // GetStringMapStringSlice returns the value associated with the key as a map to a slice of strings.
   507  func GetStringMapStringSlice(key string) map[string][]string { return v.GetStringMapStringSlice(key) }
   508  func (v *Viper) GetStringMapStringSlice(key string) map[string][]string {
   509  	return cast.ToStringMapStringSlice(v.Get(key))
   510  }
   511  
   512  // GetSizeInBytes returns the size of the value associated with the given key
   513  // in bytes.
   514  func GetSizeInBytes(key string) uint { return v.GetSizeInBytes(key) }
   515  func (v *Viper) GetSizeInBytes(key string) uint {
   516  	sizeStr := cast.ToString(v.Get(key))
   517  	return parseSizeInBytes(sizeStr)
   518  }
   519  
   520  // UnmarshalKey takes a single key and unmarshals it into a Struct.
   521  func UnmarshalKey(key string, rawVal interface{}) error { return v.UnmarshalKey(key, rawVal) }
   522  func (v *Viper) UnmarshalKey(key string, rawVal interface{}) error {
   523  	err := decode(v.Get(key), defaultDecoderConfig(rawVal))
   524  
   525  	if err != nil {
   526  		return err
   527  	}
   528  
   529  	v.insensitiviseMaps()
   530  
   531  	return nil
   532  }
   533  
   534  // Unmarshal unmarshals the config into a Struct. Make sure that the tags
   535  // on the fields of the structure are properly set.
   536  func Unmarshal(rawVal interface{}) error { return v.Unmarshal(rawVal) }
   537  func (v *Viper) Unmarshal(rawVal interface{}) error {
   538  	err := decode(v.AllSettings(), defaultDecoderConfig(rawVal))
   539  
   540  	if err != nil {
   541  		return err
   542  	}
   543  
   544  	v.insensitiviseMaps()
   545  
   546  	return nil
   547  }
   548  
   549  // defaultDecoderConfig returns default mapsstructure.DecoderConfig with suppot
   550  // of time.Duration values & string slices
   551  func defaultDecoderConfig(output interface{}) *mapstructure.DecoderConfig {
   552  	return &mapstructure.DecoderConfig{
   553  		Metadata:         nil,
   554  		Result:           output,
   555  		WeaklyTypedInput: true,
   556  		DecodeHook: mapstructure.ComposeDecodeHookFunc(
   557  			mapstructure.StringToTimeDurationHookFunc(),
   558  			mapstructure.StringToSliceHookFunc(","),
   559  		),
   560  	}
   561  }
   562  
   563  // A wrapper around mapstructure.Decode that mimics the WeakDecode functionality
   564  func decode(input interface{}, config *mapstructure.DecoderConfig) error {
   565  	decoder, err := mapstructure.NewDecoder(config)
   566  	if err != nil {
   567  		return err
   568  	}
   569  	return decoder.Decode(input)
   570  }
   571  
   572  // UnmarshalExact unmarshals the config into a Struct, erroring if a field is nonexistent
   573  // in the destination struct.
   574  func (v *Viper) UnmarshalExact(rawVal interface{}) error {
   575  	config := defaultDecoderConfig(rawVal)
   576  	config.ErrorUnused = true
   577  
   578  	err := decode(v.AllSettings(), config)
   579  
   580  	if err != nil {
   581  		return err
   582  	}
   583  
   584  	v.insensitiviseMaps()
   585  
   586  	return nil
   587  }
   588  
   589  // BindPFlags binds a full flag set to the configuration, using each flag's long
   590  // name as the config key.
   591  func BindPFlags(flags *pflag.FlagSet) error { return v.BindPFlags(flags) }
   592  func (v *Viper) BindPFlags(flags *pflag.FlagSet) error {
   593  	return v.BindFlagValues(pflagValueSet{flags})
   594  }
   595  
   596  // BindPFlag binds a specific key to a pflag (as used by cobra).
   597  // Example (where serverCmd is a Cobra instance):
   598  //
   599  //	 serverCmd.Flags().Int("port", 1138, "Port to run Application server on")
   600  //	 Viper.BindPFlag("port", serverCmd.Flags().Lookup("port"))
   601  //
   602  func BindPFlag(key string, flag *pflag.Flag) error { return v.BindPFlag(key, flag) }
   603  func (v *Viper) BindPFlag(key string, flag *pflag.Flag) error {
   604  	return v.BindFlagValue(key, pflagValue{flag})
   605  }
   606  
   607  // BindFlagValues binds a full FlagValue set to the configuration, using each flag's long
   608  // name as the config key.
   609  func BindFlagValues(flags FlagValueSet) error { return v.BindFlagValues(flags) }
   610  func (v *Viper) BindFlagValues(flags FlagValueSet) (err error) {
   611  	flags.VisitAll(func(flag FlagValue) {
   612  		if err = v.BindFlagValue(flag.Name(), flag); err != nil {
   613  			return
   614  		}
   615  	})
   616  	return nil
   617  }
   618  
   619  // BindFlagValue binds a specific key to a FlagValue.
   620  // Example (where serverCmd is a Cobra instance):
   621  //
   622  //	 serverCmd.Flags().Int("port", 1138, "Port to run Application server on")
   623  //	 Viper.BindFlagValue("port", serverCmd.Flags().Lookup("port"))
   624  //
   625  func BindFlagValue(key string, flag FlagValue) error { return v.BindFlagValue(key, flag) }
   626  func (v *Viper) BindFlagValue(key string, flag FlagValue) error {
   627  	if flag == nil {
   628  		return fmt.Errorf("flag for %q is nil", key)
   629  	}
   630  	v.pflags[strings.ToLower(key)] = flag
   631  	return nil
   632  }
   633  
   634  // BindEnv binds a Viper key to a ENV variable.
   635  // ENV variables are case sensitive.
   636  // If only a key is provided, it will use the env key matching the key, uppercased.
   637  // EnvPrefix will be used when set when env name is not provided.
   638  func BindEnv(input ...string) error { return v.BindEnv(input...) }
   639  func (v *Viper) BindEnv(input ...string) error {
   640  	var key, envkey string
   641  	if len(input) == 0 {
   642  		return fmt.Errorf("BindEnv missing key to bind to")
   643  	}
   644  
   645  	key = strings.ToLower(input[0])
   646  
   647  	if len(input) == 1 {
   648  		envkey = v.mergeWithEnvPrefix(key)
   649  	} else {
   650  		envkey = input[1]
   651  	}
   652  
   653  	v.env[key] = envkey
   654  
   655  	return nil
   656  }
   657  
   658  // Given a key, find the value.
   659  // Viper will check in the following order:
   660  // flag, env, config file, key/value store, default.
   661  // Viper will check to see if an alias exists first.
   662  // Note: this assumes a lower-cased key given.
   663  func (v *Viper) find(lcaseKey string) interface{} {
   664  
   665  	var (
   666  		val    interface{}
   667  		exists bool
   668  		path   = strings.Split(lcaseKey, v.keyDelim)
   669  		nested = len(path) > 1
   670  	)
   671  
   672  	// compute the path through the nested maps to the nested value
   673  	if nested && v.isPathShadowedInDeepMap(path, castMapStringToMapInterface(v.aliases)) != "" {
   674  		return nil
   675  	}
   676  
   677  	// if the requested key is an alias, then return the proper key
   678  	lcaseKey = v.realKey(lcaseKey)
   679  	path = strings.Split(lcaseKey, v.keyDelim)
   680  	nested = len(path) > 1
   681  
   682  	// Set() override first
   683  	val = v.searchMap(v.override, path)
   684  	if val != nil {
   685  		return val
   686  	}
   687  	if nested && v.isPathShadowedInDeepMap(path, v.override) != "" {
   688  		return nil
   689  	}
   690  
   691  	// PFlag override next
   692  	flag, exists := v.pflags[lcaseKey]
   693  	if exists && flag.HasChanged() {
   694  		switch flag.ValueType() {
   695  		case "int", "int8", "int16", "int32", "int64":
   696  			return cast.ToInt(flag.ValueString())
   697  		case "bool":
   698  			return cast.ToBool(flag.ValueString())
   699  		case "stringSlice":
   700  			s := strings.TrimPrefix(flag.ValueString(), "[")
   701  			s = strings.TrimSuffix(s, "]")
   702  			res, _ := readAsCSV(s)
   703  			return res
   704  		default:
   705  			return flag.ValueString()
   706  		}
   707  	}
   708  	if nested && v.isPathShadowedInFlatMap(path, v.pflags) != "" {
   709  		return nil
   710  	}
   711  
   712  	// Env override next
   713  	if v.automaticEnvApplied {
   714  		// even if it hasn't been registered, if automaticEnv is used,
   715  		// check any Get request
   716  		if val = v.getEnv(v.mergeWithEnvPrefix(lcaseKey)); val != "" {
   717  			return val
   718  		}
   719  		if nested && v.isPathShadowedInAutoEnv(path) != "" {
   720  			return nil
   721  		}
   722  	}
   723  	envkey, exists := v.env[lcaseKey]
   724  	if exists {
   725  		if val = v.getEnv(envkey); val != "" {
   726  			return val
   727  		}
   728  	}
   729  	if nested && v.isPathShadowedInFlatMap(path, v.env) != "" {
   730  		return nil
   731  	}
   732  
   733  	// Config file next
   734  	val = v.searchMapWithPathPrefixes(v.config, path)
   735  	if val != nil {
   736  		return val
   737  	}
   738  	if nested && v.isPathShadowedInDeepMap(path, v.config) != "" {
   739  		return nil
   740  	}
   741  
   742  	// Default next
   743  	val = v.searchMap(v.defaults, path)
   744  	if val != nil {
   745  		return val
   746  	}
   747  	if nested && v.isPathShadowedInDeepMap(path, v.defaults) != "" {
   748  		return nil
   749  	}
   750  
   751  	// last chance: if no other value is returned and a flag does exist for the value,
   752  	// get the flag's value even if the flag's value has not changed
   753  	if flag, exists := v.pflags[lcaseKey]; exists {
   754  		switch flag.ValueType() {
   755  		case "int", "int8", "int16", "int32", "int64":
   756  			return cast.ToInt(flag.ValueString())
   757  		case "bool":
   758  			return cast.ToBool(flag.ValueString())
   759  		case "stringSlice":
   760  			s := strings.TrimPrefix(flag.ValueString(), "[")
   761  			s = strings.TrimSuffix(s, "]")
   762  			res, _ := readAsCSV(s)
   763  			return res
   764  		default:
   765  			return flag.ValueString()
   766  		}
   767  	}
   768  	// last item, no need to check shadowing
   769  
   770  	return nil
   771  }
   772  
   773  func readAsCSV(val string) ([]string, error) {
   774  	if val == "" {
   775  		return []string{}, nil
   776  	}
   777  	stringReader := strings.NewReader(val)
   778  	csvReader := csv.NewReader(stringReader)
   779  	return csvReader.Read()
   780  }
   781  
   782  // IsSet checks to see if the key has been set in any of the data locations.
   783  // IsSet is case-insensitive for a key.
   784  func IsSet(key string) bool { return v.IsSet(key) }
   785  func (v *Viper) IsSet(key string) bool {
   786  	lcaseKey := strings.ToLower(key)
   787  	val := v.find(lcaseKey)
   788  	return val != nil
   789  }
   790  
   791  // AutomaticEnv has Viper check ENV variables for all.
   792  // keys set in config, default & flags
   793  func AutomaticEnv() { v.AutomaticEnv() }
   794  func (v *Viper) AutomaticEnv() {
   795  	v.automaticEnvApplied = true
   796  }
   797  
   798  // SetEnvKeyReplacer sets the strings.Replacer on the viper object
   799  // Useful for mapping an environmental variable to a key that does
   800  // not match it.
   801  func SetEnvKeyReplacer(r *strings.Replacer) { v.SetEnvKeyReplacer(r) }
   802  func (v *Viper) SetEnvKeyReplacer(r *strings.Replacer) {
   803  	v.envKeyReplacer = r
   804  }
   805  
   806  // Aliases provide another accessor for the same key.
   807  // This enables one to change a name without breaking the application
   808  func RegisterAlias(alias string, key string) { v.RegisterAlias(alias, key) }
   809  func (v *Viper) RegisterAlias(alias string, key string) {
   810  	v.registerAlias(alias, strings.ToLower(key))
   811  }
   812  
   813  func (v *Viper) registerAlias(alias string, key string) {
   814  	alias = strings.ToLower(alias)
   815  	if alias != key && alias != v.realKey(key) {
   816  		_, exists := v.aliases[alias]
   817  
   818  		if !exists {
   819  			// if we alias something that exists in one of the maps to another
   820  			// name, we'll never be able to get that value using the original
   821  			// name, so move the config value to the new realkey.
   822  			if val, ok := v.config[alias]; ok {
   823  				delete(v.config, alias)
   824  				v.config[key] = val
   825  			}
   826  			if val, ok := v.defaults[alias]; ok {
   827  				delete(v.defaults, alias)
   828  				v.defaults[key] = val
   829  			}
   830  			if val, ok := v.override[alias]; ok {
   831  				delete(v.override, alias)
   832  				v.override[key] = val
   833  			}
   834  			v.aliases[alias] = key
   835  		}
   836  	} else {
   837  		jww.WARN.Println("Creating circular reference alias", alias, key, v.realKey(key))
   838  	}
   839  }
   840  
   841  func (v *Viper) realKey(key string) string {
   842  	newkey, exists := v.aliases[key]
   843  	if exists {
   844  		jww.DEBUG.Println("Alias", key, "to", newkey)
   845  		return v.realKey(newkey)
   846  	}
   847  	return key
   848  }
   849  
   850  // InConfig checks to see if the given key (or an alias) is in the config file.
   851  func InConfig(key string) bool { return v.InConfig(key) }
   852  func (v *Viper) InConfig(key string) bool {
   853  	// if the requested key is an alias, then return the proper key
   854  	key = v.realKey(key)
   855  
   856  	_, exists := v.config[key]
   857  	return exists
   858  }
   859  
   860  // SetDefault sets the default value for this key.
   861  // SetDefault is case-insensitive for a key.
   862  // Default only used when no value is provided by the user via flag, config or ENV.
   863  func SetDefault(key string, value interface{}) { v.SetDefault(key, value) }
   864  func (v *Viper) SetDefault(key string, value interface{}) {
   865  	// If alias passed in, then set the proper default
   866  	key = v.realKey(strings.ToLower(key))
   867  	value = toCaseInsensitiveValue(value)
   868  
   869  	path := strings.Split(key, v.keyDelim)
   870  	lastKey := strings.ToLower(path[len(path)-1])
   871  	deepestMap := deepSearch(v.defaults, path[0:len(path)-1])
   872  
   873  	// set innermost value
   874  	deepestMap[lastKey] = value
   875  }
   876  
   877  // Set sets the value for the key in the override regiser.
   878  // Set is case-insensitive for a key.
   879  // Will be used instead of values obtained via
   880  // flags, config file, ENV, default, or key/value store.
   881  func Set(key string, value interface{}) { v.Set(key, value) }
   882  func (v *Viper) Set(key string, value interface{}) {
   883  	// If alias passed in, then set the proper override
   884  	key = v.realKey(strings.ToLower(key))
   885  	value = toCaseInsensitiveValue(value)
   886  
   887  	path := strings.Split(key, v.keyDelim)
   888  	lastKey := strings.ToLower(path[len(path)-1])
   889  	deepestMap := deepSearch(v.override, path[0:len(path)-1])
   890  
   891  	// set innermost value
   892  	deepestMap[lastKey] = value
   893  }
   894  
   895  // ReadInConfig will discover and load the configuration file from disk
   896  // and key/value stores, searching in one of the defined paths.
   897  func ReadInConfig() error { return v.ReadInConfig() }
   898  func (v *Viper) ReadInConfig() error {
   899  	jww.INFO.Println("Attempting to read in config file")
   900  	filename, err := v.getConfigFile()
   901  	if err != nil {
   902  		return err
   903  	}
   904  
   905  	if !stringInSlice(v.getConfigType(), SupportedExts) {
   906  		return UnsupportedConfigError(v.getConfigType())
   907  	}
   908  
   909  	file, err := ioutil.ReadFile(filename)
   910  
   911  	if err != nil {
   912  		return err
   913  	}
   914  
   915  	config := make(map[string]interface{})
   916  
   917  	err = v.unmarshalReader(bytes.NewReader(file), config)
   918  	if err != nil {
   919  		return err
   920  	}
   921  
   922  	v.config = config
   923  	return nil
   924  }
   925  
   926  // MergeInConfig merges a new configuration with an existing config.
   927  func MergeInConfig() error { return v.MergeInConfig() }
   928  func (v *Viper) MergeInConfig() error {
   929  	jww.INFO.Println("Attempting to merge in config file")
   930  	filename, err := v.getConfigFile()
   931  	if err != nil {
   932  		return err
   933  	}
   934  
   935  	if !stringInSlice(v.getConfigType(), SupportedExts) {
   936  		return UnsupportedConfigError(v.getConfigType())
   937  	}
   938  
   939  	file, err := ioutil.ReadFile(filename)
   940  	if err != nil {
   941  		return err
   942  	}
   943  
   944  	return v.MergeConfig(bytes.NewReader(file))
   945  }
   946  
   947  // ReadConfig will read a configuration file, setting existing keys to nil if the
   948  // key does not exist in the file.
   949  func ReadConfig(in io.Reader) error { return v.ReadConfig(in) }
   950  func (v *Viper) ReadConfig(in io.Reader) error {
   951  	v.config = make(map[string]interface{})
   952  	return v.unmarshalReader(in, v.config)
   953  }
   954  
   955  // MergeConfig merges a new configuration with an existing config.
   956  func MergeConfig(in io.Reader) error { return v.MergeConfig(in) }
   957  func (v *Viper) MergeConfig(in io.Reader) error {
   958  	if v.config == nil {
   959  		v.config = make(map[string]interface{})
   960  	}
   961  	cfg := make(map[string]interface{})
   962  	if err := v.unmarshalReader(in, cfg); err != nil {
   963  		return err
   964  	}
   965  	mergeMaps(cfg, v.config, nil)
   966  	return nil
   967  }
   968  
   969  func keyExists(k string, m map[string]interface{}) string {
   970  	lk := strings.ToLower(k)
   971  	for mk := range m {
   972  		lmk := strings.ToLower(mk)
   973  		if lmk == lk {
   974  			return mk
   975  		}
   976  	}
   977  	return ""
   978  }
   979  
   980  func castToMapStringInterface(
   981  	src map[interface{}]interface{}) map[string]interface{} {
   982  	tgt := map[string]interface{}{}
   983  	for k, v := range src {
   984  		tgt[fmt.Sprintf("%v", k)] = v
   985  	}
   986  	return tgt
   987  }
   988  
   989  func castMapStringToMapInterface(src map[string]string) map[string]interface{} {
   990  	tgt := map[string]interface{}{}
   991  	for k, v := range src {
   992  		tgt[k] = v
   993  	}
   994  	return tgt
   995  }
   996  
   997  func castMapFlagToMapInterface(src map[string]FlagValue) map[string]interface{} {
   998  	tgt := map[string]interface{}{}
   999  	for k, v := range src {
  1000  		tgt[k] = v
  1001  	}
  1002  	return tgt
  1003  }
  1004  
  1005  // mergeMaps merges two maps. The `itgt` parameter is for handling go-yaml's
  1006  // insistence on parsing nested structures as `map[interface{}]interface{}`
  1007  // instead of using a `string` as the key for nest structures beyond one level
  1008  // deep. Both map types are supported as there is a go-yaml fork that uses
  1009  // `map[string]interface{}` instead.
  1010  func mergeMaps(
  1011  	src, tgt map[string]interface{}, itgt map[interface{}]interface{}) {
  1012  	for sk, sv := range src {
  1013  		tk := keyExists(sk, tgt)
  1014  		if tk == "" {
  1015  			jww.TRACE.Printf("tk=\"\", tgt[%s]=%v", sk, sv)
  1016  			tgt[sk] = sv
  1017  			if itgt != nil {
  1018  				itgt[sk] = sv
  1019  			}
  1020  			continue
  1021  		}
  1022  
  1023  		tv, ok := tgt[tk]
  1024  		if !ok {
  1025  			jww.TRACE.Printf("tgt[%s] != ok, tgt[%s]=%v", tk, sk, sv)
  1026  			tgt[sk] = sv
  1027  			if itgt != nil {
  1028  				itgt[sk] = sv
  1029  			}
  1030  			continue
  1031  		}
  1032  
  1033  		svType := reflect.TypeOf(sv)
  1034  		tvType := reflect.TypeOf(tv)
  1035  		if svType != tvType {
  1036  			jww.ERROR.Printf(
  1037  				"svType != tvType; key=%s, st=%v, tt=%v, sv=%v, tv=%v",
  1038  				sk, svType, tvType, sv, tv)
  1039  			continue
  1040  		}
  1041  
  1042  		jww.TRACE.Printf("processing key=%s, st=%v, tt=%v, sv=%v, tv=%v",
  1043  			sk, svType, tvType, sv, tv)
  1044  
  1045  		switch ttv := tv.(type) {
  1046  		case map[interface{}]interface{}:
  1047  			jww.TRACE.Printf("merging maps (must convert)")
  1048  			tsv := sv.(map[interface{}]interface{})
  1049  			ssv := castToMapStringInterface(tsv)
  1050  			stv := castToMapStringInterface(ttv)
  1051  			mergeMaps(ssv, stv, ttv)
  1052  		case map[string]interface{}:
  1053  			jww.TRACE.Printf("merging maps")
  1054  			mergeMaps(sv.(map[string]interface{}), ttv, nil)
  1055  		default:
  1056  			jww.TRACE.Printf("setting value")
  1057  			tgt[tk] = sv
  1058  			if itgt != nil {
  1059  				itgt[tk] = sv
  1060  			}
  1061  		}
  1062  	}
  1063  }
  1064  
  1065  // Unmarshall a Reader into a map.
  1066  // Should probably be an unexported function.
  1067  func unmarshalReader(in io.Reader, c map[string]interface{}) error {
  1068  	return v.unmarshalReader(in, c)
  1069  }
  1070  
  1071  func (v *Viper) unmarshalReader(in io.Reader, c map[string]interface{}) error {
  1072  	return unmarshallConfigReader(in, c, v.getConfigType())
  1073  }
  1074  
  1075  func (v *Viper) insensitiviseMaps() {
  1076  	insensitiviseMap(v.config)
  1077  	insensitiviseMap(v.defaults)
  1078  	insensitiviseMap(v.override)
  1079  }
  1080  
  1081  // AllKeys returns all keys holding a value, regardless of where they are set.
  1082  // Nested keys are returned with a v.keyDelim (= ".") separator
  1083  func AllKeys() []string { return v.AllKeys() }
  1084  
  1085  func (v *Viper) AllKeys() []string {
  1086  	m := map[string]bool{}
  1087  	// add all paths, by order of descending priority to ensure correct shadowing
  1088  	m = v.flattenAndMergeMap(m, castMapStringToMapInterface(v.aliases), "")
  1089  	m = v.flattenAndMergeMap(m, v.override, "")
  1090  	m = v.mergeFlatMap(m, castMapFlagToMapInterface(v.pflags))
  1091  	m = v.mergeFlatMap(m, castMapStringToMapInterface(v.env))
  1092  	m = v.flattenAndMergeMap(m, v.config, "")
  1093  	m = v.flattenAndMergeMap(m, v.defaults, "")
  1094  
  1095  	// convert set of paths to list
  1096  	a := []string{}
  1097  	for x := range m {
  1098  		a = append(a, x)
  1099  	}
  1100  	return a
  1101  }
  1102  
  1103  // flattenAndMergeMap recursively flattens the given map into a map[string]bool
  1104  // of key paths (used as a set, easier to manipulate than a []string):
  1105  // - each path is merged into a single key string, delimited with v.keyDelim (= ".")
  1106  // - if a path is shadowed by an earlier value in the initial shadow map,
  1107  //   it is skipped.
  1108  // The resulting set of paths is merged to the given shadow set at the same time.
  1109  func (v *Viper) flattenAndMergeMap(shadow map[string]bool, m map[string]interface{}, prefix string) map[string]bool {
  1110  	if shadow != nil && prefix != "" && shadow[prefix] {
  1111  		// prefix is shadowed => nothing more to flatten
  1112  		return shadow
  1113  	}
  1114  	if shadow == nil {
  1115  		shadow = make(map[string]bool)
  1116  	}
  1117  
  1118  	var m2 map[string]interface{}
  1119  	if prefix != "" {
  1120  		prefix += v.keyDelim
  1121  	}
  1122  	for k, val := range m {
  1123  		fullKey := prefix + k
  1124  		switch val.(type) {
  1125  		case map[string]interface{}:
  1126  			m2 = val.(map[string]interface{})
  1127  		case map[interface{}]interface{}:
  1128  			m2 = cast.ToStringMap(val)
  1129  		default:
  1130  			// immediate value
  1131  			shadow[strings.ToLower(fullKey)] = true
  1132  			continue
  1133  		}
  1134  		// recursively merge to shadow map
  1135  		shadow = v.flattenAndMergeMap(shadow, m2, fullKey)
  1136  	}
  1137  	return shadow
  1138  }
  1139  
  1140  // mergeFlatMap merges the given maps, excluding values of the second map
  1141  // shadowed by values from the first map.
  1142  func (v *Viper) mergeFlatMap(shadow map[string]bool, m map[string]interface{}) map[string]bool {
  1143  	// scan keys
  1144  outer:
  1145  	for k, _ := range m {
  1146  		path := strings.Split(k, v.keyDelim)
  1147  		// scan intermediate paths
  1148  		var parentKey string
  1149  		for i := 1; i < len(path); i++ {
  1150  			parentKey = strings.Join(path[0:i], v.keyDelim)
  1151  			if shadow[parentKey] {
  1152  				// path is shadowed, continue
  1153  				continue outer
  1154  			}
  1155  		}
  1156  		// add key
  1157  		shadow[strings.ToLower(k)] = true
  1158  	}
  1159  	return shadow
  1160  }
  1161  
  1162  // AllSettings merges all settings and returns them as a map[string]interface{}.
  1163  func AllSettings() map[string]interface{} { return v.AllSettings() }
  1164  func (v *Viper) AllSettings() map[string]interface{} {
  1165  	m := map[string]interface{}{}
  1166  	// start from the list of keys, and construct the map one value at a time
  1167  	for _, k := range v.AllKeys() {
  1168  		value := v.Get(k)
  1169  		if value == nil {
  1170  			// should not happen, since AllKeys() returns only keys holding a value,
  1171  			// check just in case anything changes
  1172  			continue
  1173  		}
  1174  		path := strings.Split(k, v.keyDelim)
  1175  		lastKey := strings.ToLower(path[len(path)-1])
  1176  		deepestMap := deepSearch(m, path[0:len(path)-1])
  1177  		// set innermost value
  1178  		deepestMap[lastKey] = value
  1179  	}
  1180  	return m
  1181  }
  1182  
  1183  // SetConfigName sets name for the config file.
  1184  // Does not include extension.
  1185  func SetConfigName(in string) { v.SetConfigName(in) }
  1186  func (v *Viper) SetConfigName(in string) {
  1187  	if in != "" {
  1188  		v.configName = in
  1189  		v.configFile = ""
  1190  	}
  1191  }
  1192  
  1193  // SetConfigType sets the type of the configuration returned by the
  1194  // remote source, e.g. "json".
  1195  func SetConfigType(in string) { v.SetConfigType(in) }
  1196  func (v *Viper) SetConfigType(in string) {
  1197  	if in != "" {
  1198  		v.configType = in
  1199  	}
  1200  }
  1201  
  1202  func (v *Viper) getConfigType() string {
  1203  	if v.configType != "" {
  1204  		return v.configType
  1205  	}
  1206  
  1207  	cf, err := v.getConfigFile()
  1208  	if err != nil {
  1209  		return ""
  1210  	}
  1211  
  1212  	ext := filepath.Ext(cf)
  1213  
  1214  	if len(ext) > 1 {
  1215  		return ext[1:]
  1216  	}
  1217  
  1218  	return ""
  1219  }
  1220  
  1221  func (v *Viper) getConfigFile() (string, error) {
  1222  	// if explicitly set, then use it
  1223  	if v.configFile != "" {
  1224  		return v.configFile, nil
  1225  	}
  1226  
  1227  	cf, err := v.findConfigFile()
  1228  	if err != nil {
  1229  		return "", err
  1230  	}
  1231  
  1232  	v.configFile = cf
  1233  	return v.getConfigFile()
  1234  }
  1235  
  1236  func (v *Viper) searchInPath(in string) (filename string) {
  1237  	jww.DEBUG.Println("Searching for config in ", in)
  1238  	for _, ext := range SupportedExts {
  1239  		jww.DEBUG.Println("Checking for", filepath.Join(in, v.configName+"."+ext))
  1240  		if b, _ := exists(filepath.Join(in, v.configName+"."+ext)); b {
  1241  			jww.DEBUG.Println("Found: ", filepath.Join(in, v.configName+"."+ext))
  1242  			return filepath.Join(in, v.configName+"."+ext)
  1243  		}
  1244  	}
  1245  
  1246  	return ""
  1247  }
  1248  
  1249  // Search all configPaths for any config file.
  1250  // Returns the first path that exists (and is a config file).
  1251  func (v *Viper) findConfigFile() (string, error) {
  1252  	jww.INFO.Println("Searching for config in ", v.configPaths)
  1253  
  1254  	for _, cp := range v.configPaths {
  1255  		file := v.searchInPath(cp)
  1256  		if file != "" {
  1257  			return file, nil
  1258  		}
  1259  	}
  1260  	return "", ConfigFileNotFoundError{v.configName, fmt.Sprintf("%s", v.configPaths)}
  1261  }
  1262  
  1263  // Debug prints all configuration registries for debugging
  1264  // purposes.
  1265  func Debug() { v.Debug() }
  1266  func (v *Viper) Debug() {
  1267  	fmt.Printf("Aliases:\n%#v\n", v.aliases)
  1268  	fmt.Printf("Override:\n%#v\n", v.override)
  1269  	fmt.Printf("PFlags:\n%#v\n", v.pflags)
  1270  	fmt.Printf("Env:\n%#v\n", v.env)
  1271  	fmt.Printf("Config:\n%#v\n", v.config)
  1272  	fmt.Printf("Defaults:\n%#v\n", v.defaults)
  1273  }