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