Merge branch 'master' into bugfix/map-interface-cast

This commit is contained in:
linuxsong 2023-10-07 11:38:38 +08:00 committed by GitHub
commit d5282b8564
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
49 changed files with 642 additions and 914 deletions

View file

@ -11,7 +11,7 @@ jobs:
steps: steps:
- name: Check minimum labels - name: Check minimum labels
uses: mheap/github-action-required-labels@v5 uses: mheap/github-action-required-labels@4e9ef4ce8c697cf55716ecbf7f13a3d9e0b6ac6a # v5.1.0
with: with:
mode: minimum mode: minimum
count: 1 count: 1

View file

@ -21,12 +21,12 @@ jobs:
steps: steps:
- name: Checkout repository - name: Checkout repository
uses: actions/checkout@c85c95e3d7251135ab7dc9ce3241c5835cc595a9 # v3.5.3 uses: actions/checkout@8ade135a41bc03ea155e62e844d188df1ea18608 # v4.1.0
- name: Set up Go - name: Set up Go
uses: actions/setup-go@v4 uses: actions/setup-go@93397bea11091df50f3d7e59dc26a7711a8bcfbe # v4.1.0
with: with:
go-version: '1.20' go-version: '1.21'
- name: Build - name: Build
run: go build . run: go build .
@ -44,23 +44,24 @@ jobs:
fail-fast: false fail-fast: false
matrix: matrix:
os: [ubuntu-latest, macos-latest, windows-latest] os: [ubuntu-latest, macos-latest, windows-latest]
go: ['1.18', '1.19', '1.20'] go: ['1.19', '1.20', '1.21']
tags: ['', 'finder']
steps: steps:
- name: Checkout repository - name: Checkout repository
uses: actions/checkout@c85c95e3d7251135ab7dc9ce3241c5835cc595a9 # v3.5.3 uses: actions/checkout@8ade135a41bc03ea155e62e844d188df1ea18608 # v4.1.0
- name: Set up Go - name: Set up Go
uses: actions/setup-go@v4 uses: actions/setup-go@93397bea11091df50f3d7e59dc26a7711a8bcfbe # v4.1.0
with: with:
go-version: ${{ matrix.go }} go-version: ${{ matrix.go }}
- name: Test - name: Test
run: go test -race -v ./... run: go test -race -v -tags '${{ matrix.tags }}' ./...
if: runner.os != 'Windows' if: runner.os != 'Windows'
- name: Test (without race detector) - name: Test (without race detector)
run: go test -v ./... run: go test -v -tags '${{ matrix.tags }}' ./...
if: runner.os == 'Windows' if: runner.os == 'Windows'
lint: lint:
@ -69,17 +70,17 @@ jobs:
steps: steps:
- name: Checkout repository - name: Checkout repository
uses: actions/checkout@c85c95e3d7251135ab7dc9ce3241c5835cc595a9 # v3.5.3 uses: actions/checkout@8ade135a41bc03ea155e62e844d188df1ea18608 # v4.1.0
- name: Set up Go - name: Set up Go
uses: actions/setup-go@v4 uses: actions/setup-go@93397bea11091df50f3d7e59dc26a7711a8bcfbe # v4.1.0
with: with:
go-version: '1.20' go-version: '1.21'
- name: Lint - name: Lint
uses: golangci/golangci-lint-action@v3 uses: golangci/golangci-lint-action@3a919529898de77ec3da873e3063ca4b10e7f5cc # v3.7.0
with: with:
version: v1.53.3 version: v1.54.2
dev: dev:
name: Developer environment name: Developer environment
@ -87,10 +88,10 @@ jobs:
steps: steps:
- name: Checkout repository - name: Checkout repository
uses: actions/checkout@c85c95e3d7251135ab7dc9ce3241c5835cc595a9 # v3.5.3 uses: actions/checkout@8ade135a41bc03ea155e62e844d188df1ea18608 # v4.1.0
- name: Set up Nix - name: Set up Nix
uses: cachix/install-nix-action@6ed004b9ccb68dbc28e7c85bee15fa93dbd214ac # v22 uses: cachix/install-nix-action@6a9a9e84a173d90b3ffb42c5ddaf9ea033fad011 # v23
with: with:
extra_nix_config: | extra_nix_config: |
access-tokens = github.com=${{ secrets.GITHUB_TOKEN }} access-tokens = github.com=${{ secrets.GITHUB_TOKEN }}
@ -108,7 +109,7 @@ jobs:
steps: steps:
- name: Checkout repository - name: Checkout repository
uses: actions/checkout@c85c95e3d7251135ab7dc9ce3241c5835cc595a9 # v3.5.3 uses: actions/checkout@8ade135a41bc03ea155e62e844d188df1ea18608 # v4.1.0
- name: Dependency Review - name: Dependency Review
uses: actions/dependency-review-action@1360a344ccb0ab6e9475edef90ad2f46bf8003b1 # v3.0.6 uses: actions/dependency-review-action@6c5ccdad469c9f8a2996bfecaec55a631a347034 # v3.1.0

View file

@ -39,11 +39,11 @@ jobs:
steps: steps:
- name: Checkout repository - name: Checkout repository
uses: actions/checkout@v3 uses: actions/checkout@8ade135a41bc03ea155e62e844d188df1ea18608 # v4.1.0
# Initializes the CodeQL tools for scanning. # Initializes the CodeQL tools for scanning.
- name: Initialize CodeQL - name: Initialize CodeQL
uses: github/codeql-action/init@v2 uses: github/codeql-action/init@ddccb873888234080b77e9bc2d4764d5ccaaccf9 # v2.21.9
with: with:
languages: ${{ matrix.language }} languages: ${{ matrix.language }}
# If you wish to specify custom queries, you can do so here or in a config file. # If you wish to specify custom queries, you can do so here or in a config file.
@ -54,7 +54,7 @@ jobs:
# Autobuild attempts to build any compiled languages (C/C++, C#, or Java). # Autobuild attempts to build any compiled languages (C/C++, C#, or Java).
# If this step fails, then you should remove it and run the build manually (see below) # If this step fails, then you should remove it and run the build manually (see below)
- name: Autobuild - name: Autobuild
uses: github/codeql-action/autobuild@v2 uses: github/codeql-action/autobuild@ddccb873888234080b77e9bc2d4764d5ccaaccf9 # v2.21.9
# Command-line programs to run using the OS shell. # Command-line programs to run using the OS shell.
# 📚 https://git.io/JvXDl # 📚 https://git.io/JvXDl
@ -68,5 +68,5 @@ jobs:
# make release # make release
- name: Perform CodeQL Analysis - name: Perform CodeQL Analysis
uses: github/codeql-action/analyze@v2 uses: github/codeql-action/analyze@ddccb873888234080b77e9bc2d4764d5ccaaccf9 # v2.21.9

View file

@ -6,7 +6,7 @@ jobs:
comment: comment:
runs-on: ubuntu-latest runs-on: ubuntu-latest
steps: steps:
- uses: actions/github-script@v6 - uses: actions/github-script@d7906e4ad0b1822421a7e6a35d5ca353c962f410 # v6.4.1
with: with:
github-token: ${{secrets.GITHUB_TOKEN}} github-token: ${{secrets.GITHUB_TOKEN}}
script: | script: |

View file

@ -6,7 +6,7 @@ jobs:
comment: comment:
runs-on: ubuntu-latest runs-on: ubuntu-latest
steps: steps:
- uses: actions/github-script@v6 - uses: actions/github-script@d7906e4ad0b1822421a7e6a35d5ca353c962f410 # v6.4.1
with: with:
github-token: ${{secrets.GITHUB_TOKEN}} github-token: ${{secrets.GITHUB_TOKEN}}
script: | script: |

View file

@ -66,9 +66,9 @@ bin/golangci-lint:
@mkdir -p bin @mkdir -p bin
curl -sSfL https://raw.githubusercontent.com/golangci/golangci-lint/master/install.sh | bash -s -- v${GOLANGCI_VERSION} curl -sSfL https://raw.githubusercontent.com/golangci/golangci-lint/master/install.sh | bash -s -- v${GOLANGCI_VERSION}
.PHONY: fmt .PHONY: yamllint
yamllint: yamllint:
pip install --user yamllint pip3 install --user yamllint
# Add custom targets here # Add custom targets here
-include custom.mk -include custom.mk

View file

@ -11,7 +11,7 @@
[![GitHub Workflow Status](https://img.shields.io/github/actions/workflow/status/spf13/viper/ci.yaml?branch=master&style=flat-square)](https://github.com/spf13/viper/actions?query=workflow%3ACI) [![GitHub Workflow Status](https://img.shields.io/github/actions/workflow/status/spf13/viper/ci.yaml?branch=master&style=flat-square)](https://github.com/spf13/viper/actions?query=workflow%3ACI)
[![Join the chat at https://gitter.im/spf13/viper](https://badges.gitter.im/Join%20Chat.svg)](https://gitter.im/spf13/viper?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge) [![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 Report Card](https://goreportcard.com/badge/github.com/spf13/viper?style=flat-square)](https://goreportcard.com/report/github.com/spf13/viper)
![Go Version](https://img.shields.io/badge/go%20version-%3E=1.18-61CFDD.svg?style=flat-square) ![Go Version](https://img.shields.io/badge/go%20version-%3E=1.19-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) [![PkgGoDev](https://pkg.go.dev/badge/mod/github.com/spf13/viper)](https://pkg.go.dev/mod/github.com/spf13/viper)
**Go configuration with fangs!** **Go configuration with fangs!**
@ -30,6 +30,7 @@ Many Go projects are built using Viper including:
* [Meshery](https://github.com/meshery/meshery) * [Meshery](https://github.com/meshery/meshery)
* [Bearer](https://github.com/bearer/bearer) * [Bearer](https://github.com/bearer/bearer)
* [Coder](https://github.com/coder/coder) * [Coder](https://github.com/coder/coder)
* [Vitess](https://vitess.io/)
## Install ## Install
@ -140,7 +141,7 @@ if err := viper.ReadInConfig(); err != nil {
// Config file found and successfully parsed // Config file found and successfully parsed
``` ```
*NOTE [since 1.6]:* You can also have a file without an extension and specify the format programmaticaly. For those configuration files that lie in the home of the user without any extension like `.bashrc` *NOTE [since 1.6]:* You can also have a file without an extension and specify the format programmatically. For those configuration files that lie in the home of the user without any extension like `.bashrc`
### Writing Config Files ### Writing Config Files
@ -221,6 +222,7 @@ These could be from a command line flag, or from your own application logic.
```go ```go
viper.Set("Verbose", true) viper.Set("Verbose", true)
viper.Set("LogFile", LogFile) viper.Set("LogFile", LogFile)
viper.Set("host.port", 5899) // set subset
``` ```
### Registering and Using Aliases ### Registering and Using Aliases
@ -487,6 +489,15 @@ err := viper.ReadRemoteConfig()
Of course, you're allowed to use `SecureRemoteProvider` also Of course, you're allowed to use `SecureRemoteProvider` also
#### NATS
```go
viper.AddRemoteProvider("nats", "nats://127.0.0.1:4222", "myapp.config")
viper.SetConfigType("json")
err := viper.ReadRemoteConfig()
```
### Remote Key/Value Store Example - Encrypted ### Remote Key/Value Store Example - Encrypted
```go ```go
@ -534,19 +545,19 @@ go func(){
In Viper, there are a few ways to get a value depending on the values type. In Viper, there are a few ways to get a value depending on the values type.
The following functions and methods exist: The following functions and methods exist:
* `Get(key string) : interface{}` * `Get(key string) : any`
* `GetBool(key string) : bool` * `GetBool(key string) : bool`
* `GetFloat64(key string) : float64` * `GetFloat64(key string) : float64`
* `GetInt(key string) : int` * `GetInt(key string) : int`
* `GetIntSlice(key string) : []int` * `GetIntSlice(key string) : []int`
* `GetString(key string) : string` * `GetString(key string) : string`
* `GetStringMap(key string) : map[string]interface{}` * `GetStringMap(key string) : map[string]any`
* `GetStringMapString(key string) : map[string]string` * `GetStringMapString(key string) : map[string]string`
* `GetStringSlice(key string) : []string` * `GetStringSlice(key string) : []string`
* `GetTime(key string) : time.Time` * `GetTime(key string) : time.Time`
* `GetDuration(key string) : time.Duration` * `GetDuration(key string) : time.Duration`
* `IsSet(key string) : bool` * `IsSet(key string) : bool`
* `AllSettings() : map[string]interface{}` * `AllSettings() : map[string]any`
One important thing to recognize is that each Get function will return a zero One important thing to recognize is that each Get function will return a zero
value if its not found. To check if a given key exists, the `IsSet()` method value if its not found. To check if a given key exists, the `IsSet()` method
@ -709,8 +720,8 @@ etc.
There are two methods to do this: There are two methods to do this:
* `Unmarshal(rawVal interface{}) : error` * `Unmarshal(rawVal any) : error`
* `UnmarshalKey(key string, rawVal interface{}) : error` * `UnmarshalKey(key string, rawVal any) : error`
Example: Example:
@ -735,9 +746,9 @@ you have to change the delimiter:
```go ```go
v := viper.NewWithOptions(viper.KeyDelimiter("::")) v := viper.NewWithOptions(viper.KeyDelimiter("::"))
v.SetDefault("chart::values", map[string]interface{}{ v.SetDefault("chart::values", map[string]any{
"ingress": map[string]interface{}{ "ingress": map[string]any{
"annotations": map[string]interface{}{ "annotations": map[string]any{
"traefik.frontend.rule.type": "PathPrefix", "traefik.frontend.rule.type": "PathPrefix",
"traefik.ingress.kubernetes.io/ssl-redirect": "true", "traefik.ingress.kubernetes.io/ssl-redirect": "true",
}, },
@ -746,7 +757,7 @@ v.SetDefault("chart::values", map[string]interface{}{
type config struct { type config struct {
Chart struct{ Chart struct{
Values map[string]interface{} Values map[string]any
} }
} }

View file

@ -1,11 +0,0 @@
//go:build viper_logger
// +build viper_logger
package viper
// WithLogger sets a custom logger.
func WithLogger(l Logger) Option {
return optionFunc(func(v *Viper) {
v.logger = l
})
}

View file

@ -1,5 +1,4 @@
//go:build !go1.16 || !finder //go:build !finder
// +build !go1.16 !finder
package viper package viper

38
file_finder.go Normal file
View file

@ -0,0 +1,38 @@
//go:build finder
package viper
import (
"fmt"
"github.com/sagikazarmark/locafero"
)
// Search all configPaths for any config file.
// Returns the first path that exists (and is a config file).
func (v *Viper) findConfigFile() (string, error) {
var names []string
if v.configType != "" {
names = locafero.NameWithOptionalExtensions(v.configName, SupportedExts...)
} else {
names = locafero.NameWithExtensions(v.configName, SupportedExts...)
}
finder := locafero.Finder{
Paths: v.configPaths,
Names: names,
Type: locafero.FileTypeFile,
}
results, err := finder.Find(v.fs)
if err != nil {
return "", err
}
if len(results) == 0 {
return "", ConfigFileNotFoundError{v.configName, fmt.Sprintf("%s", v.configPaths)}
}
return results[0], nil
}

View file

@ -30,7 +30,7 @@ func (p pflagValueSet) VisitAll(fn func(flag FlagValue)) {
}) })
} }
// pflagValue is a wrapper aroung *pflag.flag // pflagValue is a wrapper around *pflag.flag
// that implements FlagValue // that implements FlagValue
type pflagValue struct { type pflagValue struct {
flag *pflag.Flag flag *pflag.Flag

View file

@ -39,7 +39,7 @@ func TestBindFlagValueSet(t *testing.T) {
}) })
for name, expected := range mutatedTestValues { for name, expected := range mutatedTestValues {
assert.Equal(t, Get(name), expected) assert.Equal(t, expected, Get(name))
} }
} }

65
fs.go
View file

@ -1,65 +0,0 @@
//go:build go1.16 && finder
// +build go1.16,finder
package viper
import (
"errors"
"io/fs"
"path"
)
type finder struct {
paths []string
fileNames []string
extensions []string
withoutExtension bool
}
func (f finder) Find(fsys fs.FS) (string, error) {
for _, searchPath := range f.paths {
for _, fileName := range f.fileNames {
for _, extension := range f.extensions {
filePath := path.Join(searchPath, fileName+"."+extension)
ok, err := fileExists(fsys, filePath)
if err != nil {
return "", err
}
if ok {
return filePath, nil
}
}
if f.withoutExtension {
filePath := path.Join(searchPath, fileName)
ok, err := fileExists(fsys, filePath)
if err != nil {
return "", err
}
if ok {
return filePath, nil
}
}
}
}
return "", nil
}
func fileExists(fsys fs.FS, filePath string) (bool, error) {
fileInfo, err := fs.Stat(fsys, filePath)
if err == nil {
return !fileInfo.IsDir(), nil
}
if errors.Is(err, fs.ErrNotExist) {
return false, nil
}
return false, err
}

View file

@ -1,100 +0,0 @@
//go:build go1.16 && finder
// +build go1.16,finder
package viper
import (
"io/fs"
"testing"
"testing/fstest"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
)
func TestFinder(t *testing.T) {
t.Parallel()
fsys := fstest.MapFS{
"home/user/.config": &fstest.MapFile{},
"home/user/config.json": &fstest.MapFile{},
"home/user/config.yaml": &fstest.MapFile{},
"home/user/data.json": &fstest.MapFile{},
"etc/config/.config": &fstest.MapFile{},
"etc/config/a_random_file.txt": &fstest.MapFile{},
"etc/config/config.json": &fstest.MapFile{},
"etc/config/config.yaml": &fstest.MapFile{},
"etc/config/config.xml": &fstest.MapFile{},
}
testCases := []struct {
name string
fsys func() fs.FS
finder finder
result string
}{
{
name: "find file",
fsys: func() fs.FS { return fsys },
finder: finder{
paths: []string{"etc/config"},
fileNames: []string{"config"},
extensions: []string{"json"},
},
result: "etc/config/config.json",
},
{
name: "file not found",
fsys: func() fs.FS { return fsys },
finder: finder{
paths: []string{"var/config"},
fileNames: []string{"config"},
extensions: []string{"json"},
},
result: "",
},
{
name: "empty search params",
fsys: func() fs.FS { return fsys },
finder: finder{},
result: "",
},
{
name: "precedence",
fsys: func() fs.FS { return fsys },
finder: finder{
paths: []string{"var/config", "home/user", "etc/config"},
fileNames: []string{"aconfig", "config"},
extensions: []string{"zml", "xml", "json"},
},
result: "home/user/config.json",
},
{
name: "without extension",
fsys: func() fs.FS { return fsys },
finder: finder{
paths: []string{"var/config", "home/user", "etc/config"},
fileNames: []string{".config"},
extensions: []string{"zml", "xml", "json"},
withoutExtension: true,
},
result: "home/user/.config",
},
}
for _, testCase := range testCases {
testCase := testCase
t.Run(testCase.name, func(t *testing.T) {
t.Parallel()
fsys := testCase.fsys()
result, err := testCase.finder.Find(fsys)
require.NoError(t, err)
assert.Equal(t, testCase.result, result)
})
}
}

58
go.mod
View file

@ -7,24 +7,25 @@ require (
github.com/hashicorp/hcl v1.0.0 github.com/hashicorp/hcl v1.0.0
github.com/magiconair/properties v1.8.7 github.com/magiconair/properties v1.8.7
github.com/mitchellh/mapstructure v1.5.0 github.com/mitchellh/mapstructure v1.5.0
github.com/pelletier/go-toml/v2 v2.0.8 github.com/pelletier/go-toml/v2 v2.1.0
github.com/sagikazarmark/crypt v0.11.0 github.com/sagikazarmark/crypt v0.15.0
github.com/spf13/afero v1.9.5 github.com/sagikazarmark/locafero v0.3.0
github.com/sagikazarmark/slog-shim v0.1.0
github.com/spf13/afero v1.10.0
github.com/spf13/cast v1.5.1 github.com/spf13/cast v1.5.1
github.com/spf13/jwalterweatherman v1.1.0
github.com/spf13/pflag v1.0.5 github.com/spf13/pflag v1.0.5
github.com/stretchr/testify v1.8.4 github.com/stretchr/testify v1.8.4
github.com/subosito/gotenv v1.4.2 github.com/subosito/gotenv v1.6.0
gopkg.in/ini.v1 v1.67.0 gopkg.in/ini.v1 v1.67.0
gopkg.in/yaml.v3 v3.0.1 gopkg.in/yaml.v3 v3.0.1
) )
require ( require (
cloud.google.com/go v0.110.2 // indirect cloud.google.com/go v0.110.7 // indirect
cloud.google.com/go/compute v1.19.3 // indirect cloud.google.com/go/compute v1.23.0 // indirect
cloud.google.com/go/compute/metadata v0.2.3 // indirect cloud.google.com/go/compute/metadata v0.2.3 // indirect
cloud.google.com/go/firestore v1.11.0 // indirect cloud.google.com/go/firestore v1.13.0 // indirect
cloud.google.com/go/longrunning v0.5.0 // indirect cloud.google.com/go/longrunning v0.5.1 // indirect
github.com/armon/go-metrics v0.4.1 // indirect github.com/armon/go-metrics v0.4.1 // indirect
github.com/coreos/go-semver v0.3.0 // indirect github.com/coreos/go-semver v0.3.0 // indirect
github.com/coreos/go-systemd/v22 v22.3.2 // indirect github.com/coreos/go-systemd/v22 v22.3.2 // indirect
@ -34,10 +35,10 @@ require (
github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da // indirect github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da // indirect
github.com/golang/protobuf v1.5.3 // indirect github.com/golang/protobuf v1.5.3 // indirect
github.com/google/go-cmp v0.5.9 // indirect github.com/google/go-cmp v0.5.9 // indirect
github.com/google/s2a-go v0.1.4 // indirect github.com/google/s2a-go v0.1.7 // indirect
github.com/googleapis/enterprise-certificate-proxy v0.2.5 // indirect github.com/googleapis/enterprise-certificate-proxy v0.3.1 // indirect
github.com/googleapis/gax-go/v2 v2.11.0 // indirect github.com/googleapis/gax-go/v2 v2.12.0 // indirect
github.com/hashicorp/consul/api v1.22.0 // indirect github.com/hashicorp/consul/api v1.25.1 // indirect
github.com/hashicorp/go-cleanhttp v0.5.2 // indirect github.com/hashicorp/go-cleanhttp v0.5.2 // indirect
github.com/hashicorp/go-hclog v1.5.0 // indirect github.com/hashicorp/go-hclog v1.5.0 // indirect
github.com/hashicorp/go-immutable-radix v1.3.1 // indirect github.com/hashicorp/go-immutable-radix v1.3.1 // indirect
@ -45,35 +46,42 @@ require (
github.com/hashicorp/golang-lru v0.5.4 // indirect github.com/hashicorp/golang-lru v0.5.4 // indirect
github.com/hashicorp/serf v0.10.1 // indirect github.com/hashicorp/serf v0.10.1 // indirect
github.com/json-iterator/go v1.1.12 // indirect github.com/json-iterator/go v1.1.12 // indirect
github.com/klauspost/compress v1.17.0 // indirect
github.com/mattn/go-colorable v0.1.13 // indirect github.com/mattn/go-colorable v0.1.13 // indirect
github.com/mattn/go-isatty v0.0.17 // indirect github.com/mattn/go-isatty v0.0.17 // indirect
github.com/minio/highwayhash v1.0.2 // indirect
github.com/mitchellh/go-homedir v1.1.0 // indirect github.com/mitchellh/go-homedir v1.1.0 // indirect
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect
github.com/modern-go/reflect2 v1.0.2 // indirect github.com/modern-go/reflect2 v1.0.2 // indirect
github.com/nats-io/jwt/v2 v2.4.1 // indirect
github.com/nats-io/nats.go v1.30.2 // indirect
github.com/nats-io/nkeys v0.4.5 // indirect
github.com/nats-io/nuid v1.0.1 // indirect
github.com/pkg/errors v0.9.1 // indirect github.com/pkg/errors v0.9.1 // indirect
github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 // indirect github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 // indirect
github.com/sourcegraph/conc v0.3.0 // indirect
go.etcd.io/etcd/api/v3 v3.5.9 // indirect go.etcd.io/etcd/api/v3 v3.5.9 // indirect
go.etcd.io/etcd/client/pkg/v3 v3.5.9 // indirect go.etcd.io/etcd/client/pkg/v3 v3.5.9 // indirect
go.etcd.io/etcd/client/v2 v2.305.9 // indirect go.etcd.io/etcd/client/v2 v2.305.9 // indirect
go.etcd.io/etcd/client/v3 v3.5.9 // indirect go.etcd.io/etcd/client/v3 v3.5.9 // indirect
go.opencensus.io v0.24.0 // indirect go.opencensus.io v0.24.0 // indirect
go.uber.org/atomic v1.9.0 // indirect go.uber.org/atomic v1.9.0 // indirect
go.uber.org/multierr v1.8.0 // indirect go.uber.org/multierr v1.9.0 // indirect
go.uber.org/zap v1.21.0 // indirect go.uber.org/zap v1.21.0 // indirect
golang.org/x/crypto v0.10.0 // indirect golang.org/x/crypto v0.13.0 // indirect
golang.org/x/exp v0.0.0-20230321023759-10a507213a29 // indirect golang.org/x/exp v0.0.0-20230905200255-921286631fa9 // indirect
golang.org/x/net v0.11.0 // indirect golang.org/x/net v0.15.0 // indirect
golang.org/x/oauth2 v0.9.0 // indirect golang.org/x/oauth2 v0.12.0 // indirect
golang.org/x/sync v0.3.0 // indirect golang.org/x/sync v0.3.0 // indirect
golang.org/x/sys v0.9.0 // indirect golang.org/x/sys v0.12.0 // indirect
golang.org/x/text v0.10.0 // indirect golang.org/x/text v0.13.0 // indirect
golang.org/x/time v0.3.0 // indirect golang.org/x/time v0.3.0 // indirect
golang.org/x/xerrors v0.0.0-20220907171357-04be3eba64a2 // indirect golang.org/x/xerrors v0.0.0-20220907171357-04be3eba64a2 // indirect
google.golang.org/api v0.129.0 // indirect google.golang.org/api v0.143.0 // indirect
google.golang.org/appengine v1.6.7 // indirect google.golang.org/appengine v1.6.7 // indirect
google.golang.org/genproto v0.0.0-20230530153820-e85fd2cbaebc // indirect google.golang.org/genproto v0.0.0-20230913181813-007df8e322eb // indirect
google.golang.org/genproto/googleapis/api v0.0.0-20230530153820-e85fd2cbaebc // indirect google.golang.org/genproto/googleapis/api v0.0.0-20230913181813-007df8e322eb // indirect
google.golang.org/genproto/googleapis/rpc v0.0.0-20230530153820-e85fd2cbaebc // indirect google.golang.org/genproto/googleapis/rpc v0.0.0-20230920204549-e6e6cdab5c13 // indirect
google.golang.org/grpc v1.56.1 // indirect google.golang.org/grpc v1.58.2 // indirect
google.golang.org/protobuf v1.31.0 // indirect google.golang.org/protobuf v1.31.0 // indirect
) )

148
go.sum
View file

@ -17,24 +17,24 @@ cloud.google.com/go v0.65.0/go.mod h1:O5N8zS7uWy9vkA9vayVHs65eM1ubvY4h553ofrNHOb
cloud.google.com/go v0.72.0/go.mod h1:M+5Vjvlc2wnp6tjzE102Dw08nGShTscUx2nZMufOKPI= cloud.google.com/go v0.72.0/go.mod h1:M+5Vjvlc2wnp6tjzE102Dw08nGShTscUx2nZMufOKPI=
cloud.google.com/go v0.74.0/go.mod h1:VV1xSbzvo+9QJOxLDaJfTjx5e+MePCpCWwvftOeQmWk= cloud.google.com/go v0.74.0/go.mod h1:VV1xSbzvo+9QJOxLDaJfTjx5e+MePCpCWwvftOeQmWk=
cloud.google.com/go v0.75.0/go.mod h1:VGuuCn7PG0dwsd5XPVm2Mm3wlh3EL55/79EKB6hlPTY= cloud.google.com/go v0.75.0/go.mod h1:VGuuCn7PG0dwsd5XPVm2Mm3wlh3EL55/79EKB6hlPTY=
cloud.google.com/go v0.110.2 h1:sdFPBr6xG9/wkBbfhmUz/JmZC7X6LavQgcrVINrKiVA= cloud.google.com/go v0.110.7 h1:rJyC7nWRg2jWGZ4wSJ5nY65GTdYJkg0cd/uXb+ACI6o=
cloud.google.com/go v0.110.2/go.mod h1:k04UEeEtb6ZBRTv3dZz4CeJC3jKGxyhl0sAiVVquxiw= cloud.google.com/go v0.110.7/go.mod h1:+EYjdK8e5RME/VY/qLCAtuyALQ9q67dvuum8i+H5xsI=
cloud.google.com/go/bigquery v1.0.1/go.mod h1:i/xbL2UlR5RvWAURpBYZTtm/cXjCha9lbfbpx4poX+o= cloud.google.com/go/bigquery v1.0.1/go.mod h1:i/xbL2UlR5RvWAURpBYZTtm/cXjCha9lbfbpx4poX+o=
cloud.google.com/go/bigquery v1.3.0/go.mod h1:PjpwJnslEMmckchkHFfq+HTD2DmtT67aNFKH1/VBDHE= cloud.google.com/go/bigquery v1.3.0/go.mod h1:PjpwJnslEMmckchkHFfq+HTD2DmtT67aNFKH1/VBDHE=
cloud.google.com/go/bigquery v1.4.0/go.mod h1:S8dzgnTigyfTmLBfrtrhyYhwRxG72rYxvftPBK2Dvzc= cloud.google.com/go/bigquery v1.4.0/go.mod h1:S8dzgnTigyfTmLBfrtrhyYhwRxG72rYxvftPBK2Dvzc=
cloud.google.com/go/bigquery v1.5.0/go.mod h1:snEHRnqQbz117VIFhE8bmtwIDY80NLUZUMb4Nv6dBIg= cloud.google.com/go/bigquery v1.5.0/go.mod h1:snEHRnqQbz117VIFhE8bmtwIDY80NLUZUMb4Nv6dBIg=
cloud.google.com/go/bigquery v1.7.0/go.mod h1://okPTzCYNXSlb24MZs83e2Do+h+VXtc4gLoIoXIAPc= cloud.google.com/go/bigquery v1.7.0/go.mod h1://okPTzCYNXSlb24MZs83e2Do+h+VXtc4gLoIoXIAPc=
cloud.google.com/go/bigquery v1.8.0/go.mod h1:J5hqkt3O0uAFnINi6JXValWIb1v0goeZM77hZzJN/fQ= cloud.google.com/go/bigquery v1.8.0/go.mod h1:J5hqkt3O0uAFnINi6JXValWIb1v0goeZM77hZzJN/fQ=
cloud.google.com/go/compute v1.19.3 h1:DcTwsFgGev/wV5+q8o2fzgcHOaac+DKGC91ZlvpsQds= cloud.google.com/go/compute v1.23.0 h1:tP41Zoavr8ptEqaW6j+LQOnyBBhO7OkOMAGrgLopTwY=
cloud.google.com/go/compute v1.19.3/go.mod h1:qxvISKp/gYnXkSAD1ppcSOveRAmzxicEv/JlizULFrI= cloud.google.com/go/compute v1.23.0/go.mod h1:4tCnrn48xsqlwSAiLf1HXMQk8CONslYbdiEZc9FEIbM=
cloud.google.com/go/compute/metadata v0.2.3 h1:mg4jlk7mCAj6xXp9UJ4fjI9VUI5rubuGBW5aJ7UnBMY= cloud.google.com/go/compute/metadata v0.2.3 h1:mg4jlk7mCAj6xXp9UJ4fjI9VUI5rubuGBW5aJ7UnBMY=
cloud.google.com/go/compute/metadata v0.2.3/go.mod h1:VAV5nSsACxMJvgaAuX6Pk2AawlZn8kiOGuCv6gTkwuA= cloud.google.com/go/compute/metadata v0.2.3/go.mod h1:VAV5nSsACxMJvgaAuX6Pk2AawlZn8kiOGuCv6gTkwuA=
cloud.google.com/go/datastore v1.0.0/go.mod h1:LXYbyblFSglQ5pkeyhO+Qmw7ukd3C+pD7TKLgZqpHYE= cloud.google.com/go/datastore v1.0.0/go.mod h1:LXYbyblFSglQ5pkeyhO+Qmw7ukd3C+pD7TKLgZqpHYE=
cloud.google.com/go/datastore v1.1.0/go.mod h1:umbIZjpQpHh4hmRpGhH4tLFup+FVzqBi1b3c64qFpCk= cloud.google.com/go/datastore v1.1.0/go.mod h1:umbIZjpQpHh4hmRpGhH4tLFup+FVzqBi1b3c64qFpCk=
cloud.google.com/go/firestore v1.11.0 h1:PPgtwcYUOXV2jFe1bV3nda3RCrOa8cvBjTOn2MQVfW8= cloud.google.com/go/firestore v1.13.0 h1:/3S4RssUV4GO/kvgJZB+tayjhOfyAHs+KcpJgRVu/Qk=
cloud.google.com/go/firestore v1.11.0/go.mod h1:b38dKhgzlmNNGTNZZwe7ZRFEuRab1Hay3/DBsIGKKy4= cloud.google.com/go/firestore v1.13.0/go.mod h1:QojqqOh8IntInDUSTAh0c8ZsPYAr68Ma8c5DWOy8xb8=
cloud.google.com/go/longrunning v0.5.0 h1:DK8BH0+hS+DIvc9a2TPnteUievsTCH4ORMAASSb7JcQ= cloud.google.com/go/longrunning v0.5.1 h1:Fr7TXftcqTudoyRJa113hyaqlGdiBQkp0Gq7tErFDWI=
cloud.google.com/go/longrunning v0.5.0/go.mod h1:0JNuqRShmscVAhIACGtskSAWtqtOoPkwP0YF1oVEchc= cloud.google.com/go/longrunning v0.5.1/go.mod h1:spvimkwdz6SPWKEt/XBij79E9fiTkHSQl/fRUUQJYJc=
cloud.google.com/go/pubsub v1.0.1/go.mod h1:R0Gpsv3s54REJCy4fxDixWD93lHJMoZTyQ2kNxGRt3I= cloud.google.com/go/pubsub v1.0.1/go.mod h1:R0Gpsv3s54REJCy4fxDixWD93lHJMoZTyQ2kNxGRt3I=
cloud.google.com/go/pubsub v1.1.0/go.mod h1:EwwdRX2sKPjnvnqCa270oGRyludottCI76h+R3AArQw= cloud.google.com/go/pubsub v1.1.0/go.mod h1:EwwdRX2sKPjnvnqCa270oGRyludottCI76h+R3AArQw=
cloud.google.com/go/pubsub v1.2.0/go.mod h1:jhfEVHT8odbXTkndysNHCcx0awwzvfOlguIAii9o8iA= cloud.google.com/go/pubsub v1.2.0/go.mod h1:jhfEVHT8odbXTkndysNHCcx0awwzvfOlguIAii9o8iA=
@ -53,7 +53,6 @@ github.com/alecthomas/template v0.0.0-20160405071501-a0175ee3bccc/go.mod h1:LOuy
github.com/alecthomas/template v0.0.0-20190718012654-fb15b899a751/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc= github.com/alecthomas/template v0.0.0-20190718012654-fb15b899a751/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc=
github.com/alecthomas/units v0.0.0-20151022065526-2efee857e7cf/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0= github.com/alecthomas/units v0.0.0-20151022065526-2efee857e7cf/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0=
github.com/alecthomas/units v0.0.0-20190717042225-c3de453c63f4/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0= github.com/alecthomas/units v0.0.0-20190717042225-c3de453c63f4/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0=
github.com/antihax/optional v1.0.0/go.mod h1:uupD/76wgC+ih3iEmQUL+0Ugr19nfwCT1kdvxnR2qWY=
github.com/armon/circbuf v0.0.0-20150827004946-bbbad097214e/go.mod h1:3U/XgcO3hCbHZ8TKRvWD2dDTCfh9M9ya+I9JpbB7O8o= github.com/armon/circbuf v0.0.0-20150827004946-bbbad097214e/go.mod h1:3U/XgcO3hCbHZ8TKRvWD2dDTCfh9M9ya+I9JpbB7O8o=
github.com/armon/go-metrics v0.0.0-20180917152333-f0300d1749da/go.mod h1:Q73ZrmVTwzkszR9V5SSuryQ31EELlFMUz1kKyl939pY= github.com/armon/go-metrics v0.0.0-20180917152333-f0300d1749da/go.mod h1:Q73ZrmVTwzkszR9V5SSuryQ31EELlFMUz1kKyl939pY=
github.com/armon/go-metrics v0.4.1 h1:hR91U9KYmb6bLBYLQjyM+3j+rcd/UhE+G78SFnF8gJA= github.com/armon/go-metrics v0.4.1 h1:hR91U9KYmb6bLBYLQjyM+3j+rcd/UhE+G78SFnF8gJA=
@ -77,10 +76,6 @@ github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDk
github.com/cncf/udpa/go v0.0.0-20191209042840-269d4d468f6f/go.mod h1:M8M6+tZqaGXZJjfX53e64911xZQV5JYwmTeXPW+k8Sc= github.com/cncf/udpa/go v0.0.0-20191209042840-269d4d468f6f/go.mod h1:M8M6+tZqaGXZJjfX53e64911xZQV5JYwmTeXPW+k8Sc=
github.com/cncf/udpa/go v0.0.0-20200629203442-efcf912fb354/go.mod h1:WmhPx2Nbnhtbo57+VJT5O0JRkEi1Wbu0z5j0R8u5Hbk= github.com/cncf/udpa/go v0.0.0-20200629203442-efcf912fb354/go.mod h1:WmhPx2Nbnhtbo57+VJT5O0JRkEi1Wbu0z5j0R8u5Hbk=
github.com/cncf/udpa/go v0.0.0-20201120205902-5459f2c99403/go.mod h1:WmhPx2Nbnhtbo57+VJT5O0JRkEi1Wbu0z5j0R8u5Hbk= github.com/cncf/udpa/go v0.0.0-20201120205902-5459f2c99403/go.mod h1:WmhPx2Nbnhtbo57+VJT5O0JRkEi1Wbu0z5j0R8u5Hbk=
github.com/cncf/udpa/go v0.0.0-20210930031921-04548b0d99d4/go.mod h1:6pvJx4me5XPnfI9Z40ddWsdw2W/uZgQLFXToKeRcDiI=
github.com/cncf/xds/go v0.0.0-20210805033703-aa0b78936158/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs=
github.com/cncf/xds/go v0.0.0-20210922020428-25de7278fc84/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs=
github.com/cncf/xds/go v0.0.0-20211011173535-cb28da3451f1/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs=
github.com/coreos/go-semver v0.3.0 h1:wkHLiw0WNATZnSG7epLsujiMCgPAc9xhjJ4tgnAxmfM= github.com/coreos/go-semver v0.3.0 h1:wkHLiw0WNATZnSG7epLsujiMCgPAc9xhjJ4tgnAxmfM=
github.com/coreos/go-semver v0.3.0/go.mod h1:nnelYz7RCh+5ahJtPPxZlU+153eP4D4r3EedlOD2RNk= github.com/coreos/go-semver v0.3.0/go.mod h1:nnelYz7RCh+5ahJtPPxZlU+153eP4D4r3EedlOD2RNk=
github.com/coreos/go-systemd/v22 v22.3.2 h1:D9/bQk5vlXQFZ6Kwuu6zaiXJ9oTPe68++AzAJc1DzSI= github.com/coreos/go-systemd/v22 v22.3.2 h1:D9/bQk5vlXQFZ6Kwuu6zaiXJ9oTPe68++AzAJc1DzSI=
@ -94,7 +89,6 @@ github.com/envoyproxy/go-control-plane v0.9.1-0.20191026205805-5f8ba28d4473/go.m
github.com/envoyproxy/go-control-plane v0.9.4/go.mod h1:6rpuAdCZL397s3pYoYcLgu1mIlRU8Am5FuJP05cCM98= github.com/envoyproxy/go-control-plane v0.9.4/go.mod h1:6rpuAdCZL397s3pYoYcLgu1mIlRU8Am5FuJP05cCM98=
github.com/envoyproxy/go-control-plane v0.9.7/go.mod h1:cwu0lG7PUMfa9snN8LXBig5ynNVH9qI8YYLbd1fK2po= github.com/envoyproxy/go-control-plane v0.9.7/go.mod h1:cwu0lG7PUMfa9snN8LXBig5ynNVH9qI8YYLbd1fK2po=
github.com/envoyproxy/go-control-plane v0.9.9-0.20201210154907-fd9021fe5dad/go.mod h1:cXg6YxExXjJnVBQHBLXeUAgxn2UodCpnH306RInaBQk= github.com/envoyproxy/go-control-plane v0.9.9-0.20201210154907-fd9021fe5dad/go.mod h1:cXg6YxExXjJnVBQHBLXeUAgxn2UodCpnH306RInaBQk=
github.com/envoyproxy/go-control-plane v0.9.10-0.20210907150352-cf90f659a021/go.mod h1:AFq3mo9L8Lqqiid3OhADV3RfLJnjiw63cSpi+fDTRC0=
github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c= github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c=
github.com/fatih/color v1.7.0/go.mod h1:Zm6kSWBoL9eyXnKyktHP6abPY2pDugNf5KwzbycvMj4= github.com/fatih/color v1.7.0/go.mod h1:Zm6kSWBoL9eyXnKyktHP6abPY2pDugNf5KwzbycvMj4=
github.com/fatih/color v1.9.0/go.mod h1:eQcE1qtQxscV5RaZvpXrrb8Drkc3/DdQ+uUYCNjL+zU= github.com/fatih/color v1.9.0/go.mod h1:eQcE1qtQxscV5RaZvpXrrb8Drkc3/DdQ+uUYCNjL+zU=
@ -104,7 +98,6 @@ github.com/fatih/color v1.14.1/go.mod h1:2oHN61fhTpgcxD3TSWCgKDiH1+x4OiDVVGH8Wlg
github.com/frankban/quicktest v1.14.4 h1:g2rn0vABPOOXmZUj+vbmUp0lPoXEMuhTpIluN0XL9UY= github.com/frankban/quicktest v1.14.4 h1:g2rn0vABPOOXmZUj+vbmUp0lPoXEMuhTpIluN0XL9UY=
github.com/fsnotify/fsnotify v1.6.0 h1:n+5WquG0fcWoWp6xPWfHdbskMCQaFnG6PfBrh1Ky4HY= github.com/fsnotify/fsnotify v1.6.0 h1:n+5WquG0fcWoWp6xPWfHdbskMCQaFnG6PfBrh1Ky4HY=
github.com/fsnotify/fsnotify v1.6.0/go.mod h1:sl3t1tCWJFWoRz9R8WJCbQihKKwmorjAbSClcnxKAGw= github.com/fsnotify/fsnotify v1.6.0/go.mod h1:sl3t1tCWJFWoRz9R8WJCbQihKKwmorjAbSClcnxKAGw=
github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04=
github.com/go-gl/glfw v0.0.0-20190409004039-e6da0acd62b1/go.mod h1:vR7hzQXu2zJy9AVAgeJqvqgH9Q5CA+iKCZ2gyEVpxRU= github.com/go-gl/glfw v0.0.0-20190409004039-e6da0acd62b1/go.mod h1:vR7hzQXu2zJy9AVAgeJqvqgH9Q5CA+iKCZ2gyEVpxRU=
github.com/go-gl/glfw/v3.3/glfw v0.0.0-20191125211704-12ad95a8df72/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8= github.com/go-gl/glfw/v3.3/glfw v0.0.0-20191125211704-12ad95a8df72/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8=
github.com/go-gl/glfw/v3.3/glfw v0.0.0-20200222043503-6f7a984d4dc4/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8= github.com/go-gl/glfw/v3.3/glfw v0.0.0-20200222043503-6f7a984d4dc4/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8=
@ -145,7 +138,6 @@ github.com/golang/protobuf v1.4.1/go.mod h1:U8fpvMrcmy5pZrNK1lt4xCsGvpyWQ/VVv6QD
github.com/golang/protobuf v1.4.2/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI= github.com/golang/protobuf v1.4.2/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI=
github.com/golang/protobuf v1.4.3/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI= github.com/golang/protobuf v1.4.3/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI=
github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk= github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk=
github.com/golang/protobuf v1.5.2/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY=
github.com/golang/protobuf v1.5.3 h1:KhyjKVUg7Usr/dYsdSqoFveMYd5ko72D+zANwlG1mmg= github.com/golang/protobuf v1.5.3 h1:KhyjKVUg7Usr/dYsdSqoFveMYd5ko72D+zANwlG1mmg=
github.com/golang/protobuf v1.5.3/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY= github.com/golang/protobuf v1.5.3/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY=
github.com/google/btree v0.0.0-20180813153112-4030bb1f1f0c/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ= github.com/google/btree v0.0.0-20180813153112-4030bb1f1f0c/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ=
@ -179,20 +171,19 @@ github.com/google/pprof v0.0.0-20201023163331-3e6fc7fc9c4c/go.mod h1:kpwsk12EmLe
github.com/google/pprof v0.0.0-20201203190320-1bf35d6f28c2/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= github.com/google/pprof v0.0.0-20201203190320-1bf35d6f28c2/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE=
github.com/google/pprof v0.0.0-20201218002935-b9804c9f04c2/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= github.com/google/pprof v0.0.0-20201218002935-b9804c9f04c2/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE=
github.com/google/renameio v0.1.0/go.mod h1:KWCgfxg9yswjAJkECMjeO8J8rahYeXnNhOm40UhjYkI= github.com/google/renameio v0.1.0/go.mod h1:KWCgfxg9yswjAJkECMjeO8J8rahYeXnNhOm40UhjYkI=
github.com/google/s2a-go v0.1.4 h1:1kZ/sQM3srePvKs3tXAvQzo66XfcReoqFpIpIccE7Oc= github.com/google/s2a-go v0.1.7 h1:60BLSyTrOV4/haCDW4zb1guZItoSq8foHCXrAnjBo/o=
github.com/google/s2a-go v0.1.4/go.mod h1:Ej+mSEMGRnqRzjc7VtF+jdBwYG5fuJfiZ8ELkjEwM0A= github.com/google/s2a-go v0.1.7/go.mod h1:50CgR4k1jNlWBu4UfS4AcfhVe1r6pdZPygJ3R8F0Qdw=
github.com/google/uuid v1.1.2/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/google/uuid v1.1.2/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
github.com/googleapis/enterprise-certificate-proxy v0.2.5 h1:UR4rDjcgpgEnqpIEvkiqTYKBCKLNmlge2eVjoZfySzM= github.com/googleapis/enterprise-certificate-proxy v0.3.1 h1:SBWmZhjUDRorQxrN0nwzf+AHBxnbFjViHQS4P0yVpmQ=
github.com/googleapis/enterprise-certificate-proxy v0.2.5/go.mod h1:RxW0N9901Cko1VOCW3SXCpWP+mlIEkk2tP7jnHy9a3w= github.com/googleapis/enterprise-certificate-proxy v0.3.1/go.mod h1:VLSiSSBs/ksPL8kq3OBOQ6WRI2QnaFynd1DCjZ62+V0=
github.com/googleapis/gax-go/v2 v2.0.4/go.mod h1:0Wqv26UfaUD9n4G6kQubkQ+KchISgw+vpHVxEJEs9eg= github.com/googleapis/gax-go/v2 v2.0.4/go.mod h1:0Wqv26UfaUD9n4G6kQubkQ+KchISgw+vpHVxEJEs9eg=
github.com/googleapis/gax-go/v2 v2.0.5/go.mod h1:DWXyrwAJ9X0FpwwEdw+IPEYBICEFu5mhpdKc/us6bOk= github.com/googleapis/gax-go/v2 v2.0.5/go.mod h1:DWXyrwAJ9X0FpwwEdw+IPEYBICEFu5mhpdKc/us6bOk=
github.com/googleapis/gax-go/v2 v2.11.0 h1:9V9PWXEsWnPpQhu/PeQIkS4eGzMlTLGgt80cUUI8Ki4= github.com/googleapis/gax-go/v2 v2.12.0 h1:A+gCJKdRfqXkr+BIRGtZLibNXf0m1f9E4HG56etFpas=
github.com/googleapis/gax-go/v2 v2.11.0/go.mod h1:DxmR61SGKkGLa2xigwuZIQpkCI2S5iydzRfb3peWZJI= github.com/googleapis/gax-go/v2 v2.12.0/go.mod h1:y+aIqrI5eb1YGMVJfuV3185Ts/D7qKpsEkdD5+I6QGU=
github.com/googleapis/google-cloud-go-testing v0.0.0-20200911160855-bcd43fbb19e8/go.mod h1:dvDLG8qkwmyD9a/MJJN3XJcT3xFxOKAvTZGvuZmac9g= github.com/googleapis/google-cloud-go-testing v0.0.0-20200911160855-bcd43fbb19e8/go.mod h1:dvDLG8qkwmyD9a/MJJN3XJcT3xFxOKAvTZGvuZmac9g=
github.com/grpc-ecosystem/grpc-gateway v1.16.0/go.mod h1:BDjrQk3hbvj6Nolgz8mAMFbcEtjT1g+wF4CSlocrBnw= github.com/hashicorp/consul/api v1.25.1 h1:CqrdhYzc8XZuPnhIYZWH45toM0LB9ZeYr/gvpLVI3PE=
github.com/hashicorp/consul/api v1.22.0 h1:ydEvDooB/A0c/xpsBd8GSt7P2/zYPBui4KrNip0xGjE= github.com/hashicorp/consul/api v1.25.1/go.mod h1:iiLVwR/htV7mas/sy0O+XSuEnrdBUUydemjxcUrAt4g=
github.com/hashicorp/consul/api v1.22.0/go.mod h1:zHpYgZ7TeYqS6zaszjwSt128OwESRpnhU9aGa6ue3Eg= github.com/hashicorp/consul/sdk v0.14.1 h1:ZiwE2bKb+zro68sWzZ1SgHF3kRMBZ94TwOCFRF4ylPs=
github.com/hashicorp/consul/sdk v0.14.0 h1:Hly+BMNMssVzoWddbBnBFi3W+Fzytvm0haSkihhj3GU=
github.com/hashicorp/errwrap v1.0.0/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4= github.com/hashicorp/errwrap v1.0.0/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4=
github.com/hashicorp/errwrap v1.1.0 h1:OxrOeh75EUXMY8TBjag2fzXGZ40LB6IKw45YeGUDY2I= github.com/hashicorp/errwrap v1.1.0 h1:OxrOeh75EUXMY8TBjag2fzXGZ40LB6IKw45YeGUDY2I=
github.com/hashicorp/go-cleanhttp v0.5.0/go.mod h1:JpRdi6/HCYpAwUzNwuwqhbovhLtngrth3wmdIIUrZ80= github.com/hashicorp/go-cleanhttp v0.5.0/go.mod h1:JpRdi6/HCYpAwUzNwuwqhbovhLtngrth3wmdIIUrZ80=
@ -241,6 +232,8 @@ github.com/jstemmer/go-junit-report v0.9.1/go.mod h1:Brl9GWCQeLvo8nXZwPNNblvFj/X
github.com/julienschmidt/httprouter v1.2.0/go.mod h1:SYymIcj16QtmaHHD7aYtjjsJG7VTCxuUUipMqKk8s4w= github.com/julienschmidt/httprouter v1.2.0/go.mod h1:SYymIcj16QtmaHHD7aYtjjsJG7VTCxuUUipMqKk8s4w=
github.com/kisielk/errcheck v1.5.0/go.mod h1:pFxgyoBC7bSaBwPgfKdkLd5X25qrDl4LWUI2bnpBCr8= github.com/kisielk/errcheck v1.5.0/go.mod h1:pFxgyoBC7bSaBwPgfKdkLd5X25qrDl4LWUI2bnpBCr8=
github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck= github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck=
github.com/klauspost/compress v1.17.0 h1:Rnbp4K9EjcDuVuHtd0dgA4qNuv9yKDYKK1ulpJwgrqM=
github.com/klauspost/compress v1.17.0/go.mod h1:ntbaceVETuRiXiv4DpjP66DpAtAGkEQskQzEyD//IeE=
github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= 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/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/logfmt v0.0.0-20140226030751-b84e30acd515/go.mod h1:+0opPa2QZZtGFBFZlji/RkVcI2GknAs/DXo4wKdlNEc=
@ -270,6 +263,8 @@ github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5
github.com/miekg/dns v1.1.26/go.mod h1:bPDLeHnStXmXAq1m/Ch/hvfNHr14JKNPMBo3VZKjuso= github.com/miekg/dns v1.1.26/go.mod h1:bPDLeHnStXmXAq1m/Ch/hvfNHr14JKNPMBo3VZKjuso=
github.com/miekg/dns v1.1.41 h1:WMszZWJG0XmzbK9FEmzH2TVcqYzFesusSIB41b8KHxY= github.com/miekg/dns v1.1.41 h1:WMszZWJG0XmzbK9FEmzH2TVcqYzFesusSIB41b8KHxY=
github.com/miekg/dns v1.1.41/go.mod h1:p6aan82bvRIyn+zDIv9xYNUpwa73JcSh9BKwknJysuI= github.com/miekg/dns v1.1.41/go.mod h1:p6aan82bvRIyn+zDIv9xYNUpwa73JcSh9BKwknJysuI=
github.com/minio/highwayhash v1.0.2 h1:Aak5U0nElisjDCfPSG79Tgzkn2gl66NxOMspRrKnA/g=
github.com/minio/highwayhash v1.0.2/go.mod h1:BQskDq+xkJ12lmlUUi7U0M5Swg3EWR+dLTk+kldvVxY=
github.com/mitchellh/cli v1.1.0/go.mod h1:xcISNoH86gajksDmfB23e/pu+B+GeFRMYmoHXxx3xhI= github.com/mitchellh/cli v1.1.0/go.mod h1:xcISNoH86gajksDmfB23e/pu+B+GeFRMYmoHXxx3xhI=
github.com/mitchellh/go-homedir v1.1.0 h1:lukF9ziXFxDFPkA1vsr5zpc1XuPDn/wFntq5mG+4E0Y= github.com/mitchellh/go-homedir v1.1.0 h1:lukF9ziXFxDFPkA1vsr5zpc1XuPDn/wFntq5mG+4E0Y=
github.com/mitchellh/go-homedir v1.1.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0= github.com/mitchellh/go-homedir v1.1.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0=
@ -284,11 +279,20 @@ github.com/modern-go/reflect2 v1.0.1/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3Rllmb
github.com/modern-go/reflect2 v1.0.2 h1:xBagoLtFs94CBntxluKeaWgTMpvLxC4ur3nMaC9Gz0M= github.com/modern-go/reflect2 v1.0.2 h1:xBagoLtFs94CBntxluKeaWgTMpvLxC4ur3nMaC9Gz0M=
github.com/modern-go/reflect2 v1.0.2/go.mod h1:yWuevngMOJpCy52FWWMvUC8ws7m/LJsjYzDa0/r8luk= github.com/modern-go/reflect2 v1.0.2/go.mod h1:yWuevngMOJpCy52FWWMvUC8ws7m/LJsjYzDa0/r8luk=
github.com/mwitkow/go-conntrack v0.0.0-20161129095857-cc309e4a2223/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U= github.com/mwitkow/go-conntrack v0.0.0-20161129095857-cc309e4a2223/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U=
github.com/nats-io/jwt/v2 v2.4.1 h1:Y35W1dgbbz2SQUYDPCaclXcuqleVmpbRa7646Jf2EX4=
github.com/nats-io/jwt/v2 v2.4.1/go.mod h1:24BeQtRwxRV8ruvC4CojXlx/WQ/VjuwlYiH+vu/+ibI=
github.com/nats-io/nats-server/v2 v2.9.20 h1:bt1dW6xsL1hWWwv7Hovm+EJt5L6iplyqlgEFkoEUk0k=
github.com/nats-io/nats.go v1.30.2 h1:aloM0TGpPorZKQhbAkdCzYDj+ZmsJDyeo3Gkbr72NuY=
github.com/nats-io/nats.go v1.30.2/go.mod h1:dcfhUgmQNN4GJEfIb2f9R7Fow+gzBF4emzDHrVBd5qM=
github.com/nats-io/nkeys v0.4.5 h1:Zdz2BUlFm4fJlierwvGK+yl20IAKUm7eV6AAZXEhkPk=
github.com/nats-io/nkeys v0.4.5/go.mod h1:XUkxdLPTufzlihbamfzQ7mw/VGx6ObUs+0bN5sNvt64=
github.com/nats-io/nuid v1.0.1 h1:5iA8DT8V7q8WK2EScv2padNa/rTESc1KdnPw4TC2paw=
github.com/nats-io/nuid v1.0.1/go.mod h1:19wcPz3Ph3q0Jbyiqsd0kePYG7A95tJPxeL+1OSON2c=
github.com/pascaldekloe/goe v0.0.0-20180627143212-57f6aae5913c/go.mod h1:lzWF7FIEvWOWxwDKqyGYQf6ZUaNfKdP144TG7ZOy1lc= github.com/pascaldekloe/goe v0.0.0-20180627143212-57f6aae5913c/go.mod h1:lzWF7FIEvWOWxwDKqyGYQf6ZUaNfKdP144TG7ZOy1lc=
github.com/pascaldekloe/goe v0.1.0 h1:cBOtyMzM9HTpWjXfbbunk26uA6nG3a8n06Wieeh0MwY= github.com/pascaldekloe/goe v0.1.0 h1:cBOtyMzM9HTpWjXfbbunk26uA6nG3a8n06Wieeh0MwY=
github.com/pascaldekloe/goe v0.1.0/go.mod h1:lzWF7FIEvWOWxwDKqyGYQf6ZUaNfKdP144TG7ZOy1lc= github.com/pascaldekloe/goe v0.1.0/go.mod h1:lzWF7FIEvWOWxwDKqyGYQf6ZUaNfKdP144TG7ZOy1lc=
github.com/pelletier/go-toml/v2 v2.0.8 h1:0ctb6s9mE31h0/lhu+J6OPmVeDxJn+kYnJc2jZR9tGQ= github.com/pelletier/go-toml/v2 v2.1.0 h1:FnwAJ4oYMvbT/34k9zzHuZNrhlz48GB3/s6at6/MHO4=
github.com/pelletier/go-toml/v2 v2.0.8/go.mod h1:vuYfssBdrU2XDZ9bYydBu6t+6a6PYNcZljzZR9VXg+4= github.com/pelletier/go-toml/v2 v2.1.0/go.mod h1:tJU2Z3ZkXwnxa4DPO899bsyIoywizdUvyaeZurnPPDc=
github.com/pkg/errors v0.8.0/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= github.com/pkg/errors v0.8.0/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4= github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4=
@ -311,22 +315,25 @@ github.com/prometheus/common v0.9.1/go.mod h1:yhUN8i9wzaXS3w1O07YhxHEBxD+W35wd8b
github.com/prometheus/procfs v0.0.0-20181005140218-185b4288413d/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk= github.com/prometheus/procfs v0.0.0-20181005140218-185b4288413d/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk=
github.com/prometheus/procfs v0.0.2/go.mod h1:TjEm7ze935MbeOT/UhFTIMYKhuLP4wbCsTZCD3I8kEA= github.com/prometheus/procfs v0.0.2/go.mod h1:TjEm7ze935MbeOT/UhFTIMYKhuLP4wbCsTZCD3I8kEA=
github.com/prometheus/procfs v0.0.8/go.mod h1:7Qr8sr6344vo1JqZ6HhLceV9o3AJ1Ff+GxbHq6oeK9A= github.com/prometheus/procfs v0.0.8/go.mod h1:7Qr8sr6344vo1JqZ6HhLceV9o3AJ1Ff+GxbHq6oeK9A=
github.com/rogpeppe/fastuuid v1.2.0/go.mod h1:jVj6XXZzXRy/MSR5jhDC/2q6DgLz+nrA6LYCDYWNEvQ=
github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4= github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4=
github.com/rogpeppe/go-internal v1.9.0 h1:73kH8U+JUqXU8lRuOHeVHaa/SZPifC7BkcraZVejAe8= github.com/rogpeppe/go-internal v1.9.0 h1:73kH8U+JUqXU8lRuOHeVHaa/SZPifC7BkcraZVejAe8=
github.com/ryanuber/columnize v0.0.0-20160712163229-9b3edd62028f/go.mod h1:sm1tb6uqfes/u+d4ooFouqFdy9/2g9QGwK3SQygK0Ts= github.com/ryanuber/columnize v0.0.0-20160712163229-9b3edd62028f/go.mod h1:sm1tb6uqfes/u+d4ooFouqFdy9/2g9QGwK3SQygK0Ts=
github.com/sagikazarmark/crypt v0.11.0 h1:pEFoux+lQBXsS9lGkGKMcQ0fp5W+6HsNfu28yK7bKVE= github.com/sagikazarmark/crypt v0.15.0 h1:TQJg76CemcIdJyC9/dmNjU9OUyIFHyvE50Tpq1t1nqY=
github.com/sagikazarmark/crypt v0.11.0/go.mod h1:04Tna7sDiOkvj4Qs78hSG+5MArl9wwrhEL1NZmblMb0= github.com/sagikazarmark/crypt v0.15.0/go.mod h1:5rwNNax6Mlk9sZ40AcyVtiEw24Z4J04cfSioF2COKmc=
github.com/sagikazarmark/locafero v0.3.0 h1:zT7VEGWC2DTflmccN/5T1etyKvxSxpHsjb9cJvm4SvQ=
github.com/sagikazarmark/locafero v0.3.0/go.mod h1:w+v7UsPNFwzF1cHuOajOOzoq4U7v/ig1mpRjqV+Bu1U=
github.com/sagikazarmark/slog-shim v0.1.0 h1:diDBnUNK9N/354PgrxMywXnAwEr1QZcOr6gto+ugjYE=
github.com/sagikazarmark/slog-shim v0.1.0/go.mod h1:SrcSrq8aKtyuqEI1uvTDTK1arOWRIczQRv+GVI1AkeQ=
github.com/sean-/seed v0.0.0-20170313163322-e2103e2c3529 h1:nn5Wsu0esKSJiIVhscUtVbo7ada43DJhG55ua/hjS5I= github.com/sean-/seed v0.0.0-20170313163322-e2103e2c3529 h1:nn5Wsu0esKSJiIVhscUtVbo7ada43DJhG55ua/hjS5I=
github.com/sean-/seed v0.0.0-20170313163322-e2103e2c3529/go.mod h1:DxrIzT+xaE7yg65j358z/aeFdxmN0P9QXhEzd20vsDc= github.com/sean-/seed v0.0.0-20170313163322-e2103e2c3529/go.mod h1:DxrIzT+xaE7yg65j358z/aeFdxmN0P9QXhEzd20vsDc=
github.com/sirupsen/logrus v1.2.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPxbbu5VWo= github.com/sirupsen/logrus v1.2.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPxbbu5VWo=
github.com/sirupsen/logrus v1.4.2/go.mod h1:tLMulIdttU9McNUspp0xgXVQah82FyeX6MwdIuYE2rE= github.com/sirupsen/logrus v1.4.2/go.mod h1:tLMulIdttU9McNUspp0xgXVQah82FyeX6MwdIuYE2rE=
github.com/spf13/afero v1.9.5 h1:stMpOSZFs//0Lv29HduCmli3GUfpFoF3Y1Q/aXj/wVM= github.com/sourcegraph/conc v0.3.0 h1:OQTbbt6P72L20UqAkXXuLOj79LfEanQ+YQFNpLA9ySo=
github.com/spf13/afero v1.9.5/go.mod h1:UBogFpq8E9Hx+xc5CNTTEpTnuHVmXDwZcZcE1eb/UhQ= github.com/sourcegraph/conc v0.3.0/go.mod h1:Sdozi7LEKbFPqYX2/J+iBAM6HpqSLTASQIKqDmF7Mt0=
github.com/spf13/afero v1.10.0 h1:EaGW2JJh15aKOejeuJ+wpFSHnbd7GE6Wvp3TsNhb6LY=
github.com/spf13/afero v1.10.0/go.mod h1:UBogFpq8E9Hx+xc5CNTTEpTnuHVmXDwZcZcE1eb/UhQ=
github.com/spf13/cast v1.5.1 h1:R+kOtfhWQE6TVQzY+4D7wJLBgkdVasCEFxSUBYBYIlA= github.com/spf13/cast v1.5.1 h1:R+kOtfhWQE6TVQzY+4D7wJLBgkdVasCEFxSUBYBYIlA=
github.com/spf13/cast v1.5.1/go.mod h1:b9PdjNptOpzXr7Rq1q9gJML/2cdGQAo69NKzQ10KN48= github.com/spf13/cast v1.5.1/go.mod h1:b9PdjNptOpzXr7Rq1q9gJML/2cdGQAo69NKzQ10KN48=
github.com/spf13/jwalterweatherman v1.1.0 h1:ue6voC5bR5F8YxI5S67j9i582FU4Qvo2bmqnqMYADFk=
github.com/spf13/jwalterweatherman v1.1.0/go.mod h1:aNWZUN0dPAAO/Ljvb5BEdw96iTZ0EXowPYD95IqWIGo=
github.com/spf13/pflag v1.0.5 h1:iy+VFUOCP1a+8yFto/drg2CJ5u0yRoB7fZw3DKv/JXA= 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/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg=
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
@ -343,18 +350,16 @@ github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/
github.com/stretchr/testify v1.7.2/go.mod h1:R6va5+xMeoiuVRoj+gSkQ7d3FALtqAAGI1FQKckRals= github.com/stretchr/testify v1.7.2/go.mod h1:R6va5+xMeoiuVRoj+gSkQ7d3FALtqAAGI1FQKckRals=
github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU= github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU=
github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4= github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4=
github.com/stretchr/testify v1.8.3/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo=
github.com/stretchr/testify v1.8.4 h1:CcVxjf3Q8PM0mHUKJCdn+eZZtm5yQwehR5yeSVQQcUk= github.com/stretchr/testify v1.8.4 h1:CcVxjf3Q8PM0mHUKJCdn+eZZtm5yQwehR5yeSVQQcUk=
github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo= github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo=
github.com/subosito/gotenv v1.4.2 h1:X1TuBLAMDFbaTAChgCBLu3DU3UPyELpnF2jjJ2cz/S8= github.com/subosito/gotenv v1.6.0 h1:9NlTDc1FTs4qu0DDq7AEtTPNw6SVm7uBMsUCUjABIf8=
github.com/subosito/gotenv v1.4.2/go.mod h1:ayKnFf/c6rvx/2iiLrJUk1e6plDbT3edrFNGqEflhK0= github.com/subosito/gotenv v1.6.0/go.mod h1:Dk4QP5c2W3ibzajGcXpNraDfq2IrhjMIvMSWPKKo0FU=
github.com/tv42/httpunix v0.0.0-20150427012821-b75d8614f926/go.mod h1:9ESjWnEqriFuLhtthL60Sar/7RFoluCcXsuvEwTV5KM= github.com/tv42/httpunix v0.0.0-20150427012821-b75d8614f926/go.mod h1:9ESjWnEqriFuLhtthL60Sar/7RFoluCcXsuvEwTV5KM=
github.com/yuin/goldmark v1.1.25/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/yuin/goldmark v1.1.25/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
github.com/yuin/goldmark v1.1.32/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/yuin/goldmark v1.1.32/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
github.com/yuin/goldmark v1.3.5/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k= github.com/yuin/goldmark v1.3.5/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k=
github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY=
go.etcd.io/etcd/api/v3 v3.5.9 h1:4wSsluwyTbGGmyjJktOf3wFQoTBIURXHnq9n/G/JQHs= go.etcd.io/etcd/api/v3 v3.5.9 h1:4wSsluwyTbGGmyjJktOf3wFQoTBIURXHnq9n/G/JQHs=
go.etcd.io/etcd/api/v3 v3.5.9/go.mod h1:uyAal843mC8uUVSLWz6eHa/d971iDGnCRpmKd2Z+X8k= go.etcd.io/etcd/api/v3 v3.5.9/go.mod h1:uyAal843mC8uUVSLWz6eHa/d971iDGnCRpmKd2Z+X8k=
go.etcd.io/etcd/client/pkg/v3 v3.5.9 h1:oidDC4+YEuSIQbsR94rY9gur91UPL6DnxDCIYd2IGsE= go.etcd.io/etcd/client/pkg/v3 v3.5.9 h1:oidDC4+YEuSIQbsR94rY9gur91UPL6DnxDCIYd2IGsE=
@ -371,15 +376,14 @@ go.opencensus.io v0.22.4/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw=
go.opencensus.io v0.22.5/go.mod h1:5pWMHQbX5EPX2/62yrJeAkowc+lfs/XD7Uxpq3pI6kk= go.opencensus.io v0.22.5/go.mod h1:5pWMHQbX5EPX2/62yrJeAkowc+lfs/XD7Uxpq3pI6kk=
go.opencensus.io v0.24.0 h1:y73uSU6J157QMP2kn2r30vwW1A2W2WFwSCGnAVxeaD0= go.opencensus.io v0.24.0 h1:y73uSU6J157QMP2kn2r30vwW1A2W2WFwSCGnAVxeaD0=
go.opencensus.io v0.24.0/go.mod h1:vNK8G9p7aAivkbmorf4v+7Hgx+Zs0yY+0fOtgBfjQKo= go.opencensus.io v0.24.0/go.mod h1:vNK8G9p7aAivkbmorf4v+7Hgx+Zs0yY+0fOtgBfjQKo=
go.opentelemetry.io/proto/otlp v0.7.0/go.mod h1:PqfVotwruBrMGOCsRd/89rSnXhoiJIqeYNgFYFoEGnI=
go.uber.org/atomic v1.7.0/go.mod h1:fEN4uk6kAWBTFdckzkM89CLk9XfWZrxpCo0nPH17wJc= go.uber.org/atomic v1.7.0/go.mod h1:fEN4uk6kAWBTFdckzkM89CLk9XfWZrxpCo0nPH17wJc=
go.uber.org/atomic v1.9.0 h1:ECmE8Bn/WFTYwEW/bpKD3M8VtR/zQVbavAoalC1PYyE= go.uber.org/atomic v1.9.0 h1:ECmE8Bn/WFTYwEW/bpKD3M8VtR/zQVbavAoalC1PYyE=
go.uber.org/atomic v1.9.0/go.mod h1:fEN4uk6kAWBTFdckzkM89CLk9XfWZrxpCo0nPH17wJc= go.uber.org/atomic v1.9.0/go.mod h1:fEN4uk6kAWBTFdckzkM89CLk9XfWZrxpCo0nPH17wJc=
go.uber.org/goleak v1.1.11 h1:wy28qYRKZgnJTxGxvye5/wgWr1EKjmUDGYox5mGlRlI= go.uber.org/goleak v1.1.11 h1:wy28qYRKZgnJTxGxvye5/wgWr1EKjmUDGYox5mGlRlI=
go.uber.org/goleak v1.1.11/go.mod h1:cwTWslyiVhfpKIDGSZEM2HlOvcqm+tG4zioyIeLoqMQ= go.uber.org/goleak v1.1.11/go.mod h1:cwTWslyiVhfpKIDGSZEM2HlOvcqm+tG4zioyIeLoqMQ=
go.uber.org/multierr v1.6.0/go.mod h1:cdWPpRnG4AhwMwsgIHip0KRBQjJy5kYEpYjJxpXp9iU= go.uber.org/multierr v1.6.0/go.mod h1:cdWPpRnG4AhwMwsgIHip0KRBQjJy5kYEpYjJxpXp9iU=
go.uber.org/multierr v1.8.0 h1:dg6GjLku4EH+249NNmoIciG9N/jURbDG+pFlTkhzIC8= go.uber.org/multierr v1.9.0 h1:7fIwc/ZtS0q++VgcfqFDxSBZVv/Xo49/SYnDFupUwlI=
go.uber.org/multierr v1.8.0/go.mod h1:7EAYxJLBy9rStEaz58O2t4Uvip6FSURkq8/ppBp95ak= go.uber.org/multierr v1.9.0/go.mod h1:X2jQV1h+kxSjClGpnseKVIxpmcjrj7MNnI0bnlfKTVQ=
go.uber.org/zap v1.21.0 h1:WefMeulhovoZ2sYXz7st6K0sLj7bBhpiFaud4r4zST8= go.uber.org/zap v1.21.0 h1:WefMeulhovoZ2sYXz7st6K0sLj7bBhpiFaud4r4zST8=
go.uber.org/zap v1.21.0/go.mod h1:wjWOCqI0f2ZZrJF/UufIOkiC8ii6tm1iqIsLo76RfJw= go.uber.org/zap v1.21.0/go.mod h1:wjWOCqI0f2ZZrJF/UufIOkiC8ii6tm1iqIsLo76RfJw=
golang.org/x/crypto v0.0.0-20180904163835-0709b304e793/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= golang.org/x/crypto v0.0.0-20180904163835-0709b304e793/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
@ -390,11 +394,9 @@ golang.org/x/crypto v0.0.0-20190923035154-9ee001bba392/go.mod h1:/lpIB1dKB+9EgE3
golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
golang.org/x/crypto v0.0.0-20210421170649-83a5a9bb288b/go.mod h1:T9bdIzuCu7OtxOm1hfPfRQxPLYneinmdGuTeoZ9dtd4= golang.org/x/crypto v0.0.0-20210421170649-83a5a9bb288b/go.mod h1:T9bdIzuCu7OtxOm1hfPfRQxPLYneinmdGuTeoZ9dtd4=
golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
golang.org/x/crypto v0.0.0-20220314234659-1baeb1ce4c0b/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4=
golang.org/x/crypto v0.0.0-20220722155217-630584e8d5aa/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4= golang.org/x/crypto v0.0.0-20220722155217-630584e8d5aa/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4=
golang.org/x/crypto v0.10.0 h1:LKqV2xt9+kDzSTfOhx4FrkEBcMrAgHSYgzywV9zcGmM= golang.org/x/crypto v0.13.0 h1:mvySKfSWJ+UKUii46M40LOvyWfN0s2U+46/jDd0e6Ck=
golang.org/x/crypto v0.10.0/go.mod h1:o4eNf7Ede1fv+hwOwZsTHl9EsPFO6q6ZvYR8vYfY45I= golang.org/x/crypto v0.13.0/go.mod h1:y6Z2r+Rw4iayiXXAIxJIDAJ1zMW4yaTpebo8fPOliYc=
golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= 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-20190306152737-a1d7652674e8/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
golang.org/x/exp v0.0.0-20190510132918-efd6b22b2522/go.mod h1:ZjyILWgesfNpC6sMxTJOJm9Kp84zZh5NQWvqDGG3Qr8= golang.org/x/exp v0.0.0-20190510132918-efd6b22b2522/go.mod h1:ZjyILWgesfNpC6sMxTJOJm9Kp84zZh5NQWvqDGG3Qr8=
@ -405,8 +407,8 @@ golang.org/x/exp v0.0.0-20191227195350-da58074b4299/go.mod h1:2RIsYlXP63K8oxa1u0
golang.org/x/exp v0.0.0-20200119233911-0405dc783f0a/go.mod h1:2RIsYlXP63K8oxa1u096TMicItID8zy7Y6sNkU49FU4= golang.org/x/exp v0.0.0-20200119233911-0405dc783f0a/go.mod h1:2RIsYlXP63K8oxa1u096TMicItID8zy7Y6sNkU49FU4=
golang.org/x/exp v0.0.0-20200207192155-f17229e696bd/go.mod h1:J/WKrq2StrnmMY6+EHIKF9dgMWnmCNThgcyBT1FY9mM= golang.org/x/exp v0.0.0-20200207192155-f17229e696bd/go.mod h1:J/WKrq2StrnmMY6+EHIKF9dgMWnmCNThgcyBT1FY9mM=
golang.org/x/exp v0.0.0-20200224162631-6cc2880d07d6/go.mod h1:3jZMyOhIsHpP37uCMkUooju7aAi5cS1Q23tOzKc+0MU= golang.org/x/exp v0.0.0-20200224162631-6cc2880d07d6/go.mod h1:3jZMyOhIsHpP37uCMkUooju7aAi5cS1Q23tOzKc+0MU=
golang.org/x/exp v0.0.0-20230321023759-10a507213a29 h1:ooxPy7fPvB4kwsA2h+iBNHkAbp/4JxTSwCmvdjEYmug= golang.org/x/exp v0.0.0-20230905200255-921286631fa9 h1:GoHiUyI/Tp2nVkLI2mCxVkOjsbSXD66ic0XW0js0R9g=
golang.org/x/exp v0.0.0-20230321023759-10a507213a29/go.mod h1:CxIveKay+FTh1D0yPZemJVgC/95VzuuOLq5Qi4xnoYc= golang.org/x/exp v0.0.0-20230905200255-921286631fa9/go.mod h1:S2oDrQGGwySpoQPVqRShND87VCbxmc6bL1Yd2oYrm6k=
golang.org/x/image v0.0.0-20190227222117-0694c2d4d067/go.mod h1:kZ7UVZpmo3dzQBMxlp+ypCbDeSB+sBbTgSJuh5dn5js= golang.org/x/image v0.0.0-20190227222117-0694c2d4d067/go.mod h1:kZ7UVZpmo3dzQBMxlp+ypCbDeSB+sBbTgSJuh5dn5js=
golang.org/x/image v0.0.0-20190802002840-cff245a6509b/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0= golang.org/x/image v0.0.0-20190802002840-cff245a6509b/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0=
golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE= golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE=
@ -431,7 +433,6 @@ golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
golang.org/x/mod v0.4.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.4.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
golang.org/x/mod v0.4.1/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.4.1/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
golang.org/x/mod v0.4.2/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.4.2/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4=
golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20181114220301-adae6a3d119a/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20181114220301-adae6a3d119a/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
@ -470,9 +471,8 @@ golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v
golang.org/x/net v0.0.0-20210405180319-a5a99cb37ef4/go.mod h1:p54w0d4576C0XHj96bSt6lcn1PtDYWL6XObtHCRCNQM= golang.org/x/net v0.0.0-20210405180319-a5a99cb37ef4/go.mod h1:p54w0d4576C0XHj96bSt6lcn1PtDYWL6XObtHCRCNQM=
golang.org/x/net v0.0.0-20210410081132-afb366fc7cd1/go.mod h1:9tjilg8BloeKEkVJvy7fQ90B1CfIiPueXVOjqfkSzI8= golang.org/x/net v0.0.0-20210410081132-afb366fc7cd1/go.mod h1:9tjilg8BloeKEkVJvy7fQ90B1CfIiPueXVOjqfkSzI8=
golang.org/x/net v0.0.0-20211112202133-69e39bad7dc2/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= golang.org/x/net v0.0.0-20211112202133-69e39bad7dc2/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c= golang.org/x/net v0.15.0 h1:ugBLEUaxABaB5AJqW9enI0ACdci2RUd4eP51NTBvuJ8=
golang.org/x/net v0.11.0 h1:Gi2tvZIJyBtO9SDr1q9h5hEQCp/4L2RQ+ar0qjx2oNU= golang.org/x/net v0.15.0/go.mod h1:idbUs1IY1+zTqbi8yxTbhexhEEk5ur9LInksu6HrEpk=
golang.org/x/net v0.11.0/go.mod h1:2L/ixqYpgIVXmeoSA/4Lu7BzTG4KIyPIryS4IsOd1oQ=
golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
@ -482,8 +482,8 @@ golang.org/x/oauth2 v0.0.0-20200902213428-5d25da1a8d43/go.mod h1:KelEdhl1UZF7XfJ
golang.org/x/oauth2 v0.0.0-20201109201403-9fd604954f58/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= golang.org/x/oauth2 v0.0.0-20201109201403-9fd604954f58/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A=
golang.org/x/oauth2 v0.0.0-20201208152858-08078c50e5b5/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= golang.org/x/oauth2 v0.0.0-20201208152858-08078c50e5b5/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A=
golang.org/x/oauth2 v0.0.0-20210218202405-ba52d332ba99/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= golang.org/x/oauth2 v0.0.0-20210218202405-ba52d332ba99/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A=
golang.org/x/oauth2 v0.9.0 h1:BPpt2kU7oMRq3kCHAA1tbSEshXRw1LpG2ztgDwrzuAs= golang.org/x/oauth2 v0.12.0 h1:smVPGxink+n1ZI5pkQa8y6fZT0RW0MgCO5bFpepy4B4=
golang.org/x/oauth2 v0.9.0/go.mod h1:qYgFZaFiu6Wg24azG8bdV52QJXJGbZzIIsRCdVKzbLw= golang.org/x/oauth2 v0.12.0/go.mod h1:A74bZ3aGXgCY0qaIC9Ahg6Lglin4AMAco8cIv9baba4=
golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
@ -495,13 +495,13 @@ golang.org/x/sync v0.0.0-20200625203802-6e8e738ad208/go.mod h1:RxMgew5VJxzue5/jJ
golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20201207232520-09787c993a3a/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20201207232520-09787c993a3a/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.3.0 h1:ftCYgMx6zT/asHUrPw8BLLscYtGznsLAnjq5RH9P66E= golang.org/x/sync v0.3.0 h1:ftCYgMx6zT/asHUrPw8BLLscYtGznsLAnjq5RH9P66E=
golang.org/x/sync v0.3.0/go.mod h1:FU7BRWz2tNW+3quACPkgCx/L+uEAv1htQ0V83Z9Rj+Y= golang.org/x/sync v0.3.0/go.mod h1:FU7BRWz2tNW+3quACPkgCx/L+uEAv1htQ0V83Z9Rj+Y=
golang.org/x/sys v0.0.0-20180823144017-11551d06cbcc/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20180823144017-11551d06cbcc/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/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-20181116152217-5ac8a444bdc5/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20190130150945-aca44879d564/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20190222072716-a9d3bda3a223/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190222072716-a9d3bda3a223/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-20190312061237-fead79001313/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
@ -548,15 +548,12 @@ golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBc
golang.org/x/sys v0.0.0-20210630005230-0f9fa26af87c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20210630005230-0f9fa26af87c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20210927094055-39ccf1dd6fa6/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20210927094055-39ccf1dd6fa6/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20220503163025-988cb79eb6c6/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220503163025-988cb79eb6c6/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20220728004956-3c1f35247d10/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220728004956-3c1f35247d10/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20220908164124-27713097b956/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220908164124-27713097b956/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.9.0 h1:KS/R3tvhPqvJvwcKfnBHJwwthS11LRhmM5D59eEXa0s= golang.org/x/sys v0.12.0 h1:CM0HF96J0hcLAwsHPJZjfdNzs0gftsLfgKt57wWHJ0o=
golang.org/x/sys v0.9.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.12.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= 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.1-0.20180807135948-17ff2d5776d2/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
@ -565,9 +562,8 @@ golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
golang.org/x/text v0.3.4/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.4/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ= golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ=
golang.org/x/text v0.3.8/go.mod h1:E6s5w1FMmriuDzIBO73fBruAKo1PCIq6d2Q6DHfQ8WQ= golang.org/x/text v0.13.0 h1:ablQoSUd0tRdKxZewP80B+BaqeKJuVhuRxj/dkrun3k=
golang.org/x/text v0.10.0 h1:UpjohKhiEgNc0CSauXmwYftY1+LlaC75SJwh0SgCX58= golang.org/x/text v0.13.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE=
golang.org/x/text v0.10.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE=
golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
golang.org/x/time v0.0.0-20191024005414-555d28b269f0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.0.0-20191024005414-555d28b269f0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
@ -624,7 +620,6 @@ golang.org/x/tools v0.0.0-20210106214847-113979e3529a/go.mod h1:emZCQorbCU4vsT4f
golang.org/x/tools v0.0.0-20210108195828-e2f9c7f1fc8e/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= golang.org/x/tools v0.0.0-20210108195828-e2f9c7f1fc8e/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA=
golang.org/x/tools v0.1.0/go.mod h1:xkSsbof2nBLbhDlRMhhhyNLN/zl3eTqcnHD5viDpcZ0= golang.org/x/tools v0.1.0/go.mod h1:xkSsbof2nBLbhDlRMhhhyNLN/zl3eTqcnHD5viDpcZ0=
golang.org/x/tools v0.1.5/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= golang.org/x/tools v0.1.5/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk=
golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc=
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
@ -650,8 +645,8 @@ google.golang.org/api v0.30.0/go.mod h1:QGmEvQ87FHZNiUVJkT14jQNYJ4ZJjdRF23ZXz513
google.golang.org/api v0.35.0/go.mod h1:/XrVsuzM0rZmrsbjJutiuftIzeuTQcEeaYcSk/mQ1dg= google.golang.org/api v0.35.0/go.mod h1:/XrVsuzM0rZmrsbjJutiuftIzeuTQcEeaYcSk/mQ1dg=
google.golang.org/api v0.36.0/go.mod h1:+z5ficQTmoYpPn8LCUNVpK5I7hwkpjbcgqA7I34qYtE= google.golang.org/api v0.36.0/go.mod h1:+z5ficQTmoYpPn8LCUNVpK5I7hwkpjbcgqA7I34qYtE=
google.golang.org/api v0.40.0/go.mod h1:fYKFpnQN0DsDSKRVRcQSDQNtqWPfM9i+zNPxepjRCQ8= google.golang.org/api v0.40.0/go.mod h1:fYKFpnQN0DsDSKRVRcQSDQNtqWPfM9i+zNPxepjRCQ8=
google.golang.org/api v0.129.0 h1:2XbdjjNfFPXQyufzQVwPf1RRnHH8Den2pfNE2jw7L8w= google.golang.org/api v0.143.0 h1:o8cekTkqhywkbZT6p1UHJPZ9+9uuCAJs/KYomxZB8fA=
google.golang.org/api v0.129.0/go.mod h1:dFjiXlanKwWE3612X97llhsoI36FAoIiRj3aTl5b/zE= google.golang.org/api v0.143.0/go.mod h1:FoX9DO9hT7DLNn97OuoZAGSDuNAXdJRuGK98rSUgurk=
google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM= google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM=
google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4=
google.golang.org/appengine v1.5.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= google.golang.org/appengine v1.5.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4=
@ -683,7 +678,6 @@ google.golang.org/genproto v0.0.0-20200312145019-da6875a35672/go.mod h1:55QSHmfG
google.golang.org/genproto v0.0.0-20200331122359-1ee6d9798940/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= google.golang.org/genproto v0.0.0-20200331122359-1ee6d9798940/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c=
google.golang.org/genproto v0.0.0-20200430143042-b979b6f78d84/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= google.golang.org/genproto v0.0.0-20200430143042-b979b6f78d84/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c=
google.golang.org/genproto v0.0.0-20200511104702-f5ebc3bea380/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= google.golang.org/genproto v0.0.0-20200511104702-f5ebc3bea380/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c=
google.golang.org/genproto v0.0.0-20200513103714-09dca8ec2884/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c=
google.golang.org/genproto v0.0.0-20200515170657-fc4c6c6a6587/go.mod h1:YsZOwe1myG/8QRHRsmBRE1LrgQY60beZKjly0O1fX9U= google.golang.org/genproto v0.0.0-20200515170657-fc4c6c6a6587/go.mod h1:YsZOwe1myG/8QRHRsmBRE1LrgQY60beZKjly0O1fX9U=
google.golang.org/genproto v0.0.0-20200526211855-cb27e3aa2013/go.mod h1:NbSheEEYHJ7i3ixzK3sjbqSGDJWnxyFXZblF3eUsNvo= google.golang.org/genproto v0.0.0-20200526211855-cb27e3aa2013/go.mod h1:NbSheEEYHJ7i3ixzK3sjbqSGDJWnxyFXZblF3eUsNvo=
google.golang.org/genproto v0.0.0-20200618031413-b414f8b61790/go.mod h1:jDfRM7FcilCzHH/e9qn6dsT145K34l5v+OpcnNgKAAA= google.golang.org/genproto v0.0.0-20200618031413-b414f8b61790/go.mod h1:jDfRM7FcilCzHH/e9qn6dsT145K34l5v+OpcnNgKAAA=
@ -697,12 +691,12 @@ google.golang.org/genproto v0.0.0-20201210142538-e3217bee35cc/go.mod h1:FWY/as6D
google.golang.org/genproto v0.0.0-20201214200347-8c77b98c765d/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= google.golang.org/genproto v0.0.0-20201214200347-8c77b98c765d/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
google.golang.org/genproto v0.0.0-20210108203827-ffc7fda8c3d7/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= google.golang.org/genproto v0.0.0-20210108203827-ffc7fda8c3d7/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
google.golang.org/genproto v0.0.0-20210226172003-ab064af71705/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= google.golang.org/genproto v0.0.0-20210226172003-ab064af71705/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
google.golang.org/genproto v0.0.0-20230530153820-e85fd2cbaebc h1:8DyZCyvI8mE1IdLy/60bS+52xfymkE72wv1asokgtao= google.golang.org/genproto v0.0.0-20230913181813-007df8e322eb h1:XFBgcDwm7irdHTbz4Zk2h7Mh+eis4nfJEFQFYzJzuIA=
google.golang.org/genproto v0.0.0-20230530153820-e85fd2cbaebc/go.mod h1:xZnkP7mREFX5MORlOPEzLMr+90PPZQ2QWzrVTWfAq64= google.golang.org/genproto v0.0.0-20230913181813-007df8e322eb/go.mod h1:yZTlhN0tQnXo3h00fuXNCxJdLdIdnVFVBaRJ5LWBbw4=
google.golang.org/genproto/googleapis/api v0.0.0-20230530153820-e85fd2cbaebc h1:kVKPf/IiYSBWEWtkIn6wZXwWGCnLKcC8oWfZvXjsGnM= google.golang.org/genproto/googleapis/api v0.0.0-20230913181813-007df8e322eb h1:lK0oleSc7IQsUxO3U5TjL9DWlsxpEBemh+zpB7IqhWI=
google.golang.org/genproto/googleapis/api v0.0.0-20230530153820-e85fd2cbaebc/go.mod h1:vHYtlOoi6TsQ3Uk2yxR7NI5z8uoV+3pZtR4jmHIkRig= google.golang.org/genproto/googleapis/api v0.0.0-20230913181813-007df8e322eb/go.mod h1:KjSP20unUpOx5kyQUFa7k4OJg0qeJ7DEZflGDu2p6Bk=
google.golang.org/genproto/googleapis/rpc v0.0.0-20230530153820-e85fd2cbaebc h1:XSJ8Vk1SWuNr8S18z1NZSziL0CPIXLCCMDOEFtHBOFc= google.golang.org/genproto/googleapis/rpc v0.0.0-20230920204549-e6e6cdab5c13 h1:N3bU/SQDCDyD6R528GJ/PwW9KjYcJA3dgyH+MovAkIM=
google.golang.org/genproto/googleapis/rpc v0.0.0-20230530153820-e85fd2cbaebc/go.mod h1:66JfowdXAEgad5O9NnYcsNPLCPZJD++2L9X0PCMODrA= google.golang.org/genproto/googleapis/rpc v0.0.0-20230920204549-e6e6cdab5c13/go.mod h1:KSqppvjFjtoCI+KGd4PELB0qLNxdJHRGqRI09mB6pQA=
google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c= google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c=
google.golang.org/grpc v1.20.1/go.mod h1:10oTOabMzJvdu6/UiuZezV6QK5dSlG84ov/aaiqXj38= google.golang.org/grpc v1.20.1/go.mod h1:10oTOabMzJvdu6/UiuZezV6QK5dSlG84ov/aaiqXj38=
google.golang.org/grpc v1.21.1/go.mod h1:oYelfM1adQP15Ek0mdvEgi9Df8B9CZIaU1084ijfRaM= google.golang.org/grpc v1.21.1/go.mod h1:oYelfM1adQP15Ek0mdvEgi9Df8B9CZIaU1084ijfRaM=
@ -716,14 +710,11 @@ google.golang.org/grpc v1.29.1/go.mod h1:itym6AZVZYACWQqET3MqgPpjcuV5QH3BxFS3Iji
google.golang.org/grpc v1.30.0/go.mod h1:N36X2cJ7JwdamYAgDz+s+rVMFjt3numwzf/HckM8pak= google.golang.org/grpc v1.30.0/go.mod h1:N36X2cJ7JwdamYAgDz+s+rVMFjt3numwzf/HckM8pak=
google.golang.org/grpc v1.31.0/go.mod h1:N36X2cJ7JwdamYAgDz+s+rVMFjt3numwzf/HckM8pak= google.golang.org/grpc v1.31.0/go.mod h1:N36X2cJ7JwdamYAgDz+s+rVMFjt3numwzf/HckM8pak=
google.golang.org/grpc v1.31.1/go.mod h1:N36X2cJ7JwdamYAgDz+s+rVMFjt3numwzf/HckM8pak= google.golang.org/grpc v1.31.1/go.mod h1:N36X2cJ7JwdamYAgDz+s+rVMFjt3numwzf/HckM8pak=
google.golang.org/grpc v1.33.1/go.mod h1:fr5YgcSWrqhRRxogOsw7RzIpsmvOZ6IcH4kBYTpR3n0=
google.golang.org/grpc v1.33.2/go.mod h1:JMHMWHQWaTccqQQlmk3MJZS+GWXOdAesneDmEnv2fbc= google.golang.org/grpc v1.33.2/go.mod h1:JMHMWHQWaTccqQQlmk3MJZS+GWXOdAesneDmEnv2fbc=
google.golang.org/grpc v1.34.0/go.mod h1:WotjhfgOW/POjDeRt8vscBtXq+2VjORFy659qA51WJ8= google.golang.org/grpc v1.34.0/go.mod h1:WotjhfgOW/POjDeRt8vscBtXq+2VjORFy659qA51WJ8=
google.golang.org/grpc v1.35.0/go.mod h1:qjiiYl8FncCW8feJPdyg3v6XW24KsRHe+dy9BAGRRjU= google.golang.org/grpc v1.35.0/go.mod h1:qjiiYl8FncCW8feJPdyg3v6XW24KsRHe+dy9BAGRRjU=
google.golang.org/grpc v1.36.0/go.mod h1:qjiiYl8FncCW8feJPdyg3v6XW24KsRHe+dy9BAGRRjU= google.golang.org/grpc v1.58.2 h1:SXUpjxeVF3FKrTYQI4f4KvbGD5u2xccdYdurwowix5I=
google.golang.org/grpc v1.45.0/go.mod h1:lN7owxKUQEqMfSyQikvvk5tf/6zMPsrK+ONuO11+0rQ= google.golang.org/grpc v1.58.2/go.mod h1:tgX3ZQDlNJGU96V6yHh1T/JeoBQ2TXdr43YbYSsCJk0=
google.golang.org/grpc v1.56.1 h1:z0dNfjIl0VpaZ9iSVjA6daGatAYwPGstTjt5vkRMFkQ=
google.golang.org/grpc v1.56.1/go.mod h1:I9bI3vqKfayGqPUAwGdOSu7kt6oIJLixfffKrpXqQ9s=
google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8= google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8=
google.golang.org/protobuf v0.0.0-20200221191635-4d8936d0db64/go.mod h1:kwYJMbMJ01Woi6D6+Kah6886xMZcty6N08ah7+eCXa0= google.golang.org/protobuf v0.0.0-20200221191635-4d8936d0db64/go.mod h1:kwYJMbMJ01Woi6D6+Kah6886xMZcty6N08ah7+eCXa0=
google.golang.org/protobuf v0.0.0-20200228230310-ab0ca4ff8a60/go.mod h1:cfTl7dwQJ+fmap5saPgwCLgHXTUD7jkjRqWcaiX5VyM= google.golang.org/protobuf v0.0.0-20200228230310-ab0ca4ff8a60/go.mod h1:cfTl7dwQJ+fmap5saPgwCLgHXTUD7jkjRqWcaiX5VyM=
@ -748,7 +739,6 @@ gopkg.in/ini.v1 v1.67.0 h1:Dgnx+6+nfE+IfzjUEISNeydPJh9AXNNsWbGP9KzCsOA=
gopkg.in/ini.v1 v1.67.0/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k= gopkg.in/ini.v1 v1.67.0/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k=
gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= 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.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
gopkg.in/yaml.v2 v2.2.3/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
gopkg.in/yaml.v2 v2.2.4/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.2.4/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
gopkg.in/yaml.v2 v2.2.5/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.2.5/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
gopkg.in/yaml.v2 v2.2.8/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.2.8/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=

View file

@ -5,9 +5,9 @@ import (
) )
// Decoder decodes the contents of b into v. // Decoder decodes the contents of b into v.
// It's primarily used for decoding contents of a file into a map[string]interface{}. // It's primarily used for decoding contents of a file into a map[string]any.
type Decoder interface { type Decoder interface {
Decode(b []byte, v map[string]interface{}) error Decode(b []byte, v map[string]any) error
} }
const ( const (
@ -48,7 +48,7 @@ func (e *DecoderRegistry) RegisterDecoder(format string, enc Decoder) error {
} }
// Decode calls the underlying Decoder based on the format. // Decode calls the underlying Decoder based on the format.
func (e *DecoderRegistry) Decode(format string, b []byte, v map[string]interface{}) error { func (e *DecoderRegistry) Decode(format string, b []byte, v map[string]any) error {
e.mu.RLock() e.mu.RLock()
decoder, ok := e.decoders[format] decoder, ok := e.decoders[format]
e.mu.RUnlock() e.mu.RUnlock()

View file

@ -6,10 +6,10 @@ import (
) )
type decoder struct { type decoder struct {
v map[string]interface{} v map[string]any
} }
func (d decoder) Decode(_ []byte, v map[string]interface{}) error { func (d decoder) Decode(_ []byte, v map[string]any) error {
for key, value := range d.v { for key, value := range d.v {
v[key] = value v[key] = value
} }
@ -46,7 +46,7 @@ func TestDecoderRegistry_Decode(t *testing.T) {
t.Run("OK", func(t *testing.T) { t.Run("OK", func(t *testing.T) {
registry := NewDecoderRegistry() registry := NewDecoderRegistry()
decoder := decoder{ decoder := decoder{
v: map[string]interface{}{ v: map[string]any{
"key": "value", "key": "value",
}, },
} }
@ -56,7 +56,7 @@ func TestDecoderRegistry_Decode(t *testing.T) {
t.Fatal(err) t.Fatal(err)
} }
v := map[string]interface{}{} v := map[string]any{}
err = registry.Decode("myformat", []byte("key: value"), v) err = registry.Decode("myformat", []byte("key: value"), v)
if err != nil { if err != nil {
@ -71,7 +71,7 @@ func TestDecoderRegistry_Decode(t *testing.T) {
t.Run("DecoderNotFound", func(t *testing.T) { t.Run("DecoderNotFound", func(t *testing.T) {
registry := NewDecoderRegistry() registry := NewDecoderRegistry()
v := map[string]interface{}{} v := map[string]any{}
err := registry.Decode("myformat", nil, v) err := registry.Decode("myformat", nil, v)
if err != ErrDecoderNotFound { if err != ErrDecoderNotFound {

View file

@ -15,8 +15,8 @@ const keyDelimiter = "_"
// (commonly called as dotenv format). // (commonly called as dotenv format).
type Codec struct{} type Codec struct{}
func (Codec) Encode(v map[string]interface{}) ([]byte, error) { func (Codec) Encode(v map[string]any) ([]byte, error) {
flattened := map[string]interface{}{} flattened := map[string]any{}
flattened = flattenAndMergeMap(flattened, v, "", keyDelimiter) flattened = flattenAndMergeMap(flattened, v, "", keyDelimiter)
@ -40,7 +40,7 @@ func (Codec) Encode(v map[string]interface{}) ([]byte, error) {
return buf.Bytes(), nil return buf.Bytes(), nil
} }
func (Codec) Decode(b []byte, v map[string]interface{}) error { func (Codec) Decode(b []byte, v map[string]any) error {
var buf bytes.Buffer var buf bytes.Buffer
_, err := buf.Write(b) _, err := buf.Write(b)

View file

@ -15,7 +15,7 @@ const encoded = `KEY=value
` `
// Viper's internal representation // Viper's internal representation
var data = map[string]interface{}{ var data = map[string]any{
"KEY": "value", "KEY": "value",
} }
@ -36,7 +36,7 @@ func TestCodec_Decode(t *testing.T) {
t.Run("OK", func(t *testing.T) { t.Run("OK", func(t *testing.T) {
codec := Codec{} codec := Codec{}
v := map[string]interface{}{} v := map[string]any{}
err := codec.Decode([]byte(original), v) err := codec.Decode([]byte(original), v)
if err != nil { if err != nil {
@ -51,7 +51,7 @@ func TestCodec_Decode(t *testing.T) {
t.Run("InvalidData", func(t *testing.T) { t.Run("InvalidData", func(t *testing.T) {
codec := Codec{} codec := Codec{}
v := map[string]interface{}{} v := map[string]any{}
err := codec.Decode([]byte(`invalid data`), v) err := codec.Decode([]byte(`invalid data`), v)
if err == nil { if err == nil {

View file

@ -7,27 +7,27 @@ import (
) )
// flattenAndMergeMap recursively flattens the given map into a new map // flattenAndMergeMap recursively flattens the given map into a new map
// Code is based on the function with the same name in tha main package. // Code is based on the function with the same name in the main package.
// TODO: move it to a common place // TODO: move it to a common place
func flattenAndMergeMap(shadow map[string]interface{}, m map[string]interface{}, prefix string, delimiter string) map[string]interface{} { func flattenAndMergeMap(shadow map[string]any, m map[string]any, prefix string, delimiter string) map[string]any {
if shadow != nil && prefix != "" && shadow[prefix] != nil { if shadow != nil && prefix != "" && shadow[prefix] != nil {
// prefix is shadowed => nothing more to flatten // prefix is shadowed => nothing more to flatten
return shadow return shadow
} }
if shadow == nil { if shadow == nil {
shadow = make(map[string]interface{}) shadow = make(map[string]any)
} }
var m2 map[string]interface{} var m2 map[string]any
if prefix != "" { if prefix != "" {
prefix += delimiter prefix += delimiter
} }
for k, val := range m { for k, val := range m {
fullKey := prefix + k fullKey := prefix + k
switch val.(type) { switch val := val.(type) {
case map[string]interface{}: case map[string]any:
m2 = val.(map[string]interface{}) m2 = val
case map[interface{}]interface{}: case map[any]any:
m2 = cast.ToStringMap(val) m2 = cast.ToStringMap(val)
default: default:
// immediate value // immediate value

View file

@ -5,9 +5,9 @@ import (
) )
// Encoder encodes the contents of v into a byte representation. // Encoder encodes the contents of v into a byte representation.
// It's primarily used for encoding a map[string]interface{} into a file format. // It's primarily used for encoding a map[string]any into a file format.
type Encoder interface { type Encoder interface {
Encode(v map[string]interface{}) ([]byte, error) Encode(v map[string]any) ([]byte, error)
} }
const ( const (
@ -47,7 +47,7 @@ func (e *EncoderRegistry) RegisterEncoder(format string, enc Encoder) error {
return nil return nil
} }
func (e *EncoderRegistry) Encode(format string, v map[string]interface{}) ([]byte, error) { func (e *EncoderRegistry) Encode(format string, v map[string]any) ([]byte, error) {
e.mu.RLock() e.mu.RLock()
encoder, ok := e.encoders[format] encoder, ok := e.encoders[format]
e.mu.RUnlock() e.mu.RUnlock()

View file

@ -8,7 +8,7 @@ type encoder struct {
b []byte b []byte
} }
func (e encoder) Encode(_ map[string]interface{}) ([]byte, error) { func (e encoder) Encode(_ map[string]any) ([]byte, error) {
return e.b, nil return e.b, nil
} }
@ -49,7 +49,7 @@ func TestEncoderRegistry_Decode(t *testing.T) {
t.Fatal(err) t.Fatal(err)
} }
b, err := registry.Encode("myformat", map[string]interface{}{"key": "value"}) b, err := registry.Encode("myformat", map[string]any{"key": "value"})
if err != nil { if err != nil {
t.Fatal(err) t.Fatal(err)
} }
@ -62,7 +62,7 @@ func TestEncoderRegistry_Decode(t *testing.T) {
t.Run("EncoderNotFound", func(t *testing.T) { t.Run("EncoderNotFound", func(t *testing.T) {
registry := NewEncoderRegistry() registry := NewEncoderRegistry()
_, err := registry.Encode("myformat", map[string]interface{}{"key": "value"}) _, err := registry.Encode("myformat", map[string]any{"key": "value"})
if err != ErrEncoderNotFound { if err != ErrEncoderNotFound {
t.Fatalf("expected ErrEncoderNotFound, got: %v", err) t.Fatalf("expected ErrEncoderNotFound, got: %v", err)
} }

View file

@ -12,7 +12,7 @@ import (
// TODO: add printer config to the codec? // TODO: add printer config to the codec?
type Codec struct{} type Codec struct{}
func (Codec) Encode(v map[string]interface{}) ([]byte, error) { func (Codec) Encode(v map[string]any) ([]byte, error) {
b, err := json.Marshal(v) b, err := json.Marshal(v)
if err != nil { if err != nil {
return nil, err return nil, err
@ -35,6 +35,6 @@ func (Codec) Encode(v map[string]interface{}) ([]byte, error) {
return buf.Bytes(), nil return buf.Bytes(), nil
} }
func (Codec) Decode(b []byte, v map[string]interface{}) error { func (Codec) Decode(b []byte, v map[string]any) error {
return hcl.Unmarshal(b, &v) return hcl.Unmarshal(b, &v)
} }

View file

@ -45,24 +45,24 @@ const encoded = `"key" = "value"
// //
// in case of HCL it's slightly different from Viper's internal representation // in case of HCL it's slightly different from Viper's internal representation
// (eg. map is decoded into a list of maps) // (eg. map is decoded into a list of maps)
var decoded = map[string]interface{}{ var decoded = map[string]any{
"key": "value", "key": "value",
"list": []interface{}{ "list": []any{
"item1", "item1",
"item2", "item2",
"item3", "item3",
}, },
"map": []map[string]interface{}{ "map": []map[string]any{
{ {
"key": "value", "key": "value",
}, },
}, },
"nested_map": []map[string]interface{}{ "nested_map": []map[string]any{
{ {
"map": []map[string]interface{}{ "map": []map[string]any{
{ {
"key": "value", "key": "value",
"list": []interface{}{ "list": []any{
"item1", "item1",
"item2", "item2",
"item3", "item3",
@ -74,20 +74,20 @@ var decoded = map[string]interface{}{
} }
// Viper's internal representation // Viper's internal representation
var data = map[string]interface{}{ var data = map[string]any{
"key": "value", "key": "value",
"list": []interface{}{ "list": []any{
"item1", "item1",
"item2", "item2",
"item3", "item3",
}, },
"map": map[string]interface{}{ "map": map[string]any{
"key": "value", "key": "value",
}, },
"nested_map": map[string]interface{}{ "nested_map": map[string]any{
"map": map[string]interface{}{ "map": map[string]any{
"key": "value", "key": "value",
"list": []interface{}{ "list": []any{
"item1", "item1",
"item2", "item2",
"item3", "item3",
@ -113,7 +113,7 @@ func TestCodec_Decode(t *testing.T) {
t.Run("OK", func(t *testing.T) { t.Run("OK", func(t *testing.T) {
codec := Codec{} codec := Codec{}
v := map[string]interface{}{} v := map[string]any{}
err := codec.Decode([]byte(original), v) err := codec.Decode([]byte(original), v)
if err != nil { if err != nil {
@ -128,7 +128,7 @@ func TestCodec_Decode(t *testing.T) {
t.Run("InvalidData", func(t *testing.T) { t.Run("InvalidData", func(t *testing.T) {
codec := Codec{} codec := Codec{}
v := map[string]interface{}{} v := map[string]any{}
err := codec.Decode([]byte(`invalid data`), v) err := codec.Decode([]byte(`invalid data`), v)
if err == nil { if err == nil {

View file

@ -19,11 +19,11 @@ type Codec struct {
LoadOptions LoadOptions LoadOptions LoadOptions
} }
func (c Codec) Encode(v map[string]interface{}) ([]byte, error) { func (c Codec) Encode(v map[string]any) ([]byte, error) {
cfg := ini.Empty() cfg := ini.Empty()
ini.PrettyFormat = false ini.PrettyFormat = false
flattened := map[string]interface{}{} flattened := map[string]any{}
flattened = flattenAndMergeMap(flattened, v, "", c.keyDelimiter()) flattened = flattenAndMergeMap(flattened, v, "", c.keyDelimiter())
@ -62,7 +62,7 @@ func (c Codec) Encode(v map[string]interface{}) ([]byte, error) {
return buf.Bytes(), nil return buf.Bytes(), nil
} }
func (c Codec) Decode(b []byte, v map[string]interface{}) error { func (c Codec) Decode(b []byte, v map[string]any) error {
cfg := ini.Empty(c.LoadOptions) cfg := ini.Empty(c.LoadOptions)
err := cfg.Append(b) err := cfg.Append(b)

View file

@ -26,19 +26,19 @@ key=value
// //
// in case of INI it's slightly different from Viper's internal representation // in case of INI it's slightly different from Viper's internal representation
// (eg. top level keys land in a section called default) // (eg. top level keys land in a section called default)
var decoded = map[string]interface{}{ var decoded = map[string]any{
"DEFAULT": map[string]interface{}{ "DEFAULT": map[string]any{
"key": "value", "key": "value",
}, },
"map": map[string]interface{}{ "map": map[string]any{
"key": "value", "key": "value",
}, },
} }
// Viper's internal representation // Viper's internal representation
var data = map[string]interface{}{ var data = map[string]any{
"key": "value", "key": "value",
"map": map[string]interface{}{ "map": map[string]any{
"key": "value", "key": "value",
}, },
} }
@ -60,11 +60,11 @@ func TestCodec_Encode(t *testing.T) {
t.Run("Default", func(t *testing.T) { t.Run("Default", func(t *testing.T) {
codec := Codec{} codec := Codec{}
data := map[string]interface{}{ data := map[string]any{
"default": map[string]interface{}{ "default": map[string]any{
"key": "value", "key": "value",
}, },
"map": map[string]interface{}{ "map": map[string]any{
"key": "value", "key": "value",
}, },
} }
@ -84,7 +84,7 @@ func TestCodec_Decode(t *testing.T) {
t.Run("OK", func(t *testing.T) { t.Run("OK", func(t *testing.T) {
codec := Codec{} codec := Codec{}
v := map[string]interface{}{} v := map[string]any{}
err := codec.Decode([]byte(original), v) err := codec.Decode([]byte(original), v)
if err != nil { if err != nil {
@ -99,7 +99,7 @@ func TestCodec_Decode(t *testing.T) {
t.Run("InvalidData", func(t *testing.T) { t.Run("InvalidData", func(t *testing.T) {
codec := Codec{} codec := Codec{}
v := map[string]interface{}{} v := map[string]any{}
err := codec.Decode([]byte(`invalid data`), v) err := codec.Decode([]byte(`invalid data`), v)
if err == nil { if err == nil {

View file

@ -15,22 +15,22 @@ import (
// In case intermediate keys do not exist, or map to a non-map value, // In case intermediate keys do not exist, or map to a non-map value,
// a new map is created and inserted, and the search continues from there: // a new map is created and inserted, and the search continues from there:
// the initial map "m" may be modified! // the initial map "m" may be modified!
func deepSearch(m map[string]interface{}, path []string) map[string]interface{} { func deepSearch(m map[string]any, path []string) map[string]any {
for _, k := range path { for _, k := range path {
m2, ok := m[k] m2, ok := m[k]
if !ok { if !ok {
// intermediate key does not exist // intermediate key does not exist
// => create it and continue from there // => create it and continue from there
m3 := make(map[string]interface{}) m3 := make(map[string]any)
m[k] = m3 m[k] = m3
m = m3 m = m3
continue continue
} }
m3, ok := m2.(map[string]interface{}) m3, ok := m2.(map[string]any)
if !ok { if !ok {
// intermediate key is a value // intermediate key is a value
// => replace with a new map // => replace with a new map
m3 = make(map[string]interface{}) m3 = make(map[string]any)
m[k] = m3 m[k] = m3
} }
// continue search from here // continue search from here
@ -40,27 +40,27 @@ func deepSearch(m map[string]interface{}, path []string) map[string]interface{}
} }
// flattenAndMergeMap recursively flattens the given map into a new map // flattenAndMergeMap recursively flattens the given map into a new map
// Code is based on the function with the same name in tha main package. // Code is based on the function with the same name in the main package.
// TODO: move it to a common place // TODO: move it to a common place
func flattenAndMergeMap(shadow map[string]interface{}, m map[string]interface{}, prefix string, delimiter string) map[string]interface{} { func flattenAndMergeMap(shadow map[string]any, m map[string]any, prefix string, delimiter string) map[string]any {
if shadow != nil && prefix != "" && shadow[prefix] != nil { if shadow != nil && prefix != "" && shadow[prefix] != nil {
// prefix is shadowed => nothing more to flatten // prefix is shadowed => nothing more to flatten
return shadow return shadow
} }
if shadow == nil { if shadow == nil {
shadow = make(map[string]interface{}) shadow = make(map[string]any)
} }
var m2 map[string]interface{} var m2 map[string]any
if prefix != "" { if prefix != "" {
prefix += delimiter prefix += delimiter
} }
for k, val := range m { for k, val := range m {
fullKey := prefix + k fullKey := prefix + k
switch val.(type) { switch val := val.(type) {
case map[string]interface{}: case map[string]any:
m2 = val.(map[string]interface{}) m2 = val
case map[interface{}]interface{}: case map[any]any:
m2 = cast.ToStringMap(val) m2 = cast.ToStringMap(val)
default: default:
// immediate value // immediate value

View file

@ -20,12 +20,12 @@ type Codec struct {
Properties *properties.Properties Properties *properties.Properties
} }
func (c *Codec) Encode(v map[string]interface{}) ([]byte, error) { func (c *Codec) Encode(v map[string]any) ([]byte, error) {
if c.Properties == nil { if c.Properties == nil {
c.Properties = properties.NewProperties() c.Properties = properties.NewProperties()
} }
flattened := map[string]interface{}{} flattened := map[string]any{}
flattened = flattenAndMergeMap(flattened, v, "", c.keyDelimiter()) flattened = flattenAndMergeMap(flattened, v, "", c.keyDelimiter())
@ -54,7 +54,7 @@ func (c *Codec) Encode(v map[string]interface{}) ([]byte, error) {
return buf.Bytes(), nil return buf.Bytes(), nil
} }
func (c *Codec) Decode(b []byte, v map[string]interface{}) error { func (c *Codec) Decode(b []byte, v map[string]any) error {
var err error var err error
c.Properties, err = properties.Load(b, properties.UTF8) c.Properties, err = properties.Load(b, properties.UTF8)
if err != nil { if err != nil {

View file

@ -17,9 +17,9 @@ map.key = value
` `
// Viper's internal representation // Viper's internal representation
var data = map[string]interface{}{ var data = map[string]any{
"key": "value", "key": "value",
"map": map[string]interface{}{ "map": map[string]any{
"key": "value", "key": "value",
}, },
} }
@ -41,7 +41,7 @@ func TestCodec_Decode(t *testing.T) {
t.Run("OK", func(t *testing.T) { t.Run("OK", func(t *testing.T) {
codec := Codec{} codec := Codec{}
v := map[string]interface{}{} v := map[string]any{}
err := codec.Decode([]byte(original), v) err := codec.Decode([]byte(original), v)
if err != nil { if err != nil {
@ -58,7 +58,7 @@ func TestCodec_Decode(t *testing.T) {
codec := Codec{} codec := Codec{}
v := map[string]interface{}{} v := map[string]any{}
codec.Decode([]byte(``), v) codec.Decode([]byte(``), v)
@ -71,7 +71,7 @@ func TestCodec_Decode(t *testing.T) {
func TestCodec_DecodeEncode(t *testing.T) { func TestCodec_DecodeEncode(t *testing.T) {
codec := Codec{} codec := Codec{}
v := map[string]interface{}{} v := map[string]any{}
err := codec.Decode([]byte(original), v) err := codec.Decode([]byte(original), v)
if err != nil { if err != nil {

View file

@ -15,22 +15,22 @@ import (
// In case intermediate keys do not exist, or map to a non-map value, // In case intermediate keys do not exist, or map to a non-map value,
// a new map is created and inserted, and the search continues from there: // a new map is created and inserted, and the search continues from there:
// the initial map "m" may be modified! // the initial map "m" may be modified!
func deepSearch(m map[string]interface{}, path []string) map[string]interface{} { func deepSearch(m map[string]any, path []string) map[string]any {
for _, k := range path { for _, k := range path {
m2, ok := m[k] m2, ok := m[k]
if !ok { if !ok {
// intermediate key does not exist // intermediate key does not exist
// => create it and continue from there // => create it and continue from there
m3 := make(map[string]interface{}) m3 := make(map[string]any)
m[k] = m3 m[k] = m3
m = m3 m = m3
continue continue
} }
m3, ok := m2.(map[string]interface{}) m3, ok := m2.(map[string]any)
if !ok { if !ok {
// intermediate key is a value // intermediate key is a value
// => replace with a new map // => replace with a new map
m3 = make(map[string]interface{}) m3 = make(map[string]any)
m[k] = m3 m[k] = m3
} }
// continue search from here // continue search from here
@ -40,27 +40,27 @@ func deepSearch(m map[string]interface{}, path []string) map[string]interface{}
} }
// flattenAndMergeMap recursively flattens the given map into a new map // flattenAndMergeMap recursively flattens the given map into a new map
// Code is based on the function with the same name in tha main package. // Code is based on the function with the same name in the main package.
// TODO: move it to a common place // TODO: move it to a common place
func flattenAndMergeMap(shadow map[string]interface{}, m map[string]interface{}, prefix string, delimiter string) map[string]interface{} { func flattenAndMergeMap(shadow map[string]any, m map[string]any, prefix string, delimiter string) map[string]any {
if shadow != nil && prefix != "" && shadow[prefix] != nil { if shadow != nil && prefix != "" && shadow[prefix] != nil {
// prefix is shadowed => nothing more to flatten // prefix is shadowed => nothing more to flatten
return shadow return shadow
} }
if shadow == nil { if shadow == nil {
shadow = make(map[string]interface{}) shadow = make(map[string]any)
} }
var m2 map[string]interface{} var m2 map[string]any
if prefix != "" { if prefix != "" {
prefix += delimiter prefix += delimiter
} }
for k, val := range m { for k, val := range m {
fullKey := prefix + k fullKey := prefix + k
switch val.(type) { switch val := val.(type) {
case map[string]interface{}: case map[string]any:
m2 = val.(map[string]interface{}) m2 = val
case map[interface{}]interface{}: case map[any]any:
m2 = cast.ToStringMap(val) m2 = cast.ToStringMap(val)
default: default:
// immediate value // immediate value

View file

@ -7,11 +7,11 @@ import (
// Codec implements the encoding.Encoder and encoding.Decoder interfaces for JSON encoding. // Codec implements the encoding.Encoder and encoding.Decoder interfaces for JSON encoding.
type Codec struct{} type Codec struct{}
func (Codec) Encode(v map[string]interface{}) ([]byte, error) { func (Codec) Encode(v map[string]any) ([]byte, error) {
// TODO: expose prefix and indent in the Codec as setting? // TODO: expose prefix and indent in the Codec as setting?
return json.MarshalIndent(v, "", " ") return json.MarshalIndent(v, "", " ")
} }
func (Codec) Decode(b []byte, v map[string]interface{}) error { func (Codec) Decode(b []byte, v map[string]any) error {
return json.Unmarshal(b, &v) return json.Unmarshal(b, &v)
} }

View file

@ -29,20 +29,20 @@ const encoded = `{
}` }`
// Viper's internal representation // Viper's internal representation
var data = map[string]interface{}{ var data = map[string]any{
"key": "value", "key": "value",
"list": []interface{}{ "list": []any{
"item1", "item1",
"item2", "item2",
"item3", "item3",
}, },
"map": map[string]interface{}{ "map": map[string]any{
"key": "value", "key": "value",
}, },
"nested_map": map[string]interface{}{ "nested_map": map[string]any{
"map": map[string]interface{}{ "map": map[string]any{
"key": "value", "key": "value",
"list": []interface{}{ "list": []any{
"item1", "item1",
"item2", "item2",
"item3", "item3",
@ -68,7 +68,7 @@ func TestCodec_Decode(t *testing.T) {
t.Run("OK", func(t *testing.T) { t.Run("OK", func(t *testing.T) {
codec := Codec{} codec := Codec{}
v := map[string]interface{}{} v := map[string]any{}
err := codec.Decode([]byte(encoded), v) err := codec.Decode([]byte(encoded), v)
if err != nil { if err != nil {
@ -83,7 +83,7 @@ func TestCodec_Decode(t *testing.T) {
t.Run("InvalidData", func(t *testing.T) { t.Run("InvalidData", func(t *testing.T) {
codec := Codec{} codec := Codec{}
v := map[string]interface{}{} v := map[string]any{}
err := codec.Decode([]byte(`invalid data`), v) err := codec.Decode([]byte(`invalid data`), v)
if err == nil { if err == nil {

View file

@ -7,10 +7,10 @@ import (
// Codec implements the encoding.Encoder and encoding.Decoder interfaces for TOML encoding. // Codec implements the encoding.Encoder and encoding.Decoder interfaces for TOML encoding.
type Codec struct{} type Codec struct{}
func (Codec) Encode(v map[string]interface{}) ([]byte, error) { func (Codec) Encode(v map[string]any) ([]byte, error) {
return toml.Marshal(v) return toml.Marshal(v)
} }
func (Codec) Decode(b []byte, v map[string]interface{}) error { func (Codec) Decode(b []byte, v map[string]any) error {
return toml.Unmarshal(b, &v) return toml.Unmarshal(b, &v)
} }

View file

@ -39,20 +39,20 @@ list = ['item1', 'item2', 'item3']
` `
// Viper's internal representation // Viper's internal representation
var data = map[string]interface{}{ var data = map[string]any{
"key": "value", "key": "value",
"list": []interface{}{ "list": []any{
"item1", "item1",
"item2", "item2",
"item3", "item3",
}, },
"map": map[string]interface{}{ "map": map[string]any{
"key": "value", "key": "value",
}, },
"nested_map": map[string]interface{}{ "nested_map": map[string]any{
"map": map[string]interface{}{ "map": map[string]any{
"key": "value", "key": "value",
"list": []interface{}{ "list": []any{
"item1", "item1",
"item2", "item2",
"item3", "item3",
@ -78,7 +78,7 @@ func TestCodec_Decode(t *testing.T) {
t.Run("OK", func(t *testing.T) { t.Run("OK", func(t *testing.T) {
codec := Codec{} codec := Codec{}
v := map[string]interface{}{} v := map[string]any{}
err := codec.Decode([]byte(original), v) err := codec.Decode([]byte(original), v)
if err != nil { if err != nil {
@ -93,7 +93,7 @@ func TestCodec_Decode(t *testing.T) {
t.Run("InvalidData", func(t *testing.T) { t.Run("InvalidData", func(t *testing.T) {
codec := Codec{} codec := Codec{}
v := map[string]interface{}{} v := map[string]any{}
err := codec.Decode([]byte(`invalid data`), v) err := codec.Decode([]byte(`invalid data`), v)
if err == nil { if err == nil {

View file

@ -5,10 +5,10 @@ import "gopkg.in/yaml.v3"
// Codec implements the encoding.Encoder and encoding.Decoder interfaces for YAML encoding. // Codec implements the encoding.Encoder and encoding.Decoder interfaces for YAML encoding.
type Codec struct{} type Codec struct{}
func (Codec) Encode(v map[string]interface{}) ([]byte, error) { func (Codec) Encode(v map[string]any) ([]byte, error) {
return yaml.Marshal(v) return yaml.Marshal(v)
} }
func (Codec) Decode(b []byte, v map[string]interface{}) error { func (Codec) Decode(b []byte, v map[string]any) error {
return yaml.Unmarshal(b, &v) return yaml.Unmarshal(b, &v)
} }

View file

@ -47,20 +47,20 @@ nested_map:
// //
// in case of YAML it's slightly different from Viper's internal representation // in case of YAML it's slightly different from Viper's internal representation
// (eg. map is decoded into a map with interface key) // (eg. map is decoded into a map with interface key)
var decoded = map[string]interface{}{ var decoded = map[string]any{
"key": "value", "key": "value",
"list": []interface{}{ "list": []any{
"item1", "item1",
"item2", "item2",
"item3", "item3",
}, },
"map": map[string]interface{}{ "map": map[string]any{
"key": "value", "key": "value",
}, },
"nested_map": map[string]interface{}{ "nested_map": map[string]any{
"map": map[string]interface{}{ "map": map[string]any{
"key": "value", "key": "value",
"list": []interface{}{ "list": []any{
"item1", "item1",
"item2", "item2",
"item3", "item3",
@ -70,20 +70,20 @@ var decoded = map[string]interface{}{
} }
// Viper's internal representation // Viper's internal representation
var data = map[string]interface{}{ var data = map[string]any{
"key": "value", "key": "value",
"list": []interface{}{ "list": []any{
"item1", "item1",
"item2", "item2",
"item3", "item3",
}, },
"map": map[string]interface{}{ "map": map[string]any{
"key": "value", "key": "value",
}, },
"nested_map": map[string]interface{}{ "nested_map": map[string]any{
"map": map[string]interface{}{ "map": map[string]any{
"key": "value", "key": "value",
"list": []interface{}{ "list": []any{
"item1", "item1",
"item2", "item2",
"item3", "item3",
@ -109,7 +109,7 @@ func TestCodec_Decode(t *testing.T) {
t.Run("OK", func(t *testing.T) { t.Run("OK", func(t *testing.T) {
codec := Codec{} codec := Codec{}
v := map[string]interface{}{} v := map[string]any{}
err := codec.Decode([]byte(original), v) err := codec.Decode([]byte(original), v)
if err != nil { if err != nil {
@ -124,7 +124,7 @@ func TestCodec_Decode(t *testing.T) {
t.Run("InvalidData", func(t *testing.T) { t.Run("InvalidData", func(t *testing.T) {
codec := Codec{} codec := Codec{}
v := map[string]interface{}{} v := map[string]any{}
err := codec.Decode([]byte(`invalid data`), v) err := codec.Decode([]byte(`invalid data`), v)
if err == nil { if err == nil {

View file

@ -1,40 +0,0 @@
//go:build !go1.17
// +build !go1.17
package testutil
import (
"os"
"testing"
)
// Based on https://github.com/frankban/quicktest/blob/577841610793d24f99e31cc2c0ef3a541fefd7c7/patch.go#L34-L64
// Licensed under the MIT license
// Copyright (c) 2017 Canonical Ltd.
// Setenv sets an environment variable to a temporary value for the
// duration of the test.
//
// At the end of the test (see "Deferred execution" in the package docs), the
// environment variable is returned to its original value.
func Setenv(t *testing.T, name, val string) {
setenv(t, name, val, true)
}
// setenv sets or unsets an environment variable to a temporary value for the
// duration of the test
func setenv(t *testing.T, name, val string, valOK bool) {
oldVal, oldOK := os.LookupEnv(name)
if valOK {
os.Setenv(name, val)
} else {
os.Unsetenv(name)
}
t.Cleanup(func() {
if oldOK {
os.Setenv(name, oldVal)
} else {
os.Unsetenv(name)
}
})
}

View file

@ -1,18 +0,0 @@
//go:build go1.17
// +build go1.17
package testutil
import (
"testing"
)
// Setenv sets an environment variable to a temporary value for the
// duration of the test.
//
// This shim can be removed once support for Go <1.17 is dropped.
func Setenv(t *testing.T, name, val string) {
t.Helper()
t.Setenv(name, val)
}

View file

@ -1,77 +1,68 @@
package viper package viper
import ( import (
"fmt" "context"
jww "github.com/spf13/jwalterweatherman" slog "github.com/sagikazarmark/slog-shim"
) )
// Logger is a unified interface for various logging use cases and practices, including: // Logger is a unified interface for various logging use cases and practices, including:
// - leveled logging // - leveled logging
// - structured logging // - structured logging
//
// Deprecated: use `log/slog` instead.
type Logger interface { type Logger interface {
// Trace logs a Trace event. // Trace logs a Trace event.
// //
// Even more fine-grained information than Debug events. // Even more fine-grained information than Debug events.
// Loggers not supporting this level should fall back to Debug. // Loggers not supporting this level should fall back to Debug.
Trace(msg string, keyvals ...interface{}) Trace(msg string, keyvals ...any)
// Debug logs a Debug event. // Debug logs a Debug event.
// //
// A verbose series of information events. // A verbose series of information events.
// They are useful when debugging the system. // They are useful when debugging the system.
Debug(msg string, keyvals ...interface{}) Debug(msg string, keyvals ...any)
// Info logs an Info event. // Info logs an Info event.
// //
// General information about what's happening inside the system. // General information about what's happening inside the system.
Info(msg string, keyvals ...interface{}) Info(msg string, keyvals ...any)
// Warn logs a Warn(ing) event. // Warn logs a Warn(ing) event.
// //
// Non-critical events that should be looked at. // Non-critical events that should be looked at.
Warn(msg string, keyvals ...interface{}) Warn(msg string, keyvals ...any)
// Error logs an Error event. // Error logs an Error event.
// //
// Critical events that require immediate attention. // Critical events that require immediate attention.
// Loggers commonly provide Fatal and Panic levels above Error level, // Loggers commonly provide Fatal and Panic levels above Error level,
// but exiting and panicing is out of scope for a logging library. // but exiting and panicking is out of scope for a logging library.
Error(msg string, keyvals ...interface{}) Error(msg string, keyvals ...any)
} }
type jwwLogger struct{} // WithLogger sets a custom logger.
func WithLogger(l *slog.Logger) Option {
func (jwwLogger) Trace(msg string, keyvals ...interface{}) { return optionFunc(func(v *Viper) {
jww.TRACE.Printf(jwwLogMessage(msg, keyvals...)) v.logger = l
})
} }
func (jwwLogger) Debug(msg string, keyvals ...interface{}) { type discardHandler struct{}
jww.DEBUG.Printf(jwwLogMessage(msg, keyvals...))
func (n *discardHandler) Enabled(_ context.Context, _ slog.Level) bool {
return false
} }
func (jwwLogger) Info(msg string, keyvals ...interface{}) { func (n *discardHandler) Handle(_ context.Context, _ slog.Record) error {
jww.INFO.Printf(jwwLogMessage(msg, keyvals...)) return nil
} }
func (jwwLogger) Warn(msg string, keyvals ...interface{}) { func (n *discardHandler) WithAttrs(_ []slog.Attr) slog.Handler {
jww.WARN.Printf(jwwLogMessage(msg, keyvals...)) return n
} }
func (jwwLogger) Error(msg string, keyvals ...interface{}) { func (n *discardHandler) WithGroup(_ string) slog.Handler {
jww.ERROR.Printf(jwwLogMessage(msg, keyvals...)) return n
}
func jwwLogMessage(msg string, keyvals ...interface{}) string {
out := msg
if len(keyvals) > 0 && len(keyvals)%2 == 1 {
keyvals = append(keyvals, nil)
}
for i := 0; i <= len(keyvals)-2; i += 2 {
out = fmt.Sprintf("%s %v=%v", out, keyvals[i], keyvals[i+1])
}
return out
} }

View file

@ -1,7 +1,6 @@
package viper package viper
import ( import (
"fmt"
"strings" "strings"
"testing" "testing"
@ -46,11 +45,11 @@ func TestNestedOverrides(t *testing.T) {
deepCheckValue(assert, v, overrideLayer, []string{"tom", "size"}, 4) deepCheckValue(assert, v, overrideLayer, []string{"tom", "size"}, 4)
// Case 4: key:value overridden by a map // Case 4: key:value overridden by a map
v = overrideDefault(assert, "tom.size", 4, "tom", map[string]interface{}{"age": 10}) // "tom.size" is first given "4" as default value, then "tom" is overridden by map{"age":10} v = overrideDefault(assert, "tom.size", 4, "tom", map[string]any{"age": 10}) // "tom.size" is first given "4" as default value, then "tom" is overridden by map{"age":10}
assert.Equal(4, v.Get("tom.size")) // "tom.size" should still be reachable assert.Equal(4, v.Get("tom.size")) // "tom.size" should still be reachable
assert.Equal(10, v.Get("tom.age")) // new value should be there assert.Equal(10, v.Get("tom.age")) // new value should be there
deepCheckValue(assert, v, overrideLayer, []string{"tom", "age"}, 10) // new value should be there deepCheckValue(assert, v, overrideLayer, []string{"tom", "age"}, 10) // new value should be there
v = override(assert, "tom.size", 4, "tom", map[string]interface{}{"age": 10}) v = override(assert, "tom.size", 4, "tom", map[string]any{"age": 10})
assert.Nil(v.Get("tom.size")) assert.Nil(v.Get("tom.size"))
assert.Equal(10, v.Get("tom.age")) assert.Equal(10, v.Get("tom.age"))
deepCheckValue(assert, v, overrideLayer, []string{"tom", "age"}, 10) deepCheckValue(assert, v, overrideLayer, []string{"tom", "age"}, 10)
@ -75,11 +74,11 @@ func TestNestedOverrides(t *testing.T) {
} }
} }
func overrideDefault(assert *assert.Assertions, firstPath string, firstValue interface{}, secondPath string, secondValue interface{}) *Viper { func overrideDefault(assert *assert.Assertions, firstPath string, firstValue any, secondPath string, secondValue any) *Viper {
return overrideFromLayer(defaultLayer, assert, firstPath, firstValue, secondPath, secondValue) return overrideFromLayer(defaultLayer, assert, firstPath, firstValue, secondPath, secondValue)
} }
func override(assert *assert.Assertions, firstPath string, firstValue interface{}, secondPath string, secondValue interface{}) *Viper { func override(assert *assert.Assertions, firstPath string, firstValue any, secondPath string, secondValue any) *Viper {
return overrideFromLayer(overrideLayer, assert, firstPath, firstValue, secondPath, secondValue) return overrideFromLayer(overrideLayer, assert, firstPath, firstValue, secondPath, secondValue)
} }
@ -94,7 +93,7 @@ func override(assert *assert.Assertions, firstPath string, firstValue interface{
// //
// After each assignment, the value is checked, retrieved both by its full path // After each assignment, the value is checked, retrieved both by its full path
// and by its key sequence (successive maps). // and by its key sequence (successive maps).
func overrideFromLayer(l layer, assert *assert.Assertions, firstPath string, firstValue interface{}, secondPath string, secondValue interface{}) *Viper { func overrideFromLayer(l layer, assert *assert.Assertions, firstPath string, firstValue any, secondPath string, secondValue any) *Viper {
v := New() v := New()
firstKeys := strings.Split(firstPath, v.keyDelim) firstKeys := strings.Split(firstPath, v.keyDelim)
if assert == nil || if assert == nil ||
@ -128,14 +127,14 @@ func overrideFromLayer(l layer, assert *assert.Assertions, firstPath string, fir
// deepCheckValue checks that all given keys correspond to a valid path in the // deepCheckValue checks that all given keys correspond to a valid path in the
// configuration map of the given layer, and that the final value equals the one given // configuration map of the given layer, and that the final value equals the one given
func deepCheckValue(assert *assert.Assertions, v *Viper, l layer, keys []string, value interface{}) { func deepCheckValue(assert *assert.Assertions, v *Viper, l layer, keys []string, value any) {
if assert == nil || v == nil || if assert == nil || v == nil ||
len(keys) == 0 || len(keys[0]) == 0 { len(keys) == 0 || len(keys[0]) == 0 {
return return
} }
// init // init
var val interface{} var val any
var ms string var ms string
switch l { switch l {
case defaultLayer: case defaultLayer:
@ -147,28 +146,25 @@ func deepCheckValue(assert *assert.Assertions, v *Viper, l layer, keys []string,
} }
// loop through map // loop through map
var m map[string]interface{} var m map[string]any
err := false
for _, k := range keys { for _, k := range keys {
if val == nil { if val == nil {
assert.Fail(fmt.Sprintf("%s is not a map[string]interface{}", ms)) assert.Failf("%s is not a map[string]any", ms)
return return
} }
// deep scan of the map to get the final value // deep scan of the map to get the final value
switch val.(type) { switch val := val.(type) {
case map[interface{}]interface{}: case map[any]any:
m = cast.ToStringMap(val) m = cast.ToStringMap(val)
case map[string]interface{}: case map[string]any:
m = val.(map[string]interface{}) m = val
default: default:
assert.Fail(fmt.Sprintf("%s is not a map[string]interface{}", ms)) assert.Failf("%s is not a map[string]any", ms)
return return
} }
ms = ms + "[\"" + k + "\"]" ms = ms + "[\"" + k + "\"]"
val = m[k] val = m[k]
} }
if !err { assert.Equal(value, val)
assert.Equal(value, val)
}
} }

View file

@ -91,6 +91,8 @@ func getConfigManager(rp viper.RemoteProvider) (crypt.ConfigManager, error) {
cm, err = crypt.NewEtcdV3ConfigManager(endpoints, kr) cm, err = crypt.NewEtcdV3ConfigManager(endpoints, kr)
case "firestore": case "firestore":
cm, err = crypt.NewFirestoreConfigManager(endpoints, kr) cm, err = crypt.NewFirestoreConfigManager(endpoints, kr)
case "nats":
cm, err = crypt.NewNatsConfigManager(endpoints, kr)
default: default:
cm, err = crypt.NewConsulConfigManager(endpoints, kr) cm, err = crypt.NewConsulConfigManager(endpoints, kr)
} }
@ -102,6 +104,8 @@ func getConfigManager(rp viper.RemoteProvider) (crypt.ConfigManager, error) {
cm, err = crypt.NewStandardEtcdV3ConfigManager(endpoints) cm, err = crypt.NewStandardEtcdV3ConfigManager(endpoints)
case "firestore": case "firestore":
cm, err = crypt.NewStandardFirestoreConfigManager(endpoints) cm, err = crypt.NewStandardFirestoreConfigManager(endpoints)
case "nats":
cm, err = crypt.NewStandardNatsConfigManager(endpoints)
default: default:
cm, err = crypt.NewStandardConsulConfigManager(endpoints) cm, err = crypt.NewStandardConsulConfigManager(endpoints)
} }

45
util.go
View file

@ -18,6 +18,7 @@ import (
"strings" "strings"
"unicode" "unicode"
slog "github.com/sagikazarmark/slog-shim"
"github.com/spf13/cast" "github.com/spf13/cast"
) )
@ -38,11 +39,11 @@ func (pe ConfigParseError) Unwrap() error {
// toCaseInsensitiveValue checks if the value is a map; // toCaseInsensitiveValue checks if the value is a map;
// if so, create a copy and lower-case the keys recursively. // if so, create a copy and lower-case the keys recursively.
func toCaseInsensitiveValue(value interface{}) interface{} { func toCaseInsensitiveValue(value any) any {
switch v := value.(type) { switch v := value.(type) {
case map[interface{}]interface{}: case map[any]any:
value = copyAndInsensitiviseMap(cast.ToStringMap(v)) value = copyAndInsensitiviseMap(cast.ToStringMap(v))
case map[string]interface{}: case map[string]any:
value = copyAndInsensitiviseMap(v) value = copyAndInsensitiviseMap(v)
} }
@ -51,15 +52,15 @@ func toCaseInsensitiveValue(value interface{}) interface{} {
// copyAndInsensitiviseMap behaves like insensitiviseMap, but creates a copy of // copyAndInsensitiviseMap behaves like insensitiviseMap, but creates a copy of
// any map it makes case insensitive. // any map it makes case insensitive.
func copyAndInsensitiviseMap(m map[string]interface{}) map[string]interface{} { func copyAndInsensitiviseMap(m map[string]any) map[string]any {
nm := make(map[string]interface{}) nm := make(map[string]any)
for key, val := range m { for key, val := range m {
lkey := strings.ToLower(key) lkey := strings.ToLower(key)
switch v := val.(type) { switch v := val.(type) {
case map[interface{}]interface{}: case map[any]any:
nm[lkey] = copyAndInsensitiviseMap(cast.ToStringMap(v)) nm[lkey] = copyAndInsensitiviseMap(cast.ToStringMap(v))
case map[string]interface{}: case map[string]any:
nm[lkey] = copyAndInsensitiviseMap(v) nm[lkey] = copyAndInsensitiviseMap(v)
default: default:
nm[lkey] = v nm[lkey] = v
@ -69,23 +70,23 @@ func copyAndInsensitiviseMap(m map[string]interface{}) map[string]interface{} {
return nm return nm
} }
func insensitiviseVal(val interface{}) interface{} { func insensitiviseVal(val any) any {
switch val.(type) { switch v := val.(type) {
case map[interface{}]interface{}: case map[any]any:
// nested map: cast and recursively insensitivise // nested map: cast and recursively insensitivise
val = cast.ToStringMap(val) val = cast.ToStringMap(val)
insensitiviseMap(val.(map[string]interface{})) insensitiviseMap(val.(map[string]any))
case map[string]interface{}: case map[string]any:
// nested map: recursively insensitivise // nested map: recursively insensitivise
insensitiviseMap(val.(map[string]interface{})) insensitiviseMap(v)
case []interface{}: case []any:
// nested array: recursively insensitivise // nested array: recursively insensitivise
insensitiveArray(val.([]interface{})) insensitiveArray(v)
} }
return val return val
} }
func insensitiviseMap(m map[string]interface{}) { func insensitiviseMap(m map[string]any) {
for key, val := range m { for key, val := range m {
val = insensitiviseVal(val) val = insensitiviseVal(val)
lower := strings.ToLower(key) lower := strings.ToLower(key)
@ -98,13 +99,13 @@ func insensitiviseMap(m map[string]interface{}) {
} }
} }
func insensitiveArray(a []interface{}) { func insensitiveArray(a []any) {
for i, val := range a { for i, val := range a {
a[i] = insensitiviseVal(val) a[i] = insensitiviseVal(val)
} }
} }
func absPathify(logger Logger, inPath string) string { func absPathify(logger *slog.Logger, inPath string) string {
logger.Info("trying to resolve absolute path", "path", inPath) logger.Info("trying to resolve absolute path", "path", inPath)
if inPath == "$HOME" || strings.HasPrefix(inPath, "$HOME"+string(os.PathSeparator)) { if inPath == "$HOME" || strings.HasPrefix(inPath, "$HOME"+string(os.PathSeparator)) {
@ -197,22 +198,22 @@ func parseSizeInBytes(sizeStr string) uint {
// In case intermediate keys do not exist, or map to a non-map value, // In case intermediate keys do not exist, or map to a non-map value,
// a new map is created and inserted, and the search continues from there: // a new map is created and inserted, and the search continues from there:
// the initial map "m" may be modified! // the initial map "m" may be modified!
func deepSearch(m map[string]interface{}, path []string) map[string]interface{} { func deepSearch(m map[string]any, path []string) map[string]any {
for _, k := range path { for _, k := range path {
m2, ok := m[k] m2, ok := m[k]
if !ok { if !ok {
// intermediate key does not exist // intermediate key does not exist
// => create it and continue from there // => create it and continue from there
m3 := make(map[string]interface{}) m3 := make(map[string]any)
m[k] = m3 m[k] = m3
m = m3 m = m3
continue continue
} }
m3, ok := m2.(map[string]interface{}) m3, ok := m2.(map[string]any)
if !ok { if !ok {
// intermediate key is a value // intermediate key is a value
// => replace with a new map // => replace with a new map
m3 = make(map[string]interface{}) m3 = make(map[string]any)
m[k] = m3 m[k] = m3
} }
// continue search from here // continue search from here

View file

@ -16,21 +16,21 @@ import (
"reflect" "reflect"
"testing" "testing"
"github.com/spf13/viper/internal/testutil" slog "github.com/sagikazarmark/slog-shim"
) )
func TestCopyAndInsensitiviseMap(t *testing.T) { func TestCopyAndInsensitiviseMap(t *testing.T) {
var ( var (
given = map[string]interface{}{ given = map[string]any{
"Foo": 32, "Foo": 32,
"Bar": map[interface{}]interface{}{ "Bar": map[any]any{
"ABc": "A", "ABc": "A",
"cDE": "B", "cDE": "B",
}, },
} }
expected = map[string]interface{}{ expected = map[string]any{
"foo": 32, "foo": 32,
"bar": map[string]interface{}{ "bar": map[string]any{
"abc": "A", "abc": "A",
"cde": "B", "cde": "B",
}, },
@ -51,7 +51,7 @@ func TestCopyAndInsensitiviseMap(t *testing.T) {
t.Fatal("Input map changed") t.Fatal("Input map changed")
} }
m := given["Bar"].(map[interface{}]interface{}) m := given["Bar"].(map[any]any)
if _, ok := m["ABc"]; !ok { if _, ok := m["ABc"]; !ok {
t.Fatal("Input map changed") t.Fatal("Input map changed")
} }
@ -64,8 +64,8 @@ func TestAbsPathify(t *testing.T) {
homer := filepath.Join(home, "homer") homer := filepath.Join(home, "homer")
wd, _ := os.Getwd() wd, _ := os.Getwd()
testutil.Setenv(t, "HOMER_ABSOLUTE_PATH", homer) t.Setenv("HOMER_ABSOLUTE_PATH", homer)
testutil.Setenv(t, "VAR_WITH_RELATIVE_PATH", "relative") t.Setenv("VAR_WITH_RELATIVE_PATH", "relative")
tests := []struct { tests := []struct {
input string input string
@ -87,7 +87,7 @@ func TestAbsPathify(t *testing.T) {
} }
for _, test := range tests { for _, test := range tests {
got := absPathify(jwwLogger{}, test.input) got := absPathify(slog.Default(), test.input)
if got != test.output { if got != test.output {
t.Errorf("Got %v\nexpected\n%q", got, test.output) t.Errorf("Got %v\nexpected\n%q", got, test.output)
} }

235
viper.go
View file

@ -35,6 +35,7 @@ import (
"github.com/fsnotify/fsnotify" "github.com/fsnotify/fsnotify"
"github.com/mitchellh/mapstructure" "github.com/mitchellh/mapstructure"
slog "github.com/sagikazarmark/slog-shim"
"github.com/spf13/afero" "github.com/spf13/afero"
"github.com/spf13/cast" "github.com/spf13/cast"
"github.com/spf13/pflag" "github.com/spf13/pflag"
@ -206,10 +207,10 @@ type Viper struct {
allowEmptyEnv bool allowEmptyEnv bool
parents []string parents []string
config map[string]interface{} config map[string]any
override map[string]interface{} override map[string]any
defaults map[string]interface{} defaults map[string]any
kvstore map[string]interface{} kvstore map[string]any
pflags map[string]FlagValue pflags map[string]FlagValue
env map[string][]string env map[string][]string
aliases map[string]string aliases map[string]string
@ -217,7 +218,7 @@ type Viper struct {
onConfigChange func(fsnotify.Event) onConfigChange func(fsnotify.Event)
logger Logger logger *slog.Logger
// TODO: should probably be protected with a mutex // TODO: should probably be protected with a mutex
encoderRegistry *encoding.EncoderRegistry encoderRegistry *encoding.EncoderRegistry
@ -231,16 +232,16 @@ func New() *Viper {
v.configName = "config" v.configName = "config"
v.configPermissions = os.FileMode(0o644) v.configPermissions = os.FileMode(0o644)
v.fs = afero.NewOsFs() v.fs = afero.NewOsFs()
v.config = make(map[string]interface{}) v.config = make(map[string]any)
v.parents = []string{} v.parents = []string{}
v.override = make(map[string]interface{}) v.override = make(map[string]any)
v.defaults = make(map[string]interface{}) v.defaults = make(map[string]any)
v.kvstore = make(map[string]interface{}) v.kvstore = make(map[string]any)
v.pflags = make(map[string]FlagValue) 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.aliases = make(map[string]string)
v.typeByDefValue = false v.typeByDefValue = false
v.logger = jwwLogger{} v.logger = slog.New(&discardHandler{})
v.resetEncoding() v.resetEncoding()
@ -301,7 +302,7 @@ func NewWithOptions(opts ...Option) *Viper {
func Reset() { func Reset() {
v = New() v = New()
SupportedExts = []string{"json", "toml", "yaml", "yml", "properties", "props", "prop", "hcl", "tfvars", "dotenv", "env", "ini"} SupportedExts = []string{"json", "toml", "yaml", "yml", "properties", "props", "prop", "hcl", "tfvars", "dotenv", "env", "ini"}
SupportedRemoteProviders = []string{"etcd", "etcd3", "consul", "firestore"} SupportedRemoteProviders = []string{"etcd", "etcd3", "consul", "firestore", "nats"}
} }
// TODO: make this lazy initialization instead // TODO: make this lazy initialization instead
@ -420,7 +421,7 @@ type RemoteProvider interface {
var SupportedExts = []string{"json", "toml", "yaml", "yml", "properties", "props", "prop", "hcl", "tfvars", "dotenv", "env", "ini"} var SupportedExts = []string{"json", "toml", "yaml", "yml", "properties", "props", "prop", "hcl", "tfvars", "dotenv", "env", "ini"}
// SupportedRemoteProviders are universally supported remote providers. // SupportedRemoteProviders are universally supported remote providers.
var SupportedRemoteProviders = []string{"etcd", "etcd3", "consul", "firestore"} var SupportedRemoteProviders = []string{"etcd", "etcd3", "consul", "firestore", "nats"}
// OnConfigChange sets the event handler that is called when a config file changes. // OnConfigChange sets the event handler that is called when a config file changes.
func OnConfigChange(run func(in fsnotify.Event)) { v.OnConfigChange(run) } func OnConfigChange(run func(in fsnotify.Event)) { v.OnConfigChange(run) }
@ -584,8 +585,8 @@ func (v *Viper) AddConfigPath(in string) {
// AddRemoteProvider adds a remote configuration source. // AddRemoteProvider adds a remote configuration source.
// Remote Providers are searched in the order they are added. // Remote Providers are searched in the order they are added.
// provider is a string value: "etcd", "etcd3", "consul" or "firestore" are currently supported. // provider is a string value: "etcd", "etcd3", "consul", "firestore" or "nats" are currently supported.
// endpoint is the url. etcd requires http://ip:port consul requires ip:port // endpoint is the url. etcd requires http://ip:port, consul requires ip:port, nats requires nats://ip:port
// path is the path in the k/v store to retrieve configuration // path is the path in the k/v store to retrieve configuration
// To retrieve a config file called myapp.json from /configs/myapp.json // To retrieve a config file called myapp.json from /configs/myapp.json
// you should set path to /configs and set config name (SetConfigName()) to // you should set path to /configs and set config name (SetConfigName()) to
@ -615,7 +616,7 @@ func (v *Viper) AddRemoteProvider(provider, endpoint, path string) error {
// AddSecureRemoteProvider adds a remote configuration source. // AddSecureRemoteProvider adds a remote configuration source.
// Secure Remote Providers are searched in the order they are added. // Secure Remote Providers are searched in the order they are added.
// provider is a string value: "etcd", "etcd3", "consul" or "firestore" are currently supported. // provider is a string value: "etcd", "etcd3", "consul", "firestore" or "nats" are currently supported.
// endpoint is the url. etcd requires http://ip:port consul requires ip:port // endpoint is the url. etcd requires http://ip:port consul requires ip:port
// secretkeyring is the filepath to your openpgp secret keyring. e.g. /etc/secrets/myring.gpg // secretkeyring is the filepath to your openpgp secret keyring. e.g. /etc/secrets/myring.gpg
// path is the path in the k/v store to retrieve configuration // path is the path in the k/v store to retrieve configuration
@ -659,7 +660,7 @@ func (v *Viper) providerPathExists(p *defaultRemoteProvider) bool {
// searchMap recursively searches for a value for path in source map. // searchMap recursively searches for a value for path in source map.
// Returns nil if not found. // Returns nil if not found.
// Note: This assumes that the path entries and map keys are lower cased. // Note: This assumes that the path entries and map keys are lower cased.
func (v *Viper) searchMap(source map[string]interface{}, path []string) interface{} { func (v *Viper) searchMap(source map[string]any, path []string) any {
if len(path) == 0 { if len(path) == 0 {
return source return source
} }
@ -672,13 +673,13 @@ func (v *Viper) searchMap(source map[string]interface{}, path []string) interfac
} }
// Nested case // Nested case
switch next.(type) { switch next := next.(type) {
case map[interface{}]interface{}: case map[any]any:
return v.searchMap(cast.ToStringMap(next), path[1:]) return v.searchMap(cast.ToStringMap(next), path[1:])
case map[string]interface{}: case map[string]any:
// Type assertion is safe here since it is only reached // Type assertion is safe here since it is only reached
// if the type of `next` is the same as the type being asserted // if the type of `next` is the same as the type being asserted
return v.searchMap(next.(map[string]interface{}), path[1:]) return v.searchMap(next, path[1:])
default: default:
// got a value but nested key expected, return "nil" for not found // got a value but nested key expected, return "nil" for not found
return nil return nil
@ -698,7 +699,7 @@ func (v *Viper) searchMap(source map[string]interface{}, path []string) interfac
// in their keys). // in their keys).
// //
// Note: This assumes that the path entries and map keys are lower cased. // Note: This assumes that the path entries and map keys are lower cased.
func (v *Viper) searchIndexableWithPathPrefixes(source interface{}, path []string) interface{} { func (v *Viper) searchIndexableWithPathPrefixes(source any, path []string) any {
if len(path) == 0 { if len(path) == 0 {
return source return source
} }
@ -707,11 +708,11 @@ func (v *Viper) searchIndexableWithPathPrefixes(source interface{}, path []strin
for i := len(path); i > 0; i-- { for i := len(path); i > 0; i-- {
prefixKey := strings.ToLower(strings.Join(path[0:i], v.keyDelim)) prefixKey := strings.ToLower(strings.Join(path[0:i], v.keyDelim))
var val interface{} var val any
switch sourceIndexable := source.(type) { switch sourceIndexable := source.(type) {
case []interface{}: case []any:
val = v.searchSliceWithPathPrefixes(sourceIndexable, prefixKey, i, path) val = v.searchSliceWithPathPrefixes(sourceIndexable, prefixKey, i, path)
case map[string]interface{}: case map[string]any:
val = v.searchMapWithPathPrefixes(sourceIndexable, prefixKey, i, path) val = v.searchMapWithPathPrefixes(sourceIndexable, prefixKey, i, path)
} }
if val != nil { if val != nil {
@ -728,11 +729,11 @@ func (v *Viper) searchIndexableWithPathPrefixes(source interface{}, path []strin
// This function is part of the searchIndexableWithPathPrefixes recurring search and // This function is part of the searchIndexableWithPathPrefixes recurring search and
// should not be called directly from functions other than searchIndexableWithPathPrefixes. // should not be called directly from functions other than searchIndexableWithPathPrefixes.
func (v *Viper) searchSliceWithPathPrefixes( func (v *Viper) searchSliceWithPathPrefixes(
sourceSlice []interface{}, sourceSlice []any,
prefixKey string, prefixKey string,
pathIndex int, pathIndex int,
path []string, path []string,
) interface{} { ) any {
// if the prefixKey is not a number or it is out of bounds of the slice // if the prefixKey is not a number or it is out of bounds of the slice
index, err := strconv.Atoi(prefixKey) index, err := strconv.Atoi(prefixKey)
if err != nil || len(sourceSlice) <= index { if err != nil || len(sourceSlice) <= index {
@ -747,9 +748,9 @@ func (v *Viper) searchSliceWithPathPrefixes(
} }
switch n := next.(type) { switch n := next.(type) {
case map[interface{}]interface{}: case map[any]any:
return v.searchIndexableWithPathPrefixes(cast.ToStringMap(n), path[pathIndex:]) return v.searchIndexableWithPathPrefixes(cast.ToStringMap(n), path[pathIndex:])
case map[string]interface{}, []interface{}: case map[string]any, []any:
return v.searchIndexableWithPathPrefixes(n, path[pathIndex:]) return v.searchIndexableWithPathPrefixes(n, path[pathIndex:])
default: default:
// got a value but nested key expected, do nothing and look for next prefix // got a value but nested key expected, do nothing and look for next prefix
@ -764,11 +765,11 @@ func (v *Viper) searchSliceWithPathPrefixes(
// This function is part of the searchIndexableWithPathPrefixes recurring search and // This function is part of the searchIndexableWithPathPrefixes recurring search and
// should not be called directly from functions other than searchIndexableWithPathPrefixes. // should not be called directly from functions other than searchIndexableWithPathPrefixes.
func (v *Viper) searchMapWithPathPrefixes( func (v *Viper) searchMapWithPathPrefixes(
sourceMap map[string]interface{}, sourceMap map[string]any,
prefixKey string, prefixKey string,
pathIndex int, pathIndex int,
path []string, path []string,
) interface{} { ) any {
next, ok := sourceMap[prefixKey] next, ok := sourceMap[prefixKey]
if !ok { if !ok {
return nil return nil
@ -781,9 +782,9 @@ func (v *Viper) searchMapWithPathPrefixes(
// Nested case // Nested case
switch n := next.(type) { switch n := next.(type) {
case map[interface{}]interface{}: case map[any]any:
return v.searchIndexableWithPathPrefixes(cast.ToStringMap(n), path[pathIndex:]) return v.searchIndexableWithPathPrefixes(cast.ToStringMap(n), path[pathIndex:])
case map[string]interface{}, []interface{}: case map[string]any, []any:
return v.searchIndexableWithPathPrefixes(n, path[pathIndex:]) return v.searchIndexableWithPathPrefixes(n, path[pathIndex:])
default: default:
// got a value but nested key expected, do nothing and look for next prefix // got a value but nested key expected, do nothing and look for next prefix
@ -798,8 +799,8 @@ func (v *Viper) searchMapWithPathPrefixes(
// e.g., if "foo.bar" has a value in the given map, it “shadows” // e.g., if "foo.bar" has a value in the given map, it “shadows”
// //
// "foo.bar.baz" in a lower-priority map // "foo.bar.baz" in a lower-priority map
func (v *Viper) isPathShadowedInDeepMap(path []string, m map[string]interface{}) string { func (v *Viper) isPathShadowedInDeepMap(path []string, m map[string]any) string {
var parentVal interface{} var parentVal any
for i := 1; i < len(path); i++ { for i := 1; i < len(path); i++ {
parentVal = v.searchMap(m, path[0:i]) parentVal = v.searchMap(m, path[0:i])
if parentVal == nil { if parentVal == nil {
@ -807,9 +808,9 @@ func (v *Viper) isPathShadowedInDeepMap(path []string, m map[string]interface{})
return "" return ""
} }
switch parentVal.(type) { switch parentVal.(type) {
case map[interface{}]interface{}: case map[any]any:
continue continue
case map[string]interface{}: case map[string]any:
continue continue
default: default:
// parentVal is a regular value which shadows "path" // parentVal is a regular value which shadows "path"
@ -824,7 +825,7 @@ func (v *Viper) isPathShadowedInDeepMap(path []string, m map[string]interface{})
// e.g., if "foo.bar" has a value in the given map, it “shadows” // e.g., if "foo.bar" has a value in the given map, it “shadows”
// //
// "foo.bar.baz" in a lower-priority map // "foo.bar.baz" in a lower-priority map
func (v *Viper) isPathShadowedInFlatMap(path []string, mi interface{}) string { func (v *Viper) isPathShadowedInFlatMap(path []string, mi any) string {
// unify input map // unify input map
var m map[string]interface{} var m map[string]interface{}
switch miv := mi.(type) { switch miv := mi.(type) {
@ -895,9 +896,9 @@ func GetViper() *Viper {
// override, flag, env, config file, key/value store, default // override, flag, env, config file, key/value store, default
// //
// Get returns an interface. For a specific value use one of the Get____ methods. // Get returns an interface. For a specific value use one of the Get____ methods.
func Get(key string) interface{} { return v.Get(key) } func Get(key string) any { return v.Get(key) }
func (v *Viper) Get(key string) interface{} { func (v *Viper) Get(key string) any {
lcaseKey := strings.ToLower(key) lcaseKey := strings.ToLower(key)
val := v.find(lcaseKey, true) val := v.find(lcaseKey, true)
if val == nil { if val == nil {
@ -1067,9 +1068,9 @@ func (v *Viper) GetStringSlice(key string) []string {
} }
// GetStringMap returns the value associated with the key as a map of interfaces. // 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 GetStringMap(key string) map[string]any { return v.GetStringMap(key) }
func (v *Viper) GetStringMap(key string) map[string]interface{} { func (v *Viper) GetStringMap(key string) map[string]any {
return cast.ToStringMap(v.Get(key)) return cast.ToStringMap(v.Get(key))
} }
@ -1097,27 +1098,27 @@ func (v *Viper) GetSizeInBytes(key string) uint {
} }
// UnmarshalKey takes a single key and unmarshals it into a Struct. // UnmarshalKey takes a single key and unmarshals it into a Struct.
func UnmarshalKey(key string, rawVal interface{}, opts ...DecoderConfigOption) error { func UnmarshalKey(key string, rawVal any, opts ...DecoderConfigOption) error {
return v.UnmarshalKey(key, rawVal, opts...) return v.UnmarshalKey(key, rawVal, opts...)
} }
func (v *Viper) UnmarshalKey(key string, rawVal interface{}, opts ...DecoderConfigOption) error { func (v *Viper) UnmarshalKey(key string, rawVal any, opts ...DecoderConfigOption) error {
return decode(v.Get(key), defaultDecoderConfig(rawVal, opts...)) return decode(v.Get(key), defaultDecoderConfig(rawVal, opts...))
} }
// Unmarshal unmarshals the config into a Struct. Make sure that the tags // Unmarshal unmarshals the config into a Struct. Make sure that the tags
// on the fields of the structure are properly set. // on the fields of the structure are properly set.
func Unmarshal(rawVal interface{}, opts ...DecoderConfigOption) error { func Unmarshal(rawVal any, opts ...DecoderConfigOption) error {
return v.Unmarshal(rawVal, opts...) return v.Unmarshal(rawVal, opts...)
} }
func (v *Viper) Unmarshal(rawVal interface{}, opts ...DecoderConfigOption) error { func (v *Viper) Unmarshal(rawVal any, opts ...DecoderConfigOption) error {
return decode(v.AllSettings(), defaultDecoderConfig(rawVal, opts...)) return decode(v.AllSettings(), defaultDecoderConfig(rawVal, opts...))
} }
// defaultDecoderConfig returns default mapstructure.DecoderConfig with support // defaultDecoderConfig returns default mapstructure.DecoderConfig with support
// of time.Duration values & string slices // of time.Duration values & string slices
func defaultDecoderConfig(output interface{}, opts ...DecoderConfigOption) *mapstructure.DecoderConfig { func defaultDecoderConfig(output any, opts ...DecoderConfigOption) *mapstructure.DecoderConfig {
c := &mapstructure.DecoderConfig{ c := &mapstructure.DecoderConfig{
Metadata: nil, Metadata: nil,
Result: output, Result: output,
@ -1134,7 +1135,7 @@ func defaultDecoderConfig(output interface{}, opts ...DecoderConfigOption) *maps
} }
// A wrapper around mapstructure.Decode that mimics the WeakDecode functionality // A wrapper around mapstructure.Decode that mimics the WeakDecode functionality
func decode(input interface{}, config *mapstructure.DecoderConfig) error { func decode(input any, config *mapstructure.DecoderConfig) error {
decoder, err := mapstructure.NewDecoder(config) decoder, err := mapstructure.NewDecoder(config)
if err != nil { if err != nil {
return err return err
@ -1144,11 +1145,11 @@ func decode(input interface{}, config *mapstructure.DecoderConfig) error {
// UnmarshalExact unmarshals the config into a Struct, erroring if a field is nonexistent // UnmarshalExact unmarshals the config into a Struct, erroring if a field is nonexistent
// in the destination struct. // in the destination struct.
func UnmarshalExact(rawVal interface{}, opts ...DecoderConfigOption) error { func UnmarshalExact(rawVal any, opts ...DecoderConfigOption) error {
return v.UnmarshalExact(rawVal, opts...) return v.UnmarshalExact(rawVal, opts...)
} }
func (v *Viper) UnmarshalExact(rawVal interface{}, opts ...DecoderConfigOption) error { func (v *Viper) UnmarshalExact(rawVal any, opts ...DecoderConfigOption) error {
config := defaultDecoderConfig(rawVal, opts...) config := defaultDecoderConfig(rawVal, opts...)
config.ErrorUnused = true config.ErrorUnused = true
@ -1245,9 +1246,9 @@ func (v *Viper) MustBindEnv(input ...string) {
// corresponds to a flag, the flag's default value is returned. // corresponds to a flag, the flag's default value is returned.
// //
// Note: this assumes a lower-cased key given. // Note: this assumes a lower-cased key given.
func (v *Viper) find(lcaseKey string, flagDefault bool) interface{} { func (v *Viper) find(lcaseKey string, flagDefault bool) any {
var ( var (
val interface{} val any
exists bool exists bool
path = strings.Split(lcaseKey, v.keyDelim) path = strings.Split(lcaseKey, v.keyDelim)
nested = len(path) > 1 nested = len(path) > 1
@ -1406,46 +1407,46 @@ func readAsCSV(val string) ([]string, error) {
} }
// mostly copied from pflag's implementation of this operation here https://github.com/spf13/pflag/blob/master/string_to_string.go#L79 // mostly copied from pflag's implementation of this operation here https://github.com/spf13/pflag/blob/master/string_to_string.go#L79
// alterations are: errors are swallowed, map[string]interface{} is returned in order to enable cast.ToStringMap // alterations are: errors are swallowed, map[string]any is returned in order to enable cast.ToStringMap
func stringToStringConv(val string) interface{} { func stringToStringConv(val string) any {
val = strings.Trim(val, "[]") val = strings.Trim(val, "[]")
// An empty string would cause an empty map // An empty string would cause an empty map
if len(val) == 0 { if len(val) == 0 {
return map[string]interface{}{} return map[string]any{}
} }
r := csv.NewReader(strings.NewReader(val)) r := csv.NewReader(strings.NewReader(val))
ss, err := r.Read() ss, err := r.Read()
if err != nil { if err != nil {
return nil return nil
} }
out := make(map[string]interface{}, len(ss)) out := make(map[string]any, len(ss))
for _, pair := range ss { for _, pair := range ss {
kv := strings.SplitN(pair, "=", 2) k, vv, found := strings.Cut(pair, "=")
if len(kv) != 2 { if !found {
return nil return nil
} }
out[kv[0]] = kv[1] out[k] = vv
} }
return out return out
} }
// mostly copied from pflag's implementation of this operation here https://github.com/spf13/pflag/blob/d5e0c0615acee7028e1e2740a11102313be88de1/string_to_int.go#L68 // mostly copied from pflag's implementation of this operation here https://github.com/spf13/pflag/blob/d5e0c0615acee7028e1e2740a11102313be88de1/string_to_int.go#L68
// alterations are: errors are swallowed, map[string]interface{} is returned in order to enable cast.ToStringMap // alterations are: errors are swallowed, map[string]any is returned in order to enable cast.ToStringMap
func stringToIntConv(val string) interface{} { func stringToIntConv(val string) any {
val = strings.Trim(val, "[]") val = strings.Trim(val, "[]")
// An empty string would cause an empty map // An empty string would cause an empty map
if len(val) == 0 { if len(val) == 0 {
return map[string]interface{}{} return map[string]any{}
} }
ss := strings.Split(val, ",") ss := strings.Split(val, ",")
out := make(map[string]interface{}, len(ss)) out := make(map[string]any, len(ss))
for _, pair := range ss { for _, pair := range ss {
kv := strings.SplitN(pair, "=", 2) k, vv, found := strings.Cut(pair, "=")
if len(kv) != 2 { if !found {
return nil return nil
} }
var err error var err error
out[kv[0]], err = strconv.Atoi(kv[1]) out[k], err = strconv.Atoi(vv)
if err != nil { if err != nil {
return nil return nil
} }
@ -1546,9 +1547,9 @@ func (v *Viper) InConfig(key string) bool {
// SetDefault sets the default value for this key. // SetDefault sets the default value for this key.
// SetDefault is case-insensitive for a key. // SetDefault is case-insensitive for a key.
// Default only used when no value is provided by the user via flag, config or ENV. // 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 SetDefault(key string, value any) { v.SetDefault(key, value) }
func (v *Viper) SetDefault(key string, value interface{}) { func (v *Viper) SetDefault(key string, value any) {
// If alias passed in, then set the proper default // If alias passed in, then set the proper default
key = v.realKey(strings.ToLower(key)) key = v.realKey(strings.ToLower(key))
value = toCaseInsensitiveValue(value) value = toCaseInsensitiveValue(value)
@ -1565,9 +1566,9 @@ func (v *Viper) SetDefault(key string, value interface{}) {
// Set is case-insensitive for a key. // Set is case-insensitive for a key.
// Will be used instead of values obtained via // Will be used instead of values obtained via
// flags, config file, ENV, default, or key/value store. // flags, config file, ENV, default, or key/value store.
func Set(key string, value interface{}) { v.Set(key, value) } func Set(key string, value any) { v.Set(key, value) }
func (v *Viper) Set(key string, value interface{}) { func (v *Viper) Set(key string, value any) {
// If alias passed in, then set the proper override // If alias passed in, then set the proper override
key = v.realKey(strings.ToLower(key)) key = v.realKey(strings.ToLower(key))
value = toCaseInsensitiveValue(value) value = toCaseInsensitiveValue(value)
@ -1601,7 +1602,7 @@ func (v *Viper) ReadInConfig() error {
return err return err
} }
config := make(map[string]interface{}) config := make(map[string]any)
err = v.unmarshalReader(bytes.NewReader(file), config) err = v.unmarshalReader(bytes.NewReader(file), config)
if err != nil { if err != nil {
@ -1639,7 +1640,7 @@ func (v *Viper) MergeInConfig() error {
func ReadConfig(in io.Reader) error { return v.ReadConfig(in) } func ReadConfig(in io.Reader) error { return v.ReadConfig(in) }
func (v *Viper) ReadConfig(in io.Reader) error { func (v *Viper) ReadConfig(in io.Reader) error {
v.config = make(map[string]interface{}) v.config = make(map[string]any)
return v.unmarshalReader(in, v.config) return v.unmarshalReader(in, v.config)
} }
@ -1647,7 +1648,7 @@ func (v *Viper) ReadConfig(in io.Reader) error {
func MergeConfig(in io.Reader) error { return v.MergeConfig(in) } func MergeConfig(in io.Reader) error { return v.MergeConfig(in) }
func (v *Viper) MergeConfig(in io.Reader) error { func (v *Viper) MergeConfig(in io.Reader) error {
cfg := make(map[string]interface{}) cfg := make(map[string]any)
if err := v.unmarshalReader(in, cfg); err != nil { if err := v.unmarshalReader(in, cfg); err != nil {
return err return err
} }
@ -1656,11 +1657,11 @@ func (v *Viper) MergeConfig(in io.Reader) error {
// MergeConfigMap merges the configuration from the map given with an existing config. // MergeConfigMap merges the configuration from the map given with an existing config.
// Note that the map given may be modified. // Note that the map given may be modified.
func MergeConfigMap(cfg map[string]interface{}) error { return v.MergeConfigMap(cfg) } func MergeConfigMap(cfg map[string]any) error { return v.MergeConfigMap(cfg) }
func (v *Viper) MergeConfigMap(cfg map[string]interface{}) error { func (v *Viper) MergeConfigMap(cfg map[string]any) error {
if v.config == nil { if v.config == nil {
v.config = make(map[string]interface{}) v.config = make(map[string]any)
} }
insensitiviseMap(cfg) insensitiviseMap(cfg)
mergeMaps(cfg, v.config, nil) mergeMaps(cfg, v.config, nil)
@ -1725,7 +1726,7 @@ func (v *Viper) writeConfig(filename string, force bool) error {
return UnsupportedConfigError(configType) return UnsupportedConfigError(configType)
} }
if v.config == nil { if v.config == nil {
v.config = make(map[string]interface{}) v.config = make(map[string]any)
} }
flags := os.O_CREATE | os.O_TRUNC | os.O_WRONLY flags := os.O_CREATE | os.O_TRUNC | os.O_WRONLY
if !force { if !force {
@ -1746,11 +1747,11 @@ func (v *Viper) writeConfig(filename string, force bool) error {
// Unmarshal a Reader into a map. // Unmarshal a Reader into a map.
// Should probably be an unexported function. // Should probably be an unexported function.
func unmarshalReader(in io.Reader, c map[string]interface{}) error { func unmarshalReader(in io.Reader, c map[string]any) error {
return v.unmarshalReader(in, c) return v.unmarshalReader(in, c)
} }
func (v *Viper) unmarshalReader(in io.Reader, c map[string]interface{}) error { func (v *Viper) unmarshalReader(in io.Reader, c map[string]any) error {
buf := new(bytes.Buffer) buf := new(bytes.Buffer)
buf.ReadFrom(in) buf.ReadFrom(in)
@ -1784,7 +1785,7 @@ func (v *Viper) marshalWriter(f afero.File, configType string) error {
return nil return nil
} }
func keyExists(k string, m map[string]interface{}) string { func keyExists(k string, m map[string]any) string {
lk := strings.ToLower(k) lk := strings.ToLower(k)
for mk := range m { for mk := range m {
lmk := strings.ToLower(mk) lmk := strings.ToLower(mk)
@ -1796,33 +1797,33 @@ func keyExists(k string, m map[string]interface{}) string {
} }
func castToMapStringInterface( func castToMapStringInterface(
src map[interface{}]interface{}, src map[any]any,
) map[string]interface{} { ) map[string]any {
tgt := map[string]interface{}{} tgt := map[string]any{}
for k, v := range src { for k, v := range src {
tgt[fmt.Sprintf("%v", k)] = v tgt[fmt.Sprintf("%v", k)] = v
} }
return tgt return tgt
} }
func castMapStringSliceToMapInterface(src map[string][]string) map[string]interface{} { func castMapStringSliceToMapInterface(src map[string][]string) map[string]any {
tgt := map[string]interface{}{} tgt := map[string]any{}
for k, v := range src { for k, v := range src {
tgt[k] = v tgt[k] = v
} }
return tgt return tgt
} }
func castMapStringToMapInterface(src map[string]string) map[string]interface{} { func castMapStringToMapInterface(src map[string]string) map[string]any {
tgt := map[string]interface{}{} tgt := map[string]any{}
for k, v := range src { for k, v := range src {
tgt[k] = v tgt[k] = v
} }
return tgt return tgt
} }
func castMapFlagToMapInterface(src map[string]FlagValue) map[string]interface{} { func castMapFlagToMapInterface(src map[string]FlagValue) map[string]any {
tgt := map[string]interface{}{} tgt := map[string]any{}
for k, v := range src { for k, v := range src {
tgt[k] = v tgt[k] = v
} }
@ -1830,17 +1831,15 @@ func castMapFlagToMapInterface(src map[string]FlagValue) map[string]interface{}
} }
// mergeMaps merges two maps. The `itgt` parameter is for handling go-yaml's // mergeMaps merges two maps. The `itgt` parameter is for handling go-yaml's
// insistence on parsing nested structures as `map[interface{}]interface{}` // insistence on parsing nested structures as `map[any]any`
// instead of using a `string` as the key for nest structures beyond one level // instead of using a `string` as the key for nest structures beyond one level
// deep. Both map types are supported as there is a go-yaml fork that uses // deep. Both map types are supported as there is a go-yaml fork that uses
// `map[string]interface{}` instead. // `map[string]any` instead.
func mergeMaps( func mergeMaps(src, tgt map[string]any, itgt map[any]any) {
src, tgt map[string]interface{}, itgt map[interface{}]interface{},
) {
for sk, sv := range src { for sk, sv := range src {
tk := keyExists(sk, tgt) tk := keyExists(sk, tgt)
if tk == "" { if tk == "" {
v.logger.Trace("", "tk", "\"\"", fmt.Sprintf("tgt[%s]", sk), sv) v.logger.Debug("", "tk", "\"\"", fmt.Sprintf("tgt[%s]", sk), sv)
tgt[sk] = sv tgt[sk] = sv
if itgt != nil { if itgt != nil {
itgt[sk] = sv itgt[sk] = sv
@ -1850,7 +1849,7 @@ func mergeMaps(
tv, ok := tgt[tk] tv, ok := tgt[tk]
if !ok { if !ok {
v.logger.Trace("", fmt.Sprintf("ok[%s]", tk), false, fmt.Sprintf("tgt[%s]", sk), sv) v.logger.Debug("", fmt.Sprintf("ok[%s]", tk), false, fmt.Sprintf("tgt[%s]", sk), sv)
tgt[sk] = sv tgt[sk] = sv
if itgt != nil { if itgt != nil {
itgt[sk] = sv itgt[sk] = sv
@ -1861,7 +1860,7 @@ func mergeMaps(
svType := reflect.TypeOf(sv) svType := reflect.TypeOf(sv)
tvType := reflect.TypeOf(tv) tvType := reflect.TypeOf(tv)
v.logger.Trace( v.logger.Debug(
"processing", "processing",
"key", sk, "key", sk,
"st", svType, "st", svType,
@ -1871,12 +1870,12 @@ func mergeMaps(
) )
switch ttv := tv.(type) { switch ttv := tv.(type) {
case map[interface{}]interface{}: case map[any]any:
v.logger.Trace("merging maps (must convert)") v.logger.Debug("merging maps (must convert)")
tsv, ok := sv.(map[interface{}]interface{}) tsv, ok := sv.(map[any]any)
if !ok { if !ok {
v.logger.Error( v.logger.Error(
"Could not cast sv to map[interface{}]interface{}", "Could not cast sv to map[any]any",
"key", sk, "key", sk,
"st", svType, "st", svType,
"tt", tvType, "tt", tvType,
@ -1889,12 +1888,12 @@ func mergeMaps(
ssv := castToMapStringInterface(tsv) ssv := castToMapStringInterface(tsv)
stv := castToMapStringInterface(ttv) stv := castToMapStringInterface(ttv)
mergeMaps(ssv, stv, ttv) mergeMaps(ssv, stv, ttv)
case map[string]interface{}: case map[string]any:
v.logger.Trace("merging maps") v.logger.Debug("merging maps")
tsv, ok := sv.(map[string]interface{}) tsv, ok := sv.(map[string]any)
if !ok { if !ok {
v.logger.Error( v.logger.Error(
"Could not cast sv to map[string]interface{}", "Could not cast sv to map[string]any",
"key", sk, "key", sk,
"st", svType, "st", svType,
"tt", tvType, "tt", tvType,
@ -1905,7 +1904,7 @@ func mergeMaps(
} }
mergeMaps(tsv, ttv, nil) mergeMaps(tsv, ttv, nil)
default: default:
v.logger.Trace("setting value") v.logger.Debug("setting value")
tgt[tk] = sv tgt[tk] = sv
if itgt != nil { if itgt != nil {
itgt[tk] = sv itgt[tk] = sv
@ -1956,7 +1955,7 @@ func (v *Viper) getKeyValueConfig() error {
return RemoteConfigError("No Files Found") return RemoteConfigError("No Files Found")
} }
func (v *Viper) getRemoteConfig(provider RemoteProvider) (map[string]interface{}, error) { func (v *Viper) getRemoteConfig(provider RemoteProvider) (map[string]any, error) {
reader, err := RemoteConfig.Get(provider) reader, err := RemoteConfig.Get(provider)
if err != nil { if err != nil {
return nil, err return nil, err
@ -2005,7 +2004,7 @@ func (v *Viper) watchKeyValueConfig() error {
return RemoteConfigError("No Files Found") return RemoteConfigError("No Files Found")
} }
func (v *Viper) watchRemoteConfig(provider RemoteProvider) (map[string]interface{}, error) { func (v *Viper) watchRemoteConfig(provider RemoteProvider) (map[string]any, error) {
reader, err := RemoteConfig.Watch(provider) reader, err := RemoteConfig.Watch(provider)
if err != nil { if err != nil {
return nil, err return nil, err
@ -2044,7 +2043,7 @@ func (v *Viper) AllKeys() []string {
// it is skipped. // it is skipped.
// //
// The resulting set of paths is merged to the given shadow set at the same time. // The resulting set of paths is merged to the given shadow set at the same time.
func (v *Viper) flattenAndMergeMap(shadow map[string]bool, m map[string]interface{}, prefix string) map[string]bool { func (v *Viper) flattenAndMergeMap(shadow map[string]bool, m map[string]any, prefix string) map[string]bool {
if shadow != nil && prefix != "" && shadow[prefix] { if shadow != nil && prefix != "" && shadow[prefix] {
// prefix is shadowed => nothing more to flatten // prefix is shadowed => nothing more to flatten
return shadow return shadow
@ -2053,16 +2052,16 @@ func (v *Viper) flattenAndMergeMap(shadow map[string]bool, m map[string]interfac
shadow = make(map[string]bool) shadow = make(map[string]bool)
} }
var m2 map[string]interface{} var m2 map[string]any
if prefix != "" { if prefix != "" {
prefix += v.keyDelim prefix += v.keyDelim
} }
for k, val := range m { for k, val := range m {
fullKey := prefix + k fullKey := prefix + k
switch val.(type) { switch val := val.(type) {
case map[string]interface{}: case map[string]any:
m2 = val.(map[string]interface{}) m2 = val
case map[interface{}]interface{}: case map[any]any:
m2 = cast.ToStringMap(val) m2 = cast.ToStringMap(val)
default: default:
// immediate value // immediate value
@ -2077,7 +2076,7 @@ func (v *Viper) flattenAndMergeMap(shadow map[string]bool, m map[string]interfac
// mergeFlatMap merges the given maps, excluding values of the second map // mergeFlatMap merges the given maps, excluding values of the second map
// shadowed by values from the first map. // shadowed by values from the first map.
func (v *Viper) mergeFlatMap(shadow map[string]bool, m map[string]interface{}) map[string]bool { func (v *Viper) mergeFlatMap(shadow map[string]bool, m map[string]any) map[string]bool {
// scan keys // scan keys
outer: outer:
for k := range m { for k := range m {
@ -2097,11 +2096,11 @@ outer:
return shadow return shadow
} }
// AllSettings merges all settings and returns them as a map[string]interface{}. // AllSettings merges all settings and returns them as a map[string]any.
func AllSettings() map[string]interface{} { return v.AllSettings() } func AllSettings() map[string]any { return v.AllSettings() }
func (v *Viper) AllSettings() map[string]interface{} { func (v *Viper) AllSettings() map[string]any {
m := map[string]interface{}{} m := map[string]any{}
// start from the list of keys, and construct the map one value at a time // start from the list of keys, and construct the map one value at a time
for _, k := range v.AllKeys() { for _, k := range v.AllKeys() {
value := v.Get(k) value := v.Get(k)

View file

@ -1,32 +0,0 @@
//go:build go1.16 && finder
// +build go1.16,finder
package viper
import (
"fmt"
"github.com/spf13/afero"
)
// Search all configPaths for any config file.
// Returns the first path that exists (and is a config file).
func (v *Viper) findConfigFile() (string, error) {
finder := finder{
paths: v.configPaths,
fileNames: []string{v.configName},
extensions: SupportedExts,
withoutExtension: v.configType != "",
}
file, err := finder.Find(afero.NewIOFS(v.fs))
if err != nil {
return "", err
}
if file == "" {
return "", ConfigFileNotFoundError{v.configName, fmt.Sprintf("%s", v.configPaths)}
}
return file, nil
}

View file

@ -10,14 +10,12 @@ import (
"encoding/json" "encoding/json"
"errors" "errors"
"io" "io"
"io/ioutil"
"os" "os"
"os/exec" "os/exec"
"path" "path"
"path/filepath" "path/filepath"
"reflect" "reflect"
"runtime" "runtime"
"sort"
"strings" "strings"
"sync" "sync"
"testing" "testing"
@ -237,7 +235,7 @@ func initIni() {
} }
// make directories for testing // make directories for testing
func initDirs(t *testing.T) (string, string, func()) { func initDirs(t *testing.T) (string, string) {
var ( var (
testDirs = []string{`a a`, `b`, `C_`} testDirs = []string{`a a`, `b`, `C_`}
config = `improbable` config = `improbable`
@ -247,38 +245,21 @@ func initDirs(t *testing.T) (string, string, func()) {
testDirs = append(testDirs, `d\d`) testDirs = append(testDirs, `d\d`)
} }
root, err := ioutil.TempDir("", "") root := t.TempDir()
require.NoError(t, err, "Failed to create temporary directory")
cleanup := true
defer func() {
if cleanup {
os.Chdir("..")
os.RemoveAll(root)
}
}()
assert.Nil(t, err)
err = os.Chdir(root)
require.Nil(t, err)
for _, dir := range testDirs { for _, dir := range testDirs {
err = os.Mkdir(dir, 0o750) innerDir := filepath.Join(root, dir)
assert.Nil(t, err) err := os.Mkdir(innerDir, 0o750)
require.NoError(t, err)
err = ioutil.WriteFile( err = os.WriteFile(
path.Join(dir, config+".toml"), filepath.Join(innerDir, config+".toml"),
[]byte("key = \"value is "+dir+"\"\n"), []byte(`key = "value is `+dir+`"`+"\n"),
0o640) 0o640)
assert.Nil(t, err) require.NoError(t, err)
} }
cleanup = false return root, config
return root, config, func() {
os.Chdir("..")
os.RemoveAll(root)
}
} }
// stubs for PFlag Values // stubs for PFlag Values
@ -514,8 +495,8 @@ func TestUnmarshaling(t *testing.T) {
assert.False(t, InConfig("state")) assert.False(t, InConfig("state"))
assert.False(t, InConfig("clothing.hat")) assert.False(t, InConfig("clothing.hat"))
assert.Equal(t, "steve", Get("name")) assert.Equal(t, "steve", Get("name"))
assert.Equal(t, []interface{}{"skateboarding", "snowboarding", "go"}, Get("hobbies")) assert.Equal(t, []any{"skateboarding", "snowboarding", "go"}, Get("hobbies"))
assert.Equal(t, map[string]interface{}{"jacket": "leather", "trousers": "denim", "pants": map[string]interface{}{"size": "large"}}, Get("clothing")) assert.Equal(t, map[string]any{"jacket": "leather", "trousers": "denim", "pants": map[string]any{"size": "large"}}, Get("clothing"))
assert.Equal(t, 35, Get("age")) assert.Equal(t, 35, Get("age"))
} }
@ -620,10 +601,10 @@ func TestEnv(t *testing.T) {
BindEnv("id") BindEnv("id")
BindEnv("f", "FOOD", "OLD_FOOD") BindEnv("f", "FOOD", "OLD_FOOD")
testutil.Setenv(t, "ID", "13") t.Setenv("ID", "13")
testutil.Setenv(t, "FOOD", "apple") t.Setenv("FOOD", "apple")
testutil.Setenv(t, "OLD_FOOD", "banana") t.Setenv("OLD_FOOD", "banana")
testutil.Setenv(t, "NAME", "crunk") t.Setenv("NAME", "crunk")
assert.Equal(t, "13", Get("id")) assert.Equal(t, "13", Get("id"))
assert.Equal(t, "apple", Get("f")) assert.Equal(t, "apple", Get("f"))
@ -639,7 +620,7 @@ func TestMultipleEnv(t *testing.T) {
BindEnv("f", "FOOD", "OLD_FOOD") BindEnv("f", "FOOD", "OLD_FOOD")
testutil.Setenv(t, "OLD_FOOD", "banana") t.Setenv("OLD_FOOD", "banana")
assert.Equal(t, "banana", Get("f")) assert.Equal(t, "banana", Get("f"))
} }
@ -650,7 +631,7 @@ func TestEmptyEnv(t *testing.T) {
BindEnv("type") // Empty environment variable BindEnv("type") // Empty environment variable
BindEnv("name") // Bound, but not set environment variable BindEnv("name") // Bound, but not set environment variable
testutil.Setenv(t, "TYPE", "") t.Setenv("TYPE", "")
assert.Equal(t, "donut", Get("type")) assert.Equal(t, "donut", Get("type"))
assert.Equal(t, "Cake", Get("name")) assert.Equal(t, "Cake", Get("name"))
@ -664,7 +645,7 @@ func TestEmptyEnv_Allowed(t *testing.T) {
BindEnv("type") // Empty environment variable BindEnv("type") // Empty environment variable
BindEnv("name") // Bound, but not set environment variable BindEnv("name") // Bound, but not set environment variable
testutil.Setenv(t, "TYPE", "") t.Setenv("TYPE", "")
assert.Equal(t, "", Get("type")) assert.Equal(t, "", Get("type"))
assert.Equal(t, "Cake", Get("name")) assert.Equal(t, "Cake", Get("name"))
@ -677,9 +658,9 @@ func TestEnvPrefix(t *testing.T) {
BindEnv("id") BindEnv("id")
BindEnv("f", "FOOD") // not using prefix BindEnv("f", "FOOD") // not using prefix
testutil.Setenv(t, "FOO_ID", "13") t.Setenv("FOO_ID", "13")
testutil.Setenv(t, "FOOD", "apple") t.Setenv("FOOD", "apple")
testutil.Setenv(t, "FOO_NAME", "crunk") t.Setenv("FOO_NAME", "crunk")
assert.Equal(t, "13", Get("id")) assert.Equal(t, "13", Get("id"))
assert.Equal(t, "apple", Get("f")) assert.Equal(t, "apple", Get("f"))
@ -695,7 +676,7 @@ func TestAutoEnv(t *testing.T) {
AutomaticEnv() AutomaticEnv()
testutil.Setenv(t, "FOO_BAR", "13") t.Setenv("FOO_BAR", "13")
assert.Equal(t, "13", Get("foo_bar")) assert.Equal(t, "13", Get("foo_bar"))
} }
@ -706,7 +687,7 @@ func TestAutoEnvWithPrefix(t *testing.T) {
AutomaticEnv() AutomaticEnv()
SetEnvPrefix("Baz") SetEnvPrefix("Baz")
testutil.Setenv(t, "BAZ_BAR", "13") t.Setenv("BAZ_BAR", "13")
assert.Equal(t, "13", Get("bar")) assert.Equal(t, "13", Get("bar"))
} }
@ -716,7 +697,7 @@ func TestSetEnvKeyReplacer(t *testing.T) {
AutomaticEnv() AutomaticEnv()
testutil.Setenv(t, "REFRESH_INTERVAL", "30s") t.Setenv("REFRESH_INTERVAL", "30s")
replacer := strings.NewReplacer("-", "_") replacer := strings.NewReplacer("-", "_")
SetEnvKeyReplacer(replacer) SetEnvKeyReplacer(replacer)
@ -729,7 +710,7 @@ func TestEnvKeyReplacer(t *testing.T) {
v.AutomaticEnv() v.AutomaticEnv()
testutil.Setenv(t, "REFRESH_INTERVAL", "30s") t.Setenv("REFRESH_INTERVAL", "30s")
assert.Equal(t, "30s", v.Get("refresh-interval")) assert.Equal(t, "30s", v.Get("refresh-interval"))
} }
@ -741,21 +722,21 @@ func TestEnvSubConfig(t *testing.T) {
v.SetEnvKeyReplacer(strings.NewReplacer(".", "_")) v.SetEnvKeyReplacer(strings.NewReplacer(".", "_"))
testutil.Setenv(t, "CLOTHING_PANTS_SIZE", "small") t.Setenv("CLOTHING_PANTS_SIZE", "small")
subv := v.Sub("clothing").Sub("pants") subv := v.Sub("clothing").Sub("pants")
assert.Equal(t, "small", subv.Get("size")) assert.Equal(t, "small", subv.Get("size"))
// again with EnvPrefix // again with EnvPrefix
v.SetEnvPrefix("foo") // will be uppercased automatically v.SetEnvPrefix("foo") // will be uppercased automatically
subWithPrefix := v.Sub("clothing").Sub("pants") subWithPrefix := v.Sub("clothing").Sub("pants")
testutil.Setenv(t, "FOO_CLOTHING_PANTS_SIZE", "large") t.Setenv("FOO_CLOTHING_PANTS_SIZE", "large")
assert.Equal(t, "large", subWithPrefix.Get("size")) assert.Equal(t, "large", subWithPrefix.Get("size"))
} }
func TestAllKeys(t *testing.T) { func TestAllKeys(t *testing.T) {
initConfigs() initConfigs()
ks := sort.StringSlice{ ks := []string{
"title", "title",
"author.bio", "author.bio",
"author.e-mail", "author.e-mail",
@ -792,14 +773,14 @@ func TestAllKeys(t *testing.T) {
"name_dotenv", "name_dotenv",
} }
dob, _ := time.Parse(time.RFC3339, "1979-05-27T07:32:00Z") dob, _ := time.Parse(time.RFC3339, "1979-05-27T07:32:00Z")
all := map[string]interface{}{ all := map[string]any{
"owner": map[string]interface{}{ "owner": map[string]any{
"organization": "MongoDB", "organization": "MongoDB",
"bio": "MongoDB Chief Developer Advocate & Hacker at Large", "bio": "MongoDB Chief Developer Advocate & Hacker at Large",
"dob": dob, "dob": dob,
}, },
"title": "TOML Example", "title": "TOML Example",
"author": map[string]interface{}{ "author": map[string]any{
"e-mail": "fake@localhost", "e-mail": "fake@localhost",
"github": "https://github.com/Unknown", "github": "https://github.com/Unknown",
"name": "Unknown", "name": "Unknown",
@ -807,28 +788,28 @@ func TestAllKeys(t *testing.T) {
}, },
"ppu": 0.55, "ppu": 0.55,
"eyes": "brown", "eyes": "brown",
"clothing": map[string]interface{}{ "clothing": map[string]any{
"trousers": "denim", "trousers": "denim",
"jacket": "leather", "jacket": "leather",
"pants": map[string]interface{}{"size": "large"}, "pants": map[string]any{"size": "large"},
}, },
"default": map[string]interface{}{ "default": map[string]any{
"import_path": "gopkg.in/ini.v1", "import_path": "gopkg.in/ini.v1",
"name": "ini", "name": "ini",
"version": "v1", "version": "v1",
}, },
"id": "0001", "id": "0001",
"batters": map[string]interface{}{ "batters": map[string]any{
"batter": []interface{}{ "batter": []any{
map[string]interface{}{"type": "Regular"}, map[string]any{"type": "Regular"},
map[string]interface{}{"type": "Chocolate"}, map[string]any{"type": "Chocolate"},
map[string]interface{}{"type": "Blueberry"}, map[string]any{"type": "Blueberry"},
map[string]interface{}{"type": "Devil's Food"}, map[string]any{"type": "Devil's Food"},
}, },
}, },
"hacker": true, "hacker": true,
"beard": true, "beard": true,
"hobbies": []interface{}{ "hobbies": []any{
"skateboarding", "skateboarding",
"snowboarding", "snowboarding",
"go", "go",
@ -840,13 +821,13 @@ func TestAllKeys(t *testing.T) {
"p_id": "0001", "p_id": "0001",
"p_ppu": "0.55", "p_ppu": "0.55",
"p_name": "Cake", "p_name": "Cake",
"p_batters": map[string]interface{}{ "p_batters": map[string]any{
"batter": map[string]interface{}{"type": "Regular"}, "batter": map[string]any{"type": "Regular"},
}, },
"p_type": "donut", "p_type": "donut",
"foos": []map[string]interface{}{ "foos": []map[string]any{
{ {
"foo": []map[string]interface{}{ "foo": []map[string]any{
{"key": 1}, {"key": 1},
{"key": 2}, {"key": 2},
{"key": 3}, {"key": 3},
@ -859,11 +840,7 @@ func TestAllKeys(t *testing.T) {
"name_dotenv": "Cake", "name_dotenv": "Cake",
} }
allkeys := sort.StringSlice(AllKeys()) assert.ElementsMatch(t, ks, AllKeys())
allkeys.Sort()
ks.Sort()
assert.Equal(t, ks, allkeys)
assert.Equal(t, all, AllSettings()) assert.Equal(t, all, AllSettings())
} }
@ -875,14 +852,10 @@ func TestAllKeysWithEnv(t *testing.T) {
v.BindEnv("foo.bar") v.BindEnv("foo.bar")
v.SetEnvKeyReplacer(strings.NewReplacer(".", "_")) v.SetEnvKeyReplacer(strings.NewReplacer(".", "_"))
testutil.Setenv(t, "ID", "13") t.Setenv("ID", "13")
testutil.Setenv(t, "FOO_BAR", "baz") t.Setenv("FOO_BAR", "baz")
expectedKeys := sort.StringSlice{"id", "foo.bar"} assert.ElementsMatch(t, []string{"id", "foo.bar"}, v.AllKeys())
expectedKeys.Sort()
keys := sort.StringSlice(v.AllKeys())
keys.Sort()
assert.Equal(t, expectedKeys, keys)
} }
func TestAliasesOfAliases(t *testing.T) { func TestAliasesOfAliases(t *testing.T) {
@ -955,7 +928,7 @@ func TestUnmarshalWithDecoderOptions(t *testing.T) {
mapstructure.StringToTimeDurationHookFunc(), mapstructure.StringToTimeDurationHookFunc(),
mapstructure.StringToSliceHookFunc(","), mapstructure.StringToSliceHookFunc(","),
// Custom Decode Hook Function // Custom Decode Hook Function
func(rf reflect.Kind, rt reflect.Kind, data interface{}) (interface{}, error) { func(rf reflect.Kind, rt reflect.Kind, data any) (any, error) {
if rf != reflect.String || rt != reflect.Map { if rf != reflect.String || rt != reflect.Map {
return data, nil return data, nil
} }
@ -1308,7 +1281,7 @@ func TestBoundCaseSensitivity(t *testing.T) {
BindEnv("eYEs", "TURTLE_EYES") BindEnv("eYEs", "TURTLE_EYES")
testutil.Setenv(t, "TURTLE_EYES", "blue") t.Setenv("TURTLE_EYES", "blue")
assert.Equal(t, "blue", Get("eyes")) assert.Equal(t, "blue", Get("eyes"))
@ -1346,38 +1319,38 @@ func TestFindsNestedKeys(t *testing.T) {
initConfigs() initConfigs()
dob, _ := time.Parse(time.RFC3339, "1979-05-27T07:32:00Z") dob, _ := time.Parse(time.RFC3339, "1979-05-27T07:32:00Z")
Set("super", map[string]interface{}{ Set("super", map[string]any{
"deep": map[string]interface{}{ "deep": map[string]any{
"nested": "value", "nested": "value",
}, },
}) })
expected := map[string]interface{}{ expected := map[string]any{
"super": map[string]interface{}{ "super": map[string]any{
"deep": map[string]interface{}{ "deep": map[string]any{
"nested": "value", "nested": "value",
}, },
}, },
"super.deep": map[string]interface{}{ "super.deep": map[string]any{
"nested": "value", "nested": "value",
}, },
"super.deep.nested": "value", "super.deep.nested": "value",
"owner.organization": "MongoDB", "owner.organization": "MongoDB",
"batters.batter": []interface{}{ "batters.batter": []any{
map[string]interface{}{ map[string]any{
"type": "Regular", "type": "Regular",
}, },
map[string]interface{}{ map[string]any{
"type": "Chocolate", "type": "Chocolate",
}, },
map[string]interface{}{ map[string]any{
"type": "Blueberry", "type": "Blueberry",
}, },
map[string]interface{}{ map[string]any{
"type": "Devil's Food", "type": "Devil's Food",
}, },
}, },
"hobbies": []interface{}{ "hobbies": []any{
"skateboarding", "snowboarding", "go", "skateboarding", "snowboarding", "go",
}, },
"TITLE_DOTENV": "DotEnv Example", "TITLE_DOTENV": "DotEnv Example",
@ -1385,25 +1358,25 @@ func TestFindsNestedKeys(t *testing.T) {
"NAME_DOTENV": "Cake", "NAME_DOTENV": "Cake",
"title": "TOML Example", "title": "TOML Example",
"newkey": "remote", "newkey": "remote",
"batters": map[string]interface{}{ "batters": map[string]any{
"batter": []interface{}{ "batter": []any{
map[string]interface{}{ map[string]any{
"type": "Regular", "type": "Regular",
}, },
map[string]interface{}{ map[string]any{
"type": "Chocolate", "type": "Chocolate",
}, },
map[string]interface{}{ map[string]any{
"type": "Blueberry", "type": "Blueberry",
}, },
map[string]interface{}{ map[string]any{
"type": "Devil's Food", "type": "Devil's Food",
}, },
}, },
}, },
"eyes": "brown", "eyes": "brown",
"age": 35, "age": 35,
"owner": map[string]interface{}{ "owner": map[string]any{
"organization": "MongoDB", "organization": "MongoDB",
"bio": "MongoDB Chief Developer Advocate & Hacker at Large", "bio": "MongoDB Chief Developer Advocate & Hacker at Large",
"dob": dob, "dob": dob,
@ -1414,10 +1387,10 @@ func TestFindsNestedKeys(t *testing.T) {
"name": "Cake", "name": "Cake",
"hacker": true, "hacker": true,
"ppu": 0.55, "ppu": 0.55,
"clothing": map[string]interface{}{ "clothing": map[string]any{
"jacket": "leather", "jacket": "leather",
"trousers": "denim", "trousers": "denim",
"pants": map[string]interface{}{ "pants": map[string]any{
"size": "large", "size": "large",
}, },
}, },
@ -1426,9 +1399,9 @@ func TestFindsNestedKeys(t *testing.T) {
"clothing.trousers": "denim", "clothing.trousers": "denim",
"owner.dob": dob, "owner.dob": dob,
"beard": true, "beard": true,
"foos": []map[string]interface{}{ "foos": []map[string]any{
{ {
"foo": []map[string]interface{}{ "foo": []map[string]any{
{ {
"key": 1, "key": 1,
}, },
@ -1462,8 +1435,8 @@ func TestReadBufConfig(t *testing.T) {
assert.False(t, v.InConfig("state")) assert.False(t, v.InConfig("state"))
assert.False(t, v.InConfig("clothing.hat")) assert.False(t, v.InConfig("clothing.hat"))
assert.Equal(t, "steve", v.Get("name")) assert.Equal(t, "steve", v.Get("name"))
assert.Equal(t, []interface{}{"skateboarding", "snowboarding", "go"}, v.Get("hobbies")) assert.Equal(t, []any{"skateboarding", "snowboarding", "go"}, v.Get("hobbies"))
assert.Equal(t, map[string]interface{}{"jacket": "leather", "trousers": "denim", "pants": map[string]interface{}{"size": "large"}}, v.Get("clothing")) assert.Equal(t, map[string]any{"jacket": "leather", "trousers": "denim", "pants": map[string]any{"size": "large"}}, v.Get("clothing"))
assert.Equal(t, 35, v.Get("age")) assert.Equal(t, 35, v.Get("age"))
} }
@ -1492,8 +1465,8 @@ func TestIsSet(t *testing.T) {
v.BindEnv("clothing.hat") v.BindEnv("clothing.hat")
v.BindEnv("clothing.hats") v.BindEnv("clothing.hats")
testutil.Setenv(t, "FOO", "bar") t.Setenv("FOO", "bar")
testutil.Setenv(t, "CLOTHING_HAT", "bowler") t.Setenv("CLOTHING_HAT", "bowler")
assert.True(t, v.IsSet("eyes")) // in the config file assert.True(t, v.IsSet("eyes")) // in the config file
assert.True(t, v.IsSet("foo")) // in the environment assert.True(t, v.IsSet("foo")) // in the environment
@ -1515,30 +1488,28 @@ func TestIsSet(t *testing.T) {
} }
func TestDirsSearch(t *testing.T) { func TestDirsSearch(t *testing.T) {
root, config, cleanup := initDirs(t) root, config := initDirs(t)
defer cleanup()
v := New() v := New()
v.SetConfigName(config) v.SetConfigName(config)
v.SetDefault(`key`, `default`) v.SetDefault(`key`, `default`)
entries, err := ioutil.ReadDir(root) entries, err := os.ReadDir(root)
assert.Nil(t, err) require.NoError(t, err)
for _, e := range entries { for _, e := range entries {
if e.IsDir() { if e.IsDir() {
v.AddConfigPath(e.Name()) v.AddConfigPath(filepath.Join(root, e.Name()))
} }
} }
err = v.ReadInConfig() err = v.ReadInConfig()
assert.Nil(t, err) require.NoError(t, err)
assert.Equal(t, `value is `+filepath.Base(v.configPaths[0]), v.GetString(`key`)) assert.Equal(t, `value is `+filepath.Base(v.configPaths[0]), v.GetString(`key`))
} }
func TestWrongDirsSearchNotFound(t *testing.T) { func TestWrongDirsSearchNotFound(t *testing.T) {
_, config, cleanup := initDirs(t) _, config := initDirs(t)
defer cleanup()
v := New() v := New()
v.SetConfigName(config) v.SetConfigName(config)
@ -1548,7 +1519,7 @@ func TestWrongDirsSearchNotFound(t *testing.T) {
v.AddConfigPath(`thispathaintthere`) v.AddConfigPath(`thispathaintthere`)
err := v.ReadInConfig() err := v.ReadInConfig()
assert.Equal(t, reflect.TypeOf(ConfigFileNotFoundError{"", ""}), reflect.TypeOf(err)) assert.IsType(t, err, ConfigFileNotFoundError{"", ""})
// Even though config did not load and the error might have // Even though config did not load and the error might have
// been ignored by the client, the default still loads // been ignored by the client, the default still loads
@ -1556,8 +1527,7 @@ func TestWrongDirsSearchNotFound(t *testing.T) {
} }
func TestWrongDirsSearchNotFoundForMerge(t *testing.T) { func TestWrongDirsSearchNotFoundForMerge(t *testing.T) {
_, config, cleanup := initDirs(t) _, config := initDirs(t)
defer cleanup()
v := New() v := New()
v.SetConfigName(config) v.SetConfigName(config)
@ -1604,12 +1574,10 @@ func TestSub(t *testing.T) {
assert.Equal(t, (*Viper)(nil), subv) assert.Equal(t, (*Viper)(nil), subv)
subv = v.Sub("clothing") subv = v.Sub("clothing")
assert.Equal(t, subv.parents[0], "clothing") assert.Equal(t, []string{"clothing"}, subv.parents)
subv = v.Sub("clothing").Sub("pants") subv = v.Sub("clothing").Sub("pants")
assert.Equal(t, len(subv.parents), 2) assert.Equal(t, []string{"clothing", "pants"}, subv.parents)
assert.Equal(t, subv.parents[0], "clothing")
assert.Equal(t, subv.parents[1], "pants")
} }
var hclWriteExpected = []byte(`"foos" = { var hclWriteExpected = []byte(`"foos" = {
@ -2201,11 +2169,11 @@ func TestMergeConfigMap(t *testing.T) {
assert(37890) assert(37890)
update := map[string]interface{}{ update := map[string]any{
"Hello": map[string]interface{}{ "Hello": map[string]any{
"Pop": 1234, "Pop": 1234,
}, },
"World": map[interface{}]interface{}{ "World": map[any]any{
"Rock": 345, "Rock": 345,
}, },
} }
@ -2276,19 +2244,19 @@ clothing:
assert.Nil(t, Get("clothing.jacket.price")) assert.Nil(t, Get("clothing.jacket.price"))
assert.Equal(t, polyester, GetString("clothing.shirt")) assert.Equal(t, polyester, GetString("clothing.shirt"))
clothingSettings := AllSettings()["clothing"].(map[string]interface{}) clothingSettings := AllSettings()["clothing"].(map[string]any)
assert.Equal(t, "leather", clothingSettings["jacket"]) assert.Equal(t, "leather", clothingSettings["jacket"])
assert.Equal(t, polyester, clothingSettings["shirt"]) assert.Equal(t, polyester, clothingSettings["shirt"])
} }
func TestDotParameter(t *testing.T) { func TestDotParameter(t *testing.T) {
initJSON() initJSON()
// shoud take precedence over batters defined in jsonExample // should take precedence over batters defined in jsonExample
r := bytes.NewReader([]byte(`{ "batters.batter": [ { "type": "Small" } ] }`)) r := bytes.NewReader([]byte(`{ "batters.batter": [ { "type": "Small" } ] }`))
unmarshalReader(r, v.config) unmarshalReader(r, v.config)
actual := Get("batters.batter") actual := Get("batters.batter")
expected := []interface{}{map[string]interface{}{"type": "Small"}} expected := []any{map[string]any{"type": "Small"}}
assert.Equal(t, expected, actual) assert.Equal(t, expected, actual)
} }
@ -2339,17 +2307,17 @@ R = 6
func TestCaseInsensitiveSet(t *testing.T) { func TestCaseInsensitiveSet(t *testing.T) {
Reset() Reset()
m1 := map[string]interface{}{ m1 := map[string]any{
"Foo": 32, "Foo": 32,
"Bar": map[interface{}]interface{}{ "Bar": map[any]any{
"ABc": "A", "ABc": "A",
"cDE": "B", "cDE": "B",
}, },
} }
m2 := map[string]interface{}{ m2 := map[string]any{
"Foo": 52, "Foo": 52,
"Bar": map[interface{}]interface{}{ "Bar": map[any]any{
"bCd": "A", "bCd": "A",
"eFG": "B", "eFG": "B",
}, },
@ -2420,7 +2388,7 @@ func TestParseNested(t *testing.T) {
t.Fatalf("unable to decode into struct, %v", err) t.Fatalf("unable to decode into struct, %v", err)
} }
assert.Equal(t, 1, len(items)) assert.Len(t, items, 1)
assert.Equal(t, 100*time.Millisecond, items[0].Delay) assert.Equal(t, 100*time.Millisecond, items[0].Delay)
assert.Equal(t, 200*time.Millisecond, items[0].Nested.Delay) assert.Equal(t, 200*time.Millisecond, items[0].Nested.Delay)
} }
@ -2438,36 +2406,28 @@ func doTestCaseInsensitive(t *testing.T, typ, config string) {
assert.Equal(t, 5, cast.ToInt(Get("ef.lm.p.q"))) assert.Equal(t, 5, cast.ToInt(Get("ef.lm.p.q")))
} }
func newViperWithConfigFile(t *testing.T) (*Viper, string, func()) { func newViperWithConfigFile(t *testing.T) (*Viper, string) {
watchDir, err := ioutil.TempDir("", "") watchDir := t.TempDir()
require.Nil(t, err)
configFile := path.Join(watchDir, "config.yaml") configFile := path.Join(watchDir, "config.yaml")
err = ioutil.WriteFile(configFile, []byte("foo: bar\n"), 0o640) err := os.WriteFile(configFile, []byte("foo: bar\n"), 0o640)
require.Nil(t, err) require.NoError(t, err)
cleanup := func() {
os.RemoveAll(watchDir)
}
v := New() v := New()
v.SetConfigFile(configFile) v.SetConfigFile(configFile)
err = v.ReadInConfig() err = v.ReadInConfig()
require.Nil(t, err) require.NoError(t, err)
require.Equal(t, "bar", v.Get("foo")) require.Equal(t, "bar", v.Get("foo"))
return v, configFile, cleanup return v, configFile
} }
func newViperWithSymlinkedConfigFile(t *testing.T) (*Viper, string, string, func()) { func newViperWithSymlinkedConfigFile(t *testing.T) (*Viper, string, string) {
watchDir, err := ioutil.TempDir("", "") watchDir := t.TempDir()
require.Nil(t, err)
dataDir1 := path.Join(watchDir, "data1") dataDir1 := path.Join(watchDir, "data1")
err = os.Mkdir(dataDir1, 0o777) err := os.Mkdir(dataDir1, 0o777)
require.Nil(t, err) require.NoError(t, err)
realConfigFile := path.Join(dataDir1, "config.yaml") realConfigFile := path.Join(dataDir1, "config.yaml")
t.Logf("Real config file location: %s\n", realConfigFile) t.Logf("Real config file location: %s\n", realConfigFile)
err = ioutil.WriteFile(realConfigFile, []byte("foo: bar\n"), 0o640) err = os.WriteFile(realConfigFile, []byte("foo: bar\n"), 0o640)
require.Nil(t, err) require.NoError(t, err)
cleanup := func() {
os.RemoveAll(watchDir)
}
// now, symlink the tm `data1` dir to `data` in the baseDir // now, symlink the tm `data1` dir to `data` in the baseDir
os.Symlink(dataDir1, path.Join(watchDir, "data")) os.Symlink(dataDir1, path.Join(watchDir, "data"))
// and link the `<watchdir>/datadir1/config.yaml` to `<watchdir>/config.yaml` // and link the `<watchdir>/datadir1/config.yaml` to `<watchdir>/config.yaml`
@ -2478,9 +2438,9 @@ func newViperWithSymlinkedConfigFile(t *testing.T) (*Viper, string, string, func
v := New() v := New()
v.SetConfigFile(configFile) v.SetConfigFile(configFile)
err = v.ReadInConfig() err = v.ReadInConfig()
require.Nil(t, err) require.NoError(t, err)
require.Equal(t, "bar", v.Get("foo")) require.Equal(t, "bar", v.Get("foo"))
return v, watchDir, configFile, cleanup return v, watchDir, configFile
} }
func TestWatchFile(t *testing.T) { func TestWatchFile(t *testing.T) {
@ -2491,8 +2451,7 @@ func TestWatchFile(t *testing.T) {
t.Run("file content changed", func(t *testing.T) { t.Run("file content changed", func(t *testing.T) {
// given a `config.yaml` file being watched // given a `config.yaml` file being watched
v, configFile, cleanup := newViperWithConfigFile(t) v, configFile := newViperWithConfigFile(t)
defer cleanup()
_, err := os.Stat(configFile) _, err := os.Stat(configFile)
require.NoError(t, err) require.NoError(t, err)
t.Logf("test config file: %s\n", configFile) t.Logf("test config file: %s\n", configFile)
@ -2507,10 +2466,10 @@ func TestWatchFile(t *testing.T) {
}) })
v.WatchConfig() v.WatchConfig()
// when overwriting the file and waiting for the custom change notification handler to be triggered // when overwriting the file and waiting for the custom change notification handler to be triggered
err = ioutil.WriteFile(configFile, []byte("foo: baz\n"), 0o640) err = os.WriteFile(configFile, []byte("foo: baz\n"), 0o640)
wg.Wait() wg.Wait()
// then the config value should have changed // then the config value should have changed
require.Nil(t, err) require.NoError(t, err)
assert.Equal(t, "baz", v.Get("foo")) assert.Equal(t, "baz", v.Get("foo"))
}) })
@ -2519,8 +2478,7 @@ func TestWatchFile(t *testing.T) {
if runtime.GOOS != "linux" { if runtime.GOOS != "linux" {
t.Skipf("Skipping test as symlink replacements don't work on non-linux environment...") t.Skipf("Skipping test as symlink replacements don't work on non-linux environment...")
} }
v, watchDir, _, _ := newViperWithSymlinkedConfigFile(t) v, watchDir, _ := newViperWithSymlinkedConfigFile(t)
// defer cleanup()
wg := sync.WaitGroup{} wg := sync.WaitGroup{}
v.WatchConfig() v.WatchConfig()
v.OnConfigChange(func(in fsnotify.Event) { v.OnConfigChange(func(in fsnotify.Event) {
@ -2531,16 +2489,16 @@ func TestWatchFile(t *testing.T) {
// when link to another `config.yaml` file // when link to another `config.yaml` file
dataDir2 := path.Join(watchDir, "data2") dataDir2 := path.Join(watchDir, "data2")
err := os.Mkdir(dataDir2, 0o777) err := os.Mkdir(dataDir2, 0o777)
require.Nil(t, err) require.NoError(t, err)
configFile2 := path.Join(dataDir2, "config.yaml") configFile2 := path.Join(dataDir2, "config.yaml")
err = ioutil.WriteFile(configFile2, []byte("foo: baz\n"), 0o640) err = os.WriteFile(configFile2, []byte("foo: baz\n"), 0o640)
require.Nil(t, err) require.NoError(t, err)
// change the symlink using the `ln -sfn` command // change the symlink using the `ln -sfn` command
err = exec.Command("ln", "-sfn", dataDir2, path.Join(watchDir, "data")).Run() err = exec.Command("ln", "-sfn", dataDir2, path.Join(watchDir, "data")).Run()
require.Nil(t, err) require.NoError(t, err)
wg.Wait() wg.Wait()
// then // then
require.Nil(t, err) require.NoError(t, err)
assert.Equal(t, "baz", v.Get("foo")) assert.Equal(t, "baz", v.Get("foo"))
}) })
} }
@ -2590,13 +2548,13 @@ func TestKeyDelimiter(t *testing.T) {
err := v.unmarshalReader(r, v.config) err := v.unmarshalReader(r, v.config)
require.NoError(t, err) require.NoError(t, err)
values := map[string]interface{}{ values := map[string]any{
"image": map[string]interface{}{ "image": map[string]any{
"repository": "someImage", "repository": "someImage",
"tag": "1.0.0", "tag": "1.0.0",
}, },
"ingress": map[string]interface{}{ "ingress": map[string]any{
"annotations": map[string]interface{}{ "annotations": map[string]any{
"traefik.frontend.rule.type": "PathPrefix", "traefik.frontend.rule.type": "PathPrefix",
"traefik.ingress.kubernetes.io/ssl-redirect": "true", "traefik.ingress.kubernetes.io/ssl-redirect": "true",
}, },
@ -2610,13 +2568,13 @@ func TestKeyDelimiter(t *testing.T) {
type config struct { type config struct {
Charts struct { Charts struct {
Values map[string]interface{} Values map[string]any
} }
} }
expected := config{ expected := config{
Charts: struct { Charts: struct {
Values map[string]interface{} Values map[string]any
}{ }{
Values: values, Values: values,
}, },

View file

@ -1,5 +1,4 @@
//go:build darwin || dragonfly || freebsd || openbsd || linux || netbsd || solaris || windows //go:build darwin || dragonfly || freebsd || openbsd || linux || netbsd || solaris || windows
// +build darwin dragonfly freebsd openbsd linux netbsd solaris windows
package viper package viper

View file

@ -1,5 +1,4 @@
//go:build appengine || (!darwin && !dragonfly && !freebsd && !openbsd && !linux && !netbsd && !solaris && !windows) //go:build appengine || (!darwin && !dragonfly && !freebsd && !openbsd && !linux && !netbsd && !solaris && !windows)
// +build appengine !darwin,!dragonfly,!freebsd,!openbsd,!linux,!netbsd,!solaris,!windows
package viper package viper