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