diff --git a/cmd/cluster/clusterCreate.go b/cmd/cluster/clusterCreate.go index e9efc4d5..68da8aff 100644 --- a/cmd/cluster/clusterCreate.go +++ b/cmd/cluster/clusterCreate.go @@ -254,16 +254,16 @@ func NewCmdClusterCreate() *cobra.Command { cmd.Flags().String("api-port", "", "Specify the Kubernetes API server port exposed on the LoadBalancer (Format: `[HOST:]HOSTPORT`)\n - Example: `k3d cluster create --servers 3 --api-port 0.0.0.0:6550`") _ = ppViper.BindPFlag("cli.api-port", cmd.Flags().Lookup("api-port")) - cmd.Flags().StringSliceP("env", "e", nil, "Add environment variables to nodes (Format: `KEY[=VALUE][@NODEFILTER[;NODEFILTER...]]`\n - Example: `k3d cluster create --agents 2 -e \"HTTP_PROXY=my.proxy.com\" -e \"SOME_KEY=SOME_VAL@server[0]\"`") + cmd.Flags().StringArrayP("env", "e", nil, "Add environment variables to nodes (Format: `KEY[=VALUE][@NODEFILTER[;NODEFILTER...]]`\n - Example: `k3d cluster create --agents 2 -e \"HTTP_PROXY=my.proxy.com\" -e \"SOME_KEY=SOME_VAL@server[0]\"`") _ = ppViper.BindPFlag("cli.env", cmd.Flags().Lookup("env")) - cmd.Flags().StringSliceP("volume", "v", nil, "Mount volumes into the nodes (Format: `[SOURCE:]DEST[@NODEFILTER[;NODEFILTER...]]`\n - Example: `k3d cluster create --agents 2 -v /my/path@agent[0,1] -v /tmp/test:/tmp/other@server[0]`") + cmd.Flags().StringArrayP("volume", "v", nil, "Mount volumes into the nodes (Format: `[SOURCE:]DEST[@NODEFILTER[;NODEFILTER...]]`\n - Example: `k3d cluster create --agents 2 -v /my/path@agent[0,1] -v /tmp/test:/tmp/other@server[0]`") _ = ppViper.BindPFlag("cli.volumes", cmd.Flags().Lookup("volume")) - cmd.Flags().StringSliceP("port", "p", nil, "Map ports from the node containers to the host (Format: `[HOST:][HOSTPORT:]CONTAINERPORT[/PROTOCOL][@NODEFILTER]`)\n - Example: `k3d cluster create --agents 2 -p 8080:80@agent[0] -p 8081@agent[1]`") + cmd.Flags().StringArrayP("port", "p", nil, "Map ports from the node containers to the host (Format: `[HOST:][HOSTPORT:]CONTAINERPORT[/PROTOCOL][@NODEFILTER]`)\n - Example: `k3d cluster create --agents 2 -p 8080:80@agent[0] -p 8081@agent[1]`") _ = ppViper.BindPFlag("cli.ports", cmd.Flags().Lookup("port")) - cmd.Flags().StringSliceP("label", "l", nil, "Add label to node container (Format: `KEY[=VALUE][@NODEFILTER[;NODEFILTER...]]`\n - Example: `k3d cluster create --agents 2 -l \"my.label@agent[0,1]\" -v \"other.label=somevalue@server[0]\"`") + cmd.Flags().StringArrayP("label", "l", nil, "Add label to node container (Format: `KEY[=VALUE][@NODEFILTER[;NODEFILTER...]]`\n - Example: `k3d cluster create --agents 2 -l \"my.label@agent[0,1]\" -v \"other.label=somevalue@server[0]\"`") _ = ppViper.BindPFlag("cli.labels", cmd.Flags().Lookup("label")) /****************** @@ -328,7 +328,7 @@ func NewCmdClusterCreate() *cobra.Command { _ = cfgViper.BindPFlag("options.k3d.disableimagevolume", cmd.Flags().Lookup("no-image-volume")) /* Registry */ - cmd.Flags().StringSlice("registry-use", nil, "Connect to one or more k3d-managed registries running locally") + cmd.Flags().StringArray("registry-use", nil, "Connect to one or more k3d-managed registries running locally") _ = cfgViper.BindPFlag("registries.use", cmd.Flags().Lookup("registry-use")) cmd.Flags().Bool("registry-create", false, "Create a k3d-managed registry and connect it to the cluster") @@ -338,10 +338,10 @@ func NewCmdClusterCreate() *cobra.Command { _ = cfgViper.BindPFlag("registries.config", cmd.Flags().Lookup("registry-config")) /* k3s */ - cmd.Flags().StringSlice("k3s-server-arg", nil, "Additional args passed to the `k3s server` command on server nodes (new flag per arg)") + cmd.Flags().StringArray("k3s-server-arg", nil, "Additional args passed to the `k3s server` command on server nodes (new flag per arg)") _ = cfgViper.BindPFlag("options.k3s.extraserverargs", cmd.Flags().Lookup("k3s-server-arg")) - cmd.Flags().StringSlice("k3s-agent-arg", nil, "Additional args passed to the `k3s agent` command on agent nodes (new flag per arg)") + cmd.Flags().StringArray("k3s-agent-arg", nil, "Additional args passed to the `k3s agent` command on agent nodes (new flag per arg)") _ = cfgViper.BindPFlag("options.k3s.extraagentargs", cmd.Flags().Lookup("k3s-agent-arg")) /* Subcommands */ diff --git a/go.mod b/go.mod index 7d947da6..5f816843 100644 --- a/go.mod +++ b/go.mod @@ -19,7 +19,6 @@ require ( github.com/imdario/mergo v0.3.11 github.com/liggitt/tabwriter v0.0.0-20181228230101-89fcab3d43de github.com/mitchellh/go-homedir v1.1.0 - github.com/mitchellh/mapstructure v1.3.3 // indirect github.com/moby/sys/mount v0.2.0 // indirect github.com/moby/term v0.0.0-20201110203204-bea5bbe245bf // indirect github.com/morikuni/aec v1.0.0 // indirect @@ -28,7 +27,6 @@ require ( github.com/pelletier/go-toml v1.8.0 // indirect github.com/pkg/errors v0.9.1 github.com/sirupsen/logrus v1.8.1 - github.com/spf13/afero v1.3.4 // indirect github.com/spf13/cast v1.3.1 // indirect github.com/spf13/cobra v1.1.3 github.com/spf13/jwalterweatherman v1.1.0 // indirect @@ -50,3 +48,5 @@ require ( k8s.io/client-go v0.20.4 sigs.k8s.io/yaml v1.2.0 ) + +replace github.com/spf13/viper => github.com/iwilltry42/viper v1.7.2-iwilltry42.0 diff --git a/go.sum b/go.sum index eadd7af6..0c3d7880 100644 --- a/go.sum +++ b/go.sum @@ -284,6 +284,8 @@ github.com/imdario/mergo v0.3.11 h1:3tnifQM4i+fbajXKBHXWEH+KvNHqojZ778UH75j3bGA= github.com/imdario/mergo v0.3.11/go.mod h1:jmQim1M+e3UYxmgPu/WyfjB3N3VflVyUjjjwH0dnCYA= github.com/inconshreveable/mousetrap v1.0.0 h1:Z8tu5sraLXCXIcARxBp/8cbvlwVa7Z1NHg9XEKhtSvM= github.com/inconshreveable/mousetrap v1.0.0/go.mod h1:PxqpIevigyE2G7u3NXJIT2ANytuPF1OarO4DADm73n8= +github.com/iwilltry42/viper v1.7.2-iwilltry42.0 h1:2WfWyjoSqydMqC8nffg0TJB575aAt3K4abpOOkIDjCo= +github.com/iwilltry42/viper v1.7.2-iwilltry42.0/go.mod h1:saRp35avIY0BQrkppYHCJOqWlJBTGuBb+rPVWAE9CTw= github.com/jonboulle/clockwork v0.1.0/go.mod h1:Ii8DK3G1RaLaWxj9trq07+26W01tbo22gdxWY5EU2bo= github.com/json-iterator/go v1.1.6/go.mod h1:+SdeFBvtyEkXs7REEP0seUULqWtbJapLOCVDaaPEHmU= github.com/json-iterator/go v1.1.10 h1:Kz6Cvnvv2wGdaG/V8yMvfkmNiXq9Ya2KUv4rouJJr68= @@ -433,10 +435,9 @@ github.com/soheilhy/cmux v0.1.4/go.mod h1:IM3LyeVVIOuxMH7sFAkER9+bJ4dT7Ms6E4xg4k github.com/sourcegraph/go-diff v0.5.1/go.mod h1:j2dHj3m8aZgQO8lMTcTnBcXkRRRqi34cd2MNlA9u1mE= github.com/spaolacci/murmur3 v0.0.0-20180118202830-f09979ecbc72/go.mod h1:JwIasOWyU6f++ZhiEuf87xNszmSA2myDM2Kzu9HwQUA= github.com/spf13/afero v1.1.0/go.mod h1:j4pytiNVoe2o6bmDsKpLACNPDBIoEAkihy7loJ1B0CQ= -github.com/spf13/afero v1.1.2/go.mod h1:j4pytiNVoe2o6bmDsKpLACNPDBIoEAkihy7loJ1B0CQ= github.com/spf13/afero v1.2.2/go.mod h1:9ZxEEn6pIJ8Rxe320qSDBk6AsU0r9pR7Q4OcevTdifk= -github.com/spf13/afero v1.3.4 h1:8q6vk3hthlpb2SouZcnBVKboxWQWMDNF38bwholZrJc= -github.com/spf13/afero v1.3.4/go.mod h1:Ai8FlHk4v/PARR026UzYexafAt9roJ7LcLMAmO6Z93I= +github.com/spf13/afero v1.5.1 h1:VHu76Lk0LSP1x254maIu2bplkWpfBWI+B+6fdoZprcg= +github.com/spf13/afero v1.5.1/go.mod h1:Ai8FlHk4v/PARR026UzYexafAt9roJ7LcLMAmO6Z93I= github.com/spf13/cast v1.2.0/go.mod h1:r2rcYCSwa1IExKTDiTfzaxqT2FNHs8hODu4LnUfgKEg= github.com/spf13/cast v1.3.0/go.mod h1:Qx5cxh0v+4UWYiBimWS+eyWzqEqokIECu5etghLkUJE= github.com/spf13/cast v1.3.1 h1:nFm6S0SMdyzrzcmThSipiEubIDy8WEXKNZ0UOgiRpng= @@ -455,10 +456,6 @@ github.com/spf13/pflag v1.0.1/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnIn github.com/spf13/pflag v1.0.3/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4= github.com/spf13/pflag v1.0.5 h1:iy+VFUOCP1a+8yFto/drg2CJ5u0yRoB7fZw3DKv/JXA= github.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg= -github.com/spf13/viper v1.0.2/go.mod h1:A8kyI5cUJhb8N+3pkfONlcEcZbueH6nhAm0Fq7SrnBM= -github.com/spf13/viper v1.7.0/go.mod h1:8WkrPz2fc9jxqZNCJI/76HCieCp4Q8HaLFoCha5qpdg= -github.com/spf13/viper v1.7.1 h1:pM5oEahlgWv/WnHXpgbKz7iLIxRf65tye2Ci+XFK5sk= -github.com/spf13/viper v1.7.1/go.mod h1:8WkrPz2fc9jxqZNCJI/76HCieCp4Q8HaLFoCha5qpdg= github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/objx v0.2.0/go.mod h1:qt09Ya8vawLte6SNmTgCsAVtYtaKzEcn8ATUoHMkEqE= diff --git a/tests/assets/config_test_simple.yaml b/tests/assets/config_test_simple.yaml index cf80cc7e..4d9f7255 100644 --- a/tests/assets/config_test_simple.yaml +++ b/tests/assets/config_test_simple.yaml @@ -19,7 +19,7 @@ ports: nodeFilters: - loadbalancer env: - - envVar: bar=baz + - envVar: bar=baz,bob nodeFilters: - all labels: diff --git a/tests/test_config_file.sh b/tests/test_config_file.sh index 268bd4e1..b367bac1 100755 --- a/tests/test_config_file.sh +++ b/tests/test_config_file.sh @@ -38,8 +38,8 @@ check_multi_node "$clustername" 5 || failed "failed to verify number of nodes" # 2. check some config settings ## Environment Variables -info "Ensuring that environment variables are present in the node containers as set in the config" -exec_in_node "k3d-$clustername-server-0" "env" | grep "bar=baz" || failed "Expected env var 'bar=baz' is not present in node k3d-$clustername-server-0" +info "Ensuring that environment variables are present in the node containers as set in the config (with comma)" +exec_in_node "k3d-$clustername-server-0" "env" | grep "bar=baz,bob" || failed "Expected env var 'bar=baz,bob' is not present in node k3d-$clustername-server-0" ## Container Labels info "Ensuring that container labels have been set as stated in the config" diff --git a/vendor/github.com/spf13/afero/.travis.yml b/vendor/github.com/spf13/afero/.travis.yml index fdaa9998..a3c59064 100644 --- a/vendor/github.com/spf13/afero/.travis.yml +++ b/vendor/github.com/spf13/afero/.travis.yml @@ -1,9 +1,12 @@ sudo: false language: go +arch: + - amd64 + - ppc64e go: - - "1.13" - "1.14" + - "1.15" - tip os: @@ -19,4 +22,4 @@ script: - go build -v ./... - go test -count=1 -cover -race -v ./... - go vet ./... - - FILES=$(gofmt -s -l . zipfs sftpfs mem); if [[ -n "${FILES}" ]]; then echo "You have go format errors; gofmt your changes"; exit 1; fi + - FILES=$(gofmt -s -l . zipfs sftpfs mem tarfs); if [[ -n "${FILES}" ]]; then echo "You have go format errors; gofmt your changes"; exit 1; fi diff --git a/vendor/github.com/spf13/afero/README.md b/vendor/github.com/spf13/afero/README.md index 16b06f2b..1400bc4e 100644 --- a/vendor/github.com/spf13/afero/README.md +++ b/vendor/github.com/spf13/afero/README.md @@ -94,6 +94,7 @@ AppFs.Open('/tmp/foo') File System Methods Available: ```go Chmod(name string, mode os.FileMode) : error +Chown(name string, uid, gid int) : error Chtimes(name string, atime time.Time, mtime time.Time) : error Create(name string) : File, error Mkdir(name string, perm os.FileMode) : error @@ -227,7 +228,7 @@ operation and a mock filesystem during testing or as needed. ```go appfs := afero.NewOsFs() -appfs.MkdirAll("src/a", 0755)) +appfs.MkdirAll("src/a", 0755) ``` ## Memory Backed Storage @@ -241,7 +242,7 @@ safely. ```go mm := afero.NewMemMapFs() -mm.MkdirAll("src/a", 0755)) +mm.MkdirAll("src/a", 0755) ``` #### InMemoryFile @@ -306,7 +307,7 @@ Any Afero FileSystem can be used as an httpFs. ```go httpFs := afero.NewHttpFs() -fileserver := http.FileServer(httpFs.Dir())) +fileserver := http.FileServer(httpFs.Dir()) http.Handle("/", fileserver) ``` @@ -380,7 +381,6 @@ The following is a short list of possible backends we hope someone will implement: * SSH -* TAR * S3 # About the project diff --git a/vendor/github.com/spf13/afero/afero.go b/vendor/github.com/spf13/afero/afero.go index f5b5e127..469ff7d2 100644 --- a/vendor/github.com/spf13/afero/afero.go +++ b/vendor/github.com/spf13/afero/afero.go @@ -91,9 +91,12 @@ type Fs interface { // The name of this FileSystem Name() string - //Chmod changes the mode of the named file to mode. + // Chmod changes the mode of the named file to mode. Chmod(name string, mode os.FileMode) error + // Chown changes the uid and gid of the named file. + Chown(name string, uid, gid int) error + //Chtimes changes the access and modification times of the named file Chtimes(name string, atime time.Time, mtime time.Time) error } diff --git a/vendor/github.com/spf13/afero/basepath.go b/vendor/github.com/spf13/afero/basepath.go index 3a14b833..4f983282 100644 --- a/vendor/github.com/spf13/afero/basepath.go +++ b/vendor/github.com/spf13/afero/basepath.go @@ -83,6 +83,13 @@ func (b *BasePathFs) Chmod(name string, mode os.FileMode) (err error) { return b.source.Chmod(name, mode) } +func (b *BasePathFs) Chown(name string, uid, gid int) (err error) { + if name, err = b.RealPath(name); err != nil { + return &os.PathError{Op: "chown", Path: name, Err: err} + } + return b.source.Chown(name, uid, gid) +} + func (b *BasePathFs) Name() string { return "BasePathFs" } @@ -202,5 +209,3 @@ func (b *BasePathFs) ReadlinkIfPossible(name string) (string, error) { } return "", &os.PathError{Op: "readlink", Path: name, Err: ErrNoReadlink} } - -// vim: ts=4 sw=4 noexpandtab nolist syn=go diff --git a/vendor/github.com/spf13/afero/cacheOnReadFs.go b/vendor/github.com/spf13/afero/cacheOnReadFs.go index 29a26c67..71471aa2 100644 --- a/vendor/github.com/spf13/afero/cacheOnReadFs.go +++ b/vendor/github.com/spf13/afero/cacheOnReadFs.go @@ -117,6 +117,27 @@ func (u *CacheOnReadFs) Chmod(name string, mode os.FileMode) error { return u.layer.Chmod(name, mode) } +func (u *CacheOnReadFs) Chown(name string, uid, gid int) error { + st, _, err := u.cacheStatus(name) + if err != nil { + return err + } + switch st { + case cacheLocal: + case cacheHit: + err = u.base.Chown(name, uid, gid) + case cacheStale, cacheMiss: + if err := u.copyToLayer(name); err != nil { + return err + } + err = u.base.Chown(name, uid, gid) + } + if err != nil { + return err + } + return u.layer.Chown(name, uid, gid) +} + func (u *CacheOnReadFs) Stat(name string) (os.FileInfo, error) { st, fi, err := u.cacheStatus(name) if err != nil { diff --git a/vendor/github.com/spf13/afero/copyOnWriteFs.go b/vendor/github.com/spf13/afero/copyOnWriteFs.go index 96b77012..6ff8f309 100644 --- a/vendor/github.com/spf13/afero/copyOnWriteFs.go +++ b/vendor/github.com/spf13/afero/copyOnWriteFs.go @@ -14,7 +14,7 @@ var _ Lstater = (*CopyOnWriteFs)(nil) // a possibly writeable layer on top. Changes to the file system will only // be made in the overlay: Changing an existing file in the base layer which // is not present in the overlay will copy the file to the overlay ("changing" -// includes also calls to e.g. Chtimes() and Chmod()). +// includes also calls to e.g. Chtimes(), Chmod() and Chown()). // // Reading directories is currently only supported via Open(), not OpenFile(). type CopyOnWriteFs struct { @@ -75,6 +75,19 @@ func (u *CopyOnWriteFs) Chmod(name string, mode os.FileMode) error { return u.layer.Chmod(name, mode) } +func (u *CopyOnWriteFs) Chown(name string, uid, gid int) error { + b, err := u.isBaseFile(name) + if err != nil { + return err + } + if b { + if err := u.copyToLayer(name); err != nil { + return err + } + } + return u.layer.Chown(name, uid, gid) +} + func (u *CopyOnWriteFs) Stat(name string) (os.FileInfo, error) { fi, err := u.layer.Stat(name) if err != nil { diff --git a/vendor/github.com/spf13/afero/httpFs.go b/vendor/github.com/spf13/afero/httpFs.go index c4219368..2b86e30d 100644 --- a/vendor/github.com/spf13/afero/httpFs.go +++ b/vendor/github.com/spf13/afero/httpFs.go @@ -67,6 +67,10 @@ func (h HttpFs) Chmod(name string, mode os.FileMode) error { return h.source.Chmod(name, mode) } +func (h HttpFs) Chown(name string, uid, gid int) error { + return h.source.Chown(name, uid, gid) +} + func (h HttpFs) Chtimes(name string, atime time.Time, mtime time.Time) error { return h.source.Chtimes(name, atime, mtime) } diff --git a/vendor/github.com/spf13/afero/mem/file.go b/vendor/github.com/spf13/afero/mem/file.go index 699f1fb0..290369ad 100644 --- a/vendor/github.com/spf13/afero/mem/file.go +++ b/vendor/github.com/spf13/afero/mem/file.go @@ -22,10 +22,9 @@ import ( "path/filepath" "sync" "sync/atomic" + "time" ) -import "time" - const FilePathSeparator = string(filepath.Separator) type File struct { @@ -57,6 +56,8 @@ type FileData struct { dir bool mode os.FileMode modtime time.Time + uid int + gid int } func (d *FileData) Name() string { @@ -95,6 +96,18 @@ func setModTime(f *FileData, mtime time.Time) { f.modtime = mtime } +func SetUID(f *FileData, uid int) { + f.Lock() + f.uid = uid + f.Unlock() +} + +func SetGID(f *FileData, gid int) { + f.Lock() + f.gid = gid + f.Unlock() +} + func GetFileInfo(f *FileData) *FileInfo { return &FileInfo{f} } @@ -210,6 +223,8 @@ func (f *File) Truncate(size int64) error { if size < 0 { return ErrOutOfRange } + f.fileData.Lock() + defer f.fileData.Unlock() if size > int64(len(f.fileData.data)) { diff := size - int64(len(f.fileData.data)) f.fileData.data = append(f.fileData.data, bytes.Repeat([]byte{00}, int(diff))...) @@ -225,11 +240,11 @@ func (f *File) Seek(offset int64, whence int) (int64, error) { return 0, ErrFileClosed } switch whence { - case 0: + case io.SeekStart: atomic.StoreInt64(&f.at, offset) - case 1: - atomic.AddInt64(&f.at, int64(offset)) - case 2: + case io.SeekCurrent: + atomic.AddInt64(&f.at, offset) + case io.SeekEnd: atomic.StoreInt64(&f.at, int64(len(f.fileData.data))+offset) } return f.at, nil @@ -260,7 +275,7 @@ func (f *File) Write(b []byte) (n int, err error) { } setModTime(f.fileData, time.Now()) - atomic.StoreInt64(&f.at, int64(len(f.fileData.data))) + atomic.AddInt64(&f.at, int64(n)) return } diff --git a/vendor/github.com/spf13/afero/memmap.go b/vendor/github.com/spf13/afero/memmap.go index bbcc2381..5c265f92 100644 --- a/vendor/github.com/spf13/afero/memmap.go +++ b/vendor/github.com/spf13/afero/memmap.go @@ -317,6 +317,11 @@ func (m *MemMapFs) Rename(oldname, newname string) error { return nil } +func (m *MemMapFs) LstatIfPossible(name string) (os.FileInfo, bool, error) { + fileInfo, err := m.Stat(name) + return fileInfo, false, err +} + func (m *MemMapFs) Stat(name string) (os.FileInfo, error) { f, err := m.Open(name) if err != nil { @@ -358,6 +363,22 @@ func (m *MemMapFs) setFileMode(name string, mode os.FileMode) error { return nil } +func (m *MemMapFs) Chown(name string, uid, gid int) error { + name = normalizePath(name) + + m.mu.RLock() + f, ok := m.getData()[name] + m.mu.RUnlock() + if !ok { + return &os.PathError{Op: "chown", Path: name, Err: ErrFileNotFound} + } + + mem.SetUID(f, uid) + mem.SetGID(f, gid) + + return nil +} + func (m *MemMapFs) Chtimes(name string, atime time.Time, mtime time.Time) error { name = normalizePath(name) @@ -381,9 +402,3 @@ func (m *MemMapFs) List() { fmt.Println(x.Name(), y.Size()) } } - -// func debugMemMapList(fs Fs) { -// if x, ok := fs.(*MemMapFs); ok { -// x.List() -// } -// } diff --git a/vendor/github.com/spf13/afero/os.go b/vendor/github.com/spf13/afero/os.go index 4761db5d..f1366321 100644 --- a/vendor/github.com/spf13/afero/os.go +++ b/vendor/github.com/spf13/afero/os.go @@ -91,6 +91,10 @@ func (OsFs) Chmod(name string, mode os.FileMode) error { return os.Chmod(name, mode) } +func (OsFs) Chown(name string, uid, gid int) error { + return os.Chown(name, uid, gid) +} + func (OsFs) Chtimes(name string, atime time.Time, mtime time.Time) error { return os.Chtimes(name, atime, mtime) } diff --git a/vendor/github.com/spf13/afero/readonlyfs.go b/vendor/github.com/spf13/afero/readonlyfs.go index f94b181b..bd8f9264 100644 --- a/vendor/github.com/spf13/afero/readonlyfs.go +++ b/vendor/github.com/spf13/afero/readonlyfs.go @@ -28,6 +28,10 @@ func (r *ReadOnlyFs) Chmod(n string, m os.FileMode) error { return syscall.EPERM } +func (r *ReadOnlyFs) Chown(n string, uid, gid int) error { + return syscall.EPERM +} + func (r *ReadOnlyFs) Name() string { return "ReadOnlyFilter" } diff --git a/vendor/github.com/spf13/afero/regexpfs.go b/vendor/github.com/spf13/afero/regexpfs.go index c8fc0086..ac359c62 100644 --- a/vendor/github.com/spf13/afero/regexpfs.go +++ b/vendor/github.com/spf13/afero/regexpfs.go @@ -60,6 +60,13 @@ func (r *RegexpFs) Chmod(name string, mode os.FileMode) error { return r.source.Chmod(name, mode) } +func (r *RegexpFs) Chown(name string, uid, gid int) error { + if err := r.dirOrMatches(name); err != nil { + return err + } + return r.source.Chown(name, uid, gid) +} + func (r *RegexpFs) Name() string { return "RegexpFs" } diff --git a/vendor/github.com/spf13/afero/unionFile.go b/vendor/github.com/spf13/afero/unionFile.go index eda96312..985363ee 100644 --- a/vendor/github.com/spf13/afero/unionFile.go +++ b/vendor/github.com/spf13/afero/unionFile.go @@ -186,25 +186,22 @@ func (f *UnionFile) Readdir(c int) (ofi []os.FileInfo, err error) { } f.files = append(f.files, merged...) } + files := f.files[f.off:] - if c <= 0 && len(f.files) == 0 { - return f.files, nil + if c <= 0 { + return files, nil } - if f.off >= len(f.files) { + if len(files) == 0 { return nil, io.EOF } - if c <= 0 { - return f.files[f.off:], nil - } - - if c > len(f.files) { - c = len(f.files) + if c > len(files) { + c = len(files) } defer func() { f.off += c }() - return f.files[f.off:c], nil + return files[:c], nil } func (f *UnionFile) Readdirnames(c int) ([]string, error) { diff --git a/vendor/github.com/spf13/viper/.golangci.yml b/vendor/github.com/spf13/viper/.golangci.yml index a0755ce7..a7b73810 100644 --- a/vendor/github.com/spf13/viper/.golangci.yml +++ b/vendor/github.com/spf13/viper/.golangci.yml @@ -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 + + # fixme + # - errcheck + # - gochecknoglobals + # - gochecknoinits + # - gocognit + # - gocritic + # - gocyclo + # - godot + # - gosec + # - gosimple + # - lll + # - nlreturn + # - scopelint - # TODO: fix me - - wsl - - gochecknoinits - - gosimple - - gochecknoglobals - - errcheck - - lll - - godox - - scopelint - - gocyclo - - gocognit - - gocritic + # unused + # - depguard + # - goheader + # - gomodguard -service: - golangci-lint-version: 1.21.x + # don't enable: + # - asciicheck + # - funlen + # - godox + # - goerr113 + # - gomnd + # - interfacer + # - maligned + # - nestif + # - testpackage + # - wsl diff --git a/vendor/github.com/spf13/viper/Makefile b/vendor/github.com/spf13/viper/Makefile index 1c2cab03..b1796c9d 100644 --- a/vendor/github.com/spf13/viper/Makefile +++ b/vendor/github.com/spf13/viper/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 @@ -49,7 +49,7 @@ bin/golangci-lint: bin/golangci-lint-${GOLANGCI_VERSION} bin/golangci-lint-${GOLANGCI_VERSION}: @mkdir -p bin curl -sfL https://install.goreleaser.com/github.com/golangci/golangci-lint.sh | bash -s -- -b ./bin/ v${GOLANGCI_VERSION} - @mv bin/golangci-lint $@ + @mv bin/golangci-lint "$@" .PHONY: lint lint: bin/golangci-lint ## Run linter diff --git a/vendor/github.com/spf13/viper/README.md b/vendor/github.com/spf13/viper/README.md index dfd8034f..766537f4 100644 --- a/vendor/github.com/spf13/viper/README.md +++ b/vendor/github.com/spf13/viper/README.md @@ -1,11 +1,18 @@ +> ## 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/workflow/status/spf13/viper/CI?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.dev reference](https://img.shields.io/badge/go.dev-reference-007d9c?logo=go&logoColor=white&style=flat-square)](https://pkg.go.dev/mod/github.com/spf13/viper) +![Go Version](https://img.shields.io/badge/go%20version-%3E=1.14-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!** @@ -24,10 +31,12 @@ Many Go projects are built using Viper including: ## Install -```console +```shell go get github.com/spf13/viper ``` +**Note:** Viper uses [Go Modules](https://github.com/golang/go/wiki/Modules) to manage dependencies. + ## What is Viper? @@ -245,9 +254,10 @@ 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 two parameters. The first parameter is the key name, the -second is the name of the environment variable. The name of the environment -variable is case sensitive. If the ENV variable name is not provided, then +`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". @@ -259,7 +269,7 @@ 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 a environment variable with a name matching the key uppercased and +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 @@ -582,6 +592,33 @@ 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: + +```json +{ + "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. @@ -607,14 +644,15 @@ will be returned instead. E.g. GetString("datastore.metric.host") // returns "0.0.0.0" ``` -### Extract sub-tree +### Extracting a sub-tree -Extract sub-tree from Viper. +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, `viper` represents: +For example, an application might use multiple different cache stores for different purposes: -```json -app: +```yaml +cache: cache1: max-items: 100 item-size: 64 @@ -623,35 +661,36 @@ app: item-size: 80 ``` -After executing: +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. -```go -subv := viper.Sub("app.cache1") -``` +So instead of doing that let's pass a Viper instance to the constructor that represents a subset of the configuration: -`subv` represents: +```go +cache1Config := viper.Sub("cache.cache1") +if cache1Config == nil { // Sub returns nil if the key cannot be found + panic("cache configuration not found") +} -```json -max-items: 100 -item-size: 64 +cache1 := NewCache(cache1Config) ``` -Suppose we have: +**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(cfg *Viper) *Cache {...} +func NewCache(v *Viper) *Cache { + return &Cache{ + MaxItems: v.GetInt("max-items"), + ItemSize: v.GetInt("item-size"), + } +} ``` -which creates a cache based on config information formatted as `subv`. -Now it’s easy to create these 2 caches separately as: - -```go -cfg1 := viper.Sub("app.cache1") -cache1 := NewCache(cfg1) +The resulting code is easy to test, since it's decoupled from the main config structure, +and easier to reuse (for the same reason). -cfg2 := viper.Sub("app.cache2") -cache2 := NewCache(cfg2) -``` ### Unmarshaling @@ -792,15 +831,32 @@ y.SetDefault("ContentDir", "foobar") When working with multiple vipers, it is up to the user to keep track of the different vipers. + ## Q & A -Q: Why is it called “Viper”? +### 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. -Q: Why is it called “Cobra”? +### 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 + + +## Troubleshooting -A: Is there a better name for a [commander](http://en.wikipedia.org/wiki/Cobra_Commander)? +See [TROUBLESHOOTING.md](TROUBLESHOOTING.md). diff --git a/vendor/github.com/spf13/viper/TROUBLESHOOTING.md b/vendor/github.com/spf13/viper/TROUBLESHOOTING.md new file mode 100644 index 00000000..096277af --- /dev/null +++ b/vendor/github.com/spf13/viper/TROUBLESHOOTING.md @@ -0,0 +1,23 @@ +# 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://github.com/golang/go/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://github.com/golang/go/wiki/Modules) on how to do that. + +**tl;dr* `export GO111MODULE=on` diff --git a/vendor/github.com/spf13/viper/go.mod b/vendor/github.com/spf13/viper/go.mod index 7d108dcc..2fb5610d 100644 --- a/vendor/github.com/spf13/viper/go.mod +++ b/vendor/github.com/spf13/viper/go.mod @@ -18,16 +18,16 @@ require ( github.com/hashicorp/hcl v1.0.0 github.com/jonboulle/clockwork v0.1.0 // indirect github.com/magiconair/properties v1.8.1 - github.com/mitchellh/mapstructure v1.1.2 + github.com/mitchellh/mapstructure v1.3.3 github.com/pelletier/go-toml v1.2.0 github.com/prometheus/client_golang v0.9.3 // indirect github.com/smartystreets/goconvey v1.6.4 // indirect github.com/soheilhy/cmux v0.1.4 // indirect - github.com/spf13/afero v1.1.2 + github.com/spf13/afero v1.5.1 github.com/spf13/cast v1.3.0 github.com/spf13/jwalterweatherman v1.0.0 github.com/spf13/pflag v1.0.3 - github.com/stretchr/testify v1.3.0 + github.com/stretchr/testify v1.4.0 github.com/subosito/gotenv v1.2.0 github.com/tmc/grpc-websocket-proxy v0.0.0-20190109142713-0ad062ec5ee5 // indirect github.com/xiang90/probing v0.0.0-20190116061207-43a291ad63a2 // indirect diff --git a/vendor/github.com/spf13/viper/go.sum b/vendor/github.com/spf13/viper/go.sum index 463aa7db..ed04a580 100644 --- a/vendor/github.com/spf13/viper/go.sum +++ b/vendor/github.com/spf13/viper/go.sum @@ -72,7 +72,6 @@ github.com/golang/mock v1.1.1/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfb github.com/golang/mock v1.2.0/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A= github.com/golang/mock v1.3.1/go.mod h1:sBzyDLLjw3U8JLTeZvSv8jJB+tU5PVekmnlKIyFUx0Y= github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= -github.com/golang/protobuf v1.3.1 h1:YF8+flBXS5eO826T4nzqPrxfhQThhXl0YzfuUPu4SBg= github.com/golang/protobuf v1.3.1/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= github.com/golang/protobuf v1.3.2 h1:6nsPYzhq5kReh6QImI3k5qWzO4PEbvbIW2cwSfR/6xs= github.com/golang/protobuf v1.3.2/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= @@ -147,6 +146,7 @@ github.com/kisielk/errcheck v1.1.0/go.mod h1:EZBBE59ingxPouuu3KfxchcWSUPOHkagtvW github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck= github.com/konsorten/go-windows-terminal-sequences v1.0.1 h1:mweAR1A6xJ3oS2pRaGiHgQ4OO8tzTaLawm8vnODuwDk= github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= +github.com/kr/fs v0.1.0/go.mod h1:FFnZGqtBN9Gxj7eW1uZ42v5BccTP0vu6NEaFoC2HwRg= github.com/kr/logfmt v0.0.0-20140226030751-b84e30acd515/go.mod h1:+0opPa2QZZtGFBFZlji/RkVcI2GknAs/DXo4wKdlNEc= github.com/kr/pretty v0.1.0 h1:L/CwN0zerZDmRFUapSPitk6f+Q3+0za1rQkzVuMiMFI= github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo= @@ -169,8 +169,9 @@ github.com/mitchellh/go-testing-interface v1.0.0/go.mod h1:kRemZodwjscx+RGhAo8eI github.com/mitchellh/gox v0.4.0/go.mod h1:Sd9lOJ0+aimLBi73mGofS1ycjY8lL3uZM3JPS42BGNg= github.com/mitchellh/iochan v1.0.0/go.mod h1:JwYml1nuB7xOzsp52dPpHFffvOCDupsG0QubkSMEySY= github.com/mitchellh/mapstructure v0.0.0-20160808181253-ca63d7c062ee/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y= -github.com/mitchellh/mapstructure v1.1.2 h1:fmNYVwqnSfB9mZU6OS2O6GsXM+wcskZDuKQzvN1EDeE= github.com/mitchellh/mapstructure v1.1.2/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y= +github.com/mitchellh/mapstructure v1.3.3 h1:SzB1nHZ2Xi+17FP0zVQBHIZqvwRN9408fJO8h+eeNA8= +github.com/mitchellh/mapstructure v1.3.3/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo= github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd h1:TRLaZ9cD/w8PVh93nsPXa1VrQ6jlwL5oN8l14QlcNfg= github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= github.com/modern-go/reflect2 v1.0.1 h1:9f412s+6RmYXLWZSEzVVgPGK7C2PphHj5RJrvfx9AWI= @@ -181,10 +182,10 @@ github.com/pascaldekloe/goe v0.0.0-20180627143212-57f6aae5913c h1:Lgl0gzECD8GnQ5 github.com/pascaldekloe/goe v0.0.0-20180627143212-57f6aae5913c/go.mod h1:lzWF7FIEvWOWxwDKqyGYQf6ZUaNfKdP144TG7ZOy1lc= github.com/pelletier/go-toml v1.2.0 h1:T5zMGML61Wp+FlcbWjRDT7yAxhJNAiPPLOFECq181zc= github.com/pelletier/go-toml v1.2.0/go.mod h1:5z9KED0ma1S8pY6P1sdut58dfprrGBbd/94hg7ilaic= -github.com/pkg/errors v0.8.0 h1:WdK/asTD0HN+q6hsWO3/vpuAkAr+tw6aNJNDFFf0+qw= github.com/pkg/errors v0.8.0/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= github.com/pkg/errors v0.8.1 h1:iURUrRGxPUNPdy5/HRSm+Yj6okJ6UtLINN0Q9M4+h3I= github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= +github.com/pkg/sftp v1.10.1/go.mod h1:lYOWFsE0bwd1+KfKJaKeuokY15vzFx25BLbzYYoAxZI= github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= github.com/posener/complete v1.1.1/go.mod h1:em0nMJCgc9GFtwrmVmEMR/ZL6WyhyjMBndrE9hABlRI= @@ -215,8 +216,8 @@ github.com/smartystreets/goconvey v1.6.4/go.mod h1:syvi0/a8iFYH4r/RixwvyeAJjdLS9 github.com/soheilhy/cmux v0.1.4 h1:0HKaf1o97UwFjHH9o5XsHUOF+tqmdA7KEzXLpiyaw0E= github.com/soheilhy/cmux v0.1.4/go.mod h1:IM3LyeVVIOuxMH7sFAkER9+bJ4dT7Ms6E4xg4kGIyLM= github.com/spaolacci/murmur3 v0.0.0-20180118202830-f09979ecbc72/go.mod h1:JwIasOWyU6f++ZhiEuf87xNszmSA2myDM2Kzu9HwQUA= -github.com/spf13/afero v1.1.2 h1:m8/z1t7/fwjysjQRYbP0RD+bUIF/8tJwPdEZsI83ACI= -github.com/spf13/afero v1.1.2/go.mod h1:j4pytiNVoe2o6bmDsKpLACNPDBIoEAkihy7loJ1B0CQ= +github.com/spf13/afero v1.5.1 h1:VHu76Lk0LSP1x254maIu2bplkWpfBWI+B+6fdoZprcg= +github.com/spf13/afero v1.5.1/go.mod h1:Ai8FlHk4v/PARR026UzYexafAt9roJ7LcLMAmO6Z93I= github.com/spf13/cast v1.3.0 h1:oget//CVOEoFewqQxwr0Ej5yjygnqGkvggSE/gB35Q8= github.com/spf13/cast v1.3.0/go.mod h1:Qx5cxh0v+4UWYiBimWS+eyWzqEqokIECu5etghLkUJE= github.com/spf13/jwalterweatherman v1.0.0 h1:XHEdyB+EcvlqZamSM4ZOMGlc93t6AcsBEu9Gc1vn7yk= @@ -225,10 +226,10 @@ github.com/spf13/pflag v1.0.3 h1:zPAT6CGy6wXeQ7NtTnaTerfKOsV6V6F8agHXFiazDkg= github.com/spf13/pflag v1.0.3/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4= github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= -github.com/stretchr/testify v1.2.2 h1:bSDNvY7ZPG5RlJ8otE/7V6gMiyenm9RtJ7IUVIAoJ1w= github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= -github.com/stretchr/testify v1.3.0 h1:TivCn/peBQ7UY8ooIcPgZFpTNSz0Q2U6UrFlUfqbe0Q= github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= +github.com/stretchr/testify v1.4.0 h1:2E4SXV/wtOkTonXsotYi4li6zVWxYlZuYNCXe9XRJyk= +github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4= github.com/subosito/gotenv v1.2.0 h1:Slr1R9HxAlEKefgq5jn9U+DnETlIUa6HfgEzj0g5d7s= github.com/subosito/gotenv v1.2.0/go.mod h1:N0PQaV/YGNqwC0u51sEeR/aUtSLEXKX9iv69rRypqCw= github.com/tmc/grpc-websocket-proxy v0.0.0-20190109142713-0ad062ec5ee5 h1:LnC5Kc/wtumK+WB441p7ynQJzVuNRJiqddSIE3IlSEQ= @@ -248,11 +249,11 @@ go.uber.org/zap v1.10.0 h1:ORx85nbTijNz8ljznvCMR1ZBIPKFn3jQrag10X2AsuM= go.uber.org/zap v1.10.0/go.mod h1:vwi/ZaCAaUcBkycHslxD9B2zi4UTXhF60s6SWpuDF0Q= golang.org/x/crypto v0.0.0-20180904163835-0709b304e793/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= golang.org/x/crypto v0.0.0-20181029021203-45a5f77698d3/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= -golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2 h1:VklqNMn3ovrHsnt90PveolxSbWFaJdECFbxSq0Mqo2M= golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= golang.org/x/crypto v0.0.0-20190510104115-cbcb75029529/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= -golang.org/x/crypto v0.0.0-20190605123033-f99c8df09eb5 h1:58fnuSXlxZmFdJyvtTFVmVhcMLU6v5fEb/ok4wyqtNU= golang.org/x/crypto v0.0.0-20190605123033-f99c8df09eb5/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= +golang.org/x/crypto v0.0.0-20190820162420-60c769a6c586 h1:7KByu05hhLed2MO29w7p1XfZvZ13m8mub3shuVftRs0= +golang.org/x/crypto v0.0.0-20190820162420-60c769a6c586/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= golang.org/x/exp v0.0.0-20190306152737-a1d7652674e8/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= golang.org/x/exp v0.0.0-20190510132918-efd6b22b2522/go.mod h1:ZjyILWgesfNpC6sMxTJOJm9Kp84zZh5NQWvqDGG3Qr8= @@ -304,7 +305,6 @@ golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5h golang.org/x/sys v0.0.0-20181026203630-95b1ffbd15a5/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20181107165924-66b7b1311ac8/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20181116152217-5ac8a444bdc5/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= -golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a h1:1BGLXjeY4akVXGgbC9HugT3Jv3hCI0z56oJR5vAMgBU= golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190312061237-fead79001313/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= @@ -313,11 +313,11 @@ golang.org/x/sys v0.0.0-20190507160741-ecd444e8653b/go.mod h1:h1NjWce9XRLGQEsW7w golang.org/x/sys v0.0.0-20190606165138-5da285871e9c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190624142023-c5567b49c5d0 h1:HyfiK1WMnHj5FXFXatD+Qs1A/xC2Run6RzeW1SyHxpc= golang.org/x/sys v0.0.0-20190624142023-c5567b49c5d0/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/text v0.3.0 h1:g61tztE5qeGQ89tm6NTjjM9VPIm088od1l6aSorWRWg= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.1-0.20180807135948-17ff2d5776d2/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= -golang.org/x/text v0.3.2 h1:tW2bmiBqwgJj/UpqtC8EpXEZVYOwU0yG4iWbprSVAcs= golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk= +golang.org/x/text v0.3.3 h1:cokOdA+Jmi5PJGXLlLllQSgYigAEfHXJAERHVMaCc2k= +golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.0.0-20190308202827-9d24e82272b4 h1:SvFZT6jyqRaOeXpc5h/JSfZenJ2O330aBsf7JfSUXmQ= golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= @@ -328,7 +328,6 @@ golang.org/x/tools v0.0.0-20190226205152-f727befe758c/go.mod h1:9Yl7xja0Znq3iFh3 golang.org/x/tools v0.0.0-20190311212946-11955173bddd/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= golang.org/x/tools v0.0.0-20190312151545-0bb0c0a6e846/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= golang.org/x/tools v0.0.0-20190312170243-e65039ee4138/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= -golang.org/x/tools v0.0.0-20190328211700-ab21143f2384 h1:TFlARGu6Czu1z7q93HTxcP1P+/ZFC/IKythI5RzrnRg= golang.org/x/tools v0.0.0-20190328211700-ab21143f2384/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= golang.org/x/tools v0.0.0-20190425150028-36563e24a262/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q= golang.org/x/tools v0.0.0-20190506145303-2d16b83fe98c/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q= @@ -352,7 +351,6 @@ google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7 google.golang.org/appengine v1.5.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= google.golang.org/appengine v1.6.1 h1:QzqyMA1tlu6CgqCDUtU9V+ZKhLFT2dkJuANu5QaxI3I= google.golang.org/appengine v1.6.1/go.mod h1:i06prIuMbXzDqacNJfV5OdTW448YApPu5ww/cMBSeb0= -google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8 h1:Nw54tB0rB7hY/N0NQvRW8DG4Yk3Q6T9cu9RcFQDu1tc= google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc= google.golang.org/genproto v0.0.0-20190307195333-5fe7a883aa19/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= google.golang.org/genproto v0.0.0-20190418145605-e7d98fc518a7/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= @@ -368,7 +366,6 @@ google.golang.org/grpc v1.20.1/go.mod h1:10oTOabMzJvdu6/UiuZezV6QK5dSlG84ov/aaiq google.golang.org/grpc v1.21.1 h1:j6XxA85m/6txkUCHvzlV5f+HBNl/1r5cZ2A/3IEFOO8= google.golang.org/grpc v1.21.1/go.mod h1:oYelfM1adQP15Ek0mdvEgi9Df8B9CZIaU1084ijfRaM= gopkg.in/alecthomas/kingpin.v2 v2.2.6/go.mod h1:FMv+mEhP44yOT+4EoQTLFTRgOQ1FBLkstjWtayDeSgw= -gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127 h1:qIbj1fsPNlZgppZ+VLlY7N33q108Sa+fhmuc+sWQYwY= gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= @@ -378,6 +375,7 @@ gopkg.in/ini.v1 v1.51.0/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k= gopkg.in/resty.v1 v1.12.0/go.mod h1:mDo4pnntr5jdWRML875a/NmxYqAlA73dVijT2AXvQQo= gopkg.in/yaml.v2 v2.0.0-20170812160011-eb3733d160e7/go.mod h1:JAlM8MvJe8wmxCU4Bli9HhUf9+ttbYbLASfIpnQbh74= gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= +gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.2.4 h1:/eiJrUcujPVeJ3xlSWaiNi3uSVmDGBK1pDHUHAnao1I= gopkg.in/yaml.v2 v2.2.4/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= diff --git a/vendor/github.com/spf13/viper/viper.go b/vendor/github.com/spf13/viper/viper.go index 405dc20f..42220fc8 100644 --- a/vendor/github.com/spf13/viper/viper.go +++ b/vendor/github.com/spf13/viper/viper.go @@ -30,6 +30,7 @@ import ( "os" "path/filepath" "reflect" + "strconv" "strings" "sync" "time" @@ -205,7 +206,7 @@ type Viper struct { defaults map[string]interface{} kvstore map[string]interface{} pflags map[string]FlagValue - env map[string]string + env map[string][]string aliases map[string]string typeByDefValue bool @@ -228,7 +229,7 @@ func New() *Viper { v.defaults = make(map[string]interface{}) v.kvstore = make(map[string]interface{}) v.pflags = make(map[string]FlagValue) - v.env = make(map[string]string) + v.env = make(map[string][]string) v.aliases = make(map[string]string) v.typeByDefValue = false @@ -409,6 +410,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 +421,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 +440,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 +469,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 +491,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) @@ -577,9 +583,9 @@ func (v *Viper) searchMap(source map[string]interface{}, path []string) interfac return nil } -// searchMapWithPathPrefixes recursively searches for a value for path in source map. +// searchIndexableWithPathPrefixes recursively searches for a value for path in source map/slice. // -// While searchMap() considers each path element as a single map key, this +// 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"]. @@ -588,7 +594,7 @@ func (v *Viper) searchMap(source map[string]interface{}, path []string) interfac // in their keys). // // Note: This assumes that the path entries and map keys are lower cased. -func (v *Viper) searchMapWithPathPrefixes(source map[string]interface{}, path []string) interface{} { +func (v *Viper) searchIndexableWithPathPrefixes(source interface{}, path []string) interface{} { if len(path) == 0 { return source } @@ -597,28 +603,15 @@ func (v *Viper) searchMapWithPathPrefixes(source map[string]interface{}, path [] for i := len(path); i > 0; i-- { prefixKey := strings.ToLower(strings.Join(path[0:i], v.keyDelim)) - next, ok := source[prefixKey] - if ok { - // Fast path - if i == len(path) { - return next - } - - // Nested case - var val interface{} - switch next.(type) { - case map[interface{}]interface{}: - val = v.searchMapWithPathPrefixes(cast.ToStringMap(next), path[i:]) - case map[string]interface{}: - // Type assertion is safe here since it is only reached - // if the type of `next` is the same as the type being asserted - val = v.searchMapWithPathPrefixes(next.(map[string]interface{}), path[i:]) - default: - // got a value but nested key expected, do nothing and look for next prefix - } - if val != nil { - return val - } + var val interface{} + switch sourceIndexable := source.(type) { + case []interface{}: + val = v.searchSliceWithPathPrefixes(sourceIndexable, prefixKey, i, path) + case map[string]interface{}: + val = v.searchMapWithPathPrefixes(sourceIndexable, prefixKey, i, path) + } + if val != nil { + return val } } @@ -626,6 +619,76 @@ func (v *Viper) searchMapWithPathPrefixes(source map[string]interface{}, path [] 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 []interface{}, + prefixKey string, + pathIndex int, + path []string, +) interface{} { + // 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[interface{}]interface{}: + return v.searchIndexableWithPathPrefixes(cast.ToStringMap(n), path[pathIndex:]) + case map[string]interface{}, []interface{}: + 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]interface{}, + prefixKey string, + pathIndex int, + path []string, +) interface{} { + next, ok := sourceMap[prefixKey] + if !ok { + return nil + } + + // Fast path + if pathIndex == len(path) { + return next + } + + // Nested case + switch n := next.(type) { + case map[interface{}]interface{}: + return v.searchIndexableWithPathPrefixes(cast.ToStringMap(n), path[pathIndex:]) + case map[string]interface{}, []interface{}: + 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” @@ -706,6 +769,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 +787,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 +838,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,96 +855,112 @@ 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)) } // 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)) } @@ -886,6 +968,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) @@ -895,6 +978,7 @@ 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 { return decode(v.Get(key), defaultDecoderConfig(rawVal, opts...)) } @@ -904,6 +988,7 @@ 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 { return decode(v.AllSettings(), defaultDecoderConfig(rawVal, opts...)) } @@ -940,6 +1025,7 @@ 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 @@ -950,6 +1036,7 @@ func (v *Viper) UnmarshalExact(rawVal interface{}, opts ...DecoderConfigOption) // 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}) } @@ -961,13 +1048,18 @@ 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 { + 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 { @@ -979,6 +1071,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) @@ -990,24 +1083,24 @@ func (v *Viper) BindFlagValue(key string, flag FlagValue) error { // 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 { - var key, envkey string if len(input) == 0 { return fmt.Errorf("missing key to bind to") } - key = strings.ToLower(input[0]) + key := strings.ToLower(input[0]) if len(input) == 1 { - envkey = v.mergeWithEnvPrefix(key) + v.env[key] = append(v.env[key], v.mergeWithEnvPrefix(key)) } else { - envkey = input[1] + v.env[key] = append(v.env[key], input[1:]...) } - v.env[key] = envkey - return nil } @@ -1055,7 +1148,7 @@ func (v *Viper) find(lcaseKey string, flagDefault bool) interface{} { return cast.ToInt(flag.ValueString()) case "bool": return cast.ToBool(flag.ValueString()) - case "stringSlice": + case "stringSlice", "stringArray": s := strings.TrimPrefix(flag.ValueString(), "[") s = strings.TrimSuffix(s, "]") res, _ := readAsCSV(s) @@ -1086,10 +1179,12 @@ func (v *Viper) find(lcaseKey string, flagDefault bool) interface{} { return nil } } - envkey, exists := v.env[lcaseKey] + envkeys, exists := v.env[lcaseKey] if exists { - if val, ok := v.getEnv(envkey); ok { - return val + for _, envkey := range envkeys { + if val, ok := v.getEnv(envkey); ok { + return val + } } } if nested && v.isPathShadowedInFlatMap(path, v.env) != "" { @@ -1097,7 +1192,7 @@ func (v *Viper) find(lcaseKey string, flagDefault bool) interface{} { } // Config file next - val = v.searchMapWithPathPrefixes(v.config, path) + val = v.searchIndexableWithPathPrefixes(v.config, path) if val != nil { return val } @@ -1132,7 +1227,7 @@ func (v *Viper) find(lcaseKey string, flagDefault bool) interface{} { return cast.ToInt(flag.ValueString()) case "bool": return cast.ToBool(flag.ValueString()) - case "stringSlice": + case "stringSlice", "stringArray": s := strings.TrimPrefix(flag.ValueString(), "[") s = strings.TrimSuffix(s, "]") res, _ := readAsCSV(s) @@ -1190,15 +1285,17 @@ 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) return val != nil } -// AutomaticEnv has Viper check ENV variables for all. -// keys set in config, default & flags +// 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 } @@ -1207,6 +1304,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 } @@ -1214,6 +1312,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)) } @@ -1261,6 +1360,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) @@ -1273,6 +1373,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)) @@ -1291,6 +1392,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)) @@ -1307,6 +1409,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() @@ -1337,6 +1440,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() @@ -1359,6 +1463,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) @@ -1366,6 +1471,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 { @@ -1377,6 +1483,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{}) @@ -1388,6 +1495,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 { @@ -1398,6 +1506,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'") @@ -1407,12 +1516,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 { @@ -1463,6 +1574,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) @@ -1631,7 +1743,7 @@ func (v *Viper) marshalWriter(f afero.File, configType string) error { if sectionName == "default" { sectionName = "" } - cfg.Section(sectionName).Key(keyName).SetValue(v.Get(key).(string)) + cfg.Section(sectionName).Key(keyName).SetValue(v.GetString(key)) } cfg.WriteTo(f) } @@ -1658,6 +1770,14 @@ func castToMapStringInterface( return tgt } +func castMapStringSliceToMapInterface(src map[string][]string) map[string]interface{} { + tgt := map[string]interface{}{} + for k, v := range src { + tgt[k] = v + } + return tgt +} + func castMapStringToMapInterface(src map[string]string) map[string]interface{} { tgt := map[string]interface{}{} for k, v := range src { @@ -1737,6 +1857,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() } @@ -1759,9 +1880,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") @@ -1818,13 +1943,14 @@ 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 m = v.flattenAndMergeMap(m, castMapStringToMapInterface(v.aliases), "") m = v.flattenAndMergeMap(m, v.override, "") m = v.mergeFlatMap(m, castMapFlagToMapInterface(v.pflags)) - m = v.mergeFlatMap(m, castMapStringToMapInterface(v.env)) + 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, "") @@ -1898,6 +2024,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 @@ -1919,6 +2046,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 } @@ -1926,6 +2054,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 @@ -1936,6 +2065,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 @@ -1944,6 +2074,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() } @@ -2014,6 +2145,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) diff --git a/vendor/modules.txt b/vendor/modules.txt index b98a727d..989b2499 100644 --- a/vendor/modules.txt +++ b/vendor/modules.txt @@ -152,7 +152,6 @@ github.com/magiconair/properties ## explicit github.com/mitchellh/go-homedir # github.com/mitchellh/mapstructure v1.3.3 -## explicit github.com/mitchellh/mapstructure # github.com/moby/sys/mount v0.2.0 ## explicit @@ -186,8 +185,7 @@ github.com/pkg/errors ## explicit github.com/sirupsen/logrus github.com/sirupsen/logrus/hooks/writer -# github.com/spf13/afero v1.3.4 -## explicit +# github.com/spf13/afero v1.5.1 github.com/spf13/afero github.com/spf13/afero/mem # github.com/spf13/cast v1.3.1 @@ -201,7 +199,7 @@ github.com/spf13/cobra github.com/spf13/jwalterweatherman # github.com/spf13/pflag v1.0.5 github.com/spf13/pflag -# github.com/spf13/viper v1.7.1 +# github.com/spf13/viper v1.7.1 => github.com/iwilltry42/viper v1.7.2-iwilltry42.0 ## explicit github.com/spf13/viper # github.com/stretchr/testify v1.7.0 @@ -384,3 +382,4 @@ sigs.k8s.io/structured-merge-diff/v4/value # sigs.k8s.io/yaml v1.2.0 ## explicit sigs.k8s.io/yaml +# github.com/spf13/viper => github.com/iwilltry42/viper v1.7.2-iwilltry42.0