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