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