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