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