vendor/github.com/spf13/viper/viper.go
changeset 260 445e01aede7e
parent 256 6d9efbef00a9
child 262 8d3354485fc3
equal deleted inserted replaced
259:db4911b0c721 260:445e01aede7e
    20 package viper
    20 package viper
    21 
    21 
    22 import (
    22 import (
    23 	"bytes"
    23 	"bytes"
    24 	"encoding/csv"
    24 	"encoding/csv"
    25 	"encoding/json"
       
    26 	"errors"
    25 	"errors"
    27 	"fmt"
    26 	"fmt"
    28 	"io"
    27 	"io"
    29 	"log"
    28 	"log"
    30 	"os"
    29 	"os"
    34 	"strings"
    33 	"strings"
    35 	"sync"
    34 	"sync"
    36 	"time"
    35 	"time"
    37 
    36 
    38 	"github.com/fsnotify/fsnotify"
    37 	"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"
    38 	"github.com/mitchellh/mapstructure"
    43 	"github.com/pelletier/go-toml"
       
    44 	"github.com/spf13/afero"
    39 	"github.com/spf13/afero"
    45 	"github.com/spf13/cast"
    40 	"github.com/spf13/cast"
    46 	jww "github.com/spf13/jwalterweatherman"
       
    47 	"github.com/spf13/pflag"
    41 	"github.com/spf13/pflag"
    48 	"github.com/subosito/gotenv"
    42 
    49 	"gopkg.in/ini.v1"
    43 	"github.com/spf13/viper/internal/encoding"
    50 	"gopkg.in/yaml.v2"
    44 	"github.com/spf13/viper/internal/encoding/dotenv"
       
    45 	"github.com/spf13/viper/internal/encoding/hcl"
       
    46 	"github.com/spf13/viper/internal/encoding/ini"
       
    47 	"github.com/spf13/viper/internal/encoding/javaproperties"
       
    48 	"github.com/spf13/viper/internal/encoding/json"
       
    49 	"github.com/spf13/viper/internal/encoding/toml"
       
    50 	"github.com/spf13/viper/internal/encoding/yaml"
    51 )
    51 )
    52 
    52 
    53 // ConfigMarshalError happens when failing to marshal the configuration.
    53 // ConfigMarshalError happens when failing to marshal the configuration.
    54 type ConfigMarshalError struct {
    54 type ConfigMarshalError struct {
    55 	err error
    55 	err error
   213 	pflags         map[string]FlagValue
   213 	pflags         map[string]FlagValue
   214 	env            map[string][]string
   214 	env            map[string][]string
   215 	aliases        map[string]string
   215 	aliases        map[string]string
   216 	typeByDefValue bool
   216 	typeByDefValue bool
   217 
   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)
   218 	onConfigChange func(fsnotify.Event)
       
   219 
       
   220 	logger Logger
       
   221 
       
   222 	// TODO: should probably be protected with a mutex
       
   223 	encoderRegistry *encoding.EncoderRegistry
       
   224 	decoderRegistry *encoding.DecoderRegistry
   223 }
   225 }
   224 
   226 
   225 // New returns an initialized Viper instance.
   227 // New returns an initialized Viper instance.
   226 func New() *Viper {
   228 func New() *Viper {
   227 	v := new(Viper)
   229 	v := new(Viper)
   228 	v.keyDelim = "."
   230 	v.keyDelim = "."
   229 	v.configName = "config"
   231 	v.configName = "config"
   230 	v.configPermissions = os.FileMode(0644)
   232 	v.configPermissions = os.FileMode(0o644)
   231 	v.fs = afero.NewOsFs()
   233 	v.fs = afero.NewOsFs()
   232 	v.config = make(map[string]interface{})
   234 	v.config = make(map[string]interface{})
   233 	v.override = make(map[string]interface{})
   235 	v.override = make(map[string]interface{})
   234 	v.defaults = make(map[string]interface{})
   236 	v.defaults = make(map[string]interface{})
   235 	v.kvstore = make(map[string]interface{})
   237 	v.kvstore = make(map[string]interface{})
   236 	v.pflags = make(map[string]FlagValue)
   238 	v.pflags = make(map[string]FlagValue)
   237 	v.env = make(map[string][]string)
   239 	v.env = make(map[string][]string)
   238 	v.aliases = make(map[string]string)
   240 	v.aliases = make(map[string]string)
   239 	v.typeByDefValue = false
   241 	v.typeByDefValue = false
       
   242 	v.logger = jwwLogger{}
       
   243 
       
   244 	v.resetEncoding()
   240 
   245 
   241 	return v
   246 	return v
   242 }
   247 }
   243 
   248 
   244 // Option configures Viper using the functional options paradigm popularized by Rob Pike and Dave Cheney.
   249 // Option configures Viper using the functional options paradigm popularized by Rob Pike and Dave Cheney.
   282 
   287 
   283 	for _, opt := range opts {
   288 	for _, opt := range opts {
   284 		opt.apply(v)
   289 		opt.apply(v)
   285 	}
   290 	}
   286 
   291 
       
   292 	v.resetEncoding()
       
   293 
   287 	return v
   294 	return v
   288 }
   295 }
   289 
   296 
   290 // Reset is intended for testing, will reset all to default settings.
   297 // Reset is intended for testing, will reset all to default settings.
   291 // In the public interface for the viper package so applications
   298 // In the public interface for the viper package so applications
   292 // can use it in their testing as well.
   299 // can use it in their testing as well.
   293 func Reset() {
   300 func Reset() {
   294 	v = New()
   301 	v = New()
   295 	SupportedExts = []string{"json", "toml", "yaml", "yml", "properties", "props", "prop", "hcl", "dotenv", "env", "ini"}
   302 	SupportedExts = []string{"json", "toml", "yaml", "yml", "properties", "props", "prop", "hcl", "tfvars", "dotenv", "env", "ini"}
   296 	SupportedRemoteProviders = []string{"etcd", "consul", "firestore"}
   303 	SupportedRemoteProviders = []string{"etcd", "consul", "firestore"}
       
   304 }
       
   305 
       
   306 // TODO: make this lazy initialization instead
       
   307 func (v *Viper) resetEncoding() {
       
   308 	encoderRegistry := encoding.NewEncoderRegistry()
       
   309 	decoderRegistry := encoding.NewDecoderRegistry()
       
   310 
       
   311 	{
       
   312 		codec := yaml.Codec{}
       
   313 
       
   314 		encoderRegistry.RegisterEncoder("yaml", codec)
       
   315 		decoderRegistry.RegisterDecoder("yaml", codec)
       
   316 
       
   317 		encoderRegistry.RegisterEncoder("yml", codec)
       
   318 		decoderRegistry.RegisterDecoder("yml", codec)
       
   319 	}
       
   320 
       
   321 	{
       
   322 		codec := json.Codec{}
       
   323 
       
   324 		encoderRegistry.RegisterEncoder("json", codec)
       
   325 		decoderRegistry.RegisterDecoder("json", codec)
       
   326 	}
       
   327 
       
   328 	{
       
   329 		codec := toml.Codec{}
       
   330 
       
   331 		encoderRegistry.RegisterEncoder("toml", codec)
       
   332 		decoderRegistry.RegisterDecoder("toml", codec)
       
   333 	}
       
   334 
       
   335 	{
       
   336 		codec := hcl.Codec{}
       
   337 
       
   338 		encoderRegistry.RegisterEncoder("hcl", codec)
       
   339 		decoderRegistry.RegisterDecoder("hcl", codec)
       
   340 
       
   341 		encoderRegistry.RegisterEncoder("tfvars", codec)
       
   342 		decoderRegistry.RegisterDecoder("tfvars", codec)
       
   343 	}
       
   344 
       
   345 	{
       
   346 		codec := ini.Codec{
       
   347 			KeyDelimiter: v.keyDelim,
       
   348 			LoadOptions:  v.iniLoadOptions,
       
   349 		}
       
   350 
       
   351 		encoderRegistry.RegisterEncoder("ini", codec)
       
   352 		decoderRegistry.RegisterDecoder("ini", codec)
       
   353 	}
       
   354 
       
   355 	{
       
   356 		codec := &javaproperties.Codec{
       
   357 			KeyDelimiter: v.keyDelim,
       
   358 		}
       
   359 
       
   360 		encoderRegistry.RegisterEncoder("properties", codec)
       
   361 		decoderRegistry.RegisterDecoder("properties", codec)
       
   362 
       
   363 		encoderRegistry.RegisterEncoder("props", codec)
       
   364 		decoderRegistry.RegisterDecoder("props", codec)
       
   365 
       
   366 		encoderRegistry.RegisterEncoder("prop", codec)
       
   367 		decoderRegistry.RegisterDecoder("prop", codec)
       
   368 	}
       
   369 
       
   370 	{
       
   371 		codec := &dotenv.Codec{}
       
   372 
       
   373 		encoderRegistry.RegisterEncoder("dotenv", codec)
       
   374 		decoderRegistry.RegisterDecoder("dotenv", codec)
       
   375 
       
   376 		encoderRegistry.RegisterEncoder("env", codec)
       
   377 		decoderRegistry.RegisterDecoder("env", codec)
       
   378 	}
       
   379 
       
   380 	v.encoderRegistry = encoderRegistry
       
   381 	v.decoderRegistry = decoderRegistry
   297 }
   382 }
   298 
   383 
   299 type defaultRemoteProvider struct {
   384 type defaultRemoteProvider struct {
   300 	provider      string
   385 	provider      string
   301 	endpoint      string
   386 	endpoint      string
   329 	Path() string
   414 	Path() string
   330 	SecretKeyring() string
   415 	SecretKeyring() string
   331 }
   416 }
   332 
   417 
   333 // SupportedExts are universally supported extensions.
   418 // SupportedExts are universally supported extensions.
   334 var SupportedExts = []string{"json", "toml", "yaml", "yml", "properties", "props", "prop", "hcl", "dotenv", "env", "ini"}
   419 var SupportedExts = []string{"json", "toml", "yaml", "yml", "properties", "props", "prop", "hcl", "tfvars", "dotenv", "env", "ini"}
   335 
   420 
   336 // SupportedRemoteProviders are universally supported remote providers.
   421 // SupportedRemoteProviders are universally supported remote providers.
   337 var SupportedRemoteProviders = []string{"etcd", "consul", "firestore"}
   422 var SupportedRemoteProviders = []string{"etcd", "consul", "firestore"}
   338 
   423 
   339 func OnConfigChange(run func(in fsnotify.Event)) { v.OnConfigChange(run) }
   424 func OnConfigChange(run func(in fsnotify.Event)) { v.OnConfigChange(run) }
   389 						}
   474 						}
   390 						if v.onConfigChange != nil {
   475 						if v.onConfigChange != nil {
   391 							v.onConfigChange(event)
   476 							v.onConfigChange(event)
   392 						}
   477 						}
   393 					} else if filepath.Clean(event.Name) == configFile &&
   478 					} else if filepath.Clean(event.Name) == configFile &&
   394 						event.Op&fsnotify.Remove&fsnotify.Remove != 0 {
   479 						event.Op&fsnotify.Remove != 0 {
   395 						eventsWG.Done()
   480 						eventsWG.Done()
   396 						return
   481 						return
   397 					}
   482 					}
   398 
   483 
   399 				case err, ok := <-watcher.Errors:
   484 				case err, ok := <-watcher.Errors:
   475 // Can be called multiple times to define multiple search paths.
   560 // Can be called multiple times to define multiple search paths.
   476 func AddConfigPath(in string) { v.AddConfigPath(in) }
   561 func AddConfigPath(in string) { v.AddConfigPath(in) }
   477 
   562 
   478 func (v *Viper) AddConfigPath(in string) {
   563 func (v *Viper) AddConfigPath(in string) {
   479 	if in != "" {
   564 	if in != "" {
   480 		absin := absPathify(in)
   565 		absin := absPathify(v.logger, in)
   481 		jww.INFO.Println("adding", absin, "to paths to search")
   566 
       
   567 		v.logger.Info("adding path to search paths", "path", absin)
   482 		if !stringInSlice(absin, v.configPaths) {
   568 		if !stringInSlice(absin, v.configPaths) {
   483 			v.configPaths = append(v.configPaths, absin)
   569 			v.configPaths = append(v.configPaths, absin)
   484 		}
   570 		}
   485 	}
   571 	}
   486 }
   572 }
   500 func (v *Viper) AddRemoteProvider(provider, endpoint, path string) error {
   586 func (v *Viper) AddRemoteProvider(provider, endpoint, path string) error {
   501 	if !stringInSlice(provider, SupportedRemoteProviders) {
   587 	if !stringInSlice(provider, SupportedRemoteProviders) {
   502 		return UnsupportedRemoteProviderError(provider)
   588 		return UnsupportedRemoteProviderError(provider)
   503 	}
   589 	}
   504 	if provider != "" && endpoint != "" {
   590 	if provider != "" && endpoint != "" {
   505 		jww.INFO.Printf("adding %s:%s to remote provider list", provider, endpoint)
   591 		v.logger.Info("adding remote provider", "provider", provider, "endpoint", endpoint)
       
   592 
   506 		rp := &defaultRemoteProvider{
   593 		rp := &defaultRemoteProvider{
   507 			endpoint: endpoint,
   594 			endpoint: endpoint,
   508 			provider: provider,
   595 			provider: provider,
   509 			path:     path,
   596 			path:     path,
   510 		}
   597 		}
   532 func (v *Viper) AddSecureRemoteProvider(provider, endpoint, path, secretkeyring string) error {
   619 func (v *Viper) AddSecureRemoteProvider(provider, endpoint, path, secretkeyring string) error {
   533 	if !stringInSlice(provider, SupportedRemoteProviders) {
   620 	if !stringInSlice(provider, SupportedRemoteProviders) {
   534 		return UnsupportedRemoteProviderError(provider)
   621 		return UnsupportedRemoteProviderError(provider)
   535 	}
   622 	}
   536 	if provider != "" && endpoint != "" {
   623 	if provider != "" && endpoint != "" {
   537 		jww.INFO.Printf("adding %s:%s to remote provider list", provider, endpoint)
   624 		v.logger.Info("adding remote provider", "provider", provider, "endpoint", endpoint)
       
   625 
   538 		rp := &defaultRemoteProvider{
   626 		rp := &defaultRemoteProvider{
   539 			endpoint:      endpoint,
   627 			endpoint:      endpoint,
   540 			provider:      provider,
   628 			provider:      provider,
   541 			path:          path,
   629 			path:          path,
   542 			secretKeyring: secretkeyring,
   630 			secretKeyring: secretkeyring,
  1107 	}
  1195 	}
  1108 
  1196 
  1109 	return nil
  1197 	return nil
  1110 }
  1198 }
  1111 
  1199 
       
  1200 // MustBindEnv wraps BindEnv in a panic.
       
  1201 // If there is an error binding an environment variable, MustBindEnv will
       
  1202 // panic.
       
  1203 func MustBindEnv(input ...string) { v.MustBindEnv(input...) }
       
  1204 
       
  1205 func (v *Viper) MustBindEnv(input ...string) {
       
  1206 	if err := v.BindEnv(input...); err != nil {
       
  1207 		panic(fmt.Sprintf("error while binding environment variable: %v", err))
       
  1208 	}
       
  1209 }
       
  1210 
  1112 // Given a key, find the value.
  1211 // Given a key, find the value.
  1113 //
  1212 //
  1114 // Viper will check to see if an alias exists first.
  1213 // Viper will check to see if an alias exists first.
  1115 // Viper will then check in the following order:
  1214 // Viper will then check in the following order:
  1116 // flag, env, config file, key/value store.
  1215 // flag, env, config file, key/value store.
  1348 				v.override[key] = val
  1447 				v.override[key] = val
  1349 			}
  1448 			}
  1350 			v.aliases[alias] = key
  1449 			v.aliases[alias] = key
  1351 		}
  1450 		}
  1352 	} else {
  1451 	} else {
  1353 		jww.WARN.Println("Creating circular reference alias", alias, key, v.realKey(key))
  1452 		v.logger.Warn("creating circular reference alias", "alias", alias, "key", key, "real_key", v.realKey(key))
  1354 	}
  1453 	}
  1355 }
  1454 }
  1356 
  1455 
  1357 func (v *Viper) realKey(key string) string {
  1456 func (v *Viper) realKey(key string) string {
  1358 	newkey, exists := v.aliases[key]
  1457 	newkey, exists := v.aliases[key]
  1359 	if exists {
  1458 	if exists {
  1360 		jww.DEBUG.Println("Alias", key, "to", newkey)
  1459 		v.logger.Debug("key is an alias", "alias", key, "to", newkey)
       
  1460 
  1361 		return v.realKey(newkey)
  1461 		return v.realKey(newkey)
  1362 	}
  1462 	}
  1363 	return key
  1463 	return key
  1364 }
  1464 }
  1365 
  1465 
  1366 // InConfig checks to see if the given key (or an alias) is in the config file.
  1466 // InConfig checks to see if the given key (or an alias) is in the config file.
  1367 func InConfig(key string) bool { return v.InConfig(key) }
  1467 func InConfig(key string) bool { return v.InConfig(key) }
  1368 
  1468 
  1369 func (v *Viper) InConfig(key string) bool {
  1469 func (v *Viper) InConfig(key string) bool {
       
  1470 	lcaseKey := strings.ToLower(key)
       
  1471 
  1370 	// if the requested key is an alias, then return the proper key
  1472 	// if the requested key is an alias, then return the proper key
  1371 	key = v.realKey(key)
  1473 	lcaseKey = v.realKey(lcaseKey)
  1372 
  1474 	path := strings.Split(lcaseKey, v.keyDelim)
  1373 	_, exists := v.config[key]
  1475 
  1374 	return exists
  1476 	return v.searchIndexableWithPathPrefixes(v.config, path) != nil
  1375 }
  1477 }
  1376 
  1478 
  1377 // SetDefault sets the default value for this key.
  1479 // SetDefault sets the default value for this key.
  1378 // SetDefault is case-insensitive for a key.
  1480 // SetDefault is case-insensitive for a key.
  1379 // Default only used when no value is provided by the user via flag, config or ENV.
  1481 // Default only used when no value is provided by the user via flag, config or ENV.
  1414 // ReadInConfig will discover and load the configuration file from disk
  1516 // ReadInConfig will discover and load the configuration file from disk
  1415 // and key/value stores, searching in one of the defined paths.
  1517 // and key/value stores, searching in one of the defined paths.
  1416 func ReadInConfig() error { return v.ReadInConfig() }
  1518 func ReadInConfig() error { return v.ReadInConfig() }
  1417 
  1519 
  1418 func (v *Viper) ReadInConfig() error {
  1520 func (v *Viper) ReadInConfig() error {
  1419 	jww.INFO.Println("Attempting to read in config file")
  1521 	v.logger.Info("attempting to read in config file")
  1420 	filename, err := v.getConfigFile()
  1522 	filename, err := v.getConfigFile()
  1421 	if err != nil {
  1523 	if err != nil {
  1422 		return err
  1524 		return err
  1423 	}
  1525 	}
  1424 
  1526 
  1425 	if !stringInSlice(v.getConfigType(), SupportedExts) {
  1527 	if !stringInSlice(v.getConfigType(), SupportedExts) {
  1426 		return UnsupportedConfigError(v.getConfigType())
  1528 		return UnsupportedConfigError(v.getConfigType())
  1427 	}
  1529 	}
  1428 
  1530 
  1429 	jww.DEBUG.Println("Reading file: ", filename)
  1531 	v.logger.Debug("reading file", "file", filename)
  1430 	file, err := afero.ReadFile(v.fs, filename)
  1532 	file, err := afero.ReadFile(v.fs, filename)
  1431 	if err != nil {
  1533 	if err != nil {
  1432 		return err
  1534 		return err
  1433 	}
  1535 	}
  1434 
  1536 
  1445 
  1547 
  1446 // MergeInConfig merges a new configuration with an existing config.
  1548 // MergeInConfig merges a new configuration with an existing config.
  1447 func MergeInConfig() error { return v.MergeInConfig() }
  1549 func MergeInConfig() error { return v.MergeInConfig() }
  1448 
  1550 
  1449 func (v *Viper) MergeInConfig() error {
  1551 func (v *Viper) MergeInConfig() error {
  1450 	jww.INFO.Println("Attempting to merge in config file")
  1552 	v.logger.Info("attempting to merge in config file")
  1451 	filename, err := v.getConfigFile()
  1553 	filename, err := v.getConfigFile()
  1452 	if err != nil {
  1554 	if err != nil {
  1453 		return err
  1555 		return err
  1454 	}
  1556 	}
  1455 
  1557 
  1536 	}
  1638 	}
  1537 	return v.writeConfig(filename, false)
  1639 	return v.writeConfig(filename, false)
  1538 }
  1640 }
  1539 
  1641 
  1540 func (v *Viper) writeConfig(filename string, force bool) error {
  1642 func (v *Viper) writeConfig(filename string, force bool) error {
  1541 	jww.INFO.Println("Attempting to write configuration to file.")
  1643 	v.logger.Info("attempting to write configuration to file")
       
  1644 
  1542 	var configType string
  1645 	var configType string
  1543 
  1646 
  1544 	ext := filepath.Ext(filename)
  1647 	ext := filepath.Ext(filename)
  1545 	if ext != "" {
  1648 	if ext != "" && ext != filepath.Base(filename) {
  1546 		configType = ext[1:]
  1649 		configType = ext[1:]
  1547 	} else {
  1650 	} else {
  1548 		configType = v.configType
  1651 		configType = v.configType
  1549 	}
  1652 	}
  1550 	if configType == "" {
  1653 	if configType == "" {
  1582 
  1685 
  1583 func (v *Viper) unmarshalReader(in io.Reader, c map[string]interface{}) error {
  1686 func (v *Viper) unmarshalReader(in io.Reader, c map[string]interface{}) error {
  1584 	buf := new(bytes.Buffer)
  1687 	buf := new(bytes.Buffer)
  1585 	buf.ReadFrom(in)
  1688 	buf.ReadFrom(in)
  1586 
  1689 
  1587 	switch strings.ToLower(v.getConfigType()) {
  1690 	switch format := strings.ToLower(v.getConfigType()); format {
  1588 	case "yaml", "yml":
  1691 	case "yaml", "yml", "json", "toml", "hcl", "tfvars", "ini", "properties", "props", "prop", "dotenv", "env":
  1589 		if err := yaml.Unmarshal(buf.Bytes(), &c); err != nil {
  1692 		err := v.decoderRegistry.Decode(format, buf.Bytes(), c)
  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 {
  1693 		if err != nil {
  1601 			return ConfigParseError{err}
  1694 			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 		}
  1695 		}
  1658 	}
  1696 	}
  1659 
  1697 
  1660 	insensitiviseMap(c)
  1698 	insensitiviseMap(c)
  1661 	return nil
  1699 	return nil
  1663 
  1701 
  1664 // Marshal a map into Writer.
  1702 // Marshal a map into Writer.
  1665 func (v *Viper) marshalWriter(f afero.File, configType string) error {
  1703 func (v *Viper) marshalWriter(f afero.File, configType string) error {
  1666 	c := v.AllSettings()
  1704 	c := v.AllSettings()
  1667 	switch configType {
  1705 	switch configType {
  1668 	case "json":
  1706 	case "yaml", "yml", "json", "toml", "hcl", "tfvars", "ini", "prop", "props", "properties", "dotenv", "env":
  1669 		b, err := json.MarshalIndent(c, "", "  ")
  1707 		b, err := v.encoderRegistry.Encode(configType, c)
  1670 		if err != nil {
  1708 		if err != nil {
  1671 			return ConfigMarshalError{err}
  1709 			return ConfigMarshalError{err}
  1672 		}
  1710 		}
       
  1711 
  1673 		_, err = f.WriteString(string(b))
  1712 		_, err = f.WriteString(string(b))
  1674 		if err != nil {
  1713 		if err != nil {
  1675 			return ConfigMarshalError{err}
  1714 			return ConfigMarshalError{err}
  1676 		}
  1715 		}
  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 	}
  1716 	}
  1755 	return nil
  1717 	return nil
  1756 }
  1718 }
  1757 
  1719 
  1758 func keyExists(k string, m map[string]interface{}) string {
  1720 func keyExists(k string, m map[string]interface{}) string {
  1765 	}
  1727 	}
  1766 	return ""
  1728 	return ""
  1767 }
  1729 }
  1768 
  1730 
  1769 func castToMapStringInterface(
  1731 func castToMapStringInterface(
  1770 	src map[interface{}]interface{}) map[string]interface{} {
  1732 	src map[interface{}]interface{},
       
  1733 ) map[string]interface{} {
  1771 	tgt := map[string]interface{}{}
  1734 	tgt := map[string]interface{}{}
  1772 	for k, v := range src {
  1735 	for k, v := range src {
  1773 		tgt[fmt.Sprintf("%v", k)] = v
  1736 		tgt[fmt.Sprintf("%v", k)] = v
  1774 	}
  1737 	}
  1775 	return tgt
  1738 	return tgt
  1803 // insistence on parsing nested structures as `map[interface{}]interface{}`
  1766 // insistence on parsing nested structures as `map[interface{}]interface{}`
  1804 // instead of using a `string` as the key for nest structures beyond one level
  1767 // 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
  1768 // deep. Both map types are supported as there is a go-yaml fork that uses
  1806 // `map[string]interface{}` instead.
  1769 // `map[string]interface{}` instead.
  1807 func mergeMaps(
  1770 func mergeMaps(
  1808 	src, tgt map[string]interface{}, itgt map[interface{}]interface{}) {
  1771 	src, tgt map[string]interface{}, itgt map[interface{}]interface{},
       
  1772 ) {
  1809 	for sk, sv := range src {
  1773 	for sk, sv := range src {
  1810 		tk := keyExists(sk, tgt)
  1774 		tk := keyExists(sk, tgt)
  1811 		if tk == "" {
  1775 		if tk == "" {
  1812 			jww.TRACE.Printf("tk=\"\", tgt[%s]=%v", sk, sv)
  1776 			v.logger.Trace("", "tk", "\"\"", fmt.Sprintf("tgt[%s]", sk), sv)
  1813 			tgt[sk] = sv
  1777 			tgt[sk] = sv
  1814 			if itgt != nil {
  1778 			if itgt != nil {
  1815 				itgt[sk] = sv
  1779 				itgt[sk] = sv
  1816 			}
  1780 			}
  1817 			continue
  1781 			continue
  1818 		}
  1782 		}
  1819 
  1783 
  1820 		tv, ok := tgt[tk]
  1784 		tv, ok := tgt[tk]
  1821 		if !ok {
  1785 		if !ok {
  1822 			jww.TRACE.Printf("tgt[%s] != ok, tgt[%s]=%v", tk, sk, sv)
  1786 			v.logger.Trace("", fmt.Sprintf("ok[%s]", tk), false, fmt.Sprintf("tgt[%s]", sk), sv)
  1823 			tgt[sk] = sv
  1787 			tgt[sk] = sv
  1824 			if itgt != nil {
  1788 			if itgt != nil {
  1825 				itgt[sk] = sv
  1789 				itgt[sk] = sv
  1826 			}
  1790 			}
  1827 			continue
  1791 			continue
  1828 		}
  1792 		}
  1829 
  1793 
  1830 		svType := reflect.TypeOf(sv)
  1794 		svType := reflect.TypeOf(sv)
  1831 		tvType := reflect.TypeOf(tv)
  1795 		tvType := reflect.TypeOf(tv)
  1832 		if tvType != nil && svType != tvType { // Allow for the target to be nil
  1796 
  1833 			jww.ERROR.Printf(
  1797 		v.logger.Trace(
  1834 				"svType != tvType; key=%s, st=%v, tt=%v, sv=%v, tv=%v",
  1798 			"processing",
  1835 				sk, svType, tvType, sv, tv)
  1799 			"key", sk,
  1836 			continue
  1800 			"st", svType,
  1837 		}
  1801 			"tt", tvType,
  1838 
  1802 			"sv", sv,
  1839 		jww.TRACE.Printf("processing key=%s, st=%v, tt=%v, sv=%v, tv=%v",
  1803 			"tv", tv,
  1840 			sk, svType, tvType, sv, tv)
  1804 		)
  1841 
  1805 
  1842 		switch ttv := tv.(type) {
  1806 		switch ttv := tv.(type) {
  1843 		case map[interface{}]interface{}:
  1807 		case map[interface{}]interface{}:
  1844 			jww.TRACE.Printf("merging maps (must convert)")
  1808 			v.logger.Trace("merging maps (must convert)")
  1845 			tsv := sv.(map[interface{}]interface{})
  1809 			tsv, ok := sv.(map[interface{}]interface{})
       
  1810 			if !ok {
       
  1811 				v.logger.Error(
       
  1812 					"Could not cast sv to map[interface{}]interface{}",
       
  1813 					"key", sk,
       
  1814 					"st", svType,
       
  1815 					"tt", tvType,
       
  1816 					"sv", sv,
       
  1817 					"tv", tv,
       
  1818 				)
       
  1819 				continue
       
  1820 			}
       
  1821 
  1846 			ssv := castToMapStringInterface(tsv)
  1822 			ssv := castToMapStringInterface(tsv)
  1847 			stv := castToMapStringInterface(ttv)
  1823 			stv := castToMapStringInterface(ttv)
  1848 			mergeMaps(ssv, stv, ttv)
  1824 			mergeMaps(ssv, stv, ttv)
  1849 		case map[string]interface{}:
  1825 		case map[string]interface{}:
  1850 			jww.TRACE.Printf("merging maps")
  1826 			v.logger.Trace("merging maps")
  1851 			mergeMaps(sv.(map[string]interface{}), ttv, nil)
  1827 			tsv, ok := sv.(map[string]interface{})
       
  1828 			if !ok {
       
  1829 				v.logger.Error(
       
  1830 					"Could not cast sv to map[string]interface{}",
       
  1831 					"key", sk,
       
  1832 					"st", svType,
       
  1833 					"tt", tvType,
       
  1834 					"sv", sv,
       
  1835 					"tv", tv,
       
  1836 				)
       
  1837 				continue
       
  1838 			}
       
  1839 			mergeMaps(tsv, ttv, nil)
  1852 		default:
  1840 		default:
  1853 			jww.TRACE.Printf("setting value")
  1841 			v.logger.Trace("setting value")
  1854 			tgt[tk] = sv
  1842 			tgt[tk] = sv
  1855 			if itgt != nil {
  1843 			if itgt != nil {
  1856 				itgt[tk] = sv
  1844 				itgt[tk] = sv
  1857 			}
  1845 			}
  1858 		}
  1846 		}
  1883 	}
  1871 	}
  1884 
  1872 
  1885 	for _, rp := range v.remoteProviders {
  1873 	for _, rp := range v.remoteProviders {
  1886 		val, err := v.getRemoteConfig(rp)
  1874 		val, err := v.getRemoteConfig(rp)
  1887 		if err != nil {
  1875 		if err != nil {
  1888 			jww.ERROR.Printf("get remote config: %s", err)
  1876 			v.logger.Error(fmt.Errorf("get remote config: %w", err).Error())
  1889 
  1877 
  1890 			continue
  1878 			continue
  1891 		}
  1879 		}
  1892 
  1880 
  1893 		v.kvstore = val
  1881 		v.kvstore = val
  2119 		v.configFile = cf
  2107 		v.configFile = cf
  2120 	}
  2108 	}
  2121 	return v.configFile, nil
  2109 	return v.configFile, nil
  2122 }
  2110 }
  2123 
  2111 
  2124 func (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).
       
  2145 func (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
  2112 // Debug prints all configuration registries for debugging
  2158 // purposes.
  2113 // purposes.
  2159 func Debug() { v.Debug() }
  2114 func Debug() { v.Debug() }
  2160 
  2115 
  2161 func (v *Viper) Debug() {
  2116 func (v *Viper) Debug() {