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