github.com/ava-labs/viper@v1.7.2-0.20210125155433-65cc0421b384/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 keysCaseSensitive bool 204 205 config map[string]interface{} 206 override map[string]interface{} 207 defaults map[string]interface{} 208 kvstore map[string]interface{} 209 pflags map[string]FlagValue 210 env map[string][]string 211 aliases map[string]string 212 typeByDefValue bool 213 214 // Store read properties on the object so that we can write back in order with comments. 215 // This will only be used if the configuration read is a properties file. 216 properties *properties.Properties 217 218 onConfigChange func(fsnotify.Event) 219 } 220 221 // New returns an initialized Viper instance. 222 func New() *Viper { 223 v := new(Viper) 224 v.keyDelim = "." 225 v.configName = "config" 226 v.configPermissions = os.FileMode(0644) 227 v.fs = afero.NewOsFs() 228 v.config = make(map[string]interface{}) 229 v.override = make(map[string]interface{}) 230 v.defaults = make(map[string]interface{}) 231 v.kvstore = make(map[string]interface{}) 232 v.pflags = make(map[string]FlagValue) 233 v.env = make(map[string][]string) 234 v.aliases = make(map[string]string) 235 v.typeByDefValue = false 236 237 return v 238 } 239 240 // Option configures Viper using the functional options paradigm popularized by Rob Pike and Dave Cheney. 241 // If you're unfamiliar with this style, 242 // see https://commandcenter.blogspot.com/2014/01/self-referential-functions-and-design.html and 243 // https://dave.cheney.net/2014/10/17/functional-options-for-friendly-apis. 244 type Option interface { 245 apply(v *Viper) 246 } 247 248 type optionFunc func(v *Viper) 249 250 func (fn optionFunc) apply(v *Viper) { 251 fn(v) 252 } 253 254 // KeyDelimiter sets the delimiter used for determining key parts. 255 // By default it's value is ".". 256 func KeyDelimiter(d string) Option { 257 return optionFunc(func(v *Viper) { 258 v.keyDelim = d 259 }) 260 } 261 262 // StringReplacer applies a set of replacements to a string. 263 type StringReplacer interface { 264 // Replace returns a copy of s with all replacements performed. 265 Replace(s string) string 266 } 267 268 // EnvKeyReplacer sets a replacer used for mapping environment variables to internal keys. 269 func EnvKeyReplacer(r StringReplacer) Option { 270 return optionFunc(func(v *Viper) { 271 v.envKeyReplacer = r 272 }) 273 } 274 275 // NewWithOptions creates a new Viper instance. 276 func NewWithOptions(opts ...Option) *Viper { 277 v := New() 278 279 for _, opt := range opts { 280 opt.apply(v) 281 } 282 283 return v 284 } 285 286 // Reset is intended for testing, will reset all to default settings. 287 // In the public interface for the viper package so applications 288 // can use it in their testing as well. 289 func Reset() { 290 v = New() 291 SupportedExts = []string{"json", "toml", "yaml", "yml", "properties", "props", "prop", "hcl", "dotenv", "env", "ini"} 292 SupportedRemoteProviders = []string{"etcd", "consul", "firestore"} 293 } 294 295 type defaultRemoteProvider struct { 296 provider string 297 endpoint string 298 path string 299 secretKeyring string 300 } 301 302 func (rp defaultRemoteProvider) Provider() string { 303 return rp.provider 304 } 305 306 func (rp defaultRemoteProvider) Endpoint() string { 307 return rp.endpoint 308 } 309 310 func (rp defaultRemoteProvider) Path() string { 311 return rp.path 312 } 313 314 func (rp defaultRemoteProvider) SecretKeyring() string { 315 return rp.secretKeyring 316 } 317 318 // RemoteProvider stores the configuration necessary 319 // to connect to a remote key/value store. 320 // Optional secretKeyring to unencrypt encrypted values 321 // can be provided. 322 type RemoteProvider interface { 323 Provider() string 324 Endpoint() string 325 Path() string 326 SecretKeyring() string 327 } 328 329 // SupportedExts are universally supported extensions. 330 var SupportedExts = []string{"json", "toml", "yaml", "yml", "properties", "props", "prop", "hcl", "dotenv", "env", "ini"} 331 332 // SupportedRemoteProviders are universally supported remote providers. 333 var SupportedRemoteProviders = []string{"etcd", "consul", "firestore"} 334 335 func OnConfigChange(run func(in fsnotify.Event)) { v.OnConfigChange(run) } 336 func (v *Viper) OnConfigChange(run func(in fsnotify.Event)) { 337 v.onConfigChange = run 338 } 339 340 func WatchConfig() { v.WatchConfig() } 341 342 func (v *Viper) WatchConfig() { 343 initWG := sync.WaitGroup{} 344 initWG.Add(1) 345 go func() { 346 watcher, err := fsnotify.NewWatcher() 347 if err != nil { 348 log.Fatal(err) 349 } 350 defer watcher.Close() 351 // we have to watch the entire directory to pick up renames/atomic saves in a cross-platform way 352 filename, err := v.getConfigFile() 353 if err != nil { 354 log.Printf("error: %v\n", err) 355 initWG.Done() 356 return 357 } 358 359 configFile := filepath.Clean(filename) 360 configDir, _ := filepath.Split(configFile) 361 realConfigFile, _ := filepath.EvalSymlinks(filename) 362 363 eventsWG := sync.WaitGroup{} 364 eventsWG.Add(1) 365 go func() { 366 for { 367 select { 368 case event, ok := <-watcher.Events: 369 if !ok { // 'Events' channel is closed 370 eventsWG.Done() 371 return 372 } 373 currentConfigFile, _ := filepath.EvalSymlinks(filename) 374 // we only care about the config file with the following cases: 375 // 1 - if the config file was modified or created 376 // 2 - if the real path to the config file changed (eg: k8s ConfigMap replacement) 377 const writeOrCreateMask = fsnotify.Write | fsnotify.Create 378 if (filepath.Clean(event.Name) == configFile && 379 event.Op&writeOrCreateMask != 0) || 380 (currentConfigFile != "" && currentConfigFile != realConfigFile) { 381 realConfigFile = currentConfigFile 382 err := v.ReadInConfig() 383 if err != nil { 384 log.Printf("error reading config file: %v\n", err) 385 } 386 if v.onConfigChange != nil { 387 v.onConfigChange(event) 388 } 389 } else if filepath.Clean(event.Name) == configFile && 390 event.Op&fsnotify.Remove&fsnotify.Remove != 0 { 391 eventsWG.Done() 392 return 393 } 394 395 case err, ok := <-watcher.Errors: 396 if ok { // 'Errors' channel is not closed 397 log.Printf("watcher error: %v\n", err) 398 } 399 eventsWG.Done() 400 return 401 } 402 } 403 }() 404 watcher.Add(configDir) 405 initWG.Done() // done initializing the watch in this go routine, so the parent routine can move on... 406 eventsWG.Wait() // now, wait for event loop to end in this go-routine... 407 }() 408 initWG.Wait() // make sure that the go routine above fully ended before returning 409 } 410 411 // SetConfigFile explicitly defines the path, name and extension of the config file. 412 // Viper will use this and not check any of the config paths. 413 func SetConfigFile(in string) { v.SetConfigFile(in) } 414 415 func (v *Viper) SetConfigFile(in string) { 416 if in != "" { 417 v.configFile = in 418 } 419 } 420 421 // SetEnvPrefix defines a prefix that ENVIRONMENT variables will use. 422 // E.g. if your prefix is "spf", the env registry will look for env 423 // variables that start with "SPF_". 424 func SetEnvPrefix(in string) { v.SetEnvPrefix(in) } 425 426 func (v *Viper) SetEnvPrefix(in string) { 427 if in != "" { 428 v.envPrefix = in 429 } 430 } 431 432 func (v *Viper) mergeWithEnvPrefix(in string) string { 433 if v.envPrefix != "" { 434 return strings.ToUpper(v.envPrefix + "_" + in) 435 } 436 437 return strings.ToUpper(in) 438 } 439 440 // AllowEmptyEnv tells Viper to consider set, 441 // but empty environment variables as valid values instead of falling back. 442 // For backward compatibility reasons this is false by default. 443 func AllowEmptyEnv(allowEmptyEnv bool) { v.AllowEmptyEnv(allowEmptyEnv) } 444 445 func (v *Viper) AllowEmptyEnv(allowEmptyEnv bool) { 446 v.allowEmptyEnv = allowEmptyEnv 447 } 448 449 // TODO: should getEnv logic be moved into find(). Can generalize the use of 450 // rewriting keys many things, Ex: Get('someKey') -> some_key 451 // (camel case to snake case for JSON keys perhaps) 452 453 // getEnv is a wrapper around os.Getenv which replaces characters in the original 454 // key. This allows env vars which have different keys than the config object 455 // keys. 456 func (v *Viper) getEnv(key string) (string, bool) { 457 if v.envKeyReplacer != nil { 458 key = v.envKeyReplacer.Replace(key) 459 } 460 461 val, ok := os.LookupEnv(key) 462 463 return val, ok && (v.allowEmptyEnv || val != "") 464 } 465 466 // ConfigFileUsed returns the file used to populate the config registry. 467 func ConfigFileUsed() string { return v.ConfigFileUsed() } 468 func (v *Viper) ConfigFileUsed() string { return v.configFile } 469 470 // AddConfigPath adds a path for Viper to search for the config file in. 471 // Can be called multiple times to define multiple search paths. 472 func AddConfigPath(in string) { v.AddConfigPath(in) } 473 474 func (v *Viper) AddConfigPath(in string) { 475 if in != "" { 476 absin := absPathify(in) 477 jww.INFO.Println("adding", absin, "to paths to search") 478 if !stringInSlice(absin, v.configPaths) { 479 v.configPaths = append(v.configPaths, absin) 480 } 481 } 482 } 483 484 // AddRemoteProvider adds a remote configuration source. 485 // Remote Providers are searched in the order they are added. 486 // provider is a string value: "etcd", "consul" or "firestore" are currently supported. 487 // endpoint is the url. etcd requires http://ip:port consul requires ip:port 488 // path is the path in the k/v store to retrieve configuration 489 // To retrieve a config file called myapp.json from /configs/myapp.json 490 // you should set path to /configs and set config name (SetConfigName()) to 491 // "myapp" 492 func AddRemoteProvider(provider, endpoint, path string) error { 493 return v.AddRemoteProvider(provider, endpoint, path) 494 } 495 496 func (v *Viper) AddRemoteProvider(provider, endpoint, path string) error { 497 if !stringInSlice(provider, SupportedRemoteProviders) { 498 return UnsupportedRemoteProviderError(provider) 499 } 500 if provider != "" && endpoint != "" { 501 jww.INFO.Printf("adding %s:%s to remote provider list", provider, endpoint) 502 rp := &defaultRemoteProvider{ 503 endpoint: endpoint, 504 provider: provider, 505 path: path, 506 } 507 if !v.providerPathExists(rp) { 508 v.remoteProviders = append(v.remoteProviders, rp) 509 } 510 } 511 return nil 512 } 513 514 // AddSecureRemoteProvider adds a remote configuration source. 515 // Secure Remote Providers are searched in the order they are added. 516 // provider is a string value: "etcd", "consul" or "firestore" are currently supported. 517 // endpoint is the url. etcd requires http://ip:port consul requires ip:port 518 // secretkeyring is the filepath to your openpgp secret keyring. e.g. /etc/secrets/myring.gpg 519 // path is the path in the k/v store to retrieve configuration 520 // To retrieve a config file called myapp.json from /configs/myapp.json 521 // you should set path to /configs and set config name (SetConfigName()) to 522 // "myapp" 523 // Secure Remote Providers are implemented with github.com/bketelsen/crypt 524 func AddSecureRemoteProvider(provider, endpoint, path, secretkeyring string) error { 525 return v.AddSecureRemoteProvider(provider, endpoint, path, secretkeyring) 526 } 527 528 func (v *Viper) AddSecureRemoteProvider(provider, endpoint, path, secretkeyring string) error { 529 if !stringInSlice(provider, SupportedRemoteProviders) { 530 return UnsupportedRemoteProviderError(provider) 531 } 532 if provider != "" && endpoint != "" { 533 jww.INFO.Printf("adding %s:%s to remote provider list", provider, endpoint) 534 rp := &defaultRemoteProvider{ 535 endpoint: endpoint, 536 provider: provider, 537 path: path, 538 secretKeyring: secretkeyring, 539 } 540 if !v.providerPathExists(rp) { 541 v.remoteProviders = append(v.remoteProviders, rp) 542 } 543 } 544 return nil 545 } 546 547 func (v *Viper) providerPathExists(p *defaultRemoteProvider) bool { 548 for _, y := range v.remoteProviders { 549 if reflect.DeepEqual(y, p) { 550 return true 551 } 552 } 553 return false 554 } 555 556 // searchMap recursively searches for a value for path in source map. 557 // Returns nil if not found. 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 := v.caseKey(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's case-sensitivity for a key is determined by viper.keysCaseSensitive. 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 casedKey := v.caseKey(key) 793 val := v.find(casedKey, 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(casedKey, 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's case-sensitivity for a key is determined by viper.KeysCaseSensitive. 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[v.caseKey(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 := v.caseKey(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: By default, this assumes that a lowercase key is given. 1116 // This behavior can be modified with viper.SetKeysCaseSensitive. 1117 func (v *Viper) find(key string, flagDefault bool) interface{} { 1118 var ( 1119 val interface{} 1120 exists bool 1121 path = strings.Split(key, v.keyDelim) 1122 nested = len(path) > 1 1123 ) 1124 1125 // compute the path through the nested maps to the nested value 1126 if nested && v.isPathShadowedInDeepMap(path, castMapStringToMapInterface(v.aliases)) != "" { 1127 return nil 1128 } 1129 1130 // if the requested key is an alias, then return the proper key 1131 key = v.realKey(key) 1132 path = strings.Split(key, v.keyDelim) 1133 nested = len(path) > 1 1134 1135 // Set() override first 1136 val = v.searchMap(v.override, path) 1137 if val != nil { 1138 return val 1139 } 1140 if nested && v.isPathShadowedInDeepMap(path, v.override) != "" { 1141 return nil 1142 } 1143 1144 // PFlag override next 1145 flag, exists := v.pflags[key] 1146 if exists && flag.HasChanged() { 1147 switch flag.ValueType() { 1148 case "int", "int8", "int16", "int32", "int64": 1149 return cast.ToInt(flag.ValueString()) 1150 case "bool": 1151 return cast.ToBool(flag.ValueString()) 1152 case "stringSlice": 1153 s := strings.TrimPrefix(flag.ValueString(), "[") 1154 s = strings.TrimSuffix(s, "]") 1155 res, _ := readAsCSV(s) 1156 return res 1157 case "intSlice": 1158 s := strings.TrimPrefix(flag.ValueString(), "[") 1159 s = strings.TrimSuffix(s, "]") 1160 res, _ := readAsCSV(s) 1161 return cast.ToIntSlice(res) 1162 case "stringToString": 1163 return stringToStringConv(flag.ValueString()) 1164 default: 1165 return flag.ValueString() 1166 } 1167 } 1168 if nested && v.isPathShadowedInFlatMap(path, v.pflags) != "" { 1169 return nil 1170 } 1171 1172 // Env override next 1173 if v.automaticEnvApplied { 1174 // even if it hasn't been registered, if automaticEnv is used, 1175 // check any Get request 1176 if val, ok := v.getEnv(v.mergeWithEnvPrefix(key)); ok { 1177 return val 1178 } 1179 if nested && v.isPathShadowedInAutoEnv(path) != "" { 1180 return nil 1181 } 1182 } 1183 envkeys, exists := v.env[key] 1184 if exists { 1185 for _, envkey := range envkeys { 1186 if val, ok := v.getEnv(envkey); ok { 1187 return val 1188 } 1189 } 1190 } 1191 if nested && v.isPathShadowedInFlatMap(path, v.env) != "" { 1192 return nil 1193 } 1194 1195 // Config file next 1196 val = v.searchIndexableWithPathPrefixes(v.config, path) 1197 if val != nil { 1198 return val 1199 } 1200 if nested && v.isPathShadowedInDeepMap(path, v.config) != "" { 1201 return nil 1202 } 1203 1204 // K/V store next 1205 val = v.searchMap(v.kvstore, path) 1206 if val != nil { 1207 return val 1208 } 1209 if nested && v.isPathShadowedInDeepMap(path, v.kvstore) != "" { 1210 return nil 1211 } 1212 1213 // Default next 1214 val = v.searchMap(v.defaults, path) 1215 if val != nil { 1216 return val 1217 } 1218 if nested && v.isPathShadowedInDeepMap(path, v.defaults) != "" { 1219 return nil 1220 } 1221 1222 if flagDefault { 1223 // last chance: if no value is found and a flag does exist for the key, 1224 // get the flag's default value even if the flag's value has not been set. 1225 if flag, exists := v.pflags[key]; exists { 1226 switch flag.ValueType() { 1227 case "int", "int8", "int16", "int32", "int64": 1228 return cast.ToInt(flag.ValueString()) 1229 case "bool": 1230 return cast.ToBool(flag.ValueString()) 1231 case "stringSlice": 1232 s := strings.TrimPrefix(flag.ValueString(), "[") 1233 s = strings.TrimSuffix(s, "]") 1234 res, _ := readAsCSV(s) 1235 return res 1236 case "intSlice": 1237 s := strings.TrimPrefix(flag.ValueString(), "[") 1238 s = strings.TrimSuffix(s, "]") 1239 res, _ := readAsCSV(s) 1240 return cast.ToIntSlice(res) 1241 case "stringToString": 1242 return stringToStringConv(flag.ValueString()) 1243 default: 1244 return flag.ValueString() 1245 } 1246 } 1247 // last item, no need to check shadowing 1248 } 1249 1250 return nil 1251 } 1252 1253 func readAsCSV(val string) ([]string, error) { 1254 if val == "" { 1255 return []string{}, nil 1256 } 1257 stringReader := strings.NewReader(val) 1258 csvReader := csv.NewReader(stringReader) 1259 return csvReader.Read() 1260 } 1261 1262 // mostly copied from pflag's implementation of this operation here https://github.com/spf13/pflag/blob/master/string_to_string.go#L79 1263 // alterations are: errors are swallowed, map[string]interface{} is returned in order to enable cast.ToStringMap 1264 func stringToStringConv(val string) interface{} { 1265 val = strings.Trim(val, "[]") 1266 // An empty string would cause an empty map 1267 if len(val) == 0 { 1268 return map[string]interface{}{} 1269 } 1270 r := csv.NewReader(strings.NewReader(val)) 1271 ss, err := r.Read() 1272 if err != nil { 1273 return nil 1274 } 1275 out := make(map[string]interface{}, len(ss)) 1276 for _, pair := range ss { 1277 kv := strings.SplitN(pair, "=", 2) 1278 if len(kv) != 2 { 1279 return nil 1280 } 1281 out[kv[0]] = kv[1] 1282 } 1283 return out 1284 } 1285 1286 // IsSet checks to see if the key has been set in any of the data locations. 1287 // IsSet is case-insensitive for a key. 1288 func IsSet(key string) bool { return v.IsSet(key) } 1289 1290 func (v *Viper) IsSet(key string) bool { 1291 casedKey := v.caseKey(key) 1292 val := v.find(casedKey, false) 1293 return val != nil 1294 } 1295 1296 // AutomaticEnv makes Viper check if environment variables match any of the existing keys 1297 // (config, default or flags). If matching env vars are found, they are loaded into Viper. 1298 func AutomaticEnv() { v.AutomaticEnv() } 1299 1300 func (v *Viper) AutomaticEnv() { 1301 v.automaticEnvApplied = true 1302 } 1303 1304 // SetEnvKeyReplacer sets the strings.Replacer on the viper object 1305 // Useful for mapping an environmental variable to a key that does 1306 // not match it. 1307 func SetEnvKeyReplacer(r *strings.Replacer) { v.SetEnvKeyReplacer(r) } 1308 1309 func (v *Viper) SetEnvKeyReplacer(r *strings.Replacer) { 1310 v.envKeyReplacer = r 1311 } 1312 1313 // RegisterAlias creates an alias that provides another accessor for the same key. 1314 // This enables one to change a name without breaking the application. 1315 func RegisterAlias(alias string, key string) { v.RegisterAlias(alias, key) } 1316 1317 func (v *Viper) RegisterAlias(alias string, key string) { 1318 v.registerAlias(alias, v.caseKey(key)) 1319 } 1320 1321 func (v *Viper) registerAlias(alias string, key string) { 1322 alias = v.caseKey(alias) 1323 if alias != key && alias != v.realKey(key) { 1324 _, exists := v.aliases[alias] 1325 1326 if !exists { 1327 // if we alias something that exists in one of the maps to another 1328 // name, we'll never be able to get that value using the original 1329 // name, so move the config value to the new realkey. 1330 if val, ok := v.config[alias]; ok { 1331 delete(v.config, alias) 1332 v.config[key] = val 1333 } 1334 if val, ok := v.kvstore[alias]; ok { 1335 delete(v.kvstore, alias) 1336 v.kvstore[key] = val 1337 } 1338 if val, ok := v.defaults[alias]; ok { 1339 delete(v.defaults, alias) 1340 v.defaults[key] = val 1341 } 1342 if val, ok := v.override[alias]; ok { 1343 delete(v.override, alias) 1344 v.override[key] = val 1345 } 1346 v.aliases[alias] = key 1347 } 1348 } else { 1349 jww.WARN.Println("Creating circular reference alias", alias, key, v.realKey(key)) 1350 } 1351 } 1352 1353 func (v *Viper) realKey(key string) string { 1354 newkey, exists := v.aliases[key] 1355 if exists { 1356 jww.DEBUG.Println("Alias", key, "to", newkey) 1357 return v.realKey(newkey) 1358 } 1359 return key 1360 } 1361 1362 // InConfig checks to see if the given key (or an alias) is in the config file. 1363 func InConfig(key string) bool { return v.InConfig(key) } 1364 1365 func (v *Viper) InConfig(key string) bool { 1366 // if the requested key is an alias, then return the proper key 1367 key = v.realKey(key) 1368 1369 _, exists := v.config[key] 1370 return exists 1371 } 1372 1373 // SetDefault sets the default value for this key. 1374 // SetDefault is case-insensitive for a key. This behavior 1375 // can be modified with viper.SetKeysCaseSensitive. 1376 // Default only used when no value is provided by the user via flag, config or ENV. 1377 func SetDefault(key string, value interface{}) { v.SetDefault(key, value) } 1378 1379 func (v *Viper) SetDefault(key string, value interface{}) { 1380 // If alias passed in, then set the proper default 1381 key = v.realKey(v.caseKey(key)) 1382 if !v.keysCaseSensitive { 1383 value = toCaseInsensitiveValue(value) 1384 } 1385 1386 path := strings.Split(key, v.keyDelim) 1387 lastKey := v.caseKey(path[len(path)-1]) 1388 deepestMap := deepSearch(v.defaults, path[0:len(path)-1]) 1389 1390 // set innermost value 1391 deepestMap[lastKey] = value 1392 } 1393 1394 // Set sets the value for the key in the override register. 1395 // Set is case-insensitive for a key. This behavior can be modified 1396 // with viper.SetKeysCaseSensitive. 1397 // Will be used instead of values obtained via 1398 // flags, config file, ENV, default, or key/value store. 1399 func Set(key string, value interface{}) { v.Set(key, value) } 1400 1401 func (v *Viper) Set(key string, value interface{}) { 1402 // If alias passed in, then set the proper override 1403 key = v.realKey(v.caseKey(key)) 1404 if !v.keysCaseSensitive { 1405 value = toCaseInsensitiveValue(value) 1406 } 1407 1408 path := strings.Split(key, v.keyDelim) 1409 lastKey := v.caseKey(path[len(path)-1]) 1410 deepestMap := deepSearch(v.override, path[0:len(path)-1]) 1411 1412 // set innermost value 1413 deepestMap[lastKey] = value 1414 } 1415 1416 // ReadInConfig will discover and load the configuration file from disk 1417 // and key/value stores, searching in one of the defined paths. 1418 func ReadInConfig() error { return v.ReadInConfig() } 1419 1420 func (v *Viper) ReadInConfig() error { 1421 jww.INFO.Println("Attempting to read in config file") 1422 filename, err := v.getConfigFile() 1423 if err != nil { 1424 return err 1425 } 1426 1427 if !stringInSlice(v.getConfigType(), SupportedExts) { 1428 return UnsupportedConfigError(v.getConfigType()) 1429 } 1430 1431 jww.DEBUG.Println("Reading file: ", filename) 1432 file, err := afero.ReadFile(v.fs, filename) 1433 if err != nil { 1434 return err 1435 } 1436 1437 config := make(map[string]interface{}) 1438 1439 err = v.unmarshalReader(bytes.NewReader(file), config) 1440 if err != nil { 1441 return err 1442 } 1443 1444 v.config = config 1445 return nil 1446 } 1447 1448 // MergeInConfig merges a new configuration with an existing config. 1449 func MergeInConfig() error { return v.MergeInConfig() } 1450 1451 func (v *Viper) MergeInConfig() error { 1452 jww.INFO.Println("Attempting to merge in config file") 1453 filename, err := v.getConfigFile() 1454 if err != nil { 1455 return err 1456 } 1457 1458 if !stringInSlice(v.getConfigType(), SupportedExts) { 1459 return UnsupportedConfigError(v.getConfigType()) 1460 } 1461 1462 file, err := afero.ReadFile(v.fs, filename) 1463 if err != nil { 1464 return err 1465 } 1466 1467 return v.MergeConfig(bytes.NewReader(file)) 1468 } 1469 1470 // ReadConfig will read a configuration file, setting existing keys to nil if the 1471 // key does not exist in the file. 1472 func ReadConfig(in io.Reader) error { return v.ReadConfig(in) } 1473 1474 func (v *Viper) ReadConfig(in io.Reader) error { 1475 v.config = make(map[string]interface{}) 1476 return v.unmarshalReader(in, v.config) 1477 } 1478 1479 // MergeConfig merges a new configuration with an existing config. 1480 func MergeConfig(in io.Reader) error { return v.MergeConfig(in) } 1481 1482 func (v *Viper) MergeConfig(in io.Reader) error { 1483 cfg := make(map[string]interface{}) 1484 if err := v.unmarshalReader(in, cfg); err != nil { 1485 return err 1486 } 1487 return v.MergeConfigMap(cfg) 1488 } 1489 1490 // MergeConfigMap merges the configuration from the map given with an existing config. 1491 // Note that the map given may be modified. 1492 func MergeConfigMap(cfg map[string]interface{}) error { return v.MergeConfigMap(cfg) } 1493 1494 func (v *Viper) MergeConfigMap(cfg map[string]interface{}) error { 1495 if v.config == nil { 1496 v.config = make(map[string]interface{}) 1497 } 1498 if !v.keysCaseSensitive { 1499 insensitiviseMap(cfg) 1500 } 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 := v.caseKey(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 if !v.keysCaseSensitive { 1665 insensitiviseMap(c) 1666 } 1667 return nil 1668 } 1669 1670 // Marshal a map into Writer. 1671 func (v *Viper) marshalWriter(f afero.File, configType string) error { 1672 c := v.AllSettings() 1673 switch configType { 1674 case "json": 1675 b, err := json.MarshalIndent(c, "", " ") 1676 if err != nil { 1677 return ConfigMarshalError{err} 1678 } 1679 _, err = f.WriteString(string(b)) 1680 if err != nil { 1681 return ConfigMarshalError{err} 1682 } 1683 1684 case "hcl": 1685 b, err := json.Marshal(c) 1686 if err != nil { 1687 return ConfigMarshalError{err} 1688 } 1689 ast, err := hcl.Parse(string(b)) 1690 if err != nil { 1691 return ConfigMarshalError{err} 1692 } 1693 err = printer.Fprint(f, ast.Node) 1694 if err != nil { 1695 return ConfigMarshalError{err} 1696 } 1697 1698 case "prop", "props", "properties": 1699 if v.properties == nil { 1700 v.properties = properties.NewProperties() 1701 } 1702 p := v.properties 1703 for _, key := range v.AllKeys() { 1704 _, _, err := p.Set(key, v.GetString(key)) 1705 if err != nil { 1706 return ConfigMarshalError{err} 1707 } 1708 } 1709 _, err := p.WriteComment(f, "#", properties.UTF8) 1710 if err != nil { 1711 return ConfigMarshalError{err} 1712 } 1713 1714 case "dotenv", "env": 1715 lines := []string{} 1716 for _, key := range v.AllKeys() { 1717 envName := strings.ToUpper(strings.Replace(key, ".", "_", -1)) 1718 val := v.Get(key) 1719 lines = append(lines, fmt.Sprintf("%v=%v", envName, val)) 1720 } 1721 s := strings.Join(lines, "\n") 1722 if _, err := f.WriteString(s); err != nil { 1723 return ConfigMarshalError{err} 1724 } 1725 1726 case "toml": 1727 t, err := toml.TreeFromMap(c) 1728 if err != nil { 1729 return ConfigMarshalError{err} 1730 } 1731 s := t.String() 1732 if _, err := f.WriteString(s); err != nil { 1733 return ConfigMarshalError{err} 1734 } 1735 1736 case "yaml", "yml": 1737 b, err := yaml.Marshal(c) 1738 if err != nil { 1739 return ConfigMarshalError{err} 1740 } 1741 if _, err = f.WriteString(string(b)); err != nil { 1742 return ConfigMarshalError{err} 1743 } 1744 1745 case "ini": 1746 keys := v.AllKeys() 1747 cfg := ini.Empty() 1748 ini.PrettyFormat = false 1749 for i := 0; i < len(keys); i++ { 1750 key := keys[i] 1751 lastSep := strings.LastIndex(key, ".") 1752 sectionName := key[:(lastSep)] 1753 keyName := key[(lastSep + 1):] 1754 if sectionName == "default" { 1755 sectionName = "" 1756 } 1757 cfg.Section(sectionName).Key(keyName).SetValue(v.Get(key).(string)) 1758 } 1759 cfg.WriteTo(f) 1760 } 1761 return nil 1762 } 1763 1764 func keyExists(k string, m map[string]interface{}) string { 1765 ck := v.caseKey(k) 1766 for mk := range m { 1767 if mk == ck { 1768 return mk 1769 } 1770 } 1771 return "" 1772 } 1773 1774 func castToMapStringInterface( 1775 src map[interface{}]interface{}) map[string]interface{} { 1776 tgt := map[string]interface{}{} 1777 for k, v := range src { 1778 tgt[fmt.Sprintf("%v", k)] = v 1779 } 1780 return tgt 1781 } 1782 1783 func castMapStringSliceToMapInterface(src map[string][]string) map[string]interface{} { 1784 tgt := map[string]interface{}{} 1785 for k, v := range src { 1786 tgt[k] = v 1787 } 1788 return tgt 1789 } 1790 1791 func castMapStringToMapInterface(src map[string]string) map[string]interface{} { 1792 tgt := map[string]interface{}{} 1793 for k, v := range src { 1794 tgt[k] = v 1795 } 1796 return tgt 1797 } 1798 1799 func castMapFlagToMapInterface(src map[string]FlagValue) map[string]interface{} { 1800 tgt := map[string]interface{}{} 1801 for k, v := range src { 1802 tgt[k] = v 1803 } 1804 return tgt 1805 } 1806 1807 // mergeMaps merges two maps. The `itgt` parameter is for handling go-yaml's 1808 // insistence on parsing nested structures as `map[interface{}]interface{}` 1809 // instead of using a `string` as the key for nest structures beyond one level 1810 // deep. Both map types are supported as there is a go-yaml fork that uses 1811 // `map[string]interface{}` instead. 1812 func mergeMaps( 1813 src, tgt map[string]interface{}, itgt map[interface{}]interface{}) { 1814 for sk, sv := range src { 1815 tk := keyExists(sk, tgt) 1816 if tk == "" { 1817 jww.TRACE.Printf("tk=\"\", tgt[%s]=%v", sk, sv) 1818 tgt[sk] = sv 1819 if itgt != nil { 1820 itgt[sk] = sv 1821 } 1822 continue 1823 } 1824 1825 tv, ok := tgt[tk] 1826 if !ok { 1827 jww.TRACE.Printf("tgt[%s] != ok, tgt[%s]=%v", tk, sk, sv) 1828 tgt[sk] = sv 1829 if itgt != nil { 1830 itgt[sk] = sv 1831 } 1832 continue 1833 } 1834 1835 svType := reflect.TypeOf(sv) 1836 tvType := reflect.TypeOf(tv) 1837 if svType != tvType { 1838 jww.ERROR.Printf( 1839 "svType != tvType; key=%s, st=%v, tt=%v, sv=%v, tv=%v", 1840 sk, svType, tvType, sv, tv) 1841 continue 1842 } 1843 1844 jww.TRACE.Printf("processing key=%s, st=%v, tt=%v, sv=%v, tv=%v", 1845 sk, svType, tvType, sv, tv) 1846 1847 switch ttv := tv.(type) { 1848 case map[interface{}]interface{}: 1849 jww.TRACE.Printf("merging maps (must convert)") 1850 tsv := sv.(map[interface{}]interface{}) 1851 ssv := castToMapStringInterface(tsv) 1852 stv := castToMapStringInterface(ttv) 1853 mergeMaps(ssv, stv, ttv) 1854 case map[string]interface{}: 1855 jww.TRACE.Printf("merging maps") 1856 mergeMaps(sv.(map[string]interface{}), ttv, nil) 1857 default: 1858 jww.TRACE.Printf("setting value") 1859 tgt[tk] = sv 1860 if itgt != nil { 1861 itgt[tk] = sv 1862 } 1863 } 1864 } 1865 } 1866 1867 // ReadRemoteConfig attempts to get configuration from a remote source 1868 // and read it in the remote configuration registry. 1869 func ReadRemoteConfig() error { return v.ReadRemoteConfig() } 1870 1871 func (v *Viper) ReadRemoteConfig() error { 1872 return v.getKeyValueConfig() 1873 } 1874 1875 func WatchRemoteConfig() error { return v.WatchRemoteConfig() } 1876 func (v *Viper) WatchRemoteConfig() error { 1877 return v.watchKeyValueConfig() 1878 } 1879 1880 func (v *Viper) WatchRemoteConfigOnChannel() error { 1881 return v.watchKeyValueConfigOnChannel() 1882 } 1883 1884 // Retrieve the first found remote configuration. 1885 func (v *Viper) getKeyValueConfig() error { 1886 if RemoteConfig == nil { 1887 return RemoteConfigError("Enable the remote features by doing a blank import of the viper/remote package: '_ github.com/ava-labs/viper/remote'") 1888 } 1889 1890 for _, rp := range v.remoteProviders { 1891 val, err := v.getRemoteConfig(rp) 1892 if err != nil { 1893 jww.ERROR.Printf("get remote config: %s", err) 1894 1895 continue 1896 } 1897 1898 v.kvstore = val 1899 1900 return nil 1901 } 1902 return RemoteConfigError("No Files Found") 1903 } 1904 1905 func (v *Viper) getRemoteConfig(provider RemoteProvider) (map[string]interface{}, error) { 1906 reader, err := RemoteConfig.Get(provider) 1907 if err != nil { 1908 return nil, err 1909 } 1910 err = v.unmarshalReader(reader, v.kvstore) 1911 return v.kvstore, err 1912 } 1913 1914 // Retrieve the first found remote configuration. 1915 func (v *Viper) watchKeyValueConfigOnChannel() error { 1916 for _, rp := range v.remoteProviders { 1917 respc, _ := RemoteConfig.WatchChannel(rp) 1918 // Todo: Add quit channel 1919 go func(rc <-chan *RemoteResponse) { 1920 for { 1921 b := <-rc 1922 reader := bytes.NewReader(b.Value) 1923 v.unmarshalReader(reader, v.kvstore) 1924 } 1925 }(respc) 1926 return nil 1927 } 1928 return RemoteConfigError("No Files Found") 1929 } 1930 1931 // Retrieve the first found remote configuration. 1932 func (v *Viper) watchKeyValueConfig() error { 1933 for _, rp := range v.remoteProviders { 1934 val, err := v.watchRemoteConfig(rp) 1935 if err != nil { 1936 continue 1937 } 1938 v.kvstore = val 1939 return nil 1940 } 1941 return RemoteConfigError("No Files Found") 1942 } 1943 1944 func (v *Viper) watchRemoteConfig(provider RemoteProvider) (map[string]interface{}, error) { 1945 reader, err := RemoteConfig.Watch(provider) 1946 if err != nil { 1947 return nil, err 1948 } 1949 err = v.unmarshalReader(reader, v.kvstore) 1950 return v.kvstore, err 1951 } 1952 1953 // AllKeys returns all keys holding a value, regardless of where they are set. 1954 // Nested keys are returned with a v.keyDelim separator 1955 func AllKeys() []string { return v.AllKeys() } 1956 1957 func (v *Viper) AllKeys() []string { 1958 m := map[string]bool{} 1959 // add all paths, by order of descending priority to ensure correct shadowing 1960 m = v.flattenAndMergeMap(m, castMapStringToMapInterface(v.aliases), "") 1961 m = v.flattenAndMergeMap(m, v.override, "") 1962 m = v.mergeFlatMap(m, castMapFlagToMapInterface(v.pflags)) 1963 m = v.mergeFlatMap(m, castMapStringSliceToMapInterface(v.env)) 1964 m = v.flattenAndMergeMap(m, v.config, "") 1965 m = v.flattenAndMergeMap(m, v.kvstore, "") 1966 m = v.flattenAndMergeMap(m, v.defaults, "") 1967 1968 // convert set of paths to list 1969 a := make([]string, 0, len(m)) 1970 for x := range m { 1971 a = append(a, x) 1972 } 1973 return a 1974 } 1975 1976 // flattenAndMergeMap recursively flattens the given map into a map[string]bool 1977 // of key paths (used as a set, easier to manipulate than a []string): 1978 // - each path is merged into a single key string, delimited with v.keyDelim 1979 // - if a path is shadowed by an earlier value in the initial shadow map, 1980 // it is skipped. 1981 // The resulting set of paths is merged to the given shadow set at the same time. 1982 func (v *Viper) flattenAndMergeMap(shadow map[string]bool, m map[string]interface{}, prefix string) map[string]bool { 1983 if shadow != nil && prefix != "" && shadow[prefix] { 1984 // prefix is shadowed => nothing more to flatten 1985 return shadow 1986 } 1987 if shadow == nil { 1988 shadow = make(map[string]bool) 1989 } 1990 1991 var m2 map[string]interface{} 1992 if prefix != "" { 1993 prefix += v.keyDelim 1994 } 1995 for k, val := range m { 1996 fullKey := prefix + k 1997 switch val.(type) { 1998 case map[string]interface{}: 1999 m2 = val.(map[string]interface{}) 2000 case map[interface{}]interface{}: 2001 m2 = cast.ToStringMap(val) 2002 default: 2003 // immediate value 2004 shadow[v.caseKey(fullKey)] = true 2005 continue 2006 } 2007 // recursively merge to shadow map 2008 shadow = v.flattenAndMergeMap(shadow, m2, fullKey) 2009 } 2010 return shadow 2011 } 2012 2013 // mergeFlatMap merges the given maps, excluding values of the second map 2014 // shadowed by values from the first map. 2015 func (v *Viper) mergeFlatMap(shadow map[string]bool, m map[string]interface{}) map[string]bool { 2016 // scan keys 2017 outer: 2018 for k := range m { 2019 path := strings.Split(k, v.keyDelim) 2020 // scan intermediate paths 2021 var parentKey string 2022 for i := 1; i < len(path); i++ { 2023 parentKey = strings.Join(path[0:i], v.keyDelim) 2024 if shadow[parentKey] { 2025 // path is shadowed, continue 2026 continue outer 2027 } 2028 } 2029 // add key 2030 shadow[v.caseKey(k)] = true 2031 } 2032 return shadow 2033 } 2034 2035 // AllSettings merges all settings and returns them as a map[string]interface{}. 2036 func AllSettings() map[string]interface{} { return v.AllSettings() } 2037 2038 func (v *Viper) AllSettings() map[string]interface{} { 2039 m := map[string]interface{}{} 2040 // start from the list of keys, and construct the map one value at a time 2041 for _, k := range v.AllKeys() { 2042 value := v.Get(k) 2043 if value == nil { 2044 // should not happen, since AllKeys() returns only keys holding a value, 2045 // check just in case anything changes 2046 continue 2047 } 2048 path := strings.Split(k, v.keyDelim) 2049 lastKey := v.caseKey(path[len(path)-1]) 2050 deepestMap := deepSearch(m, path[0:len(path)-1]) 2051 // set innermost value 2052 deepestMap[lastKey] = value 2053 } 2054 return m 2055 } 2056 2057 // SetFs sets the filesystem to use to read configuration. 2058 func SetFs(fs afero.Fs) { v.SetFs(fs) } 2059 2060 func (v *Viper) SetFs(fs afero.Fs) { 2061 v.fs = fs 2062 } 2063 2064 // SetConfigName sets name for the config file. 2065 // Does not include extension. 2066 func SetConfigName(in string) { v.SetConfigName(in) } 2067 2068 func (v *Viper) SetConfigName(in string) { 2069 if in != "" { 2070 v.configName = in 2071 v.configFile = "" 2072 } 2073 } 2074 2075 // SetConfigType sets the type of the configuration returned by the 2076 // remote source, e.g. "json". 2077 func SetConfigType(in string) { v.SetConfigType(in) } 2078 2079 func (v *Viper) SetConfigType(in string) { 2080 if in != "" { 2081 v.configType = in 2082 } 2083 } 2084 2085 // SetKeysCaseSensitive disables the default behaviour of 2086 // case-insensitivising (lowercasing) keys and preserves the key casing 2087 // as they are found in the config files. It is important 2088 // to note that operations such as set and merge when 2089 // case sensitivity is 'on', and whtn it is turneed 'off', 2090 // are incompatible. A key that is set when case sentivity 2091 // is 'on' may not be retrievable when case sensitivity is turned 'off', 2092 // as the original casing is permanently lost in the former mode. 2093 // That is ideally, this should only be invoked only once, 2094 // during initialisation, and the subsequent usage must adhere 2095 // to the same case sentivity. 2096 func SetKeysCaseSensitive(on bool) { v.SetKeysCaseSensitive(on) } 2097 func (v *Viper) SetKeysCaseSensitive(on bool) { 2098 v.keysCaseSensitive = on 2099 } 2100 2101 // SetConfigPermissions sets the permissions for the config file. 2102 func SetConfigPermissions(perm os.FileMode) { v.SetConfigPermissions(perm) } 2103 2104 func (v *Viper) SetConfigPermissions(perm os.FileMode) { 2105 v.configPermissions = perm.Perm() 2106 } 2107 2108 func (v *Viper) getConfigType() string { 2109 if v.configType != "" { 2110 return v.configType 2111 } 2112 2113 cf, err := v.getConfigFile() 2114 if err != nil { 2115 return "" 2116 } 2117 2118 ext := filepath.Ext(cf) 2119 2120 if len(ext) > 1 { 2121 return ext[1:] 2122 } 2123 2124 return "" 2125 } 2126 2127 func (v *Viper) getConfigFile() (string, error) { 2128 if v.configFile == "" { 2129 cf, err := v.findConfigFile() 2130 if err != nil { 2131 return "", err 2132 } 2133 v.configFile = cf 2134 } 2135 return v.configFile, nil 2136 } 2137 2138 func (v *Viper) searchInPath(in string) (filename string) { 2139 jww.DEBUG.Println("Searching for config in ", in) 2140 for _, ext := range SupportedExts { 2141 jww.DEBUG.Println("Checking for", filepath.Join(in, v.configName+"."+ext)) 2142 if b, _ := exists(v.fs, filepath.Join(in, v.configName+"."+ext)); b { 2143 jww.DEBUG.Println("Found: ", filepath.Join(in, v.configName+"."+ext)) 2144 return filepath.Join(in, v.configName+"."+ext) 2145 } 2146 } 2147 2148 if v.configType != "" { 2149 if b, _ := exists(v.fs, filepath.Join(in, v.configName)); b { 2150 return filepath.Join(in, v.configName) 2151 } 2152 } 2153 2154 return "" 2155 } 2156 2157 // caseKey cases (preserves sensitivity or lowercases) a 2158 // given key based on the keyCaseSensitivity config. 2159 func (v *Viper) caseKey(in string) (filename string) { 2160 if v.keysCaseSensitive { 2161 return in 2162 } 2163 return strings.ToLower(in) 2164 } 2165 2166 // Search all configPaths for any config file. 2167 // Returns the first path that exists (and is a config file). 2168 func (v *Viper) findConfigFile() (string, error) { 2169 jww.INFO.Println("Searching for config in ", v.configPaths) 2170 2171 for _, cp := range v.configPaths { 2172 file := v.searchInPath(cp) 2173 if file != "" { 2174 return file, nil 2175 } 2176 } 2177 return "", ConfigFileNotFoundError{v.configName, fmt.Sprintf("%s", v.configPaths)} 2178 } 2179 2180 // Debug prints all configuration registries for debugging 2181 // purposes. 2182 func Debug() { v.Debug() } 2183 2184 func (v *Viper) Debug() { 2185 fmt.Printf("Aliases:\n%#v\n", v.aliases) 2186 fmt.Printf("Override:\n%#v\n", v.override) 2187 fmt.Printf("PFlags:\n%#v\n", v.pflags) 2188 fmt.Printf("Env:\n%#v\n", v.env) 2189 fmt.Printf("Key/Value Store:\n%#v\n", v.kvstore) 2190 fmt.Printf("Config:\n%#v\n", v.config) 2191 fmt.Printf("Defaults:\n%#v\n", v.defaults) 2192 }