summaryrefslogtreecommitdiff
path: root/vendor/github.com/spf13/viper
diff options
context:
space:
mode:
authorLibravatar Terin Stock <terinjokes@gmail.com>2025-03-09 17:47:56 +0100
committerLibravatar Terin Stock <terinjokes@gmail.com>2025-03-10 01:59:49 +0100
commit3ac1ee16f377d31a0fb80c8dae28b6239ac4229e (patch)
treef61faa581feaaeaba2542b9f2b8234a590684413 /vendor/github.com/spf13/viper
parent[chore] update URLs to forked source (diff)
downloadgotosocial-3ac1ee16f377d31a0fb80c8dae28b6239ac4229e.tar.xz
[chore] remove vendor
Diffstat (limited to 'vendor/github.com/spf13/viper')
-rw-r--r--vendor/github.com/spf13/viper/.editorconfig18
-rw-r--r--vendor/github.com/spf13/viper/.gitignore8
-rw-r--r--vendor/github.com/spf13/viper/.golangci.yaml108
-rw-r--r--vendor/github.com/spf13/viper/.yamlignore2
-rw-r--r--vendor/github.com/spf13/viper/.yamllint.yaml6
-rw-r--r--vendor/github.com/spf13/viper/LICENSE21
-rw-r--r--vendor/github.com/spf13/viper/Makefile87
-rw-r--r--vendor/github.com/spf13/viper/README.md928
-rw-r--r--vendor/github.com/spf13/viper/TROUBLESHOOTING.md32
-rw-r--r--vendor/github.com/spf13/viper/file.go56
-rw-r--r--vendor/github.com/spf13/viper/file_finder.go38
-rw-r--r--vendor/github.com/spf13/viper/flags.go57
-rw-r--r--vendor/github.com/spf13/viper/flake.lock273
-rw-r--r--vendor/github.com/spf13/viper/flake.nix57
-rw-r--r--vendor/github.com/spf13/viper/internal/encoding/decoder.go61
-rw-r--r--vendor/github.com/spf13/viper/internal/encoding/dotenv/codec.go61
-rw-r--r--vendor/github.com/spf13/viper/internal/encoding/dotenv/map_utils.go41
-rw-r--r--vendor/github.com/spf13/viper/internal/encoding/encoder.go60
-rw-r--r--vendor/github.com/spf13/viper/internal/encoding/error.go7
-rw-r--r--vendor/github.com/spf13/viper/internal/encoding/hcl/codec.go40
-rw-r--r--vendor/github.com/spf13/viper/internal/encoding/ini/codec.go99
-rw-r--r--vendor/github.com/spf13/viper/internal/encoding/ini/map_utils.go74
-rw-r--r--vendor/github.com/spf13/viper/internal/encoding/javaproperties/codec.go86
-rw-r--r--vendor/github.com/spf13/viper/internal/encoding/javaproperties/map_utils.go74
-rw-r--r--vendor/github.com/spf13/viper/internal/encoding/json/codec.go17
-rw-r--r--vendor/github.com/spf13/viper/internal/encoding/toml/codec.go16
-rw-r--r--vendor/github.com/spf13/viper/internal/encoding/yaml/codec.go14
-rw-r--r--vendor/github.com/spf13/viper/internal/features/bind_struct.go5
-rw-r--r--vendor/github.com/spf13/viper/internal/features/bind_struct_default.go5
-rw-r--r--vendor/github.com/spf13/viper/logger.go68
-rw-r--r--vendor/github.com/spf13/viper/util.go223
-rw-r--r--vendor/github.com/spf13/viper/viper.go2252
32 files changed, 0 insertions, 4894 deletions
diff --git a/vendor/github.com/spf13/viper/.editorconfig b/vendor/github.com/spf13/viper/.editorconfig
deleted file mode 100644
index 1f664d13a..000000000
--- a/vendor/github.com/spf13/viper/.editorconfig
+++ /dev/null
@@ -1,18 +0,0 @@
-root = true
-
-[*]
-charset = utf-8
-end_of_line = lf
-indent_size = 4
-indent_style = space
-insert_final_newline = true
-trim_trailing_whitespace = true
-
-[*.go]
-indent_style = tab
-
-[{Makefile,*.mk}]
-indent_style = tab
-
-[*.nix]
-indent_size = 2
diff --git a/vendor/github.com/spf13/viper/.gitignore b/vendor/github.com/spf13/viper/.gitignore
deleted file mode 100644
index f1bbd4280..000000000
--- a/vendor/github.com/spf13/viper/.gitignore
+++ /dev/null
@@ -1,8 +0,0 @@
-/.devenv/
-/.direnv/
-/.idea/
-/.pre-commit-config.yaml
-/bin/
-/build/
-/var/
-/vendor/
diff --git a/vendor/github.com/spf13/viper/.golangci.yaml b/vendor/github.com/spf13/viper/.golangci.yaml
deleted file mode 100644
index 1faeae42c..000000000
--- a/vendor/github.com/spf13/viper/.golangci.yaml
+++ /dev/null
@@ -1,108 +0,0 @@
-run:
- timeout: 5m
-
-linters-settings:
- gci:
- sections:
- - standard
- - default
- - prefix(github.com/spf13/viper)
- gocritic:
- # Enable multiple checks by tags. See "Tags" section in https://github.com/go-critic/go-critic#usage.
- enabled-tags:
- - diagnostic
- - experimental
- - opinionated
- - style
- disabled-checks:
- - importShadow
- - unnamedResult
- golint:
- min-confidence: 0
- goimports:
- local-prefixes: github.com/spf13/viper
-
-linters:
- disable-all: true
- enable:
- - bodyclose
- - dogsled
- - dupl
- - durationcheck
- - exhaustive
- - exportloopref
- - gci
- - gocritic
- - godot
- - gofmt
- - gofumpt
- - goimports
- - gomoddirectives
- - goprintffuncname
- - govet
- - importas
- - ineffassign
- - makezero
- - misspell
- - nakedret
- - nilerr
- - noctx
- - nolintlint
- - prealloc
- - predeclared
- - revive
- - rowserrcheck
- - sqlclosecheck
- - staticcheck
- - stylecheck
- - tparallel
- - typecheck
- - unconvert
- - unparam
- - unused
- - wastedassign
- - whitespace
-
- # fixme
- # - cyclop
- # - errcheck
- # - errorlint
- # - exhaustivestruct
- # - forbidigo
- # - forcetypeassert
- # - gochecknoglobals
- # - gochecknoinits
- # - gocognit
- # - goconst
- # - gocyclo
- # - gosec
- # - gosimple
- # - ifshort
- # - lll
- # - nlreturn
- # - paralleltest
- # - scopelint
- # - thelper
- # - wrapcheck
-
- # unused
- # - depguard
- # - goheader
- # - gomodguard
-
- # deprecated
- # - deadcode
- # - structcheck
- # - varcheck
-
- # don't enable:
- # - asciicheck
- # - funlen
- # - godox
- # - goerr113
- # - gomnd
- # - interfacer
- # - maligned
- # - nestif
- # - testpackage
- # - wsl
diff --git a/vendor/github.com/spf13/viper/.yamlignore b/vendor/github.com/spf13/viper/.yamlignore
deleted file mode 100644
index c04c4dead..000000000
--- a/vendor/github.com/spf13/viper/.yamlignore
+++ /dev/null
@@ -1,2 +0,0 @@
-# TODO: FIXME
-/.github/
diff --git a/vendor/github.com/spf13/viper/.yamllint.yaml b/vendor/github.com/spf13/viper/.yamllint.yaml
deleted file mode 100644
index bac19ce18..000000000
--- a/vendor/github.com/spf13/viper/.yamllint.yaml
+++ /dev/null
@@ -1,6 +0,0 @@
-ignore-from-file: [.gitignore, .yamlignore]
-
-extends: default
-
-rules:
- line-length: disable
diff --git a/vendor/github.com/spf13/viper/LICENSE b/vendor/github.com/spf13/viper/LICENSE
deleted file mode 100644
index 4527efb9c..000000000
--- a/vendor/github.com/spf13/viper/LICENSE
+++ /dev/null
@@ -1,21 +0,0 @@
-The MIT License (MIT)
-
-Copyright (c) 2014 Steve Francia
-
-Permission is hereby granted, free of charge, to any person obtaining a copy
-of this software and associated documentation files (the "Software"), to deal
-in the Software without restriction, including without limitation the rights
-to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-copies of the Software, and to permit persons to whom the Software is
-furnished to do so, subject to the following conditions:
-
-The above copyright notice and this permission notice shall be included in all
-copies or substantial portions of the Software.
-
-THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
-SOFTWARE. \ No newline at end of file
diff --git a/vendor/github.com/spf13/viper/Makefile b/vendor/github.com/spf13/viper/Makefile
deleted file mode 100644
index a77b9c81c..000000000
--- a/vendor/github.com/spf13/viper/Makefile
+++ /dev/null
@@ -1,87 +0,0 @@
-# A Self-Documenting Makefile: http://marmelab.com/blog/2016/02/29/auto-documented-makefile.html
-
-OS = $(shell uname | tr A-Z a-z)
-export PATH := $(abspath bin/):${PATH}
-
-# Build variables
-BUILD_DIR ?= build
-export CGO_ENABLED ?= 0
-export GOOS = $(shell go env GOOS)
-ifeq (${VERBOSE}, 1)
-ifeq ($(filter -v,${GOARGS}),)
- GOARGS += -v
-endif
-TEST_FORMAT = short-verbose
-endif
-
-# Dependency versions
-GOTESTSUM_VERSION = 1.9.0
-GOLANGCI_VERSION = 1.53.3
-
-# Add the ability to override some variables
-# Use with care
--include override.mk
-
-.PHONY: clear
-clear: ## Clear the working area and the project
- rm -rf bin/
-
-.PHONY: check
-check: test lint ## Run tests and linters
-
-
-TEST_PKGS ?= ./...
-.PHONY: test
-test: TEST_FORMAT ?= short
-test: SHELL = /bin/bash
-test: export CGO_ENABLED=1
-test: bin/gotestsum ## Run tests
- @mkdir -p ${BUILD_DIR}
- bin/gotestsum --no-summary=skipped --junitfile ${BUILD_DIR}/coverage.xml --format ${TEST_FORMAT} -- -race -coverprofile=${BUILD_DIR}/coverage.txt -covermode=atomic $(filter-out -v,${GOARGS}) $(if ${TEST_PKGS},${TEST_PKGS},./...)
-
-.PHONY: lint
-lint: lint-go lint-yaml
-lint: ## Run linters
-
-.PHONY: lint-go
-lint-go:
- golangci-lint run $(if ${CI},--out-format github-actions,)
-
-.PHONY: lint-yaml
-lint-yaml:
- yamllint $(if ${CI},-f github,) --no-warnings .
-
-.PHONY: fmt
-fmt: ## Format code
- golangci-lint run --fix
-
-deps: bin/golangci-lint bin/gotestsum yamllint
-deps: ## Install dependencies
-
-bin/gotestsum:
- @mkdir -p bin
- curl -L https://github.com/gotestyourself/gotestsum/releases/download/v${GOTESTSUM_VERSION}/gotestsum_${GOTESTSUM_VERSION}_${OS}_amd64.tar.gz | tar -zOxf - gotestsum > ./bin/gotestsum && chmod +x ./bin/gotestsum
-
-bin/golangci-lint:
- @mkdir -p bin
- curl -sSfL https://raw.githubusercontent.com/golangci/golangci-lint/master/install.sh | bash -s -- v${GOLANGCI_VERSION}
-
-.PHONY: yamllint
-yamllint:
- pip3 install --user yamllint
-
-# Add custom targets here
--include custom.mk
-
-.PHONY: list
-list: ## List all make targets
- @${MAKE} -pRrn : -f $(MAKEFILE_LIST) 2>/dev/null | awk -v RS= -F: '/^# File/,/^# Finished Make data base/ {if ($$1 !~ "^[#.]") {print $$1}}' | egrep -v -e '^[^[:alnum:]]' -e '^$@$$' | sort
-
-.PHONY: help
-.DEFAULT_GOAL := help
-help:
- @grep -h -E '^[a-zA-Z_-]+:.*?## .*$$' $(MAKEFILE_LIST) | awk 'BEGIN {FS = ":.*?## "}; {printf "\033[36m%-30s\033[0m %s\n", $$1, $$2}'
-
-# Variable outputting/exporting rules
-var-%: ; @echo $($*)
-varexport-%: ; @echo $*=$($*)
diff --git a/vendor/github.com/spf13/viper/README.md b/vendor/github.com/spf13/viper/README.md
deleted file mode 100644
index 3fc7d84f1..000000000
--- a/vendor/github.com/spf13/viper/README.md
+++ /dev/null
@@ -1,928 +0,0 @@
-> ## Viper v2 feedback
-> Viper is heading towards v2 and we would love to hear what _**you**_ would like to see in it. Share your thoughts here: https://forms.gle/R6faU74qPRPAzchZ9
->
-> **Thank you!**
-
-![Viper](.github/logo.png?raw=true)
-
-[![Mentioned in Awesome Go](https://awesome.re/mentioned-badge-flat.svg)](https://github.com/avelino/awesome-go#configuration)
-[![run on repl.it](https://repl.it/badge/github/sagikazarmark/Viper-example)](https://repl.it/@sagikazarmark/Viper-example#main.go)
-
-[![GitHub Workflow Status](https://img.shields.io/github/actions/workflow/status/spf13/viper/ci.yaml?branch=master&style=flat-square)](https://github.com/spf13/viper/actions?query=workflow%3ACI)
-[![Join the chat at https://gitter.im/spf13/viper](https://badges.gitter.im/Join%20Chat.svg)](https://gitter.im/spf13/viper?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge)
-[![Go Report Card](https://goreportcard.com/badge/github.com/spf13/viper?style=flat-square)](https://goreportcard.com/report/github.com/spf13/viper)
-![Go Version](https://img.shields.io/badge/go%20version-%3E=1.20-61CFDD.svg?style=flat-square)
-[![PkgGoDev](https://pkg.go.dev/badge/mod/github.com/spf13/viper)](https://pkg.go.dev/mod/github.com/spf13/viper)
-
-**Go configuration with fangs!**
-
-Many Go projects are built using Viper including:
-
-* [Hugo](http://gohugo.io)
-* [EMC RexRay](http://rexray.readthedocs.org/en/stable/)
-* [Imgur’s Incus](https://github.com/Imgur/incus)
-* [Nanobox](https://github.com/nanobox-io/nanobox)/[Nanopack](https://github.com/nanopack)
-* [Docker Notary](https://github.com/docker/Notary)
-* [BloomApi](https://www.bloomapi.com/)
-* [doctl](https://github.com/digitalocean/doctl)
-* [Clairctl](https://github.com/jgsqware/clairctl)
-* [Mercure](https://mercure.rocks)
-* [Meshery](https://github.com/meshery/meshery)
-* [Bearer](https://github.com/bearer/bearer)
-* [Coder](https://github.com/coder/coder)
-* [Vitess](https://vitess.io/)
-
-
-## Install
-
-```shell
-go get github.com/spf13/viper
-```
-
-**Note:** Viper uses [Go Modules](https://go.dev/wiki/Modules) to manage dependencies.
-
-
-## What is Viper?
-
-Viper is a complete configuration solution for Go applications including [12-Factor apps](https://12factor.net/#the_twelve_factors).
-It is designed to work within an application, and can handle all types of configuration needs
-and formats. It supports:
-
-* setting defaults
-* reading from JSON, TOML, YAML, HCL, envfile and Java properties config files
-* live watching and re-reading of config files (optional)
-* reading from environment variables
-* reading from remote config systems (etcd or Consul), and watching changes
-* reading from command line flags
-* reading from buffer
-* setting explicit values
-
-Viper can be thought of as a registry for all of your applications configuration needs.
-
-
-## Why Viper?
-
-When building a modern application, you don’t want to worry about
-configuration file formats; you want to focus on building awesome software.
-Viper is here to help with that.
-
-Viper does the following for you:
-
-1. Find, load, and unmarshal a configuration file in JSON, TOML, YAML, HCL, INI, envfile or Java properties formats.
-2. Provide a mechanism to set default values for your different configuration options.
-3. Provide a mechanism to set override values for options specified through command line flags.
-4. Provide an alias system to easily rename parameters without breaking existing code.
-5. Make it easy to tell the difference between when a user has provided a command line or config file which is the same as the default.
-
-Viper uses the following precedence order. Each item takes precedence over the item below it:
-
- * explicit call to `Set`
- * flag
- * env
- * config
- * key/value store
- * default
-
-**Important:** Viper configuration keys are case insensitive.
-There are ongoing discussions about making that optional.
-
-
-## Putting Values into Viper
-
-### Establishing Defaults
-
-A good configuration system will support default values. A default value is not
-required for a key, but it’s useful in the event that a key hasn't been set via
-config file, environment variable, remote configuration or flag.
-
-Examples:
-
-```go
-viper.SetDefault("ContentDir", "content")
-viper.SetDefault("LayoutDir", "layouts")
-viper.SetDefault("Taxonomies", map[string]string{"tag": "tags", "category": "categories"})
-```
-
-### Reading Config Files
-
-Viper requires minimal configuration so it knows where to look for config files.
-Viper supports JSON, TOML, YAML, HCL, INI, envfile and Java Properties files. Viper can search multiple paths, but
-currently a single Viper instance only supports a single configuration file.
-Viper does not default to any configuration search paths leaving defaults decision
-to an application.
-
-Here is an example of how to use Viper to search for and read a configuration file.
-None of the specific paths are required, but at least one path should be provided
-where a configuration file is expected.
-
-```go
-viper.SetConfigName("config") // name of config file (without extension)
-viper.SetConfigType("yaml") // REQUIRED if the config file does not have the extension in the name
-viper.AddConfigPath("/etc/appname/") // path to look for the config file in
-viper.AddConfigPath("$HOME/.appname") // call multiple times to add many search paths
-viper.AddConfigPath(".") // optionally look for config in the working directory
-err := viper.ReadInConfig() // Find and read the config file
-if err != nil { // Handle errors reading the config file
- panic(fmt.Errorf("fatal error config file: %w", err))
-}
-```
-
-You can handle the specific case where no config file is found like this:
-
-```go
-if err := viper.ReadInConfig(); err != nil {
- if _, ok := err.(viper.ConfigFileNotFoundError); ok {
- // Config file not found; ignore error if desired
- } else {
- // Config file was found but another error was produced
- }
-}
-
-// Config file found and successfully parsed
-```
-
-*NOTE [since 1.6]:* You can also have a file without an extension and specify the format programmatically. For those configuration files that lie in the home of the user without any extension like `.bashrc`
-
-### Writing Config Files
-
-Reading from config files is useful, but at times you want to store all modifications made at run time.
-For that, a bunch of commands are available, each with its own purpose:
-
-* WriteConfig - writes the current viper configuration to the predefined path, if exists. Errors if no predefined path. Will overwrite the current config file, if it exists.
-* SafeWriteConfig - writes the current viper configuration to the predefined path. Errors if no predefined path. Will not overwrite the current config file, if it exists.
-* WriteConfigAs - writes the current viper configuration to the given filepath. Will overwrite the given file, if it exists.
-* SafeWriteConfigAs - writes the current viper configuration to the given filepath. Will not overwrite the given file, if it exists.
-
-As a rule of the thumb, everything marked with safe won't overwrite any file, but just create if not existent, whilst the default behavior is to create or truncate.
-
-A small examples section:
-
-```go
-viper.WriteConfig() // writes current config to predefined path set by 'viper.AddConfigPath()' and 'viper.SetConfigName'
-viper.SafeWriteConfig()
-viper.WriteConfigAs("/path/to/my/.config")
-viper.SafeWriteConfigAs("/path/to/my/.config") // will error since it has already been written
-viper.SafeWriteConfigAs("/path/to/my/.other_config")
-```
-
-### Watching and re-reading config files
-
-Viper supports the ability to have your application live read a config file while running.
-
-Gone are the days of needing to restart a server to have a config take effect,
-viper powered applications can read an update to a config file while running and
-not miss a beat.
-
-Simply tell the viper instance to watchConfig.
-Optionally you can provide a function for Viper to run each time a change occurs.
-
-**Make sure you add all of the configPaths prior to calling `WatchConfig()`**
-
-```go
-viper.OnConfigChange(func(e fsnotify.Event) {
- fmt.Println("Config file changed:", e.Name)
-})
-viper.WatchConfig()
-```
-
-### Reading Config from io.Reader
-
-Viper predefines many configuration sources such as files, environment
-variables, flags, and remote K/V store, but you are not bound to them. You can
-also implement your own required configuration source and feed it to viper.
-
-```go
-viper.SetConfigType("yaml") // or viper.SetConfigType("YAML")
-
-// any approach to require this configuration into your program.
-var yamlExample = []byte(`
-Hacker: true
-name: steve
-hobbies:
-- skateboarding
-- snowboarding
-- go
-clothing:
- jacket: leather
- trousers: denim
-age: 35
-eyes : brown
-beard: true
-`)
-
-viper.ReadConfig(bytes.NewBuffer(yamlExample))
-
-viper.Get("name") // this would be "steve"
-```
-
-### Setting Overrides
-
-These could be from a command line flag, or from your own application logic.
-
-```go
-viper.Set("Verbose", true)
-viper.Set("LogFile", LogFile)
-viper.Set("host.port", 5899) // set subset
-```
-
-### Registering and Using Aliases
-
-Aliases permit a single value to be referenced by multiple keys
-
-```go
-viper.RegisterAlias("loud", "Verbose")
-
-viper.Set("verbose", true) // same result as next line
-viper.Set("loud", true) // same result as prior line
-
-viper.GetBool("loud") // true
-viper.GetBool("verbose") // true
-```
-
-### Working with Environment Variables
-
-Viper has full support for environment variables. This enables 12 factor
-applications out of the box. There are five methods that exist to aid working
-with ENV:
-
- * `AutomaticEnv()`
- * `BindEnv(string...) : error`
- * `SetEnvPrefix(string)`
- * `SetEnvKeyReplacer(string...) *strings.Replacer`
- * `AllowEmptyEnv(bool)`
-
-_When working with ENV variables, it’s important to recognize that Viper
-treats ENV variables as case sensitive._
-
-Viper provides a mechanism to try to ensure that ENV variables are unique. By
-using `SetEnvPrefix`, you can tell Viper to use a prefix while reading from
-the environment variables. Both `BindEnv` and `AutomaticEnv` will use this
-prefix.
-
-`BindEnv` takes one or more parameters. The first parameter is the key name, the
-rest are the name of the environment variables to bind to this key. If more than
-one are provided, they will take precedence in the specified order. The name of
-the environment variable is case sensitive. If the ENV variable name is not provided, then
-Viper will automatically assume that the ENV variable matches the following format: prefix + "_" + the key name in ALL CAPS. When you explicitly provide the ENV variable name (the second parameter),
-it **does not** automatically add the prefix. For example if the second parameter is "id",
-Viper will look for the ENV variable "ID".
-
-One important thing to recognize when working with ENV variables is that the
-value will be read each time it is accessed. Viper does not fix the value when
-the `BindEnv` is called.
-
-`AutomaticEnv` is a powerful helper especially when combined with
-`SetEnvPrefix`. When called, Viper will check for an environment variable any
-time a `viper.Get` request is made. It will apply the following rules. It will
-check for an environment variable with a name matching the key uppercased and
-prefixed with the `EnvPrefix` if set.
-
-`SetEnvKeyReplacer` allows you to use a `strings.Replacer` object to rewrite Env
-keys to an extent. This is useful if you want to use `-` or something in your
-`Get()` calls, but want your environmental variables to use `_` delimiters. An
-example of using it can be found in `viper_test.go`.
-
-Alternatively, you can use `EnvKeyReplacer` with `NewWithOptions` factory function.
-Unlike `SetEnvKeyReplacer`, it accepts a `StringReplacer` interface allowing you to write custom string replacing logic.
-
-By default empty environment variables are considered unset and will fall back to
-the next configuration source. To treat empty environment variables as set, use
-the `AllowEmptyEnv` method.
-
-#### Env example
-
-```go
-SetEnvPrefix("spf") // will be uppercased automatically
-BindEnv("id")
-
-os.Setenv("SPF_ID", "13") // typically done outside of the app
-
-id := Get("id") // 13
-```
-
-### Working with Flags
-
-Viper has the ability to bind to flags. Specifically, Viper supports `Pflags`
-as used in the [Cobra](https://github.com/spf13/cobra) library.
-
-Like `BindEnv`, the value is not set when the binding method is called, but when
-it is accessed. This means you can bind as early as you want, even in an
-`init()` function.
-
-For individual flags, the `BindPFlag()` method provides this functionality.
-
-Example:
-
-```go
-serverCmd.Flags().Int("port", 1138, "Port to run Application server on")
-viper.BindPFlag("port", serverCmd.Flags().Lookup("port"))
-```
-
-You can also bind an existing set of pflags (pflag.FlagSet):
-
-Example:
-
-```go
-pflag.Int("flagname", 1234, "help message for flagname")
-
-pflag.Parse()
-viper.BindPFlags(pflag.CommandLine)
-
-i := viper.GetInt("flagname") // retrieve values from viper instead of pflag
-```
-
-The use of [pflag](https://github.com/spf13/pflag/) in Viper does not preclude
-the use of other packages that use the [flag](https://golang.org/pkg/flag/)
-package from the standard library. The pflag package can handle the flags
-defined for the flag package by importing these flags. This is accomplished
-by a calling a convenience function provided by the pflag package called
-AddGoFlagSet().
-
-Example:
-
-```go
-package main
-
-import (
- "flag"
- "github.com/spf13/pflag"
-)
-
-func main() {
-
- // using standard library "flag" package
- flag.Int("flagname", 1234, "help message for flagname")
-
- pflag.CommandLine.AddGoFlagSet(flag.CommandLine)
- pflag.Parse()
- viper.BindPFlags(pflag.CommandLine)
-
- i := viper.GetInt("flagname") // retrieve value from viper
-
- // ...
-}
-```
-
-#### Flag interfaces
-
-Viper provides two Go interfaces to bind other flag systems if you don’t use `Pflags`.
-
-`FlagValue` represents a single flag. This is a very simple example on how to implement this interface:
-
-```go
-type myFlag struct {}
-func (f myFlag) HasChanged() bool { return false }
-func (f myFlag) Name() string { return "my-flag-name" }
-func (f myFlag) ValueString() string { return "my-flag-value" }
-func (f myFlag) ValueType() string { return "string" }
-```
-
-Once your flag implements this interface, you can simply tell Viper to bind it:
-
-```go
-viper.BindFlagValue("my-flag-name", myFlag{})
-```
-
-`FlagValueSet` represents a group of flags. This is a very simple example on how to implement this interface:
-
-```go
-type myFlagSet struct {
- flags []myFlag
-}
-
-func (f myFlagSet) VisitAll(fn func(FlagValue)) {
- for _, flag := range flags {
- fn(flag)
- }
-}
-```
-
-Once your flag set implements this interface, you can simply tell Viper to bind it:
-
-```go
-fSet := myFlagSet{
- flags: []myFlag{myFlag{}, myFlag{}},
-}
-viper.BindFlagValues("my-flags", fSet)
-```
-
-### Remote Key/Value Store Support
-
-To enable remote support in Viper, do a blank import of the `viper/remote`
-package:
-
-`import _ "github.com/spf13/viper/remote"`
-
-Viper will read a config string (as JSON, TOML, YAML, HCL or envfile) retrieved from a path
-in a Key/Value store such as etcd or Consul. These values take precedence over
-default values, but are overridden by configuration values retrieved from disk,
-flags, or environment variables.
-
-Viper supports multiple hosts. To use, pass a list of endpoints separated by `;`. For example `http://127.0.0.1:4001;http://127.0.0.1:4002`.
-
-Viper uses [crypt](https://github.com/sagikazarmark/crypt) to retrieve
-configuration from the K/V store, which means that you can store your
-configuration values encrypted and have them automatically decrypted if you have
-the correct gpg keyring. Encryption is optional.
-
-You can use remote configuration in conjunction with local configuration, or
-independently of it.
-
-`crypt` has a command-line helper that you can use to put configurations in your
-K/V store. `crypt` defaults to etcd on http://127.0.0.1:4001.
-
-```bash
-$ go get github.com/sagikazarmark/crypt/bin/crypt
-$ crypt set -plaintext /config/hugo.json /Users/hugo/settings/config.json
-```
-
-Confirm that your value was set:
-
-```bash
-$ crypt get -plaintext /config/hugo.json
-```
-
-See the `crypt` documentation for examples of how to set encrypted values, or
-how to use Consul.
-
-### Remote Key/Value Store Example - Unencrypted
-
-#### etcd
-```go
-viper.AddRemoteProvider("etcd", "http://127.0.0.1:4001","/config/hugo.json")
-viper.SetConfigType("json") // because there is no file extension in a stream of bytes, supported extensions are "json", "toml", "yaml", "yml", "properties", "props", "prop", "env", "dotenv"
-err := viper.ReadRemoteConfig()
-```
-
-#### etcd3
-```go
-viper.AddRemoteProvider("etcd3", "http://127.0.0.1:4001","/config/hugo.json")
-viper.SetConfigType("json") // because there is no file extension in a stream of bytes, supported extensions are "json", "toml", "yaml", "yml", "properties", "props", "prop", "env", "dotenv"
-err := viper.ReadRemoteConfig()
-```
-
-#### Consul
-You need to set a key to Consul key/value storage with JSON value containing your desired config.
-For example, create a Consul key/value store key `MY_CONSUL_KEY` with value:
-
-```json
-{
- "port": 8080,
- "hostname": "myhostname.com"
-}
-```
-
-```go
-viper.AddRemoteProvider("consul", "localhost:8500", "MY_CONSUL_KEY")
-viper.SetConfigType("json") // Need to explicitly set this to json
-err := viper.ReadRemoteConfig()
-
-fmt.Println(viper.Get("port")) // 8080
-fmt.Println(viper.Get("hostname")) // myhostname.com
-```
-
-#### Firestore
-
-```go
-viper.AddRemoteProvider("firestore", "google-cloud-project-id", "collection/document")
-viper.SetConfigType("json") // Config's format: "json", "toml", "yaml", "yml"
-err := viper.ReadRemoteConfig()
-```
-
-Of course, you're allowed to use `SecureRemoteProvider` also
-
-
-#### NATS
-
-```go
-viper.AddRemoteProvider("nats", "nats://127.0.0.1:4222", "myapp.config")
-viper.SetConfigType("json")
-err := viper.ReadRemoteConfig()
-```
-
-### Remote Key/Value Store Example - Encrypted
-
-```go
-viper.AddSecureRemoteProvider("etcd","http://127.0.0.1:4001","/config/hugo.json","/etc/secrets/mykeyring.gpg")
-viper.SetConfigType("json") // because there is no file extension in a stream of bytes, supported extensions are "json", "toml", "yaml", "yml", "properties", "props", "prop", "env", "dotenv"
-err := viper.ReadRemoteConfig()
-```
-
-### Watching Changes in etcd - Unencrypted
-
-```go
-// alternatively, you can create a new viper instance.
-var runtime_viper = viper.New()
-
-runtime_viper.AddRemoteProvider("etcd", "http://127.0.0.1:4001", "/config/hugo.yml")
-runtime_viper.SetConfigType("yaml") // because there is no file extension in a stream of bytes, supported extensions are "json", "toml", "yaml", "yml", "properties", "props", "prop", "env", "dotenv"
-
-// read from remote config the first time.
-err := runtime_viper.ReadRemoteConfig()
-
-// unmarshal config
-runtime_viper.Unmarshal(&runtime_conf)
-
-// open a goroutine to watch remote changes forever
-go func(){
- for {
- time.Sleep(time.Second * 5) // delay after each request
-
- // currently, only tested with etcd support
- err := runtime_viper.WatchRemoteConfig()
- if err != nil {
- log.Errorf("unable to read remote config: %v", err)
- continue
- }
-
- // unmarshal new config into our runtime config struct. you can also use channel
- // to implement a signal to notify the system of the changes
- runtime_viper.Unmarshal(&runtime_conf)
- }
-}()
-```
-
-## Getting Values From Viper
-
-In Viper, there are a few ways to get a value depending on the value’s type.
-The following functions and methods exist:
-
- * `Get(key string) : any`
- * `GetBool(key string) : bool`
- * `GetFloat64(key string) : float64`
- * `GetInt(key string) : int`
- * `GetIntSlice(key string) : []int`
- * `GetString(key string) : string`
- * `GetStringMap(key string) : map[string]any`
- * `GetStringMapString(key string) : map[string]string`
- * `GetStringSlice(key string) : []string`
- * `GetTime(key string) : time.Time`
- * `GetDuration(key string) : time.Duration`
- * `IsSet(key string) : bool`
- * `AllSettings() : map[string]any`
-
-One important thing to recognize is that each Get function will return a zero
-value if it’s not found. To check if a given key exists, the `IsSet()` method
-has been provided.
-
-The zero value will also be returned if the value is set, but fails to parse
-as the requested type.
-
-Example:
-```go
-viper.GetString("logfile") // case-insensitive Setting & Getting
-if viper.GetBool("verbose") {
- fmt.Println("verbose enabled")
-}
-```
-### Accessing nested keys
-
-The accessor methods also accept formatted paths to deeply nested keys. For
-example, if the following JSON file is loaded:
-
-```json
-{
- "host": {
- "address": "localhost",
- "port": 5799
- },
- "datastore": {
- "metric": {
- "host": "127.0.0.1",
- "port": 3099
- },
- "warehouse": {
- "host": "198.0.0.1",
- "port": 2112
- }
- }
-}
-
-```
-
-Viper can access a nested field by passing a `.` delimited path of keys:
-
-```go
-GetString("datastore.metric.host") // (returns "127.0.0.1")
-```
-
-This obeys the precedence rules established above; the search for the path
-will cascade through the remaining configuration registries until found.
-
-For example, given this configuration file, both `datastore.metric.host` and
-`datastore.metric.port` are already defined (and may be overridden). If in addition
-`datastore.metric.protocol` was defined in the defaults, Viper would also find it.
-
-However, if `datastore.metric` was overridden (by a flag, an environment variable,
-the `Set()` method, …) with an immediate value, then all sub-keys of
-`datastore.metric` become undefined, they are “shadowed” by the higher-priority
-configuration level.
-
-Viper can access array indices by using numbers in the path. For example:
-
-```jsonc
-{
- "host": {
- "address": "localhost",
- "ports": [
- 5799,
- 6029
- ]
- },
- "datastore": {
- "metric": {
- "host": "127.0.0.1",
- "port": 3099
- },
- "warehouse": {
- "host": "198.0.0.1",
- "port": 2112
- }
- }
-}
-
-GetInt("host.ports.1") // returns 6029
-
-```
-
-Lastly, if there exists a key that matches the delimited key path, its value
-will be returned instead. E.g.
-
-```jsonc
-{
- "datastore.metric.host": "0.0.0.0",
- "host": {
- "address": "localhost",
- "port": 5799
- },
- "datastore": {
- "metric": {
- "host": "127.0.0.1",
- "port": 3099
- },
- "warehouse": {
- "host": "198.0.0.1",
- "port": 2112
- }
- }
-}
-
-GetString("datastore.metric.host") // returns "0.0.0.0"
-```
-
-### Extracting a sub-tree
-
-When developing reusable modules, it's often useful to extract a subset of the configuration
-and pass it to a module. This way the module can be instantiated more than once, with different configurations.
-
-For example, an application might use multiple different cache stores for different purposes:
-
-```yaml
-cache:
- cache1:
- max-items: 100
- item-size: 64
- cache2:
- max-items: 200
- item-size: 80
-```
-
-We could pass the cache name to a module (eg. `NewCache("cache1")`),
-but it would require weird concatenation for accessing config keys and would be less separated from the global config.
-
-So instead of doing that let's pass a Viper instance to the constructor that represents a subset of the configuration:
-
-```go
-cache1Config := viper.Sub("cache.cache1")
-if cache1Config == nil { // Sub returns nil if the key cannot be found
- panic("cache configuration not found")
-}
-
-cache1 := NewCache(cache1Config)
-```
-
-**Note:** Always check the return value of `Sub`. It returns `nil` if a key cannot be found.
-
-Internally, the `NewCache` function can address `max-items` and `item-size` keys directly:
-
-```go
-func NewCache(v *Viper) *Cache {
- return &Cache{
- MaxItems: v.GetInt("max-items"),
- ItemSize: v.GetInt("item-size"),
- }
-}
-```
-
-The resulting code is easy to test, since it's decoupled from the main config structure,
-and easier to reuse (for the same reason).
-
-
-### Unmarshaling
-
-You also have the option of Unmarshaling all or a specific value to a struct, map,
-etc.
-
-There are two methods to do this:
-
- * `Unmarshal(rawVal any) : error`
- * `UnmarshalKey(key string, rawVal any) : error`
-
-Example:
-
-```go
-type config struct {
- Port int
- Name string
- PathMap string `mapstructure:"path_map"`
-}
-
-var C config
-
-err := viper.Unmarshal(&C)
-if err != nil {
- t.Fatalf("unable to decode into struct, %v", err)
-}
-```
-
-If you want to unmarshal configuration where the keys themselves contain dot (the default key delimiter),
-you have to change the delimiter:
-
-```go
-v := viper.NewWithOptions(viper.KeyDelimiter("::"))
-
-v.SetDefault("chart::values", map[string]any{
- "ingress": map[string]any{
- "annotations": map[string]any{
- "traefik.frontend.rule.type": "PathPrefix",
- "traefik.ingress.kubernetes.io/ssl-redirect": "true",
- },
- },
-})
-
-type config struct {
- Chart struct{
- Values map[string]any
- }
-}
-
-var C config
-
-v.Unmarshal(&C)
-```
-
-Viper also supports unmarshaling into embedded structs:
-
-```go
-/*
-Example config:
-
-module:
- enabled: true
- token: 89h3f98hbwf987h3f98wenf89ehf
-*/
-type config struct {
- Module struct {
- Enabled bool
-
- moduleConfig `mapstructure:",squash"`
- }
-}
-
-// moduleConfig could be in a module specific package
-type moduleConfig struct {
- Token string
-}
-
-var C config
-
-err := viper.Unmarshal(&C)
-if err != nil {
- t.Fatalf("unable to decode into struct, %v", err)
-}
-```
-
-Viper uses [github.com/mitchellh/mapstructure](https://github.com/mitchellh/mapstructure) under the hood for unmarshaling values which uses `mapstructure` tags by default.
-
-### Decoding custom formats
-
-A frequently requested feature for Viper is adding more value formats and decoders.
-For example, parsing character (dot, comma, semicolon, etc) separated strings into slices.
-
-This is already available in Viper using mapstructure decode hooks.
-
-Read more about the details in [this blog post](https://sagikazarmark.hu/blog/decoding-custom-formats-with-viper/).
-
-### Marshalling to string
-
-You may need to marshal all the settings held in viper into a string rather than write them to a file.
-You can use your favorite format's marshaller with the config returned by `AllSettings()`.
-
-```go
-import (
- yaml "gopkg.in/yaml.v2"
- // ...
-)
-
-func yamlStringSettings() string {
- c := viper.AllSettings()
- bs, err := yaml.Marshal(c)
- if err != nil {
- log.Fatalf("unable to marshal config to YAML: %v", err)
- }
- return string(bs)
-}
-```
-
-## Viper or Vipers?
-
-Viper comes ready to use out of the box. There is no configuration or
-initialization needed to begin using Viper. Since most applications will want
-to use a single central repository for their configuration, the viper package
-provides this. It is similar to a singleton.
-
-In all of the examples above, they demonstrate using viper in its singleton
-style approach.
-
-### Working with multiple vipers
-
-You can also create many different vipers for use in your application. Each will
-have its own unique set of configurations and values. Each can read from a
-different config file, key value store, etc. All of the functions that viper
-package supports are mirrored as methods on a viper.
-
-Example:
-
-```go
-x := viper.New()
-y := viper.New()
-
-x.SetDefault("ContentDir", "content")
-y.SetDefault("ContentDir", "foobar")
-
-//...
-```
-
-When working with multiple vipers, it is up to the user to keep track of the
-different vipers.
-
-
-## Q & A
-
-### Why is it called “Viper”?
-
-A: Viper is designed to be a [companion](http://en.wikipedia.org/wiki/Viper_(G.I._Joe))
-to [Cobra](https://github.com/spf13/cobra). While both can operate completely
-independently, together they make a powerful pair to handle much of your
-application foundation needs.
-
-### Why is it called “Cobra”?
-
-Is there a better name for a [commander](http://en.wikipedia.org/wiki/Cobra_Commander)?
-
-### Does Viper support case sensitive keys?
-
-**tl;dr:** No.
-
-Viper merges configuration from various sources, many of which are either case insensitive or uses different casing than the rest of the sources (eg. env vars).
-In order to provide the best experience when using multiple sources, the decision has been made to make all keys case insensitive.
-
-There has been several attempts to implement case sensitivity, but unfortunately it's not that trivial. We might take a stab at implementing it in [Viper v2](https://github.com/spf13/viper/issues/772), but despite the initial noise, it does not seem to be requested that much.
-
-You can vote for case sensitivity by filling out this feedback form: https://forms.gle/R6faU74qPRPAzchZ9
-
-### Is it safe to concurrently read and write to a viper?
-
-No, you will need to synchronize access to the viper yourself (for example by using the `sync` package). Concurrent reads and writes can cause a panic.
-
-## Troubleshooting
-
-See [TROUBLESHOOTING.md](TROUBLESHOOTING.md).
-
-## Development
-
-**For an optimal developer experience, it is recommended to install [Nix](https://nixos.org/download.html) and [direnv](https://direnv.net/docs/installation.html).**
-
-_Alternatively, install [Go](https://go.dev/dl/) on your computer then run `make deps` to install the rest of the dependencies._
-
-Run the test suite:
-
-```shell
-make test
-```
-
-Run linters:
-
-```shell
-make lint # pass -j option to run them in parallel
-```
-
-Some linter violations can automatically be fixed:
-
-```shell
-make fmt
-```
-
-## License
-
-The project is licensed under the [MIT License](LICENSE).
diff --git a/vendor/github.com/spf13/viper/TROUBLESHOOTING.md b/vendor/github.com/spf13/viper/TROUBLESHOOTING.md
deleted file mode 100644
index b68993d41..000000000
--- a/vendor/github.com/spf13/viper/TROUBLESHOOTING.md
+++ /dev/null
@@ -1,32 +0,0 @@
-# Troubleshooting
-
-## Unmarshaling doesn't work
-
-The most common reason for this issue is improper use of struct tags (eg. `yaml` or `json`). Viper uses [github.com/mitchellh/mapstructure](https://github.com/mitchellh/mapstructure) under the hood for unmarshaling values which uses `mapstructure` tags by default. Please refer to the library's documentation for using other struct tags.
-
-## Cannot find package
-
-Viper installation seems to fail a lot lately with the following (or a similar) error:
-
-```
-cannot find package "github.com/hashicorp/hcl/tree/hcl1" in any of:
-/usr/local/Cellar/go/1.15.7_1/libexec/src/github.com/hashicorp/hcl/tree/hcl1 (from $GOROOT)
-/Users/user/go/src/github.com/hashicorp/hcl/tree/hcl1 (from $GOPATH)
-```
-
-As the error message suggests, Go tries to look up dependencies in `GOPATH` mode (as it's commonly called) from the `GOPATH`.
-Viper opted to use [Go Modules](https://go.dev/wiki/Modules) to manage its dependencies. While in many cases the two methods are interchangeable, once a dependency releases new (major) versions, `GOPATH` mode is no longer able to decide which version to use, so it'll either use one that's already present or pick a version (usually the `master` branch).
-
-The solution is easy: switch to using Go Modules.
-Please refer to the [wiki](https://go.dev/wiki/Modules) on how to do that.
-
-**tl;dr* `export GO111MODULE=on`
-
-## Unquoted 'y' and 'n' characters get replaced with _true_ and _false_ when reading a YAML file
-
-This is a YAML 1.1 feature according to [go-yaml/yaml#740](https://github.com/go-yaml/yaml/issues/740).
-
-Potential solutions are:
-
-1. Quoting values resolved as boolean
-1. Upgrading to YAML v3 (for the time being this is possible by passing the `viper_yaml3` tag to your build)
diff --git a/vendor/github.com/spf13/viper/file.go b/vendor/github.com/spf13/viper/file.go
deleted file mode 100644
index a54fe5a7a..000000000
--- a/vendor/github.com/spf13/viper/file.go
+++ /dev/null
@@ -1,56 +0,0 @@
-//go:build !finder
-
-package viper
-
-import (
- "fmt"
- "os"
- "path/filepath"
-
- "github.com/spf13/afero"
-)
-
-// Search all configPaths for any config file.
-// Returns the first path that exists (and is a config file).
-func (v *Viper) findConfigFile() (string, error) {
- v.logger.Info("searching for config in paths", "paths", v.configPaths)
-
- for _, cp := range v.configPaths {
- file := v.searchInPath(cp)
- if file != "" {
- return file, nil
- }
- }
- return "", ConfigFileNotFoundError{v.configName, fmt.Sprintf("%s", v.configPaths)}
-}
-
-func (v *Viper) searchInPath(in string) (filename string) {
- v.logger.Debug("searching for config in path", "path", in)
- for _, ext := range SupportedExts {
- v.logger.Debug("checking if file exists", "file", filepath.Join(in, v.configName+"."+ext))
- if b, _ := exists(v.fs, filepath.Join(in, v.configName+"."+ext)); b {
- v.logger.Debug("found file", "file", filepath.Join(in, v.configName+"."+ext))
- return filepath.Join(in, v.configName+"."+ext)
- }
- }
-
- if v.configType != "" {
- if b, _ := exists(v.fs, filepath.Join(in, v.configName)); b {
- return filepath.Join(in, v.configName)
- }
- }
-
- return ""
-}
-
-// exists checks if file exists.
-func exists(fs afero.Fs, path string) (bool, error) {
- stat, err := fs.Stat(path)
- if err == nil {
- return !stat.IsDir(), nil
- }
- if os.IsNotExist(err) {
- return false, nil
- }
- return false, err
-}
diff --git a/vendor/github.com/spf13/viper/file_finder.go b/vendor/github.com/spf13/viper/file_finder.go
deleted file mode 100644
index d96a1bd22..000000000
--- a/vendor/github.com/spf13/viper/file_finder.go
+++ /dev/null
@@ -1,38 +0,0 @@
-//go:build finder
-
-package viper
-
-import (
- "fmt"
-
- "github.com/sagikazarmark/locafero"
-)
-
-// Search all configPaths for any config file.
-// Returns the first path that exists (and is a config file).
-func (v *Viper) findConfigFile() (string, error) {
- var names []string
-
- if v.configType != "" {
- names = locafero.NameWithOptionalExtensions(v.configName, SupportedExts...)
- } else {
- names = locafero.NameWithExtensions(v.configName, SupportedExts...)
- }
-
- finder := locafero.Finder{
- Paths: v.configPaths,
- Names: names,
- Type: locafero.FileTypeFile,
- }
-
- results, err := finder.Find(v.fs)
- if err != nil {
- return "", err
- }
-
- if len(results) == 0 {
- return "", ConfigFileNotFoundError{v.configName, fmt.Sprintf("%s", v.configPaths)}
- }
-
- return results[0], nil
-}
diff --git a/vendor/github.com/spf13/viper/flags.go b/vendor/github.com/spf13/viper/flags.go
deleted file mode 100644
index de033ed58..000000000
--- a/vendor/github.com/spf13/viper/flags.go
+++ /dev/null
@@ -1,57 +0,0 @@
-package viper
-
-import "github.com/spf13/pflag"
-
-// FlagValueSet is an interface that users can implement
-// to bind a set of flags to viper.
-type FlagValueSet interface {
- VisitAll(fn func(FlagValue))
-}
-
-// FlagValue is an interface that users can implement
-// to bind different flags to viper.
-type FlagValue interface {
- HasChanged() bool
- Name() string
- ValueString() string
- ValueType() string
-}
-
-// pflagValueSet is a wrapper around *pflag.ValueSet
-// that implements FlagValueSet.
-type pflagValueSet struct {
- flags *pflag.FlagSet
-}
-
-// VisitAll iterates over all *pflag.Flag inside the *pflag.FlagSet.
-func (p pflagValueSet) VisitAll(fn func(flag FlagValue)) {
- p.flags.VisitAll(func(flag *pflag.Flag) {
- fn(pflagValue{flag})
- })
-}
-
-// pflagValue is a wrapper around *pflag.flag
-// that implements FlagValue.
-type pflagValue struct {
- flag *pflag.Flag
-}
-
-// HasChanged returns whether the flag has changes or not.
-func (p pflagValue) HasChanged() bool {
- return p.flag.Changed
-}
-
-// Name returns the name of the flag.
-func (p pflagValue) Name() string {
- return p.flag.Name
-}
-
-// ValueString returns the value of the flag as a string.
-func (p pflagValue) ValueString() string {
- return p.flag.Value.String()
-}
-
-// ValueType returns the type of the flag as a string.
-func (p pflagValue) ValueType() string {
- return p.flag.Value.Type()
-}
diff --git a/vendor/github.com/spf13/viper/flake.lock b/vendor/github.com/spf13/viper/flake.lock
deleted file mode 100644
index 3840614fa..000000000
--- a/vendor/github.com/spf13/viper/flake.lock
+++ /dev/null
@@ -1,273 +0,0 @@
-{
- "nodes": {
- "devenv": {
- "inputs": {
- "flake-compat": "flake-compat",
- "nix": "nix",
- "nixpkgs": "nixpkgs",
- "pre-commit-hooks": "pre-commit-hooks"
- },
- "locked": {
- "lastModified": 1707817777,
- "narHash": "sha256-vHyIs1OULQ3/91wD6xOiuayfI71JXALGA5KLnDKAcy0=",
- "owner": "cachix",
- "repo": "devenv",
- "rev": "5a30b9e5ac7c6167e61b1f4193d5130bb9f8defa",
- "type": "github"
- },
- "original": {
- "owner": "cachix",
- "repo": "devenv",
- "type": "github"
- }
- },
- "flake-compat": {
- "flake": false,
- "locked": {
- "lastModified": 1673956053,
- "narHash": "sha256-4gtG9iQuiKITOjNQQeQIpoIB6b16fm+504Ch3sNKLd8=",
- "owner": "edolstra",
- "repo": "flake-compat",
- "rev": "35bb57c0c8d8b62bbfd284272c928ceb64ddbde9",
- "type": "github"
- },
- "original": {
- "owner": "edolstra",
- "repo": "flake-compat",
- "type": "github"
- }
- },
- "flake-parts": {
- "inputs": {
- "nixpkgs-lib": "nixpkgs-lib"
- },
- "locked": {
- "lastModified": 1706830856,
- "narHash": "sha256-a0NYyp+h9hlb7ddVz4LUn1vT/PLwqfrWYcHMvFB1xYg=",
- "owner": "hercules-ci",
- "repo": "flake-parts",
- "rev": "b253292d9c0a5ead9bc98c4e9a26c6312e27d69f",
- "type": "github"
- },
- "original": {
- "owner": "hercules-ci",
- "repo": "flake-parts",
- "type": "github"
- }
- },
- "flake-utils": {
- "inputs": {
- "systems": "systems"
- },
- "locked": {
- "lastModified": 1685518550,
- "narHash": "sha256-o2d0KcvaXzTrPRIo0kOLV0/QXHhDQ5DTi+OxcjO8xqY=",
- "owner": "numtide",
- "repo": "flake-utils",
- "rev": "a1720a10a6cfe8234c0e93907ffe81be440f4cef",
- "type": "github"
- },
- "original": {
- "owner": "numtide",
- "repo": "flake-utils",
- "type": "github"
- }
- },
- "gitignore": {
- "inputs": {
- "nixpkgs": [
- "devenv",
- "pre-commit-hooks",
- "nixpkgs"
- ]
- },
- "locked": {
- "lastModified": 1660459072,
- "narHash": "sha256-8DFJjXG8zqoONA1vXtgeKXy68KdJL5UaXR8NtVMUbx8=",
- "owner": "hercules-ci",
- "repo": "gitignore.nix",
- "rev": "a20de23b925fd8264fd7fad6454652e142fd7f73",
- "type": "github"
- },
- "original": {
- "owner": "hercules-ci",
- "repo": "gitignore.nix",
- "type": "github"
- }
- },
- "lowdown-src": {
- "flake": false,
- "locked": {
- "lastModified": 1633514407,
- "narHash": "sha256-Dw32tiMjdK9t3ETl5fzGrutQTzh2rufgZV4A/BbxuD4=",
- "owner": "kristapsdz",
- "repo": "lowdown",
- "rev": "d2c2b44ff6c27b936ec27358a2653caaef8f73b8",
- "type": "github"
- },
- "original": {
- "owner": "kristapsdz",
- "repo": "lowdown",
- "type": "github"
- }
- },
- "nix": {
- "inputs": {
- "lowdown-src": "lowdown-src",
- "nixpkgs": [
- "devenv",
- "nixpkgs"
- ],
- "nixpkgs-regression": "nixpkgs-regression"
- },
- "locked": {
- "lastModified": 1676545802,
- "narHash": "sha256-EK4rZ+Hd5hsvXnzSzk2ikhStJnD63odF7SzsQ8CuSPU=",
- "owner": "domenkozar",
- "repo": "nix",
- "rev": "7c91803598ffbcfe4a55c44ac6d49b2cf07a527f",
- "type": "github"
- },
- "original": {
- "owner": "domenkozar",
- "ref": "relaxed-flakes",
- "repo": "nix",
- "type": "github"
- }
- },
- "nixpkgs": {
- "locked": {
- "lastModified": 1678875422,
- "narHash": "sha256-T3o6NcQPwXjxJMn2shz86Chch4ljXgZn746c2caGxd8=",
- "owner": "NixOS",
- "repo": "nixpkgs",
- "rev": "126f49a01de5b7e35a43fd43f891ecf6d3a51459",
- "type": "github"
- },
- "original": {
- "owner": "NixOS",
- "ref": "nixpkgs-unstable",
- "repo": "nixpkgs",
- "type": "github"
- }
- },
- "nixpkgs-lib": {
- "locked": {
- "dir": "lib",
- "lastModified": 1706550542,
- "narHash": "sha256-UcsnCG6wx++23yeER4Hg18CXWbgNpqNXcHIo5/1Y+hc=",
- "owner": "NixOS",
- "repo": "nixpkgs",
- "rev": "97b17f32362e475016f942bbdfda4a4a72a8a652",
- "type": "github"
- },
- "original": {
- "dir": "lib",
- "owner": "NixOS",
- "ref": "nixos-unstable",
- "repo": "nixpkgs",
- "type": "github"
- }
- },
- "nixpkgs-regression": {
- "locked": {
- "lastModified": 1643052045,
- "narHash": "sha256-uGJ0VXIhWKGXxkeNnq4TvV3CIOkUJ3PAoLZ3HMzNVMw=",
- "owner": "NixOS",
- "repo": "nixpkgs",
- "rev": "215d4d0fd80ca5163643b03a33fde804a29cc1e2",
- "type": "github"
- },
- "original": {
- "owner": "NixOS",
- "repo": "nixpkgs",
- "rev": "215d4d0fd80ca5163643b03a33fde804a29cc1e2",
- "type": "github"
- }
- },
- "nixpkgs-stable": {
- "locked": {
- "lastModified": 1685801374,
- "narHash": "sha256-otaSUoFEMM+LjBI1XL/xGB5ao6IwnZOXc47qhIgJe8U=",
- "owner": "NixOS",
- "repo": "nixpkgs",
- "rev": "c37ca420157f4abc31e26f436c1145f8951ff373",
- "type": "github"
- },
- "original": {
- "owner": "NixOS",
- "ref": "nixos-23.05",
- "repo": "nixpkgs",
- "type": "github"
- }
- },
- "nixpkgs_2": {
- "locked": {
- "lastModified": 1707939175,
- "narHash": "sha256-D1xan0lgxbmXDyzVqXTiSYHLmAMrMRdD+alKzEO/p3w=",
- "owner": "NixOS",
- "repo": "nixpkgs",
- "rev": "f7e8132daca31b1e3859ac0fb49741754375ac3d",
- "type": "github"
- },
- "original": {
- "owner": "NixOS",
- "ref": "nixpkgs-unstable",
- "repo": "nixpkgs",
- "type": "github"
- }
- },
- "pre-commit-hooks": {
- "inputs": {
- "flake-compat": [
- "devenv",
- "flake-compat"
- ],
- "flake-utils": "flake-utils",
- "gitignore": "gitignore",
- "nixpkgs": [
- "devenv",
- "nixpkgs"
- ],
- "nixpkgs-stable": "nixpkgs-stable"
- },
- "locked": {
- "lastModified": 1704725188,
- "narHash": "sha256-qq8NbkhRZF1vVYQFt1s8Mbgo8knj+83+QlL5LBnYGpI=",
- "owner": "cachix",
- "repo": "pre-commit-hooks.nix",
- "rev": "ea96f0c05924341c551a797aaba8126334c505d2",
- "type": "github"
- },
- "original": {
- "owner": "cachix",
- "repo": "pre-commit-hooks.nix",
- "type": "github"
- }
- },
- "root": {
- "inputs": {
- "devenv": "devenv",
- "flake-parts": "flake-parts",
- "nixpkgs": "nixpkgs_2"
- }
- },
- "systems": {
- "locked": {
- "lastModified": 1681028828,
- "narHash": "sha256-Vy1rq5AaRuLzOxct8nz4T6wlgyUR7zLU309k9mBC768=",
- "owner": "nix-systems",
- "repo": "default",
- "rev": "da67096a3b9bf56a91d16901293e51ba5b49a27e",
- "type": "github"
- },
- "original": {
- "owner": "nix-systems",
- "repo": "default",
- "type": "github"
- }
- }
- },
- "root": "root",
- "version": 7
-}
diff --git a/vendor/github.com/spf13/viper/flake.nix b/vendor/github.com/spf13/viper/flake.nix
deleted file mode 100644
index 0230668cf..000000000
--- a/vendor/github.com/spf13/viper/flake.nix
+++ /dev/null
@@ -1,57 +0,0 @@
-{
- description = "Viper";
-
- inputs = {
- nixpkgs.url = "github:NixOS/nixpkgs/nixpkgs-unstable";
- flake-parts.url = "github:hercules-ci/flake-parts";
- devenv.url = "github:cachix/devenv";
- };
-
- outputs = inputs@{ flake-parts, ... }:
- flake-parts.lib.mkFlake { inherit inputs; } {
- imports = [
- inputs.devenv.flakeModule
- ];
-
- systems = [ "x86_64-linux" "x86_64-darwin" "aarch64-darwin" ];
-
- perSystem = { config, self', inputs', pkgs, system, ... }: rec {
- devenv.shells = {
- default = {
- languages = {
- go.enable = true;
- go.package = pkgs.go_1_22;
- };
-
- pre-commit.hooks = {
- nixpkgs-fmt.enable = true;
- yamllint.enable = true;
- };
-
- packages = with pkgs; [
- gnumake
-
- golangci-lint
- yamllint
- ];
-
- scripts = {
- versions.exec = ''
- go version
- golangci-lint version
- '';
- };
-
- enterShell = ''
- versions
- '';
-
- # https://github.com/cachix/devenv/issues/528#issuecomment-1556108767
- containers = pkgs.lib.mkForce { };
- };
-
- ci = devenv.shells.default;
- };
- };
- };
-}
diff --git a/vendor/github.com/spf13/viper/internal/encoding/decoder.go b/vendor/github.com/spf13/viper/internal/encoding/decoder.go
deleted file mode 100644
index 8a7b1dbc9..000000000
--- a/vendor/github.com/spf13/viper/internal/encoding/decoder.go
+++ /dev/null
@@ -1,61 +0,0 @@
-package encoding
-
-import (
- "sync"
-)
-
-// Decoder decodes the contents of b into v.
-// It's primarily used for decoding contents of a file into a map[string]any.
-type Decoder interface {
- Decode(b []byte, v map[string]any) error
-}
-
-const (
- // ErrDecoderNotFound is returned when there is no decoder registered for a format.
- ErrDecoderNotFound = encodingError("decoder not found for this format")
-
- // ErrDecoderFormatAlreadyRegistered is returned when an decoder is already registered for a format.
- ErrDecoderFormatAlreadyRegistered = encodingError("decoder already registered for this format")
-)
-
-// DecoderRegistry can choose an appropriate Decoder based on the provided format.
-type DecoderRegistry struct {
- decoders map[string]Decoder
-
- mu sync.RWMutex
-}
-
-// NewDecoderRegistry returns a new, initialized DecoderRegistry.
-func NewDecoderRegistry() *DecoderRegistry {
- return &DecoderRegistry{
- decoders: make(map[string]Decoder),
- }
-}
-
-// RegisterDecoder registers a Decoder for a format.
-// Registering a Decoder for an already existing format is not supported.
-func (e *DecoderRegistry) RegisterDecoder(format string, enc Decoder) error {
- e.mu.Lock()
- defer e.mu.Unlock()
-
- if _, ok := e.decoders[format]; ok {
- return ErrDecoderFormatAlreadyRegistered
- }
-
- e.decoders[format] = enc
-
- return nil
-}
-
-// Decode calls the underlying Decoder based on the format.
-func (e *DecoderRegistry) Decode(format string, b []byte, v map[string]any) error {
- e.mu.RLock()
- decoder, ok := e.decoders[format]
- e.mu.RUnlock()
-
- if !ok {
- return ErrDecoderNotFound
- }
-
- return decoder.Decode(b, v)
-}
diff --git a/vendor/github.com/spf13/viper/internal/encoding/dotenv/codec.go b/vendor/github.com/spf13/viper/internal/encoding/dotenv/codec.go
deleted file mode 100644
index 3ebc76f02..000000000
--- a/vendor/github.com/spf13/viper/internal/encoding/dotenv/codec.go
+++ /dev/null
@@ -1,61 +0,0 @@
-package dotenv
-
-import (
- "bytes"
- "fmt"
- "sort"
- "strings"
-
- "github.com/subosito/gotenv"
-)
-
-const keyDelimiter = "_"
-
-// Codec implements the encoding.Encoder and encoding.Decoder interfaces for encoding data containing environment variables
-// (commonly called as dotenv format).
-type Codec struct{}
-
-func (Codec) Encode(v map[string]any) ([]byte, error) {
- flattened := map[string]any{}
-
- flattened = flattenAndMergeMap(flattened, v, "", keyDelimiter)
-
- keys := make([]string, 0, len(flattened))
-
- for key := range flattened {
- keys = append(keys, key)
- }
-
- sort.Strings(keys)
-
- var buf bytes.Buffer
-
- for _, key := range keys {
- _, err := buf.WriteString(fmt.Sprintf("%v=%v\n", strings.ToUpper(key), flattened[key]))
- if err != nil {
- return nil, err
- }
- }
-
- return buf.Bytes(), nil
-}
-
-func (Codec) Decode(b []byte, v map[string]any) error {
- var buf bytes.Buffer
-
- _, err := buf.Write(b)
- if err != nil {
- return err
- }
-
- env, err := gotenv.StrictParse(&buf)
- if err != nil {
- return err
- }
-
- for key, value := range env {
- v[key] = value
- }
-
- return nil
-}
diff --git a/vendor/github.com/spf13/viper/internal/encoding/dotenv/map_utils.go b/vendor/github.com/spf13/viper/internal/encoding/dotenv/map_utils.go
deleted file mode 100644
index 8bfe0a9de..000000000
--- a/vendor/github.com/spf13/viper/internal/encoding/dotenv/map_utils.go
+++ /dev/null
@@ -1,41 +0,0 @@
-package dotenv
-
-import (
- "strings"
-
- "github.com/spf13/cast"
-)
-
-// flattenAndMergeMap recursively flattens the given map into a new map
-// Code is based on the function with the same name in the main package.
-// TODO: move it to a common place.
-func flattenAndMergeMap(shadow, m map[string]any, prefix, delimiter string) map[string]any {
- if shadow != nil && prefix != "" && shadow[prefix] != nil {
- // prefix is shadowed => nothing more to flatten
- return shadow
- }
- if shadow == nil {
- shadow = make(map[string]any)
- }
-
- var m2 map[string]any
- if prefix != "" {
- prefix += delimiter
- }
- for k, val := range m {
- fullKey := prefix + k
- switch val := val.(type) {
- case map[string]any:
- m2 = val
- case map[any]any:
- m2 = cast.ToStringMap(val)
- default:
- // immediate value
- shadow[strings.ToLower(fullKey)] = val
- continue
- }
- // recursively merge to shadow map
- shadow = flattenAndMergeMap(shadow, m2, fullKey, delimiter)
- }
- return shadow
-}
diff --git a/vendor/github.com/spf13/viper/internal/encoding/encoder.go b/vendor/github.com/spf13/viper/internal/encoding/encoder.go
deleted file mode 100644
index 659585962..000000000
--- a/vendor/github.com/spf13/viper/internal/encoding/encoder.go
+++ /dev/null
@@ -1,60 +0,0 @@
-package encoding
-
-import (
- "sync"
-)
-
-// Encoder encodes the contents of v into a byte representation.
-// It's primarily used for encoding a map[string]any into a file format.
-type Encoder interface {
- Encode(v map[string]any) ([]byte, error)
-}
-
-const (
- // ErrEncoderNotFound is returned when there is no encoder registered for a format.
- ErrEncoderNotFound = encodingError("encoder not found for this format")
-
- // ErrEncoderFormatAlreadyRegistered is returned when an encoder is already registered for a format.
- ErrEncoderFormatAlreadyRegistered = encodingError("encoder already registered for this format")
-)
-
-// EncoderRegistry can choose an appropriate Encoder based on the provided format.
-type EncoderRegistry struct {
- encoders map[string]Encoder
-
- mu sync.RWMutex
-}
-
-// NewEncoderRegistry returns a new, initialized EncoderRegistry.
-func NewEncoderRegistry() *EncoderRegistry {
- return &EncoderRegistry{
- encoders: make(map[string]Encoder),
- }
-}
-
-// RegisterEncoder registers an Encoder for a format.
-// Registering a Encoder for an already existing format is not supported.
-func (e *EncoderRegistry) RegisterEncoder(format string, enc Encoder) error {
- e.mu.Lock()
- defer e.mu.Unlock()
-
- if _, ok := e.encoders[format]; ok {
- return ErrEncoderFormatAlreadyRegistered
- }
-
- e.encoders[format] = enc
-
- return nil
-}
-
-func (e *EncoderRegistry) Encode(format string, v map[string]any) ([]byte, error) {
- e.mu.RLock()
- encoder, ok := e.encoders[format]
- e.mu.RUnlock()
-
- if !ok {
- return nil, ErrEncoderNotFound
- }
-
- return encoder.Encode(v)
-}
diff --git a/vendor/github.com/spf13/viper/internal/encoding/error.go b/vendor/github.com/spf13/viper/internal/encoding/error.go
deleted file mode 100644
index e4cde02d7..000000000
--- a/vendor/github.com/spf13/viper/internal/encoding/error.go
+++ /dev/null
@@ -1,7 +0,0 @@
-package encoding
-
-type encodingError string
-
-func (e encodingError) Error() string {
- return string(e)
-}
diff --git a/vendor/github.com/spf13/viper/internal/encoding/hcl/codec.go b/vendor/github.com/spf13/viper/internal/encoding/hcl/codec.go
deleted file mode 100644
index d7fa8a1b7..000000000
--- a/vendor/github.com/spf13/viper/internal/encoding/hcl/codec.go
+++ /dev/null
@@ -1,40 +0,0 @@
-package hcl
-
-import (
- "bytes"
- "encoding/json"
-
- "github.com/hashicorp/hcl"
- "github.com/hashicorp/hcl/hcl/printer"
-)
-
-// Codec implements the encoding.Encoder and encoding.Decoder interfaces for HCL encoding.
-// TODO: add printer config to the codec?
-type Codec struct{}
-
-func (Codec) Encode(v map[string]any) ([]byte, error) {
- b, err := json.Marshal(v)
- if err != nil {
- return nil, err
- }
-
- // TODO: use printer.Format? Is the trailing newline an issue?
-
- ast, err := hcl.Parse(string(b))
- if err != nil {
- return nil, err
- }
-
- var buf bytes.Buffer
-
- err = printer.Fprint(&buf, ast.Node)
- if err != nil {
- return nil, err
- }
-
- return buf.Bytes(), nil
-}
-
-func (Codec) Decode(b []byte, v map[string]any) error {
- return hcl.Unmarshal(b, &v)
-}
diff --git a/vendor/github.com/spf13/viper/internal/encoding/ini/codec.go b/vendor/github.com/spf13/viper/internal/encoding/ini/codec.go
deleted file mode 100644
index d91cf59d2..000000000
--- a/vendor/github.com/spf13/viper/internal/encoding/ini/codec.go
+++ /dev/null
@@ -1,99 +0,0 @@
-package ini
-
-import (
- "bytes"
- "sort"
- "strings"
-
- "github.com/spf13/cast"
- "gopkg.in/ini.v1"
-)
-
-// LoadOptions contains all customized options used for load data source(s).
-// This type is added here for convenience: this way consumers can import a single package called "ini".
-type LoadOptions = ini.LoadOptions
-
-// Codec implements the encoding.Encoder and encoding.Decoder interfaces for INI encoding.
-type Codec struct {
- KeyDelimiter string
- LoadOptions LoadOptions
-}
-
-func (c Codec) Encode(v map[string]any) ([]byte, error) {
- cfg := ini.Empty()
- ini.PrettyFormat = false
-
- flattened := map[string]any{}
-
- flattened = flattenAndMergeMap(flattened, v, "", c.keyDelimiter())
-
- keys := make([]string, 0, len(flattened))
-
- for key := range flattened {
- keys = append(keys, key)
- }
-
- sort.Strings(keys)
-
- for _, key := range keys {
- sectionName, keyName := "", key
-
- lastSep := strings.LastIndex(key, ".")
- if lastSep != -1 {
- sectionName = key[:(lastSep)]
- keyName = key[(lastSep + 1):]
- }
-
- // TODO: is this a good idea?
- if sectionName == "default" {
- sectionName = ""
- }
-
- cfg.Section(sectionName).Key(keyName).SetValue(cast.ToString(flattened[key]))
- }
-
- var buf bytes.Buffer
-
- _, err := cfg.WriteTo(&buf)
- if err != nil {
- return nil, err
- }
-
- return buf.Bytes(), nil
-}
-
-func (c Codec) Decode(b []byte, v map[string]any) error {
- cfg := ini.Empty(c.LoadOptions)
-
- err := cfg.Append(b)
- if err != nil {
- return err
- }
-
- sections := cfg.Sections()
-
- for i := 0; i < len(sections); i++ {
- section := sections[i]
- keys := section.Keys()
-
- for j := 0; j < len(keys); j++ {
- key := keys[j]
- value := cfg.Section(section.Name()).Key(key.Name()).String()
-
- deepestMap := deepSearch(v, strings.Split(section.Name(), c.keyDelimiter()))
-
- // set innermost value
- deepestMap[key.Name()] = value
- }
- }
-
- return nil
-}
-
-func (c Codec) keyDelimiter() string {
- if c.KeyDelimiter == "" {
- return "."
- }
-
- return c.KeyDelimiter
-}
diff --git a/vendor/github.com/spf13/viper/internal/encoding/ini/map_utils.go b/vendor/github.com/spf13/viper/internal/encoding/ini/map_utils.go
deleted file mode 100644
index 490ab594e..000000000
--- a/vendor/github.com/spf13/viper/internal/encoding/ini/map_utils.go
+++ /dev/null
@@ -1,74 +0,0 @@
-package ini
-
-import (
- "strings"
-
- "github.com/spf13/cast"
-)
-
-// THIS CODE IS COPIED HERE: IT SHOULD NOT BE MODIFIED
-// AT SOME POINT IT WILL BE MOVED TO A COMMON PLACE
-// deepSearch scans deep maps, following the key indexes listed in the
-// sequence "path".
-// The last value is expected to be another map, and is returned.
-//
-// In case intermediate keys do not exist, or map to a non-map value,
-// a new map is created and inserted, and the search continues from there:
-// the initial map "m" may be modified!
-func deepSearch(m map[string]any, path []string) map[string]any {
- for _, k := range path {
- m2, ok := m[k]
- if !ok {
- // intermediate key does not exist
- // => create it and continue from there
- m3 := make(map[string]any)
- m[k] = m3
- m = m3
- continue
- }
- m3, ok := m2.(map[string]any)
- if !ok {
- // intermediate key is a value
- // => replace with a new map
- m3 = make(map[string]any)
- m[k] = m3
- }
- // continue search from here
- m = m3
- }
- return m
-}
-
-// flattenAndMergeMap recursively flattens the given map into a new map
-// Code is based on the function with the same name in the main package.
-// TODO: move it to a common place.
-func flattenAndMergeMap(shadow, m map[string]any, prefix, delimiter string) map[string]any {
- if shadow != nil && prefix != "" && shadow[prefix] != nil {
- // prefix is shadowed => nothing more to flatten
- return shadow
- }
- if shadow == nil {
- shadow = make(map[string]any)
- }
-
- var m2 map[string]any
- if prefix != "" {
- prefix += delimiter
- }
- for k, val := range m {
- fullKey := prefix + k
- switch val := val.(type) {
- case map[string]any:
- m2 = val
- case map[any]any:
- m2 = cast.ToStringMap(val)
- default:
- // immediate value
- shadow[strings.ToLower(fullKey)] = val
- continue
- }
- // recursively merge to shadow map
- shadow = flattenAndMergeMap(shadow, m2, fullKey, delimiter)
- }
- return shadow
-}
diff --git a/vendor/github.com/spf13/viper/internal/encoding/javaproperties/codec.go b/vendor/github.com/spf13/viper/internal/encoding/javaproperties/codec.go
deleted file mode 100644
index e92e5172c..000000000
--- a/vendor/github.com/spf13/viper/internal/encoding/javaproperties/codec.go
+++ /dev/null
@@ -1,86 +0,0 @@
-package javaproperties
-
-import (
- "bytes"
- "sort"
- "strings"
-
- "github.com/magiconair/properties"
- "github.com/spf13/cast"
-)
-
-// Codec implements the encoding.Encoder and encoding.Decoder interfaces for Java properties encoding.
-type Codec struct {
- KeyDelimiter string
-
- // Store read properties on the object so that we can write back in order with comments.
- // This will only be used if the configuration read is a properties file.
- // TODO: drop this feature in v2
- // TODO: make use of the global properties object optional
- Properties *properties.Properties
-}
-
-func (c *Codec) Encode(v map[string]any) ([]byte, error) {
- if c.Properties == nil {
- c.Properties = properties.NewProperties()
- }
-
- flattened := map[string]any{}
-
- flattened = flattenAndMergeMap(flattened, v, "", c.keyDelimiter())
-
- keys := make([]string, 0, len(flattened))
-
- for key := range flattened {
- keys = append(keys, key)
- }
-
- sort.Strings(keys)
-
- for _, key := range keys {
- _, _, err := c.Properties.Set(key, cast.ToString(flattened[key]))
- if err != nil {
- return nil, err
- }
- }
-
- var buf bytes.Buffer
-
- _, err := c.Properties.WriteComment(&buf, "#", properties.UTF8)
- if err != nil {
- return nil, err
- }
-
- return buf.Bytes(), nil
-}
-
-func (c *Codec) Decode(b []byte, v map[string]any) error {
- var err error
- c.Properties, err = properties.Load(b, properties.UTF8)
- if err != nil {
- return err
- }
-
- for _, key := range c.Properties.Keys() {
- // ignore existence check: we know it's there
- value, _ := c.Properties.Get(key)
-
- // recursively build nested maps
- path := strings.Split(key, c.keyDelimiter())
- lastKey := strings.ToLower(path[len(path)-1])
- deepestMap := deepSearch(v, path[0:len(path)-1])
-
- // set innermost value
- deepestMap[lastKey] = value
- }
-
- return nil
-}
-
-func (c Codec) keyDelimiter() string {
- if c.KeyDelimiter == "" {
- return "."
- }
-
- return c.KeyDelimiter
-}
diff --git a/vendor/github.com/spf13/viper/internal/encoding/javaproperties/map_utils.go b/vendor/github.com/spf13/viper/internal/encoding/javaproperties/map_utils.go
deleted file mode 100644
index 6e1aff223..000000000
--- a/vendor/github.com/spf13/viper/internal/encoding/javaproperties/map_utils.go
+++ /dev/null
@@ -1,74 +0,0 @@
-package javaproperties
-
-import (
- "strings"
-
- "github.com/spf13/cast"
-)
-
-// THIS CODE IS COPIED HERE: IT SHOULD NOT BE MODIFIED
-// AT SOME POINT IT WILL BE MOVED TO A COMMON PLACE
-// deepSearch scans deep maps, following the key indexes listed in the
-// sequence "path".
-// The last value is expected to be another map, and is returned.
-//
-// In case intermediate keys do not exist, or map to a non-map value,
-// a new map is created and inserted, and the search continues from there:
-// the initial map "m" may be modified!
-func deepSearch(m map[string]any, path []string) map[string]any {
- for _, k := range path {
- m2, ok := m[k]
- if !ok {
- // intermediate key does not exist
- // => create it and continue from there
- m3 := make(map[string]any)
- m[k] = m3
- m = m3
- continue
- }
- m3, ok := m2.(map[string]any)
- if !ok {
- // intermediate key is a value
- // => replace with a new map
- m3 = make(map[string]any)
- m[k] = m3
- }
- // continue search from here
- m = m3
- }
- return m
-}
-
-// flattenAndMergeMap recursively flattens the given map into a new map
-// Code is based on the function with the same name in the main package.
-// TODO: move it to a common place.
-func flattenAndMergeMap(shadow, m map[string]any, prefix, delimiter string) map[string]any {
- if shadow != nil && prefix != "" && shadow[prefix] != nil {
- // prefix is shadowed => nothing more to flatten
- return shadow
- }
- if shadow == nil {
- shadow = make(map[string]any)
- }
-
- var m2 map[string]any
- if prefix != "" {
- prefix += delimiter
- }
- for k, val := range m {
- fullKey := prefix + k
- switch val := val.(type) {
- case map[string]any:
- m2 = val
- case map[any]any:
- m2 = cast.ToStringMap(val)
- default:
- // immediate value
- shadow[strings.ToLower(fullKey)] = val
- continue
- }
- // recursively merge to shadow map
- shadow = flattenAndMergeMap(shadow, m2, fullKey, delimiter)
- }
- return shadow
-}
diff --git a/vendor/github.com/spf13/viper/internal/encoding/json/codec.go b/vendor/github.com/spf13/viper/internal/encoding/json/codec.go
deleted file mode 100644
index da7546b5a..000000000
--- a/vendor/github.com/spf13/viper/internal/encoding/json/codec.go
+++ /dev/null
@@ -1,17 +0,0 @@
-package json
-
-import (
- "encoding/json"
-)
-
-// Codec implements the encoding.Encoder and encoding.Decoder interfaces for JSON encoding.
-type Codec struct{}
-
-func (Codec) Encode(v map[string]any) ([]byte, error) {
- // TODO: expose prefix and indent in the Codec as setting?
- return json.MarshalIndent(v, "", " ")
-}
-
-func (Codec) Decode(b []byte, v map[string]any) error {
- return json.Unmarshal(b, &v)
-}
diff --git a/vendor/github.com/spf13/viper/internal/encoding/toml/codec.go b/vendor/github.com/spf13/viper/internal/encoding/toml/codec.go
deleted file mode 100644
index c70aa8d28..000000000
--- a/vendor/github.com/spf13/viper/internal/encoding/toml/codec.go
+++ /dev/null
@@ -1,16 +0,0 @@
-package toml
-
-import (
- "github.com/pelletier/go-toml/v2"
-)
-
-// Codec implements the encoding.Encoder and encoding.Decoder interfaces for TOML encoding.
-type Codec struct{}
-
-func (Codec) Encode(v map[string]any) ([]byte, error) {
- return toml.Marshal(v)
-}
-
-func (Codec) Decode(b []byte, v map[string]any) error {
- return toml.Unmarshal(b, &v)
-}
diff --git a/vendor/github.com/spf13/viper/internal/encoding/yaml/codec.go b/vendor/github.com/spf13/viper/internal/encoding/yaml/codec.go
deleted file mode 100644
index 036879249..000000000
--- a/vendor/github.com/spf13/viper/internal/encoding/yaml/codec.go
+++ /dev/null
@@ -1,14 +0,0 @@
-package yaml
-
-import "gopkg.in/yaml.v3"
-
-// Codec implements the encoding.Encoder and encoding.Decoder interfaces for YAML encoding.
-type Codec struct{}
-
-func (Codec) Encode(v map[string]any) ([]byte, error) {
- return yaml.Marshal(v)
-}
-
-func (Codec) Decode(b []byte, v map[string]any) error {
- return yaml.Unmarshal(b, &v)
-}
diff --git a/vendor/github.com/spf13/viper/internal/features/bind_struct.go b/vendor/github.com/spf13/viper/internal/features/bind_struct.go
deleted file mode 100644
index 89302c216..000000000
--- a/vendor/github.com/spf13/viper/internal/features/bind_struct.go
+++ /dev/null
@@ -1,5 +0,0 @@
-//go:build viper_bind_struct
-
-package features
-
-const BindStruct = true
diff --git a/vendor/github.com/spf13/viper/internal/features/bind_struct_default.go b/vendor/github.com/spf13/viper/internal/features/bind_struct_default.go
deleted file mode 100644
index edfaf73b6..000000000
--- a/vendor/github.com/spf13/viper/internal/features/bind_struct_default.go
+++ /dev/null
@@ -1,5 +0,0 @@
-//go:build !viper_bind_struct
-
-package features
-
-const BindStruct = false
diff --git a/vendor/github.com/spf13/viper/logger.go b/vendor/github.com/spf13/viper/logger.go
deleted file mode 100644
index 8938053b3..000000000
--- a/vendor/github.com/spf13/viper/logger.go
+++ /dev/null
@@ -1,68 +0,0 @@
-package viper
-
-import (
- "context"
-
- slog "github.com/sagikazarmark/slog-shim"
-)
-
-// Logger is a unified interface for various logging use cases and practices, including:
-// - leveled logging
-// - structured logging
-//
-// Deprecated: use `log/slog` instead.
-type Logger interface {
- // Trace logs a Trace event.
- //
- // Even more fine-grained information than Debug events.
- // Loggers not supporting this level should fall back to Debug.
- Trace(msg string, keyvals ...any)
-
- // Debug logs a Debug event.
- //
- // A verbose series of information events.
- // They are useful when debugging the system.
- Debug(msg string, keyvals ...any)
-
- // Info logs an Info event.
- //
- // General information about what's happening inside the system.
- Info(msg string, keyvals ...any)
-
- // Warn logs a Warn(ing) event.
- //
- // Non-critical events that should be looked at.
- Warn(msg string, keyvals ...any)
-
- // Error logs an Error event.
- //
- // Critical events that require immediate attention.
- // Loggers commonly provide Fatal and Panic levels above Error level,
- // but exiting and panicking is out of scope for a logging library.
- Error(msg string, keyvals ...any)
-}
-
-// WithLogger sets a custom logger.
-func WithLogger(l *slog.Logger) Option {
- return optionFunc(func(v *Viper) {
- v.logger = l
- })
-}
-
-type discardHandler struct{}
-
-func (n *discardHandler) Enabled(_ context.Context, _ slog.Level) bool {
- return false
-}
-
-func (n *discardHandler) Handle(_ context.Context, _ slog.Record) error {
- return nil
-}
-
-func (n *discardHandler) WithAttrs(_ []slog.Attr) slog.Handler {
- return n
-}
-
-func (n *discardHandler) WithGroup(_ string) slog.Handler {
- return n
-}
diff --git a/vendor/github.com/spf13/viper/util.go b/vendor/github.com/spf13/viper/util.go
deleted file mode 100644
index 117c6ac31..000000000
--- a/vendor/github.com/spf13/viper/util.go
+++ /dev/null
@@ -1,223 +0,0 @@
-// Copyright © 2014 Steve Francia <spf@spf13.com>.
-//
-// Use of this source code is governed by an MIT-style
-// license that can be found in the LICENSE file.
-
-// Viper is a application configuration system.
-// It believes that applications can be configured a variety of ways
-// via flags, ENVIRONMENT variables, configuration files retrieved
-// from the file system, or a remote key/value store.
-
-package viper
-
-import (
- "fmt"
- "os"
- "path/filepath"
- "runtime"
- "strings"
- "unicode"
-
- slog "github.com/sagikazarmark/slog-shim"
- "github.com/spf13/cast"
-)
-
-// ConfigParseError denotes failing to parse configuration file.
-type ConfigParseError struct {
- err error
-}
-
-// Error returns the formatted configuration error.
-func (pe ConfigParseError) Error() string {
- return fmt.Sprintf("While parsing config: %s", pe.err.Error())
-}
-
-// Unwrap returns the wrapped error.
-func (pe ConfigParseError) Unwrap() error {
- return pe.err
-}
-
-// toCaseInsensitiveValue checks if the value is a map;
-// if so, create a copy and lower-case the keys recursively.
-func toCaseInsensitiveValue(value any) any {
- switch v := value.(type) {
- case map[any]any:
- value = copyAndInsensitiviseMap(cast.ToStringMap(v))
- case map[string]any:
- value = copyAndInsensitiviseMap(v)
- }
-
- return value
-}
-
-// copyAndInsensitiviseMap behaves like insensitiviseMap, but creates a copy of
-// any map it makes case insensitive.
-func copyAndInsensitiviseMap(m map[string]any) map[string]any {
- nm := make(map[string]any)
-
- for key, val := range m {
- lkey := strings.ToLower(key)
- switch v := val.(type) {
- case map[any]any:
- nm[lkey] = copyAndInsensitiviseMap(cast.ToStringMap(v))
- case map[string]any:
- nm[lkey] = copyAndInsensitiviseMap(v)
- default:
- nm[lkey] = v
- }
- }
-
- return nm
-}
-
-func insensitiviseVal(val any) any {
- switch v := val.(type) {
- case map[any]any:
- // nested map: cast and recursively insensitivise
- val = cast.ToStringMap(val)
- insensitiviseMap(val.(map[string]any))
- case map[string]any:
- // nested map: recursively insensitivise
- insensitiviseMap(v)
- case []any:
- // nested array: recursively insensitivise
- insensitiveArray(v)
- }
- return val
-}
-
-func insensitiviseMap(m map[string]any) {
- for key, val := range m {
- val = insensitiviseVal(val)
- lower := strings.ToLower(key)
- if key != lower {
- // remove old key (not lower-cased)
- delete(m, key)
- }
- // update map
- m[lower] = val
- }
-}
-
-func insensitiveArray(a []any) {
- for i, val := range a {
- a[i] = insensitiviseVal(val)
- }
-}
-
-func absPathify(logger *slog.Logger, inPath string) string {
- logger.Info("trying to resolve absolute path", "path", inPath)
-
- if inPath == "$HOME" || strings.HasPrefix(inPath, "$HOME"+string(os.PathSeparator)) {
- inPath = userHomeDir() + inPath[5:]
- }
-
- inPath = os.ExpandEnv(inPath)
-
- if filepath.IsAbs(inPath) {
- return filepath.Clean(inPath)
- }
-
- p, err := filepath.Abs(inPath)
- if err == nil {
- return filepath.Clean(p)
- }
-
- logger.Error(fmt.Errorf("could not discover absolute path: %w", err).Error())
-
- return ""
-}
-
-func stringInSlice(a string, list []string) bool {
- for _, b := range list {
- if b == a {
- return true
- }
- }
- return false
-}
-
-func userHomeDir() string {
- if runtime.GOOS == "windows" {
- home := os.Getenv("HOMEDRIVE") + os.Getenv("HOMEPATH")
- if home == "" {
- home = os.Getenv("USERPROFILE")
- }
- return home
- }
- return os.Getenv("HOME")
-}
-
-func safeMul(a, b uint) uint {
- c := a * b
- if a > 1 && b > 1 && c/b != a {
- return 0
- }
- return c
-}
-
-// parseSizeInBytes converts strings like 1GB or 12 mb into an unsigned integer number of bytes.
-func parseSizeInBytes(sizeStr string) uint {
- sizeStr = strings.TrimSpace(sizeStr)
- lastChar := len(sizeStr) - 1
- multiplier := uint(1)
-
- if lastChar > 0 {
- if sizeStr[lastChar] == 'b' || sizeStr[lastChar] == 'B' {
- if lastChar > 1 {
- switch unicode.ToLower(rune(sizeStr[lastChar-1])) {
- case 'k':
- multiplier = 1 << 10
- sizeStr = strings.TrimSpace(sizeStr[:lastChar-1])
- case 'm':
- multiplier = 1 << 20
- sizeStr = strings.TrimSpace(sizeStr[:lastChar-1])
- case 'g':
- multiplier = 1 << 30
- sizeStr = strings.TrimSpace(sizeStr[:lastChar-1])
- default:
- multiplier = 1
- sizeStr = strings.TrimSpace(sizeStr[:lastChar])
- }
- }
- }
- }
-
- size := cast.ToInt(sizeStr)
- if size < 0 {
- size = 0
- }
-
- return safeMul(uint(size), multiplier)
-}
-
-// deepSearch scans deep maps, following the key indexes listed in the
-// sequence "path".
-// The last value is expected to be another map, and is returned.
-//
-// In case intermediate keys do not exist, or map to a non-map value,
-// a new map is created and inserted, and the search continues from there:
-// the initial map "m" may be modified!
-func deepSearch(m map[string]any, path []string) map[string]any {
- for _, k := range path {
- m2, ok := m[k]
- if !ok {
- // intermediate key does not exist
- // => create it and continue from there
- m3 := make(map[string]any)
- m[k] = m3
- m = m3
- continue
- }
- m3, ok := m2.(map[string]any)
- if !ok {
- // intermediate key is a value
- // => replace with a new map
- m3 = make(map[string]any)
- m[k] = m3
- }
- // continue search from here
- m = m3
- }
- return m
-}
diff --git a/vendor/github.com/spf13/viper/viper.go b/vendor/github.com/spf13/viper/viper.go
deleted file mode 100644
index da68d9944..000000000
--- a/vendor/github.com/spf13/viper/viper.go
+++ /dev/null
@@ -1,2252 +0,0 @@
-// Copyright © 2014 Steve Francia <spf@spf13.com>.
-//
-// Use of this source code is governed by an MIT-style
-// license that can be found in the LICENSE file.
-
-// Viper is an application configuration system.
-// It believes that applications can be configured a variety of ways
-// via flags, ENVIRONMENT variables, configuration files retrieved
-// from the file system, or a remote key/value store.
-
-// Each item takes precedence over the item below it:
-
-// overrides
-// flag
-// env
-// config
-// key/value store
-// default
-
-package viper
-
-import (
- "bytes"
- "encoding/csv"
- "errors"
- "fmt"
- "io"
- "os"
- "path/filepath"
- "reflect"
- "strconv"
- "strings"
- "sync"
- "time"
-
- "github.com/fsnotify/fsnotify"
- "github.com/mitchellh/mapstructure"
- slog "github.com/sagikazarmark/slog-shim"
- "github.com/spf13/afero"
- "github.com/spf13/cast"
- "github.com/spf13/pflag"
-
- "github.com/spf13/viper/internal/encoding"
- "github.com/spf13/viper/internal/encoding/dotenv"
- "github.com/spf13/viper/internal/encoding/hcl"
- "github.com/spf13/viper/internal/encoding/ini"
- "github.com/spf13/viper/internal/encoding/javaproperties"
- "github.com/spf13/viper/internal/encoding/json"
- "github.com/spf13/viper/internal/encoding/toml"
- "github.com/spf13/viper/internal/encoding/yaml"
- "github.com/spf13/viper/internal/features"
-)
-
-// ConfigMarshalError happens when failing to marshal the configuration.
-type ConfigMarshalError struct {
- err error
-}
-
-// Error returns the formatted configuration error.
-func (e ConfigMarshalError) Error() string {
- return fmt.Sprintf("While marshaling config: %s", e.err.Error())
-}
-
-var v *Viper
-
-type RemoteResponse struct {
- Value []byte
- Error error
-}
-
-func init() {
- v = New()
-}
-
-type remoteConfigFactory interface {
- Get(rp RemoteProvider) (io.Reader, error)
- Watch(rp RemoteProvider) (io.Reader, error)
- WatchChannel(rp RemoteProvider) (<-chan *RemoteResponse, chan bool)
-}
-
-// RemoteConfig is optional, see the remote package.
-var RemoteConfig remoteConfigFactory
-
-// UnsupportedConfigError denotes encountering an unsupported
-// configuration filetype.
-type UnsupportedConfigError string
-
-// Error returns the formatted configuration error.
-func (str UnsupportedConfigError) Error() string {
- return fmt.Sprintf("Unsupported Config Type %q", string(str))
-}
-
-// UnsupportedRemoteProviderError denotes encountering an unsupported remote
-// provider. Currently only etcd and Consul are supported.
-type UnsupportedRemoteProviderError string
-
-// Error returns the formatted remote provider error.
-func (str UnsupportedRemoteProviderError) Error() string {
- return fmt.Sprintf("Unsupported Remote Provider Type %q", string(str))
-}
-
-// RemoteConfigError denotes encountering an error while trying to
-// pull the configuration from the remote provider.
-type RemoteConfigError string
-
-// Error returns the formatted remote provider error.
-func (rce RemoteConfigError) Error() string {
- return fmt.Sprintf("Remote Configurations Error: %s", string(rce))
-}
-
-// ConfigFileNotFoundError denotes failing to find configuration file.
-type ConfigFileNotFoundError struct {
- name, locations string
-}
-
-// Error returns the formatted configuration error.
-func (fnfe ConfigFileNotFoundError) Error() string {
- return fmt.Sprintf("Config File %q Not Found in %q", fnfe.name, fnfe.locations)
-}
-
-// ConfigFileAlreadyExistsError denotes failure to write new configuration file.
-type ConfigFileAlreadyExistsError string
-
-// Error returns the formatted error when configuration already exists.
-func (faee ConfigFileAlreadyExistsError) Error() string {
- return fmt.Sprintf("Config File %q Already Exists", string(faee))
-}
-
-// A DecoderConfigOption can be passed to viper.Unmarshal to configure
-// mapstructure.DecoderConfig options.
-type DecoderConfigOption func(*mapstructure.DecoderConfig)
-
-// DecodeHook returns a DecoderConfigOption which overrides the default
-// DecoderConfig.DecodeHook value, the default is:
-//
-// mapstructure.ComposeDecodeHookFunc(
-// mapstructure.StringToTimeDurationHookFunc(),
-// mapstructure.StringToSliceHookFunc(","),
-// )
-func DecodeHook(hook mapstructure.DecodeHookFunc) DecoderConfigOption {
- return func(c *mapstructure.DecoderConfig) {
- c.DecodeHook = hook
- }
-}
-
-// Viper is a prioritized configuration registry. It
-// maintains a set of configuration sources, fetches
-// values to populate those, and provides them according
-// to the source's priority.
-// The priority of the sources is the following:
-// 1. overrides
-// 2. flags
-// 3. env. variables
-// 4. config file
-// 5. key/value store
-// 6. defaults
-//
-// For example, if values from the following sources were loaded:
-//
-// Defaults : {
-// "secret": "",
-// "user": "default",
-// "endpoint": "https://localhost"
-// }
-// Config : {
-// "user": "root"
-// "secret": "defaultsecret"
-// }
-// Env : {
-// "secret": "somesecretkey"
-// }
-//
-// The resulting config will have the following values:
-//
-// {
-// "secret": "somesecretkey",
-// "user": "root",
-// "endpoint": "https://localhost"
-// }
-//
-// Note: Vipers are not safe for concurrent Get() and Set() operations.
-type Viper struct {
- // Delimiter that separates a list of keys
- // used to access a nested value in one go
- keyDelim string
-
- // A set of paths to look for the config file in
- configPaths []string
-
- // The filesystem to read config from.
- fs afero.Fs
-
- // A set of remote providers to search for the configuration
- remoteProviders []*defaultRemoteProvider
-
- // Name of file to look for inside the path
- configName string
- configFile string
- configType string
- configPermissions os.FileMode
- envPrefix string
-
- // Specific commands for ini parsing
- iniLoadOptions ini.LoadOptions
-
- automaticEnvApplied bool
- envKeyReplacer StringReplacer
- allowEmptyEnv bool
-
- parents []string
- config map[string]any
- override map[string]any
- defaults map[string]any
- kvstore map[string]any
- pflags map[string]FlagValue
- env map[string][]string
- aliases map[string]string
- typeByDefValue bool
-
- onConfigChange func(fsnotify.Event)
-
- logger *slog.Logger
-
- // TODO: should probably be protected with a mutex
- encoderRegistry *encoding.EncoderRegistry
- decoderRegistry *encoding.DecoderRegistry
-}
-
-// New returns an initialized Viper instance.
-func New() *Viper {
- v := new(Viper)
- v.keyDelim = "."
- v.configName = "config"
- v.configPermissions = os.FileMode(0o644)
- v.fs = afero.NewOsFs()
- v.config = make(map[string]any)
- v.parents = []string{}
- v.override = make(map[string]any)
- v.defaults = make(map[string]any)
- v.kvstore = make(map[string]any)
- v.pflags = make(map[string]FlagValue)
- v.env = make(map[string][]string)
- v.aliases = make(map[string]string)
- v.typeByDefValue = false
- v.logger = slog.New(&discardHandler{})
-
- v.resetEncoding()
-
- return v
-}
-
-// Option configures Viper using the functional options paradigm popularized by Rob Pike and Dave Cheney.
-// If you're unfamiliar with this style,
-// see https://commandcenter.blogspot.com/2014/01/self-referential-functions-and-design.html and
-// https://dave.cheney.net/2014/10/17/functional-options-for-friendly-apis.
-type Option interface {
- apply(v *Viper)
-}
-
-type optionFunc func(v *Viper)
-
-func (fn optionFunc) apply(v *Viper) {
- fn(v)
-}
-
-// KeyDelimiter sets the delimiter used for determining key parts.
-// By default it's value is ".".
-func KeyDelimiter(d string) Option {
- return optionFunc(func(v *Viper) {
- v.keyDelim = d
- })
-}
-
-// StringReplacer applies a set of replacements to a string.
-type StringReplacer interface {
- // Replace returns a copy of s with all replacements performed.
- Replace(s string) string
-}
-
-// EnvKeyReplacer sets a replacer used for mapping environment variables to internal keys.
-func EnvKeyReplacer(r StringReplacer) Option {
- return optionFunc(func(v *Viper) {
- v.envKeyReplacer = r
- })
-}
-
-// NewWithOptions creates a new Viper instance.
-func NewWithOptions(opts ...Option) *Viper {
- v := New()
-
- for _, opt := range opts {
- opt.apply(v)
- }
-
- v.resetEncoding()
-
- return v
-}
-
-// Reset is intended for testing, will reset all to default settings.
-// In the public interface for the viper package so applications
-// can use it in their testing as well.
-func Reset() {
- v = New()
- SupportedExts = []string{"json", "toml", "yaml", "yml", "properties", "props", "prop", "hcl", "tfvars", "dotenv", "env", "ini"}
- SupportedRemoteProviders = []string{"etcd", "etcd3", "consul", "firestore", "nats"}
-}
-
-// TODO: make this lazy initialization instead.
-func (v *Viper) resetEncoding() {
- encoderRegistry := encoding.NewEncoderRegistry()
- decoderRegistry := encoding.NewDecoderRegistry()
-
- {
- codec := yaml.Codec{}
-
- encoderRegistry.RegisterEncoder("yaml", codec)
- decoderRegistry.RegisterDecoder("yaml", codec)
-
- encoderRegistry.RegisterEncoder("yml", codec)
- decoderRegistry.RegisterDecoder("yml", codec)
- }
-
- {
- codec := json.Codec{}
-
- encoderRegistry.RegisterEncoder("json", codec)
- decoderRegistry.RegisterDecoder("json", codec)
- }
-
- {
- codec := toml.Codec{}
-
- encoderRegistry.RegisterEncoder("toml", codec)
- decoderRegistry.RegisterDecoder("toml", codec)
- }
-
- {
- codec := hcl.Codec{}
-
- encoderRegistry.RegisterEncoder("hcl", codec)
- decoderRegistry.RegisterDecoder("hcl", codec)
-
- encoderRegistry.RegisterEncoder("tfvars", codec)
- decoderRegistry.RegisterDecoder("tfvars", codec)
- }
-
- {
- codec := ini.Codec{
- KeyDelimiter: v.keyDelim,
- LoadOptions: v.iniLoadOptions,
- }
-
- encoderRegistry.RegisterEncoder("ini", codec)
- decoderRegistry.RegisterDecoder("ini", codec)
- }
-
- {
- codec := &javaproperties.Codec{
- KeyDelimiter: v.keyDelim,
- }
-
- encoderRegistry.RegisterEncoder("properties", codec)
- decoderRegistry.RegisterDecoder("properties", codec)
-
- encoderRegistry.RegisterEncoder("props", codec)
- decoderRegistry.RegisterDecoder("props", codec)
-
- encoderRegistry.RegisterEncoder("prop", codec)
- decoderRegistry.RegisterDecoder("prop", codec)
- }
-
- {
- codec := &dotenv.Codec{}
-
- encoderRegistry.RegisterEncoder("dotenv", codec)
- decoderRegistry.RegisterDecoder("dotenv", codec)
-
- encoderRegistry.RegisterEncoder("env", codec)
- decoderRegistry.RegisterDecoder("env", codec)
- }
-
- v.encoderRegistry = encoderRegistry
- v.decoderRegistry = decoderRegistry
-}
-
-type defaultRemoteProvider struct {
- provider string
- endpoint string
- path string
- secretKeyring string
-}
-
-func (rp defaultRemoteProvider) Provider() string {
- return rp.provider
-}
-
-func (rp defaultRemoteProvider) Endpoint() string {
- return rp.endpoint
-}
-
-func (rp defaultRemoteProvider) Path() string {
- return rp.path
-}
-
-func (rp defaultRemoteProvider) SecretKeyring() string {
- return rp.secretKeyring
-}
-
-// RemoteProvider stores the configuration necessary
-// to connect to a remote key/value store.
-// Optional secretKeyring to unencrypt encrypted values
-// can be provided.
-type RemoteProvider interface {
- Provider() string
- Endpoint() string
- Path() string
- SecretKeyring() string
-}
-
-// SupportedExts are universally supported extensions.
-var SupportedExts = []string{"json", "toml", "yaml", "yml", "properties", "props", "prop", "hcl", "tfvars", "dotenv", "env", "ini"}
-
-// SupportedRemoteProviders are universally supported remote providers.
-var SupportedRemoteProviders = []string{"etcd", "etcd3", "consul", "firestore", "nats"}
-
-// OnConfigChange sets the event handler that is called when a config file changes.
-func OnConfigChange(run func(in fsnotify.Event)) { v.OnConfigChange(run) }
-
-// OnConfigChange sets the event handler that is called when a config file changes.
-func (v *Viper) OnConfigChange(run func(in fsnotify.Event)) {
- v.onConfigChange = run
-}
-
-// WatchConfig starts watching a config file for changes.
-func WatchConfig() { v.WatchConfig() }
-
-// WatchConfig starts watching a config file for changes.
-func (v *Viper) WatchConfig() {
- initWG := sync.WaitGroup{}
- initWG.Add(1)
- go func() {
- watcher, err := fsnotify.NewWatcher()
- if err != nil {
- v.logger.Error(fmt.Sprintf("failed to create watcher: %s", err))
- os.Exit(1)
- }
- defer watcher.Close()
- // we have to watch the entire directory to pick up renames/atomic saves in a cross-platform way
- filename, err := v.getConfigFile()
- if err != nil {
- v.logger.Error(fmt.Sprintf("get config file: %s", err))
- initWG.Done()
- return
- }
-
- configFile := filepath.Clean(filename)
- configDir, _ := filepath.Split(configFile)
- realConfigFile, _ := filepath.EvalSymlinks(filename)
-
- eventsWG := sync.WaitGroup{}
- eventsWG.Add(1)
- go func() {
- for {
- select {
- case event, ok := <-watcher.Events:
- if !ok { // 'Events' channel is closed
- eventsWG.Done()
- return
- }
- currentConfigFile, _ := filepath.EvalSymlinks(filename)
- // we only care about the config file with the following cases:
- // 1 - if the config file was modified or created
- // 2 - if the real path to the config file changed (eg: k8s ConfigMap replacement)
- if (filepath.Clean(event.Name) == configFile &&
- (event.Has(fsnotify.Write) || event.Has(fsnotify.Create))) ||
- (currentConfigFile != "" && currentConfigFile != realConfigFile) {
- realConfigFile = currentConfigFile
- err := v.ReadInConfig()
- if err != nil {
- v.logger.Error(fmt.Sprintf("read config file: %s", err))
- }
- if v.onConfigChange != nil {
- v.onConfigChange(event)
- }
- } else if filepath.Clean(event.Name) == configFile && event.Has(fsnotify.Remove) {
- eventsWG.Done()
- return
- }
-
- case err, ok := <-watcher.Errors:
- if ok { // 'Errors' channel is not closed
- v.logger.Error(fmt.Sprintf("watcher error: %s", err))
- }
- eventsWG.Done()
- return
- }
- }
- }()
- watcher.Add(configDir)
- initWG.Done() // done initializing the watch in this go routine, so the parent routine can move on...
- eventsWG.Wait() // now, wait for event loop to end in this go-routine...
- }()
- initWG.Wait() // make sure that the go routine above fully ended before returning
-}
-
-// SetConfigFile explicitly defines the path, name and extension of the config file.
-// Viper will use this and not check any of the config paths.
-func SetConfigFile(in string) { v.SetConfigFile(in) }
-
-func (v *Viper) SetConfigFile(in string) {
- if in != "" {
- v.configFile = in
- }
-}
-
-// SetEnvPrefix defines a prefix that ENVIRONMENT variables will use.
-// E.g. if your prefix is "spf", the env registry will look for env
-// variables that start with "SPF_".
-func SetEnvPrefix(in string) { v.SetEnvPrefix(in) }
-
-func (v *Viper) SetEnvPrefix(in string) {
- if in != "" {
- v.envPrefix = in
- }
-}
-
-func GetEnvPrefix() string { return v.GetEnvPrefix() }
-
-func (v *Viper) GetEnvPrefix() string {
- return v.envPrefix
-}
-
-func (v *Viper) mergeWithEnvPrefix(in string) string {
- if v.envPrefix != "" {
- return strings.ToUpper(v.envPrefix + "_" + in)
- }
-
- return strings.ToUpper(in)
-}
-
-// AllowEmptyEnv tells Viper to consider set,
-// but empty environment variables as valid values instead of falling back.
-// For backward compatibility reasons this is false by default.
-func AllowEmptyEnv(allowEmptyEnv bool) { v.AllowEmptyEnv(allowEmptyEnv) }
-
-func (v *Viper) AllowEmptyEnv(allowEmptyEnv bool) {
- v.allowEmptyEnv = allowEmptyEnv
-}
-
-// TODO: should getEnv logic be moved into find(). Can generalize the use of
-// rewriting keys many things, Ex: Get('someKey') -> some_key
-// (camel case to snake case for JSON keys perhaps)
-
-// getEnv is a wrapper around os.Getenv which replaces characters in the original
-// key. This allows env vars which have different keys than the config object
-// keys.
-func (v *Viper) getEnv(key string) (string, bool) {
- if v.envKeyReplacer != nil {
- key = v.envKeyReplacer.Replace(key)
- }
-
- val, ok := os.LookupEnv(key)
-
- return val, ok && (v.allowEmptyEnv || val != "")
-}
-
-// ConfigFileUsed returns the file used to populate the config registry.
-func ConfigFileUsed() string { return v.ConfigFileUsed() }
-func (v *Viper) ConfigFileUsed() string { return v.configFile }
-
-// AddConfigPath adds a path for Viper to search for the config file in.
-// Can be called multiple times to define multiple search paths.
-func AddConfigPath(in string) { v.AddConfigPath(in) }
-
-func (v *Viper) AddConfigPath(in string) {
- if in != "" {
- absin := absPathify(v.logger, in)
-
- v.logger.Info("adding path to search paths", "path", absin)
- if !stringInSlice(absin, v.configPaths) {
- v.configPaths = append(v.configPaths, absin)
- }
- }
-}
-
-// AddRemoteProvider adds a remote configuration source.
-// Remote Providers are searched in the order they are added.
-// provider is a string value: "etcd", "etcd3", "consul", "firestore" or "nats" are currently supported.
-// endpoint is the url. etcd requires http://ip:port, consul requires ip:port, nats requires nats://ip:port
-// path is the path in the k/v store to retrieve configuration
-// To retrieve a config file called myapp.json from /configs/myapp.json
-// you should set path to /configs and set config name (SetConfigName()) to
-// "myapp".
-func AddRemoteProvider(provider, endpoint, path string) error {
- return v.AddRemoteProvider(provider, endpoint, path)
-}
-
-func (v *Viper) AddRemoteProvider(provider, endpoint, path string) error {
- if !stringInSlice(provider, SupportedRemoteProviders) {
- return UnsupportedRemoteProviderError(provider)
- }
- if provider != "" && endpoint != "" {
- v.logger.Info("adding remote provider", "provider", provider, "endpoint", endpoint)
-
- rp := &defaultRemoteProvider{
- endpoint: endpoint,
- provider: provider,
- path: path,
- }
- if !v.providerPathExists(rp) {
- v.remoteProviders = append(v.remoteProviders, rp)
- }
- }
- return nil
-}
-
-// AddSecureRemoteProvider adds a remote configuration source.
-// Secure Remote Providers are searched in the order they are added.
-// provider is a string value: "etcd", "etcd3", "consul", "firestore" or "nats" are currently supported.
-// endpoint is the url. etcd requires http://ip:port consul requires ip:port
-// secretkeyring is the filepath to your openpgp secret keyring. e.g. /etc/secrets/myring.gpg
-// path is the path in the k/v store to retrieve configuration
-// To retrieve a config file called myapp.json from /configs/myapp.json
-// you should set path to /configs and set config name (SetConfigName()) to
-// "myapp".
-// Secure Remote Providers are implemented with github.com/sagikazarmark/crypt.
-func AddSecureRemoteProvider(provider, endpoint, path, secretkeyring string) error {
- return v.AddSecureRemoteProvider(provider, endpoint, path, secretkeyring)
-}
-
-func (v *Viper) AddSecureRemoteProvider(provider, endpoint, path, secretkeyring string) error {
- if !stringInSlice(provider, SupportedRemoteProviders) {
- return UnsupportedRemoteProviderError(provider)
- }
- if provider != "" && endpoint != "" {
- v.logger.Info("adding remote provider", "provider", provider, "endpoint", endpoint)
-
- rp := &defaultRemoteProvider{
- endpoint: endpoint,
- provider: provider,
- path: path,
- secretKeyring: secretkeyring,
- }
- if !v.providerPathExists(rp) {
- v.remoteProviders = append(v.remoteProviders, rp)
- }
- }
- return nil
-}
-
-func (v *Viper) providerPathExists(p *defaultRemoteProvider) bool {
- for _, y := range v.remoteProviders {
- if reflect.DeepEqual(y, p) {
- return true
- }
- }
- return false
-}
-
-// searchMap recursively searches for a value for path in source map.
-// Returns nil if not found.
-// Note: This assumes that the path entries and map keys are lower cased.
-func (v *Viper) searchMap(source map[string]any, path []string) any {
- if len(path) == 0 {
- return source
- }
-
- next, ok := source[path[0]]
- if ok {
- // Fast path
- if len(path) == 1 {
- return next
- }
-
- // Nested case
- switch next := next.(type) {
- case map[any]any:
- return v.searchMap(cast.ToStringMap(next), path[1:])
- case map[string]any:
- // Type assertion is safe here since it is only reached
- // if the type of `next` is the same as the type being asserted
- return v.searchMap(next, path[1:])
- default:
- // got a value but nested key expected, return "nil" for not found
- return nil
- }
- }
- return nil
-}
-
-// searchIndexableWithPathPrefixes recursively searches for a value for path in source map/slice.
-//
-// While searchMap() considers each path element as a single map key or slice index, this
-// function searches for, and prioritizes, merged path elements.
-// e.g., if in the source, "foo" is defined with a sub-key "bar", and "foo.bar"
-// is also defined, this latter value is returned for path ["foo", "bar"].
-//
-// This should be useful only at config level (other maps may not contain dots
-// in their keys).
-//
-// Note: This assumes that the path entries and map keys are lower cased.
-func (v *Viper) searchIndexableWithPathPrefixes(source any, path []string) any {
- if len(path) == 0 {
- return source
- }
-
- // search for path prefixes, starting from the longest one
- for i := len(path); i > 0; i-- {
- prefixKey := strings.ToLower(strings.Join(path[0:i], v.keyDelim))
-
- var val any
- switch sourceIndexable := source.(type) {
- case []any:
- val = v.searchSliceWithPathPrefixes(sourceIndexable, prefixKey, i, path)
- case map[string]any:
- val = v.searchMapWithPathPrefixes(sourceIndexable, prefixKey, i, path)
- }
- if val != nil {
- return val
- }
- }
-
- // not found
- return nil
-}
-
-// searchSliceWithPathPrefixes searches for a value for path in sourceSlice
-//
-// This function is part of the searchIndexableWithPathPrefixes recurring search and
-// should not be called directly from functions other than searchIndexableWithPathPrefixes.
-func (v *Viper) searchSliceWithPathPrefixes(
- sourceSlice []any,
- prefixKey string,
- pathIndex int,
- path []string,
-) any {
- // if the prefixKey is not a number or it is out of bounds of the slice
- index, err := strconv.Atoi(prefixKey)
- if err != nil || len(sourceSlice) <= index {
- return nil
- }
-
- next := sourceSlice[index]
-
- // Fast path
- if pathIndex == len(path) {
- return next
- }
-
- switch n := next.(type) {
- case map[any]any:
- return v.searchIndexableWithPathPrefixes(cast.ToStringMap(n), path[pathIndex:])
- case map[string]any, []any:
- return v.searchIndexableWithPathPrefixes(n, path[pathIndex:])
- default:
- // got a value but nested key expected, do nothing and look for next prefix
- }
-
- // not found
- return nil
-}
-
-// searchMapWithPathPrefixes searches for a value for path in sourceMap
-//
-// This function is part of the searchIndexableWithPathPrefixes recurring search and
-// should not be called directly from functions other than searchIndexableWithPathPrefixes.
-func (v *Viper) searchMapWithPathPrefixes(
- sourceMap map[string]any,
- prefixKey string,
- pathIndex int,
- path []string,
-) any {
- next, ok := sourceMap[prefixKey]
- if !ok {
- return nil
- }
-
- // Fast path
- if pathIndex == len(path) {
- return next
- }
-
- // Nested case
- switch n := next.(type) {
- case map[any]any:
- return v.searchIndexableWithPathPrefixes(cast.ToStringMap(n), path[pathIndex:])
- case map[string]any, []any:
- return v.searchIndexableWithPathPrefixes(n, path[pathIndex:])
- default:
- // got a value but nested key expected, do nothing and look for next prefix
- }
-
- // not found
- return nil
-}
-
-// isPathShadowedInDeepMap makes sure the given path is not shadowed somewhere
-// on its path in the map.
-// e.g., if "foo.bar" has a value in the given map, it “shadows”
-//
-// "foo.bar.baz" in a lower-priority map
-func (v *Viper) isPathShadowedInDeepMap(path []string, m map[string]any) string {
- var parentVal any
- for i := 1; i < len(path); i++ {
- parentVal = v.searchMap(m, path[0:i])
- if parentVal == nil {
- // not found, no need to add more path elements
- return ""
- }
- switch parentVal.(type) {
- case map[any]any:
- continue
- case map[string]any:
- continue
- default:
- // parentVal is a regular value which shadows "path"
- return strings.Join(path[0:i], v.keyDelim)
- }
- }
- return ""
-}
-
-// isPathShadowedInFlatMap makes sure the given path is not shadowed somewhere
-// in a sub-path of the map.
-// e.g., if "foo.bar" has a value in the given map, it “shadows”
-//
-// "foo.bar.baz" in a lower-priority map
-func (v *Viper) isPathShadowedInFlatMap(path []string, mi any) string {
- // unify input map
- var m map[string]interface{}
- switch miv := mi.(type) {
- case map[string]string:
- m = castMapStringToMapInterface(miv)
- case map[string]FlagValue:
- m = castMapFlagToMapInterface(miv)
- default:
- return ""
- }
-
- // scan paths
- var parentKey string
- for i := 1; i < len(path); i++ {
- parentKey = strings.Join(path[0:i], v.keyDelim)
- if _, ok := m[parentKey]; ok {
- return parentKey
- }
- }
- return ""
-}
-
-// isPathShadowedInAutoEnv makes sure the given path is not shadowed somewhere
-// in the environment, when automatic env is on.
-// e.g., if "foo.bar" has a value in the environment, it “shadows”
-//
-// "foo.bar.baz" in a lower-priority map
-func (v *Viper) isPathShadowedInAutoEnv(path []string) string {
- var parentKey string
- for i := 1; i < len(path); i++ {
- parentKey = strings.Join(path[0:i], v.keyDelim)
- if _, ok := v.getEnv(v.mergeWithEnvPrefix(parentKey)); ok {
- return parentKey
- }
- }
- return ""
-}
-
-// SetTypeByDefaultValue enables or disables the inference of a key value's
-// type when the Get function is used based upon a key's default value as
-// opposed to the value returned based on the normal fetch logic.
-//
-// For example, if a key has a default value of []string{} and the same key
-// is set via an environment variable to "a b c", a call to the Get function
-// would return a string slice for the key if the key's type is inferred by
-// the default value and the Get function would return:
-//
-// []string {"a", "b", "c"}
-//
-// Otherwise the Get function would return:
-//
-// "a b c"
-func SetTypeByDefaultValue(enable bool) { v.SetTypeByDefaultValue(enable) }
-
-func (v *Viper) SetTypeByDefaultValue(enable bool) {
- v.typeByDefValue = enable
-}
-
-// GetViper gets the global Viper instance.
-func GetViper() *Viper {
- return v
-}
-
-// Get can retrieve any value given the key to use.
-// Get is case-insensitive for a key.
-// Get has the behavior of returning the value associated with the first
-// place from where it is set. Viper will check in the following order:
-// override, flag, env, config file, key/value store, default
-//
-// Get returns an interface. For a specific value use one of the Get____ methods.
-func Get(key string) any { return v.Get(key) }
-
-func (v *Viper) Get(key string) any {
- lcaseKey := strings.ToLower(key)
- val := v.find(lcaseKey, true)
- if val == nil {
- return nil
- }
-
- if v.typeByDefValue {
- // TODO(bep) this branch isn't covered by a single test.
- valType := val
- path := strings.Split(lcaseKey, v.keyDelim)
- defVal := v.searchMap(v.defaults, path)
- if defVal != nil {
- valType = defVal
- }
-
- switch valType.(type) {
- case bool:
- return cast.ToBool(val)
- case string:
- return cast.ToString(val)
- case int32, int16, int8, int:
- return cast.ToInt(val)
- case uint:
- return cast.ToUint(val)
- case uint32:
- return cast.ToUint32(val)
- case uint64:
- return cast.ToUint64(val)
- case int64:
- return cast.ToInt64(val)
- case float64, float32:
- return cast.ToFloat64(val)
- case time.Time:
- return cast.ToTime(val)
- case time.Duration:
- return cast.ToDuration(val)
- case []string:
- return cast.ToStringSlice(val)
- case []int:
- return cast.ToIntSlice(val)
- case []time.Duration:
- return cast.ToDurationSlice(val)
- }
- }
-
- return val
-}
-
-// Sub returns new Viper instance representing a sub tree of this instance.
-// Sub is case-insensitive for a key.
-func Sub(key string) *Viper { return v.Sub(key) }
-
-func (v *Viper) Sub(key string) *Viper {
- subv := New()
- data := v.Get(key)
- if data == nil {
- return nil
- }
-
- if reflect.TypeOf(data).Kind() == reflect.Map {
- subv.parents = append([]string(nil), v.parents...)
- subv.parents = append(subv.parents, strings.ToLower(key))
- subv.automaticEnvApplied = v.automaticEnvApplied
- subv.envPrefix = v.envPrefix
- subv.envKeyReplacer = v.envKeyReplacer
- subv.config = cast.ToStringMap(data)
- return subv
- }
- return nil
-}
-
-// GetString returns the value associated with the key as a string.
-func GetString(key string) string { return v.GetString(key) }
-
-func (v *Viper) GetString(key string) string {
- return cast.ToString(v.Get(key))
-}
-
-// GetBool returns the value associated with the key as a boolean.
-func GetBool(key string) bool { return v.GetBool(key) }
-
-func (v *Viper) GetBool(key string) bool {
- return cast.ToBool(v.Get(key))
-}
-
-// GetInt returns the value associated with the key as an integer.
-func GetInt(key string) int { return v.GetInt(key) }
-
-func (v *Viper) GetInt(key string) int {
- return cast.ToInt(v.Get(key))
-}
-
-// GetInt32 returns the value associated with the key as an integer.
-func GetInt32(key string) int32 { return v.GetInt32(key) }
-
-func (v *Viper) GetInt32(key string) int32 {
- return cast.ToInt32(v.Get(key))
-}
-
-// GetInt64 returns the value associated with the key as an integer.
-func GetInt64(key string) int64 { return v.GetInt64(key) }
-
-func (v *Viper) GetInt64(key string) int64 {
- return cast.ToInt64(v.Get(key))
-}
-
-// GetUint returns the value associated with the key as an unsigned integer.
-func GetUint(key string) uint { return v.GetUint(key) }
-
-func (v *Viper) GetUint(key string) uint {
- return cast.ToUint(v.Get(key))
-}
-
-// GetUint16 returns the value associated with the key as an unsigned integer.
-func GetUint16(key string) uint16 { return v.GetUint16(key) }
-
-func (v *Viper) GetUint16(key string) uint16 {
- return cast.ToUint16(v.Get(key))
-}
-
-// GetUint32 returns the value associated with the key as an unsigned integer.
-func GetUint32(key string) uint32 { return v.GetUint32(key) }
-
-func (v *Viper) GetUint32(key string) uint32 {
- return cast.ToUint32(v.Get(key))
-}
-
-// GetUint64 returns the value associated with the key as an unsigned integer.
-func GetUint64(key string) uint64 { return v.GetUint64(key) }
-
-func (v *Viper) GetUint64(key string) uint64 {
- return cast.ToUint64(v.Get(key))
-}
-
-// GetFloat64 returns the value associated with the key as a float64.
-func GetFloat64(key string) float64 { return v.GetFloat64(key) }
-
-func (v *Viper) GetFloat64(key string) float64 {
- return cast.ToFloat64(v.Get(key))
-}
-
-// GetTime returns the value associated with the key as time.
-func GetTime(key string) time.Time { return v.GetTime(key) }
-
-func (v *Viper) GetTime(key string) time.Time {
- return cast.ToTime(v.Get(key))
-}
-
-// GetDuration returns the value associated with the key as a duration.
-func GetDuration(key string) time.Duration { return v.GetDuration(key) }
-
-func (v *Viper) GetDuration(key string) time.Duration {
- return cast.ToDuration(v.Get(key))
-}
-
-// GetIntSlice returns the value associated with the key as a slice of int values.
-func GetIntSlice(key string) []int { return v.GetIntSlice(key) }
-
-func (v *Viper) GetIntSlice(key string) []int {
- return cast.ToIntSlice(v.Get(key))
-}
-
-// GetStringSlice returns the value associated with the key as a slice of strings.
-func GetStringSlice(key string) []string { return v.GetStringSlice(key) }
-
-func (v *Viper) GetStringSlice(key string) []string {
- return cast.ToStringSlice(v.Get(key))
-}
-
-// GetStringMap returns the value associated with the key as a map of interfaces.
-func GetStringMap(key string) map[string]any { return v.GetStringMap(key) }
-
-func (v *Viper) GetStringMap(key string) map[string]any {
- return cast.ToStringMap(v.Get(key))
-}
-
-// GetStringMapString returns the value associated with the key as a map of strings.
-func GetStringMapString(key string) map[string]string { return v.GetStringMapString(key) }
-
-func (v *Viper) GetStringMapString(key string) map[string]string {
- return cast.ToStringMapString(v.Get(key))
-}
-
-// GetStringMapStringSlice returns the value associated with the key as a map to a slice of strings.
-func GetStringMapStringSlice(key string) map[string][]string { return v.GetStringMapStringSlice(key) }
-
-func (v *Viper) GetStringMapStringSlice(key string) map[string][]string {
- return cast.ToStringMapStringSlice(v.Get(key))
-}
-
-// GetSizeInBytes returns the size of the value associated with the given key
-// in bytes.
-func GetSizeInBytes(key string) uint { return v.GetSizeInBytes(key) }
-
-func (v *Viper) GetSizeInBytes(key string) uint {
- sizeStr := cast.ToString(v.Get(key))
- return parseSizeInBytes(sizeStr)
-}
-
-// UnmarshalKey takes a single key and unmarshals it into a Struct.
-func UnmarshalKey(key string, rawVal any, opts ...DecoderConfigOption) error {
- return v.UnmarshalKey(key, rawVal, opts...)
-}
-
-func (v *Viper) UnmarshalKey(key string, rawVal any, opts ...DecoderConfigOption) error {
- return decode(v.Get(key), defaultDecoderConfig(rawVal, opts...))
-}
-
-// Unmarshal unmarshals the config into a Struct. Make sure that the tags
-// on the fields of the structure are properly set.
-func Unmarshal(rawVal any, opts ...DecoderConfigOption) error {
- return v.Unmarshal(rawVal, opts...)
-}
-
-func (v *Viper) Unmarshal(rawVal any, opts ...DecoderConfigOption) error {
- keys := v.AllKeys()
-
- if features.BindStruct {
- // TODO: make this optional?
- structKeys, err := v.decodeStructKeys(rawVal, opts...)
- if err != nil {
- return err
- }
-
- keys = append(keys, structKeys...)
- }
-
- // TODO: struct keys should be enough?
- return decode(v.getSettings(keys), defaultDecoderConfig(rawVal, opts...))
-}
-
-func (v *Viper) decodeStructKeys(input any, opts ...DecoderConfigOption) ([]string, error) {
- var structKeyMap map[string]any
-
- err := decode(input, defaultDecoderConfig(&structKeyMap, opts...))
- if err != nil {
- return nil, err
- }
-
- flattenedStructKeyMap := v.flattenAndMergeMap(map[string]bool{}, structKeyMap, "")
-
- r := make([]string, 0, len(flattenedStructKeyMap))
- for v := range flattenedStructKeyMap {
- r = append(r, v)
- }
-
- return r, nil
-}
-
-// defaultDecoderConfig returns default mapstructure.DecoderConfig with support
-// of time.Duration values & string slices.
-func defaultDecoderConfig(output any, opts ...DecoderConfigOption) *mapstructure.DecoderConfig {
- c := &mapstructure.DecoderConfig{
- Metadata: nil,
- Result: output,
- WeaklyTypedInput: true,
- DecodeHook: mapstructure.ComposeDecodeHookFunc(
- mapstructure.StringToTimeDurationHookFunc(),
- mapstructure.StringToSliceHookFunc(","),
- ),
- }
- for _, opt := range opts {
- opt(c)
- }
- return c
-}
-
-// decode is a wrapper around mapstructure.Decode that mimics the WeakDecode functionality.
-func decode(input any, config *mapstructure.DecoderConfig) error {
- decoder, err := mapstructure.NewDecoder(config)
- if err != nil {
- return err
- }
- return decoder.Decode(input)
-}
-
-// UnmarshalExact unmarshals the config into a Struct, erroring if a field is nonexistent
-// in the destination struct.
-func UnmarshalExact(rawVal any, opts ...DecoderConfigOption) error {
- return v.UnmarshalExact(rawVal, opts...)
-}
-
-func (v *Viper) UnmarshalExact(rawVal any, opts ...DecoderConfigOption) error {
- config := defaultDecoderConfig(rawVal, opts...)
- config.ErrorUnused = true
-
- keys := v.AllKeys()
-
- if features.BindStruct {
- // TODO: make this optional?
- structKeys, err := v.decodeStructKeys(rawVal, opts...)
- if err != nil {
- return err
- }
-
- keys = append(keys, structKeys...)
- }
-
- // TODO: struct keys should be enough?
- return decode(v.getSettings(keys), config)
-}
-
-// BindPFlags binds a full flag set to the configuration, using each flag's long
-// name as the config key.
-func BindPFlags(flags *pflag.FlagSet) error { return v.BindPFlags(flags) }
-
-func (v *Viper) BindPFlags(flags *pflag.FlagSet) error {
- return v.BindFlagValues(pflagValueSet{flags})
-}
-
-// BindPFlag binds a specific key to a pflag (as used by cobra).
-// Example (where serverCmd is a Cobra instance):
-//
-// serverCmd.Flags().Int("port", 1138, "Port to run Application server on")
-// Viper.BindPFlag("port", serverCmd.Flags().Lookup("port"))
-func BindPFlag(key string, flag *pflag.Flag) error { return v.BindPFlag(key, flag) }
-
-func (v *Viper) BindPFlag(key string, flag *pflag.Flag) error {
- if flag == nil {
- return fmt.Errorf("flag for %q is nil", key)
- }
- return v.BindFlagValue(key, pflagValue{flag})
-}
-
-// BindFlagValues binds a full FlagValue set to the configuration, using each flag's long
-// name as the config key.
-func BindFlagValues(flags FlagValueSet) error { return v.BindFlagValues(flags) }
-
-func (v *Viper) BindFlagValues(flags FlagValueSet) (err error) {
- flags.VisitAll(func(flag FlagValue) {
- if err = v.BindFlagValue(flag.Name(), flag); err != nil {
- return
- }
- })
- return nil
-}
-
-// BindFlagValue binds a specific key to a FlagValue.
-func BindFlagValue(key string, flag FlagValue) error { return v.BindFlagValue(key, flag) }
-
-func (v *Viper) BindFlagValue(key string, flag FlagValue) error {
- if flag == nil {
- return fmt.Errorf("flag for %q is nil", key)
- }
- v.pflags[strings.ToLower(key)] = flag
- return nil
-}
-
-// BindEnv binds a Viper key to a ENV variable.
-// ENV variables are case sensitive.
-// If only a key is provided, it will use the env key matching the key, uppercased.
-// If more arguments are provided, they will represent the env variable names that
-// should bind to this key and will be taken in the specified order.
-// EnvPrefix will be used when set when env name is not provided.
-func BindEnv(input ...string) error { return v.BindEnv(input...) }
-
-func (v *Viper) BindEnv(input ...string) error {
- if len(input) == 0 {
- return fmt.Errorf("missing key to bind to")
- }
-
- key := strings.ToLower(input[0])
-
- if len(input) == 1 {
- v.env[key] = append(v.env[key], v.mergeWithEnvPrefix(key))
- } else {
- v.env[key] = append(v.env[key], input[1:]...)
- }
-
- return nil
-}
-
-// MustBindEnv wraps BindEnv in a panic.
-// If there is an error binding an environment variable, MustBindEnv will
-// panic.
-func MustBindEnv(input ...string) { v.MustBindEnv(input...) }
-
-func (v *Viper) MustBindEnv(input ...string) {
- if err := v.BindEnv(input...); err != nil {
- panic(fmt.Sprintf("error while binding environment variable: %v", err))
- }
-}
-
-// Given a key, find the value.
-//
-// Viper will check to see if an alias exists first.
-// Viper will then check in the following order:
-// flag, env, config file, key/value store.
-// Lastly, if no value was found and flagDefault is true, and if the key
-// corresponds to a flag, the flag's default value is returned.
-//
-// Note: this assumes a lower-cased key given.
-func (v *Viper) find(lcaseKey string, flagDefault bool) any {
- var (
- val any
- exists bool
- path = strings.Split(lcaseKey, v.keyDelim)
- nested = len(path) > 1
- )
-
- // compute the path through the nested maps to the nested value
- if nested && v.isPathShadowedInDeepMap(path, castMapStringToMapInterface(v.aliases)) != "" {
- return nil
- }
-
- // if the requested key is an alias, then return the proper key
- lcaseKey = v.realKey(lcaseKey)
- path = strings.Split(lcaseKey, v.keyDelim)
- nested = len(path) > 1
-
- // Set() override first
- val = v.searchMap(v.override, path)
- if val != nil {
- return val
- }
- if nested && v.isPathShadowedInDeepMap(path, v.override) != "" {
- return nil
- }
-
- // PFlag override next
- flag, exists := v.pflags[lcaseKey]
- if exists && flag.HasChanged() {
- switch flag.ValueType() {
- case "int", "int8", "int16", "int32", "int64":
- return cast.ToInt(flag.ValueString())
- case "bool":
- return cast.ToBool(flag.ValueString())
- case "stringSlice", "stringArray":
- s := strings.TrimPrefix(flag.ValueString(), "[")
- s = strings.TrimSuffix(s, "]")
- res, _ := readAsCSV(s)
- return res
- case "intSlice":
- s := strings.TrimPrefix(flag.ValueString(), "[")
- s = strings.TrimSuffix(s, "]")
- res, _ := readAsCSV(s)
- return cast.ToIntSlice(res)
- case "durationSlice":
- s := strings.TrimPrefix(flag.ValueString(), "[")
- s = strings.TrimSuffix(s, "]")
- slice := strings.Split(s, ",")
- return cast.ToDurationSlice(slice)
- case "stringToString":
- return stringToStringConv(flag.ValueString())
- case "stringToInt":
- return stringToIntConv(flag.ValueString())
- default:
- return flag.ValueString()
- }
- }
- if nested && v.isPathShadowedInFlatMap(path, v.pflags) != "" {
- return nil
- }
-
- // Env override next
- if v.automaticEnvApplied {
- envKey := strings.Join(append(v.parents, lcaseKey), ".")
- // even if it hasn't been registered, if automaticEnv is used,
- // check any Get request
- if val, ok := v.getEnv(v.mergeWithEnvPrefix(envKey)); ok {
- return val
- }
- if nested && v.isPathShadowedInAutoEnv(path) != "" {
- return nil
- }
- }
- envkeys, exists := v.env[lcaseKey]
- if exists {
- for _, envkey := range envkeys {
- if val, ok := v.getEnv(envkey); ok {
- return val
- }
- }
- }
- if nested && v.isPathShadowedInFlatMap(path, v.env) != "" {
- return nil
- }
-
- // Config file next
- val = v.searchIndexableWithPathPrefixes(v.config, path)
- if val != nil {
- return val
- }
- if nested && v.isPathShadowedInDeepMap(path, v.config) != "" {
- return nil
- }
-
- // K/V store next
- val = v.searchMap(v.kvstore, path)
- if val != nil {
- return val
- }
- if nested && v.isPathShadowedInDeepMap(path, v.kvstore) != "" {
- return nil
- }
-
- // Default next
- val = v.searchMap(v.defaults, path)
- if val != nil {
- return val
- }
- if nested && v.isPathShadowedInDeepMap(path, v.defaults) != "" {
- return nil
- }
-
- if flagDefault {
- // last chance: if no value is found and a flag does exist for the key,
- // get the flag's default value even if the flag's value has not been set.
- if flag, exists := v.pflags[lcaseKey]; exists {
- switch flag.ValueType() {
- case "int", "int8", "int16", "int32", "int64":
- return cast.ToInt(flag.ValueString())
- case "bool":
- return cast.ToBool(flag.ValueString())
- case "stringSlice", "stringArray":
- s := strings.TrimPrefix(flag.ValueString(), "[")
- s = strings.TrimSuffix(s, "]")
- res, _ := readAsCSV(s)
- return res
- case "intSlice":
- s := strings.TrimPrefix(flag.ValueString(), "[")
- s = strings.TrimSuffix(s, "]")
- res, _ := readAsCSV(s)
- return cast.ToIntSlice(res)
- case "stringToString":
- return stringToStringConv(flag.ValueString())
- case "stringToInt":
- return stringToIntConv(flag.ValueString())
- case "durationSlice":
- s := strings.TrimPrefix(flag.ValueString(), "[")
- s = strings.TrimSuffix(s, "]")
- slice := strings.Split(s, ",")
- return cast.ToDurationSlice(slice)
- default:
- return flag.ValueString()
- }
- }
- // last item, no need to check shadowing
- }
-
- return nil
-}
-
-func readAsCSV(val string) ([]string, error) {
- if val == "" {
- return []string{}, nil
- }
- stringReader := strings.NewReader(val)
- csvReader := csv.NewReader(stringReader)
- return csvReader.Read()
-}
-
-// mostly copied from pflag's implementation of this operation here https://github.com/spf13/pflag/blob/master/string_to_string.go#L79
-// alterations are: errors are swallowed, map[string]any is returned in order to enable cast.ToStringMap.
-func stringToStringConv(val string) any {
- val = strings.Trim(val, "[]")
- // An empty string would cause an empty map
- if val == "" {
- return map[string]any{}
- }
- r := csv.NewReader(strings.NewReader(val))
- ss, err := r.Read()
- if err != nil {
- return nil
- }
- out := make(map[string]any, len(ss))
- for _, pair := range ss {
- k, vv, found := strings.Cut(pair, "=")
- if !found {
- return nil
- }
- out[k] = vv
- }
- return out
-}
-
-// mostly copied from pflag's implementation of this operation here https://github.com/spf13/pflag/blob/d5e0c0615acee7028e1e2740a11102313be88de1/string_to_int.go#L68
-// alterations are: errors are swallowed, map[string]any is returned in order to enable cast.ToStringMap.
-func stringToIntConv(val string) any {
- val = strings.Trim(val, "[]")
- // An empty string would cause an empty map
- if val == "" {
- return map[string]any{}
- }
- ss := strings.Split(val, ",")
- out := make(map[string]any, len(ss))
- for _, pair := range ss {
- k, vv, found := strings.Cut(pair, "=")
- if !found {
- return nil
- }
- var err error
- out[k], err = strconv.Atoi(vv)
- if err != nil {
- return nil
- }
- }
- return out
-}
-
-// IsSet checks to see if the key has been set in any of the data locations.
-// IsSet is case-insensitive for a key.
-func IsSet(key string) bool { return v.IsSet(key) }
-
-func (v *Viper) IsSet(key string) bool {
- lcaseKey := strings.ToLower(key)
- val := v.find(lcaseKey, false)
- return val != nil
-}
-
-// AutomaticEnv makes Viper check if environment variables match any of the existing keys
-// (config, default or flags). If matching env vars are found, they are loaded into Viper.
-func AutomaticEnv() { v.AutomaticEnv() }
-
-func (v *Viper) AutomaticEnv() {
- v.automaticEnvApplied = true
-}
-
-// SetEnvKeyReplacer sets the strings.Replacer on the viper object
-// Useful for mapping an environmental variable to a key that does
-// not match it.
-func SetEnvKeyReplacer(r *strings.Replacer) { v.SetEnvKeyReplacer(r) }
-
-func (v *Viper) SetEnvKeyReplacer(r *strings.Replacer) {
- v.envKeyReplacer = r
-}
-
-// RegisterAlias creates an alias that provides another accessor for the same key.
-// This enables one to change a name without breaking the application.
-func RegisterAlias(alias, key string) { v.RegisterAlias(alias, key) }
-
-func (v *Viper) RegisterAlias(alias, key string) {
- v.registerAlias(alias, strings.ToLower(key))
-}
-
-func (v *Viper) registerAlias(alias, key string) {
- alias = strings.ToLower(alias)
- if alias != key && alias != v.realKey(key) {
- _, exists := v.aliases[alias]
-
- if !exists {
- // if we alias something that exists in one of the maps to another
- // name, we'll never be able to get that value using the original
- // name, so move the config value to the new realkey.
- if val, ok := v.config[alias]; ok {
- delete(v.config, alias)
- v.config[key] = val
- }
- if val, ok := v.kvstore[alias]; ok {
- delete(v.kvstore, alias)
- v.kvstore[key] = val
- }
- if val, ok := v.defaults[alias]; ok {
- delete(v.defaults, alias)
- v.defaults[key] = val
- }
- if val, ok := v.override[alias]; ok {
- delete(v.override, alias)
- v.override[key] = val
- }
- v.aliases[alias] = key
- }
- } else {
- v.logger.Warn("creating circular reference alias", "alias", alias, "key", key, "real_key", v.realKey(key))
- }
-}
-
-func (v *Viper) realKey(key string) string {
- newkey, exists := v.aliases[key]
- if exists {
- v.logger.Debug("key is an alias", "alias", key, "to", newkey)
-
- return v.realKey(newkey)
- }
- return key
-}
-
-// InConfig checks to see if the given key (or an alias) is in the config file.
-func InConfig(key string) bool { return v.InConfig(key) }
-
-func (v *Viper) InConfig(key string) bool {
- lcaseKey := strings.ToLower(key)
-
- // if the requested key is an alias, then return the proper key
- lcaseKey = v.realKey(lcaseKey)
- path := strings.Split(lcaseKey, v.keyDelim)
-
- return v.searchIndexableWithPathPrefixes(v.config, path) != nil
-}
-
-// SetDefault sets the default value for this key.
-// SetDefault is case-insensitive for a key.
-// Default only used when no value is provided by the user via flag, config or ENV.
-func SetDefault(key string, value any) { v.SetDefault(key, value) }
-
-func (v *Viper) SetDefault(key string, value any) {
- // If alias passed in, then set the proper default
- key = v.realKey(strings.ToLower(key))
- value = toCaseInsensitiveValue(value)
-
- path := strings.Split(key, v.keyDelim)
- lastKey := strings.ToLower(path[len(path)-1])
- deepestMap := deepSearch(v.defaults, path[0:len(path)-1])
-
- // set innermost value
- deepestMap[lastKey] = value
-}
-
-// Set sets the value for the key in the override register.
-// Set is case-insensitive for a key.
-// Will be used instead of values obtained via
-// flags, config file, ENV, default, or key/value store.
-func Set(key string, value any) { v.Set(key, value) }
-
-func (v *Viper) Set(key string, value any) {
- // If alias passed in, then set the proper override
- key = v.realKey(strings.ToLower(key))
- value = toCaseInsensitiveValue(value)
-
- path := strings.Split(key, v.keyDelim)
- lastKey := strings.ToLower(path[len(path)-1])
- deepestMap := deepSearch(v.override, path[0:len(path)-1])
-
- // set innermost value
- deepestMap[lastKey] = value
-}
-
-// ReadInConfig will discover and load the configuration file from disk
-// and key/value stores, searching in one of the defined paths.
-func ReadInConfig() error { return v.ReadInConfig() }
-
-func (v *Viper) ReadInConfig() error {
- v.logger.Info("attempting to read in config file")
- filename, err := v.getConfigFile()
- if err != nil {
- return err
- }
-
- if !stringInSlice(v.getConfigType(), SupportedExts) {
- return UnsupportedConfigError(v.getConfigType())
- }
-
- v.logger.Debug("reading file", "file", filename)
- file, err := afero.ReadFile(v.fs, filename)
- if err != nil {
- return err
- }
-
- config := make(map[string]any)
-
- err = v.unmarshalReader(bytes.NewReader(file), config)
- if err != nil {
- return err
- }
-
- v.config = config
- return nil
-}
-
-// MergeInConfig merges a new configuration with an existing config.
-func MergeInConfig() error { return v.MergeInConfig() }
-
-func (v *Viper) MergeInConfig() error {
- v.logger.Info("attempting to merge in config file")
- filename, err := v.getConfigFile()
- if err != nil {
- return err
- }
-
- if !stringInSlice(v.getConfigType(), SupportedExts) {
- return UnsupportedConfigError(v.getConfigType())
- }
-
- file, err := afero.ReadFile(v.fs, filename)
- if err != nil {
- return err
- }
-
- return v.MergeConfig(bytes.NewReader(file))
-}
-
-// ReadConfig will read a configuration file, setting existing keys to nil if the
-// key does not exist in the file.
-func ReadConfig(in io.Reader) error { return v.ReadConfig(in) }
-
-func (v *Viper) ReadConfig(in io.Reader) error {
- v.config = make(map[string]any)
- return v.unmarshalReader(in, v.config)
-}
-
-// MergeConfig merges a new configuration with an existing config.
-func MergeConfig(in io.Reader) error { return v.MergeConfig(in) }
-
-func (v *Viper) MergeConfig(in io.Reader) error {
- cfg := make(map[string]any)
- if err := v.unmarshalReader(in, cfg); err != nil {
- return err
- }
- return v.MergeConfigMap(cfg)
-}
-
-// MergeConfigMap merges the configuration from the map given with an existing config.
-// Note that the map given may be modified.
-func MergeConfigMap(cfg map[string]any) error { return v.MergeConfigMap(cfg) }
-
-func (v *Viper) MergeConfigMap(cfg map[string]any) error {
- if v.config == nil {
- v.config = make(map[string]any)
- }
- insensitiviseMap(cfg)
- mergeMaps(cfg, v.config, nil)
- return nil
-}
-
-// WriteConfig writes the current configuration to a file.
-func WriteConfig() error { return v.WriteConfig() }
-
-func (v *Viper) WriteConfig() error {
- filename, err := v.getConfigFile()
- if err != nil {
- return err
- }
- return v.writeConfig(filename, true)
-}
-
-// SafeWriteConfig writes current configuration to file only if the file does not exist.
-func SafeWriteConfig() error { return v.SafeWriteConfig() }
-
-func (v *Viper) SafeWriteConfig() error {
- if len(v.configPaths) < 1 {
- return errors.New("missing configuration for 'configPath'")
- }
- return v.SafeWriteConfigAs(filepath.Join(v.configPaths[0], v.configName+"."+v.configType))
-}
-
-// WriteConfigAs writes current configuration to a given filename.
-func WriteConfigAs(filename string) error { return v.WriteConfigAs(filename) }
-
-func (v *Viper) WriteConfigAs(filename string) error {
- return v.writeConfig(filename, true)
-}
-
-// SafeWriteConfigAs writes current configuration to a given filename if it does not exist.
-func SafeWriteConfigAs(filename string) error { return v.SafeWriteConfigAs(filename) }
-
-func (v *Viper) SafeWriteConfigAs(filename string) error {
- alreadyExists, err := afero.Exists(v.fs, filename)
- if alreadyExists && err == nil {
- return ConfigFileAlreadyExistsError(filename)
- }
- return v.writeConfig(filename, false)
-}
-
-func (v *Viper) writeConfig(filename string, force bool) error {
- v.logger.Info("attempting to write configuration to file")
-
- var configType string
-
- ext := filepath.Ext(filename)
- if ext != "" && ext != filepath.Base(filename) {
- configType = ext[1:]
- } else {
- configType = v.configType
- }
- if configType == "" {
- return fmt.Errorf("config type could not be determined for %s", filename)
- }
-
- if !stringInSlice(configType, SupportedExts) {
- return UnsupportedConfigError(configType)
- }
- if v.config == nil {
- v.config = make(map[string]any)
- }
- flags := os.O_CREATE | os.O_TRUNC | os.O_WRONLY
- if !force {
- flags |= os.O_EXCL
- }
- f, err := v.fs.OpenFile(filename, flags, v.configPermissions)
- if err != nil {
- return err
- }
- defer f.Close()
-
- if err := v.marshalWriter(f, configType); err != nil {
- return err
- }
-
- return f.Sync()
-}
-
-func (v *Viper) unmarshalReader(in io.Reader, c map[string]any) error {
- buf := new(bytes.Buffer)
- buf.ReadFrom(in)
-
- switch format := strings.ToLower(v.getConfigType()); format {
- case "yaml", "yml", "json", "toml", "hcl", "tfvars", "ini", "properties", "props", "prop", "dotenv", "env":
- err := v.decoderRegistry.Decode(format, buf.Bytes(), c)
- if err != nil {
- return ConfigParseError{err}
- }
- }
-
- insensitiviseMap(c)
- return nil
-}
-
-// Marshal a map into Writer.
-func (v *Viper) marshalWriter(f afero.File, configType string) error {
- c := v.AllSettings()
- switch configType {
- case "yaml", "yml", "json", "toml", "hcl", "tfvars", "ini", "prop", "props", "properties", "dotenv", "env":
- b, err := v.encoderRegistry.Encode(configType, c)
- if err != nil {
- return ConfigMarshalError{err}
- }
-
- _, err = f.WriteString(string(b))
- if err != nil {
- return ConfigMarshalError{err}
- }
- }
- return nil
-}
-
-func keyExists(k string, m map[string]any) string {
- lk := strings.ToLower(k)
- for mk := range m {
- lmk := strings.ToLower(mk)
- if lmk == lk {
- return mk
- }
- }
- return ""
-}
-
-func castToMapStringInterface(
- src map[any]any,
-) map[string]any {
- tgt := map[string]any{}
- for k, v := range src {
- tgt[fmt.Sprintf("%v", k)] = v
- }
- return tgt
-}
-
-func castMapStringSliceToMapInterface(src map[string][]string) map[string]any {
- tgt := map[string]any{}
- for k, v := range src {
- tgt[k] = v
- }
- return tgt
-}
-
-func castMapStringToMapInterface(src map[string]string) map[string]any {
- tgt := map[string]any{}
- for k, v := range src {
- tgt[k] = v
- }
- return tgt
-}
-
-func castMapFlagToMapInterface(src map[string]FlagValue) map[string]any {
- tgt := map[string]any{}
- for k, v := range src {
- tgt[k] = v
- }
- return tgt
-}
-
-// mergeMaps merges two maps. The `itgt` parameter is for handling go-yaml's
-// insistence on parsing nested structures as `map[any]any`
-// instead of using a `string` as the key for nest structures beyond one level
-// deep. Both map types are supported as there is a go-yaml fork that uses
-// `map[string]any` instead.
-func mergeMaps(src, tgt map[string]any, itgt map[any]any) {
- for sk, sv := range src {
- tk := keyExists(sk, tgt)
- if tk == "" {
- v.logger.Debug("", "tk", "\"\"", fmt.Sprintf("tgt[%s]", sk), sv)
- tgt[sk] = sv
- if itgt != nil {
- itgt[sk] = sv
- }
- continue
- }
-
- tv, ok := tgt[tk]
- if !ok {
- v.logger.Debug("", fmt.Sprintf("ok[%s]", tk), false, fmt.Sprintf("tgt[%s]", sk), sv)
- tgt[sk] = sv
- if itgt != nil {
- itgt[sk] = sv
- }
- continue
- }
-
- svType := reflect.TypeOf(sv)
- tvType := reflect.TypeOf(tv)
-
- v.logger.Debug(
- "processing",
- "key", sk,
- "st", svType,
- "tt", tvType,
- "sv", sv,
- "tv", tv,
- )
-
- switch ttv := tv.(type) {
- case map[any]any:
- v.logger.Debug("merging maps (must convert)")
- tsv, ok := sv.(map[any]any)
- if !ok {
- v.logger.Error(
- "Could not cast sv to map[any]any",
- "key", sk,
- "st", svType,
- "tt", tvType,
- "sv", sv,
- "tv", tv,
- )
- continue
- }
-
- ssv := castToMapStringInterface(tsv)
- stv := castToMapStringInterface(ttv)
- mergeMaps(ssv, stv, ttv)
- case map[string]any:
- v.logger.Debug("merging maps")
- tsv, ok := sv.(map[string]any)
- if !ok {
- v.logger.Error(
- "Could not cast sv to map[string]any",
- "key", sk,
- "st", svType,
- "tt", tvType,
- "sv", sv,
- "tv", tv,
- )
- continue
- }
- mergeMaps(tsv, ttv, nil)
- default:
- v.logger.Debug("setting value")
- tgt[tk] = sv
- if itgt != nil {
- itgt[tk] = sv
- }
- }
- }
-}
-
-// ReadRemoteConfig attempts to get configuration from a remote source
-// and read it in the remote configuration registry.
-func ReadRemoteConfig() error { return v.ReadRemoteConfig() }
-
-func (v *Viper) ReadRemoteConfig() error {
- return v.getKeyValueConfig()
-}
-
-func WatchRemoteConfig() error { return v.WatchRemoteConfig() }
-func (v *Viper) WatchRemoteConfig() error {
- return v.watchKeyValueConfig()
-}
-
-func (v *Viper) WatchRemoteConfigOnChannel() error {
- return v.watchKeyValueConfigOnChannel()
-}
-
-// Retrieve the first found remote configuration.
-func (v *Viper) getKeyValueConfig() error {
- if RemoteConfig == nil {
- return RemoteConfigError("Enable the remote features by doing a blank import of the viper/remote package: '_ github.com/spf13/viper/remote'")
- }
-
- if len(v.remoteProviders) == 0 {
- return RemoteConfigError("No Remote Providers")
- }
-
- for _, rp := range v.remoteProviders {
- val, err := v.getRemoteConfig(rp)
- if err != nil {
- v.logger.Error(fmt.Errorf("get remote config: %w", err).Error())
-
- continue
- }
-
- v.kvstore = val
-
- return nil
- }
- return RemoteConfigError("No Files Found")
-}
-
-func (v *Viper) getRemoteConfig(provider RemoteProvider) (map[string]any, error) {
- reader, err := RemoteConfig.Get(provider)
- if err != nil {
- return nil, err
- }
- err = v.unmarshalReader(reader, v.kvstore)
- return v.kvstore, err
-}
-
-// Retrieve the first found remote configuration.
-func (v *Viper) watchKeyValueConfigOnChannel() error {
- if len(v.remoteProviders) == 0 {
- return RemoteConfigError("No Remote Providers")
- }
-
- for _, rp := range v.remoteProviders {
- respc, _ := RemoteConfig.WatchChannel(rp)
- // Todo: Add quit channel
- go func(rc <-chan *RemoteResponse) {
- for {
- b := <-rc
- reader := bytes.NewReader(b.Value)
- v.unmarshalReader(reader, v.kvstore)
- }
- }(respc)
- return nil
- }
- return RemoteConfigError("No Files Found")
-}
-
-// Retrieve the first found remote configuration.
-func (v *Viper) watchKeyValueConfig() error {
- if len(v.remoteProviders) == 0 {
- return RemoteConfigError("No Remote Providers")
- }
-
- for _, rp := range v.remoteProviders {
- val, err := v.watchRemoteConfig(rp)
- if err != nil {
- v.logger.Error(fmt.Errorf("watch remote config: %w", err).Error())
-
- continue
- }
- v.kvstore = val
- return nil
- }
- return RemoteConfigError("No Files Found")
-}
-
-func (v *Viper) watchRemoteConfig(provider RemoteProvider) (map[string]any, error) {
- reader, err := RemoteConfig.Watch(provider)
- if err != nil {
- return nil, err
- }
- err = v.unmarshalReader(reader, v.kvstore)
- return v.kvstore, err
-}
-
-// AllKeys returns all keys holding a value, regardless of where they are set.
-// Nested keys are returned with a v.keyDelim separator.
-func AllKeys() []string { return v.AllKeys() }
-
-func (v *Viper) AllKeys() []string {
- m := map[string]bool{}
- // add all paths, by order of descending priority to ensure correct shadowing
- m = v.flattenAndMergeMap(m, castMapStringToMapInterface(v.aliases), "")
- m = v.flattenAndMergeMap(m, v.override, "")
- m = v.mergeFlatMap(m, castMapFlagToMapInterface(v.pflags))
- m = v.mergeFlatMap(m, castMapStringSliceToMapInterface(v.env))
- m = v.flattenAndMergeMap(m, v.config, "")
- m = v.flattenAndMergeMap(m, v.kvstore, "")
- m = v.flattenAndMergeMap(m, v.defaults, "")
-
- // convert set of paths to list
- a := make([]string, 0, len(m))
- for x := range m {
- a = append(a, x)
- }
- return a
-}
-
-// flattenAndMergeMap recursively flattens the given map into a map[string]bool
-// of key paths (used as a set, easier to manipulate than a []string):
-// - each path is merged into a single key string, delimited with v.keyDelim
-// - if a path is shadowed by an earlier value in the initial shadow map,
-// it is skipped.
-//
-// The resulting set of paths is merged to the given shadow set at the same time.
-func (v *Viper) flattenAndMergeMap(shadow map[string]bool, m map[string]any, prefix string) map[string]bool {
- if shadow != nil && prefix != "" && shadow[prefix] {
- // prefix is shadowed => nothing more to flatten
- return shadow
- }
- if shadow == nil {
- shadow = make(map[string]bool)
- }
-
- var m2 map[string]any
- if prefix != "" {
- prefix += v.keyDelim
- }
- for k, val := range m {
- fullKey := prefix + k
- switch val := val.(type) {
- case map[string]any:
- m2 = val
- case map[any]any:
- m2 = cast.ToStringMap(val)
- default:
- // immediate value
- shadow[strings.ToLower(fullKey)] = true
- continue
- }
- // recursively merge to shadow map
- shadow = v.flattenAndMergeMap(shadow, m2, fullKey)
- }
- return shadow
-}
-
-// mergeFlatMap merges the given maps, excluding values of the second map
-// shadowed by values from the first map.
-func (v *Viper) mergeFlatMap(shadow map[string]bool, m map[string]any) map[string]bool {
- // scan keys
-outer:
- for k := range m {
- path := strings.Split(k, v.keyDelim)
- // scan intermediate paths
- var parentKey string
- for i := 1; i < len(path); i++ {
- parentKey = strings.Join(path[0:i], v.keyDelim)
- if shadow[parentKey] {
- // path is shadowed, continue
- continue outer
- }
- }
- // add key
- shadow[strings.ToLower(k)] = true
- }
- return shadow
-}
-
-// AllSettings merges all settings and returns them as a map[string]any.
-func AllSettings() map[string]any { return v.AllSettings() }
-
-func (v *Viper) AllSettings() map[string]any {
- return v.getSettings(v.AllKeys())
-}
-
-func (v *Viper) getSettings(keys []string) map[string]any {
- m := map[string]any{}
- // start from the list of keys, and construct the map one value at a time
- for _, k := range keys {
- value := v.Get(k)
- if value == nil {
- // should not happen, since AllKeys() returns only keys holding a value,
- // check just in case anything changes
- continue
- }
- path := strings.Split(k, v.keyDelim)
- lastKey := strings.ToLower(path[len(path)-1])
- deepestMap := deepSearch(m, path[0:len(path)-1])
- // set innermost value
- deepestMap[lastKey] = value
- }
- return m
-}
-
-// SetFs sets the filesystem to use to read configuration.
-func SetFs(fs afero.Fs) { v.SetFs(fs) }
-
-func (v *Viper) SetFs(fs afero.Fs) {
- v.fs = fs
-}
-
-// SetConfigName sets name for the config file.
-// Does not include extension.
-func SetConfigName(in string) { v.SetConfigName(in) }
-
-func (v *Viper) SetConfigName(in string) {
- if in != "" {
- v.configName = in
- v.configFile = ""
- }
-}
-
-// SetConfigType sets the type of the configuration returned by the
-// remote source, e.g. "json".
-func SetConfigType(in string) { v.SetConfigType(in) }
-
-func (v *Viper) SetConfigType(in string) {
- if in != "" {
- v.configType = in
- }
-}
-
-// SetConfigPermissions sets the permissions for the config file.
-func SetConfigPermissions(perm os.FileMode) { v.SetConfigPermissions(perm) }
-
-func (v *Viper) SetConfigPermissions(perm os.FileMode) {
- v.configPermissions = perm.Perm()
-}
-
-// IniLoadOptions sets the load options for ini parsing.
-func IniLoadOptions(in ini.LoadOptions) Option {
- return optionFunc(func(v *Viper) {
- v.iniLoadOptions = in
- })
-}
-
-func (v *Viper) getConfigType() string {
- if v.configType != "" {
- return v.configType
- }
-
- cf, err := v.getConfigFile()
- if err != nil {
- return ""
- }
-
- ext := filepath.Ext(cf)
-
- if len(ext) > 1 {
- return ext[1:]
- }
-
- return ""
-}
-
-func (v *Viper) getConfigFile() (string, error) {
- if v.configFile == "" {
- cf, err := v.findConfigFile()
- if err != nil {
- return "", err
- }
- v.configFile = cf
- }
- return v.configFile, nil
-}
-
-// Debug prints all configuration registries for debugging
-// purposes.
-func Debug() { v.Debug() }
-func DebugTo(w io.Writer) { v.DebugTo(w) }
-
-func (v *Viper) Debug() { v.DebugTo(os.Stdout) }
-
-func (v *Viper) DebugTo(w io.Writer) {
- fmt.Fprintf(w, "Aliases:\n%#v\n", v.aliases)
- fmt.Fprintf(w, "Override:\n%#v\n", v.override)
- fmt.Fprintf(w, "PFlags:\n%#v\n", v.pflags)
- fmt.Fprintf(w, "Env:\n%#v\n", v.env)
- fmt.Fprintf(w, "Key/Value Store:\n%#v\n", v.kvstore)
- fmt.Fprintf(w, "Config:\n%#v\n", v.config)
- fmt.Fprintf(w, "Defaults:\n%#v\n", v.defaults)
-}