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