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