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