mirror of
https://github.com/spf13/viper
synced 2025-05-07 20:57:18 +00:00
Merge branch 'master' into bugfix/map-interface-cast
This commit is contained in:
commit
d5282b8564
49 changed files with 642 additions and 914 deletions
2
.github/workflows/checks.yaml
vendored
2
.github/workflows/checks.yaml
vendored
|
@ -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
|
||||||
|
|
35
.github/workflows/ci.yaml
vendored
35
.github/workflows/ci.yaml
vendored
|
@ -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
|
||||||
|
|
8
.github/workflows/codeql-analysis.yaml
vendored
8
.github/workflows/codeql-analysis.yaml
vendored
|
@ -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
|
||||||
|
|
||||||
|
|
2
.github/workflows/feedback_issue.yaml
vendored
2
.github/workflows/feedback_issue.yaml
vendored
|
@ -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: |
|
||||||
|
|
2
.github/workflows/feedback_pull_request.yaml
vendored
2
.github/workflows/feedback_pull_request.yaml
vendored
|
@ -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: |
|
||||||
|
|
4
Makefile
4
Makefile
|
@ -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
|
||||||
|
|
33
README.md
33
README.md
|
@ -11,7 +11,7 @@
|
||||||
[](https://github.com/spf13/viper/actions?query=workflow%3ACI)
|
[](https://github.com/spf13/viper/actions?query=workflow%3ACI)
|
||||||
[](https://gitter.im/spf13/viper?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge)
|
[](https://gitter.im/spf13/viper?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge)
|
||||||
[](https://goreportcard.com/report/github.com/spf13/viper)
|
[](https://goreportcard.com/report/github.com/spf13/viper)
|
||||||

|

|
||||||
[](https://pkg.go.dev/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 value’s type.
|
In Viper, there are a few ways to get a value depending on the value’s 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 it’s not found. To check if a given key exists, the `IsSet()` method
|
value if it’s 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
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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
|
|
||||||
})
|
|
||||||
}
|
|
|
@ -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
38
file_finder.go
Normal 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
|
||||||
|
}
|
2
flags.go
2
flags.go
|
@ -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
|
||||||
|
|
|
@ -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
65
fs.go
|
@ -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
|
|
||||||
}
|
|
100
fs_test.go
100
fs_test.go
|
@ -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
58
go.mod
|
@ -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
148
go.sum
|
@ -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=
|
||||||
|
|
|
@ -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()
|
||||||
|
|
|
@ -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 {
|
||||||
|
|
|
@ -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)
|
||||||
|
|
|
@ -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 {
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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()
|
||||||
|
|
|
@ -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)
|
||||||
}
|
}
|
||||||
|
|
|
@ -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)
|
||||||
}
|
}
|
||||||
|
|
|
@ -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 {
|
||||||
|
|
|
@ -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)
|
||||||
|
|
|
@ -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 {
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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 {
|
||||||
|
|
|
@ -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 {
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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)
|
||||||
}
|
}
|
||||||
|
|
|
@ -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 {
|
||||||
|
|
|
@ -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)
|
||||||
}
|
}
|
||||||
|
|
|
@ -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 {
|
||||||
|
|
|
@ -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)
|
||||||
}
|
}
|
||||||
|
|
|
@ -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 {
|
||||||
|
|
|
@ -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)
|
|
||||||
}
|
|
||||||
})
|
|
||||||
}
|
|
|
@ -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)
|
|
||||||
}
|
|
59
logger.go
59
logger.go
|
@ -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
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -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)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -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
45
util.go
|
@ -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
|
||||||
|
|
18
util_test.go
18
util_test.go
|
@ -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
235
viper.go
|
@ -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)
|
||||||
|
|
|
@ -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
|
|
||||||
}
|
|
300
viper_test.go
300
viper_test.go
|
@ -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,
|
||||||
},
|
},
|
||||||
|
|
1
watch.go
1
watch.go
|
@ -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
|
||||||
|
|
||||||
|
|
|
@ -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
|
||||||
|
|
||||||
|
|
Loading…
Add table
Reference in a new issue