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