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