changeset 256 | 6d9efbef00a9 |
parent 251 | 1c52a0eeb952 |
child 260 | 445e01aede7e |
255:4f153a23adab | 256:6d9efbef00a9 |
---|---|
28 "io" |
28 "io" |
29 "log" |
29 "log" |
30 "os" |
30 "os" |
31 "path/filepath" |
31 "path/filepath" |
32 "reflect" |
32 "reflect" |
33 "strconv" |
|
33 "strings" |
34 "strings" |
34 "sync" |
35 "sync" |
35 "time" |
36 "time" |
36 |
37 |
37 "github.com/fsnotify/fsnotify" |
38 "github.com/fsnotify/fsnotify" |
173 // { |
174 // { |
174 // "secret": "somesecretkey", |
175 // "secret": "somesecretkey", |
175 // "user": "root", |
176 // "user": "root", |
176 // "endpoint": "https://localhost" |
177 // "endpoint": "https://localhost" |
177 // } |
178 // } |
179 // |
|
180 // Note: Vipers are not safe for concurrent Get() and Set() operations. |
|
178 type Viper struct { |
181 type Viper struct { |
179 // Delimiter that separates a list of keys |
182 // Delimiter that separates a list of keys |
180 // used to access a nested value in one go |
183 // used to access a nested value in one go |
181 keyDelim string |
184 keyDelim string |
182 |
185 |
194 configFile string |
197 configFile string |
195 configType string |
198 configType string |
196 configPermissions os.FileMode |
199 configPermissions os.FileMode |
197 envPrefix string |
200 envPrefix string |
198 |
201 |
202 // Specific commands for ini parsing |
|
203 iniLoadOptions ini.LoadOptions |
|
204 |
|
199 automaticEnvApplied bool |
205 automaticEnvApplied bool |
200 envKeyReplacer StringReplacer |
206 envKeyReplacer StringReplacer |
201 allowEmptyEnv bool |
207 allowEmptyEnv bool |
202 |
208 |
203 config map[string]interface{} |
209 config map[string]interface{} |
204 override map[string]interface{} |
210 override map[string]interface{} |
205 defaults map[string]interface{} |
211 defaults map[string]interface{} |
206 kvstore map[string]interface{} |
212 kvstore map[string]interface{} |
207 pflags map[string]FlagValue |
213 pflags map[string]FlagValue |
208 env map[string]string |
214 env map[string][]string |
209 aliases map[string]string |
215 aliases map[string]string |
210 typeByDefValue bool |
216 typeByDefValue bool |
211 |
217 |
212 // Store read properties on the object so that we can write back in order with comments. |
218 // Store read properties on the object so that we can write back in order with comments. |
213 // This will only be used if the configuration read is a properties file. |
219 // This will only be used if the configuration read is a properties file. |
226 v.config = make(map[string]interface{}) |
232 v.config = make(map[string]interface{}) |
227 v.override = make(map[string]interface{}) |
233 v.override = make(map[string]interface{}) |
228 v.defaults = make(map[string]interface{}) |
234 v.defaults = make(map[string]interface{}) |
229 v.kvstore = make(map[string]interface{}) |
235 v.kvstore = make(map[string]interface{}) |
230 v.pflags = make(map[string]FlagValue) |
236 v.pflags = make(map[string]FlagValue) |
231 v.env = make(map[string]string) |
237 v.env = make(map[string][]string) |
232 v.aliases = make(map[string]string) |
238 v.aliases = make(map[string]string) |
233 v.typeByDefValue = false |
239 v.typeByDefValue = false |
234 |
240 |
235 return v |
241 return v |
236 } |
242 } |
285 // In the public interface for the viper package so applications |
291 // In the public interface for the viper package so applications |
286 // can use it in their testing as well. |
292 // can use it in their testing as well. |
287 func Reset() { |
293 func Reset() { |
288 v = New() |
294 v = New() |
289 SupportedExts = []string{"json", "toml", "yaml", "yml", "properties", "props", "prop", "hcl", "dotenv", "env", "ini"} |
295 SupportedExts = []string{"json", "toml", "yaml", "yml", "properties", "props", "prop", "hcl", "dotenv", "env", "ini"} |
290 SupportedRemoteProviders = []string{"etcd", "consul"} |
296 SupportedRemoteProviders = []string{"etcd", "consul", "firestore"} |
291 } |
297 } |
292 |
298 |
293 type defaultRemoteProvider struct { |
299 type defaultRemoteProvider struct { |
294 provider string |
300 provider string |
295 endpoint string |
301 endpoint string |
326 |
332 |
327 // SupportedExts are universally supported extensions. |
333 // SupportedExts are universally supported extensions. |
328 var SupportedExts = []string{"json", "toml", "yaml", "yml", "properties", "props", "prop", "hcl", "dotenv", "env", "ini"} |
334 var SupportedExts = []string{"json", "toml", "yaml", "yml", "properties", "props", "prop", "hcl", "dotenv", "env", "ini"} |
329 |
335 |
330 // SupportedRemoteProviders are universally supported remote providers. |
336 // SupportedRemoteProviders are universally supported remote providers. |
331 var SupportedRemoteProviders = []string{"etcd", "consul"} |
337 var SupportedRemoteProviders = []string{"etcd", "consul", "firestore"} |
332 |
338 |
333 func OnConfigChange(run func(in fsnotify.Event)) { v.OnConfigChange(run) } |
339 func OnConfigChange(run func(in fsnotify.Event)) { v.OnConfigChange(run) } |
334 func (v *Viper) OnConfigChange(run func(in fsnotify.Event)) { |
340 func (v *Viper) OnConfigChange(run func(in fsnotify.Event)) { |
335 v.onConfigChange = run |
341 v.onConfigChange = run |
336 } |
342 } |
339 |
345 |
340 func (v *Viper) WatchConfig() { |
346 func (v *Viper) WatchConfig() { |
341 initWG := sync.WaitGroup{} |
347 initWG := sync.WaitGroup{} |
342 initWG.Add(1) |
348 initWG.Add(1) |
343 go func() { |
349 go func() { |
344 watcher, err := fsnotify.NewWatcher() |
350 watcher, err := newWatcher() |
345 if err != nil { |
351 if err != nil { |
346 log.Fatal(err) |
352 log.Fatal(err) |
347 } |
353 } |
348 defer watcher.Close() |
354 defer watcher.Close() |
349 // we have to watch the entire directory to pick up renames/atomic saves in a cross-platform way |
355 // we have to watch the entire directory to pick up renames/atomic saves in a cross-platform way |
407 } |
413 } |
408 |
414 |
409 // SetConfigFile explicitly defines the path, name and extension of the config file. |
415 // SetConfigFile explicitly defines the path, name and extension of the config file. |
410 // Viper will use this and not check any of the config paths. |
416 // Viper will use this and not check any of the config paths. |
411 func SetConfigFile(in string) { v.SetConfigFile(in) } |
417 func SetConfigFile(in string) { v.SetConfigFile(in) } |
418 |
|
412 func (v *Viper) SetConfigFile(in string) { |
419 func (v *Viper) SetConfigFile(in string) { |
413 if in != "" { |
420 if in != "" { |
414 v.configFile = in |
421 v.configFile = in |
415 } |
422 } |
416 } |
423 } |
417 |
424 |
418 // SetEnvPrefix defines a prefix that ENVIRONMENT variables will use. |
425 // SetEnvPrefix defines a prefix that ENVIRONMENT variables will use. |
419 // E.g. if your prefix is "spf", the env registry will look for env |
426 // E.g. if your prefix is "spf", the env registry will look for env |
420 // variables that start with "SPF_". |
427 // variables that start with "SPF_". |
421 func SetEnvPrefix(in string) { v.SetEnvPrefix(in) } |
428 func SetEnvPrefix(in string) { v.SetEnvPrefix(in) } |
429 |
|
422 func (v *Viper) SetEnvPrefix(in string) { |
430 func (v *Viper) SetEnvPrefix(in string) { |
423 if in != "" { |
431 if in != "" { |
424 v.envPrefix = in |
432 v.envPrefix = in |
425 } |
433 } |
426 } |
434 } |
435 |
443 |
436 // AllowEmptyEnv tells Viper to consider set, |
444 // AllowEmptyEnv tells Viper to consider set, |
437 // but empty environment variables as valid values instead of falling back. |
445 // but empty environment variables as valid values instead of falling back. |
438 // For backward compatibility reasons this is false by default. |
446 // For backward compatibility reasons this is false by default. |
439 func AllowEmptyEnv(allowEmptyEnv bool) { v.AllowEmptyEnv(allowEmptyEnv) } |
447 func AllowEmptyEnv(allowEmptyEnv bool) { v.AllowEmptyEnv(allowEmptyEnv) } |
448 |
|
440 func (v *Viper) AllowEmptyEnv(allowEmptyEnv bool) { |
449 func (v *Viper) AllowEmptyEnv(allowEmptyEnv bool) { |
441 v.allowEmptyEnv = allowEmptyEnv |
450 v.allowEmptyEnv = allowEmptyEnv |
442 } |
451 } |
443 |
452 |
444 // TODO: should getEnv logic be moved into find(). Can generalize the use of |
453 // TODO: should getEnv logic be moved into find(). Can generalize the use of |
463 func (v *Viper) ConfigFileUsed() string { return v.configFile } |
472 func (v *Viper) ConfigFileUsed() string { return v.configFile } |
464 |
473 |
465 // AddConfigPath adds a path for Viper to search for the config file in. |
474 // AddConfigPath adds a path for Viper to search for the config file in. |
466 // Can be called multiple times to define multiple search paths. |
475 // Can be called multiple times to define multiple search paths. |
467 func AddConfigPath(in string) { v.AddConfigPath(in) } |
476 func AddConfigPath(in string) { v.AddConfigPath(in) } |
477 |
|
468 func (v *Viper) AddConfigPath(in string) { |
478 func (v *Viper) AddConfigPath(in string) { |
469 if in != "" { |
479 if in != "" { |
470 absin := absPathify(in) |
480 absin := absPathify(in) |
471 jww.INFO.Println("adding", absin, "to paths to search") |
481 jww.INFO.Println("adding", absin, "to paths to search") |
472 if !stringInSlice(absin, v.configPaths) { |
482 if !stringInSlice(absin, v.configPaths) { |
475 } |
485 } |
476 } |
486 } |
477 |
487 |
478 // AddRemoteProvider adds a remote configuration source. |
488 // AddRemoteProvider adds a remote configuration source. |
479 // Remote Providers are searched in the order they are added. |
489 // Remote Providers are searched in the order they are added. |
480 // provider is a string value, "etcd" or "consul" are currently supported. |
490 // provider is a string value: "etcd", "consul" or "firestore" are currently supported. |
481 // endpoint is the url. etcd requires http://ip:port consul requires ip:port |
491 // endpoint is the url. etcd requires http://ip:port consul requires ip:port |
482 // path is the path in the k/v store to retrieve configuration |
492 // path is the path in the k/v store to retrieve configuration |
483 // To retrieve a config file called myapp.json from /configs/myapp.json |
493 // To retrieve a config file called myapp.json from /configs/myapp.json |
484 // you should set path to /configs and set config name (SetConfigName()) to |
494 // you should set path to /configs and set config name (SetConfigName()) to |
485 // "myapp" |
495 // "myapp" |
486 func AddRemoteProvider(provider, endpoint, path string) error { |
496 func AddRemoteProvider(provider, endpoint, path string) error { |
487 return v.AddRemoteProvider(provider, endpoint, path) |
497 return v.AddRemoteProvider(provider, endpoint, path) |
488 } |
498 } |
499 |
|
489 func (v *Viper) AddRemoteProvider(provider, endpoint, path string) error { |
500 func (v *Viper) AddRemoteProvider(provider, endpoint, path string) error { |
490 if !stringInSlice(provider, SupportedRemoteProviders) { |
501 if !stringInSlice(provider, SupportedRemoteProviders) { |
491 return UnsupportedRemoteProviderError(provider) |
502 return UnsupportedRemoteProviderError(provider) |
492 } |
503 } |
493 if provider != "" && endpoint != "" { |
504 if provider != "" && endpoint != "" { |
504 return nil |
515 return nil |
505 } |
516 } |
506 |
517 |
507 // AddSecureRemoteProvider adds a remote configuration source. |
518 // AddSecureRemoteProvider adds a remote configuration source. |
508 // Secure Remote Providers are searched in the order they are added. |
519 // Secure Remote Providers are searched in the order they are added. |
509 // provider is a string value, "etcd" or "consul" are currently supported. |
520 // provider is a string value: "etcd", "consul" or "firestore" are currently supported. |
510 // endpoint is the url. etcd requires http://ip:port consul requires ip:port |
521 // endpoint is the url. etcd requires http://ip:port consul requires ip:port |
511 // secretkeyring is the filepath to your openpgp secret keyring. e.g. /etc/secrets/myring.gpg |
522 // secretkeyring is the filepath to your openpgp secret keyring. e.g. /etc/secrets/myring.gpg |
512 // path is the path in the k/v store to retrieve configuration |
523 // path is the path in the k/v store to retrieve configuration |
513 // To retrieve a config file called myapp.json from /configs/myapp.json |
524 // To retrieve a config file called myapp.json from /configs/myapp.json |
514 // you should set path to /configs and set config name (SetConfigName()) to |
525 // you should set path to /configs and set config name (SetConfigName()) to |
515 // "myapp" |
526 // "myapp" |
516 // Secure Remote Providers are implemented with github.com/xordataexchange/crypt |
527 // Secure Remote Providers are implemented with github.com/bketelsen/crypt |
517 func AddSecureRemoteProvider(provider, endpoint, path, secretkeyring string) error { |
528 func AddSecureRemoteProvider(provider, endpoint, path, secretkeyring string) error { |
518 return v.AddSecureRemoteProvider(provider, endpoint, path, secretkeyring) |
529 return v.AddSecureRemoteProvider(provider, endpoint, path, secretkeyring) |
519 } |
530 } |
520 |
531 |
521 func (v *Viper) AddSecureRemoteProvider(provider, endpoint, path, secretkeyring string) error { |
532 func (v *Viper) AddSecureRemoteProvider(provider, endpoint, path, secretkeyring string) error { |
575 } |
586 } |
576 } |
587 } |
577 return nil |
588 return nil |
578 } |
589 } |
579 |
590 |
580 // searchMapWithPathPrefixes recursively searches for a value for path in source map. |
591 // searchIndexableWithPathPrefixes recursively searches for a value for path in source map/slice. |
581 // |
592 // |
582 // While searchMap() considers each path element as a single map key, this |
593 // While searchMap() considers each path element as a single map key or slice index, this |
583 // function searches for, and prioritizes, merged path elements. |
594 // function searches for, and prioritizes, merged path elements. |
584 // e.g., if in the source, "foo" is defined with a sub-key "bar", and "foo.bar" |
595 // e.g., if in the source, "foo" is defined with a sub-key "bar", and "foo.bar" |
585 // is also defined, this latter value is returned for path ["foo", "bar"]. |
596 // is also defined, this latter value is returned for path ["foo", "bar"]. |
586 // |
597 // |
587 // This should be useful only at config level (other maps may not contain dots |
598 // This should be useful only at config level (other maps may not contain dots |
588 // in their keys). |
599 // in their keys). |
589 // |
600 // |
590 // Note: This assumes that the path entries and map keys are lower cased. |
601 // Note: This assumes that the path entries and map keys are lower cased. |
591 func (v *Viper) searchMapWithPathPrefixes(source map[string]interface{}, path []string) interface{} { |
602 func (v *Viper) searchIndexableWithPathPrefixes(source interface{}, path []string) interface{} { |
592 if len(path) == 0 { |
603 if len(path) == 0 { |
593 return source |
604 return source |
594 } |
605 } |
595 |
606 |
596 // search for path prefixes, starting from the longest one |
607 // search for path prefixes, starting from the longest one |
597 for i := len(path); i > 0; i-- { |
608 for i := len(path); i > 0; i-- { |
598 prefixKey := strings.ToLower(strings.Join(path[0:i], v.keyDelim)) |
609 prefixKey := strings.ToLower(strings.Join(path[0:i], v.keyDelim)) |
599 |
610 |
600 next, ok := source[prefixKey] |
611 var val interface{} |
601 if ok { |
612 switch sourceIndexable := source.(type) { |
602 // Fast path |
613 case []interface{}: |
603 if i == len(path) { |
614 val = v.searchSliceWithPathPrefixes(sourceIndexable, prefixKey, i, path) |
604 return next |
615 case map[string]interface{}: |
605 } |
616 val = v.searchMapWithPathPrefixes(sourceIndexable, prefixKey, i, path) |
606 |
617 } |
607 // Nested case |
618 if val != nil { |
608 var val interface{} |
619 return val |
609 switch next.(type) { |
620 } |
610 case map[interface{}]interface{}: |
621 } |
611 val = v.searchMapWithPathPrefixes(cast.ToStringMap(next), path[i:]) |
622 |
612 case map[string]interface{}: |
623 // not found |
613 // Type assertion is safe here since it is only reached |
624 return nil |
614 // if the type of `next` is the same as the type being asserted |
625 } |
615 val = v.searchMapWithPathPrefixes(next.(map[string]interface{}), path[i:]) |
626 |
616 default: |
627 // searchSliceWithPathPrefixes searches for a value for path in sourceSlice |
617 // got a value but nested key expected, do nothing and look for next prefix |
628 // |
618 } |
629 // This function is part of the searchIndexableWithPathPrefixes recurring search and |
619 if val != nil { |
630 // should not be called directly from functions other than searchIndexableWithPathPrefixes. |
620 return val |
631 func (v *Viper) searchSliceWithPathPrefixes( |
621 } |
632 sourceSlice []interface{}, |
622 } |
633 prefixKey string, |
634 pathIndex int, |
|
635 path []string, |
|
636 ) interface{} { |
|
637 // if the prefixKey is not a number or it is out of bounds of the slice |
|
638 index, err := strconv.Atoi(prefixKey) |
|
639 if err != nil || len(sourceSlice) <= index { |
|
640 return nil |
|
641 } |
|
642 |
|
643 next := sourceSlice[index] |
|
644 |
|
645 // Fast path |
|
646 if pathIndex == len(path) { |
|
647 return next |
|
648 } |
|
649 |
|
650 switch n := next.(type) { |
|
651 case map[interface{}]interface{}: |
|
652 return v.searchIndexableWithPathPrefixes(cast.ToStringMap(n), path[pathIndex:]) |
|
653 case map[string]interface{}, []interface{}: |
|
654 return v.searchIndexableWithPathPrefixes(n, path[pathIndex:]) |
|
655 default: |
|
656 // got a value but nested key expected, do nothing and look for next prefix |
|
657 } |
|
658 |
|
659 // not found |
|
660 return nil |
|
661 } |
|
662 |
|
663 // searchMapWithPathPrefixes searches for a value for path in sourceMap |
|
664 // |
|
665 // This function is part of the searchIndexableWithPathPrefixes recurring search and |
|
666 // should not be called directly from functions other than searchIndexableWithPathPrefixes. |
|
667 func (v *Viper) searchMapWithPathPrefixes( |
|
668 sourceMap map[string]interface{}, |
|
669 prefixKey string, |
|
670 pathIndex int, |
|
671 path []string, |
|
672 ) interface{} { |
|
673 next, ok := sourceMap[prefixKey] |
|
674 if !ok { |
|
675 return nil |
|
676 } |
|
677 |
|
678 // Fast path |
|
679 if pathIndex == len(path) { |
|
680 return next |
|
681 } |
|
682 |
|
683 // Nested case |
|
684 switch n := next.(type) { |
|
685 case map[interface{}]interface{}: |
|
686 return v.searchIndexableWithPathPrefixes(cast.ToStringMap(n), path[pathIndex:]) |
|
687 case map[string]interface{}, []interface{}: |
|
688 return v.searchIndexableWithPathPrefixes(n, path[pathIndex:]) |
|
689 default: |
|
690 // got a value but nested key expected, do nothing and look for next prefix |
|
623 } |
691 } |
624 |
692 |
625 // not found |
693 // not found |
626 return nil |
694 return nil |
627 } |
695 } |
704 // |
772 // |
705 // Otherwise the Get function would return: |
773 // Otherwise the Get function would return: |
706 // |
774 // |
707 // "a b c" |
775 // "a b c" |
708 func SetTypeByDefaultValue(enable bool) { v.SetTypeByDefaultValue(enable) } |
776 func SetTypeByDefaultValue(enable bool) { v.SetTypeByDefaultValue(enable) } |
777 |
|
709 func (v *Viper) SetTypeByDefaultValue(enable bool) { |
778 func (v *Viper) SetTypeByDefaultValue(enable bool) { |
710 v.typeByDefValue = enable |
779 v.typeByDefValue = enable |
711 } |
780 } |
712 |
781 |
713 // GetViper gets the global Viper instance. |
782 // GetViper gets the global Viper instance. |
721 // place from where it is set. Viper will check in the following order: |
790 // place from where it is set. Viper will check in the following order: |
722 // override, flag, env, config file, key/value store, default |
791 // override, flag, env, config file, key/value store, default |
723 // |
792 // |
724 // Get returns an interface. For a specific value use one of the Get____ methods. |
793 // Get returns an interface. For a specific value use one of the Get____ methods. |
725 func Get(key string) interface{} { return v.Get(key) } |
794 func Get(key string) interface{} { return v.Get(key) } |
795 |
|
726 func (v *Viper) Get(key string) interface{} { |
796 func (v *Viper) Get(key string) interface{} { |
727 lcaseKey := strings.ToLower(key) |
797 lcaseKey := strings.ToLower(key) |
728 val := v.find(lcaseKey, true) |
798 val := v.find(lcaseKey, true) |
729 if val == nil { |
799 if val == nil { |
730 return nil |
800 return nil |
771 } |
841 } |
772 |
842 |
773 // Sub returns new Viper instance representing a sub tree of this instance. |
843 // Sub returns new Viper instance representing a sub tree of this instance. |
774 // Sub is case-insensitive for a key. |
844 // Sub is case-insensitive for a key. |
775 func Sub(key string) *Viper { return v.Sub(key) } |
845 func Sub(key string) *Viper { return v.Sub(key) } |
846 |
|
776 func (v *Viper) Sub(key string) *Viper { |
847 func (v *Viper) Sub(key string) *Viper { |
777 subv := New() |
848 subv := New() |
778 data := v.Get(key) |
849 data := v.Get(key) |
779 if data == nil { |
850 if data == nil { |
780 return nil |
851 return nil |
787 return nil |
858 return nil |
788 } |
859 } |
789 |
860 |
790 // GetString returns the value associated with the key as a string. |
861 // GetString returns the value associated with the key as a string. |
791 func GetString(key string) string { return v.GetString(key) } |
862 func GetString(key string) string { return v.GetString(key) } |
863 |
|
792 func (v *Viper) GetString(key string) string { |
864 func (v *Viper) GetString(key string) string { |
793 return cast.ToString(v.Get(key)) |
865 return cast.ToString(v.Get(key)) |
794 } |
866 } |
795 |
867 |
796 // GetBool returns the value associated with the key as a boolean. |
868 // GetBool returns the value associated with the key as a boolean. |
797 func GetBool(key string) bool { return v.GetBool(key) } |
869 func GetBool(key string) bool { return v.GetBool(key) } |
870 |
|
798 func (v *Viper) GetBool(key string) bool { |
871 func (v *Viper) GetBool(key string) bool { |
799 return cast.ToBool(v.Get(key)) |
872 return cast.ToBool(v.Get(key)) |
800 } |
873 } |
801 |
874 |
802 // GetInt returns the value associated with the key as an integer. |
875 // GetInt returns the value associated with the key as an integer. |
803 func GetInt(key string) int { return v.GetInt(key) } |
876 func GetInt(key string) int { return v.GetInt(key) } |
877 |
|
804 func (v *Viper) GetInt(key string) int { |
878 func (v *Viper) GetInt(key string) int { |
805 return cast.ToInt(v.Get(key)) |
879 return cast.ToInt(v.Get(key)) |
806 } |
880 } |
807 |
881 |
808 // GetInt32 returns the value associated with the key as an integer. |
882 // GetInt32 returns the value associated with the key as an integer. |
809 func GetInt32(key string) int32 { return v.GetInt32(key) } |
883 func GetInt32(key string) int32 { return v.GetInt32(key) } |
884 |
|
810 func (v *Viper) GetInt32(key string) int32 { |
885 func (v *Viper) GetInt32(key string) int32 { |
811 return cast.ToInt32(v.Get(key)) |
886 return cast.ToInt32(v.Get(key)) |
812 } |
887 } |
813 |
888 |
814 // GetInt64 returns the value associated with the key as an integer. |
889 // GetInt64 returns the value associated with the key as an integer. |
815 func GetInt64(key string) int64 { return v.GetInt64(key) } |
890 func GetInt64(key string) int64 { return v.GetInt64(key) } |
891 |
|
816 func (v *Viper) GetInt64(key string) int64 { |
892 func (v *Viper) GetInt64(key string) int64 { |
817 return cast.ToInt64(v.Get(key)) |
893 return cast.ToInt64(v.Get(key)) |
818 } |
894 } |
819 |
895 |
820 // GetUint returns the value associated with the key as an unsigned integer. |
896 // GetUint returns the value associated with the key as an unsigned integer. |
821 func GetUint(key string) uint { return v.GetUint(key) } |
897 func GetUint(key string) uint { return v.GetUint(key) } |
898 |
|
822 func (v *Viper) GetUint(key string) uint { |
899 func (v *Viper) GetUint(key string) uint { |
823 return cast.ToUint(v.Get(key)) |
900 return cast.ToUint(v.Get(key)) |
824 } |
901 } |
825 |
902 |
826 // GetUint32 returns the value associated with the key as an unsigned integer. |
903 // GetUint32 returns the value associated with the key as an unsigned integer. |
827 func GetUint32(key string) uint32 { return v.GetUint32(key) } |
904 func GetUint32(key string) uint32 { return v.GetUint32(key) } |
905 |
|
828 func (v *Viper) GetUint32(key string) uint32 { |
906 func (v *Viper) GetUint32(key string) uint32 { |
829 return cast.ToUint32(v.Get(key)) |
907 return cast.ToUint32(v.Get(key)) |
830 } |
908 } |
831 |
909 |
832 // GetUint64 returns the value associated with the key as an unsigned integer. |
910 // GetUint64 returns the value associated with the key as an unsigned integer. |
833 func GetUint64(key string) uint64 { return v.GetUint64(key) } |
911 func GetUint64(key string) uint64 { return v.GetUint64(key) } |
912 |
|
834 func (v *Viper) GetUint64(key string) uint64 { |
913 func (v *Viper) GetUint64(key string) uint64 { |
835 return cast.ToUint64(v.Get(key)) |
914 return cast.ToUint64(v.Get(key)) |
836 } |
915 } |
837 |
916 |
838 // GetFloat64 returns the value associated with the key as a float64. |
917 // GetFloat64 returns the value associated with the key as a float64. |
839 func GetFloat64(key string) float64 { return v.GetFloat64(key) } |
918 func GetFloat64(key string) float64 { return v.GetFloat64(key) } |
919 |
|
840 func (v *Viper) GetFloat64(key string) float64 { |
920 func (v *Viper) GetFloat64(key string) float64 { |
841 return cast.ToFloat64(v.Get(key)) |
921 return cast.ToFloat64(v.Get(key)) |
842 } |
922 } |
843 |
923 |
844 // GetTime returns the value associated with the key as time. |
924 // GetTime returns the value associated with the key as time. |
845 func GetTime(key string) time.Time { return v.GetTime(key) } |
925 func GetTime(key string) time.Time { return v.GetTime(key) } |
926 |
|
846 func (v *Viper) GetTime(key string) time.Time { |
927 func (v *Viper) GetTime(key string) time.Time { |
847 return cast.ToTime(v.Get(key)) |
928 return cast.ToTime(v.Get(key)) |
848 } |
929 } |
849 |
930 |
850 // GetDuration returns the value associated with the key as a duration. |
931 // GetDuration returns the value associated with the key as a duration. |
851 func GetDuration(key string) time.Duration { return v.GetDuration(key) } |
932 func GetDuration(key string) time.Duration { return v.GetDuration(key) } |
933 |
|
852 func (v *Viper) GetDuration(key string) time.Duration { |
934 func (v *Viper) GetDuration(key string) time.Duration { |
853 return cast.ToDuration(v.Get(key)) |
935 return cast.ToDuration(v.Get(key)) |
854 } |
936 } |
855 |
937 |
856 // GetIntSlice returns the value associated with the key as a slice of int values. |
938 // GetIntSlice returns the value associated with the key as a slice of int values. |
857 func GetIntSlice(key string) []int { return v.GetIntSlice(key) } |
939 func GetIntSlice(key string) []int { return v.GetIntSlice(key) } |
940 |
|
858 func (v *Viper) GetIntSlice(key string) []int { |
941 func (v *Viper) GetIntSlice(key string) []int { |
859 return cast.ToIntSlice(v.Get(key)) |
942 return cast.ToIntSlice(v.Get(key)) |
860 } |
943 } |
861 |
944 |
862 // GetStringSlice returns the value associated with the key as a slice of strings. |
945 // GetStringSlice returns the value associated with the key as a slice of strings. |
863 func GetStringSlice(key string) []string { return v.GetStringSlice(key) } |
946 func GetStringSlice(key string) []string { return v.GetStringSlice(key) } |
947 |
|
864 func (v *Viper) GetStringSlice(key string) []string { |
948 func (v *Viper) GetStringSlice(key string) []string { |
865 return cast.ToStringSlice(v.Get(key)) |
949 return cast.ToStringSlice(v.Get(key)) |
866 } |
950 } |
867 |
951 |
868 // GetStringMap returns the value associated with the key as a map of interfaces. |
952 // GetStringMap returns the value associated with the key as a map of interfaces. |
869 func GetStringMap(key string) map[string]interface{} { return v.GetStringMap(key) } |
953 func GetStringMap(key string) map[string]interface{} { return v.GetStringMap(key) } |
954 |
|
870 func (v *Viper) GetStringMap(key string) map[string]interface{} { |
955 func (v *Viper) GetStringMap(key string) map[string]interface{} { |
871 return cast.ToStringMap(v.Get(key)) |
956 return cast.ToStringMap(v.Get(key)) |
872 } |
957 } |
873 |
958 |
874 // GetStringMapString returns the value associated with the key as a map of strings. |
959 // GetStringMapString returns the value associated with the key as a map of strings. |
875 func GetStringMapString(key string) map[string]string { return v.GetStringMapString(key) } |
960 func GetStringMapString(key string) map[string]string { return v.GetStringMapString(key) } |
961 |
|
876 func (v *Viper) GetStringMapString(key string) map[string]string { |
962 func (v *Viper) GetStringMapString(key string) map[string]string { |
877 return cast.ToStringMapString(v.Get(key)) |
963 return cast.ToStringMapString(v.Get(key)) |
878 } |
964 } |
879 |
965 |
880 // GetStringMapStringSlice returns the value associated with the key as a map to a slice of strings. |
966 // GetStringMapStringSlice returns the value associated with the key as a map to a slice of strings. |
881 func GetStringMapStringSlice(key string) map[string][]string { return v.GetStringMapStringSlice(key) } |
967 func GetStringMapStringSlice(key string) map[string][]string { return v.GetStringMapStringSlice(key) } |
968 |
|
882 func (v *Viper) GetStringMapStringSlice(key string) map[string][]string { |
969 func (v *Viper) GetStringMapStringSlice(key string) map[string][]string { |
883 return cast.ToStringMapStringSlice(v.Get(key)) |
970 return cast.ToStringMapStringSlice(v.Get(key)) |
884 } |
971 } |
885 |
972 |
886 // GetSizeInBytes returns the size of the value associated with the given key |
973 // GetSizeInBytes returns the size of the value associated with the given key |
887 // in bytes. |
974 // in bytes. |
888 func GetSizeInBytes(key string) uint { return v.GetSizeInBytes(key) } |
975 func GetSizeInBytes(key string) uint { return v.GetSizeInBytes(key) } |
976 |
|
889 func (v *Viper) GetSizeInBytes(key string) uint { |
977 func (v *Viper) GetSizeInBytes(key string) uint { |
890 sizeStr := cast.ToString(v.Get(key)) |
978 sizeStr := cast.ToString(v.Get(key)) |
891 return parseSizeInBytes(sizeStr) |
979 return parseSizeInBytes(sizeStr) |
892 } |
980 } |
893 |
981 |
894 // UnmarshalKey takes a single key and unmarshals it into a Struct. |
982 // UnmarshalKey takes a single key and unmarshals it into a Struct. |
895 func UnmarshalKey(key string, rawVal interface{}, opts ...DecoderConfigOption) error { |
983 func UnmarshalKey(key string, rawVal interface{}, opts ...DecoderConfigOption) error { |
896 return v.UnmarshalKey(key, rawVal, opts...) |
984 return v.UnmarshalKey(key, rawVal, opts...) |
897 } |
985 } |
986 |
|
898 func (v *Viper) UnmarshalKey(key string, rawVal interface{}, opts ...DecoderConfigOption) error { |
987 func (v *Viper) UnmarshalKey(key string, rawVal interface{}, opts ...DecoderConfigOption) error { |
899 err := decode(v.Get(key), defaultDecoderConfig(rawVal, opts...)) |
988 return decode(v.Get(key), defaultDecoderConfig(rawVal, opts...)) |
900 |
|
901 if err != nil { |
|
902 return err |
|
903 } |
|
904 |
|
905 return nil |
|
906 } |
989 } |
907 |
990 |
908 // Unmarshal unmarshals the config into a Struct. Make sure that the tags |
991 // Unmarshal unmarshals the config into a Struct. Make sure that the tags |
909 // on the fields of the structure are properly set. |
992 // on the fields of the structure are properly set. |
910 func Unmarshal(rawVal interface{}, opts ...DecoderConfigOption) error { |
993 func Unmarshal(rawVal interface{}, opts ...DecoderConfigOption) error { |
911 return v.Unmarshal(rawVal, opts...) |
994 return v.Unmarshal(rawVal, opts...) |
912 } |
995 } |
996 |
|
913 func (v *Viper) Unmarshal(rawVal interface{}, opts ...DecoderConfigOption) error { |
997 func (v *Viper) Unmarshal(rawVal interface{}, opts ...DecoderConfigOption) error { |
914 err := decode(v.AllSettings(), defaultDecoderConfig(rawVal, opts...)) |
998 return decode(v.AllSettings(), defaultDecoderConfig(rawVal, opts...)) |
915 |
|
916 if err != nil { |
|
917 return err |
|
918 } |
|
919 |
|
920 return nil |
|
921 } |
999 } |
922 |
1000 |
923 // defaultDecoderConfig returns default mapsstructure.DecoderConfig with suppot |
1001 // defaultDecoderConfig returns default mapsstructure.DecoderConfig with suppot |
924 // of time.Duration values & string slices |
1002 // of time.Duration values & string slices |
925 func defaultDecoderConfig(output interface{}, opts ...DecoderConfigOption) *mapstructure.DecoderConfig { |
1003 func defaultDecoderConfig(output interface{}, opts ...DecoderConfigOption) *mapstructure.DecoderConfig { |
950 // UnmarshalExact unmarshals the config into a Struct, erroring if a field is nonexistent |
1028 // UnmarshalExact unmarshals the config into a Struct, erroring if a field is nonexistent |
951 // in the destination struct. |
1029 // in the destination struct. |
952 func UnmarshalExact(rawVal interface{}, opts ...DecoderConfigOption) error { |
1030 func UnmarshalExact(rawVal interface{}, opts ...DecoderConfigOption) error { |
953 return v.UnmarshalExact(rawVal, opts...) |
1031 return v.UnmarshalExact(rawVal, opts...) |
954 } |
1032 } |
1033 |
|
955 func (v *Viper) UnmarshalExact(rawVal interface{}, opts ...DecoderConfigOption) error { |
1034 func (v *Viper) UnmarshalExact(rawVal interface{}, opts ...DecoderConfigOption) error { |
956 config := defaultDecoderConfig(rawVal, opts...) |
1035 config := defaultDecoderConfig(rawVal, opts...) |
957 config.ErrorUnused = true |
1036 config.ErrorUnused = true |
958 |
1037 |
959 err := decode(v.AllSettings(), config) |
1038 return decode(v.AllSettings(), config) |
960 |
|
961 if err != nil { |
|
962 return err |
|
963 } |
|
964 |
|
965 return nil |
|
966 } |
1039 } |
967 |
1040 |
968 // BindPFlags binds a full flag set to the configuration, using each flag's long |
1041 // BindPFlags binds a full flag set to the configuration, using each flag's long |
969 // name as the config key. |
1042 // name as the config key. |
970 func BindPFlags(flags *pflag.FlagSet) error { return v.BindPFlags(flags) } |
1043 func BindPFlags(flags *pflag.FlagSet) error { return v.BindPFlags(flags) } |
1044 |
|
971 func (v *Viper) BindPFlags(flags *pflag.FlagSet) error { |
1045 func (v *Viper) BindPFlags(flags *pflag.FlagSet) error { |
972 return v.BindFlagValues(pflagValueSet{flags}) |
1046 return v.BindFlagValues(pflagValueSet{flags}) |
973 } |
1047 } |
974 |
1048 |
975 // BindPFlag binds a specific key to a pflag (as used by cobra). |
1049 // BindPFlag binds a specific key to a pflag (as used by cobra). |
977 // |
1051 // |
978 // serverCmd.Flags().Int("port", 1138, "Port to run Application server on") |
1052 // serverCmd.Flags().Int("port", 1138, "Port to run Application server on") |
979 // Viper.BindPFlag("port", serverCmd.Flags().Lookup("port")) |
1053 // Viper.BindPFlag("port", serverCmd.Flags().Lookup("port")) |
980 // |
1054 // |
981 func BindPFlag(key string, flag *pflag.Flag) error { return v.BindPFlag(key, flag) } |
1055 func BindPFlag(key string, flag *pflag.Flag) error { return v.BindPFlag(key, flag) } |
1056 |
|
982 func (v *Viper) BindPFlag(key string, flag *pflag.Flag) error { |
1057 func (v *Viper) BindPFlag(key string, flag *pflag.Flag) error { |
1058 if flag == nil { |
|
1059 return fmt.Errorf("flag for %q is nil", key) |
|
1060 } |
|
983 return v.BindFlagValue(key, pflagValue{flag}) |
1061 return v.BindFlagValue(key, pflagValue{flag}) |
984 } |
1062 } |
985 |
1063 |
986 // BindFlagValues binds a full FlagValue set to the configuration, using each flag's long |
1064 // BindFlagValues binds a full FlagValue set to the configuration, using each flag's long |
987 // name as the config key. |
1065 // name as the config key. |
988 func BindFlagValues(flags FlagValueSet) error { return v.BindFlagValues(flags) } |
1066 func BindFlagValues(flags FlagValueSet) error { return v.BindFlagValues(flags) } |
1067 |
|
989 func (v *Viper) BindFlagValues(flags FlagValueSet) (err error) { |
1068 func (v *Viper) BindFlagValues(flags FlagValueSet) (err error) { |
990 flags.VisitAll(func(flag FlagValue) { |
1069 flags.VisitAll(func(flag FlagValue) { |
991 if err = v.BindFlagValue(flag.Name(), flag); err != nil { |
1070 if err = v.BindFlagValue(flag.Name(), flag); err != nil { |
992 return |
1071 return |
993 } |
1072 } |
994 }) |
1073 }) |
995 return nil |
1074 return nil |
996 } |
1075 } |
997 |
1076 |
998 // BindFlagValue binds a specific key to a FlagValue. |
1077 // BindFlagValue binds a specific key to a FlagValue. |
999 // Example (where serverCmd is a Cobra instance): |
|
1000 // |
|
1001 // serverCmd.Flags().Int("port", 1138, "Port to run Application server on") |
|
1002 // Viper.BindFlagValue("port", serverCmd.Flags().Lookup("port")) |
|
1003 // |
|
1004 func BindFlagValue(key string, flag FlagValue) error { return v.BindFlagValue(key, flag) } |
1078 func BindFlagValue(key string, flag FlagValue) error { return v.BindFlagValue(key, flag) } |
1079 |
|
1005 func (v *Viper) BindFlagValue(key string, flag FlagValue) error { |
1080 func (v *Viper) BindFlagValue(key string, flag FlagValue) error { |
1006 if flag == nil { |
1081 if flag == nil { |
1007 return fmt.Errorf("flag for %q is nil", key) |
1082 return fmt.Errorf("flag for %q is nil", key) |
1008 } |
1083 } |
1009 v.pflags[strings.ToLower(key)] = flag |
1084 v.pflags[strings.ToLower(key)] = flag |
1011 } |
1086 } |
1012 |
1087 |
1013 // BindEnv binds a Viper key to a ENV variable. |
1088 // BindEnv binds a Viper key to a ENV variable. |
1014 // ENV variables are case sensitive. |
1089 // ENV variables are case sensitive. |
1015 // If only a key is provided, it will use the env key matching the key, uppercased. |
1090 // If only a key is provided, it will use the env key matching the key, uppercased. |
1091 // If more arguments are provided, they will represent the env variable names that |
|
1092 // should bind to this key and will be taken in the specified order. |
|
1016 // EnvPrefix will be used when set when env name is not provided. |
1093 // EnvPrefix will be used when set when env name is not provided. |
1017 func BindEnv(input ...string) error { return v.BindEnv(input...) } |
1094 func BindEnv(input ...string) error { return v.BindEnv(input...) } |
1095 |
|
1018 func (v *Viper) BindEnv(input ...string) error { |
1096 func (v *Viper) BindEnv(input ...string) error { |
1019 var key, envkey string |
|
1020 if len(input) == 0 { |
1097 if len(input) == 0 { |
1021 return fmt.Errorf("missing key to bind to") |
1098 return fmt.Errorf("missing key to bind to") |
1022 } |
1099 } |
1023 |
1100 |
1024 key = strings.ToLower(input[0]) |
1101 key := strings.ToLower(input[0]) |
1025 |
1102 |
1026 if len(input) == 1 { |
1103 if len(input) == 1 { |
1027 envkey = v.mergeWithEnvPrefix(key) |
1104 v.env[key] = append(v.env[key], v.mergeWithEnvPrefix(key)) |
1028 } else { |
1105 } else { |
1029 envkey = input[1] |
1106 v.env[key] = append(v.env[key], input[1:]...) |
1030 } |
1107 } |
1031 |
|
1032 v.env[key] = envkey |
|
1033 |
1108 |
1034 return nil |
1109 return nil |
1035 } |
1110 } |
1036 |
1111 |
1037 // Given a key, find the value. |
1112 // Given a key, find the value. |
1076 switch flag.ValueType() { |
1151 switch flag.ValueType() { |
1077 case "int", "int8", "int16", "int32", "int64": |
1152 case "int", "int8", "int16", "int32", "int64": |
1078 return cast.ToInt(flag.ValueString()) |
1153 return cast.ToInt(flag.ValueString()) |
1079 case "bool": |
1154 case "bool": |
1080 return cast.ToBool(flag.ValueString()) |
1155 return cast.ToBool(flag.ValueString()) |
1081 case "stringSlice": |
1156 case "stringSlice", "stringArray": |
1082 s := strings.TrimPrefix(flag.ValueString(), "[") |
1157 s := strings.TrimPrefix(flag.ValueString(), "[") |
1083 s = strings.TrimSuffix(s, "]") |
1158 s = strings.TrimSuffix(s, "]") |
1084 res, _ := readAsCSV(s) |
1159 res, _ := readAsCSV(s) |
1085 return res |
1160 return res |
1086 case "intSlice": |
1161 case "intSlice": |
1087 s := strings.TrimPrefix(flag.ValueString(), "[") |
1162 s := strings.TrimPrefix(flag.ValueString(), "[") |
1088 s = strings.TrimSuffix(s, "]") |
1163 s = strings.TrimSuffix(s, "]") |
1089 res, _ := readAsCSV(s) |
1164 res, _ := readAsCSV(s) |
1090 return cast.ToIntSlice(res) |
1165 return cast.ToIntSlice(res) |
1166 case "stringToString": |
|
1167 return stringToStringConv(flag.ValueString()) |
|
1091 default: |
1168 default: |
1092 return flag.ValueString() |
1169 return flag.ValueString() |
1093 } |
1170 } |
1094 } |
1171 } |
1095 if nested && v.isPathShadowedInFlatMap(path, v.pflags) != "" { |
1172 if nested && v.isPathShadowedInFlatMap(path, v.pflags) != "" { |
1105 } |
1182 } |
1106 if nested && v.isPathShadowedInAutoEnv(path) != "" { |
1183 if nested && v.isPathShadowedInAutoEnv(path) != "" { |
1107 return nil |
1184 return nil |
1108 } |
1185 } |
1109 } |
1186 } |
1110 envkey, exists := v.env[lcaseKey] |
1187 envkeys, exists := v.env[lcaseKey] |
1111 if exists { |
1188 if exists { |
1112 if val, ok := v.getEnv(envkey); ok { |
1189 for _, envkey := range envkeys { |
1113 return val |
1190 if val, ok := v.getEnv(envkey); ok { |
1191 return val |
|
1192 } |
|
1114 } |
1193 } |
1115 } |
1194 } |
1116 if nested && v.isPathShadowedInFlatMap(path, v.env) != "" { |
1195 if nested && v.isPathShadowedInFlatMap(path, v.env) != "" { |
1117 return nil |
1196 return nil |
1118 } |
1197 } |
1119 |
1198 |
1120 // Config file next |
1199 // Config file next |
1121 val = v.searchMapWithPathPrefixes(v.config, path) |
1200 val = v.searchIndexableWithPathPrefixes(v.config, path) |
1122 if val != nil { |
1201 if val != nil { |
1123 return val |
1202 return val |
1124 } |
1203 } |
1125 if nested && v.isPathShadowedInDeepMap(path, v.config) != "" { |
1204 if nested && v.isPathShadowedInDeepMap(path, v.config) != "" { |
1126 return nil |
1205 return nil |
1151 switch flag.ValueType() { |
1230 switch flag.ValueType() { |
1152 case "int", "int8", "int16", "int32", "int64": |
1231 case "int", "int8", "int16", "int32", "int64": |
1153 return cast.ToInt(flag.ValueString()) |
1232 return cast.ToInt(flag.ValueString()) |
1154 case "bool": |
1233 case "bool": |
1155 return cast.ToBool(flag.ValueString()) |
1234 return cast.ToBool(flag.ValueString()) |
1156 case "stringSlice": |
1235 case "stringSlice", "stringArray": |
1157 s := strings.TrimPrefix(flag.ValueString(), "[") |
1236 s := strings.TrimPrefix(flag.ValueString(), "[") |
1158 s = strings.TrimSuffix(s, "]") |
1237 s = strings.TrimSuffix(s, "]") |
1159 res, _ := readAsCSV(s) |
1238 res, _ := readAsCSV(s) |
1160 return res |
1239 return res |
1161 case "intSlice": |
1240 case "intSlice": |
1162 s := strings.TrimPrefix(flag.ValueString(), "[") |
1241 s := strings.TrimPrefix(flag.ValueString(), "[") |
1163 s = strings.TrimSuffix(s, "]") |
1242 s = strings.TrimSuffix(s, "]") |
1164 res, _ := readAsCSV(s) |
1243 res, _ := readAsCSV(s) |
1165 return cast.ToIntSlice(res) |
1244 return cast.ToIntSlice(res) |
1245 case "stringToString": |
|
1246 return stringToStringConv(flag.ValueString()) |
|
1166 default: |
1247 default: |
1167 return flag.ValueString() |
1248 return flag.ValueString() |
1168 } |
1249 } |
1169 } |
1250 } |
1170 // last item, no need to check shadowing |
1251 // last item, no need to check shadowing |
1180 stringReader := strings.NewReader(val) |
1261 stringReader := strings.NewReader(val) |
1181 csvReader := csv.NewReader(stringReader) |
1262 csvReader := csv.NewReader(stringReader) |
1182 return csvReader.Read() |
1263 return csvReader.Read() |
1183 } |
1264 } |
1184 |
1265 |
1266 // mostly copied from pflag's implementation of this operation here https://github.com/spf13/pflag/blob/master/string_to_string.go#L79 |
|
1267 // alterations are: errors are swallowed, map[string]interface{} is returned in order to enable cast.ToStringMap |
|
1268 func stringToStringConv(val string) interface{} { |
|
1269 val = strings.Trim(val, "[]") |
|
1270 // An empty string would cause an empty map |
|
1271 if len(val) == 0 { |
|
1272 return map[string]interface{}{} |
|
1273 } |
|
1274 r := csv.NewReader(strings.NewReader(val)) |
|
1275 ss, err := r.Read() |
|
1276 if err != nil { |
|
1277 return nil |
|
1278 } |
|
1279 out := make(map[string]interface{}, len(ss)) |
|
1280 for _, pair := range ss { |
|
1281 kv := strings.SplitN(pair, "=", 2) |
|
1282 if len(kv) != 2 { |
|
1283 return nil |
|
1284 } |
|
1285 out[kv[0]] = kv[1] |
|
1286 } |
|
1287 return out |
|
1288 } |
|
1289 |
|
1185 // IsSet checks to see if the key has been set in any of the data locations. |
1290 // IsSet checks to see if the key has been set in any of the data locations. |
1186 // IsSet is case-insensitive for a key. |
1291 // IsSet is case-insensitive for a key. |
1187 func IsSet(key string) bool { return v.IsSet(key) } |
1292 func IsSet(key string) bool { return v.IsSet(key) } |
1293 |
|
1188 func (v *Viper) IsSet(key string) bool { |
1294 func (v *Viper) IsSet(key string) bool { |
1189 lcaseKey := strings.ToLower(key) |
1295 lcaseKey := strings.ToLower(key) |
1190 val := v.find(lcaseKey, false) |
1296 val := v.find(lcaseKey, false) |
1191 return val != nil |
1297 return val != nil |
1192 } |
1298 } |
1193 |
1299 |
1194 // AutomaticEnv has Viper check ENV variables for all. |
1300 // AutomaticEnv makes Viper check if environment variables match any of the existing keys |
1195 // keys set in config, default & flags |
1301 // (config, default or flags). If matching env vars are found, they are loaded into Viper. |
1196 func AutomaticEnv() { v.AutomaticEnv() } |
1302 func AutomaticEnv() { v.AutomaticEnv() } |
1303 |
|
1197 func (v *Viper) AutomaticEnv() { |
1304 func (v *Viper) AutomaticEnv() { |
1198 v.automaticEnvApplied = true |
1305 v.automaticEnvApplied = true |
1199 } |
1306 } |
1200 |
1307 |
1201 // SetEnvKeyReplacer sets the strings.Replacer on the viper object |
1308 // SetEnvKeyReplacer sets the strings.Replacer on the viper object |
1202 // Useful for mapping an environmental variable to a key that does |
1309 // Useful for mapping an environmental variable to a key that does |
1203 // not match it. |
1310 // not match it. |
1204 func SetEnvKeyReplacer(r *strings.Replacer) { v.SetEnvKeyReplacer(r) } |
1311 func SetEnvKeyReplacer(r *strings.Replacer) { v.SetEnvKeyReplacer(r) } |
1312 |
|
1205 func (v *Viper) SetEnvKeyReplacer(r *strings.Replacer) { |
1313 func (v *Viper) SetEnvKeyReplacer(r *strings.Replacer) { |
1206 v.envKeyReplacer = r |
1314 v.envKeyReplacer = r |
1207 } |
1315 } |
1208 |
1316 |
1209 // RegisterAlias creates an alias that provides another accessor for the same key. |
1317 // RegisterAlias creates an alias that provides another accessor for the same key. |
1210 // This enables one to change a name without breaking the application. |
1318 // This enables one to change a name without breaking the application. |
1211 func RegisterAlias(alias string, key string) { v.RegisterAlias(alias, key) } |
1319 func RegisterAlias(alias string, key string) { v.RegisterAlias(alias, key) } |
1320 |
|
1212 func (v *Viper) RegisterAlias(alias string, key string) { |
1321 func (v *Viper) RegisterAlias(alias string, key string) { |
1213 v.registerAlias(alias, strings.ToLower(key)) |
1322 v.registerAlias(alias, strings.ToLower(key)) |
1214 } |
1323 } |
1215 |
1324 |
1216 func (v *Viper) registerAlias(alias string, key string) { |
1325 func (v *Viper) registerAlias(alias string, key string) { |
1254 return key |
1363 return key |
1255 } |
1364 } |
1256 |
1365 |
1257 // InConfig checks to see if the given key (or an alias) is in the config file. |
1366 // InConfig checks to see if the given key (or an alias) is in the config file. |
1258 func InConfig(key string) bool { return v.InConfig(key) } |
1367 func InConfig(key string) bool { return v.InConfig(key) } |
1368 |
|
1259 func (v *Viper) InConfig(key string) bool { |
1369 func (v *Viper) InConfig(key string) bool { |
1260 // if the requested key is an alias, then return the proper key |
1370 // if the requested key is an alias, then return the proper key |
1261 key = v.realKey(key) |
1371 key = v.realKey(key) |
1262 |
1372 |
1263 _, exists := v.config[key] |
1373 _, exists := v.config[key] |
1266 |
1376 |
1267 // SetDefault sets the default value for this key. |
1377 // SetDefault sets the default value for this key. |
1268 // SetDefault is case-insensitive for a key. |
1378 // SetDefault is case-insensitive for a key. |
1269 // Default only used when no value is provided by the user via flag, config or ENV. |
1379 // Default only used when no value is provided by the user via flag, config or ENV. |
1270 func SetDefault(key string, value interface{}) { v.SetDefault(key, value) } |
1380 func SetDefault(key string, value interface{}) { v.SetDefault(key, value) } |
1381 |
|
1271 func (v *Viper) SetDefault(key string, value interface{}) { |
1382 func (v *Viper) SetDefault(key string, value interface{}) { |
1272 // If alias passed in, then set the proper default |
1383 // If alias passed in, then set the proper default |
1273 key = v.realKey(strings.ToLower(key)) |
1384 key = v.realKey(strings.ToLower(key)) |
1274 value = toCaseInsensitiveValue(value) |
1385 value = toCaseInsensitiveValue(value) |
1275 |
1386 |
1284 // Set sets the value for the key in the override register. |
1395 // Set sets the value for the key in the override register. |
1285 // Set is case-insensitive for a key. |
1396 // Set is case-insensitive for a key. |
1286 // Will be used instead of values obtained via |
1397 // Will be used instead of values obtained via |
1287 // flags, config file, ENV, default, or key/value store. |
1398 // flags, config file, ENV, default, or key/value store. |
1288 func Set(key string, value interface{}) { v.Set(key, value) } |
1399 func Set(key string, value interface{}) { v.Set(key, value) } |
1400 |
|
1289 func (v *Viper) Set(key string, value interface{}) { |
1401 func (v *Viper) Set(key string, value interface{}) { |
1290 // If alias passed in, then set the proper override |
1402 // If alias passed in, then set the proper override |
1291 key = v.realKey(strings.ToLower(key)) |
1403 key = v.realKey(strings.ToLower(key)) |
1292 value = toCaseInsensitiveValue(value) |
1404 value = toCaseInsensitiveValue(value) |
1293 |
1405 |
1300 } |
1412 } |
1301 |
1413 |
1302 // ReadInConfig will discover and load the configuration file from disk |
1414 // ReadInConfig will discover and load the configuration file from disk |
1303 // and key/value stores, searching in one of the defined paths. |
1415 // and key/value stores, searching in one of the defined paths. |
1304 func ReadInConfig() error { return v.ReadInConfig() } |
1416 func ReadInConfig() error { return v.ReadInConfig() } |
1417 |
|
1305 func (v *Viper) ReadInConfig() error { |
1418 func (v *Viper) ReadInConfig() error { |
1306 jww.INFO.Println("Attempting to read in config file") |
1419 jww.INFO.Println("Attempting to read in config file") |
1307 filename, err := v.getConfigFile() |
1420 filename, err := v.getConfigFile() |
1308 if err != nil { |
1421 if err != nil { |
1309 return err |
1422 return err |
1330 return nil |
1443 return nil |
1331 } |
1444 } |
1332 |
1445 |
1333 // MergeInConfig merges a new configuration with an existing config. |
1446 // MergeInConfig merges a new configuration with an existing config. |
1334 func MergeInConfig() error { return v.MergeInConfig() } |
1447 func MergeInConfig() error { return v.MergeInConfig() } |
1448 |
|
1335 func (v *Viper) MergeInConfig() error { |
1449 func (v *Viper) MergeInConfig() error { |
1336 jww.INFO.Println("Attempting to merge in config file") |
1450 jww.INFO.Println("Attempting to merge in config file") |
1337 filename, err := v.getConfigFile() |
1451 filename, err := v.getConfigFile() |
1338 if err != nil { |
1452 if err != nil { |
1339 return err |
1453 return err |
1352 } |
1466 } |
1353 |
1467 |
1354 // ReadConfig will read a configuration file, setting existing keys to nil if the |
1468 // ReadConfig will read a configuration file, setting existing keys to nil if the |
1355 // key does not exist in the file. |
1469 // key does not exist in the file. |
1356 func ReadConfig(in io.Reader) error { return v.ReadConfig(in) } |
1470 func ReadConfig(in io.Reader) error { return v.ReadConfig(in) } |
1471 |
|
1357 func (v *Viper) ReadConfig(in io.Reader) error { |
1472 func (v *Viper) ReadConfig(in io.Reader) error { |
1358 v.config = make(map[string]interface{}) |
1473 v.config = make(map[string]interface{}) |
1359 return v.unmarshalReader(in, v.config) |
1474 return v.unmarshalReader(in, v.config) |
1360 } |
1475 } |
1361 |
1476 |
1362 // MergeConfig merges a new configuration with an existing config. |
1477 // MergeConfig merges a new configuration with an existing config. |
1363 func MergeConfig(in io.Reader) error { return v.MergeConfig(in) } |
1478 func MergeConfig(in io.Reader) error { return v.MergeConfig(in) } |
1479 |
|
1364 func (v *Viper) MergeConfig(in io.Reader) error { |
1480 func (v *Viper) MergeConfig(in io.Reader) error { |
1365 cfg := make(map[string]interface{}) |
1481 cfg := make(map[string]interface{}) |
1366 if err := v.unmarshalReader(in, cfg); err != nil { |
1482 if err := v.unmarshalReader(in, cfg); err != nil { |
1367 return err |
1483 return err |
1368 } |
1484 } |
1370 } |
1486 } |
1371 |
1487 |
1372 // MergeConfigMap merges the configuration from the map given with an existing config. |
1488 // MergeConfigMap merges the configuration from the map given with an existing config. |
1373 // Note that the map given may be modified. |
1489 // Note that the map given may be modified. |
1374 func MergeConfigMap(cfg map[string]interface{}) error { return v.MergeConfigMap(cfg) } |
1490 func MergeConfigMap(cfg map[string]interface{}) error { return v.MergeConfigMap(cfg) } |
1491 |
|
1375 func (v *Viper) MergeConfigMap(cfg map[string]interface{}) error { |
1492 func (v *Viper) MergeConfigMap(cfg map[string]interface{}) error { |
1376 if v.config == nil { |
1493 if v.config == nil { |
1377 v.config = make(map[string]interface{}) |
1494 v.config = make(map[string]interface{}) |
1378 } |
1495 } |
1379 insensitiviseMap(cfg) |
1496 insensitiviseMap(cfg) |
1381 return nil |
1498 return nil |
1382 } |
1499 } |
1383 |
1500 |
1384 // WriteConfig writes the current configuration to a file. |
1501 // WriteConfig writes the current configuration to a file. |
1385 func WriteConfig() error { return v.WriteConfig() } |
1502 func WriteConfig() error { return v.WriteConfig() } |
1503 |
|
1386 func (v *Viper) WriteConfig() error { |
1504 func (v *Viper) WriteConfig() error { |
1387 filename, err := v.getConfigFile() |
1505 filename, err := v.getConfigFile() |
1388 if err != nil { |
1506 if err != nil { |
1389 return err |
1507 return err |
1390 } |
1508 } |
1391 return v.writeConfig(filename, true) |
1509 return v.writeConfig(filename, true) |
1392 } |
1510 } |
1393 |
1511 |
1394 // SafeWriteConfig writes current configuration to file only if the file does not exist. |
1512 // SafeWriteConfig writes current configuration to file only if the file does not exist. |
1395 func SafeWriteConfig() error { return v.SafeWriteConfig() } |
1513 func SafeWriteConfig() error { return v.SafeWriteConfig() } |
1514 |
|
1396 func (v *Viper) SafeWriteConfig() error { |
1515 func (v *Viper) SafeWriteConfig() error { |
1397 if len(v.configPaths) < 1 { |
1516 if len(v.configPaths) < 1 { |
1398 return errors.New("missing configuration for 'configPath'") |
1517 return errors.New("missing configuration for 'configPath'") |
1399 } |
1518 } |
1400 return v.SafeWriteConfigAs(filepath.Join(v.configPaths[0], v.configName+"."+v.configType)) |
1519 return v.SafeWriteConfigAs(filepath.Join(v.configPaths[0], v.configName+"."+v.configType)) |
1401 } |
1520 } |
1402 |
1521 |
1403 // WriteConfigAs writes current configuration to a given filename. |
1522 // WriteConfigAs writes current configuration to a given filename. |
1404 func WriteConfigAs(filename string) error { return v.WriteConfigAs(filename) } |
1523 func WriteConfigAs(filename string) error { return v.WriteConfigAs(filename) } |
1524 |
|
1405 func (v *Viper) WriteConfigAs(filename string) error { |
1525 func (v *Viper) WriteConfigAs(filename string) error { |
1406 return v.writeConfig(filename, true) |
1526 return v.writeConfig(filename, true) |
1407 } |
1527 } |
1408 |
1528 |
1409 // SafeWriteConfigAs writes current configuration to a given filename if it does not exist. |
1529 // SafeWriteConfigAs writes current configuration to a given filename if it does not exist. |
1410 func SafeWriteConfigAs(filename string) error { return v.SafeWriteConfigAs(filename) } |
1530 func SafeWriteConfigAs(filename string) error { return v.SafeWriteConfigAs(filename) } |
1531 |
|
1411 func (v *Viper) SafeWriteConfigAs(filename string) error { |
1532 func (v *Viper) SafeWriteConfigAs(filename string) error { |
1412 alreadyExists, err := afero.Exists(v.fs, filename) |
1533 alreadyExists, err := afero.Exists(v.fs, filename) |
1413 if alreadyExists && err == nil { |
1534 if alreadyExists && err == nil { |
1414 return ConfigFileAlreadyExistsError(filename) |
1535 return ConfigFileAlreadyExistsError(filename) |
1415 } |
1536 } |
1416 return v.writeConfig(filename, false) |
1537 return v.writeConfig(filename, false) |
1417 } |
1538 } |
1418 |
1539 |
1419 func (v *Viper) writeConfig(filename string, force bool) error { |
1540 func (v *Viper) writeConfig(filename string, force bool) error { |
1420 jww.INFO.Println("Attempting to write configuration to file.") |
1541 jww.INFO.Println("Attempting to write configuration to file.") |
1542 var configType string |
|
1543 |
|
1421 ext := filepath.Ext(filename) |
1544 ext := filepath.Ext(filename) |
1422 if len(ext) <= 1 { |
1545 if ext != "" { |
1423 return fmt.Errorf("filename: %s requires valid extension", filename) |
1546 configType = ext[1:] |
1424 } |
1547 } else { |
1425 configType := ext[1:] |
1548 configType = v.configType |
1549 } |
|
1550 if configType == "" { |
|
1551 return fmt.Errorf("config type could not be determined for %s", filename) |
|
1552 } |
|
1553 |
|
1426 if !stringInSlice(configType, SupportedExts) { |
1554 if !stringInSlice(configType, SupportedExts) { |
1427 return UnsupportedConfigError(configType) |
1555 return UnsupportedConfigError(configType) |
1428 } |
1556 } |
1429 if v.config == nil { |
1557 if v.config == nil { |
1430 v.config = make(map[string]interface{}) |
1558 v.config = make(map[string]interface{}) |
1449 // Unmarshal a Reader into a map. |
1577 // Unmarshal a Reader into a map. |
1450 // Should probably be an unexported function. |
1578 // Should probably be an unexported function. |
1451 func unmarshalReader(in io.Reader, c map[string]interface{}) error { |
1579 func unmarshalReader(in io.Reader, c map[string]interface{}) error { |
1452 return v.unmarshalReader(in, c) |
1580 return v.unmarshalReader(in, c) |
1453 } |
1581 } |
1582 |
|
1454 func (v *Viper) unmarshalReader(in io.Reader, c map[string]interface{}) error { |
1583 func (v *Viper) unmarshalReader(in io.Reader, c map[string]interface{}) error { |
1455 buf := new(bytes.Buffer) |
1584 buf := new(bytes.Buffer) |
1456 buf.ReadFrom(in) |
1585 buf.ReadFrom(in) |
1457 |
1586 |
1458 switch strings.ToLower(v.getConfigType()) { |
1587 switch strings.ToLower(v.getConfigType()) { |
1509 // set innermost value |
1638 // set innermost value |
1510 deepestMap[lastKey] = value |
1639 deepestMap[lastKey] = value |
1511 } |
1640 } |
1512 |
1641 |
1513 case "ini": |
1642 case "ini": |
1514 cfg := ini.Empty() |
1643 cfg := ini.Empty(v.iniLoadOptions) |
1515 err := cfg.Append(buf.Bytes()) |
1644 err := cfg.Append(buf.Bytes()) |
1516 if err != nil { |
1645 if err != nil { |
1517 return ConfigParseError{err} |
1646 return ConfigParseError{err} |
1518 } |
1647 } |
1519 sections := cfg.Sections() |
1648 sections := cfg.Sections() |
1617 sectionName := key[:(lastSep)] |
1746 sectionName := key[:(lastSep)] |
1618 keyName := key[(lastSep + 1):] |
1747 keyName := key[(lastSep + 1):] |
1619 if sectionName == "default" { |
1748 if sectionName == "default" { |
1620 sectionName = "" |
1749 sectionName = "" |
1621 } |
1750 } |
1622 cfg.Section(sectionName).Key(keyName).SetValue(Get(key).(string)) |
1751 cfg.Section(sectionName).Key(keyName).SetValue(v.GetString(key)) |
1623 } |
1752 } |
1624 cfg.WriteTo(f) |
1753 cfg.WriteTo(f) |
1625 } |
1754 } |
1626 return nil |
1755 return nil |
1627 } |
1756 } |
1640 func castToMapStringInterface( |
1769 func castToMapStringInterface( |
1641 src map[interface{}]interface{}) map[string]interface{} { |
1770 src map[interface{}]interface{}) map[string]interface{} { |
1642 tgt := map[string]interface{}{} |
1771 tgt := map[string]interface{}{} |
1643 for k, v := range src { |
1772 for k, v := range src { |
1644 tgt[fmt.Sprintf("%v", k)] = v |
1773 tgt[fmt.Sprintf("%v", k)] = v |
1774 } |
|
1775 return tgt |
|
1776 } |
|
1777 |
|
1778 func castMapStringSliceToMapInterface(src map[string][]string) map[string]interface{} { |
|
1779 tgt := map[string]interface{}{} |
|
1780 for k, v := range src { |
|
1781 tgt[k] = v |
|
1645 } |
1782 } |
1646 return tgt |
1783 return tgt |
1647 } |
1784 } |
1648 |
1785 |
1649 func castMapStringToMapInterface(src map[string]string) map[string]interface{} { |
1786 func castMapStringToMapInterface(src map[string]string) map[string]interface{} { |
1690 continue |
1827 continue |
1691 } |
1828 } |
1692 |
1829 |
1693 svType := reflect.TypeOf(sv) |
1830 svType := reflect.TypeOf(sv) |
1694 tvType := reflect.TypeOf(tv) |
1831 tvType := reflect.TypeOf(tv) |
1695 if svType != tvType { |
1832 if tvType != nil && svType != tvType { // Allow for the target to be nil |
1696 jww.ERROR.Printf( |
1833 jww.ERROR.Printf( |
1697 "svType != tvType; key=%s, st=%v, tt=%v, sv=%v, tv=%v", |
1834 "svType != tvType; key=%s, st=%v, tt=%v, sv=%v, tv=%v", |
1698 sk, svType, tvType, sv, tv) |
1835 sk, svType, tvType, sv, tv) |
1699 continue |
1836 continue |
1700 } |
1837 } |
1723 } |
1860 } |
1724 |
1861 |
1725 // ReadRemoteConfig attempts to get configuration from a remote source |
1862 // ReadRemoteConfig attempts to get configuration from a remote source |
1726 // and read it in the remote configuration registry. |
1863 // and read it in the remote configuration registry. |
1727 func ReadRemoteConfig() error { return v.ReadRemoteConfig() } |
1864 func ReadRemoteConfig() error { return v.ReadRemoteConfig() } |
1865 |
|
1728 func (v *Viper) ReadRemoteConfig() error { |
1866 func (v *Viper) ReadRemoteConfig() error { |
1729 return v.getKeyValueConfig() |
1867 return v.getKeyValueConfig() |
1730 } |
1868 } |
1731 |
1869 |
1732 func WatchRemoteConfig() error { return v.WatchRemoteConfig() } |
1870 func WatchRemoteConfig() error { return v.WatchRemoteConfig() } |
1745 } |
1883 } |
1746 |
1884 |
1747 for _, rp := range v.remoteProviders { |
1885 for _, rp := range v.remoteProviders { |
1748 val, err := v.getRemoteConfig(rp) |
1886 val, err := v.getRemoteConfig(rp) |
1749 if err != nil { |
1887 if err != nil { |
1888 jww.ERROR.Printf("get remote config: %s", err) |
|
1889 |
|
1750 continue |
1890 continue |
1751 } |
1891 } |
1892 |
|
1752 v.kvstore = val |
1893 v.kvstore = val |
1894 |
|
1753 return nil |
1895 return nil |
1754 } |
1896 } |
1755 return RemoteConfigError("No Files Found") |
1897 return RemoteConfigError("No Files Found") |
1756 } |
1898 } |
1757 |
1899 |
1804 } |
1946 } |
1805 |
1947 |
1806 // AllKeys returns all keys holding a value, regardless of where they are set. |
1948 // AllKeys returns all keys holding a value, regardless of where they are set. |
1807 // Nested keys are returned with a v.keyDelim separator |
1949 // Nested keys are returned with a v.keyDelim separator |
1808 func AllKeys() []string { return v.AllKeys() } |
1950 func AllKeys() []string { return v.AllKeys() } |
1951 |
|
1809 func (v *Viper) AllKeys() []string { |
1952 func (v *Viper) AllKeys() []string { |
1810 m := map[string]bool{} |
1953 m := map[string]bool{} |
1811 // add all paths, by order of descending priority to ensure correct shadowing |
1954 // add all paths, by order of descending priority to ensure correct shadowing |
1812 m = v.flattenAndMergeMap(m, castMapStringToMapInterface(v.aliases), "") |
1955 m = v.flattenAndMergeMap(m, castMapStringToMapInterface(v.aliases), "") |
1813 m = v.flattenAndMergeMap(m, v.override, "") |
1956 m = v.flattenAndMergeMap(m, v.override, "") |
1814 m = v.mergeFlatMap(m, castMapFlagToMapInterface(v.pflags)) |
1957 m = v.mergeFlatMap(m, castMapFlagToMapInterface(v.pflags)) |
1815 m = v.mergeFlatMap(m, castMapStringToMapInterface(v.env)) |
1958 m = v.mergeFlatMap(m, castMapStringSliceToMapInterface(v.env)) |
1816 m = v.flattenAndMergeMap(m, v.config, "") |
1959 m = v.flattenAndMergeMap(m, v.config, "") |
1817 m = v.flattenAndMergeMap(m, v.kvstore, "") |
1960 m = v.flattenAndMergeMap(m, v.kvstore, "") |
1818 m = v.flattenAndMergeMap(m, v.defaults, "") |
1961 m = v.flattenAndMergeMap(m, v.defaults, "") |
1819 |
1962 |
1820 // convert set of paths to list |
1963 // convert set of paths to list |
1884 return shadow |
2027 return shadow |
1885 } |
2028 } |
1886 |
2029 |
1887 // AllSettings merges all settings and returns them as a map[string]interface{}. |
2030 // AllSettings merges all settings and returns them as a map[string]interface{}. |
1888 func AllSettings() map[string]interface{} { return v.AllSettings() } |
2031 func AllSettings() map[string]interface{} { return v.AllSettings() } |
2032 |
|
1889 func (v *Viper) AllSettings() map[string]interface{} { |
2033 func (v *Viper) AllSettings() map[string]interface{} { |
1890 m := map[string]interface{}{} |
2034 m := map[string]interface{}{} |
1891 // start from the list of keys, and construct the map one value at a time |
2035 // start from the list of keys, and construct the map one value at a time |
1892 for _, k := range v.AllKeys() { |
2036 for _, k := range v.AllKeys() { |
1893 value := v.Get(k) |
2037 value := v.Get(k) |
1905 return m |
2049 return m |
1906 } |
2050 } |
1907 |
2051 |
1908 // SetFs sets the filesystem to use to read configuration. |
2052 // SetFs sets the filesystem to use to read configuration. |
1909 func SetFs(fs afero.Fs) { v.SetFs(fs) } |
2053 func SetFs(fs afero.Fs) { v.SetFs(fs) } |
2054 |
|
1910 func (v *Viper) SetFs(fs afero.Fs) { |
2055 func (v *Viper) SetFs(fs afero.Fs) { |
1911 v.fs = fs |
2056 v.fs = fs |
1912 } |
2057 } |
1913 |
2058 |
1914 // SetConfigName sets name for the config file. |
2059 // SetConfigName sets name for the config file. |
1915 // Does not include extension. |
2060 // Does not include extension. |
1916 func SetConfigName(in string) { v.SetConfigName(in) } |
2061 func SetConfigName(in string) { v.SetConfigName(in) } |
2062 |
|
1917 func (v *Viper) SetConfigName(in string) { |
2063 func (v *Viper) SetConfigName(in string) { |
1918 if in != "" { |
2064 if in != "" { |
1919 v.configName = in |
2065 v.configName = in |
1920 v.configFile = "" |
2066 v.configFile = "" |
1921 } |
2067 } |
1922 } |
2068 } |
1923 |
2069 |
1924 // SetConfigType sets the type of the configuration returned by the |
2070 // SetConfigType sets the type of the configuration returned by the |
1925 // remote source, e.g. "json". |
2071 // remote source, e.g. "json". |
1926 func SetConfigType(in string) { v.SetConfigType(in) } |
2072 func SetConfigType(in string) { v.SetConfigType(in) } |
2073 |
|
1927 func (v *Viper) SetConfigType(in string) { |
2074 func (v *Viper) SetConfigType(in string) { |
1928 if in != "" { |
2075 if in != "" { |
1929 v.configType = in |
2076 v.configType = in |
1930 } |
2077 } |
1931 } |
2078 } |
1932 |
2079 |
1933 // SetConfigPermissions sets the permissions for the config file. |
2080 // SetConfigPermissions sets the permissions for the config file. |
1934 func SetConfigPermissions(perm os.FileMode) { v.SetConfigPermissions(perm) } |
2081 func SetConfigPermissions(perm os.FileMode) { v.SetConfigPermissions(perm) } |
2082 |
|
1935 func (v *Viper) SetConfigPermissions(perm os.FileMode) { |
2083 func (v *Viper) SetConfigPermissions(perm os.FileMode) { |
1936 v.configPermissions = perm.Perm() |
2084 v.configPermissions = perm.Perm() |
2085 } |
|
2086 |
|
2087 // IniLoadOptions sets the load options for ini parsing. |
|
2088 func IniLoadOptions(in ini.LoadOptions) Option { |
|
2089 return optionFunc(func(v *Viper) { |
|
2090 v.iniLoadOptions = in |
|
2091 }) |
|
1937 } |
2092 } |
1938 |
2093 |
1939 func (v *Viper) getConfigType() string { |
2094 func (v *Viper) getConfigType() string { |
1940 if v.configType != "" { |
2095 if v.configType != "" { |
1941 return v.configType |
2096 return v.configType |
2000 } |
2155 } |
2001 |
2156 |
2002 // Debug prints all configuration registries for debugging |
2157 // Debug prints all configuration registries for debugging |
2003 // purposes. |
2158 // purposes. |
2004 func Debug() { v.Debug() } |
2159 func Debug() { v.Debug() } |
2160 |
|
2005 func (v *Viper) Debug() { |
2161 func (v *Viper) Debug() { |
2006 fmt.Printf("Aliases:\n%#v\n", v.aliases) |
2162 fmt.Printf("Aliases:\n%#v\n", v.aliases) |
2007 fmt.Printf("Override:\n%#v\n", v.override) |
2163 fmt.Printf("Override:\n%#v\n", v.override) |
2008 fmt.Printf("PFlags:\n%#v\n", v.pflags) |
2164 fmt.Printf("PFlags:\n%#v\n", v.pflags) |
2009 fmt.Printf("Env:\n%#v\n", v.env) |
2165 fmt.Printf("Env:\n%#v\n", v.env) |