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