viper.go raw

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