mirror of
https://github.com/zeromicro/go-zero.git
synced 2026-05-28 09:05:29 +08:00
Compare commits
96 Commits
tools/goct
...
v1.4.3
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
7a75dce465 | ||
|
|
801f1adf71 | ||
|
|
f76b976262 | ||
|
|
a49f9060c2 | ||
|
|
ebe28882eb | ||
|
|
fdc57d07d7 | ||
|
|
ef22042f4d | ||
|
|
944193ce25 | ||
|
|
dcfc9b79f1 | ||
|
|
b7052854bb | ||
|
|
4729a16142 | ||
|
|
3604659027 | ||
|
|
9f7f94b673 | ||
|
|
0b3629b636 | ||
|
|
a644ec7edd | ||
|
|
9941055eaa | ||
|
|
10fd9131a1 | ||
|
|
90828a0d4a | ||
|
|
b1c3c21c81 | ||
|
|
97a8b3ade5 | ||
|
|
95a5f64493 | ||
|
|
20e659749a | ||
|
|
94708cc78f | ||
|
|
06fafd2153 | ||
|
|
79de932646 | ||
|
|
b562e940e7 | ||
|
|
69068cdaf0 | ||
|
|
f25788ebea | ||
|
|
1293c4321b | ||
|
|
e3e08a7396 | ||
|
|
4b071f4c33 | ||
|
|
81831b60a9 | ||
|
|
1677a4dceb | ||
|
|
dac3600b53 | ||
|
|
3db64c7d47 | ||
|
|
7eb6aae949 | ||
|
|
07128213d6 | ||
|
|
9504d30049 | ||
|
|
ce73b9a85c | ||
|
|
4d2a146733 | ||
|
|
46e236fef7 | ||
|
|
06e4914e41 | ||
|
|
9cadab2684 | ||
|
|
7fe2492009 | ||
|
|
22bdf0bbd5 | ||
|
|
c92a2d1b77 | ||
|
|
b21162d638 | ||
|
|
7c9ef3ca67 | ||
|
|
bbadbe0175 | ||
|
|
f9beab1095 | ||
|
|
de5c59aad3 | ||
|
|
36d3765c5c | ||
|
|
d326e6f813 | ||
|
|
ea52fe2e0d | ||
|
|
05a5de7c6d | ||
|
|
d4c9fd2aff | ||
|
|
776673d57d | ||
|
|
1b87f5e30d | ||
|
|
bc47959384 | ||
|
|
9f6d926455 | ||
|
|
f7a4e3a19e | ||
|
|
a515a3c735 | ||
|
|
6f6f1ae21f | ||
|
|
10f94ffcc2 | ||
|
|
f068062b13 | ||
|
|
799c118d95 | ||
|
|
74cc6b55e8 | ||
|
|
fc59aec2e7 | ||
|
|
7868667b4f | ||
|
|
773b59106b | ||
|
|
97f8667b71 | ||
|
|
b51339b69b | ||
|
|
38a73d7fbe | ||
|
|
e50689beed | ||
|
|
1bc138bd34 | ||
|
|
4b9066eda6 | ||
|
|
0c66e041b5 | ||
|
|
aa2be0163a | ||
|
|
ada2941e87 | ||
|
|
59c0013cd1 | ||
|
|
05737f6519 | ||
|
|
4f6a900fd4 | ||
|
|
63cfe60f1a | ||
|
|
e7acadb15d | ||
|
|
111e626a73 | ||
|
|
1a6d7b3ef6 | ||
|
|
2e1e4f3574 | ||
|
|
22d0a2120a | ||
|
|
68e15360c2 | ||
|
|
1b344a8851 | ||
|
|
d640544a40 | ||
|
|
e6aa6fc361 | ||
|
|
4c927624b0 | ||
|
|
0ea92b7280 | ||
|
|
2cde970c9e | ||
|
|
5061158bd6 |
29
.github/workflows/go.yml
vendored
29
.github/workflows/go.yml
vendored
@@ -11,15 +11,17 @@ jobs:
|
|||||||
name: Linux
|
name: Linux
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
steps:
|
steps:
|
||||||
- name: Set up Go 1.x
|
|
||||||
uses: actions/setup-go@v2
|
|
||||||
with:
|
|
||||||
go-version: ^1.16
|
|
||||||
id: go
|
|
||||||
|
|
||||||
- name: Check out code into the Go module directory
|
- name: Check out code into the Go module directory
|
||||||
uses: actions/checkout@v3
|
uses: actions/checkout@v3
|
||||||
|
|
||||||
|
- name: Set up Go 1.x
|
||||||
|
uses: actions/setup-go@v3
|
||||||
|
with:
|
||||||
|
go-version: ^1.16
|
||||||
|
check-latest: true
|
||||||
|
cache: true
|
||||||
|
id: go
|
||||||
|
|
||||||
- name: Get dependencies
|
- name: Get dependencies
|
||||||
run: |
|
run: |
|
||||||
go get -v -t -d ./...
|
go get -v -t -d ./...
|
||||||
@@ -34,20 +36,23 @@ jobs:
|
|||||||
run: go test -race -coverprofile=coverage.txt -covermode=atomic ./...
|
run: go test -race -coverprofile=coverage.txt -covermode=atomic ./...
|
||||||
|
|
||||||
- name: Codecov
|
- name: Codecov
|
||||||
uses: codecov/codecov-action@v2
|
uses: codecov/codecov-action@v3
|
||||||
|
|
||||||
test-win:
|
test-win:
|
||||||
name: Windows
|
name: Windows
|
||||||
runs-on: windows-latest
|
runs-on: windows-latest
|
||||||
steps:
|
steps:
|
||||||
- name: Set up Go 1.x
|
|
||||||
uses: actions/setup-go@v2
|
|
||||||
with:
|
|
||||||
go-version: ^1.16
|
|
||||||
|
|
||||||
- name: Checkout codebase
|
- name: Checkout codebase
|
||||||
uses: actions/checkout@v3
|
uses: actions/checkout@v3
|
||||||
|
|
||||||
|
- name: Set up Go 1.x
|
||||||
|
uses: actions/setup-go@v3
|
||||||
|
with:
|
||||||
|
# use 1.16 to guarantee Go 1.16 compatibility
|
||||||
|
go-version: 1.16
|
||||||
|
check-latest: true
|
||||||
|
cache: true
|
||||||
|
|
||||||
- name: Test
|
- name: Test
|
||||||
run: |
|
run: |
|
||||||
go mod verify
|
go mod verify
|
||||||
|
|||||||
2
.github/workflows/issue-translator.yml
vendored
2
.github/workflows/issue-translator.yml
vendored
@@ -9,7 +9,7 @@ jobs:
|
|||||||
build:
|
build:
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
steps:
|
steps:
|
||||||
- uses: tomsun28/issues-translate-action@v2.6
|
- uses: usthe/issues-translate-action@v2.7
|
||||||
with:
|
with:
|
||||||
IS_MODIFY_TITLE: true
|
IS_MODIFY_TITLE: true
|
||||||
# not require, default false, . Decide whether to modify the issue title
|
# not require, default false, . Decide whether to modify the issue title
|
||||||
|
|||||||
2
.github/workflows/issues.yml
vendored
2
.github/workflows/issues.yml
vendored
@@ -7,7 +7,7 @@ jobs:
|
|||||||
close-issues:
|
close-issues:
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/stale@v3
|
- uses: actions/stale@v6
|
||||||
with:
|
with:
|
||||||
days-before-issue-stale: 365
|
days-before-issue-stale: 365
|
||||||
days-before-issue-close: 90
|
days-before-issue-close: 90
|
||||||
|
|||||||
1
.gitignore
vendored
1
.gitignore
vendored
@@ -22,6 +22,7 @@ go.work.sum
|
|||||||
|
|
||||||
# gitlab ci
|
# gitlab ci
|
||||||
.cache
|
.cache
|
||||||
|
.golangci.yml
|
||||||
|
|
||||||
# vim auto backup file
|
# vim auto backup file
|
||||||
*~
|
*~
|
||||||
|
|||||||
@@ -20,16 +20,16 @@ func (b noOpBreaker) Do(req func() error) error {
|
|||||||
return req()
|
return req()
|
||||||
}
|
}
|
||||||
|
|
||||||
func (b noOpBreaker) DoWithAcceptable(req func() error, acceptable Acceptable) error {
|
func (b noOpBreaker) DoWithAcceptable(req func() error, _ Acceptable) error {
|
||||||
return req()
|
return req()
|
||||||
}
|
}
|
||||||
|
|
||||||
func (b noOpBreaker) DoWithFallback(req func() error, fallback func(err error) error) error {
|
func (b noOpBreaker) DoWithFallback(req func() error, _ func(err error) error) error {
|
||||||
return req()
|
return req()
|
||||||
}
|
}
|
||||||
|
|
||||||
func (b noOpBreaker) DoWithFallbackAcceptable(req func() error, fallback func(err error) error,
|
func (b noOpBreaker) DoWithFallbackAcceptable(req func() error, _ func(err error) error,
|
||||||
acceptable Acceptable) error {
|
_ Acceptable) error {
|
||||||
return req()
|
return req()
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -38,5 +38,5 @@ type nopPromise struct{}
|
|||||||
func (p nopPromise) Accept() {
|
func (p nopPromise) Accept() {
|
||||||
}
|
}
|
||||||
|
|
||||||
func (p nopPromise) Reject(reason string) {
|
func (p nopPromise) Reject(_ string) {
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -29,7 +29,7 @@ func NewSet() *Set {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewUnmanagedSet returns a unmanaged Set, which can put values with different types.
|
// NewUnmanagedSet returns an unmanaged Set, which can put values with different types.
|
||||||
func NewUnmanagedSet() *Set {
|
func NewUnmanagedSet() *Set {
|
||||||
return &Set{
|
return &Set{
|
||||||
data: make(map[interface{}]lang.PlaceholderType),
|
data: make(map[interface{}]lang.PlaceholderType),
|
||||||
|
|||||||
@@ -7,9 +7,13 @@ import (
|
|||||||
"path"
|
"path"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
|
"github.com/zeromicro/go-zero/core/jsonx"
|
||||||
"github.com/zeromicro/go-zero/core/mapping"
|
"github.com/zeromicro/go-zero/core/mapping"
|
||||||
|
"github.com/zeromicro/go-zero/internal/encoding"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
const distanceBetweenUpperAndLower = 32
|
||||||
|
|
||||||
var loaders = map[string]func([]byte, interface{}) error{
|
var loaders = map[string]func([]byte, interface{}) error{
|
||||||
".json": LoadFromJsonBytes,
|
".json": LoadFromJsonBytes,
|
||||||
".toml": LoadFromTomlBytes,
|
".toml": LoadFromTomlBytes,
|
||||||
@@ -49,7 +53,12 @@ func LoadConfig(file string, v interface{}, opts ...Option) error {
|
|||||||
|
|
||||||
// LoadFromJsonBytes loads config into v from content json bytes.
|
// LoadFromJsonBytes loads config into v from content json bytes.
|
||||||
func LoadFromJsonBytes(content []byte, v interface{}) error {
|
func LoadFromJsonBytes(content []byte, v interface{}) error {
|
||||||
return mapping.UnmarshalJsonBytes(content, v)
|
var m map[string]interface{}
|
||||||
|
if err := jsonx.Unmarshal(content, &m); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
return mapping.UnmarshalJsonMap(toCamelCaseKeyMap(m), v, mapping.WithCanonicalKeyFunc(toCamelCase))
|
||||||
}
|
}
|
||||||
|
|
||||||
// LoadConfigFromJsonBytes loads config into v from content json bytes.
|
// LoadConfigFromJsonBytes loads config into v from content json bytes.
|
||||||
@@ -60,12 +69,22 @@ func LoadConfigFromJsonBytes(content []byte, v interface{}) error {
|
|||||||
|
|
||||||
// LoadFromTomlBytes loads config into v from content toml bytes.
|
// LoadFromTomlBytes loads config into v from content toml bytes.
|
||||||
func LoadFromTomlBytes(content []byte, v interface{}) error {
|
func LoadFromTomlBytes(content []byte, v interface{}) error {
|
||||||
return mapping.UnmarshalTomlBytes(content, v)
|
b, err := encoding.TomlToJson(content)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
return LoadFromJsonBytes(b, v)
|
||||||
}
|
}
|
||||||
|
|
||||||
// LoadFromYamlBytes loads config into v from content yaml bytes.
|
// LoadFromYamlBytes loads config into v from content yaml bytes.
|
||||||
func LoadFromYamlBytes(content []byte, v interface{}) error {
|
func LoadFromYamlBytes(content []byte, v interface{}) error {
|
||||||
return mapping.UnmarshalYamlBytes(content, v)
|
b, err := encoding.YamlToJson(content)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
return LoadFromJsonBytes(b, v)
|
||||||
}
|
}
|
||||||
|
|
||||||
// LoadConfigFromYamlBytes loads config into v from content yaml bytes.
|
// LoadConfigFromYamlBytes loads config into v from content yaml bytes.
|
||||||
@@ -80,3 +99,66 @@ func MustLoad(path string, v interface{}, opts ...Option) {
|
|||||||
log.Fatalf("error: config file %s, %s", path, err.Error())
|
log.Fatalf("error: config file %s, %s", path, err.Error())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func toCamelCase(s string) string {
|
||||||
|
var buf strings.Builder
|
||||||
|
buf.Grow(len(s))
|
||||||
|
var capNext bool
|
||||||
|
boundary := true
|
||||||
|
for _, v := range s {
|
||||||
|
isCap := v >= 'A' && v <= 'Z'
|
||||||
|
isLow := v >= 'a' && v <= 'z'
|
||||||
|
if boundary && (isCap || isLow) {
|
||||||
|
if capNext {
|
||||||
|
if isLow {
|
||||||
|
v -= distanceBetweenUpperAndLower
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if isCap {
|
||||||
|
v += distanceBetweenUpperAndLower
|
||||||
|
}
|
||||||
|
}
|
||||||
|
boundary = false
|
||||||
|
}
|
||||||
|
if isCap || isLow {
|
||||||
|
buf.WriteRune(v)
|
||||||
|
capNext = false
|
||||||
|
} else if v == ' ' || v == '\t' {
|
||||||
|
buf.WriteRune(v)
|
||||||
|
capNext = false
|
||||||
|
boundary = true
|
||||||
|
} else if v == '_' {
|
||||||
|
capNext = true
|
||||||
|
boundary = true
|
||||||
|
} else {
|
||||||
|
buf.WriteRune(v)
|
||||||
|
capNext = true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return buf.String()
|
||||||
|
}
|
||||||
|
|
||||||
|
func toCamelCaseInterface(v interface{}) interface{} {
|
||||||
|
switch vv := v.(type) {
|
||||||
|
case map[string]interface{}:
|
||||||
|
return toCamelCaseKeyMap(vv)
|
||||||
|
case []interface{}:
|
||||||
|
var arr []interface{}
|
||||||
|
for _, vvv := range vv {
|
||||||
|
arr = append(arr, toCamelCaseInterface(vvv))
|
||||||
|
}
|
||||||
|
return arr
|
||||||
|
default:
|
||||||
|
return v
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func toCamelCaseKeyMap(m map[string]interface{}) map[string]interface{} {
|
||||||
|
res := make(map[string]interface{})
|
||||||
|
for k, v := range m {
|
||||||
|
res[toCamelCase(k)] = toCamelCaseInterface(v)
|
||||||
|
}
|
||||||
|
|
||||||
|
return res
|
||||||
|
}
|
||||||
|
|||||||
@@ -56,6 +56,22 @@ func TestConfigJson(t *testing.T) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestLoadFromJsonBytesArray(t *testing.T) {
|
||||||
|
input := []byte(`{"users": [{"name": "foo"}, {"Name": "bar"}]}`)
|
||||||
|
var val struct {
|
||||||
|
Users []struct {
|
||||||
|
Name string
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
assert.NoError(t, LoadFromJsonBytes(input, &val))
|
||||||
|
var expect []string
|
||||||
|
for _, user := range val.Users {
|
||||||
|
expect = append(expect, user.Name)
|
||||||
|
}
|
||||||
|
assert.EqualValues(t, []string{"foo", "bar"}, expect)
|
||||||
|
}
|
||||||
|
|
||||||
func TestConfigToml(t *testing.T) {
|
func TestConfigToml(t *testing.T) {
|
||||||
text := `a = "foo"
|
text := `a = "foo"
|
||||||
b = 1
|
b = 1
|
||||||
@@ -81,6 +97,65 @@ d = "abcd!@#$112"
|
|||||||
assert.Equal(t, "abcd!@#$112", val.D)
|
assert.Equal(t, "abcd!@#$112", val.D)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestConfigJsonCanonical(t *testing.T) {
|
||||||
|
text := []byte(`{"a": "foo", "B": "bar"}`)
|
||||||
|
|
||||||
|
var val1 struct {
|
||||||
|
A string `json:"a"`
|
||||||
|
B string `json:"b"`
|
||||||
|
}
|
||||||
|
var val2 struct {
|
||||||
|
A string
|
||||||
|
B string
|
||||||
|
}
|
||||||
|
assert.NoError(t, LoadFromJsonBytes(text, &val1))
|
||||||
|
assert.Equal(t, "foo", val1.A)
|
||||||
|
assert.Equal(t, "bar", val1.B)
|
||||||
|
assert.NoError(t, LoadFromJsonBytes(text, &val2))
|
||||||
|
assert.Equal(t, "foo", val2.A)
|
||||||
|
assert.Equal(t, "bar", val2.B)
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestConfigTomlCanonical(t *testing.T) {
|
||||||
|
text := []byte(`a = "foo"
|
||||||
|
B = "bar"`)
|
||||||
|
|
||||||
|
var val1 struct {
|
||||||
|
A string `json:"a"`
|
||||||
|
B string `json:"b"`
|
||||||
|
}
|
||||||
|
var val2 struct {
|
||||||
|
A string
|
||||||
|
B string
|
||||||
|
}
|
||||||
|
assert.NoError(t, LoadFromTomlBytes(text, &val1))
|
||||||
|
assert.Equal(t, "foo", val1.A)
|
||||||
|
assert.Equal(t, "bar", val1.B)
|
||||||
|
assert.NoError(t, LoadFromTomlBytes(text, &val2))
|
||||||
|
assert.Equal(t, "foo", val2.A)
|
||||||
|
assert.Equal(t, "bar", val2.B)
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestConfigYamlCanonical(t *testing.T) {
|
||||||
|
text := []byte(`a: foo
|
||||||
|
B: bar`)
|
||||||
|
|
||||||
|
var val1 struct {
|
||||||
|
A string `json:"a"`
|
||||||
|
B string `json:"b"`
|
||||||
|
}
|
||||||
|
var val2 struct {
|
||||||
|
A string
|
||||||
|
B string
|
||||||
|
}
|
||||||
|
assert.NoError(t, LoadFromYamlBytes(text, &val1))
|
||||||
|
assert.Equal(t, "foo", val1.A)
|
||||||
|
assert.Equal(t, "bar", val1.B)
|
||||||
|
assert.NoError(t, LoadFromYamlBytes(text, &val2))
|
||||||
|
assert.Equal(t, "foo", val2.A)
|
||||||
|
assert.Equal(t, "bar", val2.B)
|
||||||
|
}
|
||||||
|
|
||||||
func TestConfigTomlEnv(t *testing.T) {
|
func TestConfigTomlEnv(t *testing.T) {
|
||||||
text := `a = "foo"
|
text := `a = "foo"
|
||||||
b = 1
|
b = 1
|
||||||
@@ -105,7 +180,6 @@ d = "abcd!@#112"
|
|||||||
assert.Equal(t, 1, val.B)
|
assert.Equal(t, 1, val.B)
|
||||||
assert.Equal(t, "2", val.C)
|
assert.Equal(t, "2", val.C)
|
||||||
assert.Equal(t, "abcd!@#112", val.D)
|
assert.Equal(t, "abcd!@#112", val.D)
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestConfigJsonEnv(t *testing.T) {
|
func TestConfigJsonEnv(t *testing.T) {
|
||||||
@@ -144,6 +218,116 @@ func TestConfigJsonEnv(t *testing.T) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestToCamelCase(t *testing.T) {
|
||||||
|
tests := []struct {
|
||||||
|
input string
|
||||||
|
expect string
|
||||||
|
}{
|
||||||
|
{
|
||||||
|
input: "",
|
||||||
|
expect: "",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
input: "A",
|
||||||
|
expect: "a",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
input: "a",
|
||||||
|
expect: "a",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
input: "hello_world",
|
||||||
|
expect: "helloWorld",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
input: "Hello_world",
|
||||||
|
expect: "helloWorld",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
input: "hello_World",
|
||||||
|
expect: "helloWorld",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
input: "helloWorld",
|
||||||
|
expect: "helloWorld",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
input: "HelloWorld",
|
||||||
|
expect: "helloWorld",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
input: "hello World",
|
||||||
|
expect: "hello world",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
input: "Hello World",
|
||||||
|
expect: "hello world",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
input: "Hello World",
|
||||||
|
expect: "hello world",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
input: "Hello World foo_bar",
|
||||||
|
expect: "hello world fooBar",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
input: "Hello World foo_Bar",
|
||||||
|
expect: "hello world fooBar",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
input: "Hello World Foo_bar",
|
||||||
|
expect: "hello world fooBar",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
input: "Hello World Foo_Bar",
|
||||||
|
expect: "hello world fooBar",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
input: "你好 World Foo_Bar",
|
||||||
|
expect: "你好 world fooBar",
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, test := range tests {
|
||||||
|
test := test
|
||||||
|
t.Run(test.input, func(t *testing.T) {
|
||||||
|
assert.Equal(t, test.expect, toCamelCase(test.input))
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestLoadFromJsonBytesError(t *testing.T) {
|
||||||
|
var val struct{}
|
||||||
|
assert.Error(t, LoadFromJsonBytes([]byte(`hello`), &val))
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestLoadFromTomlBytesError(t *testing.T) {
|
||||||
|
var val struct{}
|
||||||
|
assert.Error(t, LoadFromTomlBytes([]byte(`hello`), &val))
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestLoadFromYamlBytesError(t *testing.T) {
|
||||||
|
var val struct{}
|
||||||
|
assert.Error(t, LoadFromYamlBytes([]byte(`':hello`), &val))
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestLoadFromYamlBytes(t *testing.T) {
|
||||||
|
input := []byte(`layer1:
|
||||||
|
layer2:
|
||||||
|
layer3: foo`)
|
||||||
|
var val struct {
|
||||||
|
Layer1 struct {
|
||||||
|
Layer2 struct {
|
||||||
|
Layer3 string
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
assert.NoError(t, LoadFromYamlBytes(input, &val))
|
||||||
|
assert.Equal(t, "foo", val.Layer1.Layer2.Layer3)
|
||||||
|
}
|
||||||
|
|
||||||
func createTempFile(ext, text string) (string, error) {
|
func createTempFile(ext, text string) (string, error) {
|
||||||
tmpfile, err := os.CreateTemp(os.TempDir(), hash.Md5Hex([]byte(text))+"*"+ext)
|
tmpfile, err := os.CreateTemp(os.TempDir(), hash.Md5Hex([]byte(text))+"*"+ext)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|||||||
@@ -297,7 +297,8 @@ func (c *cluster) watch(cli EtcdClient, key string, rev int64) {
|
|||||||
func (c *cluster) watchStream(cli EtcdClient, key string, rev int64) bool {
|
func (c *cluster) watchStream(cli EtcdClient, key string, rev int64) bool {
|
||||||
var rch clientv3.WatchChan
|
var rch clientv3.WatchChan
|
||||||
if rev != 0 {
|
if rev != 0 {
|
||||||
rch = cli.Watch(clientv3.WithRequireLeader(c.context(cli)), makeKeyPrefix(key), clientv3.WithPrefix(), clientv3.WithRev(rev+1))
|
rch = cli.Watch(clientv3.WithRequireLeader(c.context(cli)), makeKeyPrefix(key), clientv3.WithPrefix(),
|
||||||
|
clientv3.WithRev(rev+1))
|
||||||
} else {
|
} else {
|
||||||
rch = cli.Watch(clientv3.WithRequireLeader(c.context(cli)), makeKeyPrefix(key), clientv3.WithPrefix())
|
rch = cli.Watch(clientv3.WithRequireLeader(c.context(cli)), makeKeyPrefix(key), clientv3.WithPrefix())
|
||||||
}
|
}
|
||||||
@@ -342,6 +343,7 @@ func DialClient(endpoints []string) (EtcdClient, error) {
|
|||||||
DialKeepAliveTime: dialKeepAliveTime,
|
DialKeepAliveTime: dialKeepAliveTime,
|
||||||
DialKeepAliveTimeout: DialTimeout,
|
DialKeepAliveTimeout: DialTimeout,
|
||||||
RejectOldCluster: true,
|
RejectOldCluster: true,
|
||||||
|
PermitWithoutStream: true,
|
||||||
}
|
}
|
||||||
if account, ok := GetAccount(endpoints); ok {
|
if account, ok := GetAccount(endpoints); ok {
|
||||||
cfg.Username = account.User
|
cfg.Username = account.User
|
||||||
|
|||||||
@@ -2,7 +2,6 @@ package internal
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
"go.etcd.io/etcd/api/v3/etcdserverpb"
|
|
||||||
"sync"
|
"sync"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
@@ -12,6 +11,7 @@ import (
|
|||||||
"github.com/zeromicro/go-zero/core/lang"
|
"github.com/zeromicro/go-zero/core/lang"
|
||||||
"github.com/zeromicro/go-zero/core/logx"
|
"github.com/zeromicro/go-zero/core/logx"
|
||||||
"github.com/zeromicro/go-zero/core/stringx"
|
"github.com/zeromicro/go-zero/core/stringx"
|
||||||
|
"go.etcd.io/etcd/api/v3/etcdserverpb"
|
||||||
"go.etcd.io/etcd/api/v3/mvccpb"
|
"go.etcd.io/etcd/api/v3/mvccpb"
|
||||||
clientv3 "go.etcd.io/etcd/client/v3"
|
clientv3 "go.etcd.io/etcd/client/v3"
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -13,7 +13,7 @@ type (
|
|||||||
// SubOption defines the method to customize a Subscriber.
|
// SubOption defines the method to customize a Subscriber.
|
||||||
SubOption func(sub *Subscriber)
|
SubOption func(sub *Subscriber)
|
||||||
|
|
||||||
// A Subscriber is used to subscribe the given key on a etcd cluster.
|
// A Subscriber is used to subscribe the given key on an etcd cluster.
|
||||||
Subscriber struct {
|
Subscriber struct {
|
||||||
endpoints []string
|
endpoints []string
|
||||||
exclusive bool
|
exclusive bool
|
||||||
|
|||||||
15
core/fs/files_test.go
Normal file
15
core/fs/files_test.go
Normal file
@@ -0,0 +1,15 @@
|
|||||||
|
package fs
|
||||||
|
|
||||||
|
import (
|
||||||
|
"os"
|
||||||
|
"testing"
|
||||||
|
|
||||||
|
"github.com/stretchr/testify/assert"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestCloseOnExec(t *testing.T) {
|
||||||
|
file := os.NewFile(0, os.DevNull)
|
||||||
|
assert.NotPanics(t, func() {
|
||||||
|
CloseOnExec(file)
|
||||||
|
})
|
||||||
|
}
|
||||||
@@ -328,7 +328,7 @@ func (s Stream) Parallel(fn ParallelFunc, opts ...Option) {
|
|||||||
}, opts...).Done()
|
}, opts...).Done()
|
||||||
}
|
}
|
||||||
|
|
||||||
// Reduce is a utility method to let the caller deal with the underlying channel.
|
// Reduce is an utility method to let the caller deal with the underlying channel.
|
||||||
func (s Stream) Reduce(fn ReduceFunc) (interface{}, error) {
|
func (s Stream) Reduce(fn ReduceFunc) (interface{}, error) {
|
||||||
return fn(s.source)
|
return fn(s.source)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -7,7 +7,6 @@ import (
|
|||||||
"sync"
|
"sync"
|
||||||
|
|
||||||
"github.com/zeromicro/go-zero/core/lang"
|
"github.com/zeromicro/go-zero/core/lang"
|
||||||
"github.com/zeromicro/go-zero/core/mapping"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
@@ -183,5 +182,5 @@ func innerRepr(node interface{}) string {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func repr(node interface{}) string {
|
func repr(node interface{}) string {
|
||||||
return mapping.Repr(node)
|
return lang.Repr(node)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -10,7 +10,7 @@ func (nopCloser) Close() error {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// NopCloser returns a io.WriteCloser that does nothing on calling Close.
|
// NopCloser returns an io.WriteCloser that does nothing on calling Close.
|
||||||
func NopCloser(w io.Writer) io.WriteCloser {
|
func NopCloser(w io.Writer) io.WriteCloser {
|
||||||
return nopCloser{w}
|
return nopCloser{w}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,5 +1,11 @@
|
|||||||
package lang
|
package lang
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"reflect"
|
||||||
|
"strconv"
|
||||||
|
)
|
||||||
|
|
||||||
// Placeholder is a placeholder object that can be used globally.
|
// Placeholder is a placeholder object that can be used globally.
|
||||||
var Placeholder PlaceholderType
|
var Placeholder PlaceholderType
|
||||||
|
|
||||||
@@ -9,3 +15,64 @@ type (
|
|||||||
// PlaceholderType represents a placeholder type.
|
// PlaceholderType represents a placeholder type.
|
||||||
PlaceholderType = struct{}
|
PlaceholderType = struct{}
|
||||||
)
|
)
|
||||||
|
|
||||||
|
// Repr returns the string representation of v.
|
||||||
|
func Repr(v interface{}) string {
|
||||||
|
if v == nil {
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
|
||||||
|
// if func (v *Type) String() string, we can't use Elem()
|
||||||
|
switch vt := v.(type) {
|
||||||
|
case fmt.Stringer:
|
||||||
|
return vt.String()
|
||||||
|
}
|
||||||
|
|
||||||
|
val := reflect.ValueOf(v)
|
||||||
|
if val.Kind() == reflect.Ptr && !val.IsNil() {
|
||||||
|
val = val.Elem()
|
||||||
|
}
|
||||||
|
|
||||||
|
return reprOfValue(val)
|
||||||
|
}
|
||||||
|
|
||||||
|
func reprOfValue(val reflect.Value) string {
|
||||||
|
switch vt := val.Interface().(type) {
|
||||||
|
case bool:
|
||||||
|
return strconv.FormatBool(vt)
|
||||||
|
case error:
|
||||||
|
return vt.Error()
|
||||||
|
case float32:
|
||||||
|
return strconv.FormatFloat(float64(vt), 'f', -1, 32)
|
||||||
|
case float64:
|
||||||
|
return strconv.FormatFloat(vt, 'f', -1, 64)
|
||||||
|
case fmt.Stringer:
|
||||||
|
return vt.String()
|
||||||
|
case int:
|
||||||
|
return strconv.Itoa(vt)
|
||||||
|
case int8:
|
||||||
|
return strconv.Itoa(int(vt))
|
||||||
|
case int16:
|
||||||
|
return strconv.Itoa(int(vt))
|
||||||
|
case int32:
|
||||||
|
return strconv.Itoa(int(vt))
|
||||||
|
case int64:
|
||||||
|
return strconv.FormatInt(vt, 10)
|
||||||
|
case string:
|
||||||
|
return vt
|
||||||
|
case uint:
|
||||||
|
return strconv.FormatUint(uint64(vt), 10)
|
||||||
|
case uint8:
|
||||||
|
return strconv.FormatUint(uint64(vt), 10)
|
||||||
|
case uint16:
|
||||||
|
return strconv.FormatUint(uint64(vt), 10)
|
||||||
|
case uint32:
|
||||||
|
return strconv.FormatUint(uint64(vt), 10)
|
||||||
|
case uint64:
|
||||||
|
return strconv.FormatUint(vt, 10)
|
||||||
|
case []byte:
|
||||||
|
return string(vt)
|
||||||
|
default:
|
||||||
|
return fmt.Sprint(val.Interface())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
131
core/lang/lang_test.go
Normal file
131
core/lang/lang_test.go
Normal file
@@ -0,0 +1,131 @@
|
|||||||
|
package lang
|
||||||
|
|
||||||
|
import (
|
||||||
|
"testing"
|
||||||
|
|
||||||
|
"github.com/stretchr/testify/assert"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestRepr(t *testing.T) {
|
||||||
|
var (
|
||||||
|
f32 float32 = 1.1
|
||||||
|
f64 = 2.2
|
||||||
|
i8 int8 = 1
|
||||||
|
i16 int16 = 2
|
||||||
|
i32 int32 = 3
|
||||||
|
i64 int64 = 4
|
||||||
|
u8 uint8 = 5
|
||||||
|
u16 uint16 = 6
|
||||||
|
u32 uint32 = 7
|
||||||
|
u64 uint64 = 8
|
||||||
|
)
|
||||||
|
tests := []struct {
|
||||||
|
v interface{}
|
||||||
|
expect string
|
||||||
|
}{
|
||||||
|
{
|
||||||
|
nil,
|
||||||
|
"",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
mockStringable{},
|
||||||
|
"mocked",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
new(mockStringable),
|
||||||
|
"mocked",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
newMockPtr(),
|
||||||
|
"mockptr",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
&mockOpacity{
|
||||||
|
val: 1,
|
||||||
|
},
|
||||||
|
"{1}",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
true,
|
||||||
|
"true",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
false,
|
||||||
|
"false",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
f32,
|
||||||
|
"1.1",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
f64,
|
||||||
|
"2.2",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
i8,
|
||||||
|
"1",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
i16,
|
||||||
|
"2",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
i32,
|
||||||
|
"3",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
i64,
|
||||||
|
"4",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
u8,
|
||||||
|
"5",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
u16,
|
||||||
|
"6",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
u32,
|
||||||
|
"7",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
u64,
|
||||||
|
"8",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
[]byte(`abcd`),
|
||||||
|
"abcd",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
mockOpacity{val: 1},
|
||||||
|
"{1}",
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, test := range tests {
|
||||||
|
t.Run(test.expect, func(t *testing.T) {
|
||||||
|
assert.Equal(t, test.expect, Repr(test.v))
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
type mockStringable struct{}
|
||||||
|
|
||||||
|
func (m mockStringable) String() string {
|
||||||
|
return "mocked"
|
||||||
|
}
|
||||||
|
|
||||||
|
type mockPtr struct{}
|
||||||
|
|
||||||
|
func newMockPtr() *mockPtr {
|
||||||
|
return new(mockPtr)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (m *mockPtr) String() string {
|
||||||
|
return "mockptr"
|
||||||
|
}
|
||||||
|
|
||||||
|
type mockOpacity struct {
|
||||||
|
val int
|
||||||
|
}
|
||||||
@@ -1,6 +1,8 @@
|
|||||||
package limit
|
package limit
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"context"
|
||||||
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
"strconv"
|
"strconv"
|
||||||
"sync"
|
"sync"
|
||||||
@@ -58,8 +60,8 @@ type TokenLimiter struct {
|
|||||||
timestampKey string
|
timestampKey string
|
||||||
rescueLock sync.Mutex
|
rescueLock sync.Mutex
|
||||||
redisAlive uint32
|
redisAlive uint32
|
||||||
rescueLimiter *xrate.Limiter
|
|
||||||
monitorStarted bool
|
monitorStarted bool
|
||||||
|
rescueLimiter *xrate.Limiter
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewTokenLimiter returns a new TokenLimiter that allows events up to rate and permits
|
// NewTokenLimiter returns a new TokenLimiter that allows events up to rate and permits
|
||||||
@@ -84,19 +86,31 @@ func (lim *TokenLimiter) Allow() bool {
|
|||||||
return lim.AllowN(time.Now(), 1)
|
return lim.AllowN(time.Now(), 1)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// AllowCtx is shorthand for AllowNCtx(ctx,time.Now(), 1) with incoming context.
|
||||||
|
func (lim *TokenLimiter) AllowCtx(ctx context.Context) bool {
|
||||||
|
return lim.AllowNCtx(ctx, time.Now(), 1)
|
||||||
|
}
|
||||||
|
|
||||||
// AllowN reports whether n events may happen at time now.
|
// AllowN reports whether n events may happen at time now.
|
||||||
// Use this method if you intend to drop / skip events that exceed the rate.
|
// Use this method if you intend to drop / skip events that exceed the rate.
|
||||||
// Otherwise, use Reserve or Wait.
|
// Otherwise, use Reserve or Wait.
|
||||||
func (lim *TokenLimiter) AllowN(now time.Time, n int) bool {
|
func (lim *TokenLimiter) AllowN(now time.Time, n int) bool {
|
||||||
return lim.reserveN(now, n)
|
return lim.reserveN(context.Background(), now, n)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (lim *TokenLimiter) reserveN(now time.Time, n int) bool {
|
// AllowNCtx reports whether n events may happen at time now with incoming context.
|
||||||
|
// Use this method if you intend to drop / skip events that exceed the rate.
|
||||||
|
// Otherwise, use Reserve or Wait.
|
||||||
|
func (lim *TokenLimiter) AllowNCtx(ctx context.Context, now time.Time, n int) bool {
|
||||||
|
return lim.reserveN(ctx, now, n)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (lim *TokenLimiter) reserveN(ctx context.Context, now time.Time, n int) bool {
|
||||||
if atomic.LoadUint32(&lim.redisAlive) == 0 {
|
if atomic.LoadUint32(&lim.redisAlive) == 0 {
|
||||||
return lim.rescueLimiter.AllowN(now, n)
|
return lim.rescueLimiter.AllowN(now, n)
|
||||||
}
|
}
|
||||||
|
|
||||||
resp, err := lim.store.Eval(
|
resp, err := lim.store.EvalCtx(ctx,
|
||||||
script,
|
script,
|
||||||
[]string{
|
[]string{
|
||||||
lim.tokenKey,
|
lim.tokenKey,
|
||||||
@@ -113,6 +127,10 @@ func (lim *TokenLimiter) reserveN(now time.Time, n int) bool {
|
|||||||
if err == redis.Nil {
|
if err == redis.Nil {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
if errors.Is(err, context.DeadlineExceeded) || errors.Is(err, context.Canceled) {
|
||||||
|
logx.Errorf("fail to use rate limiter: %s", err)
|
||||||
|
return false
|
||||||
|
}
|
||||||
if err != nil {
|
if err != nil {
|
||||||
logx.Errorf("fail to use rate limiter: %s, use in-process limiter for rescue", err)
|
logx.Errorf("fail to use rate limiter: %s, use in-process limiter for rescue", err)
|
||||||
lim.startMonitor()
|
lim.startMonitor()
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
package limit
|
package limit
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"context"
|
||||||
"testing"
|
"testing"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
@@ -15,6 +16,30 @@ func init() {
|
|||||||
logx.Disable()
|
logx.Disable()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestTokenLimit_WithCtx(t *testing.T) {
|
||||||
|
s, err := miniredis.Run()
|
||||||
|
assert.Nil(t, err)
|
||||||
|
|
||||||
|
const (
|
||||||
|
total = 100
|
||||||
|
rate = 5
|
||||||
|
burst = 10
|
||||||
|
)
|
||||||
|
l := NewTokenLimiter(rate, burst, redis.New(s.Addr()), "tokenlimit")
|
||||||
|
defer s.Close()
|
||||||
|
|
||||||
|
ctx, cancel := context.WithCancel(context.Background())
|
||||||
|
ok := l.AllowCtx(ctx)
|
||||||
|
assert.True(t, ok)
|
||||||
|
|
||||||
|
cancel()
|
||||||
|
for i := 0; i < total; i++ {
|
||||||
|
ok := l.AllowCtx(ctx)
|
||||||
|
assert.False(t, ok)
|
||||||
|
assert.False(t, l.monitorStarted)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
func TestTokenLimit_Rescue(t *testing.T) {
|
func TestTokenLimit_Rescue(t *testing.T) {
|
||||||
s, err := miniredis.Run()
|
s, err := miniredis.Run()
|
||||||
assert.Nil(t, err)
|
assert.Nil(t, err)
|
||||||
|
|||||||
@@ -17,7 +17,7 @@ import (
|
|||||||
const (
|
const (
|
||||||
defaultBuckets = 50
|
defaultBuckets = 50
|
||||||
defaultWindow = time.Second * 5
|
defaultWindow = time.Second * 5
|
||||||
// using 1000m notation, 900m is like 80%, keep it as var for unit test
|
// using 1000m notation, 900m is like 90%, keep it as var for unit test
|
||||||
defaultCpuThreshold = 900
|
defaultCpuThreshold = 900
|
||||||
defaultMinRt = float64(time.Second / time.Millisecond)
|
defaultMinRt = float64(time.Second / time.Millisecond)
|
||||||
// moving average hyperparameter beta for calculating requests on the fly
|
// moving average hyperparameter beta for calculating requests on the fly
|
||||||
@@ -70,7 +70,7 @@ type (
|
|||||||
flying int64
|
flying int64
|
||||||
avgFlying float64
|
avgFlying float64
|
||||||
avgFlyingLock syncx.SpinLock
|
avgFlyingLock syncx.SpinLock
|
||||||
dropTime *syncx.AtomicDuration
|
overloadTime *syncx.AtomicDuration
|
||||||
droppedRecently *syncx.AtomicBool
|
droppedRecently *syncx.AtomicBool
|
||||||
passCounter *collection.RollingWindow
|
passCounter *collection.RollingWindow
|
||||||
rtCounter *collection.RollingWindow
|
rtCounter *collection.RollingWindow
|
||||||
@@ -106,7 +106,7 @@ func NewAdaptiveShedder(opts ...ShedderOption) Shedder {
|
|||||||
return &adaptiveShedder{
|
return &adaptiveShedder{
|
||||||
cpuThreshold: options.cpuThreshold,
|
cpuThreshold: options.cpuThreshold,
|
||||||
windows: int64(time.Second / bucketDuration),
|
windows: int64(time.Second / bucketDuration),
|
||||||
dropTime: syncx.NewAtomicDuration(),
|
overloadTime: syncx.NewAtomicDuration(),
|
||||||
droppedRecently: syncx.NewAtomicBool(),
|
droppedRecently: syncx.NewAtomicBool(),
|
||||||
passCounter: collection.NewRollingWindow(options.buckets, bucketDuration,
|
passCounter: collection.NewRollingWindow(options.buckets, bucketDuration,
|
||||||
collection.IgnoreCurrentBucket()),
|
collection.IgnoreCurrentBucket()),
|
||||||
@@ -118,7 +118,6 @@ func NewAdaptiveShedder(opts ...ShedderOption) Shedder {
|
|||||||
// Allow implements Shedder.Allow.
|
// Allow implements Shedder.Allow.
|
||||||
func (as *adaptiveShedder) Allow() (Promise, error) {
|
func (as *adaptiveShedder) Allow() (Promise, error) {
|
||||||
if as.shouldDrop() {
|
if as.shouldDrop() {
|
||||||
as.dropTime.Set(timex.Now())
|
|
||||||
as.droppedRecently.Set(true)
|
as.droppedRecently.Set(true)
|
||||||
|
|
||||||
return nil, ErrServiceOverloaded
|
return nil, ErrServiceOverloaded
|
||||||
@@ -215,21 +214,26 @@ func (as *adaptiveShedder) stillHot() bool {
|
|||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
dropTime := as.dropTime.Load()
|
overloadTime := as.overloadTime.Load()
|
||||||
if dropTime == 0 {
|
if overloadTime == 0 {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
hot := timex.Since(dropTime) < coolOffDuration
|
if timex.Since(overloadTime) < coolOffDuration {
|
||||||
if !hot {
|
return true
|
||||||
as.droppedRecently.Set(false)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return hot
|
as.droppedRecently.Set(false)
|
||||||
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
func (as *adaptiveShedder) systemOverloaded() bool {
|
func (as *adaptiveShedder) systemOverloaded() bool {
|
||||||
return systemOverloadChecker(as.cpuThreshold)
|
if !systemOverloadChecker(as.cpuThreshold) {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
as.overloadTime.Set(timex.Now())
|
||||||
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
// WithBuckets customizes the Shedder with given number of buckets.
|
// WithBuckets customizes the Shedder with given number of buckets.
|
||||||
|
|||||||
@@ -13,6 +13,7 @@ import (
|
|||||||
"github.com/zeromicro/go-zero/core/mathx"
|
"github.com/zeromicro/go-zero/core/mathx"
|
||||||
"github.com/zeromicro/go-zero/core/stat"
|
"github.com/zeromicro/go-zero/core/stat"
|
||||||
"github.com/zeromicro/go-zero/core/syncx"
|
"github.com/zeromicro/go-zero/core/syncx"
|
||||||
|
"github.com/zeromicro/go-zero/core/timex"
|
||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
@@ -136,7 +137,7 @@ func TestAdaptiveShedderShouldDrop(t *testing.T) {
|
|||||||
passCounter: passCounter,
|
passCounter: passCounter,
|
||||||
rtCounter: rtCounter,
|
rtCounter: rtCounter,
|
||||||
windows: buckets,
|
windows: buckets,
|
||||||
dropTime: syncx.NewAtomicDuration(),
|
overloadTime: syncx.NewAtomicDuration(),
|
||||||
droppedRecently: syncx.NewAtomicBool(),
|
droppedRecently: syncx.NewAtomicBool(),
|
||||||
}
|
}
|
||||||
// cpu >= 800, inflight < maxPass
|
// cpu >= 800, inflight < maxPass
|
||||||
@@ -190,12 +191,15 @@ func TestAdaptiveShedderStillHot(t *testing.T) {
|
|||||||
passCounter: passCounter,
|
passCounter: passCounter,
|
||||||
rtCounter: rtCounter,
|
rtCounter: rtCounter,
|
||||||
windows: buckets,
|
windows: buckets,
|
||||||
dropTime: syncx.NewAtomicDuration(),
|
overloadTime: syncx.NewAtomicDuration(),
|
||||||
droppedRecently: syncx.ForAtomicBool(true),
|
droppedRecently: syncx.ForAtomicBool(true),
|
||||||
}
|
}
|
||||||
assert.False(t, shedder.stillHot())
|
assert.False(t, shedder.stillHot())
|
||||||
shedder.dropTime.Set(-coolOffDuration * 2)
|
shedder.overloadTime.Set(-coolOffDuration * 2)
|
||||||
assert.False(t, shedder.stillHot())
|
assert.False(t, shedder.stillHot())
|
||||||
|
shedder.droppedRecently.Set(true)
|
||||||
|
shedder.overloadTime.Set(timex.Now())
|
||||||
|
assert.True(t, shedder.stillHot())
|
||||||
}
|
}
|
||||||
|
|
||||||
func BenchmarkAdaptiveShedder_Allow(b *testing.B) {
|
func BenchmarkAdaptiveShedder_Allow(b *testing.B) {
|
||||||
|
|||||||
122
core/logc/logs.go
Normal file
122
core/logc/logs.go
Normal file
@@ -0,0 +1,122 @@
|
|||||||
|
package logc
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
"fmt"
|
||||||
|
|
||||||
|
"github.com/zeromicro/go-zero/core/logx"
|
||||||
|
)
|
||||||
|
|
||||||
|
type (
|
||||||
|
LogConf = logx.LogConf
|
||||||
|
LogField = logx.LogField
|
||||||
|
)
|
||||||
|
|
||||||
|
// AddGlobalFields adds global fields.
|
||||||
|
func AddGlobalFields(fields ...LogField) {
|
||||||
|
logx.AddGlobalFields(fields...)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Alert alerts v in alert level, and the message is written to error log.
|
||||||
|
func Alert(_ context.Context, v string) {
|
||||||
|
logx.Alert(v)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Close closes the logging.
|
||||||
|
func Close() error {
|
||||||
|
return logx.Close()
|
||||||
|
}
|
||||||
|
|
||||||
|
// Error writes v into error log.
|
||||||
|
func Error(ctx context.Context, v ...interface{}) {
|
||||||
|
getLogger(ctx).Error(v...)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Errorf writes v with format into error log.
|
||||||
|
func Errorf(ctx context.Context, format string, v ...interface{}) {
|
||||||
|
getLogger(ctx).Errorf(fmt.Errorf(format, v...).Error())
|
||||||
|
}
|
||||||
|
|
||||||
|
// Errorv writes v into error log with json content.
|
||||||
|
// No call stack attached, because not elegant to pack the messages.
|
||||||
|
func Errorv(ctx context.Context, v interface{}) {
|
||||||
|
getLogger(ctx).Errorv(v)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Errorw writes msg along with fields into error log.
|
||||||
|
func Errorw(ctx context.Context, msg string, fields ...LogField) {
|
||||||
|
getLogger(ctx).Errorw(msg, fields...)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Field returns a LogField for the given key and value.
|
||||||
|
func Field(key string, value interface{}) LogField {
|
||||||
|
return logx.Field(key, value)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Info writes v into access log.
|
||||||
|
func Info(ctx context.Context, v ...interface{}) {
|
||||||
|
getLogger(ctx).Info(v...)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Infof writes v with format into access log.
|
||||||
|
func Infof(ctx context.Context, format string, v ...interface{}) {
|
||||||
|
getLogger(ctx).Infof(format, v...)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Infov writes v into access log with json content.
|
||||||
|
func Infov(ctx context.Context, v interface{}) {
|
||||||
|
getLogger(ctx).Infov(v)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Infow writes msg along with fields into access log.
|
||||||
|
func Infow(ctx context.Context, msg string, fields ...LogField) {
|
||||||
|
getLogger(ctx).Infow(msg, fields...)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Must checks if err is nil, otherwise logs the error and exits.
|
||||||
|
func Must(err error) {
|
||||||
|
logx.Must(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
// MustSetup sets up logging with given config c. It exits on error.
|
||||||
|
func MustSetup(c logx.LogConf) {
|
||||||
|
logx.MustSetup(c)
|
||||||
|
}
|
||||||
|
|
||||||
|
// SetLevel sets the logging level. It can be used to suppress some logs.
|
||||||
|
func SetLevel(level uint32) {
|
||||||
|
logx.SetLevel(level)
|
||||||
|
}
|
||||||
|
|
||||||
|
// SetUp sets up the logx. If already set up, just return nil.
|
||||||
|
// we allow SetUp to be called multiple times, because for example
|
||||||
|
// we need to allow different service frameworks to initialize logx respectively.
|
||||||
|
// the same logic for SetUp
|
||||||
|
func SetUp(c LogConf) error {
|
||||||
|
return logx.SetUp(c)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Slow writes v into slow log.
|
||||||
|
func Slow(ctx context.Context, v ...interface{}) {
|
||||||
|
getLogger(ctx).Slow(v...)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Slowf writes v with format into slow log.
|
||||||
|
func Slowf(ctx context.Context, format string, v ...interface{}) {
|
||||||
|
getLogger(ctx).Slowf(format, v...)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Slowv writes v into slow log with json content.
|
||||||
|
func Slowv(ctx context.Context, v interface{}) {
|
||||||
|
getLogger(ctx).Slowv(v)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Sloww writes msg along with fields into slow log.
|
||||||
|
func Sloww(ctx context.Context, msg string, fields ...LogField) {
|
||||||
|
getLogger(ctx).Sloww(msg, fields...)
|
||||||
|
}
|
||||||
|
|
||||||
|
// getLogger returns the logx.Logger with the given ctx and correct caller.
|
||||||
|
func getLogger(ctx context.Context) logx.Logger {
|
||||||
|
return logx.WithContext(ctx).WithCallerSkip(1)
|
||||||
|
}
|
||||||
218
core/logc/logs_test.go
Normal file
218
core/logc/logs_test.go
Normal file
@@ -0,0 +1,218 @@
|
|||||||
|
package logc
|
||||||
|
|
||||||
|
import (
|
||||||
|
"bytes"
|
||||||
|
"context"
|
||||||
|
"encoding/json"
|
||||||
|
"fmt"
|
||||||
|
"runtime"
|
||||||
|
"strings"
|
||||||
|
"testing"
|
||||||
|
|
||||||
|
"github.com/stretchr/testify/assert"
|
||||||
|
"github.com/zeromicro/go-zero/core/logx"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestAddGlobalFields(t *testing.T) {
|
||||||
|
var buf bytes.Buffer
|
||||||
|
writer := logx.NewWriter(&buf)
|
||||||
|
old := logx.Reset()
|
||||||
|
logx.SetWriter(writer)
|
||||||
|
defer logx.SetWriter(old)
|
||||||
|
|
||||||
|
Info(context.Background(), "hello")
|
||||||
|
buf.Reset()
|
||||||
|
|
||||||
|
AddGlobalFields(Field("a", "1"), Field("b", "2"))
|
||||||
|
AddGlobalFields(Field("c", "3"))
|
||||||
|
Info(context.Background(), "world")
|
||||||
|
var m map[string]interface{}
|
||||||
|
assert.NoError(t, json.Unmarshal(buf.Bytes(), &m))
|
||||||
|
assert.Equal(t, "1", m["a"])
|
||||||
|
assert.Equal(t, "2", m["b"])
|
||||||
|
assert.Equal(t, "3", m["c"])
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestAlert(t *testing.T) {
|
||||||
|
var buf strings.Builder
|
||||||
|
writer := logx.NewWriter(&buf)
|
||||||
|
old := logx.Reset()
|
||||||
|
logx.SetWriter(writer)
|
||||||
|
defer logx.SetWriter(old)
|
||||||
|
|
||||||
|
Alert(context.Background(), "foo")
|
||||||
|
assert.True(t, strings.Contains(buf.String(), "foo"), buf.String())
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestError(t *testing.T) {
|
||||||
|
var buf strings.Builder
|
||||||
|
writer := logx.NewWriter(&buf)
|
||||||
|
old := logx.Reset()
|
||||||
|
logx.SetWriter(writer)
|
||||||
|
defer logx.SetWriter(old)
|
||||||
|
|
||||||
|
file, line := getFileLine()
|
||||||
|
Error(context.Background(), "foo")
|
||||||
|
assert.True(t, strings.Contains(buf.String(), fmt.Sprintf("%s:%d", file, line+1)))
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestErrorf(t *testing.T) {
|
||||||
|
var buf strings.Builder
|
||||||
|
writer := logx.NewWriter(&buf)
|
||||||
|
old := logx.Reset()
|
||||||
|
logx.SetWriter(writer)
|
||||||
|
defer logx.SetWriter(old)
|
||||||
|
|
||||||
|
file, line := getFileLine()
|
||||||
|
Errorf(context.Background(), "foo %s", "bar")
|
||||||
|
assert.True(t, strings.Contains(buf.String(), fmt.Sprintf("%s:%d", file, line+1)))
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestErrorv(t *testing.T) {
|
||||||
|
var buf strings.Builder
|
||||||
|
writer := logx.NewWriter(&buf)
|
||||||
|
old := logx.Reset()
|
||||||
|
logx.SetWriter(writer)
|
||||||
|
defer logx.SetWriter(old)
|
||||||
|
|
||||||
|
file, line := getFileLine()
|
||||||
|
Errorv(context.Background(), "foo")
|
||||||
|
assert.True(t, strings.Contains(buf.String(), fmt.Sprintf("%s:%d", file, line+1)))
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestErrorw(t *testing.T) {
|
||||||
|
var buf strings.Builder
|
||||||
|
writer := logx.NewWriter(&buf)
|
||||||
|
old := logx.Reset()
|
||||||
|
logx.SetWriter(writer)
|
||||||
|
defer logx.SetWriter(old)
|
||||||
|
|
||||||
|
file, line := getFileLine()
|
||||||
|
Errorw(context.Background(), "foo", Field("a", "b"))
|
||||||
|
assert.True(t, strings.Contains(buf.String(), fmt.Sprintf("%s:%d", file, line+1)))
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestInfo(t *testing.T) {
|
||||||
|
var buf strings.Builder
|
||||||
|
writer := logx.NewWriter(&buf)
|
||||||
|
old := logx.Reset()
|
||||||
|
logx.SetWriter(writer)
|
||||||
|
defer logx.SetWriter(old)
|
||||||
|
|
||||||
|
file, line := getFileLine()
|
||||||
|
Info(context.Background(), "foo")
|
||||||
|
assert.True(t, strings.Contains(buf.String(), fmt.Sprintf("%s:%d", file, line+1)))
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestInfof(t *testing.T) {
|
||||||
|
var buf strings.Builder
|
||||||
|
writer := logx.NewWriter(&buf)
|
||||||
|
old := logx.Reset()
|
||||||
|
logx.SetWriter(writer)
|
||||||
|
defer logx.SetWriter(old)
|
||||||
|
|
||||||
|
file, line := getFileLine()
|
||||||
|
Infof(context.Background(), "foo %s", "bar")
|
||||||
|
assert.True(t, strings.Contains(buf.String(), fmt.Sprintf("%s:%d", file, line+1)))
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestInfov(t *testing.T) {
|
||||||
|
var buf strings.Builder
|
||||||
|
writer := logx.NewWriter(&buf)
|
||||||
|
old := logx.Reset()
|
||||||
|
logx.SetWriter(writer)
|
||||||
|
defer logx.SetWriter(old)
|
||||||
|
|
||||||
|
file, line := getFileLine()
|
||||||
|
Infov(context.Background(), "foo")
|
||||||
|
assert.True(t, strings.Contains(buf.String(), fmt.Sprintf("%s:%d", file, line+1)))
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestInfow(t *testing.T) {
|
||||||
|
var buf strings.Builder
|
||||||
|
writer := logx.NewWriter(&buf)
|
||||||
|
old := logx.Reset()
|
||||||
|
logx.SetWriter(writer)
|
||||||
|
defer logx.SetWriter(old)
|
||||||
|
|
||||||
|
file, line := getFileLine()
|
||||||
|
Infow(context.Background(), "foo", Field("a", "b"))
|
||||||
|
assert.True(t, strings.Contains(buf.String(), fmt.Sprintf("%s:%d", file, line+1)))
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestMust(t *testing.T) {
|
||||||
|
assert.NotPanics(t, func() {
|
||||||
|
Must(nil)
|
||||||
|
})
|
||||||
|
assert.NotPanics(t, func() {
|
||||||
|
MustSetup(LogConf{})
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestMisc(t *testing.T) {
|
||||||
|
SetLevel(logx.DebugLevel)
|
||||||
|
assert.NoError(t, SetUp(LogConf{}))
|
||||||
|
assert.NoError(t, Close())
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestSlow(t *testing.T) {
|
||||||
|
var buf strings.Builder
|
||||||
|
writer := logx.NewWriter(&buf)
|
||||||
|
old := logx.Reset()
|
||||||
|
logx.SetWriter(writer)
|
||||||
|
defer logx.SetWriter(old)
|
||||||
|
|
||||||
|
file, line := getFileLine()
|
||||||
|
Slow(context.Background(), "foo")
|
||||||
|
assert.True(t, strings.Contains(buf.String(), fmt.Sprintf("%s:%d", file, line+1)), buf.String())
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestSlowf(t *testing.T) {
|
||||||
|
var buf strings.Builder
|
||||||
|
writer := logx.NewWriter(&buf)
|
||||||
|
old := logx.Reset()
|
||||||
|
logx.SetWriter(writer)
|
||||||
|
defer logx.SetWriter(old)
|
||||||
|
|
||||||
|
file, line := getFileLine()
|
||||||
|
Slowf(context.Background(), "foo %s", "bar")
|
||||||
|
assert.True(t, strings.Contains(buf.String(), fmt.Sprintf("%s:%d", file, line+1)), buf.String())
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestSlowv(t *testing.T) {
|
||||||
|
var buf strings.Builder
|
||||||
|
writer := logx.NewWriter(&buf)
|
||||||
|
old := logx.Reset()
|
||||||
|
logx.SetWriter(writer)
|
||||||
|
defer logx.SetWriter(old)
|
||||||
|
|
||||||
|
file, line := getFileLine()
|
||||||
|
Slowv(context.Background(), "foo")
|
||||||
|
assert.True(t, strings.Contains(buf.String(), fmt.Sprintf("%s:%d", file, line+1)), buf.String())
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestSloww(t *testing.T) {
|
||||||
|
var buf strings.Builder
|
||||||
|
writer := logx.NewWriter(&buf)
|
||||||
|
old := logx.Reset()
|
||||||
|
logx.SetWriter(writer)
|
||||||
|
defer logx.SetWriter(old)
|
||||||
|
|
||||||
|
file, line := getFileLine()
|
||||||
|
Sloww(context.Background(), "foo", Field("a", "b"))
|
||||||
|
assert.True(t, strings.Contains(buf.String(), fmt.Sprintf("%s:%d", file, line+1)), buf.String())
|
||||||
|
}
|
||||||
|
|
||||||
|
func getFileLine() (string, int) {
|
||||||
|
_, file, line, _ := runtime.Caller(1)
|
||||||
|
short := file
|
||||||
|
|
||||||
|
for i := len(file) - 1; i > 0; i-- {
|
||||||
|
if file[i] == '/' {
|
||||||
|
short = file[i+1:]
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return short, line
|
||||||
|
}
|
||||||
@@ -7,7 +7,7 @@ type LogConf struct {
|
|||||||
Encoding string `json:",default=json,options=[json,plain]"`
|
Encoding string `json:",default=json,options=[json,plain]"`
|
||||||
TimeFormat string `json:",optional"`
|
TimeFormat string `json:",optional"`
|
||||||
Path string `json:",default=logs"`
|
Path string `json:",default=logs"`
|
||||||
Level string `json:",default=info,options=[info,error,severe]"`
|
Level string `json:",default=info,options=[debug,info,error,severe]"`
|
||||||
Compress bool `json:",optional"`
|
Compress bool `json:",optional"`
|
||||||
KeepDays int `json:",optional"`
|
KeepDays int `json:",optional"`
|
||||||
StackCooldownMillis int `json:",default=100"`
|
StackCooldownMillis int `json:",default=100"`
|
||||||
|
|||||||
@@ -1,16 +1,40 @@
|
|||||||
package logx
|
package logx
|
||||||
|
|
||||||
import "context"
|
import (
|
||||||
|
"context"
|
||||||
|
"sync"
|
||||||
|
"sync/atomic"
|
||||||
|
)
|
||||||
|
|
||||||
var fieldsContextKey contextKey
|
var (
|
||||||
|
fieldsContextKey contextKey
|
||||||
|
globalFields atomic.Value
|
||||||
|
globalFieldsLock sync.Mutex
|
||||||
|
)
|
||||||
|
|
||||||
type contextKey struct{}
|
type contextKey struct{}
|
||||||
|
|
||||||
|
// AddGlobalFields adds global fields.
|
||||||
|
func AddGlobalFields(fields ...LogField) {
|
||||||
|
globalFieldsLock.Lock()
|
||||||
|
defer globalFieldsLock.Unlock()
|
||||||
|
|
||||||
|
old := globalFields.Load()
|
||||||
|
if old == nil {
|
||||||
|
globalFields.Store(append([]LogField(nil), fields...))
|
||||||
|
} else {
|
||||||
|
globalFields.Store(append(old.([]LogField), fields...))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// ContextWithFields returns a new context with the given fields.
|
// ContextWithFields returns a new context with the given fields.
|
||||||
func ContextWithFields(ctx context.Context, fields ...LogField) context.Context {
|
func ContextWithFields(ctx context.Context, fields ...LogField) context.Context {
|
||||||
if val := ctx.Value(fieldsContextKey); val != nil {
|
if val := ctx.Value(fieldsContextKey); val != nil {
|
||||||
if arr, ok := val.([]LogField); ok {
|
if arr, ok := val.([]LogField); ok {
|
||||||
return context.WithValue(ctx, fieldsContextKey, append(arr, fields...))
|
allFields := make([]LogField, 0, len(arr)+len(fields))
|
||||||
|
allFields = append(allFields, arr...)
|
||||||
|
allFields = append(allFields, fields...)
|
||||||
|
return context.WithValue(ctx, fieldsContextKey, allFields)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,12 +1,37 @@
|
|||||||
package logx
|
package logx
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"bytes"
|
||||||
"context"
|
"context"
|
||||||
|
"encoding/json"
|
||||||
|
"strconv"
|
||||||
|
"sync"
|
||||||
|
"sync/atomic"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"github.com/stretchr/testify/assert"
|
"github.com/stretchr/testify/assert"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
func TestAddGlobalFields(t *testing.T) {
|
||||||
|
var buf bytes.Buffer
|
||||||
|
writer := NewWriter(&buf)
|
||||||
|
old := Reset()
|
||||||
|
SetWriter(writer)
|
||||||
|
defer SetWriter(old)
|
||||||
|
|
||||||
|
Info("hello")
|
||||||
|
buf.Reset()
|
||||||
|
|
||||||
|
AddGlobalFields(Field("a", "1"), Field("b", "2"))
|
||||||
|
AddGlobalFields(Field("c", "3"))
|
||||||
|
Info("world")
|
||||||
|
var m map[string]interface{}
|
||||||
|
assert.NoError(t, json.Unmarshal(buf.Bytes(), &m))
|
||||||
|
assert.Equal(t, "1", m["a"])
|
||||||
|
assert.Equal(t, "2", m["b"])
|
||||||
|
assert.Equal(t, "3", m["c"])
|
||||||
|
}
|
||||||
|
|
||||||
func TestContextWithFields(t *testing.T) {
|
func TestContextWithFields(t *testing.T) {
|
||||||
ctx := ContextWithFields(context.Background(), Field("a", 1), Field("b", 2))
|
ctx := ContextWithFields(context.Background(), Field("a", 1), Field("b", 2))
|
||||||
vals := ctx.Value(fieldsContextKey)
|
vals := ctx.Value(fieldsContextKey)
|
||||||
@@ -16,6 +41,15 @@ func TestContextWithFields(t *testing.T) {
|
|||||||
assert.EqualValues(t, []LogField{Field("a", 1), Field("b", 2)}, fields)
|
assert.EqualValues(t, []LogField{Field("a", 1), Field("b", 2)}, fields)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestWithFields(t *testing.T) {
|
||||||
|
ctx := WithFields(context.Background(), Field("a", 1), Field("b", 2))
|
||||||
|
vals := ctx.Value(fieldsContextKey)
|
||||||
|
assert.NotNil(t, vals)
|
||||||
|
fields, ok := vals.([]LogField)
|
||||||
|
assert.True(t, ok)
|
||||||
|
assert.EqualValues(t, []LogField{Field("a", 1), Field("b", 2)}, fields)
|
||||||
|
}
|
||||||
|
|
||||||
func TestWithFieldsAppend(t *testing.T) {
|
func TestWithFieldsAppend(t *testing.T) {
|
||||||
var dummyKey struct{}
|
var dummyKey struct{}
|
||||||
ctx := context.WithValue(context.Background(), dummyKey, "dummy")
|
ctx := context.WithValue(context.Background(), dummyKey, "dummy")
|
||||||
@@ -33,3 +67,55 @@ func TestWithFieldsAppend(t *testing.T) {
|
|||||||
Field("d", 4),
|
Field("d", 4),
|
||||||
}, fields)
|
}, fields)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestWithFieldsAppendCopy(t *testing.T) {
|
||||||
|
const count = 10
|
||||||
|
ctx := context.Background()
|
||||||
|
for i := 0; i < count; i++ {
|
||||||
|
ctx = ContextWithFields(ctx, Field(strconv.Itoa(i), 1))
|
||||||
|
}
|
||||||
|
|
||||||
|
af := Field("foo", 1)
|
||||||
|
bf := Field("bar", 2)
|
||||||
|
ctxa := ContextWithFields(ctx, af)
|
||||||
|
ctxb := ContextWithFields(ctx, bf)
|
||||||
|
|
||||||
|
assert.EqualValues(t, af, ctxa.Value(fieldsContextKey).([]LogField)[count])
|
||||||
|
assert.EqualValues(t, bf, ctxb.Value(fieldsContextKey).([]LogField)[count])
|
||||||
|
}
|
||||||
|
|
||||||
|
func BenchmarkAtomicValue(b *testing.B) {
|
||||||
|
b.ReportAllocs()
|
||||||
|
|
||||||
|
var container atomic.Value
|
||||||
|
vals := []LogField{
|
||||||
|
Field("a", "b"),
|
||||||
|
Field("c", "d"),
|
||||||
|
Field("e", "f"),
|
||||||
|
}
|
||||||
|
container.Store(&vals)
|
||||||
|
|
||||||
|
for i := 0; i < b.N; i++ {
|
||||||
|
val := container.Load()
|
||||||
|
if val != nil {
|
||||||
|
_ = *val.(*[]LogField)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func BenchmarkRWMutex(b *testing.B) {
|
||||||
|
b.ReportAllocs()
|
||||||
|
|
||||||
|
var lock sync.RWMutex
|
||||||
|
vals := []LogField{
|
||||||
|
Field("a", "b"),
|
||||||
|
Field("c", "d"),
|
||||||
|
Field("e", "f"),
|
||||||
|
}
|
||||||
|
|
||||||
|
for i := 0; i < b.N; i++ {
|
||||||
|
lock.RLock()
|
||||||
|
_ = vals
|
||||||
|
lock.RUnlock()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
@@ -7,6 +7,14 @@ import (
|
|||||||
|
|
||||||
// A Logger represents a logger.
|
// A Logger represents a logger.
|
||||||
type Logger interface {
|
type Logger interface {
|
||||||
|
// Debug logs a message at info level.
|
||||||
|
Debug(...interface{})
|
||||||
|
// Debugf logs a message at info level.
|
||||||
|
Debugf(string, ...interface{})
|
||||||
|
// Debugv logs a message at info level.
|
||||||
|
Debugv(interface{})
|
||||||
|
// Debugw logs a message at info level.
|
||||||
|
Debugw(string, ...LogField)
|
||||||
// Error logs a message at error level.
|
// Error logs a message at error level.
|
||||||
Error(...interface{})
|
Error(...interface{})
|
||||||
// Errorf logs a message at error level.
|
// Errorf logs a message at error level.
|
||||||
@@ -37,4 +45,6 @@ type Logger interface {
|
|||||||
WithContext(ctx context.Context) Logger
|
WithContext(ctx context.Context) Logger
|
||||||
// WithDuration returns a new logger with the given duration.
|
// WithDuration returns a new logger with the given duration.
|
||||||
WithDuration(d time.Duration) Logger
|
WithDuration(d time.Duration) Logger
|
||||||
|
// WithFields returns a new logger with the given fields.
|
||||||
|
WithFields(fields ...LogField) Logger
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -64,6 +64,26 @@ func Close() error {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Debug writes v into access log.
|
||||||
|
func Debug(v ...interface{}) {
|
||||||
|
writeDebug(fmt.Sprint(v...))
|
||||||
|
}
|
||||||
|
|
||||||
|
// Debugf writes v with format into access log.
|
||||||
|
func Debugf(format string, v ...interface{}) {
|
||||||
|
writeDebug(fmt.Sprintf(format, v...))
|
||||||
|
}
|
||||||
|
|
||||||
|
// Debugv writes v into access log with json content.
|
||||||
|
func Debugv(v interface{}) {
|
||||||
|
writeDebug(v)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Debugw writes msg along with fields into access log.
|
||||||
|
func Debugw(msg string, fields ...LogField) {
|
||||||
|
writeDebug(msg, fields...)
|
||||||
|
}
|
||||||
|
|
||||||
// Disable disables the logging.
|
// Disable disables the logging.
|
||||||
func Disable() {
|
func Disable() {
|
||||||
atomic.StoreUint32(&disableLog, 1)
|
atomic.StoreUint32(&disableLog, 1)
|
||||||
@@ -352,6 +372,8 @@ func handleOptions(opts []LogOption) {
|
|||||||
|
|
||||||
func setupLogLevel(c LogConf) {
|
func setupLogLevel(c LogConf) {
|
||||||
switch c.Level {
|
switch c.Level {
|
||||||
|
case levelDebug:
|
||||||
|
SetLevel(DebugLevel)
|
||||||
case levelInfo:
|
case levelInfo:
|
||||||
SetLevel(InfoLevel)
|
SetLevel(InfoLevel)
|
||||||
case levelError:
|
case levelError:
|
||||||
@@ -392,6 +414,12 @@ func shallLogStat() bool {
|
|||||||
return atomic.LoadUint32(&disableStat) == 0
|
return atomic.LoadUint32(&disableStat) == 0
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func writeDebug(val interface{}, fields ...LogField) {
|
||||||
|
if shallLog(DebugLevel) {
|
||||||
|
getWriter().Debug(val, addCaller(fields...)...)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
func writeError(val interface{}, fields ...LogField) {
|
func writeError(val interface{}, fields ...LogField) {
|
||||||
if shallLog(ErrorLevel) {
|
if shallLog(ErrorLevel) {
|
||||||
getWriter().Error(val, addCaller(fields...)...)
|
getWriter().Error(val, addCaller(fields...)...)
|
||||||
|
|||||||
@@ -35,6 +35,12 @@ func (mw *mockWriter) Alert(v interface{}) {
|
|||||||
output(&mw.builder, levelAlert, v)
|
output(&mw.builder, levelAlert, v)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (mw *mockWriter) Debug(v interface{}, fields ...LogField) {
|
||||||
|
mw.lock.Lock()
|
||||||
|
defer mw.lock.Unlock()
|
||||||
|
output(&mw.builder, levelDebug, v, fields...)
|
||||||
|
}
|
||||||
|
|
||||||
func (mw *mockWriter) Error(v interface{}, fields ...LogField) {
|
func (mw *mockWriter) Error(v interface{}, fields ...LogField) {
|
||||||
mw.lock.Lock()
|
mw.lock.Lock()
|
||||||
defer mw.lock.Unlock()
|
defer mw.lock.Unlock()
|
||||||
@@ -212,6 +218,46 @@ func TestStructedLogAlert(t *testing.T) {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestStructedLogDebug(t *testing.T) {
|
||||||
|
w := new(mockWriter)
|
||||||
|
old := writer.Swap(w)
|
||||||
|
defer writer.Store(old)
|
||||||
|
|
||||||
|
doTestStructedLog(t, levelDebug, w, func(v ...interface{}) {
|
||||||
|
Debug(v...)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestStructedLogDebugf(t *testing.T) {
|
||||||
|
w := new(mockWriter)
|
||||||
|
old := writer.Swap(w)
|
||||||
|
defer writer.Store(old)
|
||||||
|
|
||||||
|
doTestStructedLog(t, levelDebug, w, func(v ...interface{}) {
|
||||||
|
Debugf(fmt.Sprint(v...))
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestStructedLogDebugv(t *testing.T) {
|
||||||
|
w := new(mockWriter)
|
||||||
|
old := writer.Swap(w)
|
||||||
|
defer writer.Store(old)
|
||||||
|
|
||||||
|
doTestStructedLog(t, levelDebug, w, func(v ...interface{}) {
|
||||||
|
Debugv(fmt.Sprint(v...))
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestStructedLogDebugw(t *testing.T) {
|
||||||
|
w := new(mockWriter)
|
||||||
|
old := writer.Swap(w)
|
||||||
|
defer writer.Store(old)
|
||||||
|
|
||||||
|
doTestStructedLog(t, levelDebug, w, func(v ...interface{}) {
|
||||||
|
Debugw(fmt.Sprint(v...), Field("foo", time.Second))
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
func TestStructedLogError(t *testing.T) {
|
func TestStructedLogError(t *testing.T) {
|
||||||
w := new(mockWriter)
|
w := new(mockWriter)
|
||||||
old := writer.Swap(w)
|
old := writer.Swap(w)
|
||||||
@@ -569,6 +615,8 @@ func TestSetup(t *testing.T) {
|
|||||||
Path: os.TempDir(),
|
Path: os.TempDir(),
|
||||||
Compress: true,
|
Compress: true,
|
||||||
KeepDays: 1,
|
KeepDays: 1,
|
||||||
|
MaxBackups: 3,
|
||||||
|
MaxSize: 1024 * 1024,
|
||||||
}))
|
}))
|
||||||
setupLogLevel(LogConf{
|
setupLogLevel(LogConf{
|
||||||
Level: levelInfo,
|
Level: levelInfo,
|
||||||
|
|||||||
@@ -6,7 +6,7 @@ import (
|
|||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/zeromicro/go-zero/core/timex"
|
"github.com/zeromicro/go-zero/core/timex"
|
||||||
"go.opentelemetry.io/otel/trace"
|
"github.com/zeromicro/go-zero/internal/trace"
|
||||||
)
|
)
|
||||||
|
|
||||||
// WithCallerSkip returns a Logger with given caller skip.
|
// WithCallerSkip returns a Logger with given caller skip.
|
||||||
@@ -40,6 +40,22 @@ type richLogger struct {
|
|||||||
fields []LogField
|
fields []LogField
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (l *richLogger) Debug(v ...interface{}) {
|
||||||
|
l.debug(fmt.Sprint(v...))
|
||||||
|
}
|
||||||
|
|
||||||
|
func (l *richLogger) Debugf(format string, v ...interface{}) {
|
||||||
|
l.debug(fmt.Sprintf(format, v...))
|
||||||
|
}
|
||||||
|
|
||||||
|
func (l *richLogger) Debugv(v interface{}) {
|
||||||
|
l.debug(v)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (l *richLogger) Debugw(msg string, fields ...LogField) {
|
||||||
|
l.debug(msg, fields...)
|
||||||
|
}
|
||||||
|
|
||||||
func (l *richLogger) Error(v ...interface{}) {
|
func (l *richLogger) Error(v ...interface{}) {
|
||||||
l.err(fmt.Sprint(v...))
|
l.err(fmt.Sprint(v...))
|
||||||
}
|
}
|
||||||
@@ -107,6 +123,11 @@ func (l *richLogger) WithDuration(duration time.Duration) Logger {
|
|||||||
return l
|
return l
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (l *richLogger) WithFields(fields ...LogField) Logger {
|
||||||
|
l.fields = append(l.fields, fields...)
|
||||||
|
return l
|
||||||
|
}
|
||||||
|
|
||||||
func (l *richLogger) buildFields(fields ...LogField) []LogField {
|
func (l *richLogger) buildFields(fields ...LogField) []LogField {
|
||||||
fields = append(l.fields, fields...)
|
fields = append(l.fields, fields...)
|
||||||
fields = append(fields, Field(callerKey, getCaller(callerDepth+l.callerSkip)))
|
fields = append(fields, Field(callerKey, getCaller(callerDepth+l.callerSkip)))
|
||||||
@@ -115,12 +136,12 @@ func (l *richLogger) buildFields(fields ...LogField) []LogField {
|
|||||||
return fields
|
return fields
|
||||||
}
|
}
|
||||||
|
|
||||||
traceID := traceIdFromContext(l.ctx)
|
traceID := trace.TraceIDFromContext(l.ctx)
|
||||||
if len(traceID) > 0 {
|
if len(traceID) > 0 {
|
||||||
fields = append(fields, Field(traceKey, traceID))
|
fields = append(fields, Field(traceKey, traceID))
|
||||||
}
|
}
|
||||||
|
|
||||||
spanID := spanIdFromContext(l.ctx)
|
spanID := trace.SpanIDFromContext(l.ctx)
|
||||||
if len(spanID) > 0 {
|
if len(spanID) > 0 {
|
||||||
fields = append(fields, Field(spanKey, spanID))
|
fields = append(fields, Field(spanKey, spanID))
|
||||||
}
|
}
|
||||||
@@ -135,6 +156,12 @@ func (l *richLogger) buildFields(fields ...LogField) []LogField {
|
|||||||
return fields
|
return fields
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (l *richLogger) debug(v interface{}, fields ...LogField) {
|
||||||
|
if shallLog(DebugLevel) {
|
||||||
|
getWriter().Debug(v, l.buildFields(fields...)...)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
func (l *richLogger) err(v interface{}, fields ...LogField) {
|
func (l *richLogger) err(v interface{}, fields ...LogField) {
|
||||||
if shallLog(ErrorLevel) {
|
if shallLog(ErrorLevel) {
|
||||||
getWriter().Error(v, l.buildFields(fields...)...)
|
getWriter().Error(v, l.buildFields(fields...)...)
|
||||||
@@ -152,21 +179,3 @@ func (l *richLogger) slow(v interface{}, fields ...LogField) {
|
|||||||
getWriter().Slow(v, l.buildFields(fields...)...)
|
getWriter().Slow(v, l.buildFields(fields...)...)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func spanIdFromContext(ctx context.Context) string {
|
|
||||||
spanCtx := trace.SpanContextFromContext(ctx)
|
|
||||||
if spanCtx.HasSpanID() {
|
|
||||||
return spanCtx.SpanID().String()
|
|
||||||
}
|
|
||||||
|
|
||||||
return ""
|
|
||||||
}
|
|
||||||
|
|
||||||
func traceIdFromContext(ctx context.Context) string {
|
|
||||||
spanCtx := trace.SpanContextFromContext(ctx)
|
|
||||||
if spanCtx.HasTraceID() {
|
|
||||||
return spanCtx.TraceID().String()
|
|
||||||
}
|
|
||||||
|
|
||||||
return ""
|
|
||||||
}
|
|
||||||
|
|||||||
@@ -37,6 +37,41 @@ func TestTraceLog(t *testing.T) {
|
|||||||
validate(t, w.String(), true, true)
|
validate(t, w.String(), true, true)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestTraceDebug(t *testing.T) {
|
||||||
|
w := new(mockWriter)
|
||||||
|
old := writer.Swap(w)
|
||||||
|
writer.lock.RLock()
|
||||||
|
defer func() {
|
||||||
|
writer.lock.RUnlock()
|
||||||
|
writer.Store(old)
|
||||||
|
}()
|
||||||
|
|
||||||
|
otp := otel.GetTracerProvider()
|
||||||
|
tp := sdktrace.NewTracerProvider(sdktrace.WithSampler(sdktrace.AlwaysSample()))
|
||||||
|
otel.SetTracerProvider(tp)
|
||||||
|
defer otel.SetTracerProvider(otp)
|
||||||
|
|
||||||
|
ctx, span := tp.Tracer("foo").Start(context.Background(), "bar")
|
||||||
|
defer span.End()
|
||||||
|
|
||||||
|
l := WithContext(ctx)
|
||||||
|
SetLevel(DebugLevel)
|
||||||
|
l.WithDuration(time.Second).Debug(testlog)
|
||||||
|
assert.True(t, strings.Contains(w.String(), traceKey))
|
||||||
|
assert.True(t, strings.Contains(w.String(), spanKey))
|
||||||
|
w.Reset()
|
||||||
|
l.WithDuration(time.Second).Debugf(testlog)
|
||||||
|
validate(t, w.String(), true, true)
|
||||||
|
w.Reset()
|
||||||
|
l.WithDuration(time.Second).Debugv(testlog)
|
||||||
|
validate(t, w.String(), true, true)
|
||||||
|
w.Reset()
|
||||||
|
l.WithDuration(time.Second).Debugw(testlog, Field("foo", "bar"))
|
||||||
|
validate(t, w.String(), true, true)
|
||||||
|
assert.True(t, strings.Contains(w.String(), "foo"), w.String())
|
||||||
|
assert.True(t, strings.Contains(w.String(), "bar"), w.String())
|
||||||
|
}
|
||||||
|
|
||||||
func TestTraceError(t *testing.T) {
|
func TestTraceError(t *testing.T) {
|
||||||
w := new(mockWriter)
|
w := new(mockWriter)
|
||||||
old := writer.Swap(w)
|
old := writer.Swap(w)
|
||||||
@@ -237,6 +272,23 @@ func TestLogWithCallerSkip(t *testing.T) {
|
|||||||
assert.True(t, w.Contains(fmt.Sprintf("%s:%d", file, line+1)))
|
assert.True(t, w.Contains(fmt.Sprintf("%s:%d", file, line+1)))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestLoggerWithFields(t *testing.T) {
|
||||||
|
w := new(mockWriter)
|
||||||
|
old := writer.Swap(w)
|
||||||
|
writer.lock.RLock()
|
||||||
|
defer func() {
|
||||||
|
writer.lock.RUnlock()
|
||||||
|
writer.Store(old)
|
||||||
|
}()
|
||||||
|
|
||||||
|
l := WithContext(context.Background()).WithFields(Field("foo", "bar"))
|
||||||
|
l.Info(testlog)
|
||||||
|
|
||||||
|
var val mockValue
|
||||||
|
assert.Nil(t, json.Unmarshal([]byte(w.String()), &val))
|
||||||
|
assert.Equal(t, "bar", val.Foo)
|
||||||
|
}
|
||||||
|
|
||||||
func validate(t *testing.T, body string, expectedTrace, expectedSpan bool) {
|
func validate(t *testing.T, body string, expectedTrace, expectedSpan bool) {
|
||||||
var val mockValue
|
var val mockValue
|
||||||
dec := json.NewDecoder(strings.NewReader(body))
|
dec := json.NewDecoder(strings.NewReader(body))
|
||||||
|
|||||||
@@ -115,7 +115,9 @@ func (r *DailyRotateRule) OutdatedFiles() []string {
|
|||||||
|
|
||||||
var buf strings.Builder
|
var buf strings.Builder
|
||||||
boundary := time.Now().Add(-time.Hour * time.Duration(hoursPerDay*r.days)).Format(dateFormat)
|
boundary := time.Now().Add(-time.Hour * time.Duration(hoursPerDay*r.days)).Format(dateFormat)
|
||||||
fmt.Fprintf(&buf, "%s%s%s", r.filename, r.delimiter, boundary)
|
buf.WriteString(r.filename)
|
||||||
|
buf.WriteString(r.delimiter)
|
||||||
|
buf.WriteString(boundary)
|
||||||
if r.gzip {
|
if r.gzip {
|
||||||
buf.WriteString(gzipExt)
|
buf.WriteString(gzipExt)
|
||||||
}
|
}
|
||||||
@@ -282,7 +284,7 @@ func (l *RotateLogger) getBackupFilename() string {
|
|||||||
func (l *RotateLogger) init() error {
|
func (l *RotateLogger) init() error {
|
||||||
l.backup = l.rule.BackupFileName()
|
l.backup = l.rule.BackupFileName()
|
||||||
|
|
||||||
if _, err := os.Stat(l.filename); err != nil {
|
if fileInfo, err := os.Stat(l.filename); err != nil {
|
||||||
basePath := path.Dir(l.filename)
|
basePath := path.Dir(l.filename)
|
||||||
if _, err = os.Stat(basePath); err != nil {
|
if _, err = os.Stat(basePath); err != nil {
|
||||||
if err = os.MkdirAll(basePath, defaultDirMode); err != nil {
|
if err = os.MkdirAll(basePath, defaultDirMode); err != nil {
|
||||||
@@ -293,8 +295,11 @@ func (l *RotateLogger) init() error {
|
|||||||
if l.fp, err = os.Create(l.filename); err != nil {
|
if l.fp, err = os.Create(l.filename); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
} else if l.fp, err = os.OpenFile(l.filename, os.O_APPEND|os.O_WRONLY, defaultFileMode); err != nil {
|
} else {
|
||||||
return err
|
if l.fp, err = os.OpenFile(l.filename, os.O_APPEND|os.O_WRONLY, defaultFileMode); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
l.currentSize = fileInfo.Size()
|
||||||
}
|
}
|
||||||
|
|
||||||
fs.CloseOnExec(l.fp)
|
fs.CloseOnExec(l.fp)
|
||||||
|
|||||||
@@ -3,8 +3,10 @@ package logx
|
|||||||
import "errors"
|
import "errors"
|
||||||
|
|
||||||
const (
|
const (
|
||||||
// InfoLevel logs everything
|
// DebugLevel logs everything
|
||||||
InfoLevel uint32 = iota
|
DebugLevel uint32 = iota
|
||||||
|
// InfoLevel does not include debugs
|
||||||
|
InfoLevel
|
||||||
// ErrorLevel includes errors, slows, stacks
|
// ErrorLevel includes errors, slows, stacks
|
||||||
ErrorLevel
|
ErrorLevel
|
||||||
// SevereLevel only log severe messages
|
// SevereLevel only log severe messages
|
||||||
@@ -37,6 +39,7 @@ const (
|
|||||||
levelFatal = "fatal"
|
levelFatal = "fatal"
|
||||||
levelSlow = "slow"
|
levelSlow = "slow"
|
||||||
levelStat = "stat"
|
levelStat = "stat"
|
||||||
|
levelDebug = "debug"
|
||||||
|
|
||||||
backupFileDelimiter = "-"
|
backupFileDelimiter = "-"
|
||||||
flags = 0x0
|
flags = 0x0
|
||||||
|
|||||||
@@ -1,12 +1,12 @@
|
|||||||
package logx
|
package logx
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"bytes"
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
"fmt"
|
"fmt"
|
||||||
"io"
|
"io"
|
||||||
"log"
|
"log"
|
||||||
"path"
|
"path"
|
||||||
"strings"
|
|
||||||
"sync"
|
"sync"
|
||||||
"sync/atomic"
|
"sync/atomic"
|
||||||
|
|
||||||
@@ -18,6 +18,7 @@ type (
|
|||||||
Writer interface {
|
Writer interface {
|
||||||
Alert(v interface{})
|
Alert(v interface{})
|
||||||
Close() error
|
Close() error
|
||||||
|
Debug(v interface{}, fields ...LogField)
|
||||||
Error(v interface{}, fields ...LogField)
|
Error(v interface{}, fields ...LogField)
|
||||||
Info(v interface{}, fields ...LogField)
|
Info(v interface{}, fields ...LogField)
|
||||||
Severe(v interface{})
|
Severe(v interface{})
|
||||||
@@ -194,6 +195,10 @@ func (w *concreteWriter) Close() error {
|
|||||||
return w.statLog.Close()
|
return w.statLog.Close()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (w *concreteWriter) Debug(v interface{}, fields ...LogField) {
|
||||||
|
output(w.infoLog, levelDebug, v, fields...)
|
||||||
|
}
|
||||||
|
|
||||||
func (w *concreteWriter) Error(v interface{}, fields ...LogField) {
|
func (w *concreteWriter) Error(v interface{}, fields ...LogField) {
|
||||||
output(w.errorLog, levelError, v, fields...)
|
output(w.errorLog, levelError, v, fields...)
|
||||||
}
|
}
|
||||||
@@ -227,6 +232,9 @@ func (n nopWriter) Close() error {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (n nopWriter) Debug(_ interface{}, _ ...LogField) {
|
||||||
|
}
|
||||||
|
|
||||||
func (n nopWriter) Error(_ interface{}, _ ...LogField) {
|
func (n nopWriter) Error(_ interface{}, _ ...LogField) {
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -255,7 +263,18 @@ func buildFields(fields ...LogField) []string {
|
|||||||
return items
|
return items
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func combineGlobalFields(fields []LogField) []LogField {
|
||||||
|
globals := globalFields.Load()
|
||||||
|
if globals == nil {
|
||||||
|
return fields
|
||||||
|
}
|
||||||
|
|
||||||
|
return append(globals.([]LogField), fields...)
|
||||||
|
}
|
||||||
|
|
||||||
func output(writer io.Writer, level string, val interface{}, fields ...LogField) {
|
func output(writer io.Writer, level string, val interface{}, fields ...LogField) {
|
||||||
|
fields = combineGlobalFields(fields)
|
||||||
|
|
||||||
switch atomic.LoadUint32(&encoding) {
|
switch atomic.LoadUint32(&encoding) {
|
||||||
case plainEncodingType:
|
case plainEncodingType:
|
||||||
writePlainAny(writer, level, val, buildFields(fields...)...)
|
writePlainAny(writer, level, val, buildFields(fields...)...)
|
||||||
@@ -284,6 +303,8 @@ func wrapLevelWithColor(level string) string {
|
|||||||
colour = color.FgBlue
|
colour = color.FgBlue
|
||||||
case levelSlow:
|
case levelSlow:
|
||||||
colour = color.FgYellow
|
colour = color.FgYellow
|
||||||
|
case levelDebug:
|
||||||
|
colour = color.FgYellow
|
||||||
case levelStat:
|
case levelStat:
|
||||||
colour = color.FgGreen
|
colour = color.FgGreen
|
||||||
}
|
}
|
||||||
@@ -321,7 +342,7 @@ func writePlainAny(writer io.Writer, level string, val interface{}, fields ...st
|
|||||||
}
|
}
|
||||||
|
|
||||||
func writePlainText(writer io.Writer, level, msg string, fields ...string) {
|
func writePlainText(writer io.Writer, level, msg string, fields ...string) {
|
||||||
var buf strings.Builder
|
var buf bytes.Buffer
|
||||||
buf.WriteString(getTimestamp())
|
buf.WriteString(getTimestamp())
|
||||||
buf.WriteByte(plainEncodingSep)
|
buf.WriteByte(plainEncodingSep)
|
||||||
buf.WriteString(level)
|
buf.WriteString(level)
|
||||||
@@ -337,13 +358,13 @@ func writePlainText(writer io.Writer, level, msg string, fields ...string) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
if _, err := fmt.Fprint(writer, buf.String()); err != nil {
|
if _, err := writer.Write(buf.Bytes()); err != nil {
|
||||||
log.Println(err.Error())
|
log.Println(err.Error())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func writePlainValue(writer io.Writer, level string, val interface{}, fields ...string) {
|
func writePlainValue(writer io.Writer, level string, val interface{}, fields ...string) {
|
||||||
var buf strings.Builder
|
var buf bytes.Buffer
|
||||||
buf.WriteString(getTimestamp())
|
buf.WriteString(getTimestamp())
|
||||||
buf.WriteByte(plainEncodingSep)
|
buf.WriteByte(plainEncodingSep)
|
||||||
buf.WriteString(level)
|
buf.WriteString(level)
|
||||||
@@ -363,7 +384,7 @@ func writePlainValue(writer io.Writer, level string, val interface{}, fields ...
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
if _, err := fmt.Fprint(writer, buf.String()); err != nil {
|
if _, err := writer.Write(buf.Bytes()); err != nil {
|
||||||
log.Println(err.Error())
|
log.Println(err.Error())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -16,6 +16,9 @@ func TestNewWriter(t *testing.T) {
|
|||||||
w := NewWriter(&buf)
|
w := NewWriter(&buf)
|
||||||
w.Info(literal)
|
w.Info(literal)
|
||||||
assert.Contains(t, buf.String(), literal)
|
assert.Contains(t, buf.String(), literal)
|
||||||
|
buf.Reset()
|
||||||
|
w.Debug(literal)
|
||||||
|
assert.Contains(t, buf.String(), literal)
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestConsoleWriter(t *testing.T) {
|
func TestConsoleWriter(t *testing.T) {
|
||||||
@@ -97,6 +100,7 @@ func TestNopWriter(t *testing.T) {
|
|||||||
assert.NotPanics(t, func() {
|
assert.NotPanics(t, func() {
|
||||||
var w nopWriter
|
var w nopWriter
|
||||||
w.Alert("foo")
|
w.Alert("foo")
|
||||||
|
w.Debug("foo")
|
||||||
w.Error("foo")
|
w.Error("foo")
|
||||||
w.Info("foo")
|
w.Info("foo")
|
||||||
w.Severe("foo")
|
w.Severe("foo")
|
||||||
@@ -123,6 +127,12 @@ func TestWritePlainAny(t *testing.T) {
|
|||||||
writePlainAny(nil, levelInfo, "foo")
|
writePlainAny(nil, levelInfo, "foo")
|
||||||
assert.Contains(t, buf.String(), "foo")
|
assert.Contains(t, buf.String(), "foo")
|
||||||
|
|
||||||
|
buf.Reset()
|
||||||
|
writePlainAny(nil, levelDebug, make(chan int))
|
||||||
|
assert.Contains(t, buf.String(), "unsupported type")
|
||||||
|
writePlainAny(nil, levelDebug, 100)
|
||||||
|
assert.Contains(t, buf.String(), "100")
|
||||||
|
|
||||||
buf.Reset()
|
buf.Reset()
|
||||||
writePlainAny(nil, levelError, make(chan int))
|
writePlainAny(nil, levelError, make(chan int))
|
||||||
assert.Contains(t, buf.String(), "unsupported type")
|
assert.Contains(t, buf.String(), "unsupported type")
|
||||||
|
|||||||
@@ -8,10 +8,12 @@ type (
|
|||||||
// use context and OptionalDep option to determine the value of Optional
|
// use context and OptionalDep option to determine the value of Optional
|
||||||
// nothing to do with context.Context
|
// nothing to do with context.Context
|
||||||
fieldOptionsWithContext struct {
|
fieldOptionsWithContext struct {
|
||||||
|
Inherit bool
|
||||||
FromString bool
|
FromString bool
|
||||||
Optional bool
|
Optional bool
|
||||||
Options []string
|
Options []string
|
||||||
Default string
|
Default string
|
||||||
|
EnvVar string
|
||||||
Range *numberRange
|
Range *numberRange
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -40,6 +42,10 @@ func (o *fieldOptionsWithContext) getDefault() (string, bool) {
|
|||||||
return o.Default, len(o.Default) > 0
|
return o.Default, len(o.Default) > 0
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (o *fieldOptionsWithContext) inherit() bool {
|
||||||
|
return o != nil && o.Inherit
|
||||||
|
}
|
||||||
|
|
||||||
func (o *fieldOptionsWithContext) optional() bool {
|
func (o *fieldOptionsWithContext) optional() bool {
|
||||||
return o != nil && o.Optional
|
return o != nil && o.Optional
|
||||||
}
|
}
|
||||||
@@ -101,5 +107,6 @@ func (o *fieldOptions) toOptionsWithContext(key string, m Valuer, fullName strin
|
|||||||
Optional: optional,
|
Optional: optional,
|
||||||
Options: o.Options,
|
Options: o.Options,
|
||||||
Default: o.Default,
|
Default: o.Default,
|
||||||
|
EnvVar: o.EnvVar,
|
||||||
}, nil
|
}, nil
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -11,18 +11,26 @@ const jsonTagKey = "json"
|
|||||||
var jsonUnmarshaler = NewUnmarshaler(jsonTagKey)
|
var jsonUnmarshaler = NewUnmarshaler(jsonTagKey)
|
||||||
|
|
||||||
// UnmarshalJsonBytes unmarshals content into v.
|
// UnmarshalJsonBytes unmarshals content into v.
|
||||||
func UnmarshalJsonBytes(content []byte, v interface{}) error {
|
func UnmarshalJsonBytes(content []byte, v interface{}, opts ...UnmarshalOption) error {
|
||||||
return unmarshalJsonBytes(content, v, jsonUnmarshaler)
|
return unmarshalJsonBytes(content, v, getJsonUnmarshaler(opts...))
|
||||||
}
|
}
|
||||||
|
|
||||||
// UnmarshalJsonMap unmarshals content from m into v.
|
// UnmarshalJsonMap unmarshals content from m into v.
|
||||||
func UnmarshalJsonMap(m map[string]interface{}, v interface{}) error {
|
func UnmarshalJsonMap(m map[string]interface{}, v interface{}, opts ...UnmarshalOption) error {
|
||||||
return jsonUnmarshaler.Unmarshal(m, v)
|
return getJsonUnmarshaler(opts...).Unmarshal(m, v)
|
||||||
}
|
}
|
||||||
|
|
||||||
// UnmarshalJsonReader unmarshals content from reader into v.
|
// UnmarshalJsonReader unmarshals content from reader into v.
|
||||||
func UnmarshalJsonReader(reader io.Reader, v interface{}) error {
|
func UnmarshalJsonReader(reader io.Reader, v interface{}, opts ...UnmarshalOption) error {
|
||||||
return unmarshalJsonReader(reader, v, jsonUnmarshaler)
|
return unmarshalJsonReader(reader, v, getJsonUnmarshaler(opts...))
|
||||||
|
}
|
||||||
|
|
||||||
|
func getJsonUnmarshaler(opts ...UnmarshalOption) *Unmarshaler {
|
||||||
|
if len(opts) > 0 {
|
||||||
|
return NewUnmarshaler(jsonTagKey, opts...)
|
||||||
|
}
|
||||||
|
|
||||||
|
return jsonUnmarshaler
|
||||||
}
|
}
|
||||||
|
|
||||||
func unmarshalJsonBytes(content []byte, v interface{}, unmarshaler *Unmarshaler) error {
|
func unmarshalJsonBytes(content []byte, v interface{}, unmarshaler *Unmarshaler) error {
|
||||||
|
|||||||
@@ -900,7 +900,9 @@ func TestUnmarshalMap(t *testing.T) {
|
|||||||
Any string `json:",optional"`
|
Any string `json:",optional"`
|
||||||
}
|
}
|
||||||
|
|
||||||
err := UnmarshalJsonMap(m, &v)
|
err := UnmarshalJsonMap(m, &v, WithCanonicalKeyFunc(func(s string) string {
|
||||||
|
return s
|
||||||
|
}))
|
||||||
assert.Nil(t, err)
|
assert.Nil(t, err)
|
||||||
assert.True(t, len(v.Any) == 0)
|
assert.True(t, len(v.Any) == 0)
|
||||||
})
|
})
|
||||||
|
|||||||
@@ -1,29 +1,27 @@
|
|||||||
package mapping
|
package mapping
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"bytes"
|
|
||||||
"encoding/json"
|
|
||||||
"io"
|
"io"
|
||||||
|
|
||||||
"github.com/pelletier/go-toml/v2"
|
"github.com/zeromicro/go-zero/internal/encoding"
|
||||||
)
|
)
|
||||||
|
|
||||||
// UnmarshalTomlBytes unmarshals TOML bytes into the given v.
|
// UnmarshalTomlBytes unmarshals TOML bytes into the given v.
|
||||||
func UnmarshalTomlBytes(content []byte, v interface{}) error {
|
func UnmarshalTomlBytes(content []byte, v interface{}, opts ...UnmarshalOption) error {
|
||||||
return UnmarshalTomlReader(bytes.NewReader(content), v)
|
b, err := encoding.TomlToJson(content)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
return UnmarshalJsonBytes(b, v, opts...)
|
||||||
}
|
}
|
||||||
|
|
||||||
// UnmarshalTomlReader unmarshals TOML from the given io.Reader into the given v.
|
// UnmarshalTomlReader unmarshals TOML from the given io.Reader into the given v.
|
||||||
func UnmarshalTomlReader(r io.Reader, v interface{}) error {
|
func UnmarshalTomlReader(r io.Reader, v interface{}, opts ...UnmarshalOption) error {
|
||||||
var val interface{}
|
b, err := io.ReadAll(r)
|
||||||
if err := toml.NewDecoder(r).Decode(&val); err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
var buf bytes.Buffer
|
return UnmarshalTomlBytes(b, v, opts...)
|
||||||
if err := json.NewEncoder(&buf).Encode(val); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
return UnmarshalJsonReader(&buf, v)
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
package mapping
|
package mapping
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"strings"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"github.com/stretchr/testify/assert"
|
"github.com/stretchr/testify/assert"
|
||||||
@@ -18,7 +19,7 @@ d = "abcd!@#$112"
|
|||||||
C string `json:"c"`
|
C string `json:"c"`
|
||||||
D string `json:"d"`
|
D string `json:"d"`
|
||||||
}
|
}
|
||||||
assert.Nil(t, UnmarshalTomlBytes([]byte(input), &val))
|
assert.NoError(t, UnmarshalTomlReader(strings.NewReader(input), &val))
|
||||||
assert.Equal(t, "foo", val.A)
|
assert.Equal(t, "foo", val.A)
|
||||||
assert.Equal(t, 1, val.B)
|
assert.Equal(t, 1, val.B)
|
||||||
assert.Equal(t, "${FOO}", val.C)
|
assert.Equal(t, "${FOO}", val.C)
|
||||||
@@ -37,5 +38,12 @@ d = "abcd!@#$112"
|
|||||||
C string `json:"c"`
|
C string `json:"c"`
|
||||||
D string `json:"d"`
|
D string `json:"d"`
|
||||||
}
|
}
|
||||||
assert.NotNil(t, UnmarshalTomlBytes([]byte(input), &val))
|
assert.Error(t, UnmarshalTomlReader(strings.NewReader(input), &val))
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestUnmarshalTomlBadReader(t *testing.T) {
|
||||||
|
var val struct {
|
||||||
|
A string `json:"a"`
|
||||||
|
}
|
||||||
|
assert.Error(t, UnmarshalTomlReader(new(badReader), &val))
|
||||||
}
|
}
|
||||||
|
|||||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@@ -10,11 +10,14 @@ import (
|
|||||||
"strings"
|
"strings"
|
||||||
"sync"
|
"sync"
|
||||||
|
|
||||||
|
"github.com/zeromicro/go-zero/core/lang"
|
||||||
"github.com/zeromicro/go-zero/core/stringx"
|
"github.com/zeromicro/go-zero/core/stringx"
|
||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
defaultOption = "default"
|
defaultOption = "default"
|
||||||
|
envOption = "env"
|
||||||
|
inheritOption = "inherit"
|
||||||
stringOption = "string"
|
stringOption = "string"
|
||||||
optionalOption = "optional"
|
optionalOption = "optional"
|
||||||
optionsOption = "options"
|
optionsOption = "options"
|
||||||
@@ -62,22 +65,7 @@ func Deref(t reflect.Type) reflect.Type {
|
|||||||
|
|
||||||
// Repr returns the string representation of v.
|
// Repr returns the string representation of v.
|
||||||
func Repr(v interface{}) string {
|
func Repr(v interface{}) string {
|
||||||
if v == nil {
|
return lang.Repr(v)
|
||||||
return ""
|
|
||||||
}
|
|
||||||
|
|
||||||
// if func (v *Type) String() string, we can't use Elem()
|
|
||||||
switch vt := v.(type) {
|
|
||||||
case fmt.Stringer:
|
|
||||||
return vt.String()
|
|
||||||
}
|
|
||||||
|
|
||||||
val := reflect.ValueOf(v)
|
|
||||||
if val.Kind() == reflect.Ptr && !val.IsNil() {
|
|
||||||
val = val.Elem()
|
|
||||||
}
|
|
||||||
|
|
||||||
return reprOfValue(val)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// ValidatePtr validates v if it's a valid pointer.
|
// ValidatePtr validates v if it's a valid pointer.
|
||||||
@@ -94,7 +82,14 @@ func ValidatePtr(v *reflect.Value) error {
|
|||||||
func convertType(kind reflect.Kind, str string) (interface{}, error) {
|
func convertType(kind reflect.Kind, str string) (interface{}, error) {
|
||||||
switch kind {
|
switch kind {
|
||||||
case reflect.Bool:
|
case reflect.Bool:
|
||||||
return str == "1" || strings.ToLower(str) == "true", nil
|
switch strings.ToLower(str) {
|
||||||
|
case "1", "true":
|
||||||
|
return true, nil
|
||||||
|
case "0", "false":
|
||||||
|
return false, nil
|
||||||
|
default:
|
||||||
|
return false, errTypeMismatch
|
||||||
|
}
|
||||||
case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
|
case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
|
||||||
intValue, err := strconv.ParseInt(str, 10, 64)
|
intValue, err := strconv.ParseInt(str, 10, 64)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@@ -215,8 +210,8 @@ func isRightInclude(b byte) (bool, error) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func maybeNewValue(field reflect.StructField, value reflect.Value) {
|
func maybeNewValue(fieldType reflect.Type, value reflect.Value) {
|
||||||
if field.Type.Kind() == reflect.Ptr && value.IsNil() {
|
if fieldType.Kind() == reflect.Ptr && value.IsNil() {
|
||||||
value.Set(reflect.New(value.Type().Elem()))
|
value.Set(reflect.New(value.Type().Elem()))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -335,6 +330,8 @@ func parseNumberRange(str string) (*numberRange, error) {
|
|||||||
|
|
||||||
func parseOption(fieldOpts *fieldOptions, fieldName, option string) error {
|
func parseOption(fieldOpts *fieldOptions, fieldName, option string) error {
|
||||||
switch {
|
switch {
|
||||||
|
case option == inheritOption:
|
||||||
|
fieldOpts.Inherit = true
|
||||||
case option == stringOption:
|
case option == stringOption:
|
||||||
fieldOpts.FromString = true
|
fieldOpts.FromString = true
|
||||||
case strings.HasPrefix(option, optionalOption):
|
case strings.HasPrefix(option, optionalOption):
|
||||||
@@ -351,26 +348,33 @@ func parseOption(fieldOpts *fieldOptions, fieldName, option string) error {
|
|||||||
case option == optionalOption:
|
case option == optionalOption:
|
||||||
fieldOpts.Optional = true
|
fieldOpts.Optional = true
|
||||||
case strings.HasPrefix(option, optionsOption):
|
case strings.HasPrefix(option, optionsOption):
|
||||||
segs := strings.Split(option, equalToken)
|
val, err := parseProperty(fieldName, optionsOption, option)
|
||||||
if len(segs) != 2 {
|
if err != nil {
|
||||||
return fmt.Errorf("field %s has wrong options", fieldName)
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
fieldOpts.Options = parseOptions(segs[1])
|
fieldOpts.Options = parseOptions(val)
|
||||||
case strings.HasPrefix(option, defaultOption):
|
case strings.HasPrefix(option, defaultOption):
|
||||||
segs := strings.Split(option, equalToken)
|
val, err := parseProperty(fieldName, defaultOption, option)
|
||||||
if len(segs) != 2 {
|
if err != nil {
|
||||||
return fmt.Errorf("field %s has wrong default option", fieldName)
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
fieldOpts.Default = strings.TrimSpace(segs[1])
|
fieldOpts.Default = val
|
||||||
|
case strings.HasPrefix(option, envOption):
|
||||||
|
val, err := parseProperty(fieldName, envOption, option)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
fieldOpts.EnvVar = val
|
||||||
case strings.HasPrefix(option, rangeOption):
|
case strings.HasPrefix(option, rangeOption):
|
||||||
segs := strings.Split(option, equalToken)
|
val, err := parseProperty(fieldName, rangeOption, option)
|
||||||
if len(segs) != 2 {
|
if err != nil {
|
||||||
return fmt.Errorf("field %s has wrong range", fieldName)
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
nr, err := parseNumberRange(segs[1])
|
nr, err := parseNumberRange(val)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
@@ -395,6 +399,15 @@ func parseOptions(val string) []string {
|
|||||||
return strings.Split(val, optionSeparator)
|
return strings.Split(val, optionSeparator)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func parseProperty(field, tag, val string) (string, error) {
|
||||||
|
segs := strings.Split(val, equalToken)
|
||||||
|
if len(segs) != 2 {
|
||||||
|
return "", fmt.Errorf("field %s has wrong %s", field, tag)
|
||||||
|
}
|
||||||
|
|
||||||
|
return strings.TrimSpace(segs[1]), nil
|
||||||
|
}
|
||||||
|
|
||||||
func parseSegments(val string) []string {
|
func parseSegments(val string) []string {
|
||||||
var segments []string
|
var segments []string
|
||||||
var escaped, grouped bool
|
var escaped, grouped bool
|
||||||
@@ -444,47 +457,6 @@ func parseSegments(val string) []string {
|
|||||||
return segments
|
return segments
|
||||||
}
|
}
|
||||||
|
|
||||||
func reprOfValue(val reflect.Value) string {
|
|
||||||
switch vt := val.Interface().(type) {
|
|
||||||
case bool:
|
|
||||||
return strconv.FormatBool(vt)
|
|
||||||
case error:
|
|
||||||
return vt.Error()
|
|
||||||
case float32:
|
|
||||||
return strconv.FormatFloat(float64(vt), 'f', -1, 32)
|
|
||||||
case float64:
|
|
||||||
return strconv.FormatFloat(vt, 'f', -1, 64)
|
|
||||||
case fmt.Stringer:
|
|
||||||
return vt.String()
|
|
||||||
case int:
|
|
||||||
return strconv.Itoa(vt)
|
|
||||||
case int8:
|
|
||||||
return strconv.Itoa(int(vt))
|
|
||||||
case int16:
|
|
||||||
return strconv.Itoa(int(vt))
|
|
||||||
case int32:
|
|
||||||
return strconv.Itoa(int(vt))
|
|
||||||
case int64:
|
|
||||||
return strconv.FormatInt(vt, 10)
|
|
||||||
case string:
|
|
||||||
return vt
|
|
||||||
case uint:
|
|
||||||
return strconv.FormatUint(uint64(vt), 10)
|
|
||||||
case uint8:
|
|
||||||
return strconv.FormatUint(uint64(vt), 10)
|
|
||||||
case uint16:
|
|
||||||
return strconv.FormatUint(uint64(vt), 10)
|
|
||||||
case uint32:
|
|
||||||
return strconv.FormatUint(uint64(vt), 10)
|
|
||||||
case uint64:
|
|
||||||
return strconv.FormatUint(vt, 10)
|
|
||||||
case []byte:
|
|
||||||
return string(vt)
|
|
||||||
default:
|
|
||||||
return fmt.Sprint(val.Interface())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func setMatchedPrimitiveValue(kind reflect.Kind, value reflect.Value, v interface{}) error {
|
func setMatchedPrimitiveValue(kind reflect.Kind, value reflect.Value, v interface{}) error {
|
||||||
switch kind {
|
switch kind {
|
||||||
case reflect.Bool:
|
case reflect.Bool:
|
||||||
|
|||||||
@@ -296,127 +296,3 @@ func TestSetValueFormatErrors(t *testing.T) {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestRepr(t *testing.T) {
|
|
||||||
var (
|
|
||||||
f32 float32 = 1.1
|
|
||||||
f64 = 2.2
|
|
||||||
i8 int8 = 1
|
|
||||||
i16 int16 = 2
|
|
||||||
i32 int32 = 3
|
|
||||||
i64 int64 = 4
|
|
||||||
u8 uint8 = 5
|
|
||||||
u16 uint16 = 6
|
|
||||||
u32 uint32 = 7
|
|
||||||
u64 uint64 = 8
|
|
||||||
)
|
|
||||||
tests := []struct {
|
|
||||||
v interface{}
|
|
||||||
expect string
|
|
||||||
}{
|
|
||||||
{
|
|
||||||
nil,
|
|
||||||
"",
|
|
||||||
},
|
|
||||||
{
|
|
||||||
mockStringable{},
|
|
||||||
"mocked",
|
|
||||||
},
|
|
||||||
{
|
|
||||||
new(mockStringable),
|
|
||||||
"mocked",
|
|
||||||
},
|
|
||||||
{
|
|
||||||
newMockPtr(),
|
|
||||||
"mockptr",
|
|
||||||
},
|
|
||||||
{
|
|
||||||
&mockOpacity{
|
|
||||||
val: 1,
|
|
||||||
},
|
|
||||||
"{1}",
|
|
||||||
},
|
|
||||||
{
|
|
||||||
true,
|
|
||||||
"true",
|
|
||||||
},
|
|
||||||
{
|
|
||||||
false,
|
|
||||||
"false",
|
|
||||||
},
|
|
||||||
{
|
|
||||||
f32,
|
|
||||||
"1.1",
|
|
||||||
},
|
|
||||||
{
|
|
||||||
f64,
|
|
||||||
"2.2",
|
|
||||||
},
|
|
||||||
{
|
|
||||||
i8,
|
|
||||||
"1",
|
|
||||||
},
|
|
||||||
{
|
|
||||||
i16,
|
|
||||||
"2",
|
|
||||||
},
|
|
||||||
{
|
|
||||||
i32,
|
|
||||||
"3",
|
|
||||||
},
|
|
||||||
{
|
|
||||||
i64,
|
|
||||||
"4",
|
|
||||||
},
|
|
||||||
{
|
|
||||||
u8,
|
|
||||||
"5",
|
|
||||||
},
|
|
||||||
{
|
|
||||||
u16,
|
|
||||||
"6",
|
|
||||||
},
|
|
||||||
{
|
|
||||||
u32,
|
|
||||||
"7",
|
|
||||||
},
|
|
||||||
{
|
|
||||||
u64,
|
|
||||||
"8",
|
|
||||||
},
|
|
||||||
{
|
|
||||||
[]byte(`abcd`),
|
|
||||||
"abcd",
|
|
||||||
},
|
|
||||||
{
|
|
||||||
mockOpacity{val: 1},
|
|
||||||
"{1}",
|
|
||||||
},
|
|
||||||
}
|
|
||||||
|
|
||||||
for _, test := range tests {
|
|
||||||
t.Run(test.expect, func(t *testing.T) {
|
|
||||||
assert.Equal(t, test.expect, Repr(test.v))
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
type mockStringable struct{}
|
|
||||||
|
|
||||||
func (m mockStringable) String() string {
|
|
||||||
return "mocked"
|
|
||||||
}
|
|
||||||
|
|
||||||
type mockPtr struct{}
|
|
||||||
|
|
||||||
func newMockPtr() *mockPtr {
|
|
||||||
return new(mockPtr)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (m *mockPtr) String() string {
|
|
||||||
return "mockptr"
|
|
||||||
}
|
|
||||||
|
|
||||||
type mockOpacity struct {
|
|
||||||
val int
|
|
||||||
}
|
|
||||||
|
|||||||
@@ -7,12 +7,106 @@ type (
|
|||||||
Value(key string) (interface{}, bool)
|
Value(key string) (interface{}, bool)
|
||||||
}
|
}
|
||||||
|
|
||||||
// A MapValuer is a map that can use Value method to get values with given keys.
|
// A valuerWithParent defines a node that has a parent node.
|
||||||
MapValuer map[string]interface{}
|
valuerWithParent interface {
|
||||||
|
Valuer
|
||||||
|
// Parent get the parent valuer for current node.
|
||||||
|
Parent() valuerWithParent
|
||||||
|
}
|
||||||
|
|
||||||
|
// A node is a map that can use Value method to get values with given keys.
|
||||||
|
node struct {
|
||||||
|
current Valuer
|
||||||
|
parent valuerWithParent
|
||||||
|
}
|
||||||
|
|
||||||
|
// A valueWithParent is used to wrap the value with its parent.
|
||||||
|
valueWithParent struct {
|
||||||
|
value interface{}
|
||||||
|
parent valuerWithParent
|
||||||
|
}
|
||||||
|
|
||||||
|
// mapValuer is a type for map to meet the Valuer interface.
|
||||||
|
mapValuer map[string]interface{}
|
||||||
|
// simpleValuer is a type to get value from current node.
|
||||||
|
simpleValuer node
|
||||||
|
// recursiveValuer is a type to get the value recursively from current and parent nodes.
|
||||||
|
recursiveValuer node
|
||||||
)
|
)
|
||||||
|
|
||||||
// Value gets the value associated with the given key from mv.
|
// Value gets the value assciated with the given key from mv.
|
||||||
func (mv MapValuer) Value(key string) (interface{}, bool) {
|
func (mv mapValuer) Value(key string) (interface{}, bool) {
|
||||||
v, ok := mv[key]
|
v, ok := mv[key]
|
||||||
return v, ok
|
return v, ok
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Value gets the value associated with the given key from sv.
|
||||||
|
func (sv simpleValuer) Value(key string) (interface{}, bool) {
|
||||||
|
v, ok := sv.current.Value(key)
|
||||||
|
return v, ok
|
||||||
|
}
|
||||||
|
|
||||||
|
// Parent get the parent valuer from sv.
|
||||||
|
func (sv simpleValuer) Parent() valuerWithParent {
|
||||||
|
if sv.parent == nil {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
return recursiveValuer{
|
||||||
|
current: sv.parent,
|
||||||
|
parent: sv.parent.Parent(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Value gets the value associated with the given key from rv,
|
||||||
|
// and it will inherit the value from parent nodes.
|
||||||
|
func (rv recursiveValuer) Value(key string) (interface{}, bool) {
|
||||||
|
val, ok := rv.current.Value(key)
|
||||||
|
if !ok {
|
||||||
|
if parent := rv.Parent(); parent != nil {
|
||||||
|
return parent.Value(key)
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil, false
|
||||||
|
}
|
||||||
|
|
||||||
|
vm, ok := val.(map[string]interface{})
|
||||||
|
if !ok {
|
||||||
|
return val, true
|
||||||
|
}
|
||||||
|
|
||||||
|
parent := rv.Parent()
|
||||||
|
if parent == nil {
|
||||||
|
return val, true
|
||||||
|
}
|
||||||
|
|
||||||
|
pv, ok := parent.Value(key)
|
||||||
|
if !ok {
|
||||||
|
return val, true
|
||||||
|
}
|
||||||
|
|
||||||
|
pm, ok := pv.(map[string]interface{})
|
||||||
|
if !ok {
|
||||||
|
return val, true
|
||||||
|
}
|
||||||
|
|
||||||
|
for k, v := range pm {
|
||||||
|
if _, ok := vm[k]; !ok {
|
||||||
|
vm[k] = v
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return vm, true
|
||||||
|
}
|
||||||
|
|
||||||
|
// Parent get the parent valuer from rv.
|
||||||
|
func (rv recursiveValuer) Parent() valuerWithParent {
|
||||||
|
if rv.parent == nil {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
return recursiveValuer{
|
||||||
|
current: rv.parent,
|
||||||
|
parent: rv.parent.Parent(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
33
core/mapping/valuer_test.go
Normal file
33
core/mapping/valuer_test.go
Normal file
@@ -0,0 +1,33 @@
|
|||||||
|
package mapping
|
||||||
|
|
||||||
|
import (
|
||||||
|
"testing"
|
||||||
|
|
||||||
|
"github.com/stretchr/testify/assert"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestMapValuerWithInherit_Value(t *testing.T) {
|
||||||
|
input := map[string]interface{}{
|
||||||
|
"discovery": map[string]interface{}{
|
||||||
|
"host": "localhost",
|
||||||
|
"port": 8080,
|
||||||
|
},
|
||||||
|
"component": map[string]interface{}{
|
||||||
|
"name": "test",
|
||||||
|
},
|
||||||
|
}
|
||||||
|
valuer := recursiveValuer{
|
||||||
|
current: mapValuer(input["component"].(map[string]interface{})),
|
||||||
|
parent: simpleValuer{
|
||||||
|
current: mapValuer(input),
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
val, ok := valuer.Value("discovery")
|
||||||
|
assert.True(t, ok)
|
||||||
|
|
||||||
|
m, ok := val.(map[string]interface{})
|
||||||
|
assert.True(t, ok)
|
||||||
|
assert.Equal(t, "localhost", m["host"])
|
||||||
|
assert.Equal(t, 8080, m["port"])
|
||||||
|
}
|
||||||
@@ -1,101 +1,27 @@
|
|||||||
package mapping
|
package mapping
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"encoding/json"
|
|
||||||
"errors"
|
|
||||||
"io"
|
"io"
|
||||||
|
|
||||||
"gopkg.in/yaml.v2"
|
"github.com/zeromicro/go-zero/internal/encoding"
|
||||||
)
|
|
||||||
|
|
||||||
// To make .json & .yaml consistent, we just use json as the tag key.
|
|
||||||
const yamlTagKey = "json"
|
|
||||||
|
|
||||||
var (
|
|
||||||
// ErrUnsupportedType is an error that indicates the config format is not supported.
|
|
||||||
ErrUnsupportedType = errors.New("only map-like configs are supported")
|
|
||||||
|
|
||||||
yamlUnmarshaler = NewUnmarshaler(yamlTagKey)
|
|
||||||
)
|
)
|
||||||
|
|
||||||
// UnmarshalYamlBytes unmarshals content into v.
|
// UnmarshalYamlBytes unmarshals content into v.
|
||||||
func UnmarshalYamlBytes(content []byte, v interface{}) error {
|
func UnmarshalYamlBytes(content []byte, v interface{}, opts ...UnmarshalOption) error {
|
||||||
return unmarshalYamlBytes(content, v, yamlUnmarshaler)
|
b, err := encoding.YamlToJson(content)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
return UnmarshalJsonBytes(b, v, opts...)
|
||||||
}
|
}
|
||||||
|
|
||||||
// UnmarshalYamlReader unmarshals content from reader into v.
|
// UnmarshalYamlReader unmarshals content from reader into v.
|
||||||
func UnmarshalYamlReader(reader io.Reader, v interface{}) error {
|
func UnmarshalYamlReader(reader io.Reader, v interface{}, opts ...UnmarshalOption) error {
|
||||||
return unmarshalYamlReader(reader, v, yamlUnmarshaler)
|
b, err := io.ReadAll(reader)
|
||||||
}
|
if err != nil {
|
||||||
|
|
||||||
func cleanupInterfaceMap(in map[interface{}]interface{}) map[string]interface{} {
|
|
||||||
res := make(map[string]interface{})
|
|
||||||
for k, v := range in {
|
|
||||||
res[Repr(k)] = cleanupMapValue(v)
|
|
||||||
}
|
|
||||||
return res
|
|
||||||
}
|
|
||||||
|
|
||||||
func cleanupInterfaceNumber(in interface{}) json.Number {
|
|
||||||
return json.Number(Repr(in))
|
|
||||||
}
|
|
||||||
|
|
||||||
func cleanupInterfaceSlice(in []interface{}) []interface{} {
|
|
||||||
res := make([]interface{}, len(in))
|
|
||||||
for i, v := range in {
|
|
||||||
res[i] = cleanupMapValue(v)
|
|
||||||
}
|
|
||||||
return res
|
|
||||||
}
|
|
||||||
|
|
||||||
func cleanupMapValue(v interface{}) interface{} {
|
|
||||||
switch v := v.(type) {
|
|
||||||
case []interface{}:
|
|
||||||
return cleanupInterfaceSlice(v)
|
|
||||||
case map[interface{}]interface{}:
|
|
||||||
return cleanupInterfaceMap(v)
|
|
||||||
case bool, string:
|
|
||||||
return v
|
|
||||||
case int, uint, int8, uint8, int16, uint16, int32, uint32, int64, uint64, float32, float64:
|
|
||||||
return cleanupInterfaceNumber(v)
|
|
||||||
default:
|
|
||||||
return Repr(v)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func unmarshal(unmarshaler *Unmarshaler, o interface{}, v interface{}) error {
|
|
||||||
if m, ok := o.(map[string]interface{}); ok {
|
|
||||||
return unmarshaler.Unmarshal(m, v)
|
|
||||||
}
|
|
||||||
|
|
||||||
return ErrUnsupportedType
|
|
||||||
}
|
|
||||||
|
|
||||||
func unmarshalYamlBytes(content []byte, v interface{}, unmarshaler *Unmarshaler) error {
|
|
||||||
var o interface{}
|
|
||||||
if err := yamlUnmarshal(content, &o); err != nil {
|
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
return unmarshal(unmarshaler, o, v)
|
return UnmarshalYamlBytes(b, v, opts...)
|
||||||
}
|
|
||||||
|
|
||||||
func unmarshalYamlReader(reader io.Reader, v interface{}, unmarshaler *Unmarshaler) error {
|
|
||||||
var res interface{}
|
|
||||||
if err := yaml.NewDecoder(reader).Decode(&res); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
return unmarshal(unmarshaler, cleanupMapValue(res), v)
|
|
||||||
}
|
|
||||||
|
|
||||||
// yamlUnmarshal YAML to map[string]interface{} instead of map[interface{}]interface{}.
|
|
||||||
func yamlUnmarshal(in []byte, out interface{}) error {
|
|
||||||
var res interface{}
|
|
||||||
if err := yaml.Unmarshal(in, &res); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
*out.(*interface{}) = cleanupMapValue(res)
|
|
||||||
return nil
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -934,9 +934,8 @@ func TestUnmarshalYamlReaderError(t *testing.T) {
|
|||||||
err := UnmarshalYamlReader(reader, &v)
|
err := UnmarshalYamlReader(reader, &v)
|
||||||
assert.NotNil(t, err)
|
assert.NotNil(t, err)
|
||||||
|
|
||||||
reader = strings.NewReader("chenquan")
|
reader = strings.NewReader("foo")
|
||||||
err = UnmarshalYamlReader(reader, &v)
|
assert.Error(t, UnmarshalYamlReader(reader, &v))
|
||||||
assert.ErrorIs(t, err, ErrUnsupportedType)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestUnmarshalYamlBadReader(t *testing.T) {
|
func TestUnmarshalYamlBadReader(t *testing.T) {
|
||||||
@@ -1012,6 +1011,13 @@ func TestUnmarshalYamlMapRune(t *testing.T) {
|
|||||||
assert.Equal(t, rune(3), v.Machine["node3"])
|
assert.Equal(t, rune(3), v.Machine["node3"])
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestUnmarshalYamlBadInput(t *testing.T) {
|
||||||
|
var v struct {
|
||||||
|
Any string
|
||||||
|
}
|
||||||
|
assert.Error(t, UnmarshalYamlBytes([]byte("':foo"), &v))
|
||||||
|
}
|
||||||
|
|
||||||
type badReader struct{}
|
type badReader struct{}
|
||||||
|
|
||||||
func (b *badReader) Read(_ []byte) (n int, err error) {
|
func (b *badReader) Read(_ []byte) (n int, err error) {
|
||||||
|
|||||||
@@ -6,14 +6,14 @@ import (
|
|||||||
"time"
|
"time"
|
||||||
)
|
)
|
||||||
|
|
||||||
// A Unstable is used to generate random value around the mean value base on given deviation.
|
// An Unstable is used to generate random value around the mean value base on given deviation.
|
||||||
type Unstable struct {
|
type Unstable struct {
|
||||||
deviation float64
|
deviation float64
|
||||||
r *rand.Rand
|
r *rand.Rand
|
||||||
lock *sync.Mutex
|
lock *sync.Mutex
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewUnstable returns a Unstable.
|
// NewUnstable returns an Unstable.
|
||||||
func NewUnstable(deviation float64) Unstable {
|
func NewUnstable(deviation float64) Unstable {
|
||||||
if deviation < 0 {
|
if deviation < 0 {
|
||||||
deviation = 0
|
deviation = 0
|
||||||
|
|||||||
@@ -145,7 +145,7 @@ func MapReduceChan(source <-chan interface{}, mapper MapperFunc, reducer Reducer
|
|||||||
return mapReduceWithPanicChan(source, panicChan, mapper, reducer, opts...)
|
return mapReduceWithPanicChan(source, panicChan, mapper, reducer, opts...)
|
||||||
}
|
}
|
||||||
|
|
||||||
// MapReduceChan maps all elements from source, and reduce the output elements with given reducer.
|
// mapReduceWithPanicChan maps all elements from source, and reduce the output elements with given reducer.
|
||||||
func mapReduceWithPanicChan(source <-chan interface{}, panicChan *onceChan, mapper MapperFunc,
|
func mapReduceWithPanicChan(source <-chan interface{}, panicChan *onceChan, mapper MapperFunc,
|
||||||
reducer ReducerFunc, opts ...Option) (interface{}, error) {
|
reducer ReducerFunc, opts ...Option) (interface{}, error) {
|
||||||
options := buildOptions(opts...)
|
options := buildOptions(opts...)
|
||||||
|
|||||||
@@ -19,7 +19,7 @@ func FuzzMapReduce(f *testing.F) {
|
|||||||
rand.Seed(time.Now().UnixNano())
|
rand.Seed(time.Now().UnixNano())
|
||||||
|
|
||||||
f.Add(uint(10), uint(runtime.NumCPU()))
|
f.Add(uint(10), uint(runtime.NumCPU()))
|
||||||
f.Fuzz(func(t *testing.T, num uint, workers uint) {
|
f.Fuzz(func(t *testing.T, num, workers uint) {
|
||||||
n := int64(num)%5000 + 5000
|
n := int64(num)%5000 + 5000
|
||||||
genPanic := rand.Intn(100) == 0
|
genPanic := rand.Intn(100) == 0
|
||||||
mapperPanic := rand.Intn(100) == 0
|
mapperPanic := rand.Intn(100) == 0
|
||||||
|
|||||||
@@ -4,7 +4,8 @@ import "github.com/zeromicro/go-zero/core/logx"
|
|||||||
|
|
||||||
// Recover is used with defer to do cleanup on panics.
|
// Recover is used with defer to do cleanup on panics.
|
||||||
// Use it like:
|
// Use it like:
|
||||||
// defer Recover(func() {})
|
//
|
||||||
|
// defer Recover(func() {})
|
||||||
func Recover(cleanups ...func()) {
|
func Recover(cleanups ...func()) {
|
||||||
for _, cleanup := range cleanups {
|
for _, cleanup := range cleanups {
|
||||||
cleanup()
|
cleanup()
|
||||||
|
|||||||
@@ -9,6 +9,7 @@ import (
|
|||||||
"github.com/zeromicro/go-zero/core/prometheus"
|
"github.com/zeromicro/go-zero/core/prometheus"
|
||||||
"github.com/zeromicro/go-zero/core/stat"
|
"github.com/zeromicro/go-zero/core/stat"
|
||||||
"github.com/zeromicro/go-zero/core/trace"
|
"github.com/zeromicro/go-zero/core/trace"
|
||||||
|
"github.com/zeromicro/go-zero/internal/devserver"
|
||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
@@ -28,10 +29,12 @@ const (
|
|||||||
type ServiceConf struct {
|
type ServiceConf struct {
|
||||||
Name string
|
Name string
|
||||||
Log logx.LogConf
|
Log logx.LogConf
|
||||||
Mode string `json:",default=pro,options=dev|test|rt|pre|pro"`
|
Mode string `json:",default=pro,options=dev|test|rt|pre|pro"`
|
||||||
MetricsUrl string `json:",optional"`
|
MetricsUrl string `json:",optional"`
|
||||||
|
// Deprecated: please use DevServer
|
||||||
Prometheus prometheus.Config `json:",optional"`
|
Prometheus prometheus.Config `json:",optional"`
|
||||||
Telemetry trace.Config `json:",optional"`
|
Telemetry trace.Config `json:",optional"`
|
||||||
|
DevServer devserver.Config `json:",optional"`
|
||||||
}
|
}
|
||||||
|
|
||||||
// MustSetUp sets up the service, exits on error.
|
// MustSetUp sets up the service, exits on error.
|
||||||
@@ -64,6 +67,7 @@ func (sc ServiceConf) SetUp() error {
|
|||||||
if len(sc.MetricsUrl) > 0 {
|
if len(sc.MetricsUrl) > 0 {
|
||||||
stat.SetReportWriter(stat.NewRemoteWriter(sc.MetricsUrl))
|
stat.SetReportWriter(stat.NewRemoteWriter(sc.MetricsUrl))
|
||||||
}
|
}
|
||||||
|
devserver.StartAgent(sc.DevServer)
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -46,14 +46,14 @@ func Report(msg string) {
|
|||||||
if fn != nil {
|
if fn != nil {
|
||||||
reported := lessExecutor.DoOrDiscard(func() {
|
reported := lessExecutor.DoOrDiscard(func() {
|
||||||
var builder strings.Builder
|
var builder strings.Builder
|
||||||
fmt.Fprintf(&builder, "%s\n", time.Now().Format(timeFormat))
|
builder.WriteString(fmt.Sprintln(time.Now().Format(timeFormat)))
|
||||||
if len(clusterName) > 0 {
|
if len(clusterName) > 0 {
|
||||||
fmt.Fprintf(&builder, "cluster: %s\n", clusterName)
|
builder.WriteString(fmt.Sprintf("cluster: %s\n", clusterName))
|
||||||
}
|
}
|
||||||
fmt.Fprintf(&builder, "host: %s\n", sysx.Hostname())
|
builder.WriteString(fmt.Sprintf("host: %s\n", sysx.Hostname()))
|
||||||
dp := atomic.SwapInt32(&dropped, 0)
|
dp := atomic.SwapInt32(&dropped, 0)
|
||||||
if dp > 0 {
|
if dp > 0 {
|
||||||
fmt.Fprintf(&builder, "dropped: %d\n", dp)
|
builder.WriteString(fmt.Sprintf("dropped: %d\n", dp))
|
||||||
}
|
}
|
||||||
builder.WriteString(strings.TrimSpace(msg))
|
builder.WriteString(strings.TrimSpace(msg))
|
||||||
fn(builder.String())
|
fn(builder.String())
|
||||||
|
|||||||
@@ -4,6 +4,7 @@
|
|||||||
package stat
|
package stat
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"os"
|
||||||
"strconv"
|
"strconv"
|
||||||
"sync/atomic"
|
"sync/atomic"
|
||||||
"testing"
|
"testing"
|
||||||
@@ -12,6 +13,9 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
func TestReport(t *testing.T) {
|
func TestReport(t *testing.T) {
|
||||||
|
os.Setenv(clusterNameKey, "test-cluster")
|
||||||
|
defer os.Unsetenv(clusterNameKey)
|
||||||
|
|
||||||
var count int32
|
var count int32
|
||||||
SetReporter(func(s string) {
|
SetReporter(func(s string) {
|
||||||
atomic.AddInt32(&count, 1)
|
atomic.AddInt32(&count, 1)
|
||||||
|
|||||||
@@ -258,7 +258,7 @@ func parseUints(val string) ([]uint64, error) {
|
|||||||
return sets, nil
|
return sets, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// runningInUserNS detects whether we are currently running in a user namespace.
|
// runningInUserNS detects whether we are currently running in an user namespace.
|
||||||
func runningInUserNS() bool {
|
func runningInUserNS() bool {
|
||||||
nsOnce.Do(func() {
|
nsOnce.Do(func() {
|
||||||
file, err := os.Open("/proc/self/uid_map")
|
file, err := os.Open("/proc/self/uid_map")
|
||||||
|
|||||||
@@ -33,13 +33,7 @@ func initialize() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
cores = uint64(len(cpus))
|
cores = uint64(len(cpus))
|
||||||
sets, err := cpuSets()
|
quota = float64(len(cpus))
|
||||||
if err != nil {
|
|
||||||
logx.Error(err)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
quota = float64(len(sets))
|
|
||||||
cq, err := cpuQuota()
|
cq, err := cpuQuota()
|
||||||
if err == nil {
|
if err == nil {
|
||||||
if cq != -1 {
|
if cq != -1 {
|
||||||
|
|||||||
4
core/stores/cache/cacheopt.go
vendored
4
core/stores/cache/cacheopt.go
vendored
@@ -34,14 +34,14 @@ func newOptions(opts ...Option) Options {
|
|||||||
return o
|
return o
|
||||||
}
|
}
|
||||||
|
|
||||||
// WithExpiry returns a func to customize a Options with given expiry.
|
// WithExpiry returns a func to customize an Options with given expiry.
|
||||||
func WithExpiry(expiry time.Duration) Option {
|
func WithExpiry(expiry time.Duration) Option {
|
||||||
return func(o *Options) {
|
return func(o *Options) {
|
||||||
o.Expiry = expiry
|
o.Expiry = expiry
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// WithNotFoundExpiry returns a func to customize a Options with given not found expiry.
|
// WithNotFoundExpiry returns a func to customize an Options with given not found expiry.
|
||||||
func WithNotFoundExpiry(expiry time.Duration) Option {
|
func WithNotFoundExpiry(expiry time.Duration) Option {
|
||||||
return func(o *Options) {
|
return func(o *Options) {
|
||||||
o.NotFoundExpiry = expiry
|
o.NotFoundExpiry = expiry
|
||||||
|
|||||||
@@ -83,12 +83,12 @@ type (
|
|||||||
// FindOneAndReplace returns at most one document that matches the filter. If the filter
|
// FindOneAndReplace returns at most one document that matches the filter. If the filter
|
||||||
// matches multiple documents, FindOneAndReplace returns the first document in the
|
// matches multiple documents, FindOneAndReplace returns the first document in the
|
||||||
// collection that matches the filter.
|
// collection that matches the filter.
|
||||||
FindOneAndReplace(ctx context.Context, filter interface{}, replacement interface{},
|
FindOneAndReplace(ctx context.Context, filter, replacement interface{},
|
||||||
opts ...*mopt.FindOneAndReplaceOptions) (*mongo.SingleResult, error)
|
opts ...*mopt.FindOneAndReplaceOptions) (*mongo.SingleResult, error)
|
||||||
// FindOneAndUpdate returns at most one document that matches the filter. If the filter
|
// FindOneAndUpdate returns at most one document that matches the filter. If the filter
|
||||||
// matches multiple documents, FindOneAndUpdate returns the first document in the
|
// matches multiple documents, FindOneAndUpdate returns the first document in the
|
||||||
// collection that matches the filter.
|
// collection that matches the filter.
|
||||||
FindOneAndUpdate(ctx context.Context, filter interface{}, update interface{},
|
FindOneAndUpdate(ctx context.Context, filter, update interface{},
|
||||||
opts ...*mopt.FindOneAndUpdateOptions) (*mongo.SingleResult, error)
|
opts ...*mopt.FindOneAndUpdateOptions) (*mongo.SingleResult, error)
|
||||||
// Indexes returns the index view for this collection.
|
// Indexes returns the index view for this collection.
|
||||||
Indexes() mongo.IndexView
|
Indexes() mongo.IndexView
|
||||||
@@ -99,16 +99,16 @@ type (
|
|||||||
InsertOne(ctx context.Context, document interface{}, opts ...*mopt.InsertOneOptions) (
|
InsertOne(ctx context.Context, document interface{}, opts ...*mopt.InsertOneOptions) (
|
||||||
*mongo.InsertOneResult, error)
|
*mongo.InsertOneResult, error)
|
||||||
// ReplaceOne replaces at most one document that matches the filter.
|
// ReplaceOne replaces at most one document that matches the filter.
|
||||||
ReplaceOne(ctx context.Context, filter interface{}, replacement interface{},
|
ReplaceOne(ctx context.Context, filter, replacement interface{},
|
||||||
opts ...*mopt.ReplaceOptions) (*mongo.UpdateResult, error)
|
opts ...*mopt.ReplaceOptions) (*mongo.UpdateResult, error)
|
||||||
// UpdateByID updates a single document matching the provided filter.
|
// UpdateByID updates a single document matching the provided filter.
|
||||||
UpdateByID(ctx context.Context, id interface{}, update interface{},
|
UpdateByID(ctx context.Context, id, update interface{},
|
||||||
opts ...*mopt.UpdateOptions) (*mongo.UpdateResult, error)
|
opts ...*mopt.UpdateOptions) (*mongo.UpdateResult, error)
|
||||||
// UpdateMany updates the provided documents.
|
// UpdateMany updates the provided documents.
|
||||||
UpdateMany(ctx context.Context, filter interface{}, update interface{},
|
UpdateMany(ctx context.Context, filter, update interface{},
|
||||||
opts ...*mopt.UpdateOptions) (*mongo.UpdateResult, error)
|
opts ...*mopt.UpdateOptions) (*mongo.UpdateResult, error)
|
||||||
// UpdateOne updates a single document matching the provided filter.
|
// UpdateOne updates a single document matching the provided filter.
|
||||||
UpdateOne(ctx context.Context, filter interface{}, update interface{},
|
UpdateOne(ctx context.Context, filter, update interface{},
|
||||||
opts ...*mopt.UpdateOptions) (*mongo.UpdateResult, error)
|
opts ...*mopt.UpdateOptions) (*mongo.UpdateResult, error)
|
||||||
// Watch returns a change stream cursor used to receive notifications of changes to the collection.
|
// Watch returns a change stream cursor used to receive notifications of changes to the collection.
|
||||||
Watch(ctx context.Context, pipeline interface{}, opts ...*mopt.ChangeStreamOptions) (
|
Watch(ctx context.Context, pipeline interface{}, opts ...*mopt.ChangeStreamOptions) (
|
||||||
@@ -359,7 +359,7 @@ func (c *decoratedCollection) FindOneAndReplace(ctx context.Context, filter inte
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *decoratedCollection) FindOneAndUpdate(ctx context.Context, filter interface{}, update interface{},
|
func (c *decoratedCollection) FindOneAndUpdate(ctx context.Context, filter, update interface{},
|
||||||
opts ...*mopt.FindOneAndUpdateOptions) (res *mongo.SingleResult, err error) {
|
opts ...*mopt.FindOneAndUpdateOptions) (res *mongo.SingleResult, err error) {
|
||||||
ctx, span := startSpan(ctx, findOneAndUpdate)
|
ctx, span := startSpan(ctx, findOneAndUpdate)
|
||||||
defer func() {
|
defer func() {
|
||||||
@@ -420,7 +420,7 @@ func (c *decoratedCollection) InsertOne(ctx context.Context, document interface{
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *decoratedCollection) ReplaceOne(ctx context.Context, filter interface{}, replacement interface{},
|
func (c *decoratedCollection) ReplaceOne(ctx context.Context, filter, replacement interface{},
|
||||||
opts ...*mopt.ReplaceOptions) (res *mongo.UpdateResult, err error) {
|
opts ...*mopt.ReplaceOptions) (res *mongo.UpdateResult, err error) {
|
||||||
ctx, span := startSpan(ctx, replaceOne)
|
ctx, span := startSpan(ctx, replaceOne)
|
||||||
defer func() {
|
defer func() {
|
||||||
@@ -440,7 +440,7 @@ func (c *decoratedCollection) ReplaceOne(ctx context.Context, filter interface{}
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *decoratedCollection) UpdateByID(ctx context.Context, id interface{}, update interface{},
|
func (c *decoratedCollection) UpdateByID(ctx context.Context, id, update interface{},
|
||||||
opts ...*mopt.UpdateOptions) (res *mongo.UpdateResult, err error) {
|
opts ...*mopt.UpdateOptions) (res *mongo.UpdateResult, err error) {
|
||||||
ctx, span := startSpan(ctx, updateByID)
|
ctx, span := startSpan(ctx, updateByID)
|
||||||
defer func() {
|
defer func() {
|
||||||
@@ -460,7 +460,7 @@ func (c *decoratedCollection) UpdateByID(ctx context.Context, id interface{}, up
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *decoratedCollection) UpdateMany(ctx context.Context, filter interface{}, update interface{},
|
func (c *decoratedCollection) UpdateMany(ctx context.Context, filter, update interface{},
|
||||||
opts ...*mopt.UpdateOptions) (res *mongo.UpdateResult, err error) {
|
opts ...*mopt.UpdateOptions) (res *mongo.UpdateResult, err error) {
|
||||||
ctx, span := startSpan(ctx, updateMany)
|
ctx, span := startSpan(ctx, updateMany)
|
||||||
defer func() {
|
defer func() {
|
||||||
@@ -480,7 +480,7 @@ func (c *decoratedCollection) UpdateMany(ctx context.Context, filter interface{}
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *decoratedCollection) UpdateOne(ctx context.Context, filter interface{}, update interface{},
|
func (c *decoratedCollection) UpdateOne(ctx context.Context, filter, update interface{},
|
||||||
opts ...*mopt.UpdateOptions) (res *mongo.UpdateResult, err error) {
|
opts ...*mopt.UpdateOptions) (res *mongo.UpdateResult, err error) {
|
||||||
ctx, span := startSpan(ctx, updateOne)
|
ctx, span := startSpan(ctx, updateOne)
|
||||||
defer func() {
|
defer func() {
|
||||||
|
|||||||
@@ -106,14 +106,14 @@ func TestCollection_BulkWrite(t *testing.T) {
|
|||||||
}
|
}
|
||||||
mt.AddMockResponses(mtest.CreateSuccessResponse(bson.D{{Key: "ok", Value: 1}}...))
|
mt.AddMockResponses(mtest.CreateSuccessResponse(bson.D{{Key: "ok", Value: 1}}...))
|
||||||
res, err := c.BulkWrite(context.Background(), []mongo.WriteModel{
|
res, err := c.BulkWrite(context.Background(), []mongo.WriteModel{
|
||||||
mongo.NewInsertOneModel().SetDocument(bson.D{{Key: "foo", Value: 1}})},
|
mongo.NewInsertOneModel().SetDocument(bson.D{{Key: "foo", Value: 1}}),
|
||||||
)
|
})
|
||||||
assert.Nil(t, err)
|
assert.Nil(t, err)
|
||||||
assert.NotNil(t, res)
|
assert.NotNil(t, res)
|
||||||
c.brk = new(dropBreaker)
|
c.brk = new(dropBreaker)
|
||||||
_, err = c.BulkWrite(context.Background(), []mongo.WriteModel{
|
_, err = c.BulkWrite(context.Background(), []mongo.WriteModel{
|
||||||
mongo.NewInsertOneModel().SetDocument(bson.D{{Key: "foo", Value: 1}})},
|
mongo.NewInsertOneModel().SetDocument(bson.D{{Key: "foo", Value: 1}}),
|
||||||
)
|
})
|
||||||
assert.Equal(t, errDummy, err)
|
assert.Equal(t, errDummy, err)
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
@@ -204,7 +204,7 @@ func TestCollection_EstimatedDocumentCount(t *testing.T) {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestCollectionFind(t *testing.T) {
|
func TestCollection_Find(t *testing.T) {
|
||||||
mt := mtest.New(t, mtest.NewOptions().ClientType(mtest.Mock))
|
mt := mtest.New(t, mtest.NewOptions().ClientType(mtest.Mock))
|
||||||
defer mt.Close()
|
defer mt.Close()
|
||||||
|
|
||||||
@@ -252,7 +252,7 @@ func TestCollectionFind(t *testing.T) {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestCollectionFindOne(t *testing.T) {
|
func TestCollection_FindOne(t *testing.T) {
|
||||||
mt := mtest.New(t, mtest.NewOptions().ClientType(mtest.Mock))
|
mt := mtest.New(t, mtest.NewOptions().ClientType(mtest.Mock))
|
||||||
defer mt.Close()
|
defer mt.Close()
|
||||||
|
|
||||||
@@ -436,7 +436,7 @@ func TestCollection_InsertMany(t *testing.T) {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestCollection_Remove(t *testing.T) {
|
func TestCollection_DeleteOne(t *testing.T) {
|
||||||
mt := mtest.New(t, mtest.NewOptions().ClientType(mtest.Mock))
|
mt := mtest.New(t, mtest.NewOptions().ClientType(mtest.Mock))
|
||||||
defer mt.Close()
|
defer mt.Close()
|
||||||
|
|
||||||
@@ -456,7 +456,7 @@ func TestCollection_Remove(t *testing.T) {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestCollectionRemoveAll(t *testing.T) {
|
func TestCollection_DeleteMany(t *testing.T) {
|
||||||
mt := mtest.New(t, mtest.NewOptions().ClientType(mtest.Mock))
|
mt := mtest.New(t, mtest.NewOptions().ClientType(mtest.Mock))
|
||||||
defer mt.Close()
|
defer mt.Close()
|
||||||
|
|
||||||
@@ -565,7 +565,7 @@ func TestCollection_UpdateMany(t *testing.T) {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
func Test_DecoratedCollectionLogDuration(t *testing.T) {
|
func TestDecoratedCollection_LogDuration(t *testing.T) {
|
||||||
mt := mtest.New(t, mtest.NewOptions().ClientType(mtest.Mock))
|
mt := mtest.New(t, mtest.NewOptions().ClientType(mtest.Mock))
|
||||||
defer mt.Close()
|
defer mt.Close()
|
||||||
c := decoratedCollection{
|
c := decoratedCollection{
|
||||||
|
|||||||
@@ -159,7 +159,7 @@ func (m *Model) FindOneAndDelete(ctx context.Context, v, filter interface{},
|
|||||||
}
|
}
|
||||||
|
|
||||||
// FindOneAndReplace finds a single document and replaces it.
|
// FindOneAndReplace finds a single document and replaces it.
|
||||||
func (m *Model) FindOneAndReplace(ctx context.Context, v, filter interface{}, replacement interface{},
|
func (m *Model) FindOneAndReplace(ctx context.Context, v, filter, replacement interface{},
|
||||||
opts ...*mopt.FindOneAndReplaceOptions) error {
|
opts ...*mopt.FindOneAndReplaceOptions) error {
|
||||||
res, err := m.Collection.FindOneAndReplace(ctx, filter, replacement, opts...)
|
res, err := m.Collection.FindOneAndReplace(ctx, filter, replacement, opts...)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@@ -170,7 +170,7 @@ func (m *Model) FindOneAndReplace(ctx context.Context, v, filter interface{}, re
|
|||||||
}
|
}
|
||||||
|
|
||||||
// FindOneAndUpdate finds a single document and updates it.
|
// FindOneAndUpdate finds a single document and updates it.
|
||||||
func (m *Model) FindOneAndUpdate(ctx context.Context, v, filter interface{}, update interface{},
|
func (m *Model) FindOneAndUpdate(ctx context.Context, v, filter, update interface{},
|
||||||
opts ...*mopt.FindOneAndUpdateOptions) error {
|
opts ...*mopt.FindOneAndUpdateOptions) error {
|
||||||
res, err := m.Collection.FindOneAndUpdate(ctx, filter, update, opts...)
|
res, err := m.Collection.FindOneAndUpdate(ctx, filter, update, opts...)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|||||||
@@ -192,7 +192,7 @@ func (mm *Model) InsertOneNoCache(ctx context.Context, document interface{},
|
|||||||
}
|
}
|
||||||
|
|
||||||
// ReplaceOne replaces a single document in the collection, and remove the cache.
|
// ReplaceOne replaces a single document in the collection, and remove the cache.
|
||||||
func (mm *Model) ReplaceOne(ctx context.Context, key string, filter interface{}, replacement interface{},
|
func (mm *Model) ReplaceOne(ctx context.Context, key string, filter, replacement interface{},
|
||||||
opts ...*mopt.ReplaceOptions) (*mongo.UpdateResult, error) {
|
opts ...*mopt.ReplaceOptions) (*mongo.UpdateResult, error) {
|
||||||
res, err := mm.Model.ReplaceOne(ctx, filter, replacement, opts...)
|
res, err := mm.Model.ReplaceOne(ctx, filter, replacement, opts...)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@@ -207,7 +207,7 @@ func (mm *Model) ReplaceOne(ctx context.Context, key string, filter interface{},
|
|||||||
}
|
}
|
||||||
|
|
||||||
// ReplaceOneNoCache replaces a single document in the collection.
|
// ReplaceOneNoCache replaces a single document in the collection.
|
||||||
func (mm *Model) ReplaceOneNoCache(ctx context.Context, filter interface{}, replacement interface{},
|
func (mm *Model) ReplaceOneNoCache(ctx context.Context, filter, replacement interface{},
|
||||||
opts ...*mopt.ReplaceOptions) (*mongo.UpdateResult, error) {
|
opts ...*mopt.ReplaceOptions) (*mongo.UpdateResult, error) {
|
||||||
return mm.Model.ReplaceOne(ctx, filter, replacement, opts...)
|
return mm.Model.ReplaceOne(ctx, filter, replacement, opts...)
|
||||||
}
|
}
|
||||||
@@ -218,7 +218,7 @@ func (mm *Model) SetCache(key string, v interface{}) error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// UpdateByID updates the document with given id with update, and remove the cache.
|
// UpdateByID updates the document with given id with update, and remove the cache.
|
||||||
func (mm *Model) UpdateByID(ctx context.Context, key string, id interface{}, update interface{},
|
func (mm *Model) UpdateByID(ctx context.Context, key string, id, update interface{},
|
||||||
opts ...*mopt.UpdateOptions) (*mongo.UpdateResult, error) {
|
opts ...*mopt.UpdateOptions) (*mongo.UpdateResult, error) {
|
||||||
res, err := mm.Model.UpdateByID(ctx, id, update, opts...)
|
res, err := mm.Model.UpdateByID(ctx, id, update, opts...)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@@ -233,13 +233,13 @@ func (mm *Model) UpdateByID(ctx context.Context, key string, id interface{}, upd
|
|||||||
}
|
}
|
||||||
|
|
||||||
// UpdateByIDNoCache updates the document with given id with update.
|
// UpdateByIDNoCache updates the document with given id with update.
|
||||||
func (mm *Model) UpdateByIDNoCache(ctx context.Context, id interface{}, update interface{},
|
func (mm *Model) UpdateByIDNoCache(ctx context.Context, id, update interface{},
|
||||||
opts ...*mopt.UpdateOptions) (*mongo.UpdateResult, error) {
|
opts ...*mopt.UpdateOptions) (*mongo.UpdateResult, error) {
|
||||||
return mm.Model.UpdateByID(ctx, id, update, opts...)
|
return mm.Model.UpdateByID(ctx, id, update, opts...)
|
||||||
}
|
}
|
||||||
|
|
||||||
// UpdateMany updates the documents that match filter with update, and remove the cache.
|
// UpdateMany updates the documents that match filter with update, and remove the cache.
|
||||||
func (mm *Model) UpdateMany(ctx context.Context, keys []string, filter interface{}, update interface{},
|
func (mm *Model) UpdateMany(ctx context.Context, keys []string, filter, update interface{},
|
||||||
opts ...*mopt.UpdateOptions) (*mongo.UpdateResult, error) {
|
opts ...*mopt.UpdateOptions) (*mongo.UpdateResult, error) {
|
||||||
res, err := mm.Model.UpdateMany(ctx, filter, update, opts...)
|
res, err := mm.Model.UpdateMany(ctx, filter, update, opts...)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@@ -254,13 +254,13 @@ func (mm *Model) UpdateMany(ctx context.Context, keys []string, filter interface
|
|||||||
}
|
}
|
||||||
|
|
||||||
// UpdateManyNoCache updates the documents that match filter with update.
|
// UpdateManyNoCache updates the documents that match filter with update.
|
||||||
func (mm *Model) UpdateManyNoCache(ctx context.Context, filter interface{}, update interface{},
|
func (mm *Model) UpdateManyNoCache(ctx context.Context, filter, update interface{},
|
||||||
opts ...*mopt.UpdateOptions) (*mongo.UpdateResult, error) {
|
opts ...*mopt.UpdateOptions) (*mongo.UpdateResult, error) {
|
||||||
return mm.Model.UpdateMany(ctx, filter, update, opts...)
|
return mm.Model.UpdateMany(ctx, filter, update, opts...)
|
||||||
}
|
}
|
||||||
|
|
||||||
// UpdateOne updates the first document that matches filter with update, and remove the cache.
|
// UpdateOne updates the first document that matches filter with update, and remove the cache.
|
||||||
func (mm *Model) UpdateOne(ctx context.Context, key string, filter interface{}, update interface{},
|
func (mm *Model) UpdateOne(ctx context.Context, key string, filter, update interface{},
|
||||||
opts ...*mopt.UpdateOptions) (*mongo.UpdateResult, error) {
|
opts ...*mopt.UpdateOptions) (*mongo.UpdateResult, error) {
|
||||||
res, err := mm.Model.UpdateOne(ctx, filter, update, opts...)
|
res, err := mm.Model.UpdateOne(ctx, filter, update, opts...)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@@ -275,7 +275,7 @@ func (mm *Model) UpdateOne(ctx context.Context, key string, filter interface{},
|
|||||||
}
|
}
|
||||||
|
|
||||||
// UpdateOneNoCache updates the first document that matches filter with update.
|
// UpdateOneNoCache updates the first document that matches filter with update.
|
||||||
func (mm *Model) UpdateOneNoCache(ctx context.Context, filter interface{}, update interface{},
|
func (mm *Model) UpdateOneNoCache(ctx context.Context, filter, update interface{},
|
||||||
opts ...*mopt.UpdateOptions) (*mongo.UpdateResult, error) {
|
opts ...*mopt.UpdateOptions) (*mongo.UpdateResult, error) {
|
||||||
return mm.Model.UpdateOne(ctx, filter, update, opts...)
|
return mm.Model.UpdateOne(ctx, filter, update, opts...)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,10 +2,13 @@ package redis
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
|
"io"
|
||||||
|
"net"
|
||||||
"strings"
|
"strings"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
red "github.com/go-redis/redis/v8"
|
red "github.com/go-redis/redis/v8"
|
||||||
|
"github.com/zeromicro/go-zero/core/breaker"
|
||||||
"github.com/zeromicro/go-zero/core/errorx"
|
"github.com/zeromicro/go-zero/core/errorx"
|
||||||
"github.com/zeromicro/go-zero/core/logx"
|
"github.com/zeromicro/go-zero/core/logx"
|
||||||
"github.com/zeromicro/go-zero/core/mapping"
|
"github.com/zeromicro/go-zero/core/mapping"
|
||||||
@@ -53,7 +56,7 @@ func (h hook) AfterProcess(ctx context.Context, cmd red.Cmder) error {
|
|||||||
|
|
||||||
duration := timex.Since(start)
|
duration := timex.Since(start)
|
||||||
if duration > slowThreshold.Load() {
|
if duration > slowThreshold.Load() {
|
||||||
logDuration(ctx, cmd, duration)
|
logDuration(ctx, []red.Cmder{cmd}, duration)
|
||||||
}
|
}
|
||||||
|
|
||||||
metricReqDur.Observe(int64(duration/time.Millisecond), cmd.Name())
|
metricReqDur.Observe(int64(duration/time.Millisecond), cmd.Name())
|
||||||
@@ -100,7 +103,7 @@ func (h hook) AfterProcessPipeline(ctx context.Context, cmds []red.Cmder) error
|
|||||||
|
|
||||||
duration := timex.Since(start)
|
duration := timex.Since(start)
|
||||||
if duration > slowThreshold.Load()*time.Duration(len(cmds)) {
|
if duration > slowThreshold.Load()*time.Duration(len(cmds)) {
|
||||||
logDuration(ctx, cmds[0], duration)
|
logDuration(ctx, cmds, duration)
|
||||||
}
|
}
|
||||||
|
|
||||||
metricReqDur.Observe(int64(duration/time.Millisecond), "Pipeline")
|
metricReqDur.Observe(int64(duration/time.Millisecond), "Pipeline")
|
||||||
@@ -116,37 +119,37 @@ func formatError(err error) string {
|
|||||||
return ""
|
return ""
|
||||||
}
|
}
|
||||||
|
|
||||||
es := err.Error()
|
opErr, ok := err.(*net.OpError)
|
||||||
switch {
|
if ok && opErr.Timeout() {
|
||||||
case strings.HasPrefix(es, "read"):
|
return "timeout"
|
||||||
return "read timeout"
|
}
|
||||||
case strings.HasPrefix(es, "dial"):
|
|
||||||
if strings.Contains(es, "connection refused") {
|
switch err {
|
||||||
return "connection refused"
|
case io.EOF:
|
||||||
}
|
|
||||||
return "dial timeout"
|
|
||||||
case strings.HasPrefix(es, "write"):
|
|
||||||
return "write timeout"
|
|
||||||
case strings.Contains(es, "EOF"):
|
|
||||||
return "eof"
|
return "eof"
|
||||||
case strings.Contains(es, "reset"):
|
case context.DeadlineExceeded:
|
||||||
return "reset"
|
return "context deadline"
|
||||||
case strings.Contains(es, "broken"):
|
case breaker.ErrServiceUnavailable:
|
||||||
return "broken pipe"
|
|
||||||
case strings.Contains(es, "breaker"):
|
|
||||||
return "breaker"
|
return "breaker"
|
||||||
default:
|
default:
|
||||||
return "unexpected error"
|
return "unexpected error"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func logDuration(ctx context.Context, cmd red.Cmder, duration time.Duration) {
|
func logDuration(ctx context.Context, cmds []red.Cmder, duration time.Duration) {
|
||||||
var buf strings.Builder
|
var buf strings.Builder
|
||||||
for i, arg := range cmd.Args() {
|
for k, cmd := range cmds {
|
||||||
if i > 0 {
|
if k > 0 {
|
||||||
buf.WriteByte(' ')
|
buf.WriteByte('\n')
|
||||||
}
|
}
|
||||||
buf.WriteString(mapping.Repr(arg))
|
var build strings.Builder
|
||||||
|
for i, arg := range cmd.Args() {
|
||||||
|
if i > 0 {
|
||||||
|
build.WriteByte(' ')
|
||||||
|
}
|
||||||
|
build.WriteString(mapping.Repr(arg))
|
||||||
|
}
|
||||||
|
buf.WriteString(build.String())
|
||||||
}
|
}
|
||||||
logx.WithContext(ctx).WithDuration(duration).Slowf("[REDIS] slowcall on executing: %s", buf.String())
|
logx.WithContext(ctx).WithDuration(duration).Slowf("[REDIS] slowcall on executing: %s", buf.String())
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -91,10 +91,10 @@ func TestHookProcessPipelineCase1(t *testing.T) {
|
|||||||
log.SetOutput(&buf)
|
log.SetOutput(&buf)
|
||||||
defer log.SetOutput(writer)
|
defer log.SetOutput(writer)
|
||||||
|
|
||||||
ctx, err := durationHook.BeforeProcessPipeline(context.Background(), []red.Cmder{red.NewCmd(context.Background())})
|
ctx, err := durationHook.BeforeProcessPipeline(context.Background(), []red.Cmder{
|
||||||
if err != nil {
|
red.NewCmd(context.Background()),
|
||||||
t.Fatal(err)
|
})
|
||||||
}
|
assert.NoError(t, err)
|
||||||
assert.Equal(t, "redis", tracesdk.SpanFromContext(ctx).(interface{ Name() string }).Name())
|
assert.Equal(t, "redis", tracesdk.SpanFromContext(ctx).(interface{ Name() string }).Name())
|
||||||
|
|
||||||
assert.Nil(t, durationHook.AfterProcessPipeline(ctx, []red.Cmder{
|
assert.Nil(t, durationHook.AfterProcessPipeline(ctx, []red.Cmder{
|
||||||
@@ -115,10 +115,10 @@ func TestHookProcessPipelineCase2(t *testing.T) {
|
|||||||
w, restore := injectLog()
|
w, restore := injectLog()
|
||||||
defer restore()
|
defer restore()
|
||||||
|
|
||||||
ctx, err := durationHook.BeforeProcessPipeline(context.Background(), []red.Cmder{red.NewCmd(context.Background())})
|
ctx, err := durationHook.BeforeProcessPipeline(context.Background(), []red.Cmder{
|
||||||
if err != nil {
|
red.NewCmd(context.Background()),
|
||||||
t.Fatal(err)
|
})
|
||||||
}
|
assert.NoError(t, err)
|
||||||
assert.Equal(t, "redis", tracesdk.SpanFromContext(ctx).(interface{ Name() string }).Name())
|
assert.Equal(t, "redis", tracesdk.SpanFromContext(ctx).(interface{ Name() string }).Name())
|
||||||
|
|
||||||
time.Sleep(slowThreshold.Load() + time.Millisecond)
|
time.Sleep(slowThreshold.Load() + time.Millisecond)
|
||||||
@@ -159,10 +159,28 @@ func TestHookProcessPipelineCase5(t *testing.T) {
|
|||||||
defer log.SetOutput(writer)
|
defer log.SetOutput(writer)
|
||||||
|
|
||||||
ctx := context.WithValue(context.Background(), startTimeKey, "foo")
|
ctx := context.WithValue(context.Background(), startTimeKey, "foo")
|
||||||
assert.Nil(t, durationHook.AfterProcessPipeline(ctx, []red.Cmder{red.NewCmd(context.Background())}))
|
assert.Nil(t, durationHook.AfterProcessPipeline(ctx, []red.Cmder{
|
||||||
|
red.NewCmd(context.Background()),
|
||||||
|
}))
|
||||||
assert.True(t, buf.Len() == 0)
|
assert.True(t, buf.Len() == 0)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestLogDuration(t *testing.T) {
|
||||||
|
w, restore := injectLog()
|
||||||
|
defer restore()
|
||||||
|
|
||||||
|
logDuration(context.Background(), []red.Cmder{
|
||||||
|
red.NewCmd(context.Background(), "get", "foo"),
|
||||||
|
}, 1*time.Second)
|
||||||
|
assert.True(t, strings.Contains(w.String(), "get foo"))
|
||||||
|
|
||||||
|
logDuration(context.Background(), []red.Cmder{
|
||||||
|
red.NewCmd(context.Background(), "get", "foo"),
|
||||||
|
red.NewCmd(context.Background(), "set", "bar", 0),
|
||||||
|
}, 1*time.Second)
|
||||||
|
assert.True(t, strings.Contains(w.String(), `get foo\nset bar 0`))
|
||||||
|
}
|
||||||
|
|
||||||
func injectLog() (r *strings.Builder, restore func()) {
|
func injectLog() (r *strings.Builder, restore func()) {
|
||||||
var buf strings.Builder
|
var buf strings.Builder
|
||||||
w := logx.NewWriter(&buf)
|
w := logx.NewWriter(&buf)
|
||||||
|
|||||||
@@ -226,20 +226,7 @@ func (s *Redis) Blpop(node RedisNode, key string) (string, error) {
|
|||||||
// BlpopCtx uses passed in redis connection to execute blocking queries.
|
// BlpopCtx uses passed in redis connection to execute blocking queries.
|
||||||
// Doesn't benefit from pooling redis connections of blocking queries
|
// Doesn't benefit from pooling redis connections of blocking queries
|
||||||
func (s *Redis) BlpopCtx(ctx context.Context, node RedisNode, key string) (string, error) {
|
func (s *Redis) BlpopCtx(ctx context.Context, node RedisNode, key string) (string, error) {
|
||||||
if node == nil {
|
return s.BlpopWithTimeoutCtx(ctx, node, blockingQueryTimeout, key)
|
||||||
return "", ErrNilNode
|
|
||||||
}
|
|
||||||
|
|
||||||
vals, err := node.BLPop(ctx, blockingQueryTimeout, key).Result()
|
|
||||||
if err != nil {
|
|
||||||
return "", err
|
|
||||||
}
|
|
||||||
|
|
||||||
if len(vals) < 2 {
|
|
||||||
return "", fmt.Errorf("no value on key: %s", key)
|
|
||||||
}
|
|
||||||
|
|
||||||
return vals[1], nil
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// BlpopEx uses passed in redis connection to execute blpop command.
|
// BlpopEx uses passed in redis connection to execute blpop command.
|
||||||
@@ -267,6 +254,32 @@ func (s *Redis) BlpopExCtx(ctx context.Context, node RedisNode, key string) (str
|
|||||||
return vals[1], true, nil
|
return vals[1], true, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// BlpopWithTimeout uses passed in redis connection to execute blpop command.
|
||||||
|
// Control blocking query timeout
|
||||||
|
func (s *Redis) BlpopWithTimeout(node RedisNode, timeout time.Duration, key string) (string, error) {
|
||||||
|
return s.BlpopWithTimeoutCtx(context.Background(), node, timeout, key)
|
||||||
|
}
|
||||||
|
|
||||||
|
// BlpopWithTimeoutCtx uses passed in redis connection to execute blpop command.
|
||||||
|
// Control blocking query timeout
|
||||||
|
func (s *Redis) BlpopWithTimeoutCtx(ctx context.Context, node RedisNode, timeout time.Duration,
|
||||||
|
key string) (string, error) {
|
||||||
|
if node == nil {
|
||||||
|
return "", ErrNilNode
|
||||||
|
}
|
||||||
|
|
||||||
|
vals, err := node.BLPop(ctx, timeout, key).Result()
|
||||||
|
if err != nil {
|
||||||
|
return "", err
|
||||||
|
}
|
||||||
|
|
||||||
|
if len(vals) < 2 {
|
||||||
|
return "", fmt.Errorf("no value on key: %s", key)
|
||||||
|
}
|
||||||
|
|
||||||
|
return vals[1], nil
|
||||||
|
}
|
||||||
|
|
||||||
// Decr is the implementation of redis decr command.
|
// Decr is the implementation of redis decr command.
|
||||||
func (s *Redis) Decr(key string) (int64, error) {
|
func (s *Redis) Decr(key string) (int64, error) {
|
||||||
return s.DecrCtx(context.Background(), key)
|
return s.DecrCtx(context.Background(), key)
|
||||||
|
|||||||
@@ -1117,6 +1117,17 @@ func TestRedisBlpopEx(t *testing.T) {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestRedisBlpopWithTimeout(t *testing.T) {
|
||||||
|
runOnRedis(t, func(client *Redis) {
|
||||||
|
client.Ping()
|
||||||
|
var node mockedNode
|
||||||
|
_, err := client.BlpopWithTimeout(nil, 10*time.Second, "foo")
|
||||||
|
assert.NotNil(t, err)
|
||||||
|
_, err = client.BlpopWithTimeout(node, 10*time.Second, "foo")
|
||||||
|
assert.NotNil(t, err)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
func TestRedisGeo(t *testing.T) {
|
func TestRedisGeo(t *testing.T) {
|
||||||
runOnRedis(t, func(client *Redis) {
|
runOnRedis(t, func(client *Redis) {
|
||||||
client.Ping()
|
client.Ping()
|
||||||
|
|||||||
@@ -8,7 +8,7 @@ import (
|
|||||||
"github.com/zeromicro/go-zero/core/stores/redis"
|
"github.com/zeromicro/go-zero/core/stores/redis"
|
||||||
)
|
)
|
||||||
|
|
||||||
// CreateRedis returns a in process redis.Redis.
|
// CreateRedis returns an in process redis.Redis.
|
||||||
func CreateRedis() (r *redis.Redis, clean func(), err error) {
|
func CreateRedis() (r *redis.Redis, clean func(), err error) {
|
||||||
mr, err := miniredis.Run()
|
mr, err := miniredis.Run()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|||||||
@@ -8,7 +8,7 @@ var (
|
|||||||
metricReqDur = metric.NewHistogramVec(&metric.HistogramVecOpts{
|
metricReqDur = metric.NewHistogramVec(&metric.HistogramVecOpts{
|
||||||
Namespace: namespace,
|
Namespace: namespace,
|
||||||
Subsystem: "requests",
|
Subsystem: "requests",
|
||||||
Name: "durations_ms",
|
Name: "duration_ms",
|
||||||
Help: "mysql client requests duration(ms).",
|
Help: "mysql client requests duration(ms).",
|
||||||
Labels: []string{"command"},
|
Labels: []string{"command"},
|
||||||
Buckets: []float64{5, 10, 25, 50, 100, 250, 500, 1000, 2500},
|
Buckets: []float64{5, 10, 25, 50, 100, 250, 500, 1000, 2500},
|
||||||
|
|||||||
@@ -2,6 +2,7 @@ package stringx
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"errors"
|
"errors"
|
||||||
|
"unicode"
|
||||||
|
|
||||||
"github.com/zeromicro/go-zero/core/lang"
|
"github.com/zeromicro/go-zero/core/lang"
|
||||||
)
|
)
|
||||||
@@ -69,6 +70,33 @@ func HasEmpty(args ...string) bool {
|
|||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Join joins any number of elements into a single string, separating them with given sep.
|
||||||
|
// Empty elements are ignored. However, if the argument list is empty or all its elements are empty,
|
||||||
|
// Join returns an empty string.
|
||||||
|
func Join(sep byte, elem ...string) string {
|
||||||
|
var size int
|
||||||
|
for _, e := range elem {
|
||||||
|
size += len(e)
|
||||||
|
}
|
||||||
|
if size == 0 {
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
|
||||||
|
buf := make([]byte, 0, size+len(elem)-1)
|
||||||
|
for _, e := range elem {
|
||||||
|
if len(e) == 0 {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
if len(buf) > 0 {
|
||||||
|
buf = append(buf, sep)
|
||||||
|
}
|
||||||
|
buf = append(buf, e...)
|
||||||
|
}
|
||||||
|
|
||||||
|
return string(buf)
|
||||||
|
}
|
||||||
|
|
||||||
// NotEmpty checks if all strings are not empty in args.
|
// NotEmpty checks if all strings are not empty in args.
|
||||||
func NotEmpty(args ...string) bool {
|
func NotEmpty(args ...string) bool {
|
||||||
return !HasEmpty(args...)
|
return !HasEmpty(args...)
|
||||||
@@ -141,6 +169,15 @@ func TakeWithPriority(fns ...func() string) string {
|
|||||||
return ""
|
return ""
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ToCamelCase returns the string that converts the first letter to lowercase.
|
||||||
|
func ToCamelCase(s string) string {
|
||||||
|
for i, v := range s {
|
||||||
|
return string(unicode.ToLower(v)) + s[i+1:]
|
||||||
|
}
|
||||||
|
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
|
||||||
// Union merges the strings in first and second.
|
// Union merges the strings in first and second.
|
||||||
func Union(first, second []string) []string {
|
func Union(first, second []string) []string {
|
||||||
set := make(map[string]lang.PlaceholderType)
|
set := make(map[string]lang.PlaceholderType)
|
||||||
|
|||||||
@@ -147,6 +147,42 @@ func TestFirstN(t *testing.T) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestJoin(t *testing.T) {
|
||||||
|
tests := []struct {
|
||||||
|
name string
|
||||||
|
input []string
|
||||||
|
expect string
|
||||||
|
}{
|
||||||
|
{
|
||||||
|
name: "all blanks",
|
||||||
|
input: []string{"", ""},
|
||||||
|
expect: "",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "two values",
|
||||||
|
input: []string{"012", "abc"},
|
||||||
|
expect: "012.abc",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "last blank",
|
||||||
|
input: []string{"abc", ""},
|
||||||
|
expect: "abc",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "first blank",
|
||||||
|
input: []string{"", "abc"},
|
||||||
|
expect: "abc",
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, test := range tests {
|
||||||
|
test := test
|
||||||
|
t.Run(test.name, func(t *testing.T) {
|
||||||
|
assert.Equal(t, test.expect, Join('.', test.input...))
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
func TestRemove(t *testing.T) {
|
func TestRemove(t *testing.T) {
|
||||||
cases := []struct {
|
cases := []struct {
|
||||||
input []string
|
input []string
|
||||||
@@ -360,6 +396,61 @@ func TestTakeWithPriority(t *testing.T) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestToCamelCase(t *testing.T) {
|
||||||
|
tests := []struct {
|
||||||
|
input string
|
||||||
|
expect string
|
||||||
|
}{
|
||||||
|
{
|
||||||
|
input: "",
|
||||||
|
expect: "",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
input: "A",
|
||||||
|
expect: "a",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
input: "a",
|
||||||
|
expect: "a",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
input: "hello_world",
|
||||||
|
expect: "hello_world",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
input: "Hello_world",
|
||||||
|
expect: "hello_world",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
input: "hello_World",
|
||||||
|
expect: "hello_World",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
input: "helloWorld",
|
||||||
|
expect: "helloWorld",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
input: "HelloWorld",
|
||||||
|
expect: "helloWorld",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
input: "hello World",
|
||||||
|
expect: "hello World",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
input: "Hello World",
|
||||||
|
expect: "hello World",
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, test := range tests {
|
||||||
|
test := test
|
||||||
|
t.Run(test.input, func(t *testing.T) {
|
||||||
|
assert.Equal(t, test.expect, ToCamelCase(test.input))
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
func TestUnion(t *testing.T) {
|
func TestUnion(t *testing.T) {
|
||||||
first := []string{
|
first := []string{
|
||||||
"one",
|
"one",
|
||||||
|
|||||||
@@ -2,7 +2,7 @@ package syncx
|
|||||||
|
|
||||||
import "sync/atomic"
|
import "sync/atomic"
|
||||||
|
|
||||||
// A OnceGuard is used to make sure a resource can be taken once.
|
// An OnceGuard is used to make sure a resource can be taken once.
|
||||||
type OnceGuard struct {
|
type OnceGuard struct {
|
||||||
done uint32
|
done uint32
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -29,7 +29,7 @@ var (
|
|||||||
tp *sdktrace.TracerProvider
|
tp *sdktrace.TracerProvider
|
||||||
)
|
)
|
||||||
|
|
||||||
// StartAgent starts a opentelemetry agent.
|
// StartAgent starts an opentelemetry agent.
|
||||||
func StartAgent(c Config) {
|
func StartAgent(c Config) {
|
||||||
lock.Lock()
|
lock.Lock()
|
||||||
defer lock.Unlock()
|
defer lock.Unlock()
|
||||||
|
|||||||
@@ -3,7 +3,7 @@ package trace
|
|||||||
// TraceName represents the tracing name.
|
// TraceName represents the tracing name.
|
||||||
const TraceName = "go-zero"
|
const TraceName = "go-zero"
|
||||||
|
|
||||||
// A Config is a opentelemetry config.
|
// A Config is an opentelemetry config.
|
||||||
type Config struct {
|
type Config struct {
|
||||||
Name string `json:",optional"`
|
Name string `json:",optional"`
|
||||||
Endpoint string `json:",optional"`
|
Endpoint string `json:",optional"`
|
||||||
|
|||||||
@@ -5,6 +5,7 @@ import (
|
|||||||
"net"
|
"net"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
|
ztrace "github.com/zeromicro/go-zero/internal/trace"
|
||||||
"go.opentelemetry.io/otel/attribute"
|
"go.opentelemetry.io/otel/attribute"
|
||||||
semconv "go.opentelemetry.io/otel/semconv/v1.4.0"
|
semconv "go.opentelemetry.io/otel/semconv/v1.4.0"
|
||||||
"google.golang.org/grpc/peer"
|
"google.golang.org/grpc/peer"
|
||||||
@@ -12,6 +13,13 @@ import (
|
|||||||
|
|
||||||
const localhost = "127.0.0.1"
|
const localhost = "127.0.0.1"
|
||||||
|
|
||||||
|
var (
|
||||||
|
// SpanIDFromContext returns the span id from ctx.
|
||||||
|
SpanIDFromContext = ztrace.SpanIDFromContext
|
||||||
|
// TraceIDFromContext returns the trace id from ctx.
|
||||||
|
TraceIDFromContext = ztrace.TraceIDFromContext
|
||||||
|
)
|
||||||
|
|
||||||
// PeerFromCtx returns the peer from ctx.
|
// PeerFromCtx returns the peer from ctx.
|
||||||
func PeerFromCtx(ctx context.Context) string {
|
func PeerFromCtx(ctx context.Context) string {
|
||||||
p, ok := peer.FromContext(ctx)
|
p, ok := peer.FromContext(ctx)
|
||||||
|
|||||||
@@ -7,12 +7,12 @@ import (
|
|||||||
"github.com/zeromicro/go-zero/core/timex"
|
"github.com/zeromicro/go-zero/core/timex"
|
||||||
)
|
)
|
||||||
|
|
||||||
// A ElapsedTimer is a timer to track the elapsed time.
|
// An ElapsedTimer is a timer to track the elapsed time.
|
||||||
type ElapsedTimer struct {
|
type ElapsedTimer struct {
|
||||||
start time.Duration
|
start time.Duration
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewElapsedTimer returns a ElapsedTimer.
|
// NewElapsedTimer returns an ElapsedTimer.
|
||||||
func NewElapsedTimer() *ElapsedTimer {
|
func NewElapsedTimer() *ElapsedTimer {
|
||||||
return &ElapsedTimer{
|
return &ElapsedTimer{
|
||||||
start: timex.Now(),
|
start: timex.Now(),
|
||||||
|
|||||||
@@ -2,7 +2,7 @@ package utils
|
|||||||
|
|
||||||
import "github.com/google/uuid"
|
import "github.com/google/uuid"
|
||||||
|
|
||||||
// NewUuid returns a uuid string.
|
// NewUuid returns an uuid string.
|
||||||
func NewUuid() string {
|
func NewUuid() string {
|
||||||
return uuid.New().String()
|
return uuid.New().String()
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -27,15 +27,6 @@ func NewEventHandler(writer io.Writer, resolver jsonpb.AnyResolver) *EventHandle
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (h *EventHandler) OnResolveMethod(_ *desc.MethodDescriptor) {
|
|
||||||
}
|
|
||||||
|
|
||||||
func (h *EventHandler) OnSendHeaders(_ metadata.MD) {
|
|
||||||
}
|
|
||||||
|
|
||||||
func (h *EventHandler) OnReceiveHeaders(_ metadata.MD) {
|
|
||||||
}
|
|
||||||
|
|
||||||
func (h *EventHandler) OnReceiveResponse(message proto.Message) {
|
func (h *EventHandler) OnReceiveResponse(message proto.Message) {
|
||||||
if err := h.marshaler.Marshal(h.writer, message); err != nil {
|
if err := h.marshaler.Marshal(h.writer, message); err != nil {
|
||||||
logx.Error(err)
|
logx.Error(err)
|
||||||
@@ -45,3 +36,12 @@ func (h *EventHandler) OnReceiveResponse(message proto.Message) {
|
|||||||
func (h *EventHandler) OnReceiveTrailers(status *status.Status, _ metadata.MD) {
|
func (h *EventHandler) OnReceiveTrailers(status *status.Status, _ metadata.MD) {
|
||||||
h.Status = status
|
h.Status = status
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (h *EventHandler) OnResolveMethod(_ *desc.MethodDescriptor) {
|
||||||
|
}
|
||||||
|
|
||||||
|
func (h *EventHandler) OnSendHeaders(_ metadata.MD) {
|
||||||
|
}
|
||||||
|
|
||||||
|
func (h *EventHandler) OnReceiveHeaders(_ metadata.MD) {
|
||||||
|
}
|
||||||
|
|||||||
20
gateway/internal/eventhandler_test.go
Normal file
20
gateway/internal/eventhandler_test.go
Normal file
@@ -0,0 +1,20 @@
|
|||||||
|
package internal
|
||||||
|
|
||||||
|
import (
|
||||||
|
"io"
|
||||||
|
"testing"
|
||||||
|
|
||||||
|
"github.com/stretchr/testify/assert"
|
||||||
|
"google.golang.org/grpc/codes"
|
||||||
|
"google.golang.org/grpc/status"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestEventHandler(t *testing.T) {
|
||||||
|
h := NewEventHandler(io.Discard, nil)
|
||||||
|
h.OnResolveMethod(nil)
|
||||||
|
h.OnSendHeaders(nil)
|
||||||
|
h.OnReceiveHeaders(nil)
|
||||||
|
h.OnReceiveTrailers(status.New(codes.OK, ""), nil)
|
||||||
|
assert.Equal(t, codes.OK, h.Status.Code())
|
||||||
|
h.OnReceiveResponse(nil)
|
||||||
|
}
|
||||||
@@ -1,6 +1,7 @@
|
|||||||
package internal
|
package internal
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"net/http"
|
||||||
"net/http/httptest"
|
"net/http/httptest"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
@@ -8,13 +9,13 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
func TestBuildHeadersNoValue(t *testing.T) {
|
func TestBuildHeadersNoValue(t *testing.T) {
|
||||||
req := httptest.NewRequest("GET", "/", nil)
|
req := httptest.NewRequest("GET", "/", http.NoBody)
|
||||||
req.Header.Add("a", "b")
|
req.Header.Add("a", "b")
|
||||||
assert.Nil(t, ProcessHeaders(req.Header))
|
assert.Nil(t, ProcessHeaders(req.Header))
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestBuildHeadersWithValues(t *testing.T) {
|
func TestBuildHeadersWithValues(t *testing.T) {
|
||||||
req := httptest.NewRequest("GET", "/", nil)
|
req := httptest.NewRequest("GET", "/", http.NoBody)
|
||||||
req.Header.Add("grpc-metadata-a", "b")
|
req.Header.Add("grpc-metadata-a", "b")
|
||||||
req.Header.Add("grpc-metadata-b", "b")
|
req.Header.Add("grpc-metadata-b", "b")
|
||||||
assert.ElementsMatch(t, []string{"gateway-A:b", "gateway-B:b"}, ProcessHeaders(req.Header))
|
assert.ElementsMatch(t, []string{"gateway-A:b", "gateway-B:b"}, ProcessHeaders(req.Header))
|
||||||
|
|||||||
@@ -3,6 +3,7 @@ package internal
|
|||||||
import (
|
import (
|
||||||
"bytes"
|
"bytes"
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
|
"io"
|
||||||
"net/http"
|
"net/http"
|
||||||
|
|
||||||
"github.com/fullstorydev/grpcurl"
|
"github.com/fullstorydev/grpcurl"
|
||||||
@@ -22,16 +23,18 @@ func NewRequestParser(r *http.Request, resolver jsonpb.AnyResolver) (grpcurl.Req
|
|||||||
for k, v := range vars {
|
for k, v := range vars {
|
||||||
params[k] = v
|
params[k] = v
|
||||||
}
|
}
|
||||||
if len(params) == 0 {
|
|
||||||
return grpcurl.NewJSONRequestParser(r.Body, resolver), nil
|
|
||||||
}
|
|
||||||
|
|
||||||
if r.ContentLength == 0 {
|
body, ok := getBody(r)
|
||||||
|
if !ok {
|
||||||
return buildJsonRequestParser(params, resolver)
|
return buildJsonRequestParser(params, resolver)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if len(params) == 0 {
|
||||||
|
return grpcurl.NewJSONRequestParser(body, resolver), nil
|
||||||
|
}
|
||||||
|
|
||||||
m := make(map[string]interface{})
|
m := make(map[string]interface{})
|
||||||
if err := json.NewDecoder(r.Body).Decode(&m); err != nil {
|
if err := json.NewDecoder(body).Decode(&m); err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -51,3 +54,28 @@ func buildJsonRequestParser(m map[string]interface{}, resolver jsonpb.AnyResolve
|
|||||||
|
|
||||||
return grpcurl.NewJSONRequestParser(&buf, resolver), nil
|
return grpcurl.NewJSONRequestParser(&buf, resolver), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func getBody(r *http.Request) (io.Reader, bool) {
|
||||||
|
if r.Body == nil {
|
||||||
|
return nil, false
|
||||||
|
}
|
||||||
|
|
||||||
|
if r.ContentLength == 0 {
|
||||||
|
return nil, false
|
||||||
|
}
|
||||||
|
|
||||||
|
if r.ContentLength > 0 {
|
||||||
|
return r.Body, true
|
||||||
|
}
|
||||||
|
|
||||||
|
var buf bytes.Buffer
|
||||||
|
if _, err := io.Copy(&buf, r.Body); err != nil {
|
||||||
|
return nil, false
|
||||||
|
}
|
||||||
|
|
||||||
|
if buf.Len() > 0 {
|
||||||
|
return &buf, true
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil, false
|
||||||
|
}
|
||||||
|
|||||||
@@ -1,6 +1,8 @@
|
|||||||
package internal
|
package internal
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"errors"
|
||||||
|
"net/http"
|
||||||
"net/http/httptest"
|
"net/http/httptest"
|
||||||
"strings"
|
"strings"
|
||||||
"testing"
|
"testing"
|
||||||
@@ -10,14 +12,14 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
func TestNewRequestParserNoVar(t *testing.T) {
|
func TestNewRequestParserNoVar(t *testing.T) {
|
||||||
req := httptest.NewRequest("GET", "/", nil)
|
req := httptest.NewRequest("GET", "/", http.NoBody)
|
||||||
parser, err := NewRequestParser(req, nil)
|
parser, err := NewRequestParser(req, nil)
|
||||||
assert.Nil(t, err)
|
assert.Nil(t, err)
|
||||||
assert.NotNil(t, parser)
|
assert.NotNil(t, parser)
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestNewRequestParserWithVars(t *testing.T) {
|
func TestNewRequestParserWithVars(t *testing.T) {
|
||||||
req := httptest.NewRequest("GET", "/", nil)
|
req := httptest.NewRequest("GET", "/", http.NoBody)
|
||||||
req = pathvar.WithVars(req, map[string]string{"a": "b"})
|
req = pathvar.WithVars(req, map[string]string{"a": "b"})
|
||||||
parser, err := NewRequestParser(req, nil)
|
parser, err := NewRequestParser(req, nil)
|
||||||
assert.Nil(t, err)
|
assert.Nil(t, err)
|
||||||
@@ -31,6 +33,14 @@ func TestNewRequestParserNoVarWithBody(t *testing.T) {
|
|||||||
assert.NotNil(t, parser)
|
assert.NotNil(t, parser)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestNewRequestParserWithNegativeContentLength(t *testing.T) {
|
||||||
|
req := httptest.NewRequest("GET", "/", strings.NewReader(`{"a": "b"}`))
|
||||||
|
req.ContentLength = -1
|
||||||
|
parser, err := NewRequestParser(req, nil)
|
||||||
|
assert.Nil(t, err)
|
||||||
|
assert.NotNil(t, parser)
|
||||||
|
}
|
||||||
|
|
||||||
func TestNewRequestParserWithVarsWithBody(t *testing.T) {
|
func TestNewRequestParserWithVarsWithBody(t *testing.T) {
|
||||||
req := httptest.NewRequest("GET", "/", strings.NewReader(`{"a": "b"}`))
|
req := httptest.NewRequest("GET", "/", strings.NewReader(`{"a": "b"}`))
|
||||||
req = pathvar.WithVars(req, map[string]string{"c": "d"})
|
req = pathvar.WithVars(req, map[string]string{"c": "d"})
|
||||||
@@ -53,3 +63,37 @@ func TestNewRequestParserWithForm(t *testing.T) {
|
|||||||
assert.Nil(t, err)
|
assert.Nil(t, err)
|
||||||
assert.NotNil(t, parser)
|
assert.NotNil(t, parser)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestNewRequestParserWithNilBody(t *testing.T) {
|
||||||
|
req := httptest.NewRequest("GET", "/val?a=b", http.NoBody)
|
||||||
|
req.Body = nil
|
||||||
|
parser, err := NewRequestParser(req, nil)
|
||||||
|
assert.Nil(t, err)
|
||||||
|
assert.NotNil(t, parser)
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestNewRequestParserWithBadBody(t *testing.T) {
|
||||||
|
req := httptest.NewRequest("GET", "/val?a=b", badBody{})
|
||||||
|
req.Body = badBody{}
|
||||||
|
parser, err := NewRequestParser(req, nil)
|
||||||
|
assert.Nil(t, err)
|
||||||
|
assert.NotNil(t, parser)
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestNewRequestParserWithBadForm(t *testing.T) {
|
||||||
|
req := httptest.NewRequest("GET", "/val?a%1=b", http.NoBody)
|
||||||
|
parser, err := NewRequestParser(req, nil)
|
||||||
|
assert.NotNil(t, err)
|
||||||
|
assert.Nil(t, parser)
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestRequestParser_buildJsonRequestParser(t *testing.T) {
|
||||||
|
parser, err := buildJsonRequestParser(map[string]interface{}{"a": make(chan int)}, nil)
|
||||||
|
assert.NotNil(t, err)
|
||||||
|
assert.Nil(t, parser)
|
||||||
|
}
|
||||||
|
|
||||||
|
type badBody struct{}
|
||||||
|
|
||||||
|
func (badBody) Read([]byte) (int, error) { return 0, errors.New("something bad") }
|
||||||
|
func (badBody) Close() error { return nil }
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
package internal
|
package internal
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"net/http"
|
||||||
"net/http/httptest"
|
"net/http/httptest"
|
||||||
"testing"
|
"testing"
|
||||||
"time"
|
"time"
|
||||||
@@ -9,14 +10,14 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
func TestGetTimeout(t *testing.T) {
|
func TestGetTimeout(t *testing.T) {
|
||||||
req := httptest.NewRequest("GET", "/", nil)
|
req := httptest.NewRequest("GET", "/", http.NoBody)
|
||||||
req.Header.Set(grpcTimeoutHeader, "1s")
|
req.Header.Set(grpcTimeoutHeader, "1s")
|
||||||
timeout := GetTimeout(req.Header, time.Second*5)
|
timeout := GetTimeout(req.Header, time.Second*5)
|
||||||
assert.Equal(t, time.Second, timeout)
|
assert.Equal(t, time.Second, timeout)
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestGetTimeoutDefault(t *testing.T) {
|
func TestGetTimeoutDefault(t *testing.T) {
|
||||||
req := httptest.NewRequest("GET", "/", nil)
|
req := httptest.NewRequest("GET", "/", http.NoBody)
|
||||||
timeout := GetTimeout(req.Header, time.Second*5)
|
timeout := GetTimeout(req.Header, time.Second*5)
|
||||||
assert.Equal(t, time.Second*5, timeout)
|
assert.Equal(t, time.Second*5, timeout)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -122,7 +122,7 @@ func (s *Server) buildHandler(source grpcurl.DescriptorSource, resolver jsonpb.A
|
|||||||
return func(w http.ResponseWriter, r *http.Request) {
|
return func(w http.ResponseWriter, r *http.Request) {
|
||||||
parser, err := internal.NewRequestParser(r, resolver)
|
parser, err := internal.NewRequestParser(r, resolver)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
httpx.Error(w, err)
|
httpx.ErrorCtx(r.Context(), w, err)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -134,12 +134,12 @@ func (s *Server) buildHandler(source grpcurl.DescriptorSource, resolver jsonpb.A
|
|||||||
handler := internal.NewEventHandler(w, resolver)
|
handler := internal.NewEventHandler(w, resolver)
|
||||||
if err := grpcurl.InvokeRPC(ctx, source, cli.Conn(), rpcPath, s.prepareMetadata(r.Header),
|
if err := grpcurl.InvokeRPC(ctx, source, cli.Conn(), rpcPath, s.prepareMetadata(r.Header),
|
||||||
handler, parser.Next); err != nil {
|
handler, parser.Next); err != nil {
|
||||||
httpx.Error(w, err)
|
httpx.ErrorCtx(r.Context(), w, err)
|
||||||
}
|
}
|
||||||
|
|
||||||
st := handler.Status
|
st := handler.Status
|
||||||
if st.Code() != codes.OK {
|
if st.Code() != codes.OK {
|
||||||
httpx.Error(w, st.Err())
|
httpx.ErrorCtx(r.Context(), w, st.Err())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
27
go.mod
27
go.mod
@@ -5,26 +5,26 @@ go 1.16
|
|||||||
require (
|
require (
|
||||||
github.com/ClickHouse/clickhouse-go/v2 v2.0.14
|
github.com/ClickHouse/clickhouse-go/v2 v2.0.14
|
||||||
github.com/DATA-DOG/go-sqlmock v1.5.0
|
github.com/DATA-DOG/go-sqlmock v1.5.0
|
||||||
github.com/alicebob/miniredis/v2 v2.23.0
|
github.com/alicebob/miniredis/v2 v2.23.1
|
||||||
github.com/fatih/color v1.13.0
|
github.com/fatih/color v1.13.0
|
||||||
github.com/fullstorydev/grpcurl v1.8.7
|
github.com/fullstorydev/grpcurl v1.8.7
|
||||||
github.com/globalsign/mgo v0.0.0-20181015135952-eeefdecb41b8
|
github.com/globalsign/mgo v0.0.0-20181015135952-eeefdecb41b8
|
||||||
github.com/go-redis/redis/v8 v8.11.5
|
github.com/go-redis/redis/v8 v8.11.5
|
||||||
github.com/go-sql-driver/mysql v1.6.0
|
github.com/go-sql-driver/mysql v1.7.0
|
||||||
github.com/golang-jwt/jwt/v4 v4.4.2
|
github.com/golang-jwt/jwt/v4 v4.4.3
|
||||||
github.com/golang/mock v1.6.0
|
github.com/golang/mock v1.6.0
|
||||||
github.com/golang/protobuf v1.5.2
|
github.com/golang/protobuf v1.5.2
|
||||||
github.com/google/uuid v1.3.0
|
github.com/google/uuid v1.3.0
|
||||||
github.com/jhump/protoreflect v1.13.0
|
github.com/jhump/protoreflect v1.14.0
|
||||||
github.com/lib/pq v1.10.7
|
github.com/lib/pq v1.10.7
|
||||||
github.com/olekukonko/tablewriter v0.0.5
|
github.com/olekukonko/tablewriter v0.0.5
|
||||||
github.com/pelletier/go-toml/v2 v2.0.5
|
github.com/pelletier/go-toml/v2 v2.0.6
|
||||||
github.com/prometheus/client_golang v1.13.0
|
github.com/prometheus/client_golang v1.13.0
|
||||||
github.com/spaolacci/murmur3 v1.1.0
|
github.com/spaolacci/murmur3 v1.1.0
|
||||||
github.com/stretchr/testify v1.8.0
|
github.com/stretchr/testify v1.8.1
|
||||||
go.etcd.io/etcd/api/v3 v3.5.5
|
go.etcd.io/etcd/api/v3 v3.5.5
|
||||||
go.etcd.io/etcd/client/v3 v3.5.5
|
go.etcd.io/etcd/client/v3 v3.5.5
|
||||||
go.mongodb.org/mongo-driver v1.10.2
|
go.mongodb.org/mongo-driver v1.11.1
|
||||||
go.opentelemetry.io/otel v1.10.0
|
go.opentelemetry.io/otel v1.10.0
|
||||||
go.opentelemetry.io/otel/exporters/jaeger v1.10.0
|
go.opentelemetry.io/otel/exporters/jaeger v1.10.0
|
||||||
go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.10.0
|
go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.10.0
|
||||||
@@ -33,9 +33,10 @@ require (
|
|||||||
go.opentelemetry.io/otel/trace v1.10.0
|
go.opentelemetry.io/otel/trace v1.10.0
|
||||||
go.uber.org/automaxprocs v1.5.1
|
go.uber.org/automaxprocs v1.5.1
|
||||||
go.uber.org/goleak v1.2.0
|
go.uber.org/goleak v1.2.0
|
||||||
golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a
|
golang.org/x/sys v0.0.0-20220728004956-3c1f35247d10
|
||||||
golang.org/x/time v0.0.0-20220411224347-583f2d630306
|
golang.org/x/time v0.3.0
|
||||||
google.golang.org/grpc v1.49.0
|
google.golang.org/genproto v0.0.0-20221111202108-142d8a6fa32e
|
||||||
|
google.golang.org/grpc v1.50.1
|
||||||
google.golang.org/protobuf v1.28.1
|
google.golang.org/protobuf v1.28.1
|
||||||
gopkg.in/cheggaaa/pb.v1 v1.0.28
|
gopkg.in/cheggaaa/pb.v1 v1.0.28
|
||||||
gopkg.in/h2non/gock.v1 v1.1.2
|
gopkg.in/h2non/gock.v1 v1.1.2
|
||||||
@@ -43,17 +44,15 @@ require (
|
|||||||
k8s.io/api v0.22.9
|
k8s.io/api v0.22.9
|
||||||
k8s.io/apimachinery v0.22.9
|
k8s.io/apimachinery v0.22.9
|
||||||
k8s.io/client-go v0.22.9
|
k8s.io/client-go v0.22.9
|
||||||
k8s.io/utils v0.0.0-20220706174534-f6158b442e7c
|
k8s.io/utils v0.0.0-20221108210102-8e77b1f39fe2
|
||||||
)
|
)
|
||||||
|
|
||||||
require (
|
require (
|
||||||
|
github.com/felixge/fgprof v0.9.3
|
||||||
github.com/google/gofuzz v1.2.0 // indirect
|
github.com/google/gofuzz v1.2.0 // indirect
|
||||||
github.com/mattn/go-runewidth v0.0.13 // indirect
|
github.com/mattn/go-runewidth v0.0.13 // indirect
|
||||||
github.com/matttproud/golang_protobuf_extensions v1.0.2-0.20181231171920-c182affec369 // indirect
|
github.com/matttproud/golang_protobuf_extensions v1.0.2-0.20181231171920-c182affec369 // 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.8.0 // indirect
|
||||||
go.uber.org/zap v1.21.0 // indirect
|
go.uber.org/zap v1.21.0 // indirect
|
||||||
golang.org/x/net v0.0.0-20220531201128-c960675eff93 // indirect
|
|
||||||
google.golang.org/genproto v0.0.0-20220602131408-e326c6e8e9c8
|
|
||||||
k8s.io/klog/v2 v2.40.1 // indirect
|
|
||||||
)
|
)
|
||||||
|
|||||||
639
go.sum
639
go.sum
@@ -13,23 +13,352 @@ cloud.google.com/go v0.56.0/go.mod h1:jr7tqZxxKOVYizybht9+26Z/gUq7tiRzu+ACVAMbKV
|
|||||||
cloud.google.com/go v0.57.0/go.mod h1:oXiQ6Rzq3RAkkY7N6t3TcE6jE+CIBBbA36lwQ1JyzZs=
|
cloud.google.com/go v0.57.0/go.mod h1:oXiQ6Rzq3RAkkY7N6t3TcE6jE+CIBBbA36lwQ1JyzZs=
|
||||||
cloud.google.com/go v0.62.0/go.mod h1:jmCYTdRCQuc1PHIIJ/maLInMho30T/Y0M4hTdTShOYc=
|
cloud.google.com/go v0.62.0/go.mod h1:jmCYTdRCQuc1PHIIJ/maLInMho30T/Y0M4hTdTShOYc=
|
||||||
cloud.google.com/go v0.65.0/go.mod h1:O5N8zS7uWy9vkA9vayVHs65eM1ubvY4h553ofrNHObY=
|
cloud.google.com/go v0.65.0/go.mod h1:O5N8zS7uWy9vkA9vayVHs65eM1ubvY4h553ofrNHObY=
|
||||||
|
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.78.0/go.mod h1:QjdrLG0uq+YwhjoVOLsS1t7TW8fs36kLs4XO5R5ECHg=
|
||||||
|
cloud.google.com/go v0.79.0/go.mod h1:3bzgcEeQlzbuEAYu4mrWhKqWjmpprinYgKJLgKHnbb8=
|
||||||
|
cloud.google.com/go v0.81.0/go.mod h1:mk/AM35KwGk/Nm2YSeZbxXdrNK3KZOYHmLkOqC2V6E0=
|
||||||
|
cloud.google.com/go v0.83.0/go.mod h1:Z7MJUsANfY0pYPdw0lbnivPx4/vhy/e2FEkSkF7vAVY=
|
||||||
|
cloud.google.com/go v0.84.0/go.mod h1:RazrYuxIK6Kb7YrzzhPoLmCVzl7Sup4NrbKPg8KHSUM=
|
||||||
|
cloud.google.com/go v0.87.0/go.mod h1:TpDYlFy7vuLzZMMZ+B6iRiELaY7z/gJPaqbMx6mlWcY=
|
||||||
|
cloud.google.com/go v0.90.0/go.mod h1:kRX0mNRHe0e2rC6oNakvwQqzyDmg57xJ+SZU1eT2aDQ=
|
||||||
|
cloud.google.com/go v0.93.3/go.mod h1:8utlLll2EF5XMAV15woO4lSbWQlk8rer9aLOfLh7+YI=
|
||||||
|
cloud.google.com/go v0.94.1/go.mod h1:qAlAugsXlC+JWO+Bke5vCtc9ONxjQT3drlTTnAplMW4=
|
||||||
|
cloud.google.com/go v0.97.0/go.mod h1:GF7l59pYBVlXQIBLx3a761cZ41F9bBH3JUlihCt2Udc=
|
||||||
|
cloud.google.com/go v0.99.0/go.mod h1:w0Xx2nLzqWJPuozYQX+hFfCSI8WioryfRDzkoI/Y2ZA=
|
||||||
|
cloud.google.com/go v0.100.2/go.mod h1:4Xra9TjzAeYHrl5+oeLlzbM2k3mjVhZh4UqTZ//w99A=
|
||||||
|
cloud.google.com/go v0.102.0/go.mod h1:oWcCzKlqJ5zgHQt9YsaeTY9KzIvjyy0ArmiBUgpQ+nc=
|
||||||
|
cloud.google.com/go v0.102.1/go.mod h1:XZ77E9qnTEnrgEOvr4xzfdX5TRo7fB4T2F4O6+34hIU=
|
||||||
|
cloud.google.com/go v0.104.0/go.mod h1:OO6xxXdJyvuJPcEPBLN9BJPD+jep5G1+2U5B5gkRYtA=
|
||||||
|
cloud.google.com/go v0.105.0/go.mod h1:PrLgOJNe5nfE9UMxKxgXj4mD3voiP+YQ6gdt6KMFOKM=
|
||||||
|
cloud.google.com/go/accessapproval v1.4.0/go.mod h1:zybIuC3KpDOvotz59lFe5qxRZx6C75OtwbisN56xYB4=
|
||||||
|
cloud.google.com/go/accessapproval v1.5.0/go.mod h1:HFy3tuiGvMdcd/u+Cu5b9NkO1pEICJ46IR82PoUdplw=
|
||||||
|
cloud.google.com/go/accesscontextmanager v1.3.0/go.mod h1:TgCBehyr5gNMz7ZaH9xubp+CE8dkrszb4oK9CWyvD4o=
|
||||||
|
cloud.google.com/go/accesscontextmanager v1.4.0/go.mod h1:/Kjh7BBu/Gh83sv+K60vN9QE5NJcd80sU33vIe2IFPE=
|
||||||
|
cloud.google.com/go/aiplatform v1.22.0/go.mod h1:ig5Nct50bZlzV6NvKaTwmplLLddFx0YReh9WfTO5jKw=
|
||||||
|
cloud.google.com/go/aiplatform v1.24.0/go.mod h1:67UUvRBKG6GTayHKV8DBv2RtR1t93YRu5B1P3x99mYY=
|
||||||
|
cloud.google.com/go/analytics v0.11.0/go.mod h1:DjEWCu41bVbYcKyvlws9Er60YE4a//bK6mnhWvQeFNI=
|
||||||
|
cloud.google.com/go/analytics v0.12.0/go.mod h1:gkfj9h6XRf9+TS4bmuhPEShsh3hH8PAZzm/41OOhQd4=
|
||||||
|
cloud.google.com/go/apigateway v1.3.0/go.mod h1:89Z8Bhpmxu6AmUxuVRg/ECRGReEdiP3vQtk4Z1J9rJk=
|
||||||
|
cloud.google.com/go/apigateway v1.4.0/go.mod h1:pHVY9MKGaH9PQ3pJ4YLzoj6U5FUDeDFBllIz7WmzJoc=
|
||||||
|
cloud.google.com/go/apigeeconnect v1.3.0/go.mod h1:G/AwXFAKo0gIXkPTVfZDd2qA1TxBXJ3MgMRBQkIi9jc=
|
||||||
|
cloud.google.com/go/apigeeconnect v1.4.0/go.mod h1:kV4NwOKqjvt2JYR0AoIWo2QGfoRtn/pkS3QlHp0Ni04=
|
||||||
|
cloud.google.com/go/appengine v1.4.0/go.mod h1:CS2NhuBuDXM9f+qscZ6V86m1MIIqPj3WC/UoEuR1Sno=
|
||||||
|
cloud.google.com/go/appengine v1.5.0/go.mod h1:TfasSozdkFI0zeoxW3PTBLiNqRmzraodCWatWI9Dmak=
|
||||||
|
cloud.google.com/go/area120 v0.5.0/go.mod h1:DE/n4mp+iqVyvxHN41Vf1CR602GiHQjFPusMFW6bGR4=
|
||||||
|
cloud.google.com/go/area120 v0.6.0/go.mod h1:39yFJqWVgm0UZqWTOdqkLhjoC7uFfgXRC8g/ZegeAh0=
|
||||||
|
cloud.google.com/go/artifactregistry v1.6.0/go.mod h1:IYt0oBPSAGYj/kprzsBjZ/4LnG/zOcHyFHjWPCi6SAQ=
|
||||||
|
cloud.google.com/go/artifactregistry v1.7.0/go.mod h1:mqTOFOnGZx8EtSqK/ZWcsm/4U8B77rbcLP6ruDU2Ixk=
|
||||||
|
cloud.google.com/go/artifactregistry v1.8.0/go.mod h1:w3GQXkJX8hiKN0v+at4b0qotwijQbYUqF2GWkZzAhC0=
|
||||||
|
cloud.google.com/go/artifactregistry v1.9.0/go.mod h1:2K2RqvA2CYvAeARHRkLDhMDJ3OXy26h3XW+3/Jh2uYc=
|
||||||
|
cloud.google.com/go/asset v1.5.0/go.mod h1:5mfs8UvcM5wHhqtSv8J1CtxxaQq3AdBxxQi2jGW/K4o=
|
||||||
|
cloud.google.com/go/asset v1.7.0/go.mod h1:YbENsRK4+xTiL+Ofoj5Ckf+O17kJtgp3Y3nn4uzZz5s=
|
||||||
|
cloud.google.com/go/asset v1.8.0/go.mod h1:mUNGKhiqIdbr8X7KNayoYvyc4HbbFO9URsjbytpUaW0=
|
||||||
|
cloud.google.com/go/asset v1.9.0/go.mod h1:83MOE6jEJBMqFKadM9NLRcs80Gdw76qGuHn8m3h8oHQ=
|
||||||
|
cloud.google.com/go/asset v1.10.0/go.mod h1:pLz7uokL80qKhzKr4xXGvBQXnzHn5evJAEAtZiIb0wY=
|
||||||
|
cloud.google.com/go/assuredworkloads v1.5.0/go.mod h1:n8HOZ6pff6re5KYfBXcFvSViQjDwxFkAkmUFffJRbbY=
|
||||||
|
cloud.google.com/go/assuredworkloads v1.6.0/go.mod h1:yo2YOk37Yc89Rsd5QMVECvjaMKymF9OP+QXWlKXUkXw=
|
||||||
|
cloud.google.com/go/assuredworkloads v1.7.0/go.mod h1:z/736/oNmtGAyU47reJgGN+KVoYoxeLBoj4XkKYscNI=
|
||||||
|
cloud.google.com/go/assuredworkloads v1.8.0/go.mod h1:AsX2cqyNCOvEQC8RMPnoc0yEarXQk6WEKkxYfL6kGIo=
|
||||||
|
cloud.google.com/go/assuredworkloads v1.9.0/go.mod h1:kFuI1P78bplYtT77Tb1hi0FMxM0vVpRC7VVoJC3ZoT0=
|
||||||
|
cloud.google.com/go/automl v1.5.0/go.mod h1:34EjfoFGMZ5sgJ9EoLsRtdPSNZLcfflJR39VbVNS2M0=
|
||||||
|
cloud.google.com/go/automl v1.6.0/go.mod h1:ugf8a6Fx+zP0D59WLhqgTDsQI9w07o64uf/Is3Nh5p8=
|
||||||
|
cloud.google.com/go/automl v1.7.0/go.mod h1:RL9MYCCsJEOmt0Wf3z9uzG0a7adTT1fe+aObgSpkCt8=
|
||||||
|
cloud.google.com/go/automl v1.8.0/go.mod h1:xWx7G/aPEe/NP+qzYXktoBSDfjO+vnKMGgsApGJJquM=
|
||||||
|
cloud.google.com/go/baremetalsolution v0.3.0/go.mod h1:XOrocE+pvK1xFfleEnShBlNAXf+j5blPPxrhjKgnIFc=
|
||||||
|
cloud.google.com/go/baremetalsolution v0.4.0/go.mod h1:BymplhAadOO/eBa7KewQ0Ppg4A4Wplbn+PsFKRLo0uI=
|
||||||
|
cloud.google.com/go/batch v0.3.0/go.mod h1:TR18ZoAekj1GuirsUsR1ZTKN3FC/4UDnScjT8NXImFE=
|
||||||
|
cloud.google.com/go/batch v0.4.0/go.mod h1:WZkHnP43R/QCGQsZ+0JyG4i79ranE2u8xvjq/9+STPE=
|
||||||
|
cloud.google.com/go/beyondcorp v0.2.0/go.mod h1:TB7Bd+EEtcw9PCPQhCJtJGjk/7TC6ckmnSFS+xwTfm4=
|
||||||
|
cloud.google.com/go/beyondcorp v0.3.0/go.mod h1:E5U5lcrcXMsCuoDNyGrpyTm/hn7ne941Jz2vmksAxW8=
|
||||||
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/bigquery v1.42.0/go.mod h1:8dRTJxhtG+vwBKzE5OseQn/hiydoQN3EedCaOdYmxRA=
|
||||||
|
cloud.google.com/go/bigquery v1.43.0/go.mod h1:ZMQcXHsl+xmU1z36G2jNGZmKp9zNY5BUua5wDgmNCfw=
|
||||||
|
cloud.google.com/go/billing v1.4.0/go.mod h1:g9IdKBEFlItS8bTtlrZdVLWSSdSyFUZKXNS02zKMOZY=
|
||||||
|
cloud.google.com/go/billing v1.5.0/go.mod h1:mztb1tBc3QekhjSgmpf/CV4LzWXLzCArwpLmP2Gm88s=
|
||||||
|
cloud.google.com/go/billing v1.6.0/go.mod h1:WoXzguj+BeHXPbKfNWkqVtDdzORazmCjraY+vrxcyvI=
|
||||||
|
cloud.google.com/go/billing v1.7.0/go.mod h1:q457N3Hbj9lYwwRbnlD7vUpyjq6u5U1RAOArInEiD5Y=
|
||||||
|
cloud.google.com/go/binaryauthorization v1.1.0/go.mod h1:xwnoWu3Y84jbuHa0zd526MJYmtnVXn0syOjaJgy4+dM=
|
||||||
|
cloud.google.com/go/binaryauthorization v1.2.0/go.mod h1:86WKkJHtRcv5ViNABtYMhhNWRrD1Vpi//uKEy7aYEfI=
|
||||||
|
cloud.google.com/go/binaryauthorization v1.3.0/go.mod h1:lRZbKgjDIIQvzYQS1p99A7/U1JqvqeZg0wiI5tp6tg0=
|
||||||
|
cloud.google.com/go/binaryauthorization v1.4.0/go.mod h1:tsSPQrBd77VLplV70GUhBf/Zm3FsKmgSqgm4UmiDItk=
|
||||||
|
cloud.google.com/go/certificatemanager v1.3.0/go.mod h1:n6twGDvcUBFu9uBgt4eYvvf3sQ6My8jADcOVwHmzadg=
|
||||||
|
cloud.google.com/go/certificatemanager v1.4.0/go.mod h1:vowpercVFyqs8ABSmrdV+GiFf2H/ch3KyudYQEMM590=
|
||||||
|
cloud.google.com/go/channel v1.8.0/go.mod h1:W5SwCXDJsq/rg3tn3oG0LOxpAo6IMxNa09ngphpSlnk=
|
||||||
|
cloud.google.com/go/channel v1.9.0/go.mod h1:jcu05W0my9Vx4mt3/rEHpfxc9eKi9XwsdDL8yBMbKUk=
|
||||||
|
cloud.google.com/go/cloudbuild v1.3.0/go.mod h1:WequR4ULxlqvMsjDEEEFnOG5ZSRSgWOywXYDb1vPE6U=
|
||||||
|
cloud.google.com/go/cloudbuild v1.4.0/go.mod h1:5Qwa40LHiOXmz3386FrjrYM93rM/hdRr7b53sySrTqA=
|
||||||
|
cloud.google.com/go/clouddms v1.3.0/go.mod h1:oK6XsCDdW4Ib3jCCBugx+gVjevp2TMXFtgxvPSee3OM=
|
||||||
|
cloud.google.com/go/clouddms v1.4.0/go.mod h1:Eh7sUGCC+aKry14O1NRljhjyrr0NFC0G2cjwX0cByRk=
|
||||||
|
cloud.google.com/go/cloudtasks v1.5.0/go.mod h1:fD92REy1x5woxkKEkLdvavGnPJGEn8Uic9nWuLzqCpY=
|
||||||
|
cloud.google.com/go/cloudtasks v1.6.0/go.mod h1:C6Io+sxuke9/KNRkbQpihnW93SWDU3uXt92nu85HkYI=
|
||||||
|
cloud.google.com/go/cloudtasks v1.7.0/go.mod h1:ImsfdYWwlWNJbdgPIIGJWC+gemEGTBK/SunNQQNCAb4=
|
||||||
|
cloud.google.com/go/cloudtasks v1.8.0/go.mod h1:gQXUIwCSOI4yPVK7DgTVFiiP0ZW/eQkydWzwVMdHxrI=
|
||||||
|
cloud.google.com/go/compute v0.1.0/go.mod h1:GAesmwr110a34z04OlxYkATPBEfVhkymfTBXtfbBFow=
|
||||||
|
cloud.google.com/go/compute v1.3.0/go.mod h1:cCZiE1NHEtai4wiufUhW8I8S1JKkAnhnQJWM7YD99wM=
|
||||||
|
cloud.google.com/go/compute v1.5.0/go.mod h1:9SMHyhJlzhlkJqrPAc839t2BZFTSk6Jdj6mkzQJeu0M=
|
||||||
|
cloud.google.com/go/compute v1.6.0/go.mod h1:T29tfhtVbq1wvAPo0E3+7vhgmkOYeXjhFvz/FMzPu0s=
|
||||||
|
cloud.google.com/go/compute v1.6.1/go.mod h1:g85FgpzFvNULZ+S8AYq87axRKuf2Kh7deLqV/jJ3thU=
|
||||||
|
cloud.google.com/go/compute v1.7.0/go.mod h1:435lt8av5oL9P3fv1OEzSbSUe+ybHXGMPQHHZWZxy9U=
|
||||||
|
cloud.google.com/go/compute v1.10.0/go.mod h1:ER5CLbMxl90o2jtNbGSbtfOpQKR0t15FOtRsugnLrlU=
|
||||||
|
cloud.google.com/go/compute v1.12.0/go.mod h1:e8yNOBcBONZU1vJKCvCoDw/4JQsA0dpM4x/6PIIOocU=
|
||||||
|
cloud.google.com/go/compute v1.12.1/go.mod h1:e8yNOBcBONZU1vJKCvCoDw/4JQsA0dpM4x/6PIIOocU=
|
||||||
|
cloud.google.com/go/compute/metadata v0.1.0/go.mod h1:Z1VN+bulIf6bt4P/C37K4DyZYZEXYonfTBHHFPO/4UU=
|
||||||
|
cloud.google.com/go/compute/metadata v0.2.1/go.mod h1:jgHgmJd2RKBGzXqF5LR2EZMGxBkeanZ9wwa75XHJgOM=
|
||||||
|
cloud.google.com/go/contactcenterinsights v1.3.0/go.mod h1:Eu2oemoePuEFc/xKFPjbTuPSj0fYJcPls9TFlPNnHHY=
|
||||||
|
cloud.google.com/go/contactcenterinsights v1.4.0/go.mod h1:L2YzkGbPsv+vMQMCADxJoT9YiTTnSEd6fEvCeHTYVck=
|
||||||
|
cloud.google.com/go/container v1.6.0/go.mod h1:Xazp7GjJSeUYo688S+6J5V+n/t+G5sKBTFkKNudGRxg=
|
||||||
|
cloud.google.com/go/container v1.7.0/go.mod h1:Dp5AHtmothHGX3DwwIHPgq45Y8KmNsgN3amoYfxVkLo=
|
||||||
|
cloud.google.com/go/containeranalysis v0.5.1/go.mod h1:1D92jd8gRR/c0fGMlymRgxWD3Qw9C1ff6/T7mLgVL8I=
|
||||||
|
cloud.google.com/go/containeranalysis v0.6.0/go.mod h1:HEJoiEIu+lEXM+k7+qLCci0h33lX3ZqoYFdmPcoO7s4=
|
||||||
|
cloud.google.com/go/datacatalog v1.3.0/go.mod h1:g9svFY6tuR+j+hrTw3J2dNcmI0dzmSiyOzm8kpLq0a0=
|
||||||
|
cloud.google.com/go/datacatalog v1.5.0/go.mod h1:M7GPLNQeLfWqeIm3iuiruhPzkt65+Bx8dAKvScX8jvs=
|
||||||
|
cloud.google.com/go/datacatalog v1.6.0/go.mod h1:+aEyF8JKg+uXcIdAmmaMUmZ3q1b/lKLtXCmXdnc0lbc=
|
||||||
|
cloud.google.com/go/datacatalog v1.7.0/go.mod h1:9mEl4AuDYWw81UGc41HonIHH7/sn52H0/tc8f8ZbZIE=
|
||||||
|
cloud.google.com/go/datacatalog v1.8.0/go.mod h1:KYuoVOv9BM8EYz/4eMFxrr4DUKhGIOXxZoKYF5wdISM=
|
||||||
|
cloud.google.com/go/dataflow v0.6.0/go.mod h1:9QwV89cGoxjjSR9/r7eFDqqjtvbKxAK2BaYU6PVk9UM=
|
||||||
|
cloud.google.com/go/dataflow v0.7.0/go.mod h1:PX526vb4ijFMesO1o202EaUmouZKBpjHsTlCtB4parQ=
|
||||||
|
cloud.google.com/go/dataform v0.3.0/go.mod h1:cj8uNliRlHpa6L3yVhDOBrUXH+BPAO1+KFMQQNSThKo=
|
||||||
|
cloud.google.com/go/dataform v0.4.0/go.mod h1:fwV6Y4Ty2yIFL89huYlEkwUPtS7YZinZbzzj5S9FzCE=
|
||||||
|
cloud.google.com/go/dataform v0.5.0/go.mod h1:GFUYRe8IBa2hcomWplodVmUx/iTL0FrsauObOM3Ipr0=
|
||||||
|
cloud.google.com/go/datafusion v1.4.0/go.mod h1:1Zb6VN+W6ALo85cXnM1IKiPw+yQMKMhB9TsTSRDo/38=
|
||||||
|
cloud.google.com/go/datafusion v1.5.0/go.mod h1:Kz+l1FGHB0J+4XF2fud96WMmRiq/wj8N9u007vyXZ2w=
|
||||||
|
cloud.google.com/go/datalabeling v0.5.0/go.mod h1:TGcJ0G2NzcsXSE/97yWjIZO0bXj0KbVlINXMG9ud42I=
|
||||||
|
cloud.google.com/go/datalabeling v0.6.0/go.mod h1:WqdISuk/+WIGeMkpw/1q7bK/tFEZxsrFJOJdY2bXvTQ=
|
||||||
|
cloud.google.com/go/dataplex v1.3.0/go.mod h1:hQuRtDg+fCiFgC8j0zV222HvzFQdRd+SVX8gdmFcZzA=
|
||||||
|
cloud.google.com/go/dataplex v1.4.0/go.mod h1:X51GfLXEMVJ6UN47ESVqvlsRplbLhcsAt0kZCCKsU0A=
|
||||||
|
cloud.google.com/go/dataproc v1.7.0/go.mod h1:CKAlMjII9H90RXaMpSxQ8EU6dQx6iAYNPcYPOkSbi8s=
|
||||||
|
cloud.google.com/go/dataproc v1.8.0/go.mod h1:5OW+zNAH0pMpw14JVrPONsxMQYMBqJuzORhIBfBn9uI=
|
||||||
|
cloud.google.com/go/dataqna v0.5.0/go.mod h1:90Hyk596ft3zUQ8NkFfvICSIfHFh1Bc7C4cK3vbhkeo=
|
||||||
|
cloud.google.com/go/dataqna v0.6.0/go.mod h1:1lqNpM7rqNLVgWBJyk5NF6Uen2PHym0jtVJonplVsDA=
|
||||||
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/datastream v1.2.0/go.mod h1:i/uTP8/fZwgATHS/XFu0TcNUhuA0twZxxQ3EyCUQMwo=
|
||||||
|
cloud.google.com/go/datastream v1.3.0/go.mod h1:cqlOX8xlyYF/uxhiKn6Hbv6WjwPPuI9W2M9SAXwaLLQ=
|
||||||
|
cloud.google.com/go/datastream v1.4.0/go.mod h1:h9dpzScPhDTs5noEMQVWP8Wx8AFBRyS0s8KWPx/9r0g=
|
||||||
|
cloud.google.com/go/datastream v1.5.0/go.mod h1:6TZMMNPwjUqZHBKPQ1wwXpb0d5VDVPl2/XoS5yi88q4=
|
||||||
|
cloud.google.com/go/deploy v1.4.0/go.mod h1:5Xghikd4VrmMLNaF6FiRFDlHb59VM59YoDQnOUdsH/c=
|
||||||
|
cloud.google.com/go/deploy v1.5.0/go.mod h1:ffgdD0B89tToyW/U/D2eL0jN2+IEV/3EMuXHA0l4r+s=
|
||||||
|
cloud.google.com/go/dialogflow v1.15.0/go.mod h1:HbHDWs33WOGJgn6rfzBW1Kv807BE3O1+xGbn59zZWI4=
|
||||||
|
cloud.google.com/go/dialogflow v1.16.1/go.mod h1:po6LlzGfK+smoSmTBnbkIZY2w8ffjz/RcGSS+sh1el0=
|
||||||
|
cloud.google.com/go/dialogflow v1.17.0/go.mod h1:YNP09C/kXA1aZdBgC/VtXX74G/TKn7XVCcVumTflA+8=
|
||||||
|
cloud.google.com/go/dialogflow v1.18.0/go.mod h1:trO7Zu5YdyEuR+BhSNOqJezyFQ3aUzz0njv7sMx/iek=
|
||||||
|
cloud.google.com/go/dialogflow v1.19.0/go.mod h1:JVmlG1TwykZDtxtTXujec4tQ+D8SBFMoosgy+6Gn0s0=
|
||||||
|
cloud.google.com/go/dlp v1.6.0/go.mod h1:9eyB2xIhpU0sVwUixfBubDoRwP+GjeUoxxeueZmqvmM=
|
||||||
|
cloud.google.com/go/dlp v1.7.0/go.mod h1:68ak9vCiMBjbasxeVD17hVPxDEck+ExiHavX8kiHG+Q=
|
||||||
|
cloud.google.com/go/documentai v1.7.0/go.mod h1:lJvftZB5NRiFSX4moiye1SMxHx0Bc3x1+p9e/RfXYiU=
|
||||||
|
cloud.google.com/go/documentai v1.8.0/go.mod h1:xGHNEB7CtsnySCNrCFdCyyMz44RhFEEX2Q7UD0c5IhU=
|
||||||
|
cloud.google.com/go/documentai v1.9.0/go.mod h1:FS5485S8R00U10GhgBC0aNGrJxBP8ZVpEeJ7PQDZd6k=
|
||||||
|
cloud.google.com/go/documentai v1.10.0/go.mod h1:vod47hKQIPeCfN2QS/jULIvQTugbmdc0ZvxxfQY1bg4=
|
||||||
|
cloud.google.com/go/domains v0.6.0/go.mod h1:T9Rz3GasrpYk6mEGHh4rymIhjlnIuB4ofT1wTxDeT4Y=
|
||||||
|
cloud.google.com/go/domains v0.7.0/go.mod h1:PtZeqS1xjnXuRPKE/88Iru/LdfoRyEHYA9nFQf4UKpg=
|
||||||
|
cloud.google.com/go/edgecontainer v0.1.0/go.mod h1:WgkZ9tp10bFxqO8BLPqv2LlfmQF1X8lZqwW4r1BTajk=
|
||||||
|
cloud.google.com/go/edgecontainer v0.2.0/go.mod h1:RTmLijy+lGpQ7BXuTDa4C4ssxyXT34NIuHIgKuP4s5w=
|
||||||
|
cloud.google.com/go/essentialcontacts v1.3.0/go.mod h1:r+OnHa5jfj90qIfZDO/VztSFqbQan7HV75p8sA+mdGI=
|
||||||
|
cloud.google.com/go/essentialcontacts v1.4.0/go.mod h1:8tRldvHYsmnBCHdFpvU+GL75oWiBKl80BiqlFh9tp+8=
|
||||||
|
cloud.google.com/go/eventarc v1.7.0/go.mod h1:6ctpF3zTnaQCxUjHUdcfgcA1A2T309+omHZth7gDfmc=
|
||||||
|
cloud.google.com/go/eventarc v1.8.0/go.mod h1:imbzxkyAU4ubfsaKYdQg04WS1NvncblHEup4kvF+4gw=
|
||||||
|
cloud.google.com/go/filestore v1.3.0/go.mod h1:+qbvHGvXU1HaKX2nD0WEPo92TP/8AQuCVEBXNY9z0+w=
|
||||||
|
cloud.google.com/go/filestore v1.4.0/go.mod h1:PaG5oDfo9r224f8OYXURtAsY+Fbyq/bLYoINEK8XQAI=
|
||||||
|
cloud.google.com/go/functions v1.6.0/go.mod h1:3H1UA3qiIPRWD7PeZKLvHZ9SaQhR26XIJcC0A5GbvAk=
|
||||||
|
cloud.google.com/go/functions v1.7.0/go.mod h1:+d+QBcWM+RsrgZfV9xo6KfA1GlzJfxcfZcRPEhDDfzg=
|
||||||
|
cloud.google.com/go/functions v1.8.0/go.mod h1:RTZ4/HsQjIqIYP9a9YPbU+QFoQsAlYgrwOXJWHn1POY=
|
||||||
|
cloud.google.com/go/functions v1.9.0/go.mod h1:Y+Dz8yGguzO3PpIjhLTbnqV1CWmgQ5UwtlpzoyquQ08=
|
||||||
|
cloud.google.com/go/gaming v1.5.0/go.mod h1:ol7rGcxP/qHTRQE/RO4bxkXq+Fix0j6D4LFPzYTIrDM=
|
||||||
|
cloud.google.com/go/gaming v1.6.0/go.mod h1:YMU1GEvA39Qt3zWGyAVA9bpYz/yAhTvaQ1t2sK4KPUA=
|
||||||
|
cloud.google.com/go/gaming v1.7.0/go.mod h1:LrB8U7MHdGgFG851iHAfqUdLcKBdQ55hzXy9xBJz0+w=
|
||||||
|
cloud.google.com/go/gaming v1.8.0/go.mod h1:xAqjS8b7jAVW0KFYeRUxngo9My3f33kFmua++Pi+ggM=
|
||||||
|
cloud.google.com/go/gkebackup v0.2.0/go.mod h1:XKvv/4LfG829/B8B7xRkk8zRrOEbKtEam6yNfuQNH60=
|
||||||
|
cloud.google.com/go/gkebackup v0.3.0/go.mod h1:n/E671i1aOQvUxT541aTkCwExO/bTer2HDlj4TsBRAo=
|
||||||
|
cloud.google.com/go/gkeconnect v0.5.0/go.mod h1:c5lsNAg5EwAy7fkqX/+goqFsU1Da/jQFqArp+wGNr/o=
|
||||||
|
cloud.google.com/go/gkeconnect v0.6.0/go.mod h1:Mln67KyU/sHJEBY8kFZ0xTeyPtzbq9StAVvEULYK16A=
|
||||||
|
cloud.google.com/go/gkehub v0.9.0/go.mod h1:WYHN6WG8w9bXU0hqNxt8rm5uxnk8IH+lPY9J2TV7BK0=
|
||||||
|
cloud.google.com/go/gkehub v0.10.0/go.mod h1:UIPwxI0DsrpsVoWpLB0stwKCP+WFVG9+y977wO+hBH0=
|
||||||
|
cloud.google.com/go/gkemulticloud v0.3.0/go.mod h1:7orzy7O0S+5kq95e4Hpn7RysVA7dPs8W/GgfUtsPbrA=
|
||||||
|
cloud.google.com/go/gkemulticloud v0.4.0/go.mod h1:E9gxVBnseLWCk24ch+P9+B2CoDFJZTyIgLKSalC7tuI=
|
||||||
|
cloud.google.com/go/grafeas v0.2.0/go.mod h1:KhxgtF2hb0P191HlY5besjYm6MqTSTj3LSI+M+ByZHc=
|
||||||
|
cloud.google.com/go/gsuiteaddons v1.3.0/go.mod h1:EUNK/J1lZEZO8yPtykKxLXI6JSVN2rg9bN8SXOa0bgM=
|
||||||
|
cloud.google.com/go/gsuiteaddons v1.4.0/go.mod h1:rZK5I8hht7u7HxFQcFei0+AtfS9uSushomRlg+3ua1o=
|
||||||
|
cloud.google.com/go/iam v0.3.0/go.mod h1:XzJPvDayI+9zsASAFO68Hk07u3z+f+JrT2xXNdp4bnY=
|
||||||
|
cloud.google.com/go/iam v0.5.0/go.mod h1:wPU9Vt0P4UmCux7mqtRu6jcpPAb74cP1fh50J3QpkUc=
|
||||||
|
cloud.google.com/go/iam v0.6.0/go.mod h1:+1AH33ueBne5MzYccyMHtEKqLE4/kJOibtffMHDMFMc=
|
||||||
|
cloud.google.com/go/iam v0.7.0/go.mod h1:H5Br8wRaDGNc8XP3keLc4unfUUZeyH3Sfl9XpQEYOeg=
|
||||||
|
cloud.google.com/go/iap v1.4.0/go.mod h1:RGFwRJdihTINIe4wZ2iCP0zF/qu18ZwyKxrhMhygBEc=
|
||||||
|
cloud.google.com/go/iap v1.5.0/go.mod h1:UH/CGgKd4KyohZL5Pt0jSKE4m3FR51qg6FKQ/z/Ix9A=
|
||||||
|
cloud.google.com/go/ids v1.1.0/go.mod h1:WIuwCaYVOzHIj2OhN9HAwvW+DBdmUAdcWlFxRl+KubM=
|
||||||
|
cloud.google.com/go/ids v1.2.0/go.mod h1:5WXvp4n25S0rA/mQWAg1YEEBBq6/s+7ml1RDCW1IrcY=
|
||||||
|
cloud.google.com/go/iot v1.3.0/go.mod h1:r7RGh2B61+B8oz0AGE+J72AhA0G7tdXItODWsaA2oLs=
|
||||||
|
cloud.google.com/go/iot v1.4.0/go.mod h1:dIDxPOn0UvNDUMD8Ger7FIaTuvMkj+aGk94RPP0iV+g=
|
||||||
|
cloud.google.com/go/kms v1.5.0/go.mod h1:QJS2YY0eJGBg3mnDfuaCyLauWwBJiHRboYxJ++1xJNg=
|
||||||
|
cloud.google.com/go/kms v1.6.0/go.mod h1:Jjy850yySiasBUDi6KFUwUv2n1+o7QZFyuUJg6OgjA0=
|
||||||
|
cloud.google.com/go/language v1.4.0/go.mod h1:F9dRpNFQmJbkaop6g0JhSBXCNlO90e1KWx5iDdxbWic=
|
||||||
|
cloud.google.com/go/language v1.6.0/go.mod h1:6dJ8t3B+lUYfStgls25GusK04NLh3eDLQnWM3mdEbhI=
|
||||||
|
cloud.google.com/go/language v1.7.0/go.mod h1:DJ6dYN/W+SQOjF8e1hLQXMF21AkH2w9wiPzPCJa2MIE=
|
||||||
|
cloud.google.com/go/language v1.8.0/go.mod h1:qYPVHf7SPoNNiCL2Dr0FfEFNil1qi3pQEyygwpgVKB8=
|
||||||
|
cloud.google.com/go/lifesciences v0.5.0/go.mod h1:3oIKy8ycWGPUyZDR/8RNnTOYevhaMLqh5vLUXs9zvT8=
|
||||||
|
cloud.google.com/go/lifesciences v0.6.0/go.mod h1:ddj6tSX/7BOnhxCSd3ZcETvtNr8NZ6t/iPhY2Tyfu08=
|
||||||
|
cloud.google.com/go/longrunning v0.1.1/go.mod h1:UUFxuDWkv22EuY93jjmDMFT5GPQKeFVJBIF6QlTqdsE=
|
||||||
|
cloud.google.com/go/longrunning v0.3.0/go.mod h1:qth9Y41RRSUE69rDcOn6DdK3HfQfsUI0YSmW3iIlLJc=
|
||||||
|
cloud.google.com/go/managedidentities v1.3.0/go.mod h1:UzlW3cBOiPrzucO5qWkNkh0w33KFtBJU281hacNvsdE=
|
||||||
|
cloud.google.com/go/managedidentities v1.4.0/go.mod h1:NWSBYbEMgqmbZsLIyKvxrYbtqOsxY1ZrGM+9RgDqInM=
|
||||||
|
cloud.google.com/go/mediatranslation v0.5.0/go.mod h1:jGPUhGTybqsPQn91pNXw0xVHfuJ3leR1wj37oU3y1f4=
|
||||||
|
cloud.google.com/go/mediatranslation v0.6.0/go.mod h1:hHdBCTYNigsBxshbznuIMFNe5QXEowAuNmmC7h8pu5w=
|
||||||
|
cloud.google.com/go/memcache v1.4.0/go.mod h1:rTOfiGZtJX1AaFUrOgsMHX5kAzaTQ8azHiuDoTPzNsE=
|
||||||
|
cloud.google.com/go/memcache v1.5.0/go.mod h1:dk3fCK7dVo0cUU2c36jKb4VqKPS22BTkf81Xq617aWM=
|
||||||
|
cloud.google.com/go/memcache v1.6.0/go.mod h1:XS5xB0eQZdHtTuTF9Hf8eJkKtR3pVRCcvJwtm68T3rA=
|
||||||
|
cloud.google.com/go/memcache v1.7.0/go.mod h1:ywMKfjWhNtkQTxrWxCkCFkoPjLHPW6A7WOTVI8xy3LY=
|
||||||
|
cloud.google.com/go/metastore v1.5.0/go.mod h1:2ZNrDcQwghfdtCwJ33nM0+GrBGlVuh8rakL3vdPY3XY=
|
||||||
|
cloud.google.com/go/metastore v1.6.0/go.mod h1:6cyQTls8CWXzk45G55x57DVQ9gWg7RiH65+YgPsNh9s=
|
||||||
|
cloud.google.com/go/metastore v1.7.0/go.mod h1:s45D0B4IlsINu87/AsWiEVYbLaIMeUSoxlKKDqBGFS8=
|
||||||
|
cloud.google.com/go/metastore v1.8.0/go.mod h1:zHiMc4ZUpBiM7twCIFQmJ9JMEkDSyZS9U12uf7wHqSI=
|
||||||
|
cloud.google.com/go/monitoring v1.7.0/go.mod h1:HpYse6kkGo//7p6sT0wsIC6IBDET0RhIsnmlA53dvEk=
|
||||||
|
cloud.google.com/go/monitoring v1.8.0/go.mod h1:E7PtoMJ1kQXWxPjB6mv2fhC5/15jInuulFdYYtlcvT4=
|
||||||
|
cloud.google.com/go/networkconnectivity v1.4.0/go.mod h1:nOl7YL8odKyAOtzNX73/M5/mGZgqqMeryi6UPZTk/rA=
|
||||||
|
cloud.google.com/go/networkconnectivity v1.5.0/go.mod h1:3GzqJx7uhtlM3kln0+x5wyFvuVH1pIBJjhCpjzSt75o=
|
||||||
|
cloud.google.com/go/networkconnectivity v1.6.0/go.mod h1:OJOoEXW+0LAxHh89nXd64uGG+FbQoeH8DtxCHVOMlaM=
|
||||||
|
cloud.google.com/go/networkconnectivity v1.7.0/go.mod h1:RMuSbkdbPwNMQjB5HBWD5MpTBnNm39iAVpC3TmsExt8=
|
||||||
|
cloud.google.com/go/networkmanagement v1.4.0/go.mod h1:Q9mdLLRn60AsOrPc8rs8iNV6OHXaGcDdsIQe1ohekq8=
|
||||||
|
cloud.google.com/go/networkmanagement v1.5.0/go.mod h1:ZnOeZ/evzUdUsnvRt792H0uYEnHQEMaz+REhhzJRcf4=
|
||||||
|
cloud.google.com/go/networksecurity v0.5.0/go.mod h1:xS6fOCoqpVC5zx15Z/MqkfDwH4+m/61A3ODiDV1xmiQ=
|
||||||
|
cloud.google.com/go/networksecurity v0.6.0/go.mod h1:Q5fjhTr9WMI5mbpRYEbiexTzROf7ZbDzvzCrNl14nyU=
|
||||||
|
cloud.google.com/go/notebooks v1.2.0/go.mod h1:9+wtppMfVPUeJ8fIWPOq1UnATHISkGXGqTkxeieQ6UY=
|
||||||
|
cloud.google.com/go/notebooks v1.3.0/go.mod h1:bFR5lj07DtCPC7YAAJ//vHskFBxA5JzYlH68kXVdk34=
|
||||||
|
cloud.google.com/go/notebooks v1.4.0/go.mod h1:4QPMngcwmgb6uw7Po99B2xv5ufVoIQ7nOGDyL4P8AgA=
|
||||||
|
cloud.google.com/go/notebooks v1.5.0/go.mod h1:q8mwhnP9aR8Hpfnrc5iN5IBhrXUy8S2vuYs+kBJ/gu0=
|
||||||
|
cloud.google.com/go/optimization v1.1.0/go.mod h1:5po+wfvX5AQlPznyVEZjGJTMr4+CAkJf2XSTQOOl9l4=
|
||||||
|
cloud.google.com/go/optimization v1.2.0/go.mod h1:Lr7SOHdRDENsh+WXVmQhQTrzdu9ybg0NecjHidBq6xs=
|
||||||
|
cloud.google.com/go/orchestration v1.3.0/go.mod h1:Sj5tq/JpWiB//X/q3Ngwdl5K7B7Y0KZ7bfv0wL6fqVA=
|
||||||
|
cloud.google.com/go/orchestration v1.4.0/go.mod h1:6W5NLFWs2TlniBphAViZEVhrXRSMgUGDfW7vrWKvsBk=
|
||||||
|
cloud.google.com/go/orgpolicy v1.4.0/go.mod h1:xrSLIV4RePWmP9P3tBl8S93lTmlAxjm06NSm2UTmKvE=
|
||||||
|
cloud.google.com/go/orgpolicy v1.5.0/go.mod h1:hZEc5q3wzwXJaKrsx5+Ewg0u1LxJ51nNFlext7Tanwc=
|
||||||
|
cloud.google.com/go/osconfig v1.7.0/go.mod h1:oVHeCeZELfJP7XLxcBGTMBvRO+1nQ5tFG9VQTmYS2Fs=
|
||||||
|
cloud.google.com/go/osconfig v1.8.0/go.mod h1:EQqZLu5w5XA7eKizepumcvWx+m8mJUhEwiPqWiZeEdg=
|
||||||
|
cloud.google.com/go/osconfig v1.9.0/go.mod h1:Yx+IeIZJ3bdWmzbQU4fxNl8xsZ4amB+dygAwFPlvnNo=
|
||||||
|
cloud.google.com/go/osconfig v1.10.0/go.mod h1:uMhCzqC5I8zfD9zDEAfvgVhDS8oIjySWh+l4WK6GnWw=
|
||||||
|
cloud.google.com/go/oslogin v1.4.0/go.mod h1:YdgMXWRaElXz/lDk1Na6Fh5orF7gvmJ0FGLIs9LId4E=
|
||||||
|
cloud.google.com/go/oslogin v1.5.0/go.mod h1:D260Qj11W2qx/HVF29zBg+0fd6YCSjSqLUkY/qEenQU=
|
||||||
|
cloud.google.com/go/oslogin v1.6.0/go.mod h1:zOJ1O3+dTU8WPlGEkFSh7qeHPPSoxrcMbbK1Nm2iX70=
|
||||||
|
cloud.google.com/go/oslogin v1.7.0/go.mod h1:e04SN0xO1UNJ1M5GP0vzVBFicIe4O53FOfcixIqTyXo=
|
||||||
|
cloud.google.com/go/phishingprotection v0.5.0/go.mod h1:Y3HZknsK9bc9dMi+oE8Bim0lczMU6hrX0UpADuMefr0=
|
||||||
|
cloud.google.com/go/phishingprotection v0.6.0/go.mod h1:9Y3LBLgy0kDTcYET8ZH3bq/7qni15yVUoAxiFxnlSUA=
|
||||||
|
cloud.google.com/go/policytroubleshooter v1.3.0/go.mod h1:qy0+VwANja+kKrjlQuOzmlvscn4RNsAc0e15GGqfMxg=
|
||||||
|
cloud.google.com/go/policytroubleshooter v1.4.0/go.mod h1:DZT4BcRw3QoO8ota9xw/LKtPa8lKeCByYeKTIf/vxdE=
|
||||||
|
cloud.google.com/go/privatecatalog v0.5.0/go.mod h1:XgosMUvvPyxDjAVNDYxJ7wBW8//hLDDYmnsNcMGq1K0=
|
||||||
|
cloud.google.com/go/privatecatalog v0.6.0/go.mod h1:i/fbkZR0hLN29eEWiiwue8Pb+GforiEIBnV9yrRUOKI=
|
||||||
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=
|
||||||
cloud.google.com/go/pubsub v1.3.1/go.mod h1:i+ucay31+CNRpDW4Lu78I4xXG+O1r/MAHgjpRVR+TSU=
|
cloud.google.com/go/pubsub v1.3.1/go.mod h1:i+ucay31+CNRpDW4Lu78I4xXG+O1r/MAHgjpRVR+TSU=
|
||||||
|
cloud.google.com/go/recaptchaenterprise v1.3.1/go.mod h1:OdD+q+y4XGeAlxRaMn1Y7/GveP6zmq76byL6tjPE7d4=
|
||||||
|
cloud.google.com/go/recaptchaenterprise/v2 v2.1.0/go.mod h1:w9yVqajwroDNTfGuhmOjPDN//rZGySaf6PtFVcSCa7o=
|
||||||
|
cloud.google.com/go/recaptchaenterprise/v2 v2.2.0/go.mod h1:/Zu5jisWGeERrd5HnlS3EUGb/D335f9k51B/FVil0jk=
|
||||||
|
cloud.google.com/go/recaptchaenterprise/v2 v2.3.0/go.mod h1:O9LwGCjrhGHBQET5CA7dd5NwwNQUErSgEDit1DLNTdo=
|
||||||
|
cloud.google.com/go/recaptchaenterprise/v2 v2.4.0/go.mod h1:Am3LHfOuBstrLrNCBrlI5sbwx9LBg3te2N6hGvHn2mE=
|
||||||
|
cloud.google.com/go/recaptchaenterprise/v2 v2.5.0/go.mod h1:O8LzcHXN3rz0j+LBC91jrwI3R+1ZSZEWrfL7XHgNo9U=
|
||||||
|
cloud.google.com/go/recommendationengine v0.5.0/go.mod h1:E5756pJcVFeVgaQv3WNpImkFP8a+RptV6dDLGPILjvg=
|
||||||
|
cloud.google.com/go/recommendationengine v0.6.0/go.mod h1:08mq2umu9oIqc7tDy8sx+MNJdLG0fUi3vaSVbztHgJ4=
|
||||||
|
cloud.google.com/go/recommender v1.5.0/go.mod h1:jdoeiBIVrJe9gQjwd759ecLJbxCDED4A6p+mqoqDvTg=
|
||||||
|
cloud.google.com/go/recommender v1.6.0/go.mod h1:+yETpm25mcoiECKh9DEScGzIRyDKpZ0cEhWGo+8bo+c=
|
||||||
|
cloud.google.com/go/recommender v1.7.0/go.mod h1:XLHs/W+T8olwlGOgfQenXBTbIseGclClff6lhFVe9Bs=
|
||||||
|
cloud.google.com/go/recommender v1.8.0/go.mod h1:PkjXrTT05BFKwxaUxQmtIlrtj0kph108r02ZZQ5FE70=
|
||||||
|
cloud.google.com/go/redis v1.7.0/go.mod h1:V3x5Jq1jzUcg+UNsRvdmsfuFnit1cfe3Z/PGyq/lm4Y=
|
||||||
|
cloud.google.com/go/redis v1.8.0/go.mod h1:Fm2szCDavWzBk2cDKxrkmWBqoCiL1+Ctwq7EyqBCA/A=
|
||||||
|
cloud.google.com/go/redis v1.9.0/go.mod h1:HMYQuajvb2D0LvMgZmLDZW8V5aOC/WxstZHiy4g8OiA=
|
||||||
|
cloud.google.com/go/redis v1.10.0/go.mod h1:ThJf3mMBQtW18JzGgh41/Wld6vnDDc/F/F35UolRZPM=
|
||||||
|
cloud.google.com/go/resourcemanager v1.3.0/go.mod h1:bAtrTjZQFJkiWTPDb1WBjzvc6/kifjj4QBYuKCCoqKA=
|
||||||
|
cloud.google.com/go/resourcemanager v1.4.0/go.mod h1:MwxuzkumyTX7/a3n37gmsT3py7LIXwrShilPh3P1tR0=
|
||||||
|
cloud.google.com/go/resourcesettings v1.3.0/go.mod h1:lzew8VfESA5DQ8gdlHwMrqZs1S9V87v3oCnKCWoOuQU=
|
||||||
|
cloud.google.com/go/resourcesettings v1.4.0/go.mod h1:ldiH9IJpcrlC3VSuCGvjR5of/ezRrOxFtpJoJo5SmXg=
|
||||||
|
cloud.google.com/go/retail v1.8.0/go.mod h1:QblKS8waDmNUhghY2TI9O3JLlFk8jybHeV4BF19FrE4=
|
||||||
|
cloud.google.com/go/retail v1.9.0/go.mod h1:g6jb6mKuCS1QKnH/dpu7isX253absFl6iE92nHwlBUY=
|
||||||
|
cloud.google.com/go/retail v1.10.0/go.mod h1:2gDk9HsL4HMS4oZwz6daui2/jmKvqShXKQuB2RZ+cCc=
|
||||||
|
cloud.google.com/go/retail v1.11.0/go.mod h1:MBLk1NaWPmh6iVFSz9MeKG/Psyd7TAgm6y/9L2B4x9Y=
|
||||||
|
cloud.google.com/go/run v0.2.0/go.mod h1:CNtKsTA1sDcnqqIFR3Pb5Tq0usWxJJvsWOCPldRU3Do=
|
||||||
|
cloud.google.com/go/run v0.3.0/go.mod h1:TuyY1+taHxTjrD0ZFk2iAR+xyOXEA0ztb7U3UNA0zBo=
|
||||||
|
cloud.google.com/go/scheduler v1.4.0/go.mod h1:drcJBmxF3aqZJRhmkHQ9b3uSSpQoltBPGPxGAWROx6s=
|
||||||
|
cloud.google.com/go/scheduler v1.5.0/go.mod h1:ri073ym49NW3AfT6DZi21vLZrG07GXr5p3H1KxN5QlI=
|
||||||
|
cloud.google.com/go/scheduler v1.6.0/go.mod h1:SgeKVM7MIwPn3BqtcBntpLyrIJftQISRrYB5ZtT+KOk=
|
||||||
|
cloud.google.com/go/scheduler v1.7.0/go.mod h1:jyCiBqWW956uBjjPMMuX09n3x37mtyPJegEWKxRsn44=
|
||||||
|
cloud.google.com/go/secretmanager v1.6.0/go.mod h1:awVa/OXF6IiyaU1wQ34inzQNc4ISIDIrId8qE5QGgKA=
|
||||||
|
cloud.google.com/go/secretmanager v1.8.0/go.mod h1:hnVgi/bN5MYHd3Gt0SPuTPPp5ENina1/LxM+2W9U9J4=
|
||||||
|
cloud.google.com/go/secretmanager v1.9.0/go.mod h1:b71qH2l1yHmWQHt9LC80akm86mX8AL6X1MA01dW8ht4=
|
||||||
|
cloud.google.com/go/security v1.5.0/go.mod h1:lgxGdyOKKjHL4YG3/YwIL2zLqMFCKs0UbQwgyZmfJl4=
|
||||||
|
cloud.google.com/go/security v1.7.0/go.mod h1:mZklORHl6Bg7CNnnjLH//0UlAlaXqiG7Lb9PsPXLfD0=
|
||||||
|
cloud.google.com/go/security v1.8.0/go.mod h1:hAQOwgmaHhztFhiQ41CjDODdWP0+AE1B3sX4OFlq+GU=
|
||||||
|
cloud.google.com/go/security v1.9.0/go.mod h1:6Ta1bO8LXI89nZnmnsZGp9lVoVWXqsVbIq/t9dzI+2Q=
|
||||||
|
cloud.google.com/go/security v1.10.0/go.mod h1:QtOMZByJVlibUT2h9afNDWRZ1G96gVywH8T5GUSb9IA=
|
||||||
|
cloud.google.com/go/securitycenter v1.13.0/go.mod h1:cv5qNAqjY84FCN6Y9z28WlkKXyWsgLO832YiWwkCWcU=
|
||||||
|
cloud.google.com/go/securitycenter v1.14.0/go.mod h1:gZLAhtyKv85n52XYWt6RmeBdydyxfPeTrpToDPw4Auc=
|
||||||
|
cloud.google.com/go/securitycenter v1.15.0/go.mod h1:PeKJ0t8MoFmmXLXWm41JidyzI3PJjd8sXWaVqg43WWk=
|
||||||
|
cloud.google.com/go/securitycenter v1.16.0/go.mod h1:Q9GMaLQFUD+5ZTabrbujNWLtSLZIZF7SAR0wWECrjdk=
|
||||||
|
cloud.google.com/go/servicecontrol v1.4.0/go.mod h1:o0hUSJ1TXJAmi/7fLJAedOovnujSEvjKCAFNXPQ1RaU=
|
||||||
|
cloud.google.com/go/servicecontrol v1.5.0/go.mod h1:qM0CnXHhyqKVuiZnGKrIurvVImCs8gmqWsDoqe9sU1s=
|
||||||
|
cloud.google.com/go/servicedirectory v1.4.0/go.mod h1:gH1MUaZCgtP7qQiI+F+A+OpeKF/HQWgtAddhTbhL2bs=
|
||||||
|
cloud.google.com/go/servicedirectory v1.5.0/go.mod h1:QMKFL0NUySbpZJ1UZs3oFAmdvVxhhxB6eJ/Vlp73dfg=
|
||||||
|
cloud.google.com/go/servicedirectory v1.6.0/go.mod h1:pUlbnWsLH9c13yGkxCmfumWEPjsRs1RlmJ4pqiNjVL4=
|
||||||
|
cloud.google.com/go/servicedirectory v1.7.0/go.mod h1:5p/U5oyvgYGYejufvxhgwjL8UVXjkuw7q5XcG10wx1U=
|
||||||
|
cloud.google.com/go/servicemanagement v1.4.0/go.mod h1:d8t8MDbezI7Z2R1O/wu8oTggo3BI2GKYbdG4y/SJTco=
|
||||||
|
cloud.google.com/go/servicemanagement v1.5.0/go.mod h1:XGaCRe57kfqu4+lRxaFEAuqmjzF0r+gWHjWqKqBvKFo=
|
||||||
|
cloud.google.com/go/serviceusage v1.3.0/go.mod h1:Hya1cozXM4SeSKTAgGXgj97GlqUvF5JaoXacR1JTP/E=
|
||||||
|
cloud.google.com/go/serviceusage v1.4.0/go.mod h1:SB4yxXSaYVuUBYUml6qklyONXNLt83U0Rb+CXyhjEeU=
|
||||||
|
cloud.google.com/go/shell v1.3.0/go.mod h1:VZ9HmRjZBsjLGXusm7K5Q5lzzByZmJHf1d0IWHEN5X4=
|
||||||
|
cloud.google.com/go/shell v1.4.0/go.mod h1:HDxPzZf3GkDdhExzD/gs8Grqk+dmYcEjGShZgYa9URw=
|
||||||
|
cloud.google.com/go/speech v1.6.0/go.mod h1:79tcr4FHCimOp56lwC01xnt/WPJZc4v3gzyT7FoBkCM=
|
||||||
|
cloud.google.com/go/speech v1.7.0/go.mod h1:KptqL+BAQIhMsj1kOP2la5DSEEerPDuOP/2mmkhHhZQ=
|
||||||
|
cloud.google.com/go/speech v1.8.0/go.mod h1:9bYIl1/tjsAnMgKGHKmBZzXKEkGgtU+MpdDPTE9f7y0=
|
||||||
|
cloud.google.com/go/speech v1.9.0/go.mod h1:xQ0jTcmnRFFM2RfX/U+rk6FQNUF6DQlydUSyoooSpco=
|
||||||
cloud.google.com/go/storage v1.0.0/go.mod h1:IhtSnM/ZTZV8YYJWCY8RULGVqBDmpoyjwiyrjsg+URw=
|
cloud.google.com/go/storage v1.0.0/go.mod h1:IhtSnM/ZTZV8YYJWCY8RULGVqBDmpoyjwiyrjsg+URw=
|
||||||
cloud.google.com/go/storage v1.5.0/go.mod h1:tpKbwo567HUNpVclU5sGELwQWBDZ8gh0ZeosJ0Rtdos=
|
cloud.google.com/go/storage v1.5.0/go.mod h1:tpKbwo567HUNpVclU5sGELwQWBDZ8gh0ZeosJ0Rtdos=
|
||||||
cloud.google.com/go/storage v1.6.0/go.mod h1:N7U0C8pVQ/+NIKOBQyamJIeKQKkZ+mxpohlUTyfDhBk=
|
cloud.google.com/go/storage v1.6.0/go.mod h1:N7U0C8pVQ/+NIKOBQyamJIeKQKkZ+mxpohlUTyfDhBk=
|
||||||
cloud.google.com/go/storage v1.8.0/go.mod h1:Wv1Oy7z6Yz3DshWRJFhqM/UCfaWIRTdp0RXyy7KQOVs=
|
cloud.google.com/go/storage v1.8.0/go.mod h1:Wv1Oy7z6Yz3DshWRJFhqM/UCfaWIRTdp0RXyy7KQOVs=
|
||||||
cloud.google.com/go/storage v1.10.0/go.mod h1:FLPqc6j+Ki4BU591ie1oL6qBQGu2Bl/tZ9ullr3+Kg0=
|
cloud.google.com/go/storage v1.10.0/go.mod h1:FLPqc6j+Ki4BU591ie1oL6qBQGu2Bl/tZ9ullr3+Kg0=
|
||||||
|
cloud.google.com/go/storage v1.22.1/go.mod h1:S8N1cAStu7BOeFfE8KAQzmyyLkK8p/vmRq6kuBTW58Y=
|
||||||
|
cloud.google.com/go/storage v1.23.0/go.mod h1:vOEEDNFnciUMhBeT6hsJIn3ieU5cFRmzeLgDvXzfIXc=
|
||||||
|
cloud.google.com/go/storage v1.27.0/go.mod h1:x9DOL8TK/ygDUMieqwfhdpQryTeEkhGKMi80i/iqR2s=
|
||||||
|
cloud.google.com/go/storagetransfer v1.5.0/go.mod h1:dxNzUopWy7RQevYFHewchb29POFv3/AaBgnhqzqiK0w=
|
||||||
|
cloud.google.com/go/storagetransfer v1.6.0/go.mod h1:y77xm4CQV/ZhFZH75PLEXY0ROiS7Gh6pSKrM8dJyg6I=
|
||||||
|
cloud.google.com/go/talent v1.1.0/go.mod h1:Vl4pt9jiHKvOgF9KoZo6Kob9oV4lwd/ZD5Cto54zDRw=
|
||||||
|
cloud.google.com/go/talent v1.2.0/go.mod h1:MoNF9bhFQbiJ6eFD3uSsg0uBALw4n4gaCaEjBw9zo8g=
|
||||||
|
cloud.google.com/go/talent v1.3.0/go.mod h1:CmcxwJ/PKfRgd1pBjQgU6W3YBwiewmUzQYH5HHmSCmM=
|
||||||
|
cloud.google.com/go/talent v1.4.0/go.mod h1:ezFtAgVuRf8jRsvyE6EwmbTK5LKciD4KVnHuDEFmOOA=
|
||||||
|
cloud.google.com/go/texttospeech v1.4.0/go.mod h1:FX8HQHA6sEpJ7rCMSfXuzBcysDAuWusNNNvN9FELDd8=
|
||||||
|
cloud.google.com/go/texttospeech v1.5.0/go.mod h1:oKPLhR4n4ZdQqWKURdwxMy0uiTS1xU161C8W57Wkea4=
|
||||||
|
cloud.google.com/go/tpu v1.3.0/go.mod h1:aJIManG0o20tfDQlRIej44FcwGGl/cD0oiRyMKG19IQ=
|
||||||
|
cloud.google.com/go/tpu v1.4.0/go.mod h1:mjZaX8p0VBgllCzF6wcU2ovUXN9TONFLd7iz227X2Xg=
|
||||||
|
cloud.google.com/go/trace v1.3.0/go.mod h1:FFUE83d9Ca57C+K8rDl/Ih8LwOzWIV1krKgxg6N0G28=
|
||||||
|
cloud.google.com/go/trace v1.4.0/go.mod h1:UG0v8UBqzusp+z63o7FK74SdFE+AXpCLdFb1rshXG+Y=
|
||||||
|
cloud.google.com/go/translate v1.3.0/go.mod h1:gzMUwRjvOqj5i69y/LYLd8RrNQk+hOmIXTi9+nb3Djs=
|
||||||
|
cloud.google.com/go/translate v1.4.0/go.mod h1:06Dn/ppvLD6WvA5Rhdp029IX2Mi3Mn7fpMRLPvXT5Wg=
|
||||||
|
cloud.google.com/go/video v1.8.0/go.mod h1:sTzKFc0bUSByE8Yoh8X0mn8bMymItVGPfTuUBUyRgxk=
|
||||||
|
cloud.google.com/go/video v1.9.0/go.mod h1:0RhNKFRF5v92f8dQt0yhaHrEuH95m068JYOvLZYnJSw=
|
||||||
|
cloud.google.com/go/videointelligence v1.6.0/go.mod h1:w0DIDlVRKtwPCn/C4iwZIJdvC69yInhW0cfi+p546uU=
|
||||||
|
cloud.google.com/go/videointelligence v1.7.0/go.mod h1:k8pI/1wAhjznARtVT9U1llUaFNPh7muw8QyOUpavru4=
|
||||||
|
cloud.google.com/go/videointelligence v1.8.0/go.mod h1:dIcCn4gVDdS7yte/w+koiXn5dWVplOZkE+xwG9FgK+M=
|
||||||
|
cloud.google.com/go/videointelligence v1.9.0/go.mod h1:29lVRMPDYHikk3v8EdPSaL8Ku+eMzDljjuvRs105XoU=
|
||||||
|
cloud.google.com/go/vision v1.2.0/go.mod h1:SmNwgObm5DpFBme2xpyOyasvBc1aPdjvMk2bBk0tKD0=
|
||||||
|
cloud.google.com/go/vision/v2 v2.2.0/go.mod h1:uCdV4PpN1S0jyCyq8sIM42v2Y6zOLkZs+4R9LrGYwFo=
|
||||||
|
cloud.google.com/go/vision/v2 v2.3.0/go.mod h1:UO61abBx9QRMFkNBbf1D8B1LXdS2cGiiCRx0vSpZoUo=
|
||||||
|
cloud.google.com/go/vision/v2 v2.4.0/go.mod h1:VtI579ll9RpVTrdKdkMzckdnwMyX2JILb+MhPqRbPsY=
|
||||||
|
cloud.google.com/go/vision/v2 v2.5.0/go.mod h1:MmaezXOOE+IWa+cS7OhRRLK2cNv1ZL98zhqFFZaaH2E=
|
||||||
|
cloud.google.com/go/vmmigration v1.2.0/go.mod h1:IRf0o7myyWFSmVR1ItrBSFLFD/rJkfDCUTO4vLlJvsE=
|
||||||
|
cloud.google.com/go/vmmigration v1.3.0/go.mod h1:oGJ6ZgGPQOFdjHuocGcLqX4lc98YQ7Ygq8YQwHh9A7g=
|
||||||
|
cloud.google.com/go/vpcaccess v1.4.0/go.mod h1:aQHVbTWDYUR1EbTApSVvMq1EnT57ppDmQzZ3imqIk4w=
|
||||||
|
cloud.google.com/go/vpcaccess v1.5.0/go.mod h1:drmg4HLk9NkZpGfCmZ3Tz0Bwnm2+DKqViEpeEpOq0m8=
|
||||||
|
cloud.google.com/go/webrisk v1.4.0/go.mod h1:Hn8X6Zr+ziE2aNd8SliSDWpEnSS1u4R9+xXZmFiHmGE=
|
||||||
|
cloud.google.com/go/webrisk v1.5.0/go.mod h1:iPG6fr52Tv7sGk0H6qUFzmL3HHZev1htXuWDEEsqMTg=
|
||||||
|
cloud.google.com/go/webrisk v1.6.0/go.mod h1:65sW9V9rOosnc9ZY7A7jsy1zoHS5W9IAXv6dGqhMQMc=
|
||||||
|
cloud.google.com/go/webrisk v1.7.0/go.mod h1:mVMHgEYH0r337nmt1JyLthzMr6YxwN1aAIEc2fTcq7A=
|
||||||
|
cloud.google.com/go/websecurityscanner v1.3.0/go.mod h1:uImdKm2wyeXQevQJXeh8Uun/Ym1VqworNDlBXQevGMo=
|
||||||
|
cloud.google.com/go/websecurityscanner v1.4.0/go.mod h1:ebit/Fp0a+FWu5j4JOmJEV8S8CzdTkAS77oDsiSqYWQ=
|
||||||
|
cloud.google.com/go/workflows v1.6.0/go.mod h1:6t9F5h/unJz41YqfBmqSASJSXccBLtD1Vwf+KmJENM0=
|
||||||
|
cloud.google.com/go/workflows v1.7.0/go.mod h1:JhSrZuVZWuiDfKEFxU0/F1PQjmpnpcoISEXH2bcHC3M=
|
||||||
|
cloud.google.com/go/workflows v1.8.0/go.mod h1:ysGhmEajwZxGn1OhGOGKsTXc5PyxOc0vfKf5Af+to4M=
|
||||||
|
cloud.google.com/go/workflows v1.9.0/go.mod h1:ZGkj1aFIOd9c8Gerkjjq7OW7I5+l6cSvT3ujaO/WwSA=
|
||||||
dmitri.shuralyov.com/gpu/mtl v0.0.0-20190408044501-666a987793e9/go.mod h1:H6x//7gZCb22OMCxBHrMx7a5I7Hp++hsVxbQ4BYO7hU=
|
dmitri.shuralyov.com/gpu/mtl v0.0.0-20190408044501-666a987793e9/go.mod h1:H6x//7gZCb22OMCxBHrMx7a5I7Hp++hsVxbQ4BYO7hU=
|
||||||
github.com/Azure/go-autorest v14.2.0+incompatible/go.mod h1:r+4oMnoxhatjLLJ6zxSWATqVooLgysK6ZNox3g/xq24=
|
github.com/Azure/go-autorest v14.2.0+incompatible/go.mod h1:r+4oMnoxhatjLLJ6zxSWATqVooLgysK6ZNox3g/xq24=
|
||||||
github.com/Azure/go-autorest/autorest v0.11.18/go.mod h1:dSiJPy22c3u0OtOKDNttNgqpNFY/GeWa7GH/Pz56QRA=
|
github.com/Azure/go-autorest/autorest v0.11.18/go.mod h1:dSiJPy22c3u0OtOKDNttNgqpNFY/GeWa7GH/Pz56QRA=
|
||||||
@@ -60,8 +389,8 @@ github.com/alecthomas/units v0.0.0-20190717042225-c3de453c63f4/go.mod h1:ybxpYRF
|
|||||||
github.com/alecthomas/units v0.0.0-20190924025748-f65c72e2690d/go.mod h1:rBZYJk541a8SKzHPHnH3zbiI+7dagKZ0cgpgrD7Fyho=
|
github.com/alecthomas/units v0.0.0-20190924025748-f65c72e2690d/go.mod h1:rBZYJk541a8SKzHPHnH3zbiI+7dagKZ0cgpgrD7Fyho=
|
||||||
github.com/alicebob/gopher-json v0.0.0-20200520072559-a9ecdc9d1d3a h1:HbKu58rmZpUGpz5+4FfNmIU+FmZg2P3Xaj2v2bfNWmk=
|
github.com/alicebob/gopher-json v0.0.0-20200520072559-a9ecdc9d1d3a h1:HbKu58rmZpUGpz5+4FfNmIU+FmZg2P3Xaj2v2bfNWmk=
|
||||||
github.com/alicebob/gopher-json v0.0.0-20200520072559-a9ecdc9d1d3a/go.mod h1:SGnFV6hVsYE877CKEZ6tDNTjaSXYUk6QqoIK6PrAtcc=
|
github.com/alicebob/gopher-json v0.0.0-20200520072559-a9ecdc9d1d3a/go.mod h1:SGnFV6hVsYE877CKEZ6tDNTjaSXYUk6QqoIK6PrAtcc=
|
||||||
github.com/alicebob/miniredis/v2 v2.23.0 h1:+lwAJYjvvdIVg6doFHuotFjueJ/7KY10xo/vm3X3Scw=
|
github.com/alicebob/miniredis/v2 v2.23.1 h1:jR6wZggBxwWygeXcdNyguCOCIjPsZyNUNlAkTx2fu0U=
|
||||||
github.com/alicebob/miniredis/v2 v2.23.0/go.mod h1:XNqvJdQJv5mSuVMc0ynneafpnL/zv52acZ6kqeS0t88=
|
github.com/alicebob/miniredis/v2 v2.23.1/go.mod h1:84TWKZlxYkfgMucPBf5SOQBYJceZeQRFIaQgNMiCX6Q=
|
||||||
github.com/antihax/optional v1.0.0/go.mod h1:uupD/76wgC+ih3iEmQUL+0Ugr19nfwCT1kdvxnR2qWY=
|
github.com/antihax/optional v1.0.0/go.mod h1:uupD/76wgC+ih3iEmQUL+0Ugr19nfwCT1kdvxnR2qWY=
|
||||||
github.com/asaskevich/govalidator v0.0.0-20190424111038-f61b66f89f4a/go.mod h1:lB+ZfQJz7igIIfQNfa7Ml4HSf2uFQQRzpGGRXenZAgY=
|
github.com/asaskevich/govalidator v0.0.0-20190424111038-f61b66f89f4a/go.mod h1:lB+ZfQJz7igIIfQNfa7Ml4HSf2uFQQRzpGGRXenZAgY=
|
||||||
github.com/benbjohnson/clock v1.1.0 h1:Q92kusRqC1XV2MjkWETPvjJVqKetz1OzxZB7mHJLju8=
|
github.com/benbjohnson/clock v1.1.0 h1:Q92kusRqC1XV2MjkWETPvjJVqKetz1OzxZB7mHJLju8=
|
||||||
@@ -85,6 +414,7 @@ github.com/chzyer/test v0.0.0-20180213035817-a1ea475d72b1/go.mod h1:Q3SI9o4m/ZMn
|
|||||||
github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw=
|
github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw=
|
||||||
github.com/cloudflare/golz4 v0.0.0-20150217214814-ef862a3cdc58/go.mod h1:EOBUe0h4xcZ5GoxqC5SDxFQ8gwyZPKQoEzownBlhI80=
|
github.com/cloudflare/golz4 v0.0.0-20150217214814-ef862a3cdc58/go.mod h1:EOBUe0h4xcZ5GoxqC5SDxFQ8gwyZPKQoEzownBlhI80=
|
||||||
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-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/udpa/go v0.0.0-20210930031921-04548b0d99d4/go.mod h1:6pvJx4me5XPnfI9Z40ddWsdw2W/uZgQLFXToKeRcDiI=
|
||||||
github.com/cncf/xds/go v0.0.0-20210312221358-fbca930ec8ed/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs=
|
github.com/cncf/xds/go v0.0.0-20210312221358-fbca930ec8ed/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs=
|
||||||
@@ -113,6 +443,7 @@ github.com/emicklei/go-restful v0.0.0-20170410110728-ff4f55a20633/go.mod h1:otzb
|
|||||||
github.com/envoyproxy/go-control-plane v0.9.0/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4=
|
github.com/envoyproxy/go-control-plane v0.9.0/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4=
|
||||||
github.com/envoyproxy/go-control-plane v0.9.1-0.20191026205805-5f8ba28d4473/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4=
|
github.com/envoyproxy/go-control-plane v0.9.1-0.20191026205805-5f8ba28d4473/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4=
|
||||||
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.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.9-0.20210217033140-668b12f5399d/go.mod h1:cXg6YxExXjJnVBQHBLXeUAgxn2UodCpnH306RInaBQk=
|
github.com/envoyproxy/go-control-plane v0.9.9-0.20210217033140-668b12f5399d/go.mod h1:cXg6YxExXjJnVBQHBLXeUAgxn2UodCpnH306RInaBQk=
|
||||||
github.com/envoyproxy/go-control-plane v0.9.9-0.20210512163311-63b5d3c536b0/go.mod h1:hliV/p42l8fGbc6Y9bQ70uLwIvmJyVE5k4iMKlh8wCQ=
|
github.com/envoyproxy/go-control-plane v0.9.9-0.20210512163311-63b5d3c536b0/go.mod h1:hliV/p42l8fGbc6Y9bQ70uLwIvmJyVE5k4iMKlh8wCQ=
|
||||||
@@ -122,6 +453,8 @@ github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7
|
|||||||
github.com/evanphx/json-patch v4.11.0+incompatible/go.mod h1:50XU6AFN0ol/bzJsmQLiYLvXMP4fmwYFNcr97nuDLSk=
|
github.com/evanphx/json-patch v4.11.0+incompatible/go.mod h1:50XU6AFN0ol/bzJsmQLiYLvXMP4fmwYFNcr97nuDLSk=
|
||||||
github.com/fatih/color v1.13.0 h1:8LOYc1KYPPmyKMuN8QV2DNRWNbLo6LZ0iLs8+mlH53w=
|
github.com/fatih/color v1.13.0 h1:8LOYc1KYPPmyKMuN8QV2DNRWNbLo6LZ0iLs8+mlH53w=
|
||||||
github.com/fatih/color v1.13.0/go.mod h1:kLAiJbzzSOZDVNGyDpeOxJ47H46qBXwg5ILebYFFOfk=
|
github.com/fatih/color v1.13.0/go.mod h1:kLAiJbzzSOZDVNGyDpeOxJ47H46qBXwg5ILebYFFOfk=
|
||||||
|
github.com/felixge/fgprof v0.9.3 h1:VvyZxILNuCiUCSXtPtYmmtGvb65nqXh2QFWc0Wpf2/g=
|
||||||
|
github.com/felixge/fgprof v0.9.3/go.mod h1:RdbpDgzqYVh/T9fPELJyV7EYJuHB55UTEULNun8eiPw=
|
||||||
github.com/form3tech-oss/jwt-go v3.2.2+incompatible/go.mod h1:pbq4aXjuKjdthFRnoDwaVPLA+WlJuPGy+QneDUgJi2k=
|
github.com/form3tech-oss/jwt-go v3.2.2+incompatible/go.mod h1:pbq4aXjuKjdthFRnoDwaVPLA+WlJuPGy+QneDUgJi2k=
|
||||||
github.com/form3tech-oss/jwt-go v3.2.3+incompatible/go.mod h1:pbq4aXjuKjdthFRnoDwaVPLA+WlJuPGy+QneDUgJi2k=
|
github.com/form3tech-oss/jwt-go v3.2.3+incompatible/go.mod h1:pbq4aXjuKjdthFRnoDwaVPLA+WlJuPGy+QneDUgJi2k=
|
||||||
github.com/fortytw2/leaktest v1.3.0/go.mod h1:jDsjWgpAGjm2CA7WthBh/CdZYEPF31XHquHwclZch5g=
|
github.com/fortytw2/leaktest v1.3.0/go.mod h1:jDsjWgpAGjm2CA7WthBh/CdZYEPF31XHquHwclZch5g=
|
||||||
@@ -160,16 +493,16 @@ github.com/go-openapi/swag v0.19.5/go.mod h1:POnQmlKehdgb5mhVOsnJFsivZCEZ/vjK9gh
|
|||||||
github.com/go-redis/redis/v8 v8.11.5 h1:AcZZR7igkdvfVmQTPnu9WE37LRrO/YrBH5zWyjDC0oI=
|
github.com/go-redis/redis/v8 v8.11.5 h1:AcZZR7igkdvfVmQTPnu9WE37LRrO/YrBH5zWyjDC0oI=
|
||||||
github.com/go-redis/redis/v8 v8.11.5/go.mod h1:gREzHqY1hg6oD9ngVRbLStwAWKhA0FEgq8Jd4h5lpwo=
|
github.com/go-redis/redis/v8 v8.11.5/go.mod h1:gREzHqY1hg6oD9ngVRbLStwAWKhA0FEgq8Jd4h5lpwo=
|
||||||
github.com/go-sql-driver/mysql v1.4.0/go.mod h1:zAC/RDZ24gD3HViQzih4MyKcchzm+sOG5ZlKdlhCg5w=
|
github.com/go-sql-driver/mysql v1.4.0/go.mod h1:zAC/RDZ24gD3HViQzih4MyKcchzm+sOG5ZlKdlhCg5w=
|
||||||
github.com/go-sql-driver/mysql v1.6.0 h1:BCTh4TKNUYmOmMUcQ3IipzF5prigylS7XXjEkfCHuOE=
|
github.com/go-sql-driver/mysql v1.7.0 h1:ueSltNNllEqE3qcWBTD0iQd3IpL/6U+mJxLkazJ7YPc=
|
||||||
github.com/go-sql-driver/mysql v1.6.0/go.mod h1:DCzpHaOWr8IXmIStZouvnhqoel9Qv2LBy8hT2VhHyBg=
|
github.com/go-sql-driver/mysql v1.7.0/go.mod h1:OXbVy3sEdcQ2Doequ6Z5BW6fXNQTmx+9S1MCJN5yJMI=
|
||||||
github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY=
|
github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY=
|
||||||
github.com/go-task/slim-sprig v0.0.0-20210107165309-348f09dbbbc0/go.mod h1:fyg7847qk6SyHyPtNmDHnmrv/HOrqktSC+C9fM+CJOE=
|
github.com/go-task/slim-sprig v0.0.0-20210107165309-348f09dbbbc0/go.mod h1:fyg7847qk6SyHyPtNmDHnmrv/HOrqktSC+C9fM+CJOE=
|
||||||
github.com/godbus/dbus/v5 v5.0.4/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA=
|
github.com/godbus/dbus/v5 v5.0.4/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA=
|
||||||
github.com/gogo/protobuf v1.1.1/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ=
|
github.com/gogo/protobuf v1.1.1/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ=
|
||||||
github.com/gogo/protobuf v1.3.2 h1:Ov1cvc58UF3b5XjBnZv7+opcTcQFZebYjWzi34vdm4Q=
|
github.com/gogo/protobuf v1.3.2 h1:Ov1cvc58UF3b5XjBnZv7+opcTcQFZebYjWzi34vdm4Q=
|
||||||
github.com/gogo/protobuf v1.3.2/go.mod h1:P1XiOD3dCwIKUDQYPy72D8LYyHL2YPYrpS2s69NZV8Q=
|
github.com/gogo/protobuf v1.3.2/go.mod h1:P1XiOD3dCwIKUDQYPy72D8LYyHL2YPYrpS2s69NZV8Q=
|
||||||
github.com/golang-jwt/jwt/v4 v4.4.2 h1:rcc4lwaZgFMCZ5jxF9ABolDcIHdBytAFgqFPbSJQAYs=
|
github.com/golang-jwt/jwt/v4 v4.4.3 h1:Hxl6lhQFj4AnOX6MLrsCb/+7tCj7DxP7VA+2rDIq5AU=
|
||||||
github.com/golang-jwt/jwt/v4 v4.4.2/go.mod h1:m21LjoU+eqJr34lmDMbreY2eSTRJ1cv77w39/MY0Ch0=
|
github.com/golang-jwt/jwt/v4 v4.4.3/go.mod h1:m21LjoU+eqJr34lmDMbreY2eSTRJ1cv77w39/MY0Ch0=
|
||||||
github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q=
|
github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q=
|
||||||
github.com/golang/glog v1.0.0 h1:nfP3RFugxnNRyKgeWd4oI1nYvXpxrx8ck8ZrcizshdQ=
|
github.com/golang/glog v1.0.0 h1:nfP3RFugxnNRyKgeWd4oI1nYvXpxrx8ck8ZrcizshdQ=
|
||||||
github.com/golang/glog v1.0.0/go.mod h1:EWib/APOK0SL3dFbYqvxE3UYd8E6s1ouQ7iEp/0LWV4=
|
github.com/golang/glog v1.0.0/go.mod h1:EWib/APOK0SL3dFbYqvxE3UYd8E6s1ouQ7iEp/0LWV4=
|
||||||
@@ -184,6 +517,7 @@ github.com/golang/mock v1.4.0/go.mod h1:UOMv5ysSaYNkG+OFQykRIcU/QvvxJf3p21QfJ2Bt
|
|||||||
github.com/golang/mock v1.4.1/go.mod h1:UOMv5ysSaYNkG+OFQykRIcU/QvvxJf3p21QfJ2Bt3cw=
|
github.com/golang/mock v1.4.1/go.mod h1:UOMv5ysSaYNkG+OFQykRIcU/QvvxJf3p21QfJ2Bt3cw=
|
||||||
github.com/golang/mock v1.4.3/go.mod h1:UOMv5ysSaYNkG+OFQykRIcU/QvvxJf3p21QfJ2Bt3cw=
|
github.com/golang/mock v1.4.3/go.mod h1:UOMv5ysSaYNkG+OFQykRIcU/QvvxJf3p21QfJ2Bt3cw=
|
||||||
github.com/golang/mock v1.4.4/go.mod h1:l3mdAwkq5BuhzHwde/uurv3sEJeZMXNpwsxVWU71h+4=
|
github.com/golang/mock v1.4.4/go.mod h1:l3mdAwkq5BuhzHwde/uurv3sEJeZMXNpwsxVWU71h+4=
|
||||||
|
github.com/golang/mock v1.5.0/go.mod h1:CWnOUgYIOo4TcNZ0wHX3YZCqsaM1I1Jvs6v3mP3KVu8=
|
||||||
github.com/golang/mock v1.6.0 h1:ErTB+efbowRARo13NNdxyJji2egdxLGQhRaY+DUumQc=
|
github.com/golang/mock v1.6.0 h1:ErTB+efbowRARo13NNdxyJji2egdxLGQhRaY+DUumQc=
|
||||||
github.com/golang/mock v1.6.0/go.mod h1:p6yTPP+5HYm5mzsMV8JkE6ZKdX+/wYM6Hr+LicevLPs=
|
github.com/golang/mock v1.6.0/go.mod h1:p6yTPP+5HYm5mzsMV8JkE6ZKdX+/wYM6Hr+LicevLPs=
|
||||||
github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
|
github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
|
||||||
@@ -201,9 +535,11 @@ 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.1/go.mod h1:DopwsBzvsk0Fs44TXzsVbJyPhcCPeIwnvohx4u74HPM=
|
||||||
github.com/golang/protobuf v1.5.2 h1:ROPKBNFfQgOUMifHyP+KYbvpjbdoFNs+aK7DXlji0Tw=
|
github.com/golang/protobuf v1.5.2 h1:ROPKBNFfQgOUMifHyP+KYbvpjbdoFNs+aK7DXlji0Tw=
|
||||||
github.com/golang/protobuf v1.5.2/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY=
|
github.com/golang/protobuf v1.5.2/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY=
|
||||||
github.com/golang/snappy v0.0.1/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q=
|
github.com/golang/snappy v0.0.1/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q=
|
||||||
|
github.com/golang/snappy v0.0.3/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q=
|
||||||
github.com/golang/snappy v0.0.4 h1:yAGX7huGHXlcLOEtBnF4w7FQwA26wojNCwOYAEhLjQM=
|
github.com/golang/snappy v0.0.4 h1:yAGX7huGHXlcLOEtBnF4w7FQwA26wojNCwOYAEhLjQM=
|
||||||
github.com/golang/snappy v0.0.4/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q=
|
github.com/golang/snappy v0.0.4/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q=
|
||||||
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=
|
||||||
@@ -217,18 +553,22 @@ github.com/google/go-cmp v0.4.1/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/
|
|||||||
github.com/google/go-cmp v0.5.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
|
github.com/google/go-cmp v0.5.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
|
||||||
github.com/google/go-cmp v0.5.1/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
|
github.com/google/go-cmp v0.5.1/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
|
||||||
github.com/google/go-cmp v0.5.2/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
|
github.com/google/go-cmp v0.5.2/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
|
||||||
|
github.com/google/go-cmp v0.5.3/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
|
||||||
github.com/google/go-cmp v0.5.4/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
|
github.com/google/go-cmp v0.5.4/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
|
||||||
github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
|
github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
|
||||||
github.com/google/go-cmp v0.5.6/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
|
github.com/google/go-cmp v0.5.6/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
|
||||||
github.com/google/go-cmp v0.5.7/go.mod h1:n+brtR0CgQNWTVd5ZUFpTBC8YFBDLK/h/bpaJ8/DtOE=
|
github.com/google/go-cmp v0.5.7/go.mod h1:n+brtR0CgQNWTVd5ZUFpTBC8YFBDLK/h/bpaJ8/DtOE=
|
||||||
github.com/google/go-cmp v0.5.8 h1:e6P7q2lk1O+qJJb4BtCQXlK8vWEO8V1ZeuEdJNOqZyg=
|
|
||||||
github.com/google/go-cmp v0.5.8/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY=
|
github.com/google/go-cmp v0.5.8/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY=
|
||||||
|
github.com/google/go-cmp v0.5.9 h1:O2Tfq5qg4qc4AmwVlvv0oLiVAGB7enBSJ2x2DqQFi38=
|
||||||
|
github.com/google/go-cmp v0.5.9/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY=
|
||||||
github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg=
|
github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg=
|
||||||
github.com/google/gofuzz v1.1.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg=
|
github.com/google/gofuzz v1.1.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg=
|
||||||
github.com/google/gofuzz v1.2.0 h1:xRy4A+RhZaiKjJ1bPfwQ8sedCA+YS2YcCHW6ec7JMi0=
|
github.com/google/gofuzz v1.2.0 h1:xRy4A+RhZaiKjJ1bPfwQ8sedCA+YS2YcCHW6ec7JMi0=
|
||||||
github.com/google/gofuzz v1.2.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg=
|
github.com/google/gofuzz v1.2.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg=
|
||||||
github.com/google/martian v2.1.0+incompatible/go.mod h1:9I4somxYTbIHy5NJKHRl3wXiIaQGbYVAs8BPL6v8lEs=
|
github.com/google/martian v2.1.0+incompatible/go.mod h1:9I4somxYTbIHy5NJKHRl3wXiIaQGbYVAs8BPL6v8lEs=
|
||||||
github.com/google/martian/v3 v3.0.0/go.mod h1:y5Zk1BBys9G+gd6Jrk0W3cC1+ELVxBWuIGO+w/tUAp0=
|
github.com/google/martian/v3 v3.0.0/go.mod h1:y5Zk1BBys9G+gd6Jrk0W3cC1+ELVxBWuIGO+w/tUAp0=
|
||||||
|
github.com/google/martian/v3 v3.1.0/go.mod h1:y5Zk1BBys9G+gd6Jrk0W3cC1+ELVxBWuIGO+w/tUAp0=
|
||||||
|
github.com/google/martian/v3 v3.2.1/go.mod h1:oBOf6HBosgwRXnUGWUB05QECsc6uvmMiJ3+6W4l/CUk=
|
||||||
github.com/google/pprof v0.0.0-20181206194817-3ea8567a2e57/go.mod h1:zfwlbNMJ+OItoe0UupaVj+oy1omPYYDuagoSzA8v9mc=
|
github.com/google/pprof v0.0.0-20181206194817-3ea8567a2e57/go.mod h1:zfwlbNMJ+OItoe0UupaVj+oy1omPYYDuagoSzA8v9mc=
|
||||||
github.com/google/pprof v0.0.0-20190515194954-54271f7e092f/go.mod h1:zfwlbNMJ+OItoe0UupaVj+oy1omPYYDuagoSzA8v9mc=
|
github.com/google/pprof v0.0.0-20190515194954-54271f7e092f/go.mod h1:zfwlbNMJ+OItoe0UupaVj+oy1omPYYDuagoSzA8v9mc=
|
||||||
github.com/google/pprof v0.0.0-20191218002539-d4f498aebedc/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM=
|
github.com/google/pprof v0.0.0-20191218002539-d4f498aebedc/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM=
|
||||||
@@ -236,17 +576,37 @@ github.com/google/pprof v0.0.0-20200212024743-f11f1df84d12/go.mod h1:ZgVRPoUq/hf
|
|||||||
github.com/google/pprof v0.0.0-20200229191704-1ebb73c60ed3/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM=
|
github.com/google/pprof v0.0.0-20200229191704-1ebb73c60ed3/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM=
|
||||||
github.com/google/pprof v0.0.0-20200430221834-fc25d7d30c6d/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM=
|
github.com/google/pprof v0.0.0-20200430221834-fc25d7d30c6d/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM=
|
||||||
github.com/google/pprof v0.0.0-20200708004538-1a94d8640e99/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM=
|
github.com/google/pprof v0.0.0-20200708004538-1a94d8640e99/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM=
|
||||||
|
github.com/google/pprof v0.0.0-20201023163331-3e6fc7fc9c4c/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE=
|
||||||
|
github.com/google/pprof v0.0.0-20201203190320-1bf35d6f28c2/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE=
|
||||||
|
github.com/google/pprof v0.0.0-20210122040257-d980be63207e/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE=
|
||||||
|
github.com/google/pprof v0.0.0-20210226084205-cbba55b83ad5/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE=
|
||||||
github.com/google/pprof v0.0.0-20210407192527-94a9f03dee38/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE=
|
github.com/google/pprof v0.0.0-20210407192527-94a9f03dee38/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE=
|
||||||
|
github.com/google/pprof v0.0.0-20210601050228-01bbb1931b22/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE=
|
||||||
|
github.com/google/pprof v0.0.0-20210609004039-a478d1d731e9/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE=
|
||||||
|
github.com/google/pprof v0.0.0-20210720184732-4bb14d4b1be1/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE=
|
||||||
|
github.com/google/pprof v0.0.0-20211214055906-6f57359322fd h1:1FjCyPC+syAzJ5/2S8fqdZK1R22vvA0J7JZKcuOIQ7Y=
|
||||||
|
github.com/google/pprof v0.0.0-20211214055906-6f57359322fd/go.mod h1:KgnwoLYCZ8IQu3XUZ8Nc/bM9CCZFOyjUNOSygVozoDg=
|
||||||
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/uuid v1.1.1/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
|
github.com/google/uuid v1.1.1/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
|
||||||
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/google/uuid v1.3.0 h1:t6JiXgmwXMjEs8VusXIJk2BXHsn+wx8BZdTaoZ5fu7I=
|
github.com/google/uuid v1.3.0 h1:t6JiXgmwXMjEs8VusXIJk2BXHsn+wx8BZdTaoZ5fu7I=
|
||||||
github.com/google/uuid v1.3.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
|
github.com/google/uuid v1.3.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
|
||||||
|
github.com/googleapis/enterprise-certificate-proxy v0.0.0-20220520183353-fd19c99a87aa/go.mod h1:17drOmN3MwGY7t0e+Ei9b45FFGA3fBs3x36SsCg1hq8=
|
||||||
|
github.com/googleapis/enterprise-certificate-proxy v0.1.0/go.mod h1:17drOmN3MwGY7t0e+Ei9b45FFGA3fBs3x36SsCg1hq8=
|
||||||
|
github.com/googleapis/enterprise-certificate-proxy v0.2.0/go.mod h1:8C0jb7/mgJe/9KK8Lm7X9ctZC2t60YyIpYEI16jx0Qg=
|
||||||
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.1.0/go.mod h1:Q3nei7sK6ybPYH7twZdmQpAd1MKb7pfu6SK+H1/DsU0=
|
||||||
|
github.com/googleapis/gax-go/v2 v2.1.1/go.mod h1:hddJymUZASv3XPyGkUpKj8pPO47Rmb0eJc8R6ouapiM=
|
||||||
|
github.com/googleapis/gax-go/v2 v2.2.0/go.mod h1:as02EH8zWkzwUoLbBaFeQ+arQaj/OthfcblKl4IGNaM=
|
||||||
|
github.com/googleapis/gax-go/v2 v2.3.0/go.mod h1:b8LNqSzNabLiUpXKkY7HAR5jr6bIT99EXz9pXxye9YM=
|
||||||
|
github.com/googleapis/gax-go/v2 v2.4.0/go.mod h1:XOTVJ59hdnfJLIP/dh8n5CGryZR2LxK9wbMD5+iXC6c=
|
||||||
|
github.com/googleapis/gax-go/v2 v2.5.1/go.mod h1:h6B0KMMFNtI2ddbGJn3T3ZbwkeT6yqEF02fYlzkUCyo=
|
||||||
|
github.com/googleapis/gax-go/v2 v2.6.0/go.mod h1:1mjbznJAPHFpesgE5ucqfYEscaz5kMdcIDwU/6+DDoY=
|
||||||
github.com/googleapis/gnostic v0.5.1/go.mod h1:6U4PtQXGIEt/Z3h5MAT7FNofLnw9vXk2cUuW7uA/OeU=
|
github.com/googleapis/gnostic v0.5.1/go.mod h1:6U4PtQXGIEt/Z3h5MAT7FNofLnw9vXk2cUuW7uA/OeU=
|
||||||
github.com/googleapis/gnostic v0.5.5 h1:9fHAtK0uDfpveeqqo1hkEZJcFvYXAiCN3UutL8F9xHw=
|
github.com/googleapis/gnostic v0.5.5 h1:9fHAtK0uDfpveeqqo1hkEZJcFvYXAiCN3UutL8F9xHw=
|
||||||
github.com/googleapis/gnostic v0.5.5/go.mod h1:7+EbHbldMins07ALC74bsA81Ovc97DwqyJO1AENw9kA=
|
github.com/googleapis/gnostic v0.5.5/go.mod h1:7+EbHbldMins07ALC74bsA81Ovc97DwqyJO1AENw9kA=
|
||||||
|
github.com/googleapis/go-type-adapters v1.0.0/go.mod h1:zHW75FOG2aur7gAO2B+MLby+cLsWGBF62rFAi7WjWO4=
|
||||||
github.com/gorilla/handlers v1.4.2/go.mod h1:Qkdc/uu4tH4g6mTK6auzZ766c4CA0Ng8+o/OAirnOIQ=
|
github.com/gorilla/handlers v1.4.2/go.mod h1:Qkdc/uu4tH4g6mTK6auzZ766c4CA0Ng8+o/OAirnOIQ=
|
||||||
github.com/gorilla/mux v1.8.0/go.mod h1:DVbg23sWSpFRCP0SfiEN6jmj59UnW/n46BH5rLB71So=
|
github.com/gorilla/mux v1.8.0/go.mod h1:DVbg23sWSpFRCP0SfiEN6jmj59UnW/n46BH5rLB71So=
|
||||||
github.com/gorilla/securecookie v1.1.1/go.mod h1:ra0sb63/xPlUeL+yeDciTfxMRAA+MP+HVt/4epWDjd4=
|
github.com/gorilla/securecookie v1.1.1/go.mod h1:ra0sb63/xPlUeL+yeDciTfxMRAA+MP+HVt/4epWDjd4=
|
||||||
@@ -267,6 +627,7 @@ github.com/hashicorp/golang-lru v0.5.1/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ
|
|||||||
github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU=
|
github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU=
|
||||||
github.com/ianlancetaylor/demangle v0.0.0-20181102032728-5e5cf60278f6/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc=
|
github.com/ianlancetaylor/demangle v0.0.0-20181102032728-5e5cf60278f6/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc=
|
||||||
github.com/ianlancetaylor/demangle v0.0.0-20200824232613-28f6c0f3b639/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc=
|
github.com/ianlancetaylor/demangle v0.0.0-20200824232613-28f6c0f3b639/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc=
|
||||||
|
github.com/ianlancetaylor/demangle v0.0.0-20210905161508-09a460cdf81d/go.mod h1:aYm2/VgdVmcIU8iMfdMvDMsRAQjcfZSKFby6HOFvi/w=
|
||||||
github.com/imdario/mergo v0.3.5/go.mod h1:2EnlNZ0deacrJVfApfmtdGgDfMuh/nq6Ok1EcJh5FfA=
|
github.com/imdario/mergo v0.3.5/go.mod h1:2EnlNZ0deacrJVfApfmtdGgDfMuh/nq6Ok1EcJh5FfA=
|
||||||
github.com/jcmturner/aescts/v2 v2.0.0/go.mod h1:AiaICIRyfYg35RUkr8yESTqvSy7csK90qZ5xfvvsoNs=
|
github.com/jcmturner/aescts/v2 v2.0.0/go.mod h1:AiaICIRyfYg35RUkr8yESTqvSy7csK90qZ5xfvvsoNs=
|
||||||
github.com/jcmturner/dnsutils/v2 v2.0.0/go.mod h1:b0TnjGOvI/n42bZa+hmXL+kFJZsFT7G4t3HTlQ184QM=
|
github.com/jcmturner/dnsutils/v2 v2.0.0/go.mod h1:b0TnjGOvI/n42bZa+hmXL+kFJZsFT7G4t3HTlQ184QM=
|
||||||
@@ -279,8 +640,8 @@ github.com/jhump/gopoet v0.1.0/go.mod h1:me9yfT6IJSlOL3FCfrg+L6yzUEZ+5jW6WHt4Sk+
|
|||||||
github.com/jhump/goprotoc v0.5.0/go.mod h1:VrbvcYrQOrTi3i0Vf+m+oqQWk9l72mjkJCYo7UvLHRQ=
|
github.com/jhump/goprotoc v0.5.0/go.mod h1:VrbvcYrQOrTi3i0Vf+m+oqQWk9l72mjkJCYo7UvLHRQ=
|
||||||
github.com/jhump/protoreflect v1.11.0/go.mod h1:U7aMIjN0NWq9swDP7xDdoMfRHb35uiuTd3Z9nFXJf5E=
|
github.com/jhump/protoreflect v1.11.0/go.mod h1:U7aMIjN0NWq9swDP7xDdoMfRHb35uiuTd3Z9nFXJf5E=
|
||||||
github.com/jhump/protoreflect v1.12.0/go.mod h1:JytZfP5d0r8pVNLZvai7U/MCuTWITgrI4tTg7puQFKI=
|
github.com/jhump/protoreflect v1.12.0/go.mod h1:JytZfP5d0r8pVNLZvai7U/MCuTWITgrI4tTg7puQFKI=
|
||||||
github.com/jhump/protoreflect v1.13.0 h1:zrrZqa7JAc2YGgPSzZZkmUXJ5G6NRPdxOg/9t7ISImA=
|
github.com/jhump/protoreflect v1.14.0 h1:MBbQK392K3u8NTLbKOCIi3XdI+y+c6yt5oMq0X3xviw=
|
||||||
github.com/jhump/protoreflect v1.13.0/go.mod h1:JytZfP5d0r8pVNLZvai7U/MCuTWITgrI4tTg7puQFKI=
|
github.com/jhump/protoreflect v1.14.0/go.mod h1:JytZfP5d0r8pVNLZvai7U/MCuTWITgrI4tTg7puQFKI=
|
||||||
github.com/jmoiron/sqlx v1.2.0/go.mod h1:1FEQNm3xlJgrMD+FBdI9+xvCksHtbpVBBw5dYhBSsks=
|
github.com/jmoiron/sqlx v1.2.0/go.mod h1:1FEQNm3xlJgrMD+FBdI9+xvCksHtbpVBBw5dYhBSsks=
|
||||||
github.com/jpillora/backoff v1.0.0/go.mod h1:J/6gKK9jxlEcS3zixgDgUAsiuZ7yrSoa/FX5e0EB2j4=
|
github.com/jpillora/backoff v1.0.0/go.mod h1:J/6gKK9jxlEcS3zixgDgUAsiuZ7yrSoa/FX5e0EB2j4=
|
||||||
github.com/json-iterator/go v1.1.6/go.mod h1:+SdeFBvtyEkXs7REEP0seUULqWtbJapLOCVDaaPEHmU=
|
github.com/json-iterator/go v1.1.6/go.mod h1:+SdeFBvtyEkXs7REEP0seUULqWtbJapLOCVDaaPEHmU=
|
||||||
@@ -368,8 +729,8 @@ github.com/openzipkin/zipkin-go v0.4.0/go.mod h1:4c3sLeE8xjNqehmF5RpAFLPLJxXscc0
|
|||||||
github.com/paulmach/orb v0.5.0 h1:sNhJV5ML+mv1F077ljOck/9inorF4ahDO8iNNpHbKHY=
|
github.com/paulmach/orb v0.5.0 h1:sNhJV5ML+mv1F077ljOck/9inorF4ahDO8iNNpHbKHY=
|
||||||
github.com/paulmach/orb v0.5.0/go.mod h1:FWRlTgl88VI1RBx/MkrwWDRhQ96ctqMCh8boXhmqB/A=
|
github.com/paulmach/orb v0.5.0/go.mod h1:FWRlTgl88VI1RBx/MkrwWDRhQ96ctqMCh8boXhmqB/A=
|
||||||
github.com/paulmach/protoscan v0.2.1/go.mod h1:SpcSwydNLrxUGSDvXvO0P7g7AuhJ7lcKfDlhJCDw2gY=
|
github.com/paulmach/protoscan v0.2.1/go.mod h1:SpcSwydNLrxUGSDvXvO0P7g7AuhJ7lcKfDlhJCDw2gY=
|
||||||
github.com/pelletier/go-toml/v2 v2.0.5 h1:ipoSadvV8oGUjnUbMub59IDPPwfxF694nG/jwbMiyQg=
|
github.com/pelletier/go-toml/v2 v2.0.6 h1:nrzqCb7j9cDFj2coyLNLaZuJTLjWjlaz6nvTvIwycIU=
|
||||||
github.com/pelletier/go-toml/v2 v2.0.5/go.mod h1:OMHamSCAODeSsVrwwvcJOaoN0LIUIaFVNZzmWyNfXas=
|
github.com/pelletier/go-toml/v2 v2.0.6/go.mod h1:eumQOmlWiOPt5WriQQqoM5y18pDHwha2N+QD+EUNTek=
|
||||||
github.com/peterbourgon/diskv v2.0.1+incompatible/go.mod h1:uqqh8zWWbv1HBMNONnaR/tNboyR3/BZd58JJSHlUSCU=
|
github.com/peterbourgon/diskv v2.0.1+incompatible/go.mod h1:uqqh8zWWbv1HBMNONnaR/tNboyR3/BZd58JJSHlUSCU=
|
||||||
github.com/pierrec/lz4 v2.0.5+incompatible/go.mod h1:pdkljMzZIN41W+lC3N2tnIh5sFi+IEE17M5jbnwPHcY=
|
github.com/pierrec/lz4 v2.0.5+incompatible/go.mod h1:pdkljMzZIN41W+lC3N2tnIh5sFi+IEE17M5jbnwPHcY=
|
||||||
github.com/pierrec/lz4 v2.6.1+incompatible h1:9UY3+iC23yxF0UfGaYrGplQ+79Rg+h/q9FV9ix19jjM=
|
github.com/pierrec/lz4 v2.6.1+incompatible h1:9UY3+iC23yxF0UfGaYrGplQ+79Rg+h/q9FV9ix19jjM=
|
||||||
@@ -437,8 +798,9 @@ github.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An
|
|||||||
github.com/stoewer/go-strcase v1.2.0/go.mod h1:IBiWB2sKIp3wVVQ3Y035++gc+knqhUQag1KpM8ahLw8=
|
github.com/stoewer/go-strcase v1.2.0/go.mod h1:IBiWB2sKIp3wVVQ3Y035++gc+knqhUQag1KpM8ahLw8=
|
||||||
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=
|
||||||
github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
|
github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
|
||||||
github.com/stretchr/objx v0.4.0 h1:M2gUjqZET1qApGOWNSnZ49BAIMX4F/1plDv3+l31EJ4=
|
|
||||||
github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw=
|
github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw=
|
||||||
|
github.com/stretchr/objx v0.5.0 h1:1zr/of2m5FGMsad5YfcqgdqdWrIhu+EBEJRhR1U7z/c=
|
||||||
|
github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo=
|
||||||
github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs=
|
github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs=
|
||||||
github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
|
github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
|
||||||
github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4=
|
github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4=
|
||||||
@@ -446,8 +808,9 @@ github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5
|
|||||||
github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
|
github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
|
||||||
github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
|
github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
|
||||||
github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
|
github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
|
||||||
github.com/stretchr/testify v1.8.0 h1:pSgiaMZlXftHpm5L7V1+rVB+AZJydKsMxsQBIJw4PKk=
|
|
||||||
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 h1:w7B6lhMri9wdJUVmEZPGGhZzrYTPvgJArz7wNPgYKsk=
|
||||||
|
github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4=
|
||||||
github.com/tidwall/pretty v1.0.0 h1:HsD+QiTn7sK6flMKIvNmpqz1qrpP3Ps6jOKIKMooyg4=
|
github.com/tidwall/pretty v1.0.0 h1:HsD+QiTn7sK6flMKIvNmpqz1qrpP3Ps6jOKIKMooyg4=
|
||||||
github.com/tidwall/pretty v1.0.0/go.mod h1:XNkn88O1ChpSDQmQeStsy+sBenx6DDtFZJxhVysOjyk=
|
github.com/tidwall/pretty v1.0.0/go.mod h1:XNkn88O1ChpSDQmQeStsy+sBenx6DDtFZJxhVysOjyk=
|
||||||
github.com/tklauser/go-sysconf v0.3.10/go.mod h1:C8XykCvCb+Gn0oNCWPIlcb0RuglQTYaQ2hGm7jmxEFk=
|
github.com/tklauser/go-sysconf v0.3.10/go.mod h1:C8XykCvCb+Gn0oNCWPIlcb0RuglQTYaQ2hGm7jmxEFk=
|
||||||
@@ -468,21 +831,24 @@ github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9de
|
|||||||
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/gopher-lua v0.0.0-20210529063254-f4c35e4016d9 h1:k/gmLsJDWwWqbLCur2yWnJzwQEKRcAHXo6seXGuSwWw=
|
github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY=
|
||||||
github.com/yuin/gopher-lua v0.0.0-20210529063254-f4c35e4016d9/go.mod h1:E1AXubJBdNmFERAOucpDIxNzeGfLzg0mYh+UfMWdChA=
|
github.com/yuin/gopher-lua v0.0.0-20220504180219-658193537a64 h1:5mLPGnFdSsevFRFc9q3yYbBkB6tsm4aCwwQV/j1JQAQ=
|
||||||
|
github.com/yuin/gopher-lua v0.0.0-20220504180219-658193537a64/go.mod h1:GBR0iDaNXjAgGg9zfCvksxSRnQx76gclCIb7kdAd1Pw=
|
||||||
go.etcd.io/etcd/api/v3 v3.5.5 h1:BX4JIbQ7hl7+jL+g+2j5UAr0o1bctCm6/Ct+ArBGkf0=
|
go.etcd.io/etcd/api/v3 v3.5.5 h1:BX4JIbQ7hl7+jL+g+2j5UAr0o1bctCm6/Ct+ArBGkf0=
|
||||||
go.etcd.io/etcd/api/v3 v3.5.5/go.mod h1:KFtNaxGDw4Yx/BA4iPPwevUTAuqcsPxzyX8PHydchN8=
|
go.etcd.io/etcd/api/v3 v3.5.5/go.mod h1:KFtNaxGDw4Yx/BA4iPPwevUTAuqcsPxzyX8PHydchN8=
|
||||||
go.etcd.io/etcd/client/pkg/v3 v3.5.5 h1:9S0JUVvmrVl7wCF39iTQthdaaNIiAaQbmK75ogO6GU8=
|
go.etcd.io/etcd/client/pkg/v3 v3.5.5 h1:9S0JUVvmrVl7wCF39iTQthdaaNIiAaQbmK75ogO6GU8=
|
||||||
go.etcd.io/etcd/client/pkg/v3 v3.5.5/go.mod h1:ggrwbk069qxpKPq8/FKkQ3Xq9y39kbFR4LnKszpRXeQ=
|
go.etcd.io/etcd/client/pkg/v3 v3.5.5/go.mod h1:ggrwbk069qxpKPq8/FKkQ3Xq9y39kbFR4LnKszpRXeQ=
|
||||||
go.etcd.io/etcd/client/v3 v3.5.5 h1:q++2WTJbUgpQu4B6hCuT7VkdwaTP7Qz6Daak3WzbrlI=
|
go.etcd.io/etcd/client/v3 v3.5.5 h1:q++2WTJbUgpQu4B6hCuT7VkdwaTP7Qz6Daak3WzbrlI=
|
||||||
go.etcd.io/etcd/client/v3 v3.5.5/go.mod h1:aApjR4WGlSumpnJ2kloS75h6aHUmAyaPLjHMxpc7E7c=
|
go.etcd.io/etcd/client/v3 v3.5.5/go.mod h1:aApjR4WGlSumpnJ2kloS75h6aHUmAyaPLjHMxpc7E7c=
|
||||||
go.mongodb.org/mongo-driver v1.10.2 h1:4Wk3cnqOrQCn0P92L3/mmurMxzdvWWs5J9jinAVKD+k=
|
go.mongodb.org/mongo-driver v1.11.1 h1:QP0znIRTuL0jf1oBQoAoM0C6ZJfBK4kx0Uumtv1A7w8=
|
||||||
go.mongodb.org/mongo-driver v1.10.2/go.mod h1:z4XpeoU6w+9Vht+jAFyLgVrD+jGSQQe0+CBWFHNiHt8=
|
go.mongodb.org/mongo-driver v1.11.1/go.mod h1:s7p5vEtfbeR1gYi6pnj3c3/urpbLv2T5Sfd6Rp2HBB8=
|
||||||
go.opencensus.io v0.21.0/go.mod h1:mSImk1erAIZhrmZN+AvHh14ztQfjbGwt4TtuofqLduU=
|
go.opencensus.io v0.21.0/go.mod h1:mSImk1erAIZhrmZN+AvHh14ztQfjbGwt4TtuofqLduU=
|
||||||
go.opencensus.io v0.22.0/go.mod h1:+kGneAE2xo2IficOXnaByMWTGM9T73dGwxeWcUqIpI8=
|
go.opencensus.io v0.22.0/go.mod h1:+kGneAE2xo2IficOXnaByMWTGM9T73dGwxeWcUqIpI8=
|
||||||
go.opencensus.io v0.22.2/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw=
|
go.opencensus.io v0.22.2/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw=
|
||||||
go.opencensus.io v0.22.3/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw=
|
go.opencensus.io v0.22.3/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw=
|
||||||
go.opencensus.io v0.22.4/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw=
|
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.23.0/go.mod h1:XItmlyltB5F7CS4xOC1DcqMoFqwtC6OG2xF7mCv7P7E=
|
||||||
go.opentelemetry.io/otel v1.7.0/go.mod h1:5BdUoMIz5WEs0vt0CUEMtSSaTSHBBVwrhnz7+nrD5xk=
|
go.opentelemetry.io/otel v1.7.0/go.mod h1:5BdUoMIz5WEs0vt0CUEMtSSaTSHBBVwrhnz7+nrD5xk=
|
||||||
go.opentelemetry.io/otel v1.10.0 h1:Y7DTJMR6zs1xkS/upamJYk0SxxN4C9AqRd77jmZnyY4=
|
go.opentelemetry.io/otel v1.10.0 h1:Y7DTJMR6zs1xkS/upamJYk0SxxN4C9AqRd77jmZnyY4=
|
||||||
go.opentelemetry.io/otel v1.10.0/go.mod h1:NbvWjCthWHKBEUMpf0/v8ZRZlni86PpGFEMA9pnQSnQ=
|
go.opentelemetry.io/otel v1.10.0/go.mod h1:NbvWjCthWHKBEUMpf0/v8ZRZlni86PpGFEMA9pnQSnQ=
|
||||||
@@ -529,6 +895,7 @@ golang.org/x/crypto v0.0.0-20201002170205-7f63de1d35b0/go.mod h1:LzIPMQfyMNhhGPh
|
|||||||
golang.org/x/crypto v0.0.0-20201112155050-0c6587e931a9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
|
golang.org/x/crypto v0.0.0-20201112155050-0c6587e931a9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
|
||||||
golang.org/x/crypto v0.0.0-20210220033148-5ea612d1eb83/go.mod h1:jdWPYTVW3xRLrWPugEBEK3UY2ZEsg3UU495nc5E+M+I=
|
golang.org/x/crypto v0.0.0-20210220033148-5ea612d1eb83/go.mod h1:jdWPYTVW3xRLrWPugEBEK3UY2ZEsg3UU495nc5E+M+I=
|
||||||
golang.org/x/crypto v0.0.0-20210920023735-84f357641f63/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
|
golang.org/x/crypto v0.0.0-20210920023735-84f357641f63/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
|
||||||
|
golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
|
||||||
golang.org/x/crypto v0.0.0-20220622213112-05595931fe9d h1:sK3txAijHtOK88l68nt020reeT1ZdKLIYetKl95FzVY=
|
golang.org/x/crypto v0.0.0-20220622213112-05595931fe9d h1:sK3txAijHtOK88l68nt020reeT1ZdKLIYetKl95FzVY=
|
||||||
golang.org/x/crypto v0.0.0-20220622213112-05595931fe9d/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4=
|
golang.org/x/crypto v0.0.0-20220622213112-05595931fe9d/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4=
|
||||||
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=
|
||||||
@@ -553,6 +920,7 @@ golang.org/x/lint v0.0.0-20190930215403-16217165b5de/go.mod h1:6SW0HCj/g11FgYtHl
|
|||||||
golang.org/x/lint v0.0.0-20191125180803-fdd1cda4f05f/go.mod h1:5qLYkcX4OjUUV8bRuDixDT3tpyyb+LUpUlRWLxfhWrs=
|
golang.org/x/lint v0.0.0-20191125180803-fdd1cda4f05f/go.mod h1:5qLYkcX4OjUUV8bRuDixDT3tpyyb+LUpUlRWLxfhWrs=
|
||||||
golang.org/x/lint v0.0.0-20200130185559-910be7a94367/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY=
|
golang.org/x/lint v0.0.0-20200130185559-910be7a94367/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY=
|
||||||
golang.org/x/lint v0.0.0-20200302205851-738671d3881b/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY=
|
golang.org/x/lint v0.0.0-20200302205851-738671d3881b/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY=
|
||||||
|
golang.org/x/lint v0.0.0-20201208152925-83fdc39ff7b5/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY=
|
||||||
golang.org/x/lint v0.0.0-20210508222113-6edffad5e616 h1:VLliZ0d+/avPrXXH+OakdXhpJuEoBZuwh1m2j7U6Iug=
|
golang.org/x/lint v0.0.0-20210508222113-6edffad5e616 h1:VLliZ0d+/avPrXXH+OakdXhpJuEoBZuwh1m2j7U6Iug=
|
||||||
golang.org/x/lint v0.0.0-20210508222113-6edffad5e616/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY=
|
golang.org/x/lint v0.0.0-20210508222113-6edffad5e616/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY=
|
||||||
golang.org/x/mobile v0.0.0-20190312151609-d3739f865fa6/go.mod h1:z+o9i4GpDbdi3rU15maQ/Ox0txvL9dWGYEHz965HBQE=
|
golang.org/x/mobile v0.0.0-20190312151609-d3739f865fa6/go.mod h1:z+o9i4GpDbdi3rU15maQ/Ox0txvL9dWGYEHz965HBQE=
|
||||||
@@ -563,7 +931,10 @@ golang.org/x/mod v0.1.1-0.20191105210325-c90efee705ee/go.mod h1:QqPTAvyqsEbceGzB
|
|||||||
golang.org/x/mod v0.1.1-0.20191107180719-034126e5016b/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg=
|
golang.org/x/mod v0.1.1-0.20191107180719-034126e5016b/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg=
|
||||||
golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
|
golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
|
||||||
golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
|
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.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-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||||
@@ -596,26 +967,58 @@ golang.org/x/net v0.0.0-20200625001655-4c5254603344/go.mod h1:/O7V0waA8r7cgGh81R
|
|||||||
golang.org/x/net v0.0.0-20200707034311-ab3426394381/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA=
|
golang.org/x/net v0.0.0-20200707034311-ab3426394381/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA=
|
||||||
golang.org/x/net v0.0.0-20200822124328-c89045814202/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA=
|
golang.org/x/net v0.0.0-20200822124328-c89045814202/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA=
|
||||||
golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU=
|
golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU=
|
||||||
|
golang.org/x/net v0.0.0-20201031054903-ff519b6c9102/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU=
|
||||||
|
golang.org/x/net v0.0.0-20201110031124-69a78807bb2b/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU=
|
||||||
|
golang.org/x/net v0.0.0-20201209123823-ac852fbbde11/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
|
||||||
|
golang.org/x/net v0.0.0-20210119194325-5f4716e94777/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
|
||||||
golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
|
golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
|
||||||
|
golang.org/x/net v0.0.0-20210316092652-d523dce5a7f4/go.mod h1:RBQZq4jEuRlivfhVLdyRGr576XBO4/greRjx4P4O3yc=
|
||||||
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-20210428140749-89ef3d95e781/go.mod h1:OJAsFXCWl8Ukc7SiCT/9KSuxbyM7479/AVlXFRxuMCk=
|
golang.org/x/net v0.0.0-20210428140749-89ef3d95e781/go.mod h1:OJAsFXCWl8Ukc7SiCT/9KSuxbyM7479/AVlXFRxuMCk=
|
||||||
|
golang.org/x/net v0.0.0-20210503060351-7fd8e65b6420/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
|
||||||
golang.org/x/net v0.0.0-20210525063256-abc453219eb5/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
|
golang.org/x/net v0.0.0-20210525063256-abc453219eb5/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
|
||||||
golang.org/x/net v0.0.0-20210917221730-978cfadd31cf/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
|
golang.org/x/net v0.0.0-20210917221730-978cfadd31cf/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
|
||||||
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-20211209124913-491a49abca63/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
|
golang.org/x/net v0.0.0-20211209124913-491a49abca63/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
|
||||||
golang.org/x/net v0.0.0-20220127200216-cd36cc0744dd/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk=
|
golang.org/x/net v0.0.0-20220127200216-cd36cc0744dd/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk=
|
||||||
golang.org/x/net v0.0.0-20220225172249-27dd8689420f/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk=
|
golang.org/x/net v0.0.0-20220225172249-27dd8689420f/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk=
|
||||||
golang.org/x/net v0.0.0-20220531201128-c960675eff93 h1:MYimHLfoXEpOhqd/zgoA/uoXzHB86AEky4LAx5ij9xA=
|
golang.org/x/net v0.0.0-20220325170049-de3da57026de/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk=
|
||||||
golang.org/x/net v0.0.0-20220531201128-c960675eff93/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c=
|
golang.org/x/net v0.0.0-20220412020605-290c469a71a5/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk=
|
||||||
|
golang.org/x/net v0.0.0-20220425223048-2871e0cb64e4/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk=
|
||||||
|
golang.org/x/net v0.0.0-20220607020251-c690dde0001d/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c=
|
||||||
|
golang.org/x/net v0.0.0-20220617184016-355a448f1bc9/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c=
|
||||||
|
golang.org/x/net v0.0.0-20220624214902-1bab6f366d9e/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c=
|
||||||
|
golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c=
|
||||||
|
golang.org/x/net v0.0.0-20220909164309-bea034e7d591/go.mod h1:YDH+HFinaLZZlnHAfSS6ZXJJ9M9t4Dl22yv3iI2vPwk=
|
||||||
|
golang.org/x/net v0.0.0-20221012135044-0b7e1fb9d458/go.mod h1:YDH+HFinaLZZlnHAfSS6ZXJJ9M9t4Dl22yv3iI2vPwk=
|
||||||
|
golang.org/x/net v0.0.0-20221014081412-f15817d10f9b h1:tvrvnPFcdzp294diPnrdZZZ8XUt2Tyj7svb7X52iDuU=
|
||||||
|
golang.org/x/net v0.0.0-20221014081412-f15817d10f9b/go.mod h1:YDH+HFinaLZZlnHAfSS6ZXJJ9M9t4Dl22yv3iI2vPwk=
|
||||||
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=
|
||||||
golang.org/x/oauth2 v0.0.0-20191202225959-858c2ad4c8b6/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
|
golang.org/x/oauth2 v0.0.0-20191202225959-858c2ad4c8b6/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
|
||||||
golang.org/x/oauth2 v0.0.0-20200107190931-bf48bf16ab8d/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
|
golang.org/x/oauth2 v0.0.0-20200107190931-bf48bf16ab8d/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
|
||||||
|
golang.org/x/oauth2 v0.0.0-20200902213428-5d25da1a8d43/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-20210218202405-ba52d332ba99/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A=
|
||||||
|
golang.org/x/oauth2 v0.0.0-20210220000619-9bb904979d93/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A=
|
||||||
|
golang.org/x/oauth2 v0.0.0-20210313182246-cd4f82c27b84/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A=
|
||||||
golang.org/x/oauth2 v0.0.0-20210514164344-f6687ab2804c/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A=
|
golang.org/x/oauth2 v0.0.0-20210514164344-f6687ab2804c/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A=
|
||||||
|
golang.org/x/oauth2 v0.0.0-20210628180205-a41e5a781914/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A=
|
||||||
|
golang.org/x/oauth2 v0.0.0-20210805134026-6f1e6394065a/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A=
|
||||||
|
golang.org/x/oauth2 v0.0.0-20210819190943-2bc19b11175f/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A=
|
||||||
golang.org/x/oauth2 v0.0.0-20211104180415-d3ed0bb246c8/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A=
|
golang.org/x/oauth2 v0.0.0-20211104180415-d3ed0bb246c8/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A=
|
||||||
golang.org/x/oauth2 v0.0.0-20220223155221-ee480838109b h1:clP8eMhB30EHdc0bd2Twtq6kgU7yl5ub2cQLSdrv1Dg=
|
|
||||||
golang.org/x/oauth2 v0.0.0-20220223155221-ee480838109b/go.mod h1:DAh4E804XQdzx2j+YRIaUnCqCV2RuMz24cGBJ5QYIrc=
|
golang.org/x/oauth2 v0.0.0-20220223155221-ee480838109b/go.mod h1:DAh4E804XQdzx2j+YRIaUnCqCV2RuMz24cGBJ5QYIrc=
|
||||||
|
golang.org/x/oauth2 v0.0.0-20220309155454-6242fa91716a/go.mod h1:DAh4E804XQdzx2j+YRIaUnCqCV2RuMz24cGBJ5QYIrc=
|
||||||
|
golang.org/x/oauth2 v0.0.0-20220411215720-9780585627b5/go.mod h1:DAh4E804XQdzx2j+YRIaUnCqCV2RuMz24cGBJ5QYIrc=
|
||||||
|
golang.org/x/oauth2 v0.0.0-20220608161450-d0670ef3b1eb/go.mod h1:jaDAt6Dkxork7LmZnYtzbRWj0W47D86a3TGe0YHBvmE=
|
||||||
|
golang.org/x/oauth2 v0.0.0-20220622183110-fd043fe589d2/go.mod h1:jaDAt6Dkxork7LmZnYtzbRWj0W47D86a3TGe0YHBvmE=
|
||||||
|
golang.org/x/oauth2 v0.0.0-20220822191816-0ebed06d0094/go.mod h1:h4gKUeWbJ4rQPri7E0u6Gs4e9Ri2zaLxzw5DI5XGrYg=
|
||||||
|
golang.org/x/oauth2 v0.0.0-20220909003341-f21342109be1/go.mod h1:h4gKUeWbJ4rQPri7E0u6Gs4e9Ri2zaLxzw5DI5XGrYg=
|
||||||
|
golang.org/x/oauth2 v0.0.0-20221006150949-b44042a4b9c1/go.mod h1:h4gKUeWbJ4rQPri7E0u6Gs4e9Ri2zaLxzw5DI5XGrYg=
|
||||||
|
golang.org/x/oauth2 v0.0.0-20221014153046-6fdb5e3db783 h1:nt+Q6cXKz4MosCSpnbMtqiQ8Oz0pxTef2B4Vca2lvfk=
|
||||||
|
golang.org/x/oauth2 v0.0.0-20221014153046-6fdb5e3db783/go.mod h1:h4gKUeWbJ4rQPri7E0u6Gs4e9Ri2zaLxzw5DI5XGrYg=
|
||||||
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=
|
||||||
@@ -627,8 +1030,11 @@ 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-20220601150217-0de741cfad7f h1:Ax0t5p6N38Ga0dThY21weqDEyz2oklo4IvDkpigvkD8=
|
|
||||||
golang.org/x/sync v0.0.0-20220601150217-0de741cfad7f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
golang.org/x/sync v0.0.0-20220601150217-0de741cfad7f/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.0.0-20220929204114-8fcdb60fdcc0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||||
|
golang.org/x/sync v0.1.0 h1:wsuoTGHzEhffawBOhz5CYhcrV4IdKZbEyZjBMuTp12o=
|
||||||
|
golang.org/x/sync v0.1.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||||
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-20180909124046-d0be0721c37e/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
golang.org/x/sys v0.0.0-20180909124046-d0be0721c37e/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||||
@@ -669,26 +1075,52 @@ golang.org/x/sys v0.0.0-20200523222454-059865788121/go.mod h1:h1NjWce9XRLGQEsW7w
|
|||||||
golang.org/x/sys v0.0.0-20200615200032-f1bc736245b1/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
golang.org/x/sys v0.0.0-20200615200032-f1bc736245b1/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
golang.org/x/sys v0.0.0-20200625212154-ddb9806d33ae/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
golang.org/x/sys v0.0.0-20200625212154-ddb9806d33ae/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
golang.org/x/sys v0.0.0-20200803210538-64077c9b5642/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
golang.org/x/sys v0.0.0-20200803210538-64077c9b5642/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
|
golang.org/x/sys v0.0.0-20200905004654-be1d3432aa8f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
|
golang.org/x/sys v0.0.0-20201201145000-ef89a241ccb3/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
|
golang.org/x/sys v0.0.0-20210104204734-6f8348627aad/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
golang.org/x/sys v0.0.0-20210112080510-489259a85091/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
golang.org/x/sys v0.0.0-20210112080510-489259a85091/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
golang.org/x/sys v0.0.0-20210119212857-b64e53b001e4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
golang.org/x/sys v0.0.0-20210119212857-b64e53b001e4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
golang.org/x/sys v0.0.0-20210124154548-22da62e12c0c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
golang.org/x/sys v0.0.0-20210124154548-22da62e12c0c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
|
golang.org/x/sys v0.0.0-20210220050731-9a76102bfb43/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
|
golang.org/x/sys v0.0.0-20210305230114-8fe3ee5dd75b/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
|
golang.org/x/sys v0.0.0-20210315160823-c6e025ad8005/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
|
golang.org/x/sys v0.0.0-20210320140829-1e4c9ba3b0c4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
golang.org/x/sys v0.0.0-20210330210617-4fbd30eecc44/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
golang.org/x/sys v0.0.0-20210330210617-4fbd30eecc44/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
golang.org/x/sys v0.0.0-20210403161142-5e06dd20ab57/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
golang.org/x/sys v0.0.0-20210403161142-5e06dd20ab57/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
golang.org/x/sys v0.0.0-20210423185535-09eb48e85fd7/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
golang.org/x/sys v0.0.0-20210423185535-09eb48e85fd7/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
golang.org/x/sys v0.0.0-20210510120138-977fb7262007/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
golang.org/x/sys v0.0.0-20210510120138-977fb7262007/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
|
golang.org/x/sys v0.0.0-20210514084401-e8d321eab015/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
golang.org/x/sys v0.0.0-20210603081109-ebe580a85c40/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
golang.org/x/sys v0.0.0-20210603081109-ebe580a85c40/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
|
golang.org/x/sys v0.0.0-20210603125802-9665404d3644/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
golang.org/x/sys v0.0.0-20210616094352-59db8d763f22/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
golang.org/x/sys v0.0.0-20210616094352-59db8d763f22/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-20210630005230-0f9fa26af87c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
|
golang.org/x/sys v0.0.0-20210806184541-e5e7981a1069/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
|
golang.org/x/sys v0.0.0-20210823070655-63515b42dcdf/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
|
golang.org/x/sys v0.0.0-20210908233432-aa78b53d3365/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
|
golang.org/x/sys v0.0.0-20211007075335-d3039528d8ac/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
|
golang.org/x/sys v0.0.0-20211124211545-fe61309f8881/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
|
golang.org/x/sys v0.0.0-20211210111614-af8b64212486/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
golang.org/x/sys v0.0.0-20211216021012-1d35b9e2eb4e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
golang.org/x/sys v0.0.0-20211216021012-1d35b9e2eb4e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
golang.org/x/sys v0.0.0-20220114195835-da31bd327af9/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
golang.org/x/sys v0.0.0-20220114195835-da31bd327af9/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
golang.org/x/sys v0.0.0-20220128215802-99c3d69c2c27/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
golang.org/x/sys v0.0.0-20220128215802-99c3d69c2c27/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
|
golang.org/x/sys v0.0.0-20220209214540-3681064d5158/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
|
golang.org/x/sys v0.0.0-20220227234510-4e6760a101f9/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
|
golang.org/x/sys v0.0.0-20220328115105-d36c6a25d886/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
|
golang.org/x/sys v0.0.0-20220412211240-33da011f77ad/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
golang.org/x/sys v0.0.0-20220429233432-b5fbb4746d32/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
golang.org/x/sys v0.0.0-20220429233432-b5fbb4746d32/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a h1:dGzPydgVsqGcTRVwiLJ1jVbufYwmzD3LfVPLKsKg+0k=
|
golang.org/x/sys v0.0.0-20220502124256-b6088ccd6cba/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-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
|
golang.org/x/sys v0.0.0-20220610221304-9f5ed59c137d/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
|
golang.org/x/sys v0.0.0-20220615213510-4f61da869c0c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
|
golang.org/x/sys v0.0.0-20220624220833-87e55d714810/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 h1:WIoqL4EROvwiPdUtaip4VcDdpZ4kha7wBWZrbVKCIZg=
|
||||||
|
golang.org/x/sys v0.0.0-20220728004956-3c1f35247d10/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
golang.org/x/term v0.0.0-20201117132131-f5c789dd3221/go.mod h1:Nr5EML6q2oocZ2LXRh80K7BxOlk5/8JxuGnuhpl+muw=
|
golang.org/x/term v0.0.0-20201117132131-f5c789dd3221/go.mod h1:Nr5EML6q2oocZ2LXRh80K7BxOlk5/8JxuGnuhpl+muw=
|
||||||
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-20210220032956-6a3ed077a48d/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
|
golang.org/x/term v0.0.0-20210220032956-6a3ed077a48d/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
|
||||||
@@ -699,16 +1131,19 @@ 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=
|
||||||
golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk=
|
golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk=
|
||||||
golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
|
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.5/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
|
golang.org/x/text v0.3.5/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 h1:olpwvP2KacW1ZWvsR7uQhoyTYvKAupfQrRGBFM352Gk=
|
|
||||||
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.4.0 h1:BrVqGRd7+k1DiOgtnFvAkoQEWQvBc25ouMJM6429SFg=
|
||||||
|
golang.org/x/text v0.4.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8=
|
||||||
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=
|
||||||
golang.org/x/time v0.0.0-20210723032227-1f47c861a9ac/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
|
golang.org/x/time v0.0.0-20210723032227-1f47c861a9ac/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
|
||||||
golang.org/x/time v0.0.0-20220411224347-583f2d630306 h1:+gHMid33q6pen7kv9xvT+JRinntgeXO2AeZVd0AWD3w=
|
golang.org/x/time v0.3.0 h1:rg5rLMjNzMS1RkNLzCG38eapWhnYLFYXDXj2gOlr8j4=
|
||||||
golang.org/x/time v0.0.0-20220411224347-583f2d630306/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
|
golang.org/x/time v0.3.0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
|
||||||
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
||||||
golang.org/x/tools v0.0.0-20190114222345-bf090417da8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
golang.org/x/tools v0.0.0-20190114222345-bf090417da8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
||||||
golang.org/x/tools v0.0.0-20190226205152-f727befe758c/go.mod h1:9Yl7xja0Znq3iFh3HoIrodX9oNMXvdceNzlUR8zjMvY=
|
golang.org/x/tools v0.0.0-20190226205152-f727befe758c/go.mod h1:9Yl7xja0Znq3iFh3HoIrodX9oNMXvdceNzlUR8zjMvY=
|
||||||
@@ -750,16 +1185,29 @@ golang.org/x/tools v0.0.0-20200619180055-7c47624df98f/go.mod h1:EkVYQZoAsY45+roY
|
|||||||
golang.org/x/tools v0.0.0-20200729194436-6467de6f59a7/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA=
|
golang.org/x/tools v0.0.0-20200729194436-6467de6f59a7/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA=
|
||||||
golang.org/x/tools v0.0.0-20200804011535-6c149bb5ef0d/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA=
|
golang.org/x/tools v0.0.0-20200804011535-6c149bb5ef0d/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA=
|
||||||
golang.org/x/tools v0.0.0-20200825202427-b303f430e36d/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA=
|
golang.org/x/tools v0.0.0-20200825202427-b303f430e36d/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA=
|
||||||
|
golang.org/x/tools v0.0.0-20200904185747-39188db58858/go.mod h1:Cj7w3i3Rnn0Xh82ur9kSqwfTHTeVxaDqrfMjpcNT6bE=
|
||||||
|
golang.org/x/tools v0.0.0-20201110124207-079ba7bd75cd/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA=
|
||||||
|
golang.org/x/tools v0.0.0-20201201161351-ac6f37ff4c2a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA=
|
||||||
|
golang.org/x/tools v0.0.0-20201208233053-a543418bbed2/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA=
|
||||||
golang.org/x/tools v0.0.0-20201224043029-2b0845dc783e/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA=
|
golang.org/x/tools v0.0.0-20201224043029-2b0845dc783e/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA=
|
||||||
|
golang.org/x/tools v0.0.0-20210105154028-b0ab187a4818/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA=
|
||||||
golang.org/x/tools v0.0.0-20210106214847-113979e3529a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA=
|
golang.org/x/tools v0.0.0-20210106214847-113979e3529a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA=
|
||||||
|
golang.org/x/tools v0.1.0/go.mod h1:xkSsbof2nBLbhDlRMhhhyNLN/zl3eTqcnHD5viDpcZ0=
|
||||||
golang.org/x/tools v0.1.1/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk=
|
golang.org/x/tools v0.1.1/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk=
|
||||||
golang.org/x/tools v0.1.2/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk=
|
golang.org/x/tools v0.1.2/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk=
|
||||||
golang.org/x/tools v0.1.5 h1:ouewzE6p+/VEB31YYnTbEJdi8pFqKp4P4n85vwo3DHA=
|
golang.org/x/tools v0.1.3/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk=
|
||||||
|
golang.org/x/tools v0.1.4/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk=
|
||||||
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 h1:VveCTK38A2rkS8ZqFY25HIDFscX5X9OoEhJd3quQmXU=
|
||||||
|
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=
|
||||||
golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||||
|
golang.org/x/xerrors v0.0.0-20220411194840-2f41105eb62f/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||||
|
golang.org/x/xerrors v0.0.0-20220517211312-f3a8303e98df/go.mod h1:K8+ghG5WaK9qNqU5K3HdILfMLy1f3aNYFI/wnl100a8=
|
||||||
|
golang.org/x/xerrors v0.0.0-20220609144429-65e65417b02f/go.mod h1:K8+ghG5WaK9qNqU5K3HdILfMLy1f3aNYFI/wnl100a8=
|
||||||
|
golang.org/x/xerrors v0.0.0-20220907171357-04be3eba64a2/go.mod h1:K8+ghG5WaK9qNqU5K3HdILfMLy1f3aNYFI/wnl100a8=
|
||||||
google.golang.org/api v0.4.0/go.mod h1:8k5glujaEP+g9n7WNsDg8QP6cUVNI86fCNMcbazEtwE=
|
google.golang.org/api v0.4.0/go.mod h1:8k5glujaEP+g9n7WNsDg8QP6cUVNI86fCNMcbazEtwE=
|
||||||
google.golang.org/api v0.7.0/go.mod h1:WtwebWUNSVBH/HAw79HIFXZNqEvBhG+Ra+ax0hx3E3M=
|
google.golang.org/api v0.7.0/go.mod h1:WtwebWUNSVBH/HAw79HIFXZNqEvBhG+Ra+ax0hx3E3M=
|
||||||
google.golang.org/api v0.8.0/go.mod h1:o4eAsZoiT+ibD93RtjEohWalFOjRDx6CVaqeizhEnKg=
|
google.golang.org/api v0.8.0/go.mod h1:o4eAsZoiT+ibD93RtjEohWalFOjRDx6CVaqeizhEnKg=
|
||||||
@@ -776,13 +1224,48 @@ google.golang.org/api v0.24.0/go.mod h1:lIXQywCXRcnZPGlsd8NbLnOjtAoL6em04bJ9+z0M
|
|||||||
google.golang.org/api v0.28.0/go.mod h1:lIXQywCXRcnZPGlsd8NbLnOjtAoL6em04bJ9+z0MncE=
|
google.golang.org/api v0.28.0/go.mod h1:lIXQywCXRcnZPGlsd8NbLnOjtAoL6em04bJ9+z0MncE=
|
||||||
google.golang.org/api v0.29.0/go.mod h1:Lcubydp8VUV7KeIHD9z2Bys/sm/vGKnG1UHuDBSrHWM=
|
google.golang.org/api v0.29.0/go.mod h1:Lcubydp8VUV7KeIHD9z2Bys/sm/vGKnG1UHuDBSrHWM=
|
||||||
google.golang.org/api v0.30.0/go.mod h1:QGmEvQ87FHZNiUVJkT14jQNYJ4ZJjdRF23ZXz5138Fc=
|
google.golang.org/api v0.30.0/go.mod h1:QGmEvQ87FHZNiUVJkT14jQNYJ4ZJjdRF23ZXz5138Fc=
|
||||||
|
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.40.0/go.mod h1:fYKFpnQN0DsDSKRVRcQSDQNtqWPfM9i+zNPxepjRCQ8=
|
||||||
|
google.golang.org/api v0.41.0/go.mod h1:RkxM5lITDfTzmyKFPt+wGrCJbVfniCr2ool8kTBzRTU=
|
||||||
|
google.golang.org/api v0.43.0/go.mod h1:nQsDGjRXMo4lvh5hP0TKqF244gqhGcr/YSIykhUk/94=
|
||||||
|
google.golang.org/api v0.47.0/go.mod h1:Wbvgpq1HddcWVtzsVLyfLp8lDg6AA241LmgIL59tHXo=
|
||||||
|
google.golang.org/api v0.48.0/go.mod h1:71Pr1vy+TAZRPkPs/xlCf5SsU8WjuAWv1Pfjbtukyy4=
|
||||||
|
google.golang.org/api v0.50.0/go.mod h1:4bNT5pAuq5ji4SRZm+5QIkjny9JAyVD/3gaSihNefaw=
|
||||||
|
google.golang.org/api v0.51.0/go.mod h1:t4HdrdoNgyN5cbEfm7Lum0lcLDLiise1F8qDKX00sOU=
|
||||||
|
google.golang.org/api v0.54.0/go.mod h1:7C4bFFOvVDGXjfDTAsgGwDgAxRDeQ4X8NvUedIt6z3k=
|
||||||
|
google.golang.org/api v0.55.0/go.mod h1:38yMfeP1kfjsl8isn0tliTjIb1rJXcQi4UXlbqivdVE=
|
||||||
|
google.golang.org/api v0.56.0/go.mod h1:38yMfeP1kfjsl8isn0tliTjIb1rJXcQi4UXlbqivdVE=
|
||||||
|
google.golang.org/api v0.57.0/go.mod h1:dVPlbZyBo2/OjBpmvNdpn2GRm6rPy75jyU7bmhdrMgI=
|
||||||
|
google.golang.org/api v0.61.0/go.mod h1:xQRti5UdCmoCEqFxcz93fTl338AVqDgyaDRuOZ3hg9I=
|
||||||
|
google.golang.org/api v0.63.0/go.mod h1:gs4ij2ffTRXwuzzgJl/56BdwJaA194ijkfn++9tDuPo=
|
||||||
|
google.golang.org/api v0.67.0/go.mod h1:ShHKP8E60yPsKNw/w8w+VYaj9H6buA5UqDp8dhbQZ6g=
|
||||||
|
google.golang.org/api v0.70.0/go.mod h1:Bs4ZM2HGifEvXwd50TtW70ovgJffJYw2oRCOFU/SkfA=
|
||||||
|
google.golang.org/api v0.71.0/go.mod h1:4PyU6e6JogV1f9eA4voyrTY2batOLdgZ5qZ5HOCc4j8=
|
||||||
|
google.golang.org/api v0.74.0/go.mod h1:ZpfMZOVRMywNyvJFeqL9HRWBgAuRfSjJFpe9QtRRyDs=
|
||||||
|
google.golang.org/api v0.75.0/go.mod h1:pU9QmyHLnzlpar1Mjt4IbapUCy8J+6HD6GeELN69ljA=
|
||||||
|
google.golang.org/api v0.77.0/go.mod h1:pU9QmyHLnzlpar1Mjt4IbapUCy8J+6HD6GeELN69ljA=
|
||||||
|
google.golang.org/api v0.78.0/go.mod h1:1Sg78yoMLOhlQTeF+ARBoytAcH1NNyyl390YMy6rKmw=
|
||||||
|
google.golang.org/api v0.80.0/go.mod h1:xY3nI94gbvBrE0J6NHXhxOmW97HG7Khjkku6AFB3Hyg=
|
||||||
|
google.golang.org/api v0.84.0/go.mod h1:NTsGnUFJMYROtiquksZHBWtHfeMC7iYthki7Eq3pa8o=
|
||||||
|
google.golang.org/api v0.85.0/go.mod h1:AqZf8Ep9uZ2pyTvgL+x0D3Zt0eoT9b5E8fmzfu6FO2g=
|
||||||
|
google.golang.org/api v0.90.0/go.mod h1:+Sem1dnrKlrXMR/X0bPnMWyluQe4RsNoYfmNLhOIkzw=
|
||||||
|
google.golang.org/api v0.93.0/go.mod h1:+Sem1dnrKlrXMR/X0bPnMWyluQe4RsNoYfmNLhOIkzw=
|
||||||
|
google.golang.org/api v0.95.0/go.mod h1:eADj+UBuxkh5zlrSntJghuNeg8HwQ1w5lTKkuqaETEI=
|
||||||
|
google.golang.org/api v0.96.0/go.mod h1:w7wJQLTM+wvQpNf5JyEcBoxK0RH7EDrh/L4qfsuJ13s=
|
||||||
|
google.golang.org/api v0.97.0/go.mod h1:w7wJQLTM+wvQpNf5JyEcBoxK0RH7EDrh/L4qfsuJ13s=
|
||||||
|
google.golang.org/api v0.98.0/go.mod h1:w7wJQLTM+wvQpNf5JyEcBoxK0RH7EDrh/L4qfsuJ13s=
|
||||||
|
google.golang.org/api v0.99.0/go.mod h1:1YOf74vkVndF7pG6hIHuINsM7eWwpVTAfNMNiL91A08=
|
||||||
|
google.golang.org/api v0.100.0/go.mod h1:ZE3Z2+ZOr87Rx7dqFsdRQkRBk36kDtp/h+QpHbB7a70=
|
||||||
|
google.golang.org/api v0.102.0/go.mod h1:3VFl6/fzoA+qNuS1N1/VfXY4LjoXN/wzeIp7TweWwGo=
|
||||||
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=
|
||||||
google.golang.org/appengine v1.6.1/go.mod h1:i06prIuMbXzDqacNJfV5OdTW448YApPu5ww/cMBSeb0=
|
google.golang.org/appengine v1.6.1/go.mod h1:i06prIuMbXzDqacNJfV5OdTW448YApPu5ww/cMBSeb0=
|
||||||
google.golang.org/appengine v1.6.5/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc=
|
google.golang.org/appengine v1.6.5/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc=
|
||||||
google.golang.org/appengine v1.6.6 h1:lMO5rYAqUxkmaj76jAkRUvt5JZgFymx/+Q5Mzfivuhc=
|
|
||||||
google.golang.org/appengine v1.6.6/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc=
|
google.golang.org/appengine v1.6.6/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc=
|
||||||
|
google.golang.org/appengine v1.6.7 h1:FZR1q0exgwxzPzp/aF+VccGrSfxfPpkBqjIIEq3ru6c=
|
||||||
|
google.golang.org/appengine v1.6.7/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc=
|
||||||
google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc=
|
google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc=
|
||||||
google.golang.org/genproto v0.0.0-20190307195333-5fe7a883aa19/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE=
|
google.golang.org/genproto v0.0.0-20190307195333-5fe7a883aa19/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE=
|
||||||
google.golang.org/genproto v0.0.0-20190418145605-e7d98fc518a7/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE=
|
google.golang.org/genproto v0.0.0-20190418145605-e7d98fc518a7/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE=
|
||||||
@@ -813,11 +1296,82 @@ google.golang.org/genproto v0.0.0-20200618031413-b414f8b61790/go.mod h1:jDfRM7Fc
|
|||||||
google.golang.org/genproto v0.0.0-20200729003335-053ba62fc06f/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
|
google.golang.org/genproto v0.0.0-20200729003335-053ba62fc06f/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
|
||||||
google.golang.org/genproto v0.0.0-20200804131852-c06518451d9c/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
|
google.golang.org/genproto v0.0.0-20200804131852-c06518451d9c/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
|
||||||
google.golang.org/genproto v0.0.0-20200825200019-8632dd797987/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
|
google.golang.org/genproto v0.0.0-20200825200019-8632dd797987/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
|
||||||
|
google.golang.org/genproto v0.0.0-20200904004341-0bd0a958aa1d/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
|
||||||
google.golang.org/genproto v0.0.0-20201019141844-1ed22bb0c154/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
|
google.golang.org/genproto v0.0.0-20201019141844-1ed22bb0c154/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
|
||||||
|
google.golang.org/genproto v0.0.0-20201109203340-2640f1f9cdfb/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
|
||||||
|
google.golang.org/genproto v0.0.0-20201201144952-b05cb90ed32e/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
|
||||||
|
google.golang.org/genproto v0.0.0-20201210142538-e3217bee35cc/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-20210222152913-aa3ee6e6a81c/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
|
||||||
|
google.golang.org/genproto v0.0.0-20210303154014-9728d6b83eeb/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
|
||||||
|
google.golang.org/genproto v0.0.0-20210310155132-4ce2db91004e/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
|
||||||
|
google.golang.org/genproto v0.0.0-20210319143718-93e7006c17a6/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
|
||||||
|
google.golang.org/genproto v0.0.0-20210329143202-679c6ae281ee/go.mod h1:9lPAdzaEmUacj36I+k7YKbEc5CXzPIeORRgDAUOu28A=
|
||||||
|
google.golang.org/genproto v0.0.0-20210402141018-6c239bbf2bb1/go.mod h1:9lPAdzaEmUacj36I+k7YKbEc5CXzPIeORRgDAUOu28A=
|
||||||
|
google.golang.org/genproto v0.0.0-20210513213006-bf773b8c8384/go.mod h1:P3QM42oQyzQSnHPnZ/vqoCdDmzH28fzWByN9asMeM8A=
|
||||||
google.golang.org/genproto v0.0.0-20210602131652-f16073e35f0c/go.mod h1:UODoCrxHCcBojKKwX1terBiRUaqAsFqJiF615XL43r0=
|
google.golang.org/genproto v0.0.0-20210602131652-f16073e35f0c/go.mod h1:UODoCrxHCcBojKKwX1terBiRUaqAsFqJiF615XL43r0=
|
||||||
|
google.golang.org/genproto v0.0.0-20210604141403-392c879c8b08/go.mod h1:UODoCrxHCcBojKKwX1terBiRUaqAsFqJiF615XL43r0=
|
||||||
|
google.golang.org/genproto v0.0.0-20210608205507-b6d2f5bf0d7d/go.mod h1:UODoCrxHCcBojKKwX1terBiRUaqAsFqJiF615XL43r0=
|
||||||
|
google.golang.org/genproto v0.0.0-20210624195500-8bfb893ecb84/go.mod h1:SzzZ/N+nwJDaO1kznhnlzqS8ocJICar6hYhVyhi++24=
|
||||||
|
google.golang.org/genproto v0.0.0-20210713002101-d411969a0d9a/go.mod h1:AxrInvYm1dci+enl5hChSFPOmmUF1+uAa/UsgNRWd7k=
|
||||||
|
google.golang.org/genproto v0.0.0-20210716133855-ce7ef5c701ea/go.mod h1:AxrInvYm1dci+enl5hChSFPOmmUF1+uAa/UsgNRWd7k=
|
||||||
|
google.golang.org/genproto v0.0.0-20210728212813-7823e685a01f/go.mod h1:ob2IJxKrgPT52GcgX759i1sleT07tiKowYBGbczaW48=
|
||||||
|
google.golang.org/genproto v0.0.0-20210805201207-89edb61ffb67/go.mod h1:ob2IJxKrgPT52GcgX759i1sleT07tiKowYBGbczaW48=
|
||||||
|
google.golang.org/genproto v0.0.0-20210813162853-db860fec028c/go.mod h1:cFeNkxwySK631ADgubI+/XFU/xp8FD5KIVV4rj8UC5w=
|
||||||
|
google.golang.org/genproto v0.0.0-20210821163610-241b8fcbd6c8/go.mod h1:eFjDcFEctNawg4eG61bRv87N7iHBWyVhJu7u1kqDUXY=
|
||||||
|
google.golang.org/genproto v0.0.0-20210828152312-66f60bf46e71/go.mod h1:eFjDcFEctNawg4eG61bRv87N7iHBWyVhJu7u1kqDUXY=
|
||||||
|
google.golang.org/genproto v0.0.0-20210831024726-fe130286e0e2/go.mod h1:eFjDcFEctNawg4eG61bRv87N7iHBWyVhJu7u1kqDUXY=
|
||||||
|
google.golang.org/genproto v0.0.0-20210903162649-d08c68adba83/go.mod h1:eFjDcFEctNawg4eG61bRv87N7iHBWyVhJu7u1kqDUXY=
|
||||||
|
google.golang.org/genproto v0.0.0-20210909211513-a8c4777a87af/go.mod h1:eFjDcFEctNawg4eG61bRv87N7iHBWyVhJu7u1kqDUXY=
|
||||||
|
google.golang.org/genproto v0.0.0-20210924002016-3dee208752a0/go.mod h1:5CzLGKJ67TSI2B9POpiiyGha0AjJvZIUgRMt1dSmuhc=
|
||||||
google.golang.org/genproto v0.0.0-20211118181313-81c1377c94b1/go.mod h1:5CzLGKJ67TSI2B9POpiiyGha0AjJvZIUgRMt1dSmuhc=
|
google.golang.org/genproto v0.0.0-20211118181313-81c1377c94b1/go.mod h1:5CzLGKJ67TSI2B9POpiiyGha0AjJvZIUgRMt1dSmuhc=
|
||||||
google.golang.org/genproto v0.0.0-20220602131408-e326c6e8e9c8 h1:qRu95HZ148xXw+XeZ3dvqe85PxH4X8+jIo0iRPKcEnM=
|
google.golang.org/genproto v0.0.0-20211206160659-862468c7d6e0/go.mod h1:5CzLGKJ67TSI2B9POpiiyGha0AjJvZIUgRMt1dSmuhc=
|
||||||
google.golang.org/genproto v0.0.0-20220602131408-e326c6e8e9c8/go.mod h1:yKyY4AMRwFiC8yMMNaMi+RkCnjZJt9LoWuvhXjMs+To=
|
google.golang.org/genproto v0.0.0-20211208223120-3a66f561d7aa/go.mod h1:5CzLGKJ67TSI2B9POpiiyGha0AjJvZIUgRMt1dSmuhc=
|
||||||
|
google.golang.org/genproto v0.0.0-20211221195035-429b39de9b1c/go.mod h1:5CzLGKJ67TSI2B9POpiiyGha0AjJvZIUgRMt1dSmuhc=
|
||||||
|
google.golang.org/genproto v0.0.0-20220126215142-9970aeb2e350/go.mod h1:5CzLGKJ67TSI2B9POpiiyGha0AjJvZIUgRMt1dSmuhc=
|
||||||
|
google.golang.org/genproto v0.0.0-20220207164111-0872dc986b00/go.mod h1:5CzLGKJ67TSI2B9POpiiyGha0AjJvZIUgRMt1dSmuhc=
|
||||||
|
google.golang.org/genproto v0.0.0-20220218161850-94dd64e39d7c/go.mod h1:kGP+zUP2Ddo0ayMi4YuN7C3WZyJvGLZRh8Z5wnAqvEI=
|
||||||
|
google.golang.org/genproto v0.0.0-20220222213610-43724f9ea8cf/go.mod h1:kGP+zUP2Ddo0ayMi4YuN7C3WZyJvGLZRh8Z5wnAqvEI=
|
||||||
|
google.golang.org/genproto v0.0.0-20220304144024-325a89244dc8/go.mod h1:kGP+zUP2Ddo0ayMi4YuN7C3WZyJvGLZRh8Z5wnAqvEI=
|
||||||
|
google.golang.org/genproto v0.0.0-20220310185008-1973136f34c6/go.mod h1:kGP+zUP2Ddo0ayMi4YuN7C3WZyJvGLZRh8Z5wnAqvEI=
|
||||||
|
google.golang.org/genproto v0.0.0-20220324131243-acbaeb5b85eb/go.mod h1:hAL49I2IFola2sVEjAn7MEwsja0xp51I0tlGAf9hz4E=
|
||||||
|
google.golang.org/genproto v0.0.0-20220407144326-9054f6ed7bac/go.mod h1:8w6bsBMX6yCPbAVTeqQHvzxW0EIFigd5lZyahWgyfDo=
|
||||||
|
google.golang.org/genproto v0.0.0-20220413183235-5e96e2839df9/go.mod h1:8w6bsBMX6yCPbAVTeqQHvzxW0EIFigd5lZyahWgyfDo=
|
||||||
|
google.golang.org/genproto v0.0.0-20220414192740-2d67ff6cf2b4/go.mod h1:8w6bsBMX6yCPbAVTeqQHvzxW0EIFigd5lZyahWgyfDo=
|
||||||
|
google.golang.org/genproto v0.0.0-20220421151946-72621c1f0bd3/go.mod h1:8w6bsBMX6yCPbAVTeqQHvzxW0EIFigd5lZyahWgyfDo=
|
||||||
|
google.golang.org/genproto v0.0.0-20220429170224-98d788798c3e/go.mod h1:8w6bsBMX6yCPbAVTeqQHvzxW0EIFigd5lZyahWgyfDo=
|
||||||
|
google.golang.org/genproto v0.0.0-20220502173005-c8bf987b8c21/go.mod h1:RAyBrSAP7Fh3Nc84ghnVLDPuV51xc9agzmm4Ph6i0Q4=
|
||||||
|
google.golang.org/genproto v0.0.0-20220505152158-f39f71e6c8f3/go.mod h1:RAyBrSAP7Fh3Nc84ghnVLDPuV51xc9agzmm4Ph6i0Q4=
|
||||||
|
google.golang.org/genproto v0.0.0-20220518221133-4f43b3371335/go.mod h1:RAyBrSAP7Fh3Nc84ghnVLDPuV51xc9agzmm4Ph6i0Q4=
|
||||||
|
google.golang.org/genproto v0.0.0-20220523171625-347a074981d8/go.mod h1:RAyBrSAP7Fh3Nc84ghnVLDPuV51xc9agzmm4Ph6i0Q4=
|
||||||
|
google.golang.org/genproto v0.0.0-20220608133413-ed9918b62aac/go.mod h1:KEWEmljWE5zPzLBa/oHl6DaEt9LmfH6WtH1OHIvleBA=
|
||||||
|
google.golang.org/genproto v0.0.0-20220616135557-88e70c0c3a90/go.mod h1:KEWEmljWE5zPzLBa/oHl6DaEt9LmfH6WtH1OHIvleBA=
|
||||||
|
google.golang.org/genproto v0.0.0-20220617124728-180714bec0ad/go.mod h1:KEWEmljWE5zPzLBa/oHl6DaEt9LmfH6WtH1OHIvleBA=
|
||||||
|
google.golang.org/genproto v0.0.0-20220624142145-8cd45d7dbd1f/go.mod h1:KEWEmljWE5zPzLBa/oHl6DaEt9LmfH6WtH1OHIvleBA=
|
||||||
|
google.golang.org/genproto v0.0.0-20220628213854-d9e0b6570c03/go.mod h1:KEWEmljWE5zPzLBa/oHl6DaEt9LmfH6WtH1OHIvleBA=
|
||||||
|
google.golang.org/genproto v0.0.0-20220722212130-b98a9ff5e252/go.mod h1:GkXuJDJ6aQ7lnJcRF+SJVgFdQhypqgl3LB1C9vabdRE=
|
||||||
|
google.golang.org/genproto v0.0.0-20220801145646-83ce21fca29f/go.mod h1:iHe1svFLAZg9VWz891+QbRMwUv9O/1Ww+/mngYeThbc=
|
||||||
|
google.golang.org/genproto v0.0.0-20220815135757-37a418bb8959/go.mod h1:dbqgFATTzChvnt+ujMdZwITVAJHFtfyN1qUhDqEiIlk=
|
||||||
|
google.golang.org/genproto v0.0.0-20220817144833-d7fd3f11b9b1/go.mod h1:dbqgFATTzChvnt+ujMdZwITVAJHFtfyN1qUhDqEiIlk=
|
||||||
|
google.golang.org/genproto v0.0.0-20220822174746-9e6da59bd2fc/go.mod h1:dbqgFATTzChvnt+ujMdZwITVAJHFtfyN1qUhDqEiIlk=
|
||||||
|
google.golang.org/genproto v0.0.0-20220829144015-23454907ede3/go.mod h1:dbqgFATTzChvnt+ujMdZwITVAJHFtfyN1qUhDqEiIlk=
|
||||||
|
google.golang.org/genproto v0.0.0-20220829175752-36a9c930ecbf/go.mod h1:dbqgFATTzChvnt+ujMdZwITVAJHFtfyN1qUhDqEiIlk=
|
||||||
|
google.golang.org/genproto v0.0.0-20220913154956-18f8339a66a5/go.mod h1:0Nb8Qy+Sk5eDzHnzlStwW3itdNaWoZA5XeSG+R3JHSo=
|
||||||
|
google.golang.org/genproto v0.0.0-20220914142337-ca0e39ece12f/go.mod h1:0Nb8Qy+Sk5eDzHnzlStwW3itdNaWoZA5XeSG+R3JHSo=
|
||||||
|
google.golang.org/genproto v0.0.0-20220915135415-7fd63a7952de/go.mod h1:0Nb8Qy+Sk5eDzHnzlStwW3itdNaWoZA5XeSG+R3JHSo=
|
||||||
|
google.golang.org/genproto v0.0.0-20220916172020-2692e8806bfa/go.mod h1:0Nb8Qy+Sk5eDzHnzlStwW3itdNaWoZA5XeSG+R3JHSo=
|
||||||
|
google.golang.org/genproto v0.0.0-20220919141832-68c03719ef51/go.mod h1:0Nb8Qy+Sk5eDzHnzlStwW3itdNaWoZA5XeSG+R3JHSo=
|
||||||
|
google.golang.org/genproto v0.0.0-20220920201722-2b89144ce006/go.mod h1:ht8XFiar2npT/g4vkk7O0WYS1sHOHbdujxbEp7CJWbw=
|
||||||
|
google.golang.org/genproto v0.0.0-20220926165614-551eb538f295/go.mod h1:woMGP53BroOrRY3xTxlbr8Y3eB/nzAvvFM83q7kG2OI=
|
||||||
|
google.golang.org/genproto v0.0.0-20220926220553-6981cbe3cfce/go.mod h1:woMGP53BroOrRY3xTxlbr8Y3eB/nzAvvFM83q7kG2OI=
|
||||||
|
google.golang.org/genproto v0.0.0-20221010155953-15ba04fc1c0e/go.mod h1:3526vdqwhZAwq4wsRUaVG555sVgsNmIjRtO7t/JH29U=
|
||||||
|
google.golang.org/genproto v0.0.0-20221014173430-6e2ab493f96b/go.mod h1:1vXfmgAz9N9Jx0QA82PqRVauvCz1SGSz739p0f183jM=
|
||||||
|
google.golang.org/genproto v0.0.0-20221014213838-99cd37c6964a/go.mod h1:1vXfmgAz9N9Jx0QA82PqRVauvCz1SGSz739p0f183jM=
|
||||||
|
google.golang.org/genproto v0.0.0-20221024153911-1573dae28c9c/go.mod h1:9qHF0xnpdSfF6knlcsnpzUu5y+rpwgbvsyGAZPBMg4s=
|
||||||
|
google.golang.org/genproto v0.0.0-20221024183307-1bc688fe9f3e/go.mod h1:9qHF0xnpdSfF6knlcsnpzUu5y+rpwgbvsyGAZPBMg4s=
|
||||||
|
google.golang.org/genproto v0.0.0-20221027153422-115e99e71e1c/go.mod h1:CGI5F/G+E5bKwmfYo09AXuVN4dD894kIKUFmVbP2/Fo=
|
||||||
|
google.golang.org/genproto v0.0.0-20221111202108-142d8a6fa32e h1:azcyH5lGzGy7pkLCbhPe0KkKxsM7c6UA/FZIXImKE7M=
|
||||||
|
google.golang.org/genproto v0.0.0-20221111202108-142d8a6fa32e/go.mod h1:rZS5c/ZVYMaOGBfO68GWtjOw/eLaZM1X6iVtgjZ+EWg=
|
||||||
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=
|
||||||
@@ -830,16 +1384,33 @@ google.golang.org/grpc v1.28.0/go.mod h1:rpkK4SK4GF4Ach/+MFLZUBavHOvF2JJB5uozKKa
|
|||||||
google.golang.org/grpc v1.29.1/go.mod h1:itym6AZVZYACWQqET3MqgPpjcuV5QH3BxFS3IjizoKk=
|
google.golang.org/grpc v1.29.1/go.mod h1:itym6AZVZYACWQqET3MqgPpjcuV5QH3BxFS3IjizoKk=
|
||||||
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.33.1/go.mod h1:fr5YgcSWrqhRRxogOsw7RzIpsmvOZ6IcH4kBYTpR3n0=
|
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.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.36.0/go.mod h1:qjiiYl8FncCW8feJPdyg3v6XW24KsRHe+dy9BAGRRjU=
|
google.golang.org/grpc v1.36.0/go.mod h1:qjiiYl8FncCW8feJPdyg3v6XW24KsRHe+dy9BAGRRjU=
|
||||||
|
google.golang.org/grpc v1.36.1/go.mod h1:qjiiYl8FncCW8feJPdyg3v6XW24KsRHe+dy9BAGRRjU=
|
||||||
|
google.golang.org/grpc v1.37.0/go.mod h1:NREThFqKR1f3iQ6oBuvc5LadQuXVGo9rkm5ZGrQdJfM=
|
||||||
|
google.golang.org/grpc v1.37.1/go.mod h1:NREThFqKR1f3iQ6oBuvc5LadQuXVGo9rkm5ZGrQdJfM=
|
||||||
google.golang.org/grpc v1.38.0/go.mod h1:NREThFqKR1f3iQ6oBuvc5LadQuXVGo9rkm5ZGrQdJfM=
|
google.golang.org/grpc v1.38.0/go.mod h1:NREThFqKR1f3iQ6oBuvc5LadQuXVGo9rkm5ZGrQdJfM=
|
||||||
|
google.golang.org/grpc v1.39.0/go.mod h1:PImNr+rS9TWYb2O4/emRugxiyHZ5JyHW5F+RPnDzfrE=
|
||||||
|
google.golang.org/grpc v1.39.1/go.mod h1:PImNr+rS9TWYb2O4/emRugxiyHZ5JyHW5F+RPnDzfrE=
|
||||||
google.golang.org/grpc v1.40.0/go.mod h1:ogyxbiOoUXAkP+4+xa6PZSE9DZgIHtSpzjDTB9KAK34=
|
google.golang.org/grpc v1.40.0/go.mod h1:ogyxbiOoUXAkP+4+xa6PZSE9DZgIHtSpzjDTB9KAK34=
|
||||||
|
google.golang.org/grpc v1.40.1/go.mod h1:ogyxbiOoUXAkP+4+xa6PZSE9DZgIHtSpzjDTB9KAK34=
|
||||||
google.golang.org/grpc v1.41.0/go.mod h1:U3l9uK9J0sini8mHphKoXyaqDA/8VyGnDee1zzIUK6k=
|
google.golang.org/grpc v1.41.0/go.mod h1:U3l9uK9J0sini8mHphKoXyaqDA/8VyGnDee1zzIUK6k=
|
||||||
google.golang.org/grpc v1.42.0/go.mod h1:k+4IHHFw41K8+bbowsex27ge2rCb65oeWqe4jJ590SU=
|
google.golang.org/grpc v1.42.0/go.mod h1:k+4IHHFw41K8+bbowsex27ge2rCb65oeWqe4jJ590SU=
|
||||||
|
google.golang.org/grpc v1.44.0/go.mod h1:k+4IHHFw41K8+bbowsex27ge2rCb65oeWqe4jJ590SU=
|
||||||
|
google.golang.org/grpc v1.45.0/go.mod h1:lN7owxKUQEqMfSyQikvvk5tf/6zMPsrK+ONuO11+0rQ=
|
||||||
|
google.golang.org/grpc v1.46.0/go.mod h1:vN9eftEi1UMyUsIF80+uQXhHjbXYbm0uXoFCACuMGWk=
|
||||||
google.golang.org/grpc v1.46.2/go.mod h1:vN9eftEi1UMyUsIF80+uQXhHjbXYbm0uXoFCACuMGWk=
|
google.golang.org/grpc v1.46.2/go.mod h1:vN9eftEi1UMyUsIF80+uQXhHjbXYbm0uXoFCACuMGWk=
|
||||||
|
google.golang.org/grpc v1.47.0/go.mod h1:vN9eftEi1UMyUsIF80+uQXhHjbXYbm0uXoFCACuMGWk=
|
||||||
google.golang.org/grpc v1.48.0/go.mod h1:vN9eftEi1UMyUsIF80+uQXhHjbXYbm0uXoFCACuMGWk=
|
google.golang.org/grpc v1.48.0/go.mod h1:vN9eftEi1UMyUsIF80+uQXhHjbXYbm0uXoFCACuMGWk=
|
||||||
google.golang.org/grpc v1.49.0 h1:WTLtQzmQori5FUH25Pq4WT22oCsv8USpQ+F6rqtsmxw=
|
|
||||||
google.golang.org/grpc v1.49.0/go.mod h1:ZgQEeidpAuNRZ8iRrlBKXZQP1ghovWIVhdJRyCDK+GI=
|
google.golang.org/grpc v1.49.0/go.mod h1:ZgQEeidpAuNRZ8iRrlBKXZQP1ghovWIVhdJRyCDK+GI=
|
||||||
|
google.golang.org/grpc v1.50.0/go.mod h1:ZgQEeidpAuNRZ8iRrlBKXZQP1ghovWIVhdJRyCDK+GI=
|
||||||
|
google.golang.org/grpc v1.50.1 h1:DS/BukOZWp8s6p4Dt/tOaJaTQyPyOoCcrjroHuCeLzY=
|
||||||
|
google.golang.org/grpc v1.50.1/go.mod h1:ZgQEeidpAuNRZ8iRrlBKXZQP1ghovWIVhdJRyCDK+GI=
|
||||||
|
google.golang.org/grpc/cmd/protoc-gen-go-grpc v1.1.0/go.mod h1:6Kw0yEErY5E/yWrBtf03jp27GLLJujG4z/JK95pnjjw=
|
||||||
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=
|
||||||
@@ -903,12 +1474,12 @@ k8s.io/client-go v0.22.9/go.mod h1:IoH7exYnoH/zgvHOuVxh2c4yJepcCBt72FzCTisOc4k=
|
|||||||
k8s.io/gengo v0.0.0-20200413195148-3a45101e95ac/go.mod h1:ezvh/TsK7cY6rbqRK0oQQ8IAqLxYwwyPxAX1Pzy0ii0=
|
k8s.io/gengo v0.0.0-20200413195148-3a45101e95ac/go.mod h1:ezvh/TsK7cY6rbqRK0oQQ8IAqLxYwwyPxAX1Pzy0ii0=
|
||||||
k8s.io/klog/v2 v2.0.0/go.mod h1:PBfzABfn139FHAV07az/IF9Wp1bkk3vpT2XSJ76fSDE=
|
k8s.io/klog/v2 v2.0.0/go.mod h1:PBfzABfn139FHAV07az/IF9Wp1bkk3vpT2XSJ76fSDE=
|
||||||
k8s.io/klog/v2 v2.9.0/go.mod h1:hy9LJ/NvuK+iVyP4Ehqva4HxZG/oXyIS3n3Jmire4Ec=
|
k8s.io/klog/v2 v2.9.0/go.mod h1:hy9LJ/NvuK+iVyP4Ehqva4HxZG/oXyIS3n3Jmire4Ec=
|
||||||
k8s.io/klog/v2 v2.40.1 h1:P4RRucWk/lFOlDdkAr3mc7iWFkgKrZY9qZMAgek06S4=
|
k8s.io/klog/v2 v2.80.1 h1:atnLQ121W371wYYFawwYx1aEY2eUfs4l3J72wtgAwV4=
|
||||||
k8s.io/klog/v2 v2.40.1/go.mod h1:y1WjHnz7Dj687irZUWR/WLkLc5N1YHtjLdmgWjndZn0=
|
k8s.io/klog/v2 v2.80.1/go.mod h1:y1WjHnz7Dj687irZUWR/WLkLc5N1YHtjLdmgWjndZn0=
|
||||||
k8s.io/kube-openapi v0.0.0-20211109043538-20434351676c/go.mod h1:vHXdDvt9+2spS2Rx9ql3I8tycm3H9FDfdUoIuKCefvw=
|
k8s.io/kube-openapi v0.0.0-20211109043538-20434351676c/go.mod h1:vHXdDvt9+2spS2Rx9ql3I8tycm3H9FDfdUoIuKCefvw=
|
||||||
k8s.io/utils v0.0.0-20211116205334-6203023598ed/go.mod h1:jPW/WVKK9YHAvNhRxK0md/EJ228hCsBRufyofKtW8HA=
|
k8s.io/utils v0.0.0-20211116205334-6203023598ed/go.mod h1:jPW/WVKK9YHAvNhRxK0md/EJ228hCsBRufyofKtW8HA=
|
||||||
k8s.io/utils v0.0.0-20220706174534-f6158b442e7c h1:hFZO68mv/0xe8+V0gRT9BAq3/31cKjjeVv4nScriuBk=
|
k8s.io/utils v0.0.0-20221108210102-8e77b1f39fe2 h1:GfD9OzL11kvZN5iArC6oTS7RTj7oJOIfnislxYlqTj8=
|
||||||
k8s.io/utils v0.0.0-20220706174534-f6158b442e7c/go.mod h1:jPW/WVKK9YHAvNhRxK0md/EJ228hCsBRufyofKtW8HA=
|
k8s.io/utils v0.0.0-20221108210102-8e77b1f39fe2/go.mod h1:OLgZIPagt7ERELqWJFomSt595RzquPNLL48iOWgYOg0=
|
||||||
rsc.io/binaryregexp v0.2.0/go.mod h1:qTv7/COck+e2FymRvadv62gMdZztPaShugOCi3I+8D8=
|
rsc.io/binaryregexp v0.2.0/go.mod h1:qTv7/COck+e2FymRvadv62gMdZztPaShugOCi3I+8D8=
|
||||||
rsc.io/quote/v3 v3.1.0/go.mod h1:yEA65RcK8LyAZtP9Kv3t0HmxON59tX3rD+tICJqUlj0=
|
rsc.io/quote/v3 v3.1.0/go.mod h1:yEA65RcK8LyAZtP9Kv3t0HmxON59tX3rD+tICJqUlj0=
|
||||||
rsc.io/sampler v1.3.0/go.mod h1:T1hPZKmBbMNahiBKFy5HrXp6adAjACjK9JXDnKaTXpA=
|
rsc.io/sampler v1.3.0/go.mod h1:T1hPZKmBbMNahiBKFy5HrXp6adAjACjK9JXDnKaTXpA=
|
||||||
|
|||||||
12
internal/devserver/config.go
Normal file
12
internal/devserver/config.go
Normal file
@@ -0,0 +1,12 @@
|
|||||||
|
package devserver
|
||||||
|
|
||||||
|
// Config is config for inner http server.
|
||||||
|
type Config struct {
|
||||||
|
Enabled bool `json:",default=true"`
|
||||||
|
Host string `json:",optional"`
|
||||||
|
Port int `json:",default=6470"`
|
||||||
|
MetricsPath string `json:",default=/metrics"`
|
||||||
|
HealthPath string `json:",default=/healthz"`
|
||||||
|
EnableMetrics bool `json:",default=true"`
|
||||||
|
EnablePprof bool `json:",default=true"`
|
||||||
|
}
|
||||||
83
internal/devserver/server.go
Normal file
83
internal/devserver/server.go
Normal file
@@ -0,0 +1,83 @@
|
|||||||
|
package devserver
|
||||||
|
|
||||||
|
import (
|
||||||
|
"encoding/json"
|
||||||
|
"fmt"
|
||||||
|
"net/http"
|
||||||
|
"net/http/pprof"
|
||||||
|
"sync"
|
||||||
|
|
||||||
|
"github.com/felixge/fgprof"
|
||||||
|
"github.com/prometheus/client_golang/prometheus/promhttp"
|
||||||
|
"github.com/zeromicro/go-zero/core/logx"
|
||||||
|
"github.com/zeromicro/go-zero/core/threading"
|
||||||
|
"github.com/zeromicro/go-zero/internal/health"
|
||||||
|
)
|
||||||
|
|
||||||
|
var once sync.Once
|
||||||
|
|
||||||
|
// Server is inner http server, expose some useful observability information of app.
|
||||||
|
// For example health check, metrics and pprof.
|
||||||
|
type Server struct {
|
||||||
|
config *Config
|
||||||
|
server *http.ServeMux
|
||||||
|
routes []string
|
||||||
|
}
|
||||||
|
|
||||||
|
// NewServer returns a new inner http Server.
|
||||||
|
func NewServer(config *Config) *Server {
|
||||||
|
return &Server{
|
||||||
|
config: config,
|
||||||
|
server: http.NewServeMux(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *Server) addRoutes() {
|
||||||
|
// route path, routes list
|
||||||
|
s.handleFunc("/", func(w http.ResponseWriter, _ *http.Request) {
|
||||||
|
_ = json.NewEncoder(w).Encode(s.routes)
|
||||||
|
})
|
||||||
|
// health
|
||||||
|
s.handleFunc(s.config.HealthPath, health.CreateHttpHandler())
|
||||||
|
|
||||||
|
// metrics
|
||||||
|
if s.config.EnableMetrics {
|
||||||
|
s.handleFunc(s.config.MetricsPath, promhttp.Handler().ServeHTTP)
|
||||||
|
}
|
||||||
|
// pprof
|
||||||
|
if s.config.EnablePprof {
|
||||||
|
s.handleFunc("/debug/fgprof", fgprof.Handler().(http.HandlerFunc))
|
||||||
|
s.handleFunc("/debug/pprof/", pprof.Index)
|
||||||
|
s.handleFunc("/debug/pprof/cmdline", pprof.Cmdline)
|
||||||
|
s.handleFunc("/debug/pprof/profile", pprof.Profile)
|
||||||
|
s.handleFunc("/debug/pprof/symbol", pprof.Symbol)
|
||||||
|
s.handleFunc("/debug/pprof/trace", pprof.Trace)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *Server) handleFunc(pattern string, handler http.HandlerFunc) {
|
||||||
|
s.server.HandleFunc(pattern, handler)
|
||||||
|
s.routes = append(s.routes, pattern)
|
||||||
|
}
|
||||||
|
|
||||||
|
// StartAsync start inner http server background.
|
||||||
|
func (s *Server) StartAsync() {
|
||||||
|
s.addRoutes()
|
||||||
|
threading.GoSafe(func() {
|
||||||
|
addr := fmt.Sprintf("%s:%d", s.config.Host, s.config.Port)
|
||||||
|
logx.Infof("Starting dev http server at %s", addr)
|
||||||
|
if err := http.ListenAndServe(addr, s.server); err != nil {
|
||||||
|
logx.Error(err)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
// StartAgent start inner http server by config.
|
||||||
|
func StartAgent(c Config) {
|
||||||
|
once.Do(func() {
|
||||||
|
if c.Enabled {
|
||||||
|
s := NewServer(&c)
|
||||||
|
s.StartAsync()
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
75
internal/encoding/encoding.go
Normal file
75
internal/encoding/encoding.go
Normal file
@@ -0,0 +1,75 @@
|
|||||||
|
package encoding
|
||||||
|
|
||||||
|
import (
|
||||||
|
"bytes"
|
||||||
|
"encoding/json"
|
||||||
|
|
||||||
|
"github.com/pelletier/go-toml/v2"
|
||||||
|
"github.com/zeromicro/go-zero/core/lang"
|
||||||
|
"gopkg.in/yaml.v2"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TomlToJson(data []byte) ([]byte, error) {
|
||||||
|
var val interface{}
|
||||||
|
if err := toml.NewDecoder(bytes.NewReader(data)).Decode(&val); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
var buf bytes.Buffer
|
||||||
|
if err := json.NewEncoder(&buf).Encode(val); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return buf.Bytes(), nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func YamlToJson(data []byte) ([]byte, error) {
|
||||||
|
var val interface{}
|
||||||
|
if err := yaml.Unmarshal(data, &val); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
val = toStringKeyMap(val)
|
||||||
|
|
||||||
|
var buf bytes.Buffer
|
||||||
|
if err := json.NewEncoder(&buf).Encode(val); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return buf.Bytes(), nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func convertKeyToString(in map[interface{}]interface{}) map[string]interface{} {
|
||||||
|
res := make(map[string]interface{})
|
||||||
|
for k, v := range in {
|
||||||
|
res[lang.Repr(k)] = toStringKeyMap(v)
|
||||||
|
}
|
||||||
|
return res
|
||||||
|
}
|
||||||
|
|
||||||
|
func convertNumberToJsonNumber(in interface{}) json.Number {
|
||||||
|
return json.Number(lang.Repr(in))
|
||||||
|
}
|
||||||
|
|
||||||
|
func convertSlice(in []interface{}) []interface{} {
|
||||||
|
res := make([]interface{}, len(in))
|
||||||
|
for i, v := range in {
|
||||||
|
res[i] = toStringKeyMap(v)
|
||||||
|
}
|
||||||
|
return res
|
||||||
|
}
|
||||||
|
|
||||||
|
func toStringKeyMap(v interface{}) interface{} {
|
||||||
|
switch v := v.(type) {
|
||||||
|
case []interface{}:
|
||||||
|
return convertSlice(v)
|
||||||
|
case map[interface{}]interface{}:
|
||||||
|
return convertKeyToString(v)
|
||||||
|
case bool, string:
|
||||||
|
return v
|
||||||
|
case int, uint, int8, uint8, int16, uint16, int32, uint32, int64, uint64, float32, float64:
|
||||||
|
return convertNumberToJsonNumber(v)
|
||||||
|
default:
|
||||||
|
return lang.Repr(v)
|
||||||
|
}
|
||||||
|
}
|
||||||
118
internal/encoding/encoding_test.go
Normal file
118
internal/encoding/encoding_test.go
Normal file
@@ -0,0 +1,118 @@
|
|||||||
|
package encoding
|
||||||
|
|
||||||
|
import (
|
||||||
|
"testing"
|
||||||
|
|
||||||
|
"github.com/stretchr/testify/assert"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestTomlToJson(t *testing.T) {
|
||||||
|
tests := []struct {
|
||||||
|
input string
|
||||||
|
expect string
|
||||||
|
}{
|
||||||
|
{
|
||||||
|
input: "a = \"foo\"\nb = 1\nc = \"${FOO}\"\nd = \"abcd!@#$112\"",
|
||||||
|
expect: "{\"a\":\"foo\",\"b\":1,\"c\":\"${FOO}\",\"d\":\"abcd!@#$112\"}\n",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
input: "a = \"foo\"\nb = 1\nc = \"${FOO}\"\nd = \"abcd!@#$112\"",
|
||||||
|
expect: "{\"a\":\"foo\",\"b\":1,\"c\":\"${FOO}\",\"d\":\"abcd!@#$112\"}\n",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
input: "a = \"foo\"\nb = 1\nc = \"${FOO}\"\nd = \"abcd!@#$112\"",
|
||||||
|
expect: "{\"a\":\"foo\",\"b\":1,\"c\":\"${FOO}\",\"d\":\"abcd!@#$112\"}\n",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
input: "a = \"foo\"\nb = 1\nc = \"${FOO}\"\nd = \"abcd!@#$112\"",
|
||||||
|
expect: "{\"a\":\"foo\",\"b\":1,\"c\":\"${FOO}\",\"d\":\"abcd!@#$112\"}\n",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
input: "a = \"foo\"\nb = 1\nc = \"${FOO}\"\nd = \"abcd!@#$112\"",
|
||||||
|
expect: "{\"a\":\"foo\",\"b\":1,\"c\":\"${FOO}\",\"d\":\"abcd!@#$112\"}\n",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
input: "a = \"foo\"\nb = 1\nc = \"${FOO}\"\nd = \"abcd!@#$112\"\n",
|
||||||
|
expect: "{\"a\":\"foo\",\"b\":1,\"c\":\"${FOO}\",\"d\":\"abcd!@#$112\"}\n",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
input: "a = \"foo\"\nb = 1\nc = \"${FOO}\"\nd = \"abcd!@#$112\"\n",
|
||||||
|
expect: "{\"a\":\"foo\",\"b\":1,\"c\":\"${FOO}\",\"d\":\"abcd!@#$112\"}\n",
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, test := range tests {
|
||||||
|
test := test
|
||||||
|
t.Run(test.input, func(t *testing.T) {
|
||||||
|
t.Parallel()
|
||||||
|
got, err := TomlToJson([]byte(test.input))
|
||||||
|
assert.NoError(t, err)
|
||||||
|
assert.Equal(t, test.expect, string(got))
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestTomlToJsonError(t *testing.T) {
|
||||||
|
_, err := TomlToJson([]byte("foo"))
|
||||||
|
assert.Error(t, err)
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestYamlToJson(t *testing.T) {
|
||||||
|
tests := []struct {
|
||||||
|
input string
|
||||||
|
expect string
|
||||||
|
}{
|
||||||
|
{
|
||||||
|
input: "a: foo\nb: 1\nc: ${FOO}\nd: abcd!@#$112",
|
||||||
|
expect: "{\"a\":\"foo\",\"b\":1,\"c\":\"${FOO}\",\"d\":\"abcd!@#$112\"}\n",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
input: "a: foo\nb: 1\nc: ${FOO}\nd: abcd!@#$112",
|
||||||
|
expect: "{\"a\":\"foo\",\"b\":1,\"c\":\"${FOO}\",\"d\":\"abcd!@#$112\"}\n",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
input: "a: foo\nb: 1\nc: ${FOO}\nd: abcd!@#$112",
|
||||||
|
expect: "{\"a\":\"foo\",\"b\":1,\"c\":\"${FOO}\",\"d\":\"abcd!@#$112\"}\n",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
input: "a: foo\nb: 1\nc: ${FOO}\nd: abcd!@#$112",
|
||||||
|
expect: "{\"a\":\"foo\",\"b\":1,\"c\":\"${FOO}\",\"d\":\"abcd!@#$112\"}\n",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
input: "a: foo\nb: 1\nc: ${FOO}\nd: abcd!@#$112",
|
||||||
|
expect: "{\"a\":\"foo\",\"b\":1,\"c\":\"${FOO}\",\"d\":\"abcd!@#$112\"}\n",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
input: "a: foo\nb: 1\nc: ${FOO}\nd: abcd!@#$112\n",
|
||||||
|
expect: "{\"a\":\"foo\",\"b\":1,\"c\":\"${FOO}\",\"d\":\"abcd!@#$112\"}\n",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
input: "a: foo\nb: 1\nc: ${FOO}\nd: abcd!@#$112\n",
|
||||||
|
expect: "{\"a\":\"foo\",\"b\":1,\"c\":\"${FOO}\",\"d\":\"abcd!@#$112\"}\n",
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, test := range tests {
|
||||||
|
test := test
|
||||||
|
t.Run(test.input, func(t *testing.T) {
|
||||||
|
t.Parallel()
|
||||||
|
got, err := YamlToJson([]byte(test.input))
|
||||||
|
assert.NoError(t, err)
|
||||||
|
assert.Equal(t, test.expect, string(got))
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestYamlToJsonError(t *testing.T) {
|
||||||
|
_, err := YamlToJson([]byte("':foo"))
|
||||||
|
assert.Error(t, err)
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestYamlToJsonSlice(t *testing.T) {
|
||||||
|
b, err := YamlToJson([]byte(`foo:
|
||||||
|
- bar
|
||||||
|
- baz`))
|
||||||
|
assert.NoError(t, err)
|
||||||
|
assert.Equal(t, `{"foo":["bar","baz"]}
|
||||||
|
`, string(b))
|
||||||
|
}
|
||||||
145
internal/health/health.go
Normal file
145
internal/health/health.go
Normal file
@@ -0,0 +1,145 @@
|
|||||||
|
package health
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"net/http"
|
||||||
|
"strings"
|
||||||
|
"sync"
|
||||||
|
|
||||||
|
"github.com/zeromicro/go-zero/core/syncx"
|
||||||
|
)
|
||||||
|
|
||||||
|
// defaultHealthManager is global comboHealthManager for byone self.
|
||||||
|
var defaultHealthManager = newComboHealthManager()
|
||||||
|
|
||||||
|
type (
|
||||||
|
// Probe represents readiness status of given component.
|
||||||
|
Probe interface {
|
||||||
|
// MarkReady sets a ready state for the endpoint handlers.
|
||||||
|
MarkReady()
|
||||||
|
// MarkNotReady sets a not ready state for the endpoint handlers.
|
||||||
|
MarkNotReady()
|
||||||
|
// IsReady return inner state for the component.
|
||||||
|
IsReady() bool
|
||||||
|
// Name return probe name identifier
|
||||||
|
Name() string
|
||||||
|
}
|
||||||
|
|
||||||
|
// healthManager manage app healthy.
|
||||||
|
healthManager struct {
|
||||||
|
ready syncx.AtomicBool
|
||||||
|
name string
|
||||||
|
}
|
||||||
|
|
||||||
|
// comboHealthManager folds given probes into one, reflects their statuses in a thread-safe way.
|
||||||
|
comboHealthManager struct {
|
||||||
|
mu sync.Mutex
|
||||||
|
probes []Probe
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
|
// AddProbe add components probe to global comboHealthManager.
|
||||||
|
func AddProbe(probe Probe) {
|
||||||
|
defaultHealthManager.addProbe(probe)
|
||||||
|
}
|
||||||
|
|
||||||
|
// CreateHttpHandler create health http handler base on given probe.
|
||||||
|
func CreateHttpHandler() http.HandlerFunc {
|
||||||
|
return func(w http.ResponseWriter, _ *http.Request) {
|
||||||
|
if defaultHealthManager.IsReady() {
|
||||||
|
_, _ = w.Write([]byte("OK"))
|
||||||
|
} else {
|
||||||
|
http.Error(w, "Service Unavailable\n"+defaultHealthManager.verboseInfo(),
|
||||||
|
http.StatusServiceUnavailable)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// NewHealthManager returns a new healthManager.
|
||||||
|
func NewHealthManager(name string) Probe {
|
||||||
|
return &healthManager{
|
||||||
|
name: name,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// MarkReady sets a ready state for the endpoint handlers.
|
||||||
|
func (h *healthManager) MarkReady() {
|
||||||
|
h.ready.Set(true)
|
||||||
|
}
|
||||||
|
|
||||||
|
// MarkNotReady sets a not ready state for the endpoint handlers.
|
||||||
|
func (h *healthManager) MarkNotReady() {
|
||||||
|
h.ready.Set(false)
|
||||||
|
}
|
||||||
|
|
||||||
|
// IsReady return inner state for the component.
|
||||||
|
func (h *healthManager) IsReady() bool {
|
||||||
|
return h.ready.True()
|
||||||
|
}
|
||||||
|
|
||||||
|
// Name return probe name identifier
|
||||||
|
func (h *healthManager) Name() string {
|
||||||
|
return h.name
|
||||||
|
}
|
||||||
|
|
||||||
|
func newComboHealthManager() *comboHealthManager {
|
||||||
|
return &comboHealthManager{}
|
||||||
|
}
|
||||||
|
|
||||||
|
// MarkReady sets components status to ready.
|
||||||
|
func (p *comboHealthManager) MarkReady() {
|
||||||
|
p.mu.Lock()
|
||||||
|
defer p.mu.Unlock()
|
||||||
|
|
||||||
|
for _, probe := range p.probes {
|
||||||
|
probe.MarkReady()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// MarkNotReady sets components status to not ready with given error as a cause.
|
||||||
|
func (p *comboHealthManager) MarkNotReady() {
|
||||||
|
p.mu.Lock()
|
||||||
|
defer p.mu.Unlock()
|
||||||
|
|
||||||
|
for _, probe := range p.probes {
|
||||||
|
probe.MarkNotReady()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// IsReady return composed status of all components.
|
||||||
|
func (p *comboHealthManager) IsReady() bool {
|
||||||
|
p.mu.Lock()
|
||||||
|
defer p.mu.Unlock()
|
||||||
|
|
||||||
|
for _, probe := range p.probes {
|
||||||
|
if !probe.IsReady() {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p *comboHealthManager) verboseInfo() string {
|
||||||
|
p.mu.Lock()
|
||||||
|
defer p.mu.Unlock()
|
||||||
|
|
||||||
|
var info strings.Builder
|
||||||
|
for _, probe := range p.probes {
|
||||||
|
if probe.IsReady() {
|
||||||
|
info.WriteString(fmt.Sprintf("%s is ready\n", probe.Name()))
|
||||||
|
} else {
|
||||||
|
info.WriteString(fmt.Sprintf("%s is not ready\n", probe.Name()))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return info.String()
|
||||||
|
}
|
||||||
|
|
||||||
|
// addProbe add components probe to comboHealthManager.
|
||||||
|
func (p *comboHealthManager) addProbe(probe Probe) {
|
||||||
|
p.mu.Lock()
|
||||||
|
defer p.mu.Unlock()
|
||||||
|
|
||||||
|
p.probes = append(p.probes, probe)
|
||||||
|
}
|
||||||
140
internal/health/health_test.go
Normal file
140
internal/health/health_test.go
Normal file
@@ -0,0 +1,140 @@
|
|||||||
|
package health
|
||||||
|
|
||||||
|
import (
|
||||||
|
"io"
|
||||||
|
"net/http"
|
||||||
|
"net/http/httptest"
|
||||||
|
"strings"
|
||||||
|
"sync"
|
||||||
|
"testing"
|
||||||
|
|
||||||
|
"github.com/stretchr/testify/assert"
|
||||||
|
)
|
||||||
|
|
||||||
|
const probeName = "probe"
|
||||||
|
|
||||||
|
func TestHealthManager(t *testing.T) {
|
||||||
|
hm := NewHealthManager(probeName)
|
||||||
|
assert.False(t, hm.IsReady())
|
||||||
|
|
||||||
|
hm.MarkReady()
|
||||||
|
assert.True(t, hm.IsReady())
|
||||||
|
|
||||||
|
hm.MarkNotReady()
|
||||||
|
assert.False(t, hm.IsReady())
|
||||||
|
|
||||||
|
t.Run("concurrent should works", func(t *testing.T) {
|
||||||
|
var wg sync.WaitGroup
|
||||||
|
wg.Add(10)
|
||||||
|
for i := 0; i < 10; i++ {
|
||||||
|
go func() {
|
||||||
|
hm.MarkReady()
|
||||||
|
wg.Done()
|
||||||
|
}()
|
||||||
|
}
|
||||||
|
wg.Wait()
|
||||||
|
assert.True(t, hm.IsReady())
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestComboHealthManager(t *testing.T) {
|
||||||
|
t.Run("base", func(t *testing.T) {
|
||||||
|
chm := newComboHealthManager()
|
||||||
|
hm1 := NewHealthManager(probeName)
|
||||||
|
hm2 := NewHealthManager(probeName + "2")
|
||||||
|
|
||||||
|
assert.True(t, chm.IsReady())
|
||||||
|
chm.addProbe(hm1)
|
||||||
|
chm.addProbe(hm2)
|
||||||
|
assert.False(t, chm.IsReady())
|
||||||
|
hm1.MarkReady()
|
||||||
|
assert.False(t, chm.IsReady())
|
||||||
|
hm2.MarkReady()
|
||||||
|
assert.True(t, chm.IsReady())
|
||||||
|
})
|
||||||
|
|
||||||
|
t.Run("concurrent add probes", func(t *testing.T) {
|
||||||
|
chm := newComboHealthManager()
|
||||||
|
|
||||||
|
var wg sync.WaitGroup
|
||||||
|
wg.Add(10)
|
||||||
|
for i := 0; i < 10; i++ {
|
||||||
|
go func() {
|
||||||
|
hm := NewHealthManager(probeName)
|
||||||
|
hm.MarkReady()
|
||||||
|
chm.addProbe(hm)
|
||||||
|
wg.Done()
|
||||||
|
}()
|
||||||
|
}
|
||||||
|
wg.Wait()
|
||||||
|
assert.True(t, chm.IsReady())
|
||||||
|
})
|
||||||
|
|
||||||
|
t.Run("markReady and markNotReady", func(t *testing.T) {
|
||||||
|
chm := newComboHealthManager()
|
||||||
|
|
||||||
|
for i := 0; i < 10; i++ {
|
||||||
|
hm := NewHealthManager(probeName)
|
||||||
|
chm.addProbe(hm)
|
||||||
|
}
|
||||||
|
assert.False(t, chm.IsReady())
|
||||||
|
|
||||||
|
chm.MarkReady()
|
||||||
|
assert.True(t, chm.IsReady())
|
||||||
|
|
||||||
|
chm.MarkNotReady()
|
||||||
|
assert.False(t, chm.IsReady())
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestAddGlobalProbes(t *testing.T) {
|
||||||
|
cleanupForTest(t)
|
||||||
|
|
||||||
|
t.Run("concurrent add probes", func(t *testing.T) {
|
||||||
|
var wg sync.WaitGroup
|
||||||
|
wg.Add(10)
|
||||||
|
for i := 0; i < 10; i++ {
|
||||||
|
go func() {
|
||||||
|
hm := NewHealthManager(probeName)
|
||||||
|
hm.MarkReady()
|
||||||
|
AddProbe(hm)
|
||||||
|
wg.Done()
|
||||||
|
}()
|
||||||
|
}
|
||||||
|
wg.Wait()
|
||||||
|
assert.True(t, defaultHealthManager.IsReady())
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestCreateHttpHandler(t *testing.T) {
|
||||||
|
cleanupForTest(t)
|
||||||
|
srv := httptest.NewServer(CreateHttpHandler())
|
||||||
|
defer srv.Close()
|
||||||
|
|
||||||
|
resp, err := http.Get(srv.URL)
|
||||||
|
assert.Nil(t, err)
|
||||||
|
_ = resp.Body.Close()
|
||||||
|
assert.Equal(t, http.StatusOK, resp.StatusCode)
|
||||||
|
|
||||||
|
hm := NewHealthManager(probeName)
|
||||||
|
defaultHealthManager.addProbe(hm)
|
||||||
|
|
||||||
|
resp, err = http.Get(srv.URL)
|
||||||
|
assert.Nil(t, err)
|
||||||
|
assert.Equal(t, http.StatusServiceUnavailable, resp.StatusCode)
|
||||||
|
content, _ := io.ReadAll(resp.Body)
|
||||||
|
assert.True(t, strings.HasPrefix(string(content), "Service Unavailable"))
|
||||||
|
_ = resp.Body.Close()
|
||||||
|
|
||||||
|
hm.MarkReady()
|
||||||
|
resp, err = http.Get(srv.URL)
|
||||||
|
assert.Nil(t, err)
|
||||||
|
_ = resp.Body.Close()
|
||||||
|
assert.Equal(t, http.StatusOK, resp.StatusCode)
|
||||||
|
}
|
||||||
|
|
||||||
|
func cleanupForTest(t *testing.T) {
|
||||||
|
t.Cleanup(func() {
|
||||||
|
defaultHealthManager = &comboHealthManager{}
|
||||||
|
})
|
||||||
|
}
|
||||||
25
internal/trace/trace.go
Normal file
25
internal/trace/trace.go
Normal file
@@ -0,0 +1,25 @@
|
|||||||
|
package trace
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
|
||||||
|
"go.opentelemetry.io/otel/trace"
|
||||||
|
)
|
||||||
|
|
||||||
|
func SpanIDFromContext(ctx context.Context) string {
|
||||||
|
spanCtx := trace.SpanContextFromContext(ctx)
|
||||||
|
if spanCtx.HasSpanID() {
|
||||||
|
return spanCtx.SpanID().String()
|
||||||
|
}
|
||||||
|
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
|
||||||
|
func TraceIDFromContext(ctx context.Context) string {
|
||||||
|
spanCtx := trace.SpanContextFromContext(ctx)
|
||||||
|
if spanCtx.HasTraceID() {
|
||||||
|
return spanCtx.TraceID().String()
|
||||||
|
}
|
||||||
|
|
||||||
|
return ""
|
||||||
|
}
|
||||||
32
internal/trace/trace_test.go
Normal file
32
internal/trace/trace_test.go
Normal file
@@ -0,0 +1,32 @@
|
|||||||
|
package trace
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
"net/http"
|
||||||
|
"net/http/httptest"
|
||||||
|
"testing"
|
||||||
|
|
||||||
|
"github.com/stretchr/testify/assert"
|
||||||
|
sdktrace "go.opentelemetry.io/otel/sdk/trace"
|
||||||
|
semconv "go.opentelemetry.io/otel/semconv/v1.4.0"
|
||||||
|
oteltrace "go.opentelemetry.io/otel/trace"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestSpanIDFromContext(t *testing.T) {
|
||||||
|
tracer := sdktrace.NewTracerProvider().Tracer("test")
|
||||||
|
ctx, span := tracer.Start(
|
||||||
|
context.Background(),
|
||||||
|
"foo",
|
||||||
|
oteltrace.WithSpanKind(oteltrace.SpanKindClient),
|
||||||
|
oteltrace.WithAttributes(semconv.HTTPClientAttributesFromHTTPRequest(httptest.NewRequest(http.MethodGet, "/", nil))...),
|
||||||
|
)
|
||||||
|
defer span.End()
|
||||||
|
|
||||||
|
assert.NotEmpty(t, TraceIDFromContext(ctx))
|
||||||
|
assert.NotEmpty(t, SpanIDFromContext(ctx))
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestSpanIDFromContextEmpty(t *testing.T) {
|
||||||
|
assert.Empty(t, TraceIDFromContext(context.Background()))
|
||||||
|
assert.Empty(t, SpanIDFromContext(context.Background()))
|
||||||
|
}
|
||||||
69
readme.md
69
readme.md
@@ -1,8 +1,11 @@
|
|||||||
<img align="right" width="150px" src="https://raw.githubusercontent.com/zeromicro/zero-doc/main/doc/images/go-zero.png">
|
|
||||||
|
|
||||||
# go-zero
|
# go-zero
|
||||||
|
<p align="center">
|
||||||
|
<img align="center" width="150px" src="https://raw.githubusercontent.com/zeromicro/zero-doc/main/doc/images/go-zero.png">
|
||||||
|
</p>
|
||||||
|
|
||||||
English | [简体中文](readme-cn.md)
|
go-zero is a web and rpc framework with lots of builtin engineering practices. It’s born to ensure the stability of the busy services with resilience design and has been serving sites with tens of millions of users for years.
|
||||||
|
|
||||||
|
<div align=center>
|
||||||
|
|
||||||
[](https://github.com/zeromicro/go-zero/actions)
|
[](https://github.com/zeromicro/go-zero/actions)
|
||||||
[](https://codecov.io/gh/zeromicro/go-zero)
|
[](https://codecov.io/gh/zeromicro/go-zero)
|
||||||
@@ -13,23 +16,20 @@ English | [简体中文](readme-cn.md)
|
|||||||
[](https://opensource.org/licenses/MIT)
|
[](https://opensource.org/licenses/MIT)
|
||||||
[](https://discord.gg/4JQvC5A4Fe)
|
[](https://discord.gg/4JQvC5A4Fe)
|
||||||
|
|
||||||
|
</div>
|
||||||
|
|
||||||
|
|
||||||
|
## 🤷 What is go-zero?
|
||||||
|
English | [简体中文](readme-cn.md)
|
||||||
|
|
||||||
<a href="https://www.producthunt.com/posts/go-zero?utm_source=badge-featured&utm_medium=badge&utm_souce=badge-go-zero" target="_blank"><img src="https://api.producthunt.com/widgets/embed-image/v1/featured.svg?post_id=334030&theme=light" alt="go-zero - A web & rpc framework written in Go. | Product Hunt" style="width: 250px; height: 54px;" width="250" height="54" /></a>
|
<a href="https://www.producthunt.com/posts/go-zero?utm_source=badge-featured&utm_medium=badge&utm_souce=badge-go-zero" target="_blank"><img src="https://api.producthunt.com/widgets/embed-image/v1/featured.svg?post_id=334030&theme=light" alt="go-zero - A web & rpc framework written in Go. | Product Hunt" style="width: 250px; height: 54px;" width="250" height="54" /></a>
|
||||||
|
|
||||||
> ***Important!***
|
|
||||||
>
|
|
||||||
> To upgrade from versions eariler than v1.3.0, run the following commands.
|
|
||||||
>
|
|
||||||
> `go install github.com/zeromicro/go-zero/tools/goctl@latest`
|
|
||||||
>
|
|
||||||
> `goctl migrate —verbose —version v1.4.0`
|
|
||||||
|
|
||||||
## 0. what is go-zero
|
|
||||||
|
|
||||||
go-zero (listed in CNCF Landscape: [https://landscape.cncf.io/?selected=go-zero](https://landscape.cncf.io/?selected=go-zero)) is a web and rpc framework with lots of builtin engineering practices. It’s born to ensure the stability of the busy services with resilience design and has been serving sites with tens of millions of users for years.
|
go-zero (listed in CNCF Landscape: [https://landscape.cncf.io/?selected=go-zero](https://landscape.cncf.io/?selected=go-zero)) is a web and rpc framework with lots of builtin engineering practices. It’s born to ensure the stability of the busy services with resilience design and has been serving sites with tens of millions of users for years.
|
||||||
|
|
||||||
go-zero contains simple API description syntax and code generation tool called `goctl`. You can generate Go, iOS, Android, Kotlin, Dart, TypeScript, JavaScript from .api files with `goctl`.
|
go-zero contains simple API description syntax and code generation tool called `goctl`. You can generate Go, iOS, Android, Kotlin, Dart, TypeScript, JavaScript from .api files with `goctl`.
|
||||||
|
|
||||||
Advantages of go-zero:
|
#### Advantages of go-zero:
|
||||||
|
|
||||||
* improve the stability of the services with tens of millions of daily active users
|
* improve the stability of the services with tens of millions of daily active users
|
||||||
* builtin chained timeout control, concurrency control, rate limit, adaptive circuit breaker, adaptive load shedding, even no configuration needed
|
* builtin chained timeout control, concurrency control, rate limit, adaptive circuit breaker, adaptive load shedding, even no configuration needed
|
||||||
@@ -40,7 +40,7 @@ Advantages of go-zero:
|
|||||||
|
|
||||||
<img src="https://raw.githubusercontent.com/zeromicro/zero-doc/main/doc/images/architecture-en.png" alt="Architecture" width="1500" />
|
<img src="https://raw.githubusercontent.com/zeromicro/zero-doc/main/doc/images/architecture-en.png" alt="Architecture" width="1500" />
|
||||||
|
|
||||||
## 1. Backgrounds of go-zero
|
## Backgrounds of go-zero
|
||||||
|
|
||||||
At the beginning of 2018, we decided to re-design our system, from monolithic architecture with Java+MongoDB to microservice architecture. After research and comparison, we chose to:
|
At the beginning of 2018, we decided to re-design our system, from monolithic architecture with Java+MongoDB to microservice architecture. After research and comparison, we chose to:
|
||||||
|
|
||||||
@@ -55,7 +55,7 @@ At the beginning of 2018, we decided to re-design our system, from monolithic ar
|
|||||||
* easy to locate the problems
|
* easy to locate the problems
|
||||||
* easy to extend the features
|
* easy to extend the features
|
||||||
|
|
||||||
## 2. Design considerations on go-zero
|
## Design considerations on go-zero
|
||||||
|
|
||||||
By designing the microservice architecture, we expected to ensure stability, as well as productivity. And from just the beginning, we have the following design principles:
|
By designing the microservice architecture, we expected to ensure stability, as well as productivity. And from just the beginning, we have the following design principles:
|
||||||
|
|
||||||
@@ -69,7 +69,7 @@ By designing the microservice architecture, we expected to ensure stability, as
|
|||||||
|
|
||||||
After almost half a year, we finished the transfer from a monolithic system to microservice system and deployed on August 2018. The new system guaranteed business growth and system stability.
|
After almost half a year, we finished the transfer from a monolithic system to microservice system and deployed on August 2018. The new system guaranteed business growth and system stability.
|
||||||
|
|
||||||
## 3. The implementation and features of go-zero
|
## The implementation and features of go-zero
|
||||||
|
|
||||||
go-zero is a web and rpc framework that integrates lots of engineering practices. The features are mainly listed below:
|
go-zero is a web and rpc framework that integrates lots of engineering practices. The features are mainly listed below:
|
||||||
|
|
||||||
@@ -91,27 +91,38 @@ As below, go-zero protects the system with a couple of layers and mechanisms:
|
|||||||
|
|
||||||

|

|
||||||
|
|
||||||
## 4. The simplified architecture that we use with go-zero
|
## The simplified architecture that we use with go-zero
|
||||||
|
|
||||||
<img width="1067" alt="image" src="https://user-images.githubusercontent.com/1918356/171880372-5010d846-e8b1-4942-8fe2-e2bbb584f762.png">
|
<img width="1067" alt="image" src="https://user-images.githubusercontent.com/1918356/171880372-5010d846-e8b1-4942-8fe2-e2bbb584f762.png">
|
||||||
|
|
||||||
## 5. Installation
|
## Installation
|
||||||
|
|
||||||
Run the following command under your project:
|
Run the following command under your project:
|
||||||
|
|
||||||
```shell
|
```shell
|
||||||
go get -u github.com/zeromicro/go-zero
|
go get -u github.com/zeromicro/go-zero
|
||||||
```
|
```
|
||||||
|
## Upgrade
|
||||||
|
|
||||||
## 6. Quick Start
|
To upgrade from versions eariler than v1.3.0, run the following commands.
|
||||||
|
|
||||||
0. full examples can be checked out from below:
|
```shell
|
||||||
|
go install github.com/zeromicro/go-zero/tools/goctl@latest
|
||||||
|
```
|
||||||
|
|
||||||
|
```shell
|
||||||
|
goctl migrate —verbose —version v1.4.0
|
||||||
|
```
|
||||||
|
|
||||||
|
## Quick Start
|
||||||
|
|
||||||
|
1. full examples can be checked out from below:
|
||||||
|
|
||||||
[Rapid development of microservice systems](https://github.com/zeromicro/zero-doc/blob/main/doc/shorturl-en.md)
|
[Rapid development of microservice systems](https://github.com/zeromicro/zero-doc/blob/main/doc/shorturl-en.md)
|
||||||
|
|
||||||
[Rapid development of microservice systems - multiple RPCs](https://github.com/zeromicro/zero-doc/blob/main/docs/zero/bookstore-en.md)
|
[Rapid development of microservice systems - multiple RPCs](https://github.com/zeromicro/zero-doc/blob/main/docs/zero/bookstore-en.md)
|
||||||
|
|
||||||
1. install goctl
|
2. install goctl
|
||||||
|
|
||||||
`goctl`can be read as `go control`. `goctl` means not to be controlled by code, instead, we control it. The inside `go` is not `golang`. At the very beginning, I was expecting it to help us improve productivity, and make our lives easier.
|
`goctl`can be read as `go control`. `goctl` means not to be controlled by code, instead, we control it. The inside `go` is not `golang`. At the very beginning, I was expecting it to help us improve productivity, and make our lives easier.
|
||||||
|
|
||||||
@@ -138,7 +149,7 @@ go get -u github.com/zeromicro/go-zero
|
|||||||
|
|
||||||
make sure goctl is executable.
|
make sure goctl is executable.
|
||||||
|
|
||||||
2. create the API file, like greet.api, you can install the plugin of goctl in vs code, api syntax is supported.
|
3. create the API file, like greet.api, you can install the plugin of goctl in vs code, api syntax is supported.
|
||||||
|
|
||||||
```go
|
```go
|
||||||
type (
|
type (
|
||||||
@@ -163,7 +174,7 @@ go get -u github.com/zeromicro/go-zero
|
|||||||
goctl api -o greet.api
|
goctl api -o greet.api
|
||||||
```
|
```
|
||||||
|
|
||||||
3. generate the go server-side code
|
4. generate the go server-side code
|
||||||
|
|
||||||
```shell
|
```shell
|
||||||
goctl api go -api greet.api -dir greet
|
goctl api go -api greet.api -dir greet
|
||||||
@@ -216,12 +227,12 @@ go get -u github.com/zeromicro/go-zero
|
|||||||
Content-Length: 0
|
Content-Length: 0
|
||||||
```
|
```
|
||||||
|
|
||||||
4. Write the business logic code
|
5. Write the business logic code
|
||||||
|
|
||||||
* the dependencies can be passed into the logic within servicecontext.go, like mysql, reds, etc.
|
* the dependencies can be passed into the logic within servicecontext.go, like mysql, reds, etc.
|
||||||
* add the logic code in a logic package according to .api file
|
* add the logic code in a logic package according to .api file
|
||||||
|
|
||||||
5. Generate code like Java, TypeScript, Dart, JavaScript, etc. just from the api file
|
6. Generate code like Java, TypeScript, Dart, JavaScript, etc. just from the api file
|
||||||
|
|
||||||
```shell
|
```shell
|
||||||
goctl api java -api greet.api -dir greet
|
goctl api java -api greet.api -dir greet
|
||||||
@@ -229,24 +240,24 @@ go get -u github.com/zeromicro/go-zero
|
|||||||
...
|
...
|
||||||
```
|
```
|
||||||
|
|
||||||
## 7. Benchmark
|
## Benchmark
|
||||||
|
|
||||||

|

|
||||||
|
|
||||||
[Checkout the test code](https://github.com/smallnest/go-web-framework-benchmark)
|
[Checkout the test code](https://github.com/smallnest/go-web-framework-benchmark)
|
||||||
|
|
||||||
## 8. Documents
|
## Documents
|
||||||
|
|
||||||
* [Documents](https://go-zero.dev/)
|
* [Documents](https://go-zero.dev/)
|
||||||
* [Rapid development of microservice systems](https://github.com/zeromicro/zero-doc/blob/main/doc/shorturl-en.md)
|
* [Rapid development of microservice systems](https://github.com/zeromicro/zero-doc/blob/main/doc/shorturl-en.md)
|
||||||
* [Rapid development of microservice systems - multiple RPCs](https://github.com/zeromicro/zero-doc/blob/main/docs/zero/bookstore-en.md)
|
* [Rapid development of microservice systems - multiple RPCs](https://github.com/zeromicro/zero-doc/blob/main/docs/zero/bookstore-en.md)
|
||||||
* [Examples](https://github.com/zeromicro/zero-examples)
|
* [Examples](https://github.com/zeromicro/zero-examples)
|
||||||
|
|
||||||
## 9. Chat group
|
## Chat group
|
||||||
|
|
||||||
Join the chat via https://discord.gg/4JQvC5A4Fe
|
Join the chat via https://discord.gg/4JQvC5A4Fe
|
||||||
|
|
||||||
## 10. Cloud Native Landscape
|
## Cloud Native Landscape
|
||||||
|
|
||||||
<p float="left">
|
<p float="left">
|
||||||
<img src="https://landscape.cncf.io/images/left-logo.svg" width="150"/>
|
<img src="https://landscape.cncf.io/images/left-logo.svg" width="150"/>
|
||||||
|
|||||||
@@ -37,35 +37,41 @@ func New(middlewares ...Middleware) Chain {
|
|||||||
|
|
||||||
// Append extends a chain, adding the specified middlewares as the last ones in the request flow.
|
// Append extends a chain, adding the specified middlewares as the last ones in the request flow.
|
||||||
//
|
//
|
||||||
// c := chain.New(m1, m2)
|
// c := chain.New(m1, m2)
|
||||||
// c.Append(m3, m4)
|
// c.Append(m3, m4)
|
||||||
// // requests in c go m1 -> m2 -> m3 -> m4
|
// // requests in c go m1 -> m2 -> m3 -> m4
|
||||||
func (c chain) Append(middlewares ...Middleware) Chain {
|
func (c chain) Append(middlewares ...Middleware) Chain {
|
||||||
return chain{middlewares: join(c.middlewares, middlewares)}
|
return chain{middlewares: join(c.middlewares, middlewares)}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Prepend extends a chain by adding the specified chain as the first one in the request flow.
|
// Prepend extends a chain by adding the specified chain as the first one in the request flow.
|
||||||
//
|
//
|
||||||
// c := chain.New(m3, m4)
|
// c := chain.New(m3, m4)
|
||||||
// c1 := chain.New(m1, m2)
|
// c1 := chain.New(m1, m2)
|
||||||
// c.Prepend(c1)
|
// c.Prepend(c1)
|
||||||
// // requests in c go m1 -> m2 -> m3 -> m4
|
// // requests in c go m1 -> m2 -> m3 -> m4
|
||||||
func (c chain) Prepend(middlewares ...Middleware) Chain {
|
func (c chain) Prepend(middlewares ...Middleware) Chain {
|
||||||
return chain{middlewares: join(middlewares, c.middlewares)}
|
return chain{middlewares: join(middlewares, c.middlewares)}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Then chains the middleware and returns the final http.Handler.
|
// Then chains the middleware and returns the final http.Handler.
|
||||||
// New(m1, m2, m3).Then(h)
|
//
|
||||||
|
// New(m1, m2, m3).Then(h)
|
||||||
|
//
|
||||||
// is equivalent to:
|
// is equivalent to:
|
||||||
// m1(m2(m3(h)))
|
//
|
||||||
|
// m1(m2(m3(h)))
|
||||||
|
//
|
||||||
// When the request comes in, it will be passed to m1, then m2, then m3
|
// When the request comes in, it will be passed to m1, then m2, then m3
|
||||||
// and finally, the given handler
|
// and finally, the given handler
|
||||||
// (assuming every middleware calls the following one).
|
// (assuming every middleware calls the following one).
|
||||||
//
|
//
|
||||||
// A chain can be safely reused by calling Then() several times.
|
// A chain can be safely reused by calling Then() several times.
|
||||||
// stdStack := chain.New(ratelimitHandler, csrfHandler)
|
//
|
||||||
// indexPipe = stdStack.Then(indexHandler)
|
// stdStack := chain.New(ratelimitHandler, csrfHandler)
|
||||||
// authPipe = stdStack.Then(authHandler)
|
// indexPipe = stdStack.Then(indexHandler)
|
||||||
|
// authPipe = stdStack.Then(authHandler)
|
||||||
|
//
|
||||||
// Note that middlewares are called on every call to Then() or ThenFunc()
|
// Note that middlewares are called on every call to Then() or ThenFunc()
|
||||||
// and thus several instances of the same middleware will be created
|
// and thus several instances of the same middleware will be created
|
||||||
// when a chain is reused in this way.
|
// when a chain is reused in this way.
|
||||||
@@ -88,8 +94,9 @@ func (c chain) Then(h http.Handler) http.Handler {
|
|||||||
// a HandlerFunc instead of a Handler.
|
// a HandlerFunc instead of a Handler.
|
||||||
//
|
//
|
||||||
// The following two statements are equivalent:
|
// The following two statements are equivalent:
|
||||||
// c.Then(http.HandlerFunc(fn))
|
//
|
||||||
// c.ThenFunc(fn)
|
// c.Then(http.HandlerFunc(fn))
|
||||||
|
// c.ThenFunc(fn)
|
||||||
//
|
//
|
||||||
// ThenFunc provides all the guarantees of Then.
|
// ThenFunc provides all the guarantees of Then.
|
||||||
func (c chain) ThenFunc(fn http.HandlerFunc) http.Handler {
|
func (c chain) ThenFunc(fn http.HandlerFunc) http.Handler {
|
||||||
|
|||||||
@@ -86,7 +86,7 @@ func TestThenOrdersHandlersCorrectly(t *testing.T) {
|
|||||||
chained := New(t1, t2, t3).Then(testApp)
|
chained := New(t1, t2, t3).Then(testApp)
|
||||||
|
|
||||||
w := httptest.NewRecorder()
|
w := httptest.NewRecorder()
|
||||||
r, err := http.NewRequest("GET", "/", nil)
|
r, err := http.NewRequest("GET", "/", http.NoBody)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
@@ -103,7 +103,7 @@ func TestAppendAddsHandlersCorrectly(t *testing.T) {
|
|||||||
h := c.Then(testApp)
|
h := c.Then(testApp)
|
||||||
|
|
||||||
w := httptest.NewRecorder()
|
w := httptest.NewRecorder()
|
||||||
r, err := http.NewRequest("GET", "/", nil)
|
r, err := http.NewRequest("GET", "/", http.NoBody)
|
||||||
assert.Nil(t, err)
|
assert.Nil(t, err)
|
||||||
|
|
||||||
h.ServeHTTP(w, r)
|
h.ServeHTTP(w, r)
|
||||||
|
|||||||
@@ -237,8 +237,8 @@ func TestEngine_notFoundHandler(t *testing.T) {
|
|||||||
defer ts.Close()
|
defer ts.Close()
|
||||||
|
|
||||||
client := ts.Client()
|
client := ts.Client()
|
||||||
err := func(ctx context.Context) error {
|
err := func(_ context.Context) error {
|
||||||
req, err := http.NewRequest("GET", ts.URL+"/bad", nil)
|
req, err := http.NewRequest("GET", ts.URL+"/bad", http.NoBody)
|
||||||
assert.Nil(t, err)
|
assert.Nil(t, err)
|
||||||
res, err := client.Do(req)
|
res, err := client.Do(req)
|
||||||
assert.Nil(t, err)
|
assert.Nil(t, err)
|
||||||
@@ -260,8 +260,8 @@ func TestEngine_notFoundHandlerNotNil(t *testing.T) {
|
|||||||
defer ts.Close()
|
defer ts.Close()
|
||||||
|
|
||||||
client := ts.Client()
|
client := ts.Client()
|
||||||
err := func(ctx context.Context) error {
|
err := func(_ context.Context) error {
|
||||||
req, err := http.NewRequest("GET", ts.URL+"/bad", nil)
|
req, err := http.NewRequest("GET", ts.URL+"/bad", http.NoBody)
|
||||||
assert.Nil(t, err)
|
assert.Nil(t, err)
|
||||||
res, err := client.Do(req)
|
res, err := client.Do(req)
|
||||||
assert.Nil(t, err)
|
assert.Nil(t, err)
|
||||||
@@ -285,8 +285,8 @@ func TestEngine_notFoundHandlerNotNilWriteHeader(t *testing.T) {
|
|||||||
defer ts.Close()
|
defer ts.Close()
|
||||||
|
|
||||||
client := ts.Client()
|
client := ts.Client()
|
||||||
err := func(ctx context.Context) error {
|
err := func(_ context.Context) error {
|
||||||
req, err := http.NewRequest("GET", ts.URL+"/bad", nil)
|
req, err := http.NewRequest("GET", ts.URL+"/bad", http.NoBody)
|
||||||
assert.Nil(t, err)
|
assert.Nil(t, err)
|
||||||
res, err := client.Do(req)
|
res, err := client.Do(req)
|
||||||
assert.Nil(t, err)
|
assert.Nil(t, err)
|
||||||
|
|||||||
@@ -29,7 +29,7 @@ var (
|
|||||||
)
|
)
|
||||||
|
|
||||||
type (
|
type (
|
||||||
// A AuthorizeOptions is authorize options.
|
// An AuthorizeOptions is authorize options.
|
||||||
AuthorizeOptions struct {
|
AuthorizeOptions struct {
|
||||||
PrevSecret string
|
PrevSecret string
|
||||||
Callback UnauthorizedCallback
|
Callback UnauthorizedCallback
|
||||||
|
|||||||
@@ -13,7 +13,7 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
func TestAuthHandlerFailed(t *testing.T) {
|
func TestAuthHandlerFailed(t *testing.T) {
|
||||||
req := httptest.NewRequest(http.MethodGet, "http://localhost", nil)
|
req := httptest.NewRequest(http.MethodGet, "http://localhost", http.NoBody)
|
||||||
handler := Authorize("B63F477D-BBA3-4E52-96D3-C0034C27694A", WithUnauthorizedCallback(
|
handler := Authorize("B63F477D-BBA3-4E52-96D3-C0034C27694A", WithUnauthorizedCallback(
|
||||||
func(w http.ResponseWriter, r *http.Request, err error) {
|
func(w http.ResponseWriter, r *http.Request, err error) {
|
||||||
assert.NotNil(t, err)
|
assert.NotNil(t, err)
|
||||||
@@ -33,7 +33,7 @@ func TestAuthHandlerFailed(t *testing.T) {
|
|||||||
|
|
||||||
func TestAuthHandler(t *testing.T) {
|
func TestAuthHandler(t *testing.T) {
|
||||||
const key = "B63F477D-BBA3-4E52-96D3-C0034C27694A"
|
const key = "B63F477D-BBA3-4E52-96D3-C0034C27694A"
|
||||||
req := httptest.NewRequest(http.MethodGet, "http://localhost", nil)
|
req := httptest.NewRequest(http.MethodGet, "http://localhost", http.NoBody)
|
||||||
token, err := buildToken(key, map[string]interface{}{
|
token, err := buildToken(key, map[string]interface{}{
|
||||||
"key": "value",
|
"key": "value",
|
||||||
}, 3600)
|
}, 3600)
|
||||||
@@ -62,7 +62,7 @@ func TestAuthHandlerWithPrevSecret(t *testing.T) {
|
|||||||
key = "14F17379-EB8F-411B-8F12-6929002DCA76"
|
key = "14F17379-EB8F-411B-8F12-6929002DCA76"
|
||||||
prevKey = "B63F477D-BBA3-4E52-96D3-C0034C27694A"
|
prevKey = "B63F477D-BBA3-4E52-96D3-C0034C27694A"
|
||||||
)
|
)
|
||||||
req := httptest.NewRequest(http.MethodGet, "http://localhost", nil)
|
req := httptest.NewRequest(http.MethodGet, "http://localhost", http.NoBody)
|
||||||
token, err := buildToken(key, map[string]interface{}{
|
token, err := buildToken(key, map[string]interface{}{
|
||||||
"key": "value",
|
"key": "value",
|
||||||
}, 3600)
|
}, 3600)
|
||||||
@@ -83,7 +83,7 @@ func TestAuthHandlerWithPrevSecret(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func TestAuthHandler_NilError(t *testing.T) {
|
func TestAuthHandler_NilError(t *testing.T) {
|
||||||
req := httptest.NewRequest(http.MethodGet, "http://localhost", nil)
|
req := httptest.NewRequest(http.MethodGet, "http://localhost", http.NoBody)
|
||||||
resp := httptest.NewRecorder()
|
resp := httptest.NewRecorder()
|
||||||
assert.NotPanics(t, func() {
|
assert.NotPanics(t, func() {
|
||||||
unauthorized(resp, req, nil, nil)
|
unauthorized(resp, req, nil, nil)
|
||||||
|
|||||||
@@ -25,7 +25,7 @@ func TestBreakerHandlerAccept(t *testing.T) {
|
|||||||
assert.Nil(t, err)
|
assert.Nil(t, err)
|
||||||
}))
|
}))
|
||||||
|
|
||||||
req := httptest.NewRequest(http.MethodGet, "http://localhost", nil)
|
req := httptest.NewRequest(http.MethodGet, "http://localhost", http.NoBody)
|
||||||
req.Header.Set("X-Test", "test")
|
req.Header.Set("X-Test", "test")
|
||||||
resp := httptest.NewRecorder()
|
resp := httptest.NewRecorder()
|
||||||
handler.ServeHTTP(resp, req)
|
handler.ServeHTTP(resp, req)
|
||||||
@@ -41,7 +41,7 @@ func TestBreakerHandlerFail(t *testing.T) {
|
|||||||
w.WriteHeader(http.StatusBadGateway)
|
w.WriteHeader(http.StatusBadGateway)
|
||||||
}))
|
}))
|
||||||
|
|
||||||
req := httptest.NewRequest(http.MethodGet, "http://localhost", nil)
|
req := httptest.NewRequest(http.MethodGet, "http://localhost", http.NoBody)
|
||||||
resp := httptest.NewRecorder()
|
resp := httptest.NewRecorder()
|
||||||
handler.ServeHTTP(resp, req)
|
handler.ServeHTTP(resp, req)
|
||||||
assert.Equal(t, http.StatusBadGateway, resp.Code)
|
assert.Equal(t, http.StatusBadGateway, resp.Code)
|
||||||
@@ -55,7 +55,7 @@ func TestBreakerHandler_4XX(t *testing.T) {
|
|||||||
}))
|
}))
|
||||||
|
|
||||||
for i := 0; i < 1000; i++ {
|
for i := 0; i < 1000; i++ {
|
||||||
req := httptest.NewRequest(http.MethodGet, "http://localhost", nil)
|
req := httptest.NewRequest(http.MethodGet, "http://localhost", http.NoBody)
|
||||||
resp := httptest.NewRecorder()
|
resp := httptest.NewRecorder()
|
||||||
handler.ServeHTTP(resp, req)
|
handler.ServeHTTP(resp, req)
|
||||||
}
|
}
|
||||||
@@ -63,7 +63,7 @@ func TestBreakerHandler_4XX(t *testing.T) {
|
|||||||
const tries = 100
|
const tries = 100
|
||||||
var pass int
|
var pass int
|
||||||
for i := 0; i < tries; i++ {
|
for i := 0; i < tries; i++ {
|
||||||
req := httptest.NewRequest(http.MethodGet, "http://localhost", nil)
|
req := httptest.NewRequest(http.MethodGet, "http://localhost", http.NoBody)
|
||||||
resp := httptest.NewRecorder()
|
resp := httptest.NewRecorder()
|
||||||
handler.ServeHTTP(resp, req)
|
handler.ServeHTTP(resp, req)
|
||||||
if resp.Code == http.StatusBadRequest {
|
if resp.Code == http.StatusBadRequest {
|
||||||
@@ -82,14 +82,14 @@ func TestBreakerHandlerReject(t *testing.T) {
|
|||||||
}))
|
}))
|
||||||
|
|
||||||
for i := 0; i < 1000; i++ {
|
for i := 0; i < 1000; i++ {
|
||||||
req := httptest.NewRequest(http.MethodGet, "http://localhost", nil)
|
req := httptest.NewRequest(http.MethodGet, "http://localhost", http.NoBody)
|
||||||
resp := httptest.NewRecorder()
|
resp := httptest.NewRecorder()
|
||||||
handler.ServeHTTP(resp, req)
|
handler.ServeHTTP(resp, req)
|
||||||
}
|
}
|
||||||
|
|
||||||
var drops int
|
var drops int
|
||||||
for i := 0; i < 100; i++ {
|
for i := 0; i < 100; i++ {
|
||||||
req := httptest.NewRequest(http.MethodGet, "http://localhost", nil)
|
req := httptest.NewRequest(http.MethodGet, "http://localhost", http.NoBody)
|
||||||
resp := httptest.NewRecorder()
|
resp := httptest.NewRecorder()
|
||||||
handler.ServeHTTP(resp, req)
|
handler.ServeHTTP(resp, req)
|
||||||
if resp.Code == http.StatusServiceUnavailable {
|
if resp.Code == http.StatusServiceUnavailable {
|
||||||
|
|||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user