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