github.com/peter-mogensen/viper@v1.1.1/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 "encoding/json" 26 "fmt" 27 "io" 28 "log" 29 "os" 30 "path/filepath" 31 "reflect" 32 "strings" 33 "time" 34 35 yaml "gopkg.in/yaml.v2" 36 37 "github.com/fsnotify/fsnotify" 38 "github.com/hashicorp/hcl" 39 "github.com/hashicorp/hcl/hcl/printer" 40 "github.com/magiconair/properties" 41 "github.com/mitchellh/mapstructure" 42 toml "github.com/pelletier/go-toml" 43 "github.com/spf13/afero" 44 "github.com/spf13/cast" 45 jww "github.com/spf13/jwalterweatherman" 46 "github.com/spf13/pflag" 47 ) 48 49 // ConfigMarshalError happens when failing to marshal the configuration. 50 type ConfigMarshalError struct { 51 err error 52 } 53 54 // Error returns the formatted configuration error. 55 func (e ConfigMarshalError) Error() string { 56 return fmt.Sprintf("While marshaling config: %s", e.err.Error()) 57 } 58 59 var v *Viper 60 61 type RemoteResponse struct { 62 Value []byte 63 Error error 64 } 65 66 func init() { 67 v = New() 68 } 69 70 type remoteConfigFactory interface { 71 Get(rp RemoteProvider) (io.Reader, error) 72 Watch(rp RemoteProvider) (io.Reader, error) 73 WatchChannel(rp RemoteProvider) (<-chan *RemoteResponse, chan bool) 74 } 75 76 // RemoteConfig is optional, see the remote package 77 var RemoteConfig remoteConfigFactory 78 79 // UnsupportedConfigError denotes encountering an unsupported 80 // configuration filetype. 81 type UnsupportedConfigError string 82 83 // Error returns the formatted configuration error. 84 func (str UnsupportedConfigError) Error() string { 85 return fmt.Sprintf("Unsupported Config Type %q", string(str)) 86 } 87 88 // UnsupportedRemoteProviderError denotes encountering an unsupported remote 89 // provider. Currently only etcd and Consul are supported. 90 type UnsupportedRemoteProviderError string 91 92 // Error returns the formatted remote provider error. 93 func (str UnsupportedRemoteProviderError) Error() string { 94 return fmt.Sprintf("Unsupported Remote Provider Type %q", string(str)) 95 } 96 97 // RemoteConfigError denotes encountering an error while trying to 98 // pull the configuration from the remote provider. 99 type RemoteConfigError string 100 101 // Error returns the formatted remote provider error 102 func (rce RemoteConfigError) Error() string { 103 return fmt.Sprintf("Remote Configurations Error: %s", string(rce)) 104 } 105 106 // ConfigFileNotFoundError denotes failing to find configuration file. 107 type ConfigFileNotFoundError struct { 108 name, locations string 109 } 110 111 // Error returns the formatted configuration error. 112 func (fnfe ConfigFileNotFoundError) Error() string { 113 return fmt.Sprintf("Config File %q Not Found in %q", fnfe.name, fnfe.locations) 114 } 115 116 // A DecoderConfigOption can be passed to viper.Unmarshal to configure 117 // mapstructure.DecoderConfig options 118 type DecoderConfigOption func(*mapstructure.DecoderConfig) 119 120 // DecodeHook returns a DecoderConfigOption which overrides the default 121 // DecoderConfig.DecodeHook value, the default is: 122 // 123 // mapstructure.ComposeDecodeHookFunc( 124 // mapstructure.StringToTimeDurationHookFunc(), 125 // mapstructure.StringToSliceHookFunc(","), 126 // ) 127 func DecodeHook(hook mapstructure.DecodeHookFunc) DecoderConfigOption { 128 return func(c *mapstructure.DecoderConfig) { 129 c.DecodeHook = hook 130 } 131 } 132 133 // Viper is a prioritized configuration registry. It 134 // maintains a set of configuration sources, fetches 135 // values to populate those, and provides them according 136 // to the source's priority. 137 // The priority of the sources is the following: 138 // 1. overrides 139 // 2. flags 140 // 3. env. variables 141 // 4. config file 142 // 5. key/value store 143 // 6. defaults 144 // 145 // For example, if values from the following sources were loaded: 146 // 147 // Defaults : { 148 // "secret": "", 149 // "user": "default", 150 // "endpoint": "https://localhost" 151 // } 152 // Config : { 153 // "user": "root" 154 // "secret": "defaultsecret" 155 // } 156 // Env : { 157 // "secret": "somesecretkey" 158 // } 159 // 160 // The resulting config will have the following values: 161 // 162 // { 163 // "secret": "somesecretkey", 164 // "user": "root", 165 // "endpoint": "https://localhost" 166 // } 167 type Viper struct { 168 // Delimiter that separates a list of keys 169 // used to access a nested value in one go 170 keyDelim string 171 172 // A set of paths to look for the config file in 173 configPaths []string 174 175 // The filesystem to read config from. 176 fs afero.Fs 177 178 // A set of remote providers to search for the configuration 179 remoteProviders []*defaultRemoteProvider 180 181 // Name of file to look for inside the path 182 configName string 183 configFile string 184 configType string 185 envPrefix string 186 187 automaticEnvApplied bool 188 envKeyReplacer *strings.Replacer 189 190 config map[string]interface{} 191 override map[string]interface{} 192 defaults map[string]interface{} 193 kvstore map[string]interface{} 194 pflags map[string]FlagValue 195 env map[string]string 196 aliases map[string]string 197 typeByDefValue bool 198 199 // Store read properties on the object so that we can write back in order with comments. 200 // This will only be used if the configuration read is a properties file. 201 properties *properties.Properties 202 203 onConfigChange func(fsnotify.Event) 204 } 205 206 // New returns an initialized Viper instance. 207 func New() *Viper { 208 v := new(Viper) 209 v.keyDelim = "." 210 v.configName = "config" 211 v.fs = afero.NewOsFs() 212 v.config = make(map[string]interface{}) 213 v.override = make(map[string]interface{}) 214 v.defaults = make(map[string]interface{}) 215 v.kvstore = make(map[string]interface{}) 216 v.pflags = make(map[string]FlagValue) 217 v.env = make(map[string]string) 218 v.aliases = make(map[string]string) 219 v.typeByDefValue = false 220 221 return v 222 } 223 224 // Intended for testing, will reset all to default settings. 225 // In the public interface for the viper package so applications 226 // can use it in their testing as well. 227 func Reset() { 228 v = New() 229 SupportedExts = []string{"json", "toml", "yaml", "yml", "properties", "props", "prop", "hcl"} 230 SupportedRemoteProviders = []string{"etcd", "consul"} 231 } 232 233 type defaultRemoteProvider struct { 234 provider string 235 endpoint string 236 path string 237 secretKeyring string 238 } 239 240 func (rp defaultRemoteProvider) Provider() string { 241 return rp.provider 242 } 243 244 func (rp defaultRemoteProvider) Endpoint() string { 245 return rp.endpoint 246 } 247 248 func (rp defaultRemoteProvider) Path() string { 249 return rp.path 250 } 251 252 func (rp defaultRemoteProvider) SecretKeyring() string { 253 return rp.secretKeyring 254 } 255 256 // RemoteProvider stores the configuration necessary 257 // to connect to a remote key/value store. 258 // Optional secretKeyring to unencrypt encrypted values 259 // can be provided. 260 type RemoteProvider interface { 261 Provider() string 262 Endpoint() string 263 Path() string 264 SecretKeyring() string 265 } 266 267 // SupportedExts are universally supported extensions. 268 var SupportedExts = []string{"json", "toml", "yaml", "yml", "properties", "props", "prop", "hcl"} 269 270 // SupportedRemoteProviders are universally supported remote providers. 271 var SupportedRemoteProviders = []string{"etcd", "consul"} 272 273 func OnConfigChange(run func(in fsnotify.Event)) { v.OnConfigChange(run) } 274 func (v *Viper) OnConfigChange(run func(in fsnotify.Event)) { 275 v.onConfigChange = run 276 } 277 278 func WatchConfig() { v.WatchConfig() } 279 func (v *Viper) WatchConfig() { 280 go func() { 281 watcher, err := fsnotify.NewWatcher() 282 if err != nil { 283 log.Fatal(err) 284 } 285 defer watcher.Close() 286 287 // we have to watch the entire directory to pick up renames/atomic saves in a cross-platform way 288 filename, err := v.getConfigFile() 289 if err != nil { 290 log.Println("error:", err) 291 return 292 } 293 294 configFile := filepath.Clean(filename) 295 configDir, _ := filepath.Split(configFile) 296 297 done := make(chan bool) 298 go func() { 299 for { 300 select { 301 case event := <-watcher.Events: 302 // we only care about the config file 303 if filepath.Clean(event.Name) == configFile { 304 if event.Op&fsnotify.Write == fsnotify.Write || event.Op&fsnotify.Create == fsnotify.Create { 305 err := v.ReadInConfig() 306 if err != nil { 307 log.Println("error:", err) 308 } 309 if v.onConfigChange != nil { 310 v.onConfigChange(event) 311 } 312 } 313 } 314 case err := <-watcher.Errors: 315 log.Println("error:", err) 316 } 317 } 318 }() 319 320 watcher.Add(configDir) 321 <-done 322 }() 323 } 324 325 // SetConfigFile explicitly defines the path, name and extension of the config file. 326 // Viper will use this and not check any of the config paths. 327 func SetConfigFile(in string) { v.SetConfigFile(in) } 328 func (v *Viper) SetConfigFile(in string) { 329 if in != "" { 330 v.configFile = in 331 } 332 } 333 334 // SetEnvPrefix defines a prefix that ENVIRONMENT variables will use. 335 // E.g. if your prefix is "spf", the env registry will look for env 336 // variables that start with "SPF_". 337 func SetEnvPrefix(in string) { v.SetEnvPrefix(in) } 338 func (v *Viper) SetEnvPrefix(in string) { 339 if in != "" { 340 v.envPrefix = in 341 } 342 } 343 344 func (v *Viper) mergeWithEnvPrefix(in string) string { 345 if v.envPrefix != "" { 346 return strings.ToUpper(v.envPrefix + "_" + in) 347 } 348 349 return strings.ToUpper(in) 350 } 351 352 // TODO: should getEnv logic be moved into find(). Can generalize the use of 353 // rewriting keys many things, Ex: Get('someKey') -> some_key 354 // (camel case to snake case for JSON keys perhaps) 355 356 // getEnv is a wrapper around os.Getenv which replaces characters in the original 357 // key. This allows env vars which have different keys than the config object 358 // keys. 359 func (v *Viper) getEnv(key string) string { 360 if v.envKeyReplacer != nil { 361 key = v.envKeyReplacer.Replace(key) 362 } 363 return os.Getenv(key) 364 } 365 366 // ConfigFileUsed returns the file used to populate the config registry. 367 func ConfigFileUsed() string { return v.ConfigFileUsed() } 368 func (v *Viper) ConfigFileUsed() string { return v.configFile } 369 370 // AddConfigPath adds a path for Viper to search for the config file in. 371 // Can be called multiple times to define multiple search paths. 372 func AddConfigPath(in string) { v.AddConfigPath(in) } 373 func (v *Viper) AddConfigPath(in string) { 374 if in != "" { 375 absin := absPathify(in) 376 jww.INFO.Println("adding", absin, "to paths to search") 377 if !stringInSlice(absin, v.configPaths) { 378 v.configPaths = append(v.configPaths, absin) 379 } 380 } 381 } 382 383 // AddRemoteProvider adds a remote configuration source. 384 // Remote Providers are searched in the order they are added. 385 // provider is a string value, "etcd" or "consul" are currently supported. 386 // endpoint is the url. etcd requires http://ip:port consul requires ip:port 387 // path is the path in the k/v store to retrieve configuration 388 // To retrieve a config file called myapp.json from /configs/myapp.json 389 // you should set path to /configs and set config name (SetConfigName()) to 390 // "myapp" 391 func AddRemoteProvider(provider, endpoint, path string) error { 392 return v.AddRemoteProvider(provider, endpoint, path) 393 } 394 func (v *Viper) AddRemoteProvider(provider, endpoint, path string) error { 395 if !stringInSlice(provider, SupportedRemoteProviders) { 396 return UnsupportedRemoteProviderError(provider) 397 } 398 if provider != "" && endpoint != "" { 399 jww.INFO.Printf("adding %s:%s to remote provider list", provider, endpoint) 400 rp := &defaultRemoteProvider{ 401 endpoint: endpoint, 402 provider: provider, 403 path: path, 404 } 405 if !v.providerPathExists(rp) { 406 v.remoteProviders = append(v.remoteProviders, rp) 407 } 408 } 409 return nil 410 } 411 412 // AddSecureRemoteProvider adds a remote configuration source. 413 // Secure Remote Providers are searched in the order they are added. 414 // provider is a string value, "etcd" or "consul" are currently supported. 415 // endpoint is the url. etcd requires http://ip:port consul requires ip:port 416 // secretkeyring is the filepath to your openpgp secret keyring. e.g. /etc/secrets/myring.gpg 417 // path is the path in the k/v store to retrieve configuration 418 // To retrieve a config file called myapp.json from /configs/myapp.json 419 // you should set path to /configs and set config name (SetConfigName()) to 420 // "myapp" 421 // Secure Remote Providers are implemented with github.com/xordataexchange/crypt 422 func AddSecureRemoteProvider(provider, endpoint, path, secretkeyring string) error { 423 return v.AddSecureRemoteProvider(provider, endpoint, path, secretkeyring) 424 } 425 426 func (v *Viper) AddSecureRemoteProvider(provider, endpoint, path, secretkeyring string) error { 427 if !stringInSlice(provider, SupportedRemoteProviders) { 428 return UnsupportedRemoteProviderError(provider) 429 } 430 if provider != "" && endpoint != "" { 431 jww.INFO.Printf("adding %s:%s to remote provider list", provider, endpoint) 432 rp := &defaultRemoteProvider{ 433 endpoint: endpoint, 434 provider: provider, 435 path: path, 436 secretKeyring: secretkeyring, 437 } 438 if !v.providerPathExists(rp) { 439 v.remoteProviders = append(v.remoteProviders, rp) 440 } 441 } 442 return nil 443 } 444 445 func (v *Viper) providerPathExists(p *defaultRemoteProvider) bool { 446 for _, y := range v.remoteProviders { 447 if reflect.DeepEqual(y, p) { 448 return true 449 } 450 } 451 return false 452 } 453 454 // searchMap recursively searches for a value for path in source map. 455 // Returns nil if not found. 456 // Note: This assumes that the path entries and map keys are lower cased. 457 func (v *Viper) searchMap(source map[string]interface{}, path []string) interface{} { 458 if len(path) == 0 { 459 return source 460 } 461 462 next, ok := source[path[0]] 463 if ok { 464 // Fast path 465 if len(path) == 1 { 466 return next 467 } 468 469 // Nested case 470 switch next.(type) { 471 case map[interface{}]interface{}: 472 return v.searchMap(cast.ToStringMap(next), path[1:]) 473 case map[string]interface{}: 474 // Type assertion is safe here since it is only reached 475 // if the type of `next` is the same as the type being asserted 476 return v.searchMap(next.(map[string]interface{}), path[1:]) 477 default: 478 // got a value but nested key expected, return "nil" for not found 479 return nil 480 } 481 } 482 return nil 483 } 484 485 // searchMapWithPathPrefixes recursively searches for a value for path in source map. 486 // 487 // While searchMap() considers each path element as a single map key, this 488 // function searches for, and prioritizes, merged path elements. 489 // e.g., if in the source, "foo" is defined with a sub-key "bar", and "foo.bar" 490 // is also defined, this latter value is returned for path ["foo", "bar"]. 491 // 492 // This should be useful only at config level (other maps may not contain dots 493 // in their keys). 494 // 495 // Note: This assumes that the path entries and map keys are lower cased. 496 func (v *Viper) searchMapWithPathPrefixes(source map[string]interface{}, path []string) interface{} { 497 if len(path) == 0 { 498 return source 499 } 500 501 // search for path prefixes, starting from the longest one 502 for i := len(path); i > 0; i-- { 503 prefixKey := strings.ToLower(strings.Join(path[0:i], v.keyDelim)) 504 505 next, ok := source[prefixKey] 506 if ok { 507 // Fast path 508 if i == len(path) { 509 return next 510 } 511 512 // Nested case 513 var val interface{} 514 switch next.(type) { 515 case map[interface{}]interface{}: 516 val = v.searchMapWithPathPrefixes(cast.ToStringMap(next), path[i:]) 517 case map[string]interface{}: 518 // Type assertion is safe here since it is only reached 519 // if the type of `next` is the same as the type being asserted 520 val = v.searchMapWithPathPrefixes(next.(map[string]interface{}), path[i:]) 521 default: 522 // got a value but nested key expected, do nothing and look for next prefix 523 } 524 if val != nil { 525 return val 526 } 527 } 528 } 529 530 // not found 531 return nil 532 } 533 534 // isPathShadowedInDeepMap makes sure the given path is not shadowed somewhere 535 // on its path in the map. 536 // e.g., if "foo.bar" has a value in the given map, it “shadows” 537 // "foo.bar.baz" in a lower-priority map 538 func (v *Viper) isPathShadowedInDeepMap(path []string, m map[string]interface{}) string { 539 var parentVal interface{} 540 for i := 1; i < len(path); i++ { 541 parentVal = v.searchMap(m, path[0:i]) 542 if parentVal == nil { 543 // not found, no need to add more path elements 544 return "" 545 } 546 switch parentVal.(type) { 547 case map[interface{}]interface{}: 548 continue 549 case map[string]interface{}: 550 continue 551 default: 552 // parentVal is a regular value which shadows "path" 553 return strings.Join(path[0:i], v.keyDelim) 554 } 555 } 556 return "" 557 } 558 559 // isPathShadowedInFlatMap makes sure the given path is not shadowed somewhere 560 // in a sub-path of the map. 561 // e.g., if "foo.bar" has a value in the given map, it “shadows” 562 // "foo.bar.baz" in a lower-priority map 563 func (v *Viper) isPathShadowedInFlatMap(path []string, mi interface{}) string { 564 // unify input map 565 var m map[string]interface{} 566 switch mi.(type) { 567 case map[string]string, map[string]FlagValue: 568 m = cast.ToStringMap(mi) 569 default: 570 return "" 571 } 572 573 // scan paths 574 var parentKey string 575 for i := 1; i < len(path); i++ { 576 parentKey = strings.Join(path[0:i], v.keyDelim) 577 if _, ok := m[parentKey]; ok { 578 return parentKey 579 } 580 } 581 return "" 582 } 583 584 // isPathShadowedInAutoEnv makes sure the given path is not shadowed somewhere 585 // in the environment, when automatic env is on. 586 // e.g., if "foo.bar" has a value in the environment, it “shadows” 587 // "foo.bar.baz" in a lower-priority map 588 func (v *Viper) isPathShadowedInAutoEnv(path []string) string { 589 var parentKey string 590 var val string 591 for i := 1; i < len(path); i++ { 592 parentKey = strings.Join(path[0:i], v.keyDelim) 593 if val = v.getEnv(v.mergeWithEnvPrefix(parentKey)); val != "" { 594 return parentKey 595 } 596 } 597 return "" 598 } 599 600 // SetTypeByDefaultValue enables or disables the inference of a key value's 601 // type when the Get function is used based upon a key's default value as 602 // opposed to the value returned based on the normal fetch logic. 603 // 604 // For example, if a key has a default value of []string{} and the same key 605 // is set via an environment variable to "a b c", a call to the Get function 606 // would return a string slice for the key if the key's type is inferred by 607 // the default value and the Get function would return: 608 // 609 // []string {"a", "b", "c"} 610 // 611 // Otherwise the Get function would return: 612 // 613 // "a b c" 614 func SetTypeByDefaultValue(enable bool) { v.SetTypeByDefaultValue(enable) } 615 func (v *Viper) SetTypeByDefaultValue(enable bool) { 616 v.typeByDefValue = enable 617 } 618 619 // GetViper gets the global Viper instance. 620 func GetViper() *Viper { 621 return v 622 } 623 624 // Get can retrieve any value given the key to use. 625 // Get is case-insensitive for a key. 626 // Get has the behavior of returning the value associated with the first 627 // place from where it is set. Viper will check in the following order: 628 // override, flag, env, config file, key/value store, default 629 // 630 // Get returns an interface. For a specific value use one of the Get____ methods. 631 func Get(key string) interface{} { return v.Get(key) } 632 func (v *Viper) Get(key string) interface{} { 633 lcaseKey := strings.ToLower(key) 634 val := v.find(lcaseKey) 635 if val == nil { 636 return nil 637 } 638 639 if v.typeByDefValue { 640 // TODO(bep) this branch isn't covered by a single test. 641 valType := val 642 path := strings.Split(lcaseKey, v.keyDelim) 643 defVal := v.searchMap(v.defaults, path) 644 if defVal != nil { 645 valType = defVal 646 } 647 648 switch valType.(type) { 649 case bool: 650 return cast.ToBool(val) 651 case string: 652 return cast.ToString(val) 653 case int64, int32, int16, int8, int: 654 return cast.ToInt(val) 655 case float64, float32: 656 return cast.ToFloat64(val) 657 case time.Time: 658 return cast.ToTime(val) 659 case time.Duration: 660 return cast.ToDuration(val) 661 case []string: 662 return cast.ToStringSlice(val) 663 } 664 } 665 666 return val 667 } 668 669 // Sub returns new Viper instance representing a sub tree of this instance. 670 // Sub is case-insensitive for a key. 671 func Sub(key string) *Viper { return v.Sub(key) } 672 func (v *Viper) Sub(key string) *Viper { 673 subv := New() 674 data := v.Get(key) 675 if data == nil { 676 return nil 677 } 678 679 if reflect.TypeOf(data).Kind() == reflect.Map { 680 subv.config = cast.ToStringMap(data) 681 return subv 682 } 683 return nil 684 } 685 686 // GetString returns the value associated with the key as a string. 687 func GetString(key string) string { return v.GetString(key) } 688 func (v *Viper) GetString(key string) string { 689 return cast.ToString(v.Get(key)) 690 } 691 692 // GetBool returns the value associated with the key as a boolean. 693 func GetBool(key string) bool { return v.GetBool(key) } 694 func (v *Viper) GetBool(key string) bool { 695 return cast.ToBool(v.Get(key)) 696 } 697 698 // GetInt returns the value associated with the key as an integer. 699 func GetInt(key string) int { return v.GetInt(key) } 700 func (v *Viper) GetInt(key string) int { 701 return cast.ToInt(v.Get(key)) 702 } 703 704 // GetInt32 returns the value associated with the key as an integer. 705 func GetInt32(key string) int32 { return v.GetInt32(key) } 706 func (v *Viper) GetInt32(key string) int32 { 707 return cast.ToInt32(v.Get(key)) 708 } 709 710 // GetInt64 returns the value associated with the key as an integer. 711 func GetInt64(key string) int64 { return v.GetInt64(key) } 712 func (v *Viper) GetInt64(key string) int64 { 713 return cast.ToInt64(v.Get(key)) 714 } 715 716 // GetFloat64 returns the value associated with the key as a float64. 717 func GetFloat64(key string) float64 { return v.GetFloat64(key) } 718 func (v *Viper) GetFloat64(key string) float64 { 719 return cast.ToFloat64(v.Get(key)) 720 } 721 722 // GetTime returns the value associated with the key as time. 723 func GetTime(key string) time.Time { return v.GetTime(key) } 724 func (v *Viper) GetTime(key string) time.Time { 725 return cast.ToTime(v.Get(key)) 726 } 727 728 // GetDuration returns the value associated with the key as a duration. 729 func GetDuration(key string) time.Duration { return v.GetDuration(key) } 730 func (v *Viper) GetDuration(key string) time.Duration { 731 return cast.ToDuration(v.Get(key)) 732 } 733 734 // GetStringSlice returns the value associated with the key as a slice of strings. 735 func GetStringSlice(key string) []string { return v.GetStringSlice(key) } 736 func (v *Viper) GetStringSlice(key string) []string { 737 return cast.ToStringSlice(v.Get(key)) 738 } 739 740 // GetStringMap returns the value associated with the key as a map of interfaces. 741 func GetStringMap(key string) map[string]interface{} { return v.GetStringMap(key) } 742 func (v *Viper) GetStringMap(key string) map[string]interface{} { 743 return cast.ToStringMap(v.Get(key)) 744 } 745 746 // GetStringMapString returns the value associated with the key as a map of strings. 747 func GetStringMapString(key string) map[string]string { return v.GetStringMapString(key) } 748 func (v *Viper) GetStringMapString(key string) map[string]string { 749 return cast.ToStringMapString(v.Get(key)) 750 } 751 752 // GetStringMapStringSlice returns the value associated with the key as a map to a slice of strings. 753 func GetStringMapStringSlice(key string) map[string][]string { return v.GetStringMapStringSlice(key) } 754 func (v *Viper) GetStringMapStringSlice(key string) map[string][]string { 755 return cast.ToStringMapStringSlice(v.Get(key)) 756 } 757 758 // GetSizeInBytes returns the size of the value associated with the given key 759 // in bytes. 760 func GetSizeInBytes(key string) uint { return v.GetSizeInBytes(key) } 761 func (v *Viper) GetSizeInBytes(key string) uint { 762 sizeStr := cast.ToString(v.Get(key)) 763 return parseSizeInBytes(sizeStr) 764 } 765 766 // UnmarshalKey takes a single key and unmarshals it into a Struct. 767 func UnmarshalKey(key string, rawVal interface{}, opts ...DecoderConfigOption) error { 768 return v.UnmarshalKey(key, rawVal, opts...) 769 } 770 func (v *Viper) UnmarshalKey(key string, rawVal interface{}, opts ...DecoderConfigOption) error { 771 err := decode(v.Get(key), defaultDecoderConfig(rawVal, opts...)) 772 773 if err != nil { 774 return err 775 } 776 777 v.insensitiviseMaps() 778 779 return nil 780 } 781 782 // Unmarshal unmarshals the config into a Struct. Make sure that the tags 783 // on the fields of the structure are properly set. 784 func Unmarshal(rawVal interface{}, opts ...DecoderConfigOption) error { 785 return v.Unmarshal(rawVal, opts...) 786 } 787 func (v *Viper) Unmarshal(rawVal interface{}, opts ...DecoderConfigOption) error { 788 err := decode(v.AllSettings(), defaultDecoderConfig(rawVal, opts...)) 789 790 if err != nil { 791 return err 792 } 793 794 v.insensitiviseMaps() 795 796 return nil 797 } 798 799 // defaultDecoderConfig returns default mapsstructure.DecoderConfig with suppot 800 // of time.Duration values & string slices 801 func defaultDecoderConfig(output interface{}, opts ...DecoderConfigOption) *mapstructure.DecoderConfig { 802 c := &mapstructure.DecoderConfig{ 803 Metadata: nil, 804 Result: output, 805 WeaklyTypedInput: true, 806 DecodeHook: mapstructure.ComposeDecodeHookFunc( 807 mapstructure.StringToTimeDurationHookFunc(), 808 mapstructure.StringToSliceHookFunc(","), 809 ), 810 } 811 for _, opt := range opts { 812 opt(c) 813 } 814 return c 815 } 816 817 // A wrapper around mapstructure.Decode that mimics the WeakDecode functionality 818 func decode(input interface{}, config *mapstructure.DecoderConfig) error { 819 decoder, err := mapstructure.NewDecoder(config) 820 if err != nil { 821 return err 822 } 823 return decoder.Decode(input) 824 } 825 826 // UnmarshalExact unmarshals the config into a Struct, erroring if a field is nonexistent 827 // in the destination struct. 828 func (v *Viper) UnmarshalExact(rawVal interface{}) error { 829 config := defaultDecoderConfig(rawVal) 830 config.ErrorUnused = true 831 832 err := decode(v.AllSettings(), config) 833 834 if err != nil { 835 return err 836 } 837 838 v.insensitiviseMaps() 839 840 return nil 841 } 842 843 // BindPFlags binds a full flag set to the configuration, using each flag's long 844 // name as the config key. 845 func BindPFlags(flags *pflag.FlagSet) error { return v.BindPFlags(flags) } 846 func (v *Viper) BindPFlags(flags *pflag.FlagSet) error { 847 return v.BindFlagValues(pflagValueSet{flags}) 848 } 849 850 // BindPFlag binds a specific key to a pflag (as used by cobra). 851 // Example (where serverCmd is a Cobra instance): 852 // 853 // serverCmd.Flags().Int("port", 1138, "Port to run Application server on") 854 // Viper.BindPFlag("port", serverCmd.Flags().Lookup("port")) 855 // 856 func BindPFlag(key string, flag *pflag.Flag) error { return v.BindPFlag(key, flag) } 857 func (v *Viper) BindPFlag(key string, flag *pflag.Flag) error { 858 return v.BindFlagValue(key, pflagValue{flag}) 859 } 860 861 // BindFlagValues binds a full FlagValue set to the configuration, using each flag's long 862 // name as the config key. 863 func BindFlagValues(flags FlagValueSet) error { return v.BindFlagValues(flags) } 864 func (v *Viper) BindFlagValues(flags FlagValueSet) (err error) { 865 flags.VisitAll(func(flag FlagValue) { 866 if err = v.BindFlagValue(flag.Name(), flag); err != nil { 867 return 868 } 869 }) 870 return nil 871 } 872 873 // BindFlagValue binds a specific key to a FlagValue. 874 // Example (where serverCmd is a Cobra instance): 875 // 876 // serverCmd.Flags().Int("port", 1138, "Port to run Application server on") 877 // Viper.BindFlagValue("port", serverCmd.Flags().Lookup("port")) 878 // 879 func BindFlagValue(key string, flag FlagValue) error { return v.BindFlagValue(key, flag) } 880 func (v *Viper) BindFlagValue(key string, flag FlagValue) error { 881 if flag == nil { 882 return fmt.Errorf("flag for %q is nil", key) 883 } 884 v.pflags[strings.ToLower(key)] = flag 885 return nil 886 } 887 888 // BindEnv binds a Viper key to a ENV variable. 889 // ENV variables are case sensitive. 890 // If only a key is provided, it will use the env key matching the key, uppercased. 891 // EnvPrefix will be used when set when env name is not provided. 892 func BindEnv(input ...string) error { return v.BindEnv(input...) } 893 func (v *Viper) BindEnv(input ...string) error { 894 var key, envkey string 895 if len(input) == 0 { 896 return fmt.Errorf("BindEnv missing key to bind to") 897 } 898 899 key = strings.ToLower(input[0]) 900 901 if len(input) == 1 { 902 envkey = v.mergeWithEnvPrefix(key) 903 } else { 904 envkey = input[1] 905 } 906 907 v.env[key] = envkey 908 909 return nil 910 } 911 912 // Given a key, find the value. 913 // Viper will check in the following order: 914 // flag, env, config file, key/value store, default. 915 // Viper will check to see if an alias exists first. 916 // Note: this assumes a lower-cased key given. 917 func (v *Viper) find(lcaseKey string) interface{} { 918 919 var ( 920 val interface{} 921 exists bool 922 path = strings.Split(lcaseKey, v.keyDelim) 923 nested = len(path) > 1 924 ) 925 926 // compute the path through the nested maps to the nested value 927 if nested && v.isPathShadowedInDeepMap(path, castMapStringToMapInterface(v.aliases)) != "" { 928 return nil 929 } 930 931 // if the requested key is an alias, then return the proper key 932 lcaseKey = v.realKey(lcaseKey) 933 path = strings.Split(lcaseKey, v.keyDelim) 934 nested = len(path) > 1 935 936 // Set() override first 937 val = v.searchMap(v.override, path) 938 if val != nil { 939 return val 940 } 941 if nested && v.isPathShadowedInDeepMap(path, v.override) != "" { 942 return nil 943 } 944 945 // PFlag override next 946 flag, exists := v.pflags[lcaseKey] 947 if exists && flag.HasChanged() { 948 switch flag.ValueType() { 949 case "int", "int8", "int16", "int32", "int64": 950 return cast.ToInt(flag.ValueString()) 951 case "bool": 952 return cast.ToBool(flag.ValueString()) 953 case "stringSlice": 954 s := strings.TrimPrefix(flag.ValueString(), "[") 955 s = strings.TrimSuffix(s, "]") 956 res, _ := readAsCSV(s) 957 return res 958 default: 959 return flag.ValueString() 960 } 961 } 962 if nested && v.isPathShadowedInFlatMap(path, v.pflags) != "" { 963 return nil 964 } 965 966 // Env override next 967 if v.automaticEnvApplied { 968 // even if it hasn't been registered, if automaticEnv is used, 969 // check any Get request 970 if val = v.getEnv(v.mergeWithEnvPrefix(lcaseKey)); val != "" { 971 return val 972 } 973 if nested && v.isPathShadowedInAutoEnv(path) != "" { 974 return nil 975 } 976 } 977 envkey, exists := v.env[lcaseKey] 978 if exists { 979 if val = v.getEnv(envkey); val != "" { 980 return val 981 } 982 } 983 if nested && v.isPathShadowedInFlatMap(path, v.env) != "" { 984 return nil 985 } 986 987 // Config file next 988 val = v.searchMapWithPathPrefixes(v.config, path) 989 if val != nil { 990 return val 991 } 992 if nested && v.isPathShadowedInDeepMap(path, v.config) != "" { 993 return nil 994 } 995 996 // K/V store next 997 val = v.searchMap(v.kvstore, path) 998 if val != nil { 999 return val 1000 } 1001 if nested && v.isPathShadowedInDeepMap(path, v.kvstore) != "" { 1002 return nil 1003 } 1004 1005 // Default next 1006 val = v.searchMap(v.defaults, path) 1007 if val != nil { 1008 return val 1009 } 1010 if nested && v.isPathShadowedInDeepMap(path, v.defaults) != "" { 1011 return nil 1012 } 1013 1014 // last chance: if no other value is returned and a flag does exist for the value, 1015 // get the flag's value even if the flag's value has not changed 1016 if flag, exists := v.pflags[lcaseKey]; exists { 1017 switch flag.ValueType() { 1018 case "int", "int8", "int16", "int32", "int64": 1019 return cast.ToInt(flag.ValueString()) 1020 case "bool": 1021 return cast.ToBool(flag.ValueString()) 1022 case "stringSlice": 1023 s := strings.TrimPrefix(flag.ValueString(), "[") 1024 s = strings.TrimSuffix(s, "]") 1025 res, _ := readAsCSV(s) 1026 return res 1027 default: 1028 return flag.ValueString() 1029 } 1030 } 1031 // last item, no need to check shadowing 1032 1033 return nil 1034 } 1035 1036 func readAsCSV(val string) ([]string, error) { 1037 if val == "" { 1038 return []string{}, nil 1039 } 1040 stringReader := strings.NewReader(val) 1041 csvReader := csv.NewReader(stringReader) 1042 return csvReader.Read() 1043 } 1044 1045 // IsSet checks to see if the key has been set in any of the data locations. 1046 // IsSet is case-insensitive for a key. 1047 func IsSet(key string) bool { return v.IsSet(key) } 1048 func (v *Viper) IsSet(key string) bool { 1049 lcaseKey := strings.ToLower(key) 1050 val := v.find(lcaseKey) 1051 return val != nil 1052 } 1053 1054 // AutomaticEnv has Viper check ENV variables for all. 1055 // keys set in config, default & flags 1056 func AutomaticEnv() { v.AutomaticEnv() } 1057 func (v *Viper) AutomaticEnv() { 1058 v.automaticEnvApplied = true 1059 } 1060 1061 // SetEnvKeyReplacer sets the strings.Replacer on the viper object 1062 // Useful for mapping an environmental variable to a key that does 1063 // not match it. 1064 func SetEnvKeyReplacer(r *strings.Replacer) { v.SetEnvKeyReplacer(r) } 1065 func (v *Viper) SetEnvKeyReplacer(r *strings.Replacer) { 1066 v.envKeyReplacer = r 1067 } 1068 1069 // Aliases provide another accessor for the same key. 1070 // This enables one to change a name without breaking the application 1071 func RegisterAlias(alias string, key string) { v.RegisterAlias(alias, key) } 1072 func (v *Viper) RegisterAlias(alias string, key string) { 1073 v.registerAlias(alias, strings.ToLower(key)) 1074 } 1075 1076 func (v *Viper) registerAlias(alias string, key string) { 1077 alias = strings.ToLower(alias) 1078 if alias != key && alias != v.realKey(key) { 1079 _, exists := v.aliases[alias] 1080 1081 if !exists { 1082 // if we alias something that exists in one of the maps to another 1083 // name, we'll never be able to get that value using the original 1084 // name, so move the config value to the new realkey. 1085 if val, ok := v.config[alias]; ok { 1086 delete(v.config, alias) 1087 v.config[key] = val 1088 } 1089 if val, ok := v.kvstore[alias]; ok { 1090 delete(v.kvstore, alias) 1091 v.kvstore[key] = val 1092 } 1093 if val, ok := v.defaults[alias]; ok { 1094 delete(v.defaults, alias) 1095 v.defaults[key] = val 1096 } 1097 if val, ok := v.override[alias]; ok { 1098 delete(v.override, alias) 1099 v.override[key] = val 1100 } 1101 v.aliases[alias] = key 1102 } 1103 } else { 1104 jww.WARN.Println("Creating circular reference alias", alias, key, v.realKey(key)) 1105 } 1106 } 1107 1108 func (v *Viper) realKey(key string) string { 1109 newkey, exists := v.aliases[key] 1110 if exists { 1111 jww.DEBUG.Println("Alias", key, "to", newkey) 1112 return v.realKey(newkey) 1113 } 1114 return key 1115 } 1116 1117 // InConfig checks to see if the given key (or an alias) is in the config file. 1118 func InConfig(key string) bool { return v.InConfig(key) } 1119 func (v *Viper) InConfig(key string) bool { 1120 // if the requested key is an alias, then return the proper key 1121 key = v.realKey(key) 1122 1123 _, exists := v.config[key] 1124 return exists 1125 } 1126 1127 // SetDefault sets the default value for this key. 1128 // SetDefault is case-insensitive for a key. 1129 // Default only used when no value is provided by the user via flag, config or ENV. 1130 func SetDefault(key string, value interface{}) { v.SetDefault(key, value) } 1131 func (v *Viper) SetDefault(key string, value interface{}) { 1132 // If alias passed in, then set the proper default 1133 key = v.realKey(strings.ToLower(key)) 1134 value = toCaseInsensitiveValue(value) 1135 1136 path := strings.Split(key, v.keyDelim) 1137 lastKey := strings.ToLower(path[len(path)-1]) 1138 deepestMap := deepSearch(v.defaults, path[0:len(path)-1]) 1139 1140 // set innermost value 1141 deepestMap[lastKey] = value 1142 } 1143 1144 // Set sets the value for the key in the override regiser. 1145 // Set is case-insensitive for a key. 1146 // Will be used instead of values obtained via 1147 // flags, config file, ENV, default, or key/value store. 1148 func Set(key string, value interface{}) { v.Set(key, value) } 1149 func (v *Viper) Set(key string, value interface{}) { 1150 // If alias passed in, then set the proper override 1151 key = v.realKey(strings.ToLower(key)) 1152 value = toCaseInsensitiveValue(value) 1153 1154 path := strings.Split(key, v.keyDelim) 1155 lastKey := strings.ToLower(path[len(path)-1]) 1156 deepestMap := deepSearch(v.override, path[0:len(path)-1]) 1157 1158 // set innermost value 1159 deepestMap[lastKey] = value 1160 } 1161 1162 // ReadInConfig will discover and load the configuration file from disk 1163 // and key/value stores, searching in one of the defined paths. 1164 func ReadInConfig() error { return v.ReadInConfig() } 1165 func (v *Viper) ReadInConfig() error { 1166 jww.INFO.Println("Attempting to read in config file") 1167 filename, err := v.getConfigFile() 1168 if err != nil { 1169 return err 1170 } 1171 1172 if !stringInSlice(v.getConfigType(), SupportedExts) { 1173 return UnsupportedConfigError(v.getConfigType()) 1174 } 1175 1176 jww.DEBUG.Println("Reading file: ", filename) 1177 file, err := afero.ReadFile(v.fs, filename) 1178 if err != nil { 1179 return err 1180 } 1181 1182 config := make(map[string]interface{}) 1183 1184 err = v.unmarshalReader(bytes.NewReader(file), config) 1185 if err != nil { 1186 return err 1187 } 1188 1189 v.config = config 1190 return nil 1191 } 1192 1193 // MergeInConfig merges a new configuration with an existing config. 1194 func MergeInConfig() error { return v.MergeInConfig() } 1195 func (v *Viper) MergeInConfig() error { 1196 jww.INFO.Println("Attempting to merge in config file") 1197 filename, err := v.getConfigFile() 1198 if err != nil { 1199 return err 1200 } 1201 1202 if !stringInSlice(v.getConfigType(), SupportedExts) { 1203 return UnsupportedConfigError(v.getConfigType()) 1204 } 1205 1206 file, err := afero.ReadFile(v.fs, filename) 1207 if err != nil { 1208 return err 1209 } 1210 1211 return v.MergeConfig(bytes.NewReader(file)) 1212 } 1213 1214 // ReadConfig will read a configuration file, setting existing keys to nil if the 1215 // key does not exist in the file. 1216 func ReadConfig(in io.Reader) error { return v.ReadConfig(in) } 1217 func (v *Viper) ReadConfig(in io.Reader) error { 1218 v.config = make(map[string]interface{}) 1219 return v.unmarshalReader(in, v.config) 1220 } 1221 1222 // MergeConfig merges a new configuration with an existing config. 1223 func MergeConfig(in io.Reader) error { return v.MergeConfig(in) } 1224 func (v *Viper) MergeConfig(in io.Reader) error { 1225 if v.config == nil { 1226 v.config = make(map[string]interface{}) 1227 } 1228 cfg := make(map[string]interface{}) 1229 if err := v.unmarshalReader(in, cfg); err != nil { 1230 return err 1231 } 1232 mergeMaps(cfg, v.config, nil) 1233 return nil 1234 } 1235 1236 // WriteConfig writes the current configuration to a file. 1237 func WriteConfig() error { return v.WriteConfig() } 1238 func (v *Viper) WriteConfig() error { 1239 filename, err := v.getConfigFile() 1240 if err != nil { 1241 return err 1242 } 1243 return v.writeConfig(filename, true) 1244 } 1245 1246 // SafeWriteConfig writes current configuration to file only if the file does not exist. 1247 func SafeWriteConfig() error { return v.SafeWriteConfig() } 1248 func (v *Viper) SafeWriteConfig() error { 1249 filename, err := v.getConfigFile() 1250 if err != nil { 1251 return err 1252 } 1253 return v.writeConfig(filename, false) 1254 } 1255 1256 // WriteConfigAs writes current configuration to a given filename. 1257 func WriteConfigAs(filename string) error { return v.WriteConfigAs(filename) } 1258 func (v *Viper) WriteConfigAs(filename string) error { 1259 return v.writeConfig(filename, true) 1260 } 1261 1262 // SafeWriteConfigAs writes current configuration to a given filename if it does not exist. 1263 func SafeWriteConfigAs(filename string) error { return v.SafeWriteConfigAs(filename) } 1264 func (v *Viper) SafeWriteConfigAs(filename string) error { 1265 return v.writeConfig(filename, false) 1266 } 1267 1268 func writeConfig(filename string, force bool) error { return v.writeConfig(filename, force) } 1269 func (v *Viper) writeConfig(filename string, force bool) error { 1270 jww.INFO.Println("Attempting to write configuration to file.") 1271 ext := filepath.Ext(filename) 1272 if len(ext) <= 1 { 1273 return fmt.Errorf("Filename: %s requires valid extension.", filename) 1274 } 1275 configType := ext[1:] 1276 if !stringInSlice(configType, SupportedExts) { 1277 return UnsupportedConfigError(configType) 1278 } 1279 if v.config == nil { 1280 v.config = make(map[string]interface{}) 1281 } 1282 var flags int 1283 if force == true { 1284 flags = os.O_CREATE | os.O_TRUNC | os.O_WRONLY 1285 } else { 1286 if _, err := os.Stat(filename); os.IsNotExist(err) { 1287 flags = os.O_WRONLY 1288 } else { 1289 return fmt.Errorf("File: %s exists. Use WriteConfig to overwrite.", filename) 1290 } 1291 } 1292 f, err := v.fs.OpenFile(filename, flags, os.FileMode(0644)) 1293 if err != nil { 1294 return err 1295 } 1296 return v.marshalWriter(f, configType) 1297 } 1298 1299 // Unmarshal a Reader into a map. 1300 // Should probably be an unexported function. 1301 func unmarshalReader(in io.Reader, c map[string]interface{}) error { 1302 return v.unmarshalReader(in, c) 1303 } 1304 func (v *Viper) unmarshalReader(in io.Reader, c map[string]interface{}) error { 1305 buf := new(bytes.Buffer) 1306 buf.ReadFrom(in) 1307 1308 switch strings.ToLower(v.getConfigType()) { 1309 case "yaml", "yml": 1310 if err := yaml.Unmarshal(buf.Bytes(), &c); err != nil { 1311 return ConfigParseError{err} 1312 } 1313 1314 case "json": 1315 if err := json.Unmarshal(buf.Bytes(), &c); err != nil { 1316 return ConfigParseError{err} 1317 } 1318 1319 case "hcl": 1320 obj, err := hcl.Parse(string(buf.Bytes())) 1321 if err != nil { 1322 return ConfigParseError{err} 1323 } 1324 if err = hcl.DecodeObject(&c, obj); err != nil { 1325 return ConfigParseError{err} 1326 } 1327 1328 case "toml": 1329 tree, err := toml.LoadReader(buf) 1330 if err != nil { 1331 return ConfigParseError{err} 1332 } 1333 tmap := tree.ToMap() 1334 for k, v := range tmap { 1335 c[k] = v 1336 } 1337 1338 case "properties", "props", "prop": 1339 v.properties = properties.NewProperties() 1340 var err error 1341 if v.properties, err = properties.Load(buf.Bytes(), properties.UTF8); err != nil { 1342 return ConfigParseError{err} 1343 } 1344 for _, key := range v.properties.Keys() { 1345 value, _ := v.properties.Get(key) 1346 // recursively build nested maps 1347 path := strings.Split(key, ".") 1348 lastKey := strings.ToLower(path[len(path)-1]) 1349 deepestMap := deepSearch(c, path[0:len(path)-1]) 1350 // set innermost value 1351 deepestMap[lastKey] = value 1352 } 1353 } 1354 1355 insensitiviseMap(c) 1356 return nil 1357 } 1358 1359 // Marshal a map into Writer. 1360 func marshalWriter(f afero.File, configType string) error { 1361 return v.marshalWriter(f, configType) 1362 } 1363 func (v *Viper) marshalWriter(f afero.File, configType string) error { 1364 c := v.AllSettings() 1365 switch configType { 1366 case "json": 1367 b, err := json.MarshalIndent(c, "", " ") 1368 if err != nil { 1369 return ConfigMarshalError{err} 1370 } 1371 _, err = f.WriteString(string(b)) 1372 if err != nil { 1373 return ConfigMarshalError{err} 1374 } 1375 1376 case "hcl": 1377 b, err := json.Marshal(c) 1378 ast, err := hcl.Parse(string(b)) 1379 if err != nil { 1380 return ConfigMarshalError{err} 1381 } 1382 err = printer.Fprint(f, ast.Node) 1383 if err != nil { 1384 return ConfigMarshalError{err} 1385 } 1386 1387 case "prop", "props", "properties": 1388 if v.properties == nil { 1389 v.properties = properties.NewProperties() 1390 } 1391 p := v.properties 1392 for _, key := range v.AllKeys() { 1393 _, _, err := p.Set(key, v.GetString(key)) 1394 if err != nil { 1395 return ConfigMarshalError{err} 1396 } 1397 } 1398 _, err := p.WriteComment(f, "#", properties.UTF8) 1399 if err != nil { 1400 return ConfigMarshalError{err} 1401 } 1402 1403 case "toml": 1404 t, err := toml.TreeFromMap(c) 1405 if err != nil { 1406 return ConfigMarshalError{err} 1407 } 1408 s := t.String() 1409 if _, err := f.WriteString(s); err != nil { 1410 return ConfigMarshalError{err} 1411 } 1412 1413 case "yaml", "yml": 1414 b, err := yaml.Marshal(c) 1415 if err != nil { 1416 return ConfigMarshalError{err} 1417 } 1418 if _, err = f.WriteString(string(b)); err != nil { 1419 return ConfigMarshalError{err} 1420 } 1421 } 1422 return nil 1423 } 1424 1425 func keyExists(k string, m map[string]interface{}) string { 1426 lk := strings.ToLower(k) 1427 for mk := range m { 1428 lmk := strings.ToLower(mk) 1429 if lmk == lk { 1430 return mk 1431 } 1432 } 1433 return "" 1434 } 1435 1436 func castToMapStringInterface( 1437 src map[interface{}]interface{}) map[string]interface{} { 1438 tgt := map[string]interface{}{} 1439 for k, v := range src { 1440 tgt[fmt.Sprintf("%v", k)] = v 1441 } 1442 return tgt 1443 } 1444 1445 func castMapStringToMapInterface(src map[string]string) map[string]interface{} { 1446 tgt := map[string]interface{}{} 1447 for k, v := range src { 1448 tgt[k] = v 1449 } 1450 return tgt 1451 } 1452 1453 func castMapFlagToMapInterface(src map[string]FlagValue) map[string]interface{} { 1454 tgt := map[string]interface{}{} 1455 for k, v := range src { 1456 tgt[k] = v 1457 } 1458 return tgt 1459 } 1460 1461 // mergeMaps merges two maps. The `itgt` parameter is for handling go-yaml's 1462 // insistence on parsing nested structures as `map[interface{}]interface{}` 1463 // instead of using a `string` as the key for nest structures beyond one level 1464 // deep. Both map types are supported as there is a go-yaml fork that uses 1465 // `map[string]interface{}` instead. 1466 func mergeMaps( 1467 src, tgt map[string]interface{}, itgt map[interface{}]interface{}) { 1468 for sk, sv := range src { 1469 tk := keyExists(sk, tgt) 1470 if tk == "" { 1471 jww.TRACE.Printf("tk=\"\", tgt[%s]=%v", sk, sv) 1472 tgt[sk] = sv 1473 if itgt != nil { 1474 itgt[sk] = sv 1475 } 1476 continue 1477 } 1478 1479 tv, ok := tgt[tk] 1480 if !ok { 1481 jww.TRACE.Printf("tgt[%s] != ok, tgt[%s]=%v", tk, sk, sv) 1482 tgt[sk] = sv 1483 if itgt != nil { 1484 itgt[sk] = sv 1485 } 1486 continue 1487 } 1488 1489 svType := reflect.TypeOf(sv) 1490 tvType := reflect.TypeOf(tv) 1491 if svType != tvType { 1492 jww.ERROR.Printf( 1493 "svType != tvType; key=%s, st=%v, tt=%v, sv=%v, tv=%v", 1494 sk, svType, tvType, sv, tv) 1495 continue 1496 } 1497 1498 jww.TRACE.Printf("processing key=%s, st=%v, tt=%v, sv=%v, tv=%v", 1499 sk, svType, tvType, sv, tv) 1500 1501 switch ttv := tv.(type) { 1502 case map[interface{}]interface{}: 1503 jww.TRACE.Printf("merging maps (must convert)") 1504 tsv := sv.(map[interface{}]interface{}) 1505 ssv := castToMapStringInterface(tsv) 1506 stv := castToMapStringInterface(ttv) 1507 mergeMaps(ssv, stv, ttv) 1508 case map[string]interface{}: 1509 jww.TRACE.Printf("merging maps") 1510 mergeMaps(sv.(map[string]interface{}), ttv, nil) 1511 default: 1512 jww.TRACE.Printf("setting value") 1513 tgt[tk] = sv 1514 if itgt != nil { 1515 itgt[tk] = sv 1516 } 1517 } 1518 } 1519 } 1520 1521 // ReadRemoteConfig attempts to get configuration from a remote source 1522 // and read it in the remote configuration registry. 1523 func ReadRemoteConfig() error { return v.ReadRemoteConfig() } 1524 func (v *Viper) ReadRemoteConfig() error { 1525 return v.getKeyValueConfig() 1526 } 1527 1528 func WatchRemoteConfig() error { return v.WatchRemoteConfig() } 1529 func (v *Viper) WatchRemoteConfig() error { 1530 return v.watchKeyValueConfig() 1531 } 1532 1533 func (v *Viper) WatchRemoteConfigOnChannel() error { 1534 return v.watchKeyValueConfigOnChannel() 1535 } 1536 1537 func (v *Viper) insensitiviseMaps() { 1538 insensitiviseMap(v.config) 1539 insensitiviseMap(v.defaults) 1540 insensitiviseMap(v.override) 1541 insensitiviseMap(v.kvstore) 1542 } 1543 1544 // Retrieve the first found remote configuration. 1545 func (v *Viper) getKeyValueConfig() error { 1546 if RemoteConfig == nil { 1547 return RemoteConfigError("Enable the remote features by doing a blank import of the viper/remote package: '_ github.com/spf13/viper/remote'") 1548 } 1549 1550 for _, rp := range v.remoteProviders { 1551 val, err := v.getRemoteConfig(rp) 1552 if err != nil { 1553 continue 1554 } 1555 v.kvstore = val 1556 return nil 1557 } 1558 return RemoteConfigError("No Files Found") 1559 } 1560 1561 func (v *Viper) getRemoteConfig(provider RemoteProvider) (map[string]interface{}, error) { 1562 reader, err := RemoteConfig.Get(provider) 1563 if err != nil { 1564 return nil, err 1565 } 1566 err = v.unmarshalReader(reader, v.kvstore) 1567 return v.kvstore, err 1568 } 1569 1570 // Retrieve the first found remote configuration. 1571 func (v *Viper) watchKeyValueConfigOnChannel() error { 1572 for _, rp := range v.remoteProviders { 1573 respc, _ := RemoteConfig.WatchChannel(rp) 1574 //Todo: Add quit channel 1575 go func(rc <-chan *RemoteResponse) { 1576 for { 1577 b := <-rc 1578 reader := bytes.NewReader(b.Value) 1579 v.unmarshalReader(reader, v.kvstore) 1580 } 1581 }(respc) 1582 return nil 1583 } 1584 return RemoteConfigError("No Files Found") 1585 } 1586 1587 // Retrieve the first found remote configuration. 1588 func (v *Viper) watchKeyValueConfig() error { 1589 for _, rp := range v.remoteProviders { 1590 val, err := v.watchRemoteConfig(rp) 1591 if err != nil { 1592 continue 1593 } 1594 v.kvstore = val 1595 return nil 1596 } 1597 return RemoteConfigError("No Files Found") 1598 } 1599 1600 func (v *Viper) watchRemoteConfig(provider RemoteProvider) (map[string]interface{}, error) { 1601 reader, err := RemoteConfig.Watch(provider) 1602 if err != nil { 1603 return nil, err 1604 } 1605 err = v.unmarshalReader(reader, v.kvstore) 1606 return v.kvstore, err 1607 } 1608 1609 // AllKeys returns all keys holding a value, regardless of where they are set. 1610 // Nested keys are returned with a v.keyDelim (= ".") separator 1611 func AllKeys() []string { return v.AllKeys() } 1612 func (v *Viper) AllKeys() []string { 1613 m := map[string]bool{} 1614 // add all paths, by order of descending priority to ensure correct shadowing 1615 m = v.flattenAndMergeMap(m, castMapStringToMapInterface(v.aliases), "") 1616 m = v.flattenAndMergeMap(m, v.override, "") 1617 m = v.mergeFlatMap(m, castMapFlagToMapInterface(v.pflags)) 1618 m = v.mergeFlatMap(m, castMapStringToMapInterface(v.env)) 1619 m = v.flattenAndMergeMap(m, v.config, "") 1620 m = v.flattenAndMergeMap(m, v.kvstore, "") 1621 m = v.flattenAndMergeMap(m, v.defaults, "") 1622 1623 // convert set of paths to list 1624 a := []string{} 1625 for x := range m { 1626 a = append(a, x) 1627 } 1628 return a 1629 } 1630 1631 // flattenAndMergeMap recursively flattens the given map into a map[string]bool 1632 // of key paths (used as a set, easier to manipulate than a []string): 1633 // - each path is merged into a single key string, delimited with v.keyDelim (= ".") 1634 // - if a path is shadowed by an earlier value in the initial shadow map, 1635 // it is skipped. 1636 // The resulting set of paths is merged to the given shadow set at the same time. 1637 func (v *Viper) flattenAndMergeMap(shadow map[string]bool, m map[string]interface{}, prefix string) map[string]bool { 1638 if shadow != nil && prefix != "" && shadow[prefix] { 1639 // prefix is shadowed => nothing more to flatten 1640 return shadow 1641 } 1642 if shadow == nil { 1643 shadow = make(map[string]bool) 1644 } 1645 1646 var m2 map[string]interface{} 1647 if prefix != "" { 1648 prefix += v.keyDelim 1649 } 1650 for k, val := range m { 1651 fullKey := prefix + k 1652 switch val.(type) { 1653 case map[string]interface{}: 1654 m2 = val.(map[string]interface{}) 1655 case map[interface{}]interface{}: 1656 m2 = cast.ToStringMap(val) 1657 default: 1658 // immediate value 1659 shadow[strings.ToLower(fullKey)] = true 1660 continue 1661 } 1662 // recursively merge to shadow map 1663 shadow = v.flattenAndMergeMap(shadow, m2, fullKey) 1664 } 1665 return shadow 1666 } 1667 1668 // mergeFlatMap merges the given maps, excluding values of the second map 1669 // shadowed by values from the first map. 1670 func (v *Viper) mergeFlatMap(shadow map[string]bool, m map[string]interface{}) map[string]bool { 1671 // scan keys 1672 outer: 1673 for k, _ := range m { 1674 path := strings.Split(k, v.keyDelim) 1675 // scan intermediate paths 1676 var parentKey string 1677 for i := 1; i < len(path); i++ { 1678 parentKey = strings.Join(path[0:i], v.keyDelim) 1679 if shadow[parentKey] { 1680 // path is shadowed, continue 1681 continue outer 1682 } 1683 } 1684 // add key 1685 shadow[strings.ToLower(k)] = true 1686 } 1687 return shadow 1688 } 1689 1690 // AllSettings merges all settings and returns them as a map[string]interface{}. 1691 func AllSettings() map[string]interface{} { return v.AllSettings() } 1692 func (v *Viper) AllSettings() map[string]interface{} { 1693 m := map[string]interface{}{} 1694 // start from the list of keys, and construct the map one value at a time 1695 for _, k := range v.AllKeys() { 1696 value := v.Get(k) 1697 if value == nil { 1698 // should not happen, since AllKeys() returns only keys holding a value, 1699 // check just in case anything changes 1700 continue 1701 } 1702 path := strings.Split(k, v.keyDelim) 1703 lastKey := strings.ToLower(path[len(path)-1]) 1704 deepestMap := deepSearch(m, path[0:len(path)-1]) 1705 // set innermost value 1706 deepestMap[lastKey] = value 1707 } 1708 return m 1709 } 1710 1711 // SetFs sets the filesystem to use to read configuration. 1712 func SetFs(fs afero.Fs) { v.SetFs(fs) } 1713 func (v *Viper) SetFs(fs afero.Fs) { 1714 v.fs = fs 1715 } 1716 1717 // SetConfigName sets name for the config file. 1718 // Does not include extension. 1719 func SetConfigName(in string) { v.SetConfigName(in) } 1720 func (v *Viper) SetConfigName(in string) { 1721 if in != "" { 1722 v.configName = in 1723 v.configFile = "" 1724 } 1725 } 1726 1727 // SetConfigType sets the type of the configuration returned by the 1728 // remote source, e.g. "json". 1729 func SetConfigType(in string) { v.SetConfigType(in) } 1730 func (v *Viper) SetConfigType(in string) { 1731 if in != "" { 1732 v.configType = in 1733 } 1734 } 1735 1736 func (v *Viper) getConfigType() string { 1737 if v.configType != "" { 1738 return v.configType 1739 } 1740 1741 cf, err := v.getConfigFile() 1742 if err != nil { 1743 return "" 1744 } 1745 1746 ext := filepath.Ext(cf) 1747 1748 if len(ext) > 1 { 1749 return ext[1:] 1750 } 1751 1752 return "" 1753 } 1754 1755 func (v *Viper) getConfigFile() (string, error) { 1756 if v.configFile == "" { 1757 cf, err := v.findConfigFile() 1758 if err != nil { 1759 return "", err 1760 } 1761 v.configFile = cf 1762 } 1763 return v.configFile, nil 1764 } 1765 1766 func (v *Viper) searchInPath(in string) (filename string) { 1767 jww.DEBUG.Println("Searching for config in ", in) 1768 for _, ext := range SupportedExts { 1769 jww.DEBUG.Println("Checking for", filepath.Join(in, v.configName+"."+ext)) 1770 if b, _ := exists(v.fs, filepath.Join(in, v.configName+"."+ext)); b { 1771 jww.DEBUG.Println("Found: ", filepath.Join(in, v.configName+"."+ext)) 1772 return filepath.Join(in, v.configName+"."+ext) 1773 } 1774 } 1775 1776 return "" 1777 } 1778 1779 // Search all configPaths for any config file. 1780 // Returns the first path that exists (and is a config file). 1781 func (v *Viper) findConfigFile() (string, error) { 1782 jww.INFO.Println("Searching for config in ", v.configPaths) 1783 1784 for _, cp := range v.configPaths { 1785 file := v.searchInPath(cp) 1786 if file != "" { 1787 return file, nil 1788 } 1789 } 1790 return "", ConfigFileNotFoundError{v.configName, fmt.Sprintf("%s", v.configPaths)} 1791 } 1792 1793 // Debug prints all configuration registries for debugging 1794 // purposes. 1795 func Debug() { v.Debug() } 1796 func (v *Viper) Debug() { 1797 fmt.Printf("Aliases:\n%#v\n", v.aliases) 1798 fmt.Printf("Override:\n%#v\n", v.override) 1799 fmt.Printf("PFlags:\n%#v\n", v.pflags) 1800 fmt.Printf("Env:\n%#v\n", v.env) 1801 fmt.Printf("Key/Value Store:\n%#v\n", v.kvstore) 1802 fmt.Printf("Config:\n%#v\n", v.config) 1803 fmt.Printf("Defaults:\n%#v\n", v.defaults) 1804 }