mirror of
https://github.com/spf13/viper
synced 2024-12-22 19:47:01 +00:00
Merge branch 'master' of https://github.com/spf13/viper into GetStringEnv
This commit is contained in:
commit
bcab3ff5ff
10 changed files with 214 additions and 67 deletions
5
.github/workflows/ci.yml
vendored
5
.github/workflows/ci.yml
vendored
|
@ -9,10 +9,11 @@ on:
|
|||
jobs:
|
||||
build:
|
||||
name: Build
|
||||
runs-on: ubuntu-latest
|
||||
runs-on: ${{ matrix.os }}
|
||||
strategy:
|
||||
matrix:
|
||||
go: ['1.11', '1.12', '1.13', '1.14']
|
||||
os: [ubuntu-latest, macos-latest]
|
||||
go: ['1.11', '1.12', '1.13', '1.14', '1.15']
|
||||
env:
|
||||
VERBOSE: 1
|
||||
GOFLAGS: -mod=readonly
|
||||
|
|
|
@ -1,27 +1,76 @@
|
|||
run:
|
||||
timeout: 5m
|
||||
|
||||
linters-settings:
|
||||
gci:
|
||||
local-prefixes: github.com/spf13/viper
|
||||
golint:
|
||||
min-confidence: 0.1
|
||||
min-confidence: 0
|
||||
goimports:
|
||||
local-prefixes: github.com/spf13/viper
|
||||
|
||||
linters:
|
||||
enable-all: true
|
||||
disable:
|
||||
- funlen
|
||||
- maligned
|
||||
disable-all: true
|
||||
enable:
|
||||
- bodyclose
|
||||
- deadcode
|
||||
- dogsled
|
||||
- dupl
|
||||
- exhaustive
|
||||
- exportloopref
|
||||
- gci
|
||||
- goconst
|
||||
- gofmt
|
||||
- gofumpt
|
||||
- goimports
|
||||
- golint
|
||||
- goprintffuncname
|
||||
- govet
|
||||
- ineffassign
|
||||
- misspell
|
||||
- nakedret
|
||||
- noctx
|
||||
- nolintlint
|
||||
- prealloc
|
||||
- rowserrcheck
|
||||
- sqlclosecheck
|
||||
- staticcheck
|
||||
- structcheck
|
||||
- stylecheck
|
||||
- typecheck
|
||||
- unconvert
|
||||
- unparam
|
||||
- unused
|
||||
- varcheck
|
||||
- whitespace
|
||||
|
||||
# TODO: fix me
|
||||
- wsl
|
||||
- gochecknoinits
|
||||
- gosimple
|
||||
- gochecknoglobals
|
||||
- errcheck
|
||||
- lll
|
||||
- godox
|
||||
- scopelint
|
||||
- gocyclo
|
||||
- gocognit
|
||||
- gocritic
|
||||
# fixme
|
||||
# - errcheck
|
||||
# - gochecknoglobals
|
||||
# - gochecknoinits
|
||||
# - gocognit
|
||||
# - gocritic
|
||||
# - gocyclo
|
||||
# - godot
|
||||
# - gosec
|
||||
# - gosimple
|
||||
# - lll
|
||||
# - nlreturn
|
||||
# - scopelint
|
||||
|
||||
service:
|
||||
golangci-lint-version: 1.21.x
|
||||
# unused
|
||||
# - depguard
|
||||
# - goheader
|
||||
# - gomodguard
|
||||
|
||||
# don't enable:
|
||||
# - asciicheck
|
||||
# - funlen
|
||||
# - godox
|
||||
# - goerr113
|
||||
# - gomnd
|
||||
# - interfacer
|
||||
# - maligned
|
||||
# - nestif
|
||||
# - testpackage
|
||||
# - wsl
|
||||
|
|
4
Makefile
4
Makefile
|
@ -15,8 +15,8 @@ TEST_FORMAT = short-verbose
|
|||
endif
|
||||
|
||||
# Dependency versions
|
||||
GOTESTSUM_VERSION = 0.4.0
|
||||
GOLANGCI_VERSION = 1.21.0
|
||||
GOTESTSUM_VERSION = 0.5.3
|
||||
GOLANGCI_VERSION = 1.31.0
|
||||
|
||||
# Add the ability to override some variables
|
||||
# Use with care
|
||||
|
|
|
@ -10,13 +10,13 @@ import (
|
|||
func TestBindFlagValueSet(t *testing.T) {
|
||||
flagSet := pflag.NewFlagSet("test", pflag.ContinueOnError)
|
||||
|
||||
var testValues = map[string]*string{
|
||||
testValues := map[string]*string{
|
||||
"host": nil,
|
||||
"port": nil,
|
||||
"endpoint": nil,
|
||||
}
|
||||
|
||||
var mutatedTestValues = map[string]string{
|
||||
mutatedTestValues := map[string]string{
|
||||
"host": "localhost",
|
||||
"port": "6060",
|
||||
"endpoint": "/public",
|
||||
|
@ -44,8 +44,8 @@ func TestBindFlagValueSet(t *testing.T) {
|
|||
}
|
||||
|
||||
func TestBindFlagValue(t *testing.T) {
|
||||
var testString = "testing"
|
||||
var testValue = newStringValue(testString, &testString)
|
||||
testString := "testing"
|
||||
testValue := newStringValue(testString, &testString)
|
||||
|
||||
flag := &pflag.Flag{
|
||||
Name: "testflag",
|
||||
|
|
|
@ -78,6 +78,7 @@ func TestNestedOverrides(t *testing.T) {
|
|||
func overrideDefault(assert *assert.Assertions, firstPath string, firstValue interface{}, secondPath string, secondValue interface{}) *Viper {
|
||||
return overrideFromLayer(defaultLayer, assert, firstPath, firstValue, secondPath, secondValue)
|
||||
}
|
||||
|
||||
func override(assert *assert.Assertions, firstPath string, firstValue interface{}, secondPath string, secondValue interface{}) *Viper {
|
||||
return overrideFromLayer(overrideLayer, assert, firstPath, firstValue, secondPath, secondValue)
|
||||
}
|
||||
|
|
|
@ -11,9 +11,9 @@ import (
|
|||
"io"
|
||||
"os"
|
||||
|
||||
"github.com/spf13/viper"
|
||||
|
||||
crypt "github.com/bketelsen/crypt/config"
|
||||
|
||||
"github.com/spf13/viper"
|
||||
)
|
||||
|
||||
type remoteConfigProvider struct{}
|
||||
|
|
13
util.go
13
util.go
|
@ -92,13 +92,22 @@ func insensitiviseMap(m map[string]interface{}) {
|
|||
func absPathify(inPath string) string {
|
||||
jww.INFO.Println("Trying to resolve absolute path to", inPath)
|
||||
|
||||
if strings.HasPrefix(inPath, "$HOME") {
|
||||
if inPath == "$HOME" || strings.HasPrefix(inPath, "$HOME"+string(os.PathSeparator)) {
|
||||
inPath = userHomeDir() + inPath[5:]
|
||||
}
|
||||
|
||||
if strings.HasPrefix(inPath, "$") {
|
||||
end := strings.Index(inPath, string(os.PathSeparator))
|
||||
inPath = os.Getenv(inPath[1:end]) + inPath[end:]
|
||||
|
||||
var value, suffix string
|
||||
if end == -1 {
|
||||
value = os.Getenv(inPath[1:])
|
||||
} else {
|
||||
value = os.Getenv(inPath[1:end])
|
||||
suffix = inPath[end:]
|
||||
}
|
||||
|
||||
inPath = value + suffix
|
||||
}
|
||||
|
||||
if filepath.IsAbs(inPath) {
|
||||
|
|
43
util_test.go
43
util_test.go
|
@ -11,6 +11,8 @@
|
|||
package viper
|
||||
|
||||
import (
|
||||
"os"
|
||||
"path/filepath"
|
||||
"reflect"
|
||||
"testing"
|
||||
)
|
||||
|
@ -22,14 +24,16 @@ func TestCopyAndInsensitiviseMap(t *testing.T) {
|
|||
"Bar": map[interface{}]interface {
|
||||
}{
|
||||
"ABc": "A",
|
||||
"cDE": "B"},
|
||||
"cDE": "B",
|
||||
},
|
||||
}
|
||||
expected = map[string]interface{}{
|
||||
"foo": 32,
|
||||
"bar": map[string]interface {
|
||||
}{
|
||||
"abc": "A",
|
||||
"cde": "B"},
|
||||
"cde": "B",
|
||||
},
|
||||
}
|
||||
)
|
||||
|
||||
|
@ -52,3 +56,38 @@ func TestCopyAndInsensitiviseMap(t *testing.T) {
|
|||
t.Fatal("Input map changed")
|
||||
}
|
||||
}
|
||||
|
||||
func TestAbsPathify(t *testing.T) {
|
||||
home := userHomeDir()
|
||||
homer := filepath.Join(home, "homer")
|
||||
wd, _ := os.Getwd()
|
||||
|
||||
os.Setenv("HOMER_ABSOLUTE_PATH", homer)
|
||||
os.Setenv("VAR_WITH_RELATIVE_PATH", "relative")
|
||||
|
||||
tests := []struct {
|
||||
input string
|
||||
output string
|
||||
}{
|
||||
{"", wd},
|
||||
{"sub", filepath.Join(wd, "sub")},
|
||||
{"./", wd},
|
||||
{"./sub", filepath.Join(wd, "sub")},
|
||||
{"$HOME", home},
|
||||
{"$HOME/", home},
|
||||
{"$HOME/sub", filepath.Join(home, "sub")},
|
||||
{"$HOMER_ABSOLUTE_PATH", homer},
|
||||
{"$HOMER_ABSOLUTE_PATH/", homer},
|
||||
{"$HOMER_ABSOLUTE_PATH/sub", filepath.Join(homer, "sub")},
|
||||
{"$VAR_WITH_RELATIVE_PATH", filepath.Join(wd, "relative")},
|
||||
{"$VAR_WITH_RELATIVE_PATH/", filepath.Join(wd, "relative")},
|
||||
{"$VAR_WITH_RELATIVE_PATH/sub", filepath.Join(wd, "relative", "sub")},
|
||||
}
|
||||
|
||||
for _, test := range tests {
|
||||
got := absPathify(test.input)
|
||||
if got != test.output {
|
||||
t.Errorf("Got %v\nexpected\n%q", got, test.output)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
86
viper.go
86
viper.go
|
@ -409,6 +409,7 @@ func (v *Viper) WatchConfig() {
|
|||
// 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
|
||||
|
@ -419,6 +420,7 @@ func (v *Viper) SetConfigFile(in string) {
|
|||
// 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
|
||||
|
@ -437,6 +439,7 @@ func (v *Viper) mergeWithEnvPrefix(in string) string {
|
|||
// 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
|
||||
}
|
||||
|
@ -465,6 +468,7 @@ 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(in)
|
||||
|
@ -486,6 +490,7 @@ func (v *Viper) AddConfigPath(in string) {
|
|||
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)
|
||||
|
@ -706,6 +711,7 @@ func (v *Viper) isPathShadowedInAutoEnv(path []string) string {
|
|||
//
|
||||
// "a b c"
|
||||
func SetTypeByDefaultValue(enable bool) { v.SetTypeByDefaultValue(enable) }
|
||||
|
||||
func (v *Viper) SetTypeByDefaultValue(enable bool) {
|
||||
v.typeByDefValue = enable
|
||||
}
|
||||
|
@ -723,6 +729,7 @@ func GetViper() *Viper {
|
|||
//
|
||||
// Get returns an interface. For a specific value use one of the Get____ methods.
|
||||
func Get(key string) interface{} { return v.Get(key) }
|
||||
|
||||
func (v *Viper) Get(key string) interface{} {
|
||||
lcaseKey := strings.ToLower(key)
|
||||
val := v.find(lcaseKey, true)
|
||||
|
@ -773,6 +780,7 @@ func (v *Viper) Get(key string) interface{} {
|
|||
// 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)
|
||||
|
@ -789,6 +797,7 @@ func (v *Viper) Sub(key string) *Viper {
|
|||
|
||||
// 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))
|
||||
}
|
||||
|
@ -801,90 +810,105 @@ func (v *Viper) GetStringEnv(key string) string {
|
|||
|
||||
// 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))
|
||||
}
|
||||
|
||||
// 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]interface{} { return v.GetStringMap(key) }
|
||||
|
||||
func (v *Viper) GetStringMap(key string) map[string]interface{} {
|
||||
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))
|
||||
}
|
||||
|
@ -892,6 +916,7 @@ func (v *Viper) GetStringMapStringSlice(key string) map[string][]string {
|
|||
// 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)
|
||||
|
@ -901,14 +926,9 @@ func (v *Viper) GetSizeInBytes(key string) uint {
|
|||
func UnmarshalKey(key string, rawVal interface{}, opts ...DecoderConfigOption) error {
|
||||
return v.UnmarshalKey(key, rawVal, opts...)
|
||||
}
|
||||
|
||||
func (v *Viper) UnmarshalKey(key string, rawVal interface{}, opts ...DecoderConfigOption) error {
|
||||
err := decode(v.Get(key), defaultDecoderConfig(rawVal, opts...))
|
||||
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
return decode(v.Get(key), defaultDecoderConfig(rawVal, opts...))
|
||||
}
|
||||
|
||||
// Unmarshal unmarshals the config into a Struct. Make sure that the tags
|
||||
|
@ -916,14 +936,9 @@ func (v *Viper) UnmarshalKey(key string, rawVal interface{}, opts ...DecoderConf
|
|||
func Unmarshal(rawVal interface{}, opts ...DecoderConfigOption) error {
|
||||
return v.Unmarshal(rawVal, opts...)
|
||||
}
|
||||
|
||||
func (v *Viper) Unmarshal(rawVal interface{}, opts ...DecoderConfigOption) error {
|
||||
err := decode(v.AllSettings(), defaultDecoderConfig(rawVal, opts...))
|
||||
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
return decode(v.AllSettings(), defaultDecoderConfig(rawVal, opts...))
|
||||
}
|
||||
|
||||
// defaultDecoderConfig returns default mapsstructure.DecoderConfig with suppot
|
||||
|
@ -958,22 +973,18 @@ func decode(input interface{}, config *mapstructure.DecoderConfig) error {
|
|||
func UnmarshalExact(rawVal interface{}, opts ...DecoderConfigOption) error {
|
||||
return v.UnmarshalExact(rawVal, opts...)
|
||||
}
|
||||
|
||||
func (v *Viper) UnmarshalExact(rawVal interface{}, opts ...DecoderConfigOption) error {
|
||||
config := defaultDecoderConfig(rawVal, opts...)
|
||||
config.ErrorUnused = true
|
||||
|
||||
err := decode(v.AllSettings(), config)
|
||||
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
return decode(v.AllSettings(), 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})
|
||||
}
|
||||
|
@ -985,6 +996,7 @@ func (v *Viper) BindPFlags(flags *pflag.FlagSet) error {
|
|||
// 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 {
|
||||
return v.BindFlagValue(key, pflagValue{flag})
|
||||
}
|
||||
|
@ -992,6 +1004,7 @@ func (v *Viper) BindPFlag(key string, flag *pflag.Flag) error {
|
|||
// 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 {
|
||||
|
@ -1003,6 +1016,7 @@ func (v *Viper) BindFlagValues(flags FlagValueSet) (err error) {
|
|||
|
||||
// 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)
|
||||
|
@ -1016,6 +1030,7 @@ func (v *Viper) BindFlagValue(key string, flag FlagValue) error {
|
|||
// If only a key is provided, it will use the env key matching the key, uppercased.
|
||||
// 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 {
|
||||
var key, envkey string
|
||||
if len(input) == 0 {
|
||||
|
@ -1214,6 +1229,7 @@ func stringToStringConv(val string) interface{} {
|
|||
// 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)
|
||||
|
@ -1223,6 +1239,7 @@ func (v *Viper) IsSet(key string) bool {
|
|||
// AutomaticEnv has Viper check ENV variables for all.
|
||||
// keys set in config, default & flags
|
||||
func AutomaticEnv() { v.AutomaticEnv() }
|
||||
|
||||
func (v *Viper) AutomaticEnv() {
|
||||
v.automaticEnvApplied = true
|
||||
}
|
||||
|
@ -1231,6 +1248,7 @@ func (v *Viper) AutomaticEnv() {
|
|||
// 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
|
||||
}
|
||||
|
@ -1238,6 +1256,7 @@ func (v *Viper) SetEnvKeyReplacer(r *strings.Replacer) {
|
|||
// 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 string, key string) { v.RegisterAlias(alias, key) }
|
||||
|
||||
func (v *Viper) RegisterAlias(alias string, key string) {
|
||||
v.registerAlias(alias, strings.ToLower(key))
|
||||
}
|
||||
|
@ -1285,6 +1304,7 @@ func (v *Viper) realKey(key string) string {
|
|||
|
||||
// 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 {
|
||||
// if the requested key is an alias, then return the proper key
|
||||
key = v.realKey(key)
|
||||
|
@ -1297,6 +1317,7 @@ func (v *Viper) InConfig(key string) bool {
|
|||
// 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 interface{}) { v.SetDefault(key, value) }
|
||||
|
||||
func (v *Viper) SetDefault(key string, value interface{}) {
|
||||
// If alias passed in, then set the proper default
|
||||
key = v.realKey(strings.ToLower(key))
|
||||
|
@ -1315,6 +1336,7 @@ func (v *Viper) SetDefault(key string, value interface{}) {
|
|||
// Will be used instead of values obtained via
|
||||
// flags, config file, ENV, default, or key/value store.
|
||||
func Set(key string, value interface{}) { v.Set(key, value) }
|
||||
|
||||
func (v *Viper) Set(key string, value interface{}) {
|
||||
// If alias passed in, then set the proper override
|
||||
key = v.realKey(strings.ToLower(key))
|
||||
|
@ -1331,6 +1353,7 @@ func (v *Viper) Set(key string, value interface{}) {
|
|||
// 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 {
|
||||
jww.INFO.Println("Attempting to read in config file")
|
||||
filename, err := v.getConfigFile()
|
||||
|
@ -1361,6 +1384,7 @@ func (v *Viper) ReadInConfig() error {
|
|||
|
||||
// MergeInConfig merges a new configuration with an existing config.
|
||||
func MergeInConfig() error { return v.MergeInConfig() }
|
||||
|
||||
func (v *Viper) MergeInConfig() error {
|
||||
jww.INFO.Println("Attempting to merge in config file")
|
||||
filename, err := v.getConfigFile()
|
||||
|
@ -1383,6 +1407,7 @@ func (v *Viper) MergeInConfig() error {
|
|||
// 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]interface{})
|
||||
return v.unmarshalReader(in, v.config)
|
||||
|
@ -1390,6 +1415,7 @@ func (v *Viper) ReadConfig(in io.Reader) error {
|
|||
|
||||
// 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]interface{})
|
||||
if err := v.unmarshalReader(in, cfg); err != nil {
|
||||
|
@ -1401,6 +1427,7 @@ func (v *Viper) MergeConfig(in io.Reader) error {
|
|||
// 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]interface{}) error { return v.MergeConfigMap(cfg) }
|
||||
|
||||
func (v *Viper) MergeConfigMap(cfg map[string]interface{}) error {
|
||||
if v.config == nil {
|
||||
v.config = make(map[string]interface{})
|
||||
|
@ -1412,6 +1439,7 @@ func (v *Viper) MergeConfigMap(cfg map[string]interface{}) error {
|
|||
|
||||
// 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 {
|
||||
|
@ -1422,6 +1450,7 @@ func (v *Viper) WriteConfig() error {
|
|||
|
||||
// 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'")
|
||||
|
@ -1431,12 +1460,14 @@ func (v *Viper) SafeWriteConfig() error {
|
|||
|
||||
// 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 {
|
||||
|
@ -1487,6 +1518,7 @@ func (v *Viper) writeConfig(filename string, force bool) error {
|
|||
func unmarshalReader(in io.Reader, c map[string]interface{}) error {
|
||||
return v.unmarshalReader(in, c)
|
||||
}
|
||||
|
||||
func (v *Viper) unmarshalReader(in io.Reader, c map[string]interface{}) error {
|
||||
buf := new(bytes.Buffer)
|
||||
buf.ReadFrom(in)
|
||||
|
@ -1761,6 +1793,7 @@ func mergeMaps(
|
|||
// 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()
|
||||
}
|
||||
|
@ -1783,9 +1816,13 @@ func (v *Viper) getKeyValueConfig() error {
|
|||
for _, rp := range v.remoteProviders {
|
||||
val, err := v.getRemoteConfig(rp)
|
||||
if err != nil {
|
||||
jww.ERROR.Printf("get remote config: %s", err)
|
||||
|
||||
continue
|
||||
}
|
||||
|
||||
v.kvstore = val
|
||||
|
||||
return nil
|
||||
}
|
||||
return RemoteConfigError("No Files Found")
|
||||
|
@ -1842,6 +1879,7 @@ func (v *Viper) watchRemoteConfig(provider RemoteProvider) (map[string]interface
|
|||
// 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
|
||||
|
@ -1922,6 +1960,7 @@ outer:
|
|||
|
||||
// AllSettings merges all settings and returns them as a map[string]interface{}.
|
||||
func AllSettings() map[string]interface{} { return v.AllSettings() }
|
||||
|
||||
func (v *Viper) AllSettings() map[string]interface{} {
|
||||
m := map[string]interface{}{}
|
||||
// start from the list of keys, and construct the map one value at a time
|
||||
|
@ -1943,6 +1982,7 @@ func (v *Viper) AllSettings() map[string]interface{} {
|
|||
|
||||
// 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
|
||||
}
|
||||
|
@ -1950,6 +1990,7 @@ func (v *Viper) SetFs(fs afero.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
|
||||
|
@ -1960,6 +2001,7 @@ func (v *Viper) SetConfigName(in string) {
|
|||
// 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
|
||||
|
@ -1968,6 +2010,7 @@ func (v *Viper) SetConfigType(in string) {
|
|||
|
||||
// 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()
|
||||
}
|
||||
|
@ -2038,6 +2081,7 @@ func (v *Viper) findConfigFile() (string, error) {
|
|||
// Debug prints all configuration registries for debugging
|
||||
// purposes.
|
||||
func Debug() { v.Debug() }
|
||||
|
||||
func (v *Viper) Debug() {
|
||||
fmt.Printf("Aliases:\n%#v\n", v.aliases)
|
||||
fmt.Printf("Override:\n%#v\n", v.override)
|
||||
|
|
|
@ -26,7 +26,6 @@ import (
|
|||
"github.com/mitchellh/mapstructure"
|
||||
"github.com/spf13/afero"
|
||||
"github.com/spf13/cast"
|
||||
|
||||
"github.com/spf13/pflag"
|
||||
"github.com/stretchr/testify/assert"
|
||||
"github.com/stretchr/testify/require"
|
||||
|
@ -717,7 +716,8 @@ func TestAllKeys(t *testing.T) {
|
|||
{"key": 1},
|
||||
{"key": 2},
|
||||
{"key": 3},
|
||||
{"key": 4}},
|
||||
{"key": 4},
|
||||
},
|
||||
},
|
||||
},
|
||||
"title_dotenv": "DotEnv Example",
|
||||
|
@ -851,13 +851,13 @@ func TestBindPFlags(t *testing.T) {
|
|||
v := New() // create independent Viper object
|
||||
flagSet := pflag.NewFlagSet("test", pflag.ContinueOnError)
|
||||
|
||||
var testValues = map[string]*string{
|
||||
testValues := map[string]*string{
|
||||
"host": nil,
|
||||
"port": nil,
|
||||
"endpoint": nil,
|
||||
}
|
||||
|
||||
var mutatedTestValues = map[string]string{
|
||||
mutatedTestValues := map[string]string{
|
||||
"host": "localhost",
|
||||
"port": "6060",
|
||||
"endpoint": "/public",
|
||||
|
@ -974,8 +974,8 @@ func TestBindPFlagsIntSlice(t *testing.T) {
|
|||
}
|
||||
|
||||
func TestBindPFlag(t *testing.T) {
|
||||
var testString = "testing"
|
||||
var testValue = newStringValue(testString, &testString)
|
||||
testString := "testing"
|
||||
testValue := newStringValue(testString, &testString)
|
||||
|
||||
flag := &pflag.Flag{
|
||||
Name: "testflag",
|
||||
|
@ -1048,8 +1048,8 @@ func TestBoundCaseSensitivity(t *testing.T) {
|
|||
|
||||
assert.Equal(t, "blue", Get("eyes"))
|
||||
|
||||
var testString = "green"
|
||||
var testValue = newStringValue(testString, &testString)
|
||||
testString := "green"
|
||||
testValue := newStringValue(testString, &testString)
|
||||
|
||||
flag := &pflag.Flag{
|
||||
Name: "eyeballs",
|
||||
|
@ -1128,9 +1128,11 @@ func TestFindsNestedKeys(t *testing.T) {
|
|||
},
|
||||
map[string]interface{}{
|
||||
"type": "Chocolate",
|
||||
}, map[string]interface{}{
|
||||
},
|
||||
map[string]interface{}{
|
||||
"type": "Blueberry",
|
||||
}, map[string]interface{}{
|
||||
},
|
||||
map[string]interface{}{
|
||||
"type": "Devil's Food",
|
||||
},
|
||||
},
|
||||
|
@ -1995,7 +1997,8 @@ func TestCaseInsensitiveSet(t *testing.T) {
|
|||
"Bar": map[interface{}]interface {
|
||||
}{
|
||||
"ABc": "A",
|
||||
"cDE": "B"},
|
||||
"cDE": "B",
|
||||
},
|
||||
}
|
||||
|
||||
m2 := map[string]interface{}{
|
||||
|
@ -2003,7 +2006,8 @@ func TestCaseInsensitiveSet(t *testing.T) {
|
|||
"Bar": map[interface{}]interface {
|
||||
}{
|
||||
"bCd": "A",
|
||||
"eFG": "B"},
|
||||
"eFG": "B",
|
||||
},
|
||||
}
|
||||
|
||||
Set("Given1", m1)
|
||||
|
|
Loading…
Reference in a new issue