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