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