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