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