From 2b796a0c9ab3614e7360bfbdb451dc5f753e6157 Mon Sep 17 00:00:00 2001 From: Karuppiah Natarajan Date: Fri, 2 Jul 2021 17:47:40 +0530 Subject: [PATCH 001/258] scripts: add script to measure percentage of commits with failed status This is to start measuring the test flakiness and see the numbers improving once we improve and deflake flaky tests Fixes #13167 --- scripts/measure-test-flakiness.sh | 27 +++++++++++++++++++++++++++ 1 file changed, 27 insertions(+) create mode 100755 scripts/measure-test-flakiness.sh diff --git a/scripts/measure-test-flakiness.sh b/scripts/measure-test-flakiness.sh new file mode 100755 index 000000000000..84f9782ddad6 --- /dev/null +++ b/scripts/measure-test-flakiness.sh @@ -0,0 +1,27 @@ +#!/bin/bash + +set -e +set -o pipefail + +if [[ -z ${GITHUB_TOKEN} ]] +then + echo "Please set the \$GITHUB_TOKEN environment variable for the script to work" + exit 1 +fi + +temp_dir=$(mktemp -d) + +trap '{ rm -rf -- "${temp_dir}"; }' EXIT + +json_file="${temp_dir}/commit-and-check-data.json" + +curl --fail --show-error --silent -H "Authorization: token ${GITHUB_TOKEN}" \ + -X POST \ + -d '{ + "query": "query { repository(owner: \"etcd-io\", name: \"etcd\") { defaultBranchRef { target { ... on Commit { history(first: 100) { edges { node { ... on Commit { commitUrl statusCheckRollup { state } } } } } } } } } }" + }' \ + https://api.github.com/graphql | jq . > "${json_file}" + +failure_percentage=$(jq '.data.repository.defaultBranchRef.target.history.edges | reduce .[] as $item (0; if $item.node.statusCheckRollup.state == "FAILURE" then (. + 1) else . end)' "${json_file}") + +echo "Commit status failure percentage is - ${failure_percentage} %" From 3317716fafedbf849583fd9df73f70cdfdb382b2 Mon Sep 17 00:00:00 2001 From: Karuppiah Natarajan Date: Tue, 13 Jul 2021 18:50:55 +0530 Subject: [PATCH 002/258] workflow: add workflow to invoke script that measures percentage of commits with failed status The workflow runs on a cron schedule on a weekly basis - once every week Fixes #13167 --- .github/workflows/measure-test-flakiness.yaml | 15 +++++++++++++++ 1 file changed, 15 insertions(+) create mode 100644 .github/workflows/measure-test-flakiness.yaml diff --git a/.github/workflows/measure-test-flakiness.yaml b/.github/workflows/measure-test-flakiness.yaml new file mode 100644 index 000000000000..0c128fb2b859 --- /dev/null +++ b/.github/workflows/measure-test-flakiness.yaml @@ -0,0 +1,15 @@ +name: Measure Test Flakiness + +on: + schedule: + - cron: "0 0 * * 0" + +jobs: + measure-test-flakiness: + name: Measure Test Flakiness + runs-on: ubuntu-latest + steps: + - name: Run script to measure test flakiness + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + run: "./scripts/measure-test-flakiness.sh" From 020c4f8ca7bf30db12410ce2871d4b251aac787e Mon Sep 17 00:00:00 2001 From: Xiang Liu Date: Sun, 24 Oct 2021 19:33:22 +0800 Subject: [PATCH 003/258] raft: avoid jump tag to make code more understandable --- raft/node.go | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/raft/node.go b/raft/node.go index 74376ba84816..d374b6c0c21f 100644 --- a/raft/node.go +++ b/raft/node.go @@ -372,14 +372,16 @@ func (n *node) run() { // very sound and likely has bugs. if _, okAfter := r.prs.Progress[r.id]; okBefore && !okAfter { var found bool - outer: for _, sl := range [][]uint64{cs.Voters, cs.VotersOutgoing} { for _, id := range sl { if id == r.id { found = true - break outer + break } } + if found { + break + } } if !found { propc = nil From 63a1cc3fe40bace6898289dec35a9aad05163889 Mon Sep 17 00:00:00 2001 From: Sam Batschelet Date: Thu, 30 Sep 2021 12:44:39 -0400 Subject: [PATCH 004/258] add --experimental-max-learner flag Signed-off-by: Sam Batschelet --- server/config/config.go | 3 + server/embed/config.go | 4 + server/embed/etcd.go | 4 +- server/etcdmain/config.go | 2 + server/etcdmain/help.go | 4 +- server/etcdserver/api/membership/cluster.go | 74 +++++---- .../etcdserver/api/membership/cluster_opts.go | 43 ++++++ .../etcdserver/api/membership/cluster_test.go | 35 ++++- .../api/membership/membership_test.go | 4 +- server/etcdserver/bootstrap.go | 23 ++- server/etcdserver/bootstrap_test.go | 140 ++++++++++++++++++ tests/framework/integration/cluster.go | 9 +- tests/integration/clientv3/cluster_test.go | 33 +++-- 13 files changed, 330 insertions(+), 48 deletions(-) create mode 100644 server/etcdserver/api/membership/cluster_opts.go create mode 100644 server/etcdserver/bootstrap_test.go diff --git a/server/config/config.go b/server/config/config.go index c9e7d3aa3f01..74587efd6a04 100644 --- a/server/config/config.go +++ b/server/config/config.go @@ -185,6 +185,9 @@ type ServerConfig struct { // consider running defrag during bootstrap. Needs to be set to non-zero value to take effect. ExperimentalBootstrapDefragThresholdMegabytes uint `json:"experimental-bootstrap-defrag-threshold-megabytes"` + // ExperimentalMaxLearners sets a limit to the number of learner members that can exist in the cluster membership. + ExperimentalMaxLearners int `json:"experimental-max-learners"` + // V2Deprecation defines a phase of v2store deprecation process. V2Deprecation V2DeprecationEnum `json:"v2-deprecation"` } diff --git a/server/embed/config.go b/server/embed/config.go index abcdead5a8ba..ecec546a0e0b 100644 --- a/server/embed/config.go +++ b/server/embed/config.go @@ -34,6 +34,7 @@ import ( "go.etcd.io/etcd/pkg/v3/netutil" "go.etcd.io/etcd/server/v3/config" "go.etcd.io/etcd/server/v3/etcdserver" + "go.etcd.io/etcd/server/v3/etcdserver/api/membership" "go.etcd.io/etcd/server/v3/etcdserver/api/v3compactor" bolt "go.etcd.io/bbolt" @@ -329,6 +330,8 @@ type Config struct { // ExperimentalWarningUnaryRequestDuration is the time duration after which a warning is generated if applying // unary request takes more time than this value. ExperimentalWarningUnaryRequestDuration time.Duration `json:"experimental-warning-unary-request-duration"` + // ExperimentalMaxLearners sets a limit to the number of learner members that can exist in the cluster membership. + ExperimentalMaxLearners int `json:"experimental-max-learners"` // ForceNewCluster starts a new cluster even if previously started; unsafe. ForceNewCluster bool `json:"force-new-cluster"` @@ -503,6 +506,7 @@ func NewConfig() *Config { ExperimentalDowngradeCheckTime: DefaultDowngradeCheckTime, ExperimentalMemoryMlock: false, ExperimentalTxnModeWriteWithSharedBuffer: true, + ExperimentalMaxLearners: membership.DefaultMaxLearners, V2Deprecation: config.V2_DEPR_DEFAULT, } diff --git a/server/embed/etcd.go b/server/embed/etcd.go index 418199037cd0..5970437f0f07 100644 --- a/server/embed/etcd.go +++ b/server/embed/etcd.go @@ -219,7 +219,8 @@ func StartEtcd(inCfg *Config) (e *Etcd, err error) { ExperimentalMemoryMlock: cfg.ExperimentalMemoryMlock, ExperimentalTxnModeWriteWithSharedBuffer: cfg.ExperimentalTxnModeWriteWithSharedBuffer, ExperimentalBootstrapDefragThresholdMegabytes: cfg.ExperimentalBootstrapDefragThresholdMegabytes, - V2Deprecation: cfg.V2DeprecationEffective(), + ExperimentalMaxLearners: cfg.ExperimentalMaxLearners, + V2Deprecation: cfg.V2DeprecationEffective(), } if srvcfg.ExperimentalEnableDistributedTracing { @@ -345,6 +346,7 @@ func print(lg *zap.Logger, ec Config, sc config.ServerConfig, memberInitialized zap.String("discovery-url", sc.DiscoveryURL), zap.String("discovery-proxy", sc.DiscoveryProxy), zap.String("downgrade-check-interval", sc.DowngradeCheckTime.String()), + zap.Int("max-learners", sc.ExperimentalMaxLearners), ) } diff --git a/server/etcdmain/config.go b/server/etcdmain/config.go index 2c3f135d88bc..52c99eb6b7e1 100644 --- a/server/etcdmain/config.go +++ b/server/etcdmain/config.go @@ -28,6 +28,7 @@ import ( "go.etcd.io/etcd/pkg/v3/flags" cconfig "go.etcd.io/etcd/server/v3/config" "go.etcd.io/etcd/server/v3/embed" + "go.etcd.io/etcd/server/v3/etcdserver/api/membership" "go.etcd.io/etcd/server/v3/etcdserver/api/rafthttp" "go.uber.org/zap" @@ -291,6 +292,7 @@ func newConfig() *config { fs.BoolVar(&cfg.ec.ExperimentalMemoryMlock, "experimental-memory-mlock", cfg.ec.ExperimentalMemoryMlock, "Enable to enforce etcd pages (in particular bbolt) to stay in RAM.") fs.BoolVar(&cfg.ec.ExperimentalTxnModeWriteWithSharedBuffer, "experimental-txn-mode-write-with-shared-buffer", true, "Enable the write transaction to use a shared buffer in its readonly check operations.") fs.UintVar(&cfg.ec.ExperimentalBootstrapDefragThresholdMegabytes, "experimental-bootstrap-defrag-threshold-megabytes", 0, "Enable the defrag during etcd server bootstrap on condition that it will free at least the provided threshold of disk space. Needs to be set to non-zero value to take effect.") + fs.IntVar(&cfg.ec.ExperimentalMaxLearners, "experimental-max-learners", membership.DefaultMaxLearners, "Sets the maximum number of learners that can be available in the cluster membership.") // unsafe fs.BoolVar(&cfg.ec.UnsafeNoFsync, "unsafe-no-fsync", false, "Disables fsync, unsafe, will cause data loss.") diff --git a/server/etcdmain/help.go b/server/etcdmain/help.go index 1af8293340ce..617e66bd7e50 100644 --- a/server/etcdmain/help.go +++ b/server/etcdmain/help.go @@ -245,13 +245,15 @@ Experimental feature: --experimental-watch-progress-notify-interval '10m' Duration of periodical watch progress notification. --experimental-warning-apply-duration '100ms' - Warning is generated if requests take more than this duration. + Warning is generated if requests take more than this duration. --experimental-txn-mode-write-with-shared-buffer 'true' Enable the write transaction to use a shared buffer in its readonly check operations. --experimental-bootstrap-defrag-threshold-megabytes Enable the defrag during etcd server bootstrap on condition that it will free at least the provided threshold of disk space. Needs to be set to non-zero value to take effect. --experimental-warning-unary-request-duration '300ms' Set time duration after which a warning is generated if a unary request takes more than this duration. + --experimental-max-learners '1' + Set the max number of learner members allowed in the cluster membership. Unsafe feature: --force-new-cluster 'false' diff --git a/server/etcdserver/api/membership/cluster.go b/server/etcdserver/api/membership/cluster.go index 795556b8835f..18ac1a35f51a 100644 --- a/server/etcdserver/api/membership/cluster.go +++ b/server/etcdserver/api/membership/cluster.go @@ -40,8 +40,6 @@ import ( "go.uber.org/zap" ) -const maxLearners = 1 - // RaftCluster is a list of Members that belong to the same raft cluster type RaftCluster struct { lg *zap.Logger @@ -60,6 +58,7 @@ type RaftCluster struct { removed map[types.ID]bool downgradeInfo *serverversion.DowngradeInfo + maxLearners int versionChanged *notify.Notifier } @@ -81,8 +80,8 @@ const ( // NewClusterFromURLsMap creates a new raft cluster using provided urls map. Currently, it does not support creating // cluster with raft learner member. -func NewClusterFromURLsMap(lg *zap.Logger, token string, urlsmap types.URLsMap) (*RaftCluster, error) { - c := NewCluster(lg) +func NewClusterFromURLsMap(lg *zap.Logger, token string, urlsmap types.URLsMap, opts ...ClusterOption) (*RaftCluster, error) { + c := NewCluster(lg, opts...) for name, urls := range urlsmap { m := NewMember(name, urls, token, nil) if _, ok := c.members[m.ID]; ok { @@ -97,8 +96,8 @@ func NewClusterFromURLsMap(lg *zap.Logger, token string, urlsmap types.URLsMap) return c, nil } -func NewClusterFromMembers(lg *zap.Logger, id types.ID, membs []*Member) *RaftCluster { - c := NewCluster(lg) +func NewClusterFromMembers(lg *zap.Logger, id types.ID, membs []*Member, opts ...ClusterOption) *RaftCluster { + c := NewCluster(lg, opts...) c.cid = id for _, m := range membs { c.members[m.ID] = m @@ -106,15 +105,18 @@ func NewClusterFromMembers(lg *zap.Logger, id types.ID, membs []*Member) *RaftCl return c } -func NewCluster(lg *zap.Logger) *RaftCluster { +func NewCluster(lg *zap.Logger, opts ...ClusterOption) *RaftCluster { if lg == nil { lg = zap.NewNop() } + clOpts := newClusterOpts(opts...) + return &RaftCluster{ lg: lg, members: make(map[types.ID]*Member), removed: make(map[types.ID]bool), downgradeInfo: &serverversion.DowngradeInfo{Enabled: false}, + maxLearners: clOpts.maxLearners, } } @@ -289,6 +291,7 @@ func (c *RaftCluster) Recover(onSet func(*zap.Logger, *semver.Version)) { zap.String("local-member-id", c.localID.String()), zap.String("recovered-remote-peer-id", m.ID.String()), zap.Strings("recovered-remote-peer-urls", m.PeerURLs), + zap.Bool("recovered-remote-peer-is-learner", m.IsLearner), ) } if c.version != nil { @@ -303,9 +306,9 @@ func (c *RaftCluster) Recover(onSet func(*zap.Logger, *semver.Version)) { // ensures that it is still valid. func (c *RaftCluster) ValidateConfigurationChange(cc raftpb.ConfChange) error { // TODO: this must be switched to backend as well. - members, removed := membersFromStore(c.lg, c.v2store) + membersMap, removedMap := membersFromStore(c.lg, c.v2store) id := types.ID(cc.NodeID) - if removed[id] { + if removedMap[id] { return ErrIDRemoved } switch cc.Type { @@ -316,19 +319,21 @@ func (c *RaftCluster) ValidateConfigurationChange(cc raftpb.ConfChange) error { } if confChangeContext.IsPromote { // promoting a learner member to voting member - if members[id] == nil { + if membersMap[id] == nil { return ErrIDNotFound } - if !members[id].IsLearner { + if !membersMap[id].IsLearner { return ErrMemberNotLearner } } else { // adding a new member - if members[id] != nil { + if membersMap[id] != nil { return ErrIDExists } + var members []*Member urls := make(map[string]bool) - for _, m := range members { + for _, m := range membersMap { + members = append(members, m) for _, u := range m.PeerURLs { urls[u] = true } @@ -339,29 +344,24 @@ func (c *RaftCluster) ValidateConfigurationChange(cc raftpb.ConfChange) error { } } - if confChangeContext.Member.IsLearner { // the new member is a learner - numLearners := 0 - for _, m := range members { - if m.IsLearner { - numLearners++ - } - } - if numLearners+1 > maxLearners { - return ErrTooManyLearners + if confChangeContext.Member.RaftAttributes.IsLearner && cc.Type == raftpb.ConfChangeAddLearnerNode { // the new member is a learner + scaleUpLearners := true + if err := ValidateMaxLearnerConfig(c.maxLearners, members, scaleUpLearners); err != nil { + return err } } } case raftpb.ConfChangeRemoveNode: - if members[id] == nil { + if membersMap[id] == nil { return ErrIDNotFound } case raftpb.ConfChangeUpdateNode: - if members[id] == nil { + if membersMap[id] == nil { return ErrIDNotFound } urls := make(map[string]bool) - for _, m := range members { + for _, m := range membersMap { if m.ID == id { continue } @@ -407,6 +407,7 @@ func (c *RaftCluster) AddMember(m *Member, shouldApplyV3 ShouldApplyV3) { zap.String("local-member-id", c.localID.String()), zap.String("added-peer-id", m.ID.String()), zap.Strings("added-peer-peer-urls", m.PeerURLs), + zap.Bool("added-peer-is-learner", m.IsLearner), ) } @@ -434,6 +435,7 @@ func (c *RaftCluster) RemoveMember(id types.ID, shouldApplyV3 ShouldApplyV3) { zap.String("local-member-id", c.localID.String()), zap.String("removed-remote-peer-id", id.String()), zap.Strings("removed-remote-peer-urls", m.PeerURLs), + zap.Bool("removed-remote-peer-is-learner", m.IsLearner), ) } else { c.lg.Warn( @@ -517,6 +519,7 @@ func (c *RaftCluster) UpdateRaftAttributes(id types.ID, raftAttr RaftAttributes, zap.String("local-member-id", c.localID.String()), zap.String("updated-remote-peer-id", id.String()), zap.Strings("updated-remote-peer-urls", raftAttr.PeerURLs), + zap.Bool("updated-remote-peer-is-learner", raftAttr.IsLearner), ) } @@ -831,3 +834,24 @@ func (c *RaftCluster) updateMembershipMetric(peer types.ID, known bool) { } knownPeers.WithLabelValues(c.localID.String(), peer.String()).Set(v) } + +// ValidateMaxLearnerConfig verifies the existing learner members in the cluster membership and an optional N+1 learner +// scale up are not more than maxLearners. +func ValidateMaxLearnerConfig(maxLearners int, members []*Member, scaleUpLearners bool) error { + numLearners := 0 + for _, m := range members { + if m.IsLearner { + numLearners++ + } + } + // Validate config can accommodate scale up. + if scaleUpLearners { + numLearners++ + } + + if numLearners > maxLearners { + return ErrTooManyLearners + } + + return nil +} diff --git a/server/etcdserver/api/membership/cluster_opts.go b/server/etcdserver/api/membership/cluster_opts.go new file mode 100644 index 000000000000..204fbf04d2c5 --- /dev/null +++ b/server/etcdserver/api/membership/cluster_opts.go @@ -0,0 +1,43 @@ +// Copyright 2021 The etcd Authors +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package membership + +const DefaultMaxLearners = 1 + +type ClusterOptions struct { + maxLearners int +} + +// ClusterOption are options which can be applied to the raft cluster. +type ClusterOption func(*ClusterOptions) + +func newClusterOpts(opts ...ClusterOption) *ClusterOptions { + clOpts := &ClusterOptions{} + clOpts.applyOpts(opts) + return clOpts +} + +func (co *ClusterOptions) applyOpts(opts []ClusterOption) { + for _, opt := range opts { + opt(co) + } +} + +// WithMaxLearners sets the maximum number of learners that can exist in the cluster membership. +func WithMaxLearners(max int) ClusterOption { + return func(co *ClusterOptions) { + co.maxLearners = max + } +} diff --git a/server/etcdserver/api/membership/cluster_test.go b/server/etcdserver/api/membership/cluster_test.go index e96e4cca34ba..c8dc18c8a3f6 100644 --- a/server/etcdserver/api/membership/cluster_test.go +++ b/server/etcdserver/api/membership/cluster_test.go @@ -278,10 +278,14 @@ func TestClusterValidateAndAssignIDs(t *testing.T) { } func TestClusterValidateConfigurationChange(t *testing.T) { - cl := NewCluster(zaptest.NewLogger(t)) + cl := NewCluster(zaptest.NewLogger(t), WithMaxLearners(1)) cl.SetStore(v2store.New()) for i := 1; i <= 4; i++ { - attr := RaftAttributes{PeerURLs: []string{fmt.Sprintf("http://127.0.0.1:%d", i)}} + var isLearner bool + if i == 1 { + isLearner = true + } + attr := RaftAttributes{PeerURLs: []string{fmt.Sprintf("http://127.0.0.1:%d", i)}, IsLearner: isLearner} cl.AddMember(&Member{ID: types.ID(i), RaftAttributes: attr}, true) } cl.RemoveMember(4, true) @@ -326,6 +330,17 @@ func TestClusterValidateConfigurationChange(t *testing.T) { t.Fatal(err) } + attr = RaftAttributes{PeerURLs: []string{fmt.Sprintf("http://127.0.0.1:%d", 7)}, IsLearner: true} + ctx7, err := json.Marshal(&ConfigChangeContext{Member: Member{ID: types.ID(7), RaftAttributes: attr}}) + if err != nil { + t.Fatal(err) + } + + attr = RaftAttributes{PeerURLs: []string{fmt.Sprintf("http://127.0.0.1:%d", 1)}, IsLearner: true} + ctx8, err := json.Marshal(&ConfigChangeContext{Member: Member{ID: types.ID(1), RaftAttributes: attr}, IsPromote: true}) + if err != nil { + t.Fatal(err) + } tests := []struct { cc raftpb.ConfChange werr error @@ -423,6 +438,22 @@ func TestClusterValidateConfigurationChange(t *testing.T) { }, ErrIDNotFound, }, + { + raftpb.ConfChange{ + Type: raftpb.ConfChangeAddLearnerNode, + NodeID: 7, + Context: ctx7, + }, + ErrTooManyLearners, + }, + { + raftpb.ConfChange{ + Type: raftpb.ConfChangeAddNode, + NodeID: 1, + Context: ctx8, + }, + nil, + }, } for i, tt := range tests { err := cl.ValidateConfigurationChange(tt.cc) diff --git a/server/etcdserver/api/membership/membership_test.go b/server/etcdserver/api/membership/membership_test.go index 221831d7b0b4..62c74fc28d76 100644 --- a/server/etcdserver/api/membership/membership_test.go +++ b/server/etcdserver/api/membership/membership_test.go @@ -15,12 +15,14 @@ func TestAddRemoveMember(t *testing.T) { c := newTestCluster(t, nil) be := &backendMock{} c.SetBackend(be) - c.AddMember(newTestMember(17, nil, "node17", nil), true) + c.AddMember(newTestMemberAsLearner(17, nil, "node17", nil), true) c.RemoveMember(17, true) c.AddMember(newTestMember(18, nil, "node18", nil), true) + c.RemoveMember(18, true) // Skipping removal of already removed member c.RemoveMember(17, true) + c.RemoveMember(18, true) if false { // TODO: Enable this code when Recover is reading membership from the backend. diff --git a/server/etcdserver/bootstrap.go b/server/etcdserver/bootstrap.go index 3435289258ae..d1b8bbe643ed 100644 --- a/server/etcdserver/bootstrap.go +++ b/server/etcdserver/bootstrap.go @@ -236,6 +236,7 @@ func bootstrapBackend(cfg config.ServerConfig, haveWAL bool, st v2store.Store, s return nil, err } } + return &bootstrappedBackend{ beHooks: beHooks, be: be, @@ -285,7 +286,7 @@ func bootstrapExistingClusterNoWAL(cfg config.ServerConfig, prt http.RoundTrippe if err := cfg.VerifyJoinExisting(); err != nil { return nil, err } - cl, err := membership.NewClusterFromURLsMap(cfg.Logger, cfg.InitialClusterToken, cfg.InitialPeerURLsMap) + cl, err := membership.NewClusterFromURLsMap(cfg.Logger, cfg.InitialClusterToken, cfg.InitialPeerURLsMap, membership.WithMaxLearners(cfg.ExperimentalMaxLearners)) if err != nil { return nil, err } @@ -299,7 +300,10 @@ func bootstrapExistingClusterNoWAL(cfg config.ServerConfig, prt http.RoundTrippe if !isCompatibleWithCluster(cfg.Logger, cl, cl.MemberByName(cfg.Name).ID, prt) { return nil, fmt.Errorf("incompatible with current running cluster") } - + scaleUpLearners := false + if err := membership.ValidateMaxLearnerConfig(cfg.ExperimentalMaxLearners, existingCluster.Members(), scaleUpLearners); err != nil { + return nil, err + } remotes := existingCluster.Members() cl.SetID(types.ID(0), existingCluster.ID()) member := cl.MemberByName(cfg.Name) @@ -314,7 +318,7 @@ func bootstrapNewClusterNoWAL(cfg config.ServerConfig, prt http.RoundTripper) (* if err := cfg.VerifyBootstrap(); err != nil { return nil, err } - cl, err := membership.NewClusterFromURLsMap(cfg.Logger, cfg.InitialClusterToken, cfg.InitialPeerURLsMap) + cl, err := membership.NewClusterFromURLsMap(cfg.Logger, cfg.InitialClusterToken, cfg.InitialPeerURLsMap, membership.WithMaxLearners(cfg.ExperimentalMaxLearners)) if err != nil { return nil, err } @@ -336,7 +340,7 @@ func bootstrapNewClusterNoWAL(cfg config.ServerConfig, prt http.RoundTripper) (* if config.CheckDuplicateURL(urlsmap) { return nil, fmt.Errorf("discovery cluster %s has duplicate url", urlsmap) } - if cl, err = membership.NewClusterFromURLsMap(cfg.Logger, cfg.InitialClusterToken, urlsmap); err != nil { + if cl, err = membership.NewClusterFromURLsMap(cfg.Logger, cfg.InitialClusterToken, urlsmap, membership.WithMaxLearners(cfg.ExperimentalMaxLearners)); err != nil { return nil, err } } @@ -358,7 +362,13 @@ func bootstrapClusterWithWAL(cfg config.ServerConfig, meta *snapshotMetadata) (* zap.String("wal-dir", cfg.WALDir()), ) } - cl := membership.NewCluster(cfg.Logger) + cl := membership.NewCluster(cfg.Logger, membership.WithMaxLearners(cfg.ExperimentalMaxLearners)) + + scaleUpLearners := false + if err := membership.ValidateMaxLearnerConfig(cfg.ExperimentalMaxLearners, cl.Members(), scaleUpLearners); err != nil { + return nil, err + } + cl.SetID(meta.nodeID, meta.clusterID) return &bootstrapedCluster{ cl: cl, @@ -440,7 +450,8 @@ func (c *bootstrapedCluster) Finalize(cfg config.ServerConfig, s *bootstrappedSt return fmt.Errorf("database file (%v) of the backend is missing", bepath) } } - return nil + scaleUpLearners := false + return membership.ValidateMaxLearnerConfig(cfg.ExperimentalMaxLearners, c.cl.Members(), scaleUpLearners) } func (c *bootstrapedCluster) databaseFileMissing(s *bootstrappedStorage) bool { diff --git a/server/etcdserver/bootstrap_test.go b/server/etcdserver/bootstrap_test.go new file mode 100644 index 000000000000..8d6effd450f9 --- /dev/null +++ b/server/etcdserver/bootstrap_test.go @@ -0,0 +1,140 @@ +// Copyright 2021 The etcd Authors +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +// Package version implements etcd version parsing and contains latest version +// information. + +package etcdserver + +import ( + "encoding/json" + "io" + "net/http" + "strings" + "testing" + + "go.etcd.io/etcd/api/v3/etcdserverpb" + "go.etcd.io/etcd/api/v3/version" + "go.etcd.io/etcd/client/pkg/v3/types" + "go.etcd.io/etcd/server/v3/config" + "go.etcd.io/etcd/server/v3/etcdserver/api/membership" + "go.uber.org/zap" +) + +func TestBootstrapExistingClusterNoWALMaxLearner(t *testing.T) { + tests := []struct { + name string + members []etcdserverpb.Member + maxLearner int + hasError bool + expectedError error + }{ + { + name: "bootstrap success: maxLearner gt learner count", + members: []etcdserverpb.Member{ + {ID: 4512484362714696085, PeerURLs: []string{"http://localhost:2380"}}, + {ID: 5321713336100798248, PeerURLs: []string{"http://localhost:2381"}}, + {ID: 5670219998796287055, PeerURLs: []string{"http://localhost:2382"}}, + }, + maxLearner: 1, + hasError: false, + expectedError: nil, + }, + { + name: "bootstrap success: maxLearner eq learner count", + members: []etcdserverpb.Member{ + {ID: 4512484362714696085, PeerURLs: []string{"http://localhost:2380"}, IsLearner: true}, + {ID: 5321713336100798248, PeerURLs: []string{"http://localhost:2381"}}, + {ID: 5670219998796287055, PeerURLs: []string{"http://localhost:2382"}, IsLearner: true}, + }, + maxLearner: 2, + hasError: false, + expectedError: nil, + }, + { + name: "bootstrap fail: maxLearner lt learner count", + members: []etcdserverpb.Member{ + {ID: 4512484362714696085, PeerURLs: []string{"http://localhost:2380"}}, + {ID: 5321713336100798248, PeerURLs: []string{"http://localhost:2381"}, IsLearner: true}, + {ID: 5670219998796287055, PeerURLs: []string{"http://localhost:2382"}, IsLearner: true}, + }, + maxLearner: 1, + hasError: true, + expectedError: membership.ErrTooManyLearners, + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + cluster, err := types.NewURLsMap("node0=http://localhost:2380,node1=http://localhost:2381,node2=http://localhost:2382") + if err != nil { + t.Fatalf("unexpected error: %v", err) + } + cfg := config.ServerConfig{ + Name: "node0", + InitialPeerURLsMap: cluster, + Logger: zap.NewExample(), + ExperimentalMaxLearners: tt.maxLearner, + } + _, err = bootstrapExistingClusterNoWAL(cfg, mockBootstrapRoundTrip(tt.members)) + hasError := err != nil + if hasError != tt.hasError { + t.Errorf("expected error: %v got: %v", tt.hasError, err) + } + if hasError && !strings.Contains(err.Error(), tt.expectedError.Error()) { + t.Fatalf("expected error to contain: %q, got: %q", tt.expectedError.Error(), err.Error()) + } + }) + } +} + +type roundTripFunc func(r *http.Request) (*http.Response, error) + +func (s roundTripFunc) RoundTrip(r *http.Request) (*http.Response, error) { + return s(r) +} + +func mockBootstrapRoundTrip(members []etcdserverpb.Member) roundTripFunc { + return func(r *http.Request) (*http.Response, error) { + switch { + case strings.Contains(r.URL.String(), "/members"): + return &http.Response{ + StatusCode: http.StatusOK, + Body: io.NopCloser(strings.NewReader(mockMembersJSON(members))), + Header: http.Header{"X-Etcd-Cluster-Id": []string{"f4588138892a16b0"}}, + }, nil + case strings.Contains(r.URL.String(), "/version"): + return &http.Response{ + StatusCode: http.StatusOK, + Body: io.NopCloser(strings.NewReader(mockVersionJSON())), + }, nil + case strings.Contains(r.URL.String(), DowngradeEnabledPath): + return &http.Response{ + StatusCode: http.StatusOK, + Body: io.NopCloser(strings.NewReader(`true`)), + }, nil + } + return nil, nil + } +} + +func mockVersionJSON() string { + v := version.Versions{Server: "3.7.0", Cluster: "3.7.0"} + version, _ := json.Marshal(v) + return string(version) +} + +func mockMembersJSON(m []etcdserverpb.Member) string { + members, _ := json.Marshal(m) + return string(members) +} diff --git a/tests/framework/integration/cluster.go b/tests/framework/integration/cluster.go index 6087de09ee45..631e00689bcb 100644 --- a/tests/framework/integration/cluster.go +++ b/tests/framework/integration/cluster.go @@ -45,6 +45,7 @@ import ( "go.etcd.io/etcd/server/v3/embed" "go.etcd.io/etcd/server/v3/etcdserver" "go.etcd.io/etcd/server/v3/etcdserver/api/etcdhttp" + "go.etcd.io/etcd/server/v3/etcdserver/api/membership" "go.etcd.io/etcd/server/v3/etcdserver/api/rafthttp" "go.etcd.io/etcd/server/v3/etcdserver/api/v2http" "go.etcd.io/etcd/server/v3/etcdserver/api/v3client" @@ -169,6 +170,7 @@ type ClusterConfig struct { LeaseCheckpointInterval time.Duration WatchProgressNotifyInterval time.Duration + ExperimentalMaxLearners int } type Cluster struct { @@ -330,6 +332,7 @@ func (c *Cluster) mustNewMember(t testutil.TB, memberNumber int64) *Member { EnableLeaseCheckpoint: c.Cfg.EnableLeaseCheckpoint, LeaseCheckpointInterval: c.Cfg.LeaseCheckpointInterval, WatchProgressNotifyInterval: c.Cfg.WatchProgressNotifyInterval, + ExperimentalMaxLearners: c.Cfg.ExperimentalMaxLearners, }) m.DiscoveryURL = c.Cfg.DiscoveryURL if c.Cfg.UseGRPC { @@ -632,6 +635,7 @@ type MemberConfig struct { EnableLeaseCheckpoint bool LeaseCheckpointInterval time.Duration WatchProgressNotifyInterval time.Duration + ExperimentalMaxLearners int } // MustNewMember return an inited member with the given name. If peerTLS is @@ -735,7 +739,10 @@ func MustNewMember(t testutil.TB, mcfg MemberConfig) *Member { m.InitialCorruptCheck = true m.WarningApplyDuration = embed.DefaultWarningApplyDuration m.WarningUnaryRequestDuration = embed.DefaultWarningUnaryRequestDuration - + m.ExperimentalMaxLearners = membership.DefaultMaxLearners + if mcfg.ExperimentalMaxLearners != 0 { + m.ExperimentalMaxLearners = mcfg.ExperimentalMaxLearners + } m.V2Deprecation = config.V2_DEPR_DEFAULT m.GrpcServerRecorder = &grpc_testing.GrpcRecorder{} m.Logger = memberLogger(t, mcfg.Name) diff --git a/tests/integration/clientv3/cluster_test.go b/tests/integration/clientv3/cluster_test.go index b9a63c55c906..edf47f29b4f2 100644 --- a/tests/integration/clientv3/cluster_test.go +++ b/tests/integration/clientv3/cluster_test.go @@ -16,6 +16,7 @@ package clientv3test import ( "context" + "fmt" "math/rand" "reflect" "strings" @@ -376,18 +377,28 @@ func TestMemberPromoteMemberNotExist(t *testing.T) { } } -// TestMaxLearnerInCluster verifies that the maximum number of learners allowed in a cluster is 1 +// TestMaxLearnerInCluster verifies that the maximum number of learners allowed in a cluster func TestMaxLearnerInCluster(t *testing.T) { integration2.BeforeTest(t) - // 1. start with a cluster with 3 voting member and 0 learner member - clus := integration2.NewClusterV3(t, &integration2.ClusterConfig{Size: 3}) + // 1. start with a cluster with 3 voting member and max learner 2 + clus := integration2.NewClusterV3(t, &integration2.ClusterConfig{Size: 3, ExperimentalMaxLearners: 2}) defer clus.Terminate(t) - // 2. adding a learner member should succeed - resp1, err := clus.Client(0).MemberAddAsLearner(context.Background(), []string{"http://127.0.0.1:1234"}) + // 2. adding 2 learner members should succeed + for i := 0; i < 2; i++ { + _, err := clus.Client(0).MemberAddAsLearner(context.Background(), []string{fmt.Sprintf("http://127.0.0.1:123%d", i)}) + if err != nil { + t.Fatalf("failed to add learner member %v", err) + } + } + + // ensure client endpoint is voting member + leaderIdx := clus.WaitLeader(t) + capi := clus.Client(leaderIdx) + resp1, err := capi.MemberList(context.Background()) if err != nil { - t.Fatalf("failed to add learner member %v", err) + t.Fatalf("failed to get member list") } numberOfLearners := 0 for _, m := range resp1.Members { @@ -395,12 +406,12 @@ func TestMaxLearnerInCluster(t *testing.T) { numberOfLearners++ } } - if numberOfLearners != 1 { - t.Fatalf("Added 1 learner node to cluster, got %d", numberOfLearners) + if numberOfLearners != 2 { + t.Fatalf("added 2 learner node to cluster, got %d", numberOfLearners) } - // 3. cluster has 3 voting member and 1 learner, adding another learner should fail - _, err = clus.Client(0).MemberAddAsLearner(context.Background(), []string{"http://127.0.0.1:2345"}) + // 3. cluster has 3 voting member and 2 learner, adding another learner should fail + _, err = clus.Client(0).MemberAddAsLearner(context.Background(), []string{"http://127.0.0.1:2342"}) if err == nil { t.Fatalf("expect member add to fail, got no error") } @@ -410,7 +421,7 @@ func TestMaxLearnerInCluster(t *testing.T) { } // 4. cluster has 3 voting member and 1 learner, adding a voting member should succeed - _, err = clus.Client(0).MemberAdd(context.Background(), []string{"http://127.0.0.1:3456"}) + _, err = clus.Client(0).MemberAdd(context.Background(), []string{"http://127.0.0.1:3453"}) if err != nil { t.Errorf("failed to add member %v", err) } From b5e4c2d3c483d9c3d03a0f97ae7b07607f38a5cc Mon Sep 17 00:00:00 2001 From: Chao Chen Date: Tue, 9 Nov 2021 11:16:40 -0800 Subject: [PATCH 005/258] client/v2: remove unsafe json-iterator/reflect2 --- bill-of-materials.json | 36 ++++++--------------- client/v2/go.mod | 4 +-- client/v2/go.sum | 10 ++---- client/v2/json.go | 73 ------------------------------------------ client/v2/keys.go | 5 ++- etcdctl/go.mod | 4 +-- etcdctl/go.sum | 5 ++- etcdutl/go.mod | 4 +-- etcdutl/go.sum | 5 ++- go.mod | 4 +-- go.sum | 5 ++- server/go.mod | 4 +-- server/go.sum | 5 ++- tests/go.mod | 4 +-- tests/go.sum | 5 ++- 15 files changed, 29 insertions(+), 144 deletions(-) delete mode 100644 client/v2/json.go diff --git a/bill-of-materials.json b/bill-of-materials.json index af9b7e008d4b..0a66e6c54d9f 100644 --- a/bill-of-materials.json +++ b/bill-of-materials.json @@ -233,15 +233,6 @@ } ] }, - { - "project": "github.com/json-iterator/go", - "licenses": [ - { - "type": "MIT License", - "confidence": 1 - } - ] - }, { "project": "github.com/mattn/go-runewidth", "licenses": [ @@ -260,24 +251,6 @@ } ] }, - { - "project": "github.com/modern-go/concurrent", - "licenses": [ - { - "type": "Apache License 2.0", - "confidence": 1 - } - ] - }, - { - "project": "github.com/modern-go/reflect2", - "licenses": [ - { - "type": "Apache License 2.0", - "confidence": 1 - } - ] - }, { "project": "github.com/olekukonko/tablewriter", "licenses": [ @@ -741,6 +714,15 @@ } ] }, + { + "project": "sigs.k8s.io/json", + "licenses": [ + { + "type": "Apache License 2.0", + "confidence": 0.9617021276595744 + } + ] + }, { "project": "sigs.k8s.io/yaml", "licenses": [ diff --git a/client/v2/go.mod b/client/v2/go.mod index d7f585ec9455..7f6d6ab3b046 100644 --- a/client/v2/go.mod +++ b/client/v2/go.mod @@ -3,16 +3,14 @@ module go.etcd.io/etcd/client/v2 go 1.17 require ( - github.com/json-iterator/go v1.1.11 - github.com/modern-go/reflect2 v1.0.1 go.etcd.io/etcd/api/v3 v3.5.0 go.etcd.io/etcd/client/pkg/v3 v3.5.0 + sigs.k8s.io/json v0.0.0-20211020170558-c049b76a60c6 ) require ( github.com/coreos/go-semver v0.3.0 // indirect github.com/davecgh/go-spew v1.1.1 // indirect - github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421 // indirect github.com/pmezard/go-difflib v1.0.0 // indirect github.com/stretchr/testify v1.7.0 // indirect gopkg.in/yaml.v2 v2.4.0 // indirect diff --git a/client/v2/go.sum b/client/v2/go.sum index ab507446d659..920e7ee807da 100644 --- a/client/v2/go.sum +++ b/client/v2/go.sum @@ -45,18 +45,10 @@ github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMyw github.com/google/go-cmp v0.4.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.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= -github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= github.com/google/uuid v1.1.2/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/grpc-ecosystem/grpc-gateway v1.16.0/go.mod h1:BDjrQk3hbvj6Nolgz8mAMFbcEtjT1g+wF4CSlocrBnw= -github.com/json-iterator/go v1.1.11 h1:uVUAXhF2To8cbw/3xN3pxj6kk7TYKs98NIrTqPlMWAQ= -github.com/json-iterator/go v1.1.11/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4= github.com/kisielk/errcheck v1.5.0/go.mod h1:pFxgyoBC7bSaBwPgfKdkLd5X25qrDl4LWUI2bnpBCr8= github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck= -github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421 h1:ZqeYNhU3OHLH3mGKHDcjJRFFRrJa6eAM5H+CtDdOsPc= -github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= -github.com/modern-go/reflect2 v0.0.0-20180701023420-4b7aa43c6742/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0= -github.com/modern-go/reflect2 v1.0.1 h1:9f412s+6RmYXLWZSEzVVgPGK7C2PphHj5RJrvfx9AWI= -github.com/modern-go/reflect2 v1.0.1/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0= github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= @@ -171,3 +163,5 @@ gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b h1:h8qDotaEPuJATrMmW04NCwg7v gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= honnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= +sigs.k8s.io/json v0.0.0-20211020170558-c049b76a60c6 h1:fD1pz4yfdADVNfFmcP2aBEtudwUQ1AlLnRBALr33v3s= +sigs.k8s.io/json v0.0.0-20211020170558-c049b76a60c6/go.mod h1:p4QtZmO4uMYipTQNzagwnNoseA6OxSUutVw05NhYDRs= diff --git a/client/v2/json.go b/client/v2/json.go deleted file mode 100644 index d5be690a1716..000000000000 --- a/client/v2/json.go +++ /dev/null @@ -1,73 +0,0 @@ -// Copyright 2019 The etcd Authors -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -package client - -import ( - "strconv" - "unsafe" - - "github.com/json-iterator/go" - "github.com/modern-go/reflect2" -) - -type customNumberExtension struct { - jsoniter.DummyExtension -} - -func (cne *customNumberExtension) CreateDecoder(typ reflect2.Type) jsoniter.ValDecoder { - if typ.String() == "interface {}" { - return customNumberDecoder{} - } - return nil -} - -type customNumberDecoder struct { -} - -func (customNumberDecoder) Decode(ptr unsafe.Pointer, iter *jsoniter.Iterator) { - switch iter.WhatIsNext() { - case jsoniter.NumberValue: - var number jsoniter.Number - iter.ReadVal(&number) - i64, err := strconv.ParseInt(string(number), 10, 64) - if err == nil { - *(*interface{})(ptr) = i64 - return - } - f64, err := strconv.ParseFloat(string(number), 64) - if err == nil { - *(*interface{})(ptr) = f64 - return - } - iter.ReportError("DecodeNumber", err.Error()) - default: - *(*interface{})(ptr) = iter.Read() - } -} - -// caseSensitiveJsonIterator returns a jsoniterator API that's configured to be -// case-sensitive when unmarshalling, and otherwise compatible with -// the encoding/json standard library. -func caseSensitiveJsonIterator() jsoniter.API { - config := jsoniter.Config{ - EscapeHTML: true, - SortMapKeys: true, - ValidateJsonRawMessage: true, - CaseSensitive: true, - }.Froze() - // Force jsoniter to decode number to interface{} via int64/float64, if possible. - config.RegisterExtension(&customNumberExtension{}) - return config -} diff --git a/client/v2/keys.go b/client/v2/keys.go index e8f166461747..7eb927e56295 100644 --- a/client/v2/keys.go +++ b/client/v2/keys.go @@ -26,6 +26,7 @@ import ( "time" "go.etcd.io/etcd/client/pkg/v3/pathutil" + kjson "sigs.k8s.io/json" ) const ( @@ -653,11 +654,9 @@ func unmarshalHTTPResponse(code int, header http.Header, body []byte) (res *Resp return res, err } -var jsonIterator = caseSensitiveJsonIterator() - func unmarshalSuccessfulKeysResponse(header http.Header, body []byte) (*Response, error) { var res Response - err := jsonIterator.Unmarshal(body, &res) + err := kjson.UnmarshalCaseSensitivePreserveInts(body, &res) if err != nil { return nil, ErrInvalidJSON } diff --git a/etcdctl/go.mod b/etcdctl/go.mod index a7342230bdea..bc17a7d04a18 100644 --- a/etcdctl/go.mod +++ b/etcdctl/go.mod @@ -33,11 +33,8 @@ require ( github.com/google/btree v1.0.1 // indirect github.com/inconshreveable/mousetrap v1.0.0 // indirect github.com/jonboulle/clockwork v0.2.2 // indirect - github.com/json-iterator/go v1.1.11 // indirect github.com/mattn/go-runewidth v0.0.9 // indirect github.com/matttproud/golang_protobuf_extensions v1.0.1 // indirect - github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect - github.com/modern-go/reflect2 v1.0.1 // indirect github.com/prometheus/client_golang v1.11.0 // indirect github.com/prometheus/client_model v0.2.0 // indirect github.com/prometheus/common v0.26.0 // indirect @@ -59,6 +56,7 @@ require ( golang.org/x/text v0.3.6 // indirect google.golang.org/genproto v0.0.0-20210602131652-f16073e35f0c // indirect google.golang.org/protobuf v1.27.1 // indirect + sigs.k8s.io/json v0.0.0-20211020170558-c049b76a60c6 // indirect ) replace ( diff --git a/etcdctl/go.sum b/etcdctl/go.sum index 215943aead32..7f7c073faa8b 100644 --- a/etcdctl/go.sum +++ b/etcdctl/go.sum @@ -181,7 +181,6 @@ github.com/jonboulle/clockwork v0.2.2/go.mod h1:Pkfl5aHPm1nk2H9h0bjmnJD/BcgbGXUB 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.10/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4= -github.com/json-iterator/go v1.1.11 h1:uVUAXhF2To8cbw/3xN3pxj6kk7TYKs98NIrTqPlMWAQ= github.com/json-iterator/go v1.1.11/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4= github.com/jstemmer/go-junit-report v0.0.0-20190106144839-af01ea7f8024/go.mod h1:6v2b51hI/fHJwM22ozAgKL4VKDeJcHhJFhtBdhmNjmU= github.com/jtolds/gls v4.20.0+incompatible/go.mod h1:QJZ7F/aHp+rZTRtaJ1ow/lLfFfVYBRgL+9YlvaHOwJU= @@ -217,10 +216,8 @@ github.com/mitchellh/iochan v1.0.0/go.mod h1:JwYml1nuB7xOzsp52dPpHFffvOCDupsG0Qu github.com/mitchellh/mapstructure v0.0.0-20160808181253-ca63d7c062ee/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y= github.com/mitchellh/mapstructure v1.1.2/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y= github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= -github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd h1:TRLaZ9cD/w8PVh93nsPXa1VrQ6jlwL5oN8l14QlcNfg= github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= github.com/modern-go/reflect2 v0.0.0-20180701023420-4b7aa43c6742/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0= -github.com/modern-go/reflect2 v1.0.1 h1:9f412s+6RmYXLWZSEzVVgPGK7C2PphHj5RJrvfx9AWI= github.com/modern-go/reflect2 v1.0.1/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0= github.com/mwitkow/go-conntrack v0.0.0-20161129095857-cc309e4a2223/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U= github.com/mwitkow/go-conntrack v0.0.0-20190716064945-2f068394615f/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U= @@ -553,4 +550,6 @@ honnef.co/go/tools v0.0.0-20190418001031-e561f6794a2a/go.mod h1:rf3lG4BRIbNafJWh honnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= honnef.co/go/tools v0.0.1-2019.2.3/go.mod h1:a3bituU0lyd329TUQxRnasdCoJDkEUEAqEt0JzvZhAg= rsc.io/binaryregexp v0.2.0/go.mod h1:qTv7/COck+e2FymRvadv62gMdZztPaShugOCi3I+8D8= +sigs.k8s.io/json v0.0.0-20211020170558-c049b76a60c6 h1:fD1pz4yfdADVNfFmcP2aBEtudwUQ1AlLnRBALr33v3s= +sigs.k8s.io/json v0.0.0-20211020170558-c049b76a60c6/go.mod h1:p4QtZmO4uMYipTQNzagwnNoseA6OxSUutVw05NhYDRs= sigs.k8s.io/yaml v1.2.0/go.mod h1:yfXDCHCao9+ENCvLSE62v9VSji2MKu5jeNfTrofGhJc= diff --git a/etcdutl/go.mod b/etcdutl/go.mod index 1f922de5d9ab..6ea6bc7710de 100644 --- a/etcdutl/go.mod +++ b/etcdutl/go.mod @@ -45,11 +45,8 @@ require ( github.com/google/btree v1.0.1 // indirect github.com/inconshreveable/mousetrap v1.0.0 // indirect github.com/jonboulle/clockwork v0.2.2 // indirect - github.com/json-iterator/go v1.1.11 // indirect github.com/mattn/go-runewidth v0.0.9 // indirect github.com/matttproud/golang_protobuf_extensions v1.0.1 // indirect - github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect - github.com/modern-go/reflect2 v1.0.1 // indirect github.com/prometheus/client_golang v1.11.0 // indirect github.com/prometheus/client_model v0.2.0 // indirect github.com/prometheus/common v0.26.0 // indirect @@ -70,4 +67,5 @@ require ( google.golang.org/genproto v0.0.0-20210602131652-f16073e35f0c // indirect google.golang.org/grpc v1.41.0 // indirect google.golang.org/protobuf v1.27.1 // indirect + sigs.k8s.io/json v0.0.0-20211020170558-c049b76a60c6 // indirect ) diff --git a/etcdutl/go.sum b/etcdutl/go.sum index 588615f794c1..40502ee95672 100644 --- a/etcdutl/go.sum +++ b/etcdutl/go.sum @@ -177,7 +177,6 @@ github.com/jonboulle/clockwork v0.2.2/go.mod h1:Pkfl5aHPm1nk2H9h0bjmnJD/BcgbGXUB 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.10/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4= -github.com/json-iterator/go v1.1.11 h1:uVUAXhF2To8cbw/3xN3pxj6kk7TYKs98NIrTqPlMWAQ= github.com/json-iterator/go v1.1.11/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4= github.com/jstemmer/go-junit-report v0.0.0-20190106144839-af01ea7f8024/go.mod h1:6v2b51hI/fHJwM22ozAgKL4VKDeJcHhJFhtBdhmNjmU= github.com/jtolds/gls v4.20.0+incompatible/go.mod h1:QJZ7F/aHp+rZTRtaJ1ow/lLfFfVYBRgL+9YlvaHOwJU= @@ -211,10 +210,8 @@ github.com/mitchellh/iochan v1.0.0/go.mod h1:JwYml1nuB7xOzsp52dPpHFffvOCDupsG0Qu github.com/mitchellh/mapstructure v0.0.0-20160808181253-ca63d7c062ee/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y= github.com/mitchellh/mapstructure v1.1.2/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y= github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= -github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd h1:TRLaZ9cD/w8PVh93nsPXa1VrQ6jlwL5oN8l14QlcNfg= github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= github.com/modern-go/reflect2 v0.0.0-20180701023420-4b7aa43c6742/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0= -github.com/modern-go/reflect2 v1.0.1 h1:9f412s+6RmYXLWZSEzVVgPGK7C2PphHj5RJrvfx9AWI= github.com/modern-go/reflect2 v1.0.1/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0= github.com/mwitkow/go-conntrack v0.0.0-20161129095857-cc309e4a2223/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U= github.com/mwitkow/go-conntrack v0.0.0-20190716064945-2f068394615f/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U= @@ -541,4 +538,6 @@ honnef.co/go/tools v0.0.0-20190418001031-e561f6794a2a/go.mod h1:rf3lG4BRIbNafJWh honnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= honnef.co/go/tools v0.0.1-2019.2.3/go.mod h1:a3bituU0lyd329TUQxRnasdCoJDkEUEAqEt0JzvZhAg= rsc.io/binaryregexp v0.2.0/go.mod h1:qTv7/COck+e2FymRvadv62gMdZztPaShugOCi3I+8D8= +sigs.k8s.io/json v0.0.0-20211020170558-c049b76a60c6 h1:fD1pz4yfdADVNfFmcP2aBEtudwUQ1AlLnRBALr33v3s= +sigs.k8s.io/json v0.0.0-20211020170558-c049b76a60c6/go.mod h1:p4QtZmO4uMYipTQNzagwnNoseA6OxSUutVw05NhYDRs= sigs.k8s.io/yaml v1.2.0/go.mod h1:yfXDCHCao9+ENCvLSE62v9VSji2MKu5jeNfTrofGhJc= diff --git a/go.mod b/go.mod index dbdef2f5a058..0656d079f29b 100644 --- a/go.mod +++ b/go.mod @@ -54,11 +54,8 @@ require ( github.com/grpc-ecosystem/grpc-gateway v1.16.0 // indirect github.com/inconshreveable/mousetrap v1.0.0 // indirect github.com/jonboulle/clockwork v0.2.2 // indirect - github.com/json-iterator/go v1.1.11 // indirect github.com/mattn/go-runewidth v0.0.9 // indirect github.com/matttproud/golang_protobuf_extensions v1.0.1 // indirect - github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect - github.com/modern-go/reflect2 v1.0.1 // indirect github.com/olekukonko/tablewriter v0.0.5 // indirect github.com/pmezard/go-difflib v1.0.0 // indirect github.com/prometheus/client_golang v1.11.0 // indirect @@ -89,5 +86,6 @@ require ( gopkg.in/natefinch/lumberjack.v2 v2.0.0 // indirect gopkg.in/yaml.v2 v2.4.0 // indirect gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b // indirect + sigs.k8s.io/json v0.0.0-20211020170558-c049b76a60c6 // indirect sigs.k8s.io/yaml v1.2.0 // indirect ) diff --git a/go.sum b/go.sum index 78811a2aba06..ae3b058bda29 100644 --- a/go.sum +++ b/go.sum @@ -186,7 +186,6 @@ github.com/jonboulle/clockwork v0.2.2/go.mod h1:Pkfl5aHPm1nk2H9h0bjmnJD/BcgbGXUB 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.10/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4= -github.com/json-iterator/go v1.1.11 h1:uVUAXhF2To8cbw/3xN3pxj6kk7TYKs98NIrTqPlMWAQ= github.com/json-iterator/go v1.1.11/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4= github.com/jstemmer/go-junit-report v0.0.0-20190106144839-af01ea7f8024/go.mod h1:6v2b51hI/fHJwM22ozAgKL4VKDeJcHhJFhtBdhmNjmU= github.com/jtolds/gls v4.20.0+incompatible/go.mod h1:QJZ7F/aHp+rZTRtaJ1ow/lLfFfVYBRgL+9YlvaHOwJU= @@ -224,10 +223,8 @@ github.com/mitchellh/iochan v1.0.0/go.mod h1:JwYml1nuB7xOzsp52dPpHFffvOCDupsG0Qu github.com/mitchellh/mapstructure v0.0.0-20160808181253-ca63d7c062ee/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y= github.com/mitchellh/mapstructure v1.1.2/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y= github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= -github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd h1:TRLaZ9cD/w8PVh93nsPXa1VrQ6jlwL5oN8l14QlcNfg= github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= github.com/modern-go/reflect2 v0.0.0-20180701023420-4b7aa43c6742/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0= -github.com/modern-go/reflect2 v1.0.1 h1:9f412s+6RmYXLWZSEzVVgPGK7C2PphHj5RJrvfx9AWI= github.com/modern-go/reflect2 v1.0.1/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0= github.com/mwitkow/go-conntrack v0.0.0-20161129095857-cc309e4a2223/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U= github.com/mwitkow/go-conntrack v0.0.0-20190716064945-2f068394615f/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U= @@ -567,5 +564,7 @@ honnef.co/go/tools v0.0.0-20190418001031-e561f6794a2a/go.mod h1:rf3lG4BRIbNafJWh honnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= honnef.co/go/tools v0.0.1-2019.2.3/go.mod h1:a3bituU0lyd329TUQxRnasdCoJDkEUEAqEt0JzvZhAg= rsc.io/binaryregexp v0.2.0/go.mod h1:qTv7/COck+e2FymRvadv62gMdZztPaShugOCi3I+8D8= +sigs.k8s.io/json v0.0.0-20211020170558-c049b76a60c6 h1:fD1pz4yfdADVNfFmcP2aBEtudwUQ1AlLnRBALr33v3s= +sigs.k8s.io/json v0.0.0-20211020170558-c049b76a60c6/go.mod h1:p4QtZmO4uMYipTQNzagwnNoseA6OxSUutVw05NhYDRs= sigs.k8s.io/yaml v1.2.0 h1:kr/MCeFWJWTwyaHoR9c8EjH9OumOmoF9YGiZd7lFm/Q= sigs.k8s.io/yaml v1.2.0/go.mod h1:yfXDCHCao9+ENCvLSE62v9VSji2MKu5jeNfTrofGhJc= diff --git a/server/go.mod b/server/go.mod index 77c20eb43087..bcd07353d251 100644 --- a/server/go.mod +++ b/server/go.mod @@ -52,11 +52,8 @@ require ( github.com/davecgh/go-spew v1.1.1 // indirect github.com/gorilla/websocket v1.4.2 // indirect github.com/inconshreveable/mousetrap v1.0.0 // indirect - github.com/json-iterator/go v1.1.11 // indirect github.com/kr/text v0.2.0 // indirect github.com/matttproud/golang_protobuf_extensions v1.0.1 // indirect - github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect - github.com/modern-go/reflect2 v1.0.1 // indirect github.com/pmezard/go-difflib v1.0.0 // indirect github.com/prometheus/common v0.26.0 // indirect github.com/prometheus/procfs v0.6.0 // indirect @@ -70,6 +67,7 @@ require ( golang.org/x/text v0.3.6 // indirect gopkg.in/yaml.v2 v2.4.0 // indirect gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b // indirect + sigs.k8s.io/json v0.0.0-20211020170558-c049b76a60c6 // indirect ) replace ( diff --git a/server/go.sum b/server/go.sum index 3fe56c8db974..b3ddb8f5b931 100644 --- a/server/go.sum +++ b/server/go.sum @@ -183,7 +183,6 @@ github.com/jonboulle/clockwork v0.2.2/go.mod h1:Pkfl5aHPm1nk2H9h0bjmnJD/BcgbGXUB 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.10/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4= -github.com/json-iterator/go v1.1.11 h1:uVUAXhF2To8cbw/3xN3pxj6kk7TYKs98NIrTqPlMWAQ= github.com/json-iterator/go v1.1.11/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4= github.com/jstemmer/go-junit-report v0.0.0-20190106144839-af01ea7f8024/go.mod h1:6v2b51hI/fHJwM22ozAgKL4VKDeJcHhJFhtBdhmNjmU= github.com/jtolds/gls v4.20.0+incompatible/go.mod h1:QJZ7F/aHp+rZTRtaJ1ow/lLfFfVYBRgL+9YlvaHOwJU= @@ -217,10 +216,8 @@ github.com/mitchellh/iochan v1.0.0/go.mod h1:JwYml1nuB7xOzsp52dPpHFffvOCDupsG0Qu github.com/mitchellh/mapstructure v0.0.0-20160808181253-ca63d7c062ee/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y= github.com/mitchellh/mapstructure v1.1.2/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y= github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= -github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd h1:TRLaZ9cD/w8PVh93nsPXa1VrQ6jlwL5oN8l14QlcNfg= github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= github.com/modern-go/reflect2 v0.0.0-20180701023420-4b7aa43c6742/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0= -github.com/modern-go/reflect2 v1.0.1 h1:9f412s+6RmYXLWZSEzVVgPGK7C2PphHj5RJrvfx9AWI= github.com/modern-go/reflect2 v1.0.1/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0= github.com/mwitkow/go-conntrack v0.0.0-20161129095857-cc309e4a2223/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U= github.com/mwitkow/go-conntrack v0.0.0-20190716064945-2f068394615f/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U= @@ -554,5 +551,7 @@ honnef.co/go/tools v0.0.0-20190418001031-e561f6794a2a/go.mod h1:rf3lG4BRIbNafJWh honnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= honnef.co/go/tools v0.0.1-2019.2.3/go.mod h1:a3bituU0lyd329TUQxRnasdCoJDkEUEAqEt0JzvZhAg= rsc.io/binaryregexp v0.2.0/go.mod h1:qTv7/COck+e2FymRvadv62gMdZztPaShugOCi3I+8D8= +sigs.k8s.io/json v0.0.0-20211020170558-c049b76a60c6 h1:fD1pz4yfdADVNfFmcP2aBEtudwUQ1AlLnRBALr33v3s= +sigs.k8s.io/json v0.0.0-20211020170558-c049b76a60c6/go.mod h1:p4QtZmO4uMYipTQNzagwnNoseA6OxSUutVw05NhYDRs= sigs.k8s.io/yaml v1.2.0 h1:kr/MCeFWJWTwyaHoR9c8EjH9OumOmoF9YGiZd7lFm/Q= sigs.k8s.io/yaml v1.2.0/go.mod h1:yfXDCHCao9+ENCvLSE62v9VSji2MKu5jeNfTrofGhJc= diff --git a/tests/go.mod b/tests/go.mod index aa0dcaabb23f..84ce5720ba44 100644 --- a/tests/go.mod +++ b/tests/go.mod @@ -57,10 +57,7 @@ require ( github.com/gorilla/websocket v1.4.2 // indirect github.com/inconshreveable/mousetrap v1.0.0 // indirect github.com/jonboulle/clockwork v0.2.2 // indirect - github.com/json-iterator/go v1.1.11 // indirect github.com/matttproud/golang_protobuf_extensions v1.0.1 // indirect - github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect - github.com/modern-go/reflect2 v1.0.1 // indirect github.com/pmezard/go-difflib v1.0.0 // indirect github.com/prometheus/client_model v0.2.0 // indirect github.com/prometheus/common v0.26.0 // indirect @@ -84,5 +81,6 @@ require ( google.golang.org/protobuf v1.27.1 // indirect gopkg.in/natefinch/lumberjack.v2 v2.0.0 // indirect gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b // indirect + sigs.k8s.io/json v0.0.0-20211020170558-c049b76a60c6 // indirect sigs.k8s.io/yaml v1.2.0 // indirect ) diff --git a/tests/go.sum b/tests/go.sum index 6569c58faa66..10bfd3275536 100644 --- a/tests/go.sum +++ b/tests/go.sum @@ -184,7 +184,6 @@ github.com/jonboulle/clockwork v0.2.2/go.mod h1:Pkfl5aHPm1nk2H9h0bjmnJD/BcgbGXUB 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.10/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4= -github.com/json-iterator/go v1.1.11 h1:uVUAXhF2To8cbw/3xN3pxj6kk7TYKs98NIrTqPlMWAQ= github.com/json-iterator/go v1.1.11/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4= github.com/jstemmer/go-junit-report v0.0.0-20190106144839-af01ea7f8024/go.mod h1:6v2b51hI/fHJwM22ozAgKL4VKDeJcHhJFhtBdhmNjmU= github.com/jtolds/gls v4.20.0+incompatible/go.mod h1:QJZ7F/aHp+rZTRtaJ1ow/lLfFfVYBRgL+9YlvaHOwJU= @@ -219,10 +218,8 @@ github.com/mitchellh/iochan v1.0.0/go.mod h1:JwYml1nuB7xOzsp52dPpHFffvOCDupsG0Qu github.com/mitchellh/mapstructure v0.0.0-20160808181253-ca63d7c062ee/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y= github.com/mitchellh/mapstructure v1.1.2/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y= github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= -github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd h1:TRLaZ9cD/w8PVh93nsPXa1VrQ6jlwL5oN8l14QlcNfg= github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= github.com/modern-go/reflect2 v0.0.0-20180701023420-4b7aa43c6742/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0= -github.com/modern-go/reflect2 v1.0.1 h1:9f412s+6RmYXLWZSEzVVgPGK7C2PphHj5RJrvfx9AWI= github.com/modern-go/reflect2 v1.0.1/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0= github.com/mwitkow/go-conntrack v0.0.0-20161129095857-cc309e4a2223/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U= github.com/mwitkow/go-conntrack v0.0.0-20190716064945-2f068394615f/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U= @@ -558,5 +555,7 @@ honnef.co/go/tools v0.0.0-20190418001031-e561f6794a2a/go.mod h1:rf3lG4BRIbNafJWh honnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= honnef.co/go/tools v0.0.1-2019.2.3/go.mod h1:a3bituU0lyd329TUQxRnasdCoJDkEUEAqEt0JzvZhAg= rsc.io/binaryregexp v0.2.0/go.mod h1:qTv7/COck+e2FymRvadv62gMdZztPaShugOCi3I+8D8= +sigs.k8s.io/json v0.0.0-20211020170558-c049b76a60c6 h1:fD1pz4yfdADVNfFmcP2aBEtudwUQ1AlLnRBALr33v3s= +sigs.k8s.io/json v0.0.0-20211020170558-c049b76a60c6/go.mod h1:p4QtZmO4uMYipTQNzagwnNoseA6OxSUutVw05NhYDRs= sigs.k8s.io/yaml v1.2.0 h1:kr/MCeFWJWTwyaHoR9c8EjH9OumOmoF9YGiZd7lFm/Q= sigs.k8s.io/yaml v1.2.0/go.mod h1:yfXDCHCao9+ENCvLSE62v9VSji2MKu5jeNfTrofGhJc= From f6f27d32d16ca251b285cc36771fa09954589c48 Mon Sep 17 00:00:00 2001 From: Chao Chen Date: Tue, 9 Nov 2021 10:17:11 -0800 Subject: [PATCH 006/258] server/etcdserver/api/etcdhttp: exclude the same alarm type activated by multiple peers --- server/etcdserver/api/etcdhttp/metrics.go | 7 +------ server/etcdserver/api/etcdhttp/metrics_test.go | 6 ++++++ 2 files changed, 7 insertions(+), 6 deletions(-) diff --git a/server/etcdserver/api/etcdhttp/metrics.go b/server/etcdserver/api/etcdhttp/metrics.go index a9f278081d9b..659ab8067080 100644 --- a/server/etcdserver/api/etcdhttp/metrics.go +++ b/server/etcdserver/api/etcdhttp/metrics.go @@ -138,8 +138,7 @@ func checkHealth(lg *zap.Logger, srv etcdserver.ServerV2, excludedAlarms AlarmSe for _, v := range as { alarmName := v.Alarm.String() if _, found := excludedAlarms[alarmName]; found { - lg.Debug("/health excluded alarm", zap.String("alarm", alarmName)) - delete(excludedAlarms, alarmName) + lg.Debug("/health excluded alarm", zap.String("alarm", v.String())) continue } @@ -157,10 +156,6 @@ func checkHealth(lg *zap.Logger, srv etcdserver.ServerV2, excludedAlarms AlarmSe } } - if len(excludedAlarms) > 0 { - lg.Warn("fail exclude alarms from health check", zap.String("exclude alarms", fmt.Sprintf("%+v", excludedAlarms))) - } - if uint64(srv.Leader()) == raft.None { h.Health = "false" h.Reason = "RAFT NO LEADER" diff --git a/server/etcdserver/api/etcdhttp/metrics_test.go b/server/etcdserver/api/etcdhttp/metrics_test.go index fbafddff68d7..859bdf495b30 100644 --- a/server/etcdserver/api/etcdhttp/metrics_test.go +++ b/server/etcdserver/api/etcdhttp/metrics_test.go @@ -77,6 +77,12 @@ func TestHealthHandler(t *testing.T) { http.StatusOK, "true", }, + { + []*pb.AlarmMember{{MemberID: uint64(1), Alarm: pb.AlarmType_NOSPACE}, {MemberID: uint64(2), Alarm: pb.AlarmType_NOSPACE}, {MemberID: uint64(3), Alarm: pb.AlarmType_NOSPACE}}, + "/health?exclude=NOSPACE", + http.StatusOK, + "true", + }, { []*pb.AlarmMember{{MemberID: uint64(0), Alarm: pb.AlarmType_NOSPACE}, {MemberID: uint64(1), Alarm: pb.AlarmType_CORRUPT}}, "/health?exclude=NOSPACE", From 729af2ad2e1c32d284ba27efe60362dbf533ce10 Mon Sep 17 00:00:00 2001 From: Clivern Date: Wed, 10 Nov 2021 20:12:28 +0100 Subject: [PATCH 007/258] fix undefined io --- tools/etcd-dump-metrics/install_darwin.go | 1 + 1 file changed, 1 insertion(+) diff --git a/tools/etcd-dump-metrics/install_darwin.go b/tools/etcd-dump-metrics/install_darwin.go index bfcc19e72289..e4ef95220791 100644 --- a/tools/etcd-dump-metrics/install_darwin.go +++ b/tools/etcd-dump-metrics/install_darwin.go @@ -19,6 +19,7 @@ package main import ( "fmt" + "io" "net/http" "os" "os/exec" From d6161ec3871ddaaa57ce9a5cbf76889316784a00 Mon Sep 17 00:00:00 2001 From: Chao Chen Date: Fri, 12 Nov 2021 14:34:33 -0800 Subject: [PATCH 008/258] Update CHANGELOG --- CHANGELOG-3.4.md | 11 ++++++++++- CHANGELOG-3.5.md | 9 +++++++++ CHANGELOG-3.6.md | 1 + 3 files changed, 20 insertions(+), 1 deletion(-) diff --git a/CHANGELOG-3.4.md b/CHANGELOG-3.4.md index f1a1ba25bd6e..4612d8910626 100644 --- a/CHANGELOG-3.4.md +++ b/CHANGELOG-3.4.md @@ -5,12 +5,21 @@ Previous change logs can be found at [CHANGELOG-3.3](https://github.com/etcd-io/ The minimum recommended etcd versions to run in **production** are 3.2.28+, 3.3.18+, 3.4.2+, and 3.5.1+. -See [code changes](https://github.com/etcd-io/etcd/compare/v3.4.17...v3.4.18) and [v3.4 upgrade guide](https://etcd.io/docs/latest/upgrades/upgrade_3_4/) for any breaking changes. +
+ +## v3.4.19 (TODO) + +See [code changes](https://github.com/etcd-io/etcd/compare/v3.4.18...v3.4.19) and [v3.4 upgrade guide](https://etcd.io/docs/latest/upgrades/upgrade_3_4/) for any breaking changes. + +### etcd server +- Fix [exclude the same alarm type activated by multiple peers](https://github.com/etcd-io/etcd/pull/13475).
## v3.4.18 (2021-10-15) +See [code changes](https://github.com/etcd-io/etcd/compare/v3.4.17...v3.4.18) and [v3.4 upgrade guide](https://etcd.io/docs/latest/upgrades/upgrade_3_4/) for any breaking changes. + ### Metrics, Monitoring See [List of metrics](https://etcd.io/docs/latest/metrics/) for all metrics per release. diff --git a/CHANGELOG-3.5.md b/CHANGELOG-3.5.md index 78015a50160d..3de30512eb5e 100644 --- a/CHANGELOG-3.5.md +++ b/CHANGELOG-3.5.md @@ -6,6 +6,15 @@ Previous change logs can be found at [CHANGELOG-3.4](https://github.com/etcd-io/ The minimum recommended etcd versions to run in **production** are 3.2.28+, 3.3.18+, 3.4.2+, and 3.5.1+. +
+ +## [v3.5.2](https://github.com/etcd-io/etcd/releases/tag/v3.5.2) (TODO) + +See [code changes](https://github.com/etcd-io/etcd/compare/v3.5.1...v3.5.2) and [v3.5 upgrade guide](https://etcd.io/docs/latest/upgrades/upgrade_3_5/) for any breaking changes. + +### etcd server +- Fix [exclude the same alarm type activated by multiple peers](https://github.com/etcd-io/etcd/pull/13476). +
## [v3.5.1](https://github.com/etcd-io/etcd/releases/tag/v3.5.1) (2021-10-15) diff --git a/CHANGELOG-3.6.md b/CHANGELOG-3.6.md index f792d3a132dd..5e07703993bb 100644 --- a/CHANGELOG-3.6.md +++ b/CHANGELOG-3.6.md @@ -33,6 +33,7 @@ See [code changes](https://github.com/etcd-io/etcd/compare/v3.5.0...v3.6.0). - Add [`etcd --log-format`](https://github.com/etcd-io/etcd/pull/13339) flag to support log format. - Fix [non mutating requests pass through quotaKVServer when NOSPACE](https://github.com/etcd-io/etcd/pull/13435) +- Fix [exclude the same alarm type activated by multiple peers](https://github.com/etcd-io/etcd/pull/13467). ### tools/benchmark From 09ff05108be1aaf2c29f345542b87c63cd4be6f8 Mon Sep 17 00:00:00 2001 From: ahrtr Date: Thu, 7 Oct 2021 14:35:54 +0800 Subject: [PATCH 009/258] enhance health check endpoint to support serializable request --- CHANGELOG-3.6.md | 1 + server/etcdserver/api/etcdhttp/metrics.go | 31 +++++++++++++++-------- server/proxy/grpcproxy/health.go | 4 +-- 3 files changed, 24 insertions(+), 12 deletions(-) diff --git a/CHANGELOG-3.6.md b/CHANGELOG-3.6.md index 5e07703993bb..d3267857ff2f 100644 --- a/CHANGELOG-3.6.md +++ b/CHANGELOG-3.6.md @@ -34,6 +34,7 @@ See [code changes](https://github.com/etcd-io/etcd/compare/v3.5.0...v3.6.0). - Add [`etcd --log-format`](https://github.com/etcd-io/etcd/pull/13339) flag to support log format. - Fix [non mutating requests pass through quotaKVServer when NOSPACE](https://github.com/etcd-io/etcd/pull/13435) - Fix [exclude the same alarm type activated by multiple peers](https://github.com/etcd-io/etcd/pull/13467). +- Fix [Provide a better liveness probe for when etcd runs as a Kubernetes pod](https://github.com/etcd-io/etcd/pull/13399) ### tools/benchmark diff --git a/server/etcdserver/api/etcdhttp/metrics.go b/server/etcdserver/api/etcdhttp/metrics.go index 659ab8067080..fedf2a9e33d4 100644 --- a/server/etcdserver/api/etcdhttp/metrics.go +++ b/server/etcdserver/api/etcdhttp/metrics.go @@ -40,14 +40,16 @@ const ( // HandleMetricsHealth registers metrics and health handlers. func HandleMetricsHealth(lg *zap.Logger, mux *http.ServeMux, srv etcdserver.ServerV2) { mux.Handle(PathMetrics, promhttp.Handler()) - mux.Handle(PathHealth, NewHealthHandler(lg, func(excludedAlarms AlarmSet) Health { return checkV2Health(lg, srv, excludedAlarms) })) + mux.Handle(PathHealth, NewHealthHandler(lg, func(excludedAlarms AlarmSet, serializable bool) Health { return checkV2Health(lg, srv, excludedAlarms) })) } // HandleMetricsHealthForV3 registers metrics and health handlers. it checks health by using v3 range request // and its corresponding timeout. func HandleMetricsHealthForV3(lg *zap.Logger, mux *http.ServeMux, srv *etcdserver.EtcdServer) { mux.Handle(PathMetrics, promhttp.Handler()) - mux.Handle(PathHealth, NewHealthHandler(lg, func(excludedAlarms AlarmSet) Health { return checkV3Health(lg, srv, excludedAlarms) })) + mux.Handle(PathHealth, NewHealthHandler(lg, func(excludedAlarms AlarmSet, serializable bool) Health { + return checkV3Health(lg, srv, excludedAlarms, serializable) + })) } // HandlePrometheus registers prometheus handler on '/metrics'. @@ -56,7 +58,7 @@ func HandlePrometheus(mux *http.ServeMux) { } // NewHealthHandler handles '/health' requests. -func NewHealthHandler(lg *zap.Logger, hfunc func(excludedAlarms AlarmSet) Health) http.HandlerFunc { +func NewHealthHandler(lg *zap.Logger, hfunc func(excludedAlarms AlarmSet, Serializable bool) Health) http.HandlerFunc { return func(w http.ResponseWriter, r *http.Request) { if r.Method != http.MethodGet { w.Header().Set("Allow", http.MethodGet) @@ -65,7 +67,12 @@ func NewHealthHandler(lg *zap.Logger, hfunc func(excludedAlarms AlarmSet) Health return } excludedAlarms := getExcludedAlarms(r) - h := hfunc(excludedAlarms) + // Passing the query parameter "serializable=true" ensures that the + // health of the local etcd is checked vs the health of the cluster. + // This is useful for probes attempting to validate the liveness of + // the etcd process vs readiness of the cluster to serve requests. + serializableFlag := getSerializableFlag(r) + h := hfunc(excludedAlarms, serializableFlag) defer func() { if h.Health == "true" { healthSuccess.Inc() @@ -128,9 +135,13 @@ func getExcludedAlarms(r *http.Request) (alarms AlarmSet) { return alarms } +func getSerializableFlag(r *http.Request) bool { + return r.URL.Query().Get("serializable") == "true" +} + // TODO: etcdserver.ErrNoLeader in health API -func checkHealth(lg *zap.Logger, srv etcdserver.ServerV2, excludedAlarms AlarmSet) Health { +func checkHealth(lg *zap.Logger, srv etcdserver.ServerV2, excludedAlarms AlarmSet, serializable bool) Health { h := Health{} h.Health = "true" as := srv.Alarms() @@ -156,7 +167,7 @@ func checkHealth(lg *zap.Logger, srv etcdserver.ServerV2, excludedAlarms AlarmSe } } - if uint64(srv.Leader()) == raft.None { + if !serializable && (uint64(srv.Leader()) == raft.None) { h.Health = "false" h.Reason = "RAFT NO LEADER" lg.Warn("serving /health false; no leader") @@ -166,7 +177,7 @@ func checkHealth(lg *zap.Logger, srv etcdserver.ServerV2, excludedAlarms AlarmSe } func checkV2Health(lg *zap.Logger, srv etcdserver.ServerV2, excludedAlarms AlarmSet) (h Health) { - if h = checkHealth(lg, srv, excludedAlarms); h.Health != "true" { + if h = checkHealth(lg, srv, excludedAlarms, false); h.Health != "true" { return } ctx, cancel := context.WithTimeout(context.Background(), time.Second) @@ -182,12 +193,12 @@ func checkV2Health(lg *zap.Logger, srv etcdserver.ServerV2, excludedAlarms Alarm return } -func checkV3Health(lg *zap.Logger, srv *etcdserver.EtcdServer, excludedAlarms AlarmSet) (h Health) { - if h = checkHealth(lg, srv, excludedAlarms); h.Health != "true" { +func checkV3Health(lg *zap.Logger, srv *etcdserver.EtcdServer, excludedAlarms AlarmSet, serializable bool) (h Health) { + if h = checkHealth(lg, srv, excludedAlarms, serializable); h.Health != "true" { return } ctx, cancel := context.WithTimeout(context.Background(), srv.Cfg.ReqTimeout()) - _, err := srv.Range(ctx, &etcdserverpb.RangeRequest{KeysOnly: true, Limit: 1}) + _, err := srv.Range(ctx, &etcdserverpb.RangeRequest{KeysOnly: true, Limit: 1, Serializable: serializable}) cancel() if err != nil && err != auth.ErrUserEmpty && err != auth.ErrPermissionDenied { h.Health = "false" diff --git a/server/proxy/grpcproxy/health.go b/server/proxy/grpcproxy/health.go index 1d6f7a2d8b9c..882af4b46a8e 100644 --- a/server/proxy/grpcproxy/health.go +++ b/server/proxy/grpcproxy/health.go @@ -31,7 +31,7 @@ func HandleHealth(lg *zap.Logger, mux *http.ServeMux, c *clientv3.Client) { if lg == nil { lg = zap.NewNop() } - mux.Handle(etcdhttp.PathHealth, etcdhttp.NewHealthHandler(lg, func(excludedAlarms etcdhttp.AlarmSet) etcdhttp.Health { return checkHealth(c) })) + mux.Handle(etcdhttp.PathHealth, etcdhttp.NewHealthHandler(lg, func(excludedAlarms etcdhttp.AlarmSet, serializable bool) etcdhttp.Health { return checkHealth(c) })) } // HandleProxyHealth registers health handler on '/proxy/health'. @@ -39,7 +39,7 @@ func HandleProxyHealth(lg *zap.Logger, mux *http.ServeMux, c *clientv3.Client) { if lg == nil { lg = zap.NewNop() } - mux.Handle(etcdhttp.PathProxyHealth, etcdhttp.NewHealthHandler(lg, func(excludedAlarms etcdhttp.AlarmSet) etcdhttp.Health { return checkProxyHealth(c) })) + mux.Handle(etcdhttp.PathProxyHealth, etcdhttp.NewHealthHandler(lg, func(excludedAlarms etcdhttp.AlarmSet, serializable bool) etcdhttp.Health { return checkProxyHealth(c) })) } func checkHealth(c *clientv3.Client) etcdhttp.Health { From 23146a9fafb9671e47d069b6a33217d71faac9e5 Mon Sep 17 00:00:00 2001 From: Sam Batschelet Date: Mon, 15 Nov 2021 17:18:14 -0500 Subject: [PATCH 010/258] CHANGELOG: add experimental-max-learners Signed-off-by: Sam Batschelet --- CHANGELOG-3.6.md | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/CHANGELOG-3.6.md b/CHANGELOG-3.6.md index d3267857ff2f..3f6b28d5f432 100644 --- a/CHANGELOG-3.6.md +++ b/CHANGELOG-3.6.md @@ -32,6 +32,7 @@ See [code changes](https://github.com/etcd-io/etcd/compare/v3.5.0...v3.6.0). ### etcd server - Add [`etcd --log-format`](https://github.com/etcd-io/etcd/pull/13339) flag to support log format. +- Add [`etcd --experimental-max-learners`](https://github.com/etcd-io/etcd/pull/13377) flag to allow configuration of learner max membership. - Fix [non mutating requests pass through quotaKVServer when NOSPACE](https://github.com/etcd-io/etcd/pull/13435) - Fix [exclude the same alarm type activated by multiple peers](https://github.com/etcd-io/etcd/pull/13467). - Fix [Provide a better liveness probe for when etcd runs as a Kubernetes pod](https://github.com/etcd-io/etcd/pull/13399) @@ -44,4 +45,6 @@ See [code changes](https://github.com/etcd-io/etcd/compare/v3.5.0...v3.6.0). See [List of metrics](https://etcd.io/docs/latest/metrics/) for all metrics per release. -- Add [`etcd_disk_defrag_inflight`](https://github.com/etcd-io/etcd/pull/13371). \ No newline at end of file +- Add [`etcd_disk_defrag_inflight`](https://github.com/etcd-io/etcd/pull/13371). + +
From eccabd237beb0c40dd38b1fb0645bf0aa7060b7e Mon Sep 17 00:00:00 2001 From: qsyqian Date: Fri, 5 Nov 2021 15:53:58 +0800 Subject: [PATCH 011/258] etcdctl/ctlv3/command: add use time for defrag command --- etcdctl/ctlv3/command/defrag_command.go | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/etcdctl/ctlv3/command/defrag_command.go b/etcdctl/ctlv3/command/defrag_command.go index cd0d8a94ad49..9b4f29a6aa68 100644 --- a/etcdctl/ctlv3/command/defrag_command.go +++ b/etcdctl/ctlv3/command/defrag_command.go @@ -17,6 +17,7 @@ package command import ( "fmt" "os" + "time" "github.com/spf13/cobra" "go.etcd.io/etcd/etcdutl/v3/etcdutl" @@ -53,13 +54,15 @@ func defragCommandFunc(cmd *cobra.Command, args []string) { c := mustClientFromCmd(cmd) for _, ep := range endpointsFromCluster(cmd) { ctx, cancel := commandCtx(cmd) + start := time.Now() _, err := c.Defragment(ctx, ep) + d := time.Now().Sub(start) cancel() if err != nil { - fmt.Fprintf(os.Stderr, "Failed to defragment etcd member[%s] (%v)\n", ep, err) + fmt.Fprintf(os.Stderr, "Failed to defragment etcd member[%s]. took %s. (%v)\n", ep, d.String(), err) failures++ } else { - fmt.Printf("Finished defragmenting etcd member[%s]\n", ep) + fmt.Printf("Finished defragmenting etcd member[%s]. took %s\n", ep, d.String()) } } From ae7143903791121dcf5862ab76246625c390a031 Mon Sep 17 00:00:00 2001 From: Hitoshi Mitake Date: Sun, 21 Nov 2021 23:04:58 +0900 Subject: [PATCH 012/258] Update CHANGELOG for PR 13477 --- CHANGELOG-3.5.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/CHANGELOG-3.5.md b/CHANGELOG-3.5.md index 3de30512eb5e..cc38797ed998 100644 --- a/CHANGELOG-3.5.md +++ b/CHANGELOG-3.5.md @@ -294,7 +294,8 @@ Note that any `etcd_debugging_*` metrics are experimental and subject to change. - [Fix a data corruption bug by saving consistent index](https://github.com/etcd-io/etcd/pull/11652). - [Improve checkPassword performance](https://github.com/etcd-io/etcd/pull/11735). - [Add authRevision field in AuthStatus](https://github.com/etcd-io/etcd/pull/11659). - +- Fix [a bug of not refreshing expired tokens](https://github.com/etcd-io/etcd/pull/13308). +- ### API - Add [`/v3/auth/status`](https://github.com/etcd-io/etcd/pull/11536) endpoint to check if authentication is enabled From 7eb4bed2547cf3d06542631499e9b2a1e5e113c0 Mon Sep 17 00:00:00 2001 From: Liang Zheng Date: Wed, 24 Nov 2021 09:56:33 +0000 Subject: [PATCH 013/258] fix etcd benchmark binary not found Signed-off-by: Liang Zheng --- tools/rw-heatmaps/rw-benchmark.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tools/rw-heatmaps/rw-benchmark.sh b/tools/rw-heatmaps/rw-benchmark.sh index aeec18549942..abd63db1a635 100755 --- a/tools/rw-heatmaps/rw-benchmark.sh +++ b/tools/rw-heatmaps/rw-benchmark.sh @@ -19,7 +19,7 @@ COMMIT= ETCD_ROOT_DIR="$(cd $(dirname $0) && pwd)/../.." ETCD_BIN_DIR="${ETCD_ROOT_DIR}/bin" ETCD_BIN="${ETCD_BIN_DIR}/etcd" -ETCD_BM_BIN="${ETCD_ROOT_DIR}/tools/benchmark/benchmark" +ETCD_BM_BIN="${ETCD_BIN_DIR}/tools/benchmark" WORKING_DIR="$(mktemp -d)" CURRENT_DIR="$(pwd -P)" From 71493bde3e4218e80bc714bd08adc33789942bfd Mon Sep 17 00:00:00 2001 From: Kushal Pisavadia Date: Wed, 24 Nov 2021 11:39:46 +0000 Subject: [PATCH 014/258] *: Upgrade to use go.opentelemetry.io/otel@v1.2.0 Upgrading from v1.0.1. Upgrading related dependencies ------------------------------ The following dependencies also had to be upgraded: - go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.26.1 From v0.25.0. This gets rid of a transitive dependency on go.opentelemetry.io/otel@v1.0.1. - google.golang.org/genproto@v0.0.0-20211118181313-81c1377c94b1 --- api/go.mod | 4 ++-- api/go.sum | 22 +++++++++----------- client/v2/go.sum | 18 ++++++++-------- client/v3/go.mod | 4 ++-- client/v3/go.sum | 23 ++++++++++----------- etcdctl/go.mod | 14 ++++++------- etcdctl/go.sum | 45 +++++++++++++++++++--------------------- etcdutl/go.mod | 14 ++++++------- etcdutl/go.sum | 45 +++++++++++++++++++--------------------- go.mod | 26 ++++++++++++------------ go.sum | 52 +++++++++++++++++++++++------------------------ pkg/go.mod | 10 ++++----- pkg/go.sum | 24 ++++++++++++++++------ raft/go.mod | 2 +- raft/go.sum | 20 ++++++++---------- server/go.mod | 22 ++++++++++---------- server/go.sum | 53 +++++++++++++++++++++++------------------------- tests/go.mod | 22 ++++++++++---------- tests/go.sum | 52 +++++++++++++++++++++++------------------------ 19 files changed, 232 insertions(+), 240 deletions(-) diff --git a/api/go.mod b/api/go.mod index acb579c0e303..36f0c97c1084 100644 --- a/api/go.mod +++ b/api/go.mod @@ -7,7 +7,7 @@ require ( github.com/gogo/protobuf v1.3.2 github.com/golang/protobuf v1.5.2 github.com/grpc-ecosystem/grpc-gateway v1.16.0 - google.golang.org/genproto v0.0.0-20210602131652-f16073e35f0c + google.golang.org/genproto v0.0.0-20211118181313-81c1377c94b1 google.golang.org/grpc v1.41.0 ) @@ -15,7 +15,7 @@ require ( golang.org/x/net v0.0.0-20210405180319-a5a99cb37ef4 // indirect golang.org/x/sys v0.0.0-20210510120138-977fb7262007 // indirect golang.org/x/text v0.3.5 // indirect - google.golang.org/protobuf v1.26.0 // indirect + google.golang.org/protobuf v1.27.1 // indirect ) // Bad imports are sometimes causing attempts to pull that code. diff --git a/api/go.sum b/api/go.sum index bc491f0f788e..c0dacaa603be 100644 --- a/api/go.sum +++ b/api/go.sum @@ -1,12 +1,15 @@ cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= cloud.google.com/go v0.34.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= +github.com/OneOfOne/xxhash v1.2.2/go.mod h1:HSdplMjZKSmBqAxg5vPj2TmRDmfkzw+cTzAElWljhcU= github.com/antihax/optional v1.0.0/go.mod h1:uupD/76wgC+ih3iEmQUL+0Ugr19nfwCT1kdvxnR2qWY= github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU= +github.com/cespare/xxhash v1.1.0/go.mod h1:XrSqR1VqqWfGrhpAt58auRo0WTKS1nRRg3ghfAqPWnc= github.com/cespare/xxhash/v2 v2.1.1/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw= github.com/cncf/udpa/go v0.0.0-20191209042840-269d4d468f6f/go.mod h1:M8M6+tZqaGXZJjfX53e64911xZQV5JYwmTeXPW+k8Sc= github.com/cncf/udpa/go v0.0.0-20201120205902-5459f2c99403/go.mod h1:WmhPx2Nbnhtbo57+VJT5O0JRkEi1Wbu0z5j0R8u5Hbk= +github.com/cncf/xds/go v0.0.0-20210312221358-fbca930ec8ed/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs= github.com/cncf/xds/go v0.0.0-20210805033703-aa0b78936158/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs= github.com/coreos/go-semver v0.3.0 h1:wkHLiw0WNATZnSG7epLsujiMCgPAc9xhjJ4tgnAxmfM= github.com/coreos/go-semver v0.3.0/go.mod h1:nnelYz7RCh+5ahJtPPxZlU+153eP4D4r3EedlOD2RNk= @@ -15,7 +18,7 @@ github.com/envoyproxy/go-control-plane v0.9.0/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymF 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.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.20210512163311-63b5d3c536b0/go.mod h1:hliV/p42l8fGbc6Y9bQ70uLwIvmJyVE5k4iMKlh8wCQ= github.com/envoyproxy/go-control-plane v0.9.10-0.20210907150352-cf90f659a021/go.mod h1:AFq3mo9L8Lqqiid3OhADV3RfLJnjiw63cSpi+fDTRC0= github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c= github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04= @@ -52,12 +55,12 @@ github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+o github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= github.com/rogpeppe/fastuuid v1.2.0/go.mod h1:jVj6XXZzXRy/MSR5jhDC/2q6DgLz+nrA6LYCDYWNEvQ= +github.com/spaolacci/murmur3 v0.0.0-20180118202830-f09979ecbc72/go.mod h1:JwIasOWyU6f++ZhiEuf87xNszmSA2myDM2Kzu9HwQUA= github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA= github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/yuin/goldmark v1.1.27/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= go.opentelemetry.io/proto/otlp v0.7.0/go.mod h1:PqfVotwruBrMGOCsRd/89rSnXhoiJIqeYNgFYFoEGnI= golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= @@ -66,11 +69,8 @@ golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE= golang.org/x/lint v0.0.0-20190227174305-5b3e6a55c961/go.mod h1:wehouNa3lNwaWXcvxsM5YxQ5yQlVC4a0KAMCusXpPoU= golang.org/x/lint v0.0.0-20190313153728-d0100b6bd8b3/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= -golang.org/x/lint v0.0.0-20210508222113-6edffad5e616/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY= -golang.org/x/mod v0.1.1-0.20191105210325-c90efee705ee/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg= 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.4.2/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= 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-20190108225652-1e06a53dbb7e/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= @@ -91,7 +91,6 @@ golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJ golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/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-20210220032951-036812b2e83c/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-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= @@ -112,10 +111,8 @@ golang.org/x/tools v0.0.0-20190226205152-f727befe758c/go.mod h1:9Yl7xja0Znq3iFh3 golang.org/x/tools v0.0.0-20190311212946-11955173bddd/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= golang.org/x/tools v0.0.0-20190524140312-2c0ae7006135/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q= golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= -golang.org/x/tools v0.0.0-20200130002326-2f3ba24bd6e7/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= golang.org/x/tools v0.0.0-20200619180055-7c47624df98f/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= golang.org/x/tools v0.0.0-20210106214847-113979e3529a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= -golang.org/x/tools v0.1.2/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= 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-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= @@ -127,15 +124,15 @@ google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8/go.mod h1:JiN7NxoA google.golang.org/genproto v0.0.0-20190819201941-24fa4b261c55/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc= google.golang.org/genproto v0.0.0-20200513103714-09dca8ec2884/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= google.golang.org/genproto v0.0.0-20200526211855-cb27e3aa2013/go.mod h1:NbSheEEYHJ7i3ixzK3sjbqSGDJWnxyFXZblF3eUsNvo= -google.golang.org/genproto v0.0.0-20210602131652-f16073e35f0c h1:wtujag7C+4D6KMoulW9YauvK2lgdvCMS260jsqqBXr0= -google.golang.org/genproto v0.0.0-20210602131652-f16073e35f0c/go.mod h1:UODoCrxHCcBojKKwX1terBiRUaqAsFqJiF615XL43r0= +google.golang.org/genproto v0.0.0-20211118181313-81c1377c94b1 h1:b9mVrqYfq3P4bCdaLg1qtBnPzUYgglsIdjZkL/fQVOE= +google.golang.org/genproto v0.0.0-20211118181313-81c1377c94b1/go.mod h1:5CzLGKJ67TSI2B9POpiiyGha0AjJvZIUgRMt1dSmuhc= google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c= google.golang.org/grpc v1.23.0/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg= google.golang.org/grpc v1.25.1/go.mod h1:c3i+UQWmh7LiEpx4sFZnkU36qjEYZ0imhYfXVyQciAY= google.golang.org/grpc v1.27.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk= google.golang.org/grpc v1.33.1/go.mod h1:fr5YgcSWrqhRRxogOsw7RzIpsmvOZ6IcH4kBYTpR3n0= google.golang.org/grpc v1.36.0/go.mod h1:qjiiYl8FncCW8feJPdyg3v6XW24KsRHe+dy9BAGRRjU= -google.golang.org/grpc v1.38.0/go.mod h1:NREThFqKR1f3iQ6oBuvc5LadQuXVGo9rkm5ZGrQdJfM= +google.golang.org/grpc v1.40.0/go.mod h1:ogyxbiOoUXAkP+4+xa6PZSE9DZgIHtSpzjDTB9KAK34= google.golang.org/grpc v1.41.0 h1:f+PlOh7QV4iIJkPrx5NQ7qaNGFQ3OTse67yaDHfju4E= google.golang.org/grpc v1.41.0/go.mod h1:U3l9uK9J0sini8mHphKoXyaqDA/8VyGnDee1zzIUK6k= google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8= @@ -148,8 +145,9 @@ google.golang.org/protobuf v1.23.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2 google.golang.org/protobuf v1.23.1-0.20200526195155-81db48ad09cc/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= google.golang.org/protobuf v1.25.0/go.mod h1:9JNX74DMeImyA3h4bdi1ymwjUzf21/xIlbajtzgsN7c= google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw= -google.golang.org/protobuf v1.26.0 h1:bxAC2xTBsZGibn2RTntX0oH50xLsqy1OxA9tTL3p/lk= google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc= +google.golang.org/protobuf v1.27.1 h1:SnqbnDw1V7RiZcXPx5MEeqPv2s79L9i7BJUlG/+RurQ= +google.golang.org/protobuf v1.27.1/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.2.3 h1:fvjTMHxHEw/mxHbtzPi3JCcKXQRAnQTBRo6YCJSVHKI= diff --git a/client/v2/go.sum b/client/v2/go.sum index 920e7ee807da..b9b481332d67 100644 --- a/client/v2/go.sum +++ b/client/v2/go.sum @@ -1,12 +1,15 @@ cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= cloud.google.com/go v0.34.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= +github.com/OneOfOne/xxhash v1.2.2/go.mod h1:HSdplMjZKSmBqAxg5vPj2TmRDmfkzw+cTzAElWljhcU= github.com/antihax/optional v1.0.0/go.mod h1:uupD/76wgC+ih3iEmQUL+0Ugr19nfwCT1kdvxnR2qWY= github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU= +github.com/cespare/xxhash v1.1.0/go.mod h1:XrSqR1VqqWfGrhpAt58auRo0WTKS1nRRg3ghfAqPWnc= github.com/cespare/xxhash/v2 v2.1.1/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw= github.com/cncf/udpa/go v0.0.0-20191209042840-269d4d468f6f/go.mod h1:M8M6+tZqaGXZJjfX53e64911xZQV5JYwmTeXPW+k8Sc= github.com/cncf/udpa/go v0.0.0-20201120205902-5459f2c99403/go.mod h1:WmhPx2Nbnhtbo57+VJT5O0JRkEi1Wbu0z5j0R8u5Hbk= +github.com/cncf/xds/go v0.0.0-20210312221358-fbca930ec8ed/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs= github.com/cncf/xds/go v0.0.0-20210805033703-aa0b78936158/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs= github.com/coreos/go-semver v0.3.0 h1:wkHLiw0WNATZnSG7epLsujiMCgPAc9xhjJ4tgnAxmfM= github.com/coreos/go-semver v0.3.0/go.mod h1:nnelYz7RCh+5ahJtPPxZlU+153eP4D4r3EedlOD2RNk= @@ -18,7 +21,7 @@ github.com/envoyproxy/go-control-plane v0.9.0/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymF 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.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.20210512163311-63b5d3c536b0/go.mod h1:hliV/p42l8fGbc6Y9bQ70uLwIvmJyVE5k4iMKlh8wCQ= github.com/envoyproxy/go-control-plane v0.9.10-0.20210907150352-cf90f659a021/go.mod h1:AFq3mo9L8Lqqiid3OhADV3RfLJnjiw63cSpi+fDTRC0= github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c= github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04= @@ -54,6 +57,7 @@ github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZb github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= github.com/rogpeppe/fastuuid v1.2.0/go.mod h1:jVj6XXZzXRy/MSR5jhDC/2q6DgLz+nrA6LYCDYWNEvQ= +github.com/spaolacci/murmur3 v0.0.0-20180118202830-f09979ecbc72/go.mod h1:JwIasOWyU6f++ZhiEuf87xNszmSA2myDM2Kzu9HwQUA= github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA= @@ -61,7 +65,6 @@ github.com/stretchr/testify v1.7.0 h1:nwc3DEeHmmLAfoZucVR881uASk0Mfjw8xYJ99tb5Cc github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/yuin/goldmark v1.1.27/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= go.opentelemetry.io/proto/otlp v0.7.0/go.mod h1:PqfVotwruBrMGOCsRd/89rSnXhoiJIqeYNgFYFoEGnI= go.uber.org/atomic v1.7.0/go.mod h1:fEN4uk6kAWBTFdckzkM89CLk9XfWZrxpCo0nPH17wJc= go.uber.org/multierr v1.6.0/go.mod h1:cdWPpRnG4AhwMwsgIHip0KRBQjJy5kYEpYjJxpXp9iU= @@ -73,11 +76,8 @@ golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE= golang.org/x/lint v0.0.0-20190227174305-5b3e6a55c961/go.mod h1:wehouNa3lNwaWXcvxsM5YxQ5yQlVC4a0KAMCusXpPoU= golang.org/x/lint v0.0.0-20190313153728-d0100b6bd8b3/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= -golang.org/x/lint v0.0.0-20210508222113-6edffad5e616/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY= -golang.org/x/mod v0.1.1-0.20191105210325-c90efee705ee/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg= 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.4.2/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= 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-20190108225652-1e06a53dbb7e/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= @@ -97,7 +97,6 @@ golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJ golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/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-20210220032951-036812b2e83c/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-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= @@ -117,10 +116,8 @@ golang.org/x/tools v0.0.0-20190226205152-f727befe758c/go.mod h1:9Yl7xja0Znq3iFh3 golang.org/x/tools v0.0.0-20190311212946-11955173bddd/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= golang.org/x/tools v0.0.0-20190524140312-2c0ae7006135/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q= golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= -golang.org/x/tools v0.0.0-20200130002326-2f3ba24bd6e7/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= golang.org/x/tools v0.0.0-20200619180055-7c47624df98f/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= golang.org/x/tools v0.0.0-20210106214847-113979e3529a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= -golang.org/x/tools v0.1.2/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= 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-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= @@ -131,14 +128,14 @@ google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8/go.mod h1:JiN7NxoA google.golang.org/genproto v0.0.0-20190819201941-24fa4b261c55/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc= google.golang.org/genproto v0.0.0-20200513103714-09dca8ec2884/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= google.golang.org/genproto v0.0.0-20200526211855-cb27e3aa2013/go.mod h1:NbSheEEYHJ7i3ixzK3sjbqSGDJWnxyFXZblF3eUsNvo= -google.golang.org/genproto v0.0.0-20210602131652-f16073e35f0c/go.mod h1:UODoCrxHCcBojKKwX1terBiRUaqAsFqJiF615XL43r0= +google.golang.org/genproto v0.0.0-20211118181313-81c1377c94b1/go.mod h1:5CzLGKJ67TSI2B9POpiiyGha0AjJvZIUgRMt1dSmuhc= google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c= google.golang.org/grpc v1.23.0/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg= google.golang.org/grpc v1.25.1/go.mod h1:c3i+UQWmh7LiEpx4sFZnkU36qjEYZ0imhYfXVyQciAY= google.golang.org/grpc v1.27.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk= google.golang.org/grpc v1.33.1/go.mod h1:fr5YgcSWrqhRRxogOsw7RzIpsmvOZ6IcH4kBYTpR3n0= google.golang.org/grpc v1.36.0/go.mod h1:qjiiYl8FncCW8feJPdyg3v6XW24KsRHe+dy9BAGRRjU= -google.golang.org/grpc v1.38.0/go.mod h1:NREThFqKR1f3iQ6oBuvc5LadQuXVGo9rkm5ZGrQdJfM= +google.golang.org/grpc v1.40.0/go.mod h1:ogyxbiOoUXAkP+4+xa6PZSE9DZgIHtSpzjDTB9KAK34= google.golang.org/grpc v1.41.0/go.mod h1:U3l9uK9J0sini8mHphKoXyaqDA/8VyGnDee1zzIUK6k= 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= @@ -151,6 +148,7 @@ google.golang.org/protobuf v1.23.1-0.20200526195155-81db48ad09cc/go.mod h1:EGpAD google.golang.org/protobuf v1.25.0/go.mod h1:9JNX74DMeImyA3h4bdi1ymwjUzf21/xIlbajtzgsN7c= google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw= google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc= +google.golang.org/protobuf v1.27.1/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= diff --git a/client/v3/go.mod b/client/v3/go.mod index f1215f9b094f..3c3b0f631e0c 100644 --- a/client/v3/go.mod +++ b/client/v3/go.mod @@ -32,8 +32,8 @@ require ( golang.org/x/net v0.0.0-20210405180319-a5a99cb37ef4 // indirect golang.org/x/sys v0.0.0-20210603125802-9665404d3644 // indirect golang.org/x/text v0.3.5 // indirect - google.golang.org/genproto v0.0.0-20210602131652-f16073e35f0c // indirect - google.golang.org/protobuf v1.26.0 // indirect + google.golang.org/genproto v0.0.0-20211118181313-81c1377c94b1 // indirect + google.golang.org/protobuf v1.27.1 // indirect gopkg.in/yaml.v2 v2.3.0 // indirect gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b // indirect ) diff --git a/client/v3/go.sum b/client/v3/go.sum index 57e49a2a80dc..eef5c5e6ae5f 100644 --- a/client/v3/go.sum +++ b/client/v3/go.sum @@ -1,6 +1,7 @@ cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= cloud.google.com/go v0.34.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= +github.com/OneOfOne/xxhash v1.2.2/go.mod h1:HSdplMjZKSmBqAxg5vPj2TmRDmfkzw+cTzAElWljhcU= github.com/alecthomas/template v0.0.0-20160405071501-a0175ee3bccc/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc= github.com/alecthomas/template v0.0.0-20190718012654-fb15b899a751/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc= github.com/alecthomas/units v0.0.0-20151022065526-2efee857e7cf/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0= @@ -12,11 +13,14 @@ github.com/beorn7/perks v1.0.0/go.mod h1:KWe93zE9D1o94FZ5RNwFwVgaQK1VOXiVxmqh+Ce github.com/beorn7/perks v1.0.1 h1:VlbKKnNfV8bJzeqoa4cOKqO6bYr3WgKZxO8Z16+hsOM= github.com/beorn7/perks v1.0.1/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6rlkpw= github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU= +github.com/cespare/xxhash v1.1.0 h1:a6HrQnmkObjyL+Gs60czilIUGqrzKutQD6XZog3p+ko= +github.com/cespare/xxhash v1.1.0/go.mod h1:XrSqR1VqqWfGrhpAt58auRo0WTKS1nRRg3ghfAqPWnc= github.com/cespare/xxhash/v2 v2.1.1 h1:6MnRN8NT7+YBpUIWxHtefFZOKTAPgGjpQSxqLNn0+qY= github.com/cespare/xxhash/v2 v2.1.1/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw= github.com/cncf/udpa/go v0.0.0-20191209042840-269d4d468f6f/go.mod h1:M8M6+tZqaGXZJjfX53e64911xZQV5JYwmTeXPW+k8Sc= github.com/cncf/udpa/go v0.0.0-20201120205902-5459f2c99403/go.mod h1:WmhPx2Nbnhtbo57+VJT5O0JRkEi1Wbu0z5j0R8u5Hbk= +github.com/cncf/xds/go v0.0.0-20210312221358-fbca930ec8ed/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs= github.com/cncf/xds/go v0.0.0-20210805033703-aa0b78936158/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs= github.com/coreos/go-semver v0.3.0 h1:wkHLiw0WNATZnSG7epLsujiMCgPAc9xhjJ4tgnAxmfM= github.com/coreos/go-semver v0.3.0/go.mod h1:nnelYz7RCh+5ahJtPPxZlU+153eP4D4r3EedlOD2RNk= @@ -31,7 +35,7 @@ github.com/envoyproxy/go-control-plane v0.9.0/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymF 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.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.20210512163311-63b5d3c536b0/go.mod h1:hliV/p42l8fGbc6Y9bQ70uLwIvmJyVE5k4iMKlh8wCQ= github.com/envoyproxy/go-control-plane v0.9.10-0.20210907150352-cf90f659a021/go.mod h1:AFq3mo9L8Lqqiid3OhADV3RfLJnjiw63cSpi+fDTRC0= github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c= github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04= @@ -129,6 +133,7 @@ github.com/rogpeppe/fastuuid v1.2.0/go.mod h1:jVj6XXZzXRy/MSR5jhDC/2q6DgLz+nrA6L github.com/sirupsen/logrus v1.2.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPxbbu5VWo= github.com/sirupsen/logrus v1.4.2/go.mod h1:tLMulIdttU9McNUspp0xgXVQah82FyeX6MwdIuYE2rE= github.com/sirupsen/logrus v1.6.0/go.mod h1:7uNnSEd1DgxDLC74fIahvMZmmYsHGZGEOFrfsX/uA88= +github.com/spaolacci/murmur3 v0.0.0-20180118202830-f09979ecbc72/go.mod h1:JwIasOWyU6f++ZhiEuf87xNszmSA2myDM2Kzu9HwQUA= github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= @@ -139,7 +144,6 @@ github.com/stretchr/testify v1.7.0 h1:nwc3DEeHmmLAfoZucVR881uASk0Mfjw8xYJ99tb5Cc github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/yuin/goldmark v1.1.27/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= go.opentelemetry.io/proto/otlp v0.7.0/go.mod h1:PqfVotwruBrMGOCsRd/89rSnXhoiJIqeYNgFYFoEGnI= go.uber.org/atomic v1.7.0 h1:ADUqmZGgLDDfbSL9ZmPxKTybcoEYHgpYfELNoN+7hsw= go.uber.org/atomic v1.7.0/go.mod h1:fEN4uk6kAWBTFdckzkM89CLk9XfWZrxpCo0nPH17wJc= @@ -155,11 +159,8 @@ golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE= golang.org/x/lint v0.0.0-20190227174305-5b3e6a55c961/go.mod h1:wehouNa3lNwaWXcvxsM5YxQ5yQlVC4a0KAMCusXpPoU= golang.org/x/lint v0.0.0-20190313153728-d0100b6bd8b3/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= -golang.org/x/lint v0.0.0-20210508222113-6edffad5e616/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY= -golang.org/x/mod v0.1.1-0.20191105210325-c90efee705ee/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg= 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.4.2/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= 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-20181114220301-adae6a3d119a/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= @@ -185,7 +186,6 @@ golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJ golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/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-20210220032951-036812b2e83c/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-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20181116152217-5ac8a444bdc5/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= @@ -216,10 +216,8 @@ golang.org/x/tools v0.0.0-20190226205152-f727befe758c/go.mod h1:9Yl7xja0Znq3iFh3 golang.org/x/tools v0.0.0-20190311212946-11955173bddd/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= golang.org/x/tools v0.0.0-20190524140312-2c0ae7006135/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q= golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= -golang.org/x/tools v0.0.0-20200130002326-2f3ba24bd6e7/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= golang.org/x/tools v0.0.0-20200619180055-7c47624df98f/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= golang.org/x/tools v0.0.0-20210106214847-113979e3529a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= -golang.org/x/tools v0.1.2/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= 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-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= @@ -231,15 +229,15 @@ google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8/go.mod h1:JiN7NxoA google.golang.org/genproto v0.0.0-20190819201941-24fa4b261c55/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc= google.golang.org/genproto v0.0.0-20200513103714-09dca8ec2884/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= google.golang.org/genproto v0.0.0-20200526211855-cb27e3aa2013/go.mod h1:NbSheEEYHJ7i3ixzK3sjbqSGDJWnxyFXZblF3eUsNvo= -google.golang.org/genproto v0.0.0-20210602131652-f16073e35f0c h1:wtujag7C+4D6KMoulW9YauvK2lgdvCMS260jsqqBXr0= -google.golang.org/genproto v0.0.0-20210602131652-f16073e35f0c/go.mod h1:UODoCrxHCcBojKKwX1terBiRUaqAsFqJiF615XL43r0= +google.golang.org/genproto v0.0.0-20211118181313-81c1377c94b1 h1:b9mVrqYfq3P4bCdaLg1qtBnPzUYgglsIdjZkL/fQVOE= +google.golang.org/genproto v0.0.0-20211118181313-81c1377c94b1/go.mod h1:5CzLGKJ67TSI2B9POpiiyGha0AjJvZIUgRMt1dSmuhc= google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c= google.golang.org/grpc v1.23.0/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg= google.golang.org/grpc v1.25.1/go.mod h1:c3i+UQWmh7LiEpx4sFZnkU36qjEYZ0imhYfXVyQciAY= google.golang.org/grpc v1.27.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk= google.golang.org/grpc v1.33.1/go.mod h1:fr5YgcSWrqhRRxogOsw7RzIpsmvOZ6IcH4kBYTpR3n0= google.golang.org/grpc v1.36.0/go.mod h1:qjiiYl8FncCW8feJPdyg3v6XW24KsRHe+dy9BAGRRjU= -google.golang.org/grpc v1.38.0/go.mod h1:NREThFqKR1f3iQ6oBuvc5LadQuXVGo9rkm5ZGrQdJfM= +google.golang.org/grpc v1.40.0/go.mod h1:ogyxbiOoUXAkP+4+xa6PZSE9DZgIHtSpzjDTB9KAK34= google.golang.org/grpc v1.41.0 h1:f+PlOh7QV4iIJkPrx5NQ7qaNGFQ3OTse67yaDHfju4E= google.golang.org/grpc v1.41.0/go.mod h1:U3l9uK9J0sini8mHphKoXyaqDA/8VyGnDee1zzIUK6k= google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8= @@ -252,8 +250,9 @@ google.golang.org/protobuf v1.23.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2 google.golang.org/protobuf v1.23.1-0.20200526195155-81db48ad09cc/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= google.golang.org/protobuf v1.25.0/go.mod h1:9JNX74DMeImyA3h4bdi1ymwjUzf21/xIlbajtzgsN7c= google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw= -google.golang.org/protobuf v1.26.0 h1:bxAC2xTBsZGibn2RTntX0oH50xLsqy1OxA9tTL3p/lk= google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc= +google.golang.org/protobuf v1.27.1 h1:SnqbnDw1V7RiZcXPx5MEeqPv2s79L9i7BJUlG/+RurQ= +google.golang.org/protobuf v1.27.1/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc= gopkg.in/alecthomas/kingpin.v2 v2.2.6/go.mod h1:FMv+mEhP44yOT+4EoQTLFTRgOQ1FBLkstjWtayDeSgw= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15 h1:YR8cESwS4TdDjEe65xsg0ogRM/Nc3DYOhEAlW+xobZo= diff --git a/etcdctl/go.mod b/etcdctl/go.mod index bc17a7d04a18..f08655bde072 100644 --- a/etcdctl/go.mod +++ b/etcdctl/go.mod @@ -45,16 +45,16 @@ require ( go.etcd.io/bbolt v1.3.6 // indirect go.etcd.io/etcd/raft/v3 v3.5.0 // indirect go.etcd.io/etcd/server/v3 v3.5.0 // indirect - go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.25.0 // indirect - go.opentelemetry.io/otel v1.0.1 // indirect - go.opentelemetry.io/otel/trace v1.0.1 // indirect + go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.26.1 // indirect + go.opentelemetry.io/otel v1.2.0 // indirect + go.opentelemetry.io/otel/trace v1.2.0 // indirect go.uber.org/atomic v1.7.0 // indirect go.uber.org/multierr v1.7.0 // indirect golang.org/x/crypto v0.0.0-20210513164829-c07d793c2f9a // indirect - golang.org/x/net v0.0.0-20210525063256-abc453219eb5 // indirect - golang.org/x/sys v0.0.0-20210603125802-9665404d3644 // indirect - golang.org/x/text v0.3.6 // indirect - google.golang.org/genproto v0.0.0-20210602131652-f16073e35f0c // indirect + golang.org/x/net v0.0.0-20211123203042-d83791d6bcd9 // indirect + golang.org/x/sys v0.0.0-20211123173158-ef496fb156ab // indirect + golang.org/x/text v0.3.7 // indirect + google.golang.org/genproto v0.0.0-20211118181313-81c1377c94b1 // indirect google.golang.org/protobuf v1.27.1 // indirect sigs.k8s.io/json v0.0.0-20211020170558-c049b76a60c6 // indirect ) diff --git a/etcdctl/go.sum b/etcdctl/go.sum index 7f7c073faa8b..840df2269895 100644 --- a/etcdctl/go.sum +++ b/etcdctl/go.sum @@ -121,7 +121,6 @@ github.com/golang/protobuf v1.4.1/go.mod h1:U8fpvMrcmy5pZrNK1lt4xCsGvpyWQ/VVv6QD github.com/golang/protobuf v1.4.2/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI= github.com/golang/protobuf v1.4.3/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI= 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/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY= github.com/google/btree v0.0.0-20180813153112-4030bb1f1f0c/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ= @@ -302,23 +301,26 @@ github.com/xiang90/probing v0.0.0-20190116061207-43a291ad63a2 h1:eY9dn8+vbi4tKz5 github.com/xiang90/probing v0.0.0-20190116061207-43a291ad63a2/go.mod h1:UETIi67q53MR2AWcXfiuqkDkRtnGDLqkBTpCHuJHxtU= github.com/yuin/goldmark v1.1.27/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= go.etcd.io/bbolt v1.3.2/go.mod h1:IbVyRI1SCnLcuJnV2u8VeU0CEYM7e686BmAb1XKL+uU= go.etcd.io/bbolt v1.3.6 h1:/ecaJf0sk1l4l6V4awd65v2C3ILy7MSj+s/x1ADCIMU= go.etcd.io/bbolt v1.3.6/go.mod h1:qXsaaIqmgQH0T+OPdb99Bf+PKfBBQVAdyD6TY9G8XM4= go.opencensus.io v0.21.0/go.mod h1:mSImk1erAIZhrmZN+AvHh14ztQfjbGwt4TtuofqLduU= go.opencensus.io v0.22.0/go.mod h1:+kGneAE2xo2IficOXnaByMWTGM9T73dGwxeWcUqIpI8= -go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.25.0 h1:Wx7nFnvCaissIUZxPkBqDz2963Z+Cl+PkYbDKzTxDqQ= -go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.25.0/go.mod h1:E5NNboN0UqSAki0Atn9kVwaN7I+l25gGxDqBueo/74E= -go.opentelemetry.io/otel v1.0.1 h1:4XKyXmfqJLOQ7feyV5DB6gsBFZ0ltB8vLtp6pj4JIcc= -go.opentelemetry.io/otel v1.0.1/go.mod h1:OPEOD4jIT2SlZPMmwT6FqZz2C0ZNdQqiWcoK6M0SNFU= -go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.0.1/go.mod h1:Kv8liBeVNFkkkbilbgWRpV+wWuu+H5xdOT6HAgd30iw= -go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.0.1/go.mod h1:xOvWoTOrQjxjW61xtOmD/WKGRYb/P4NzRo3bs65U6Rk= -go.opentelemetry.io/otel/sdk v1.0.1/go.mod h1:HrdXne+BiwsOHYYkBE5ysIcv2bvdZstxzmCQhxTcZkI= -go.opentelemetry.io/otel/trace v1.0.1 h1:StTeIH6Q3G4r0Fiw34LTokUFESZgIDUr0qIJ7mKmAfw= -go.opentelemetry.io/otel/trace v1.0.1/go.mod h1:5g4i4fKLaX2BQpSBsxw8YYcgKpMMSW3x7ZTuYBr3sUk= +go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.26.1 h1:puWrOArBwWlr5dq6vyZ6fKykHyS8JgMIVhTBA8XsGuU= +go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.26.1/go.mod h1:4wsfAAW5N9wUHM0QTmZS8z7fvYZ1rv3m+sVeSpf8NhU= +go.opentelemetry.io/otel v1.1.0/go.mod h1:7cww0OW51jQ8IaZChIEdqLwgh+44+7uiTdWsAL0wQpA= +go.opentelemetry.io/otel v1.2.0 h1:YOQDvxO1FayUcT9MIhJhgMyNO1WqoduiyvQHzGN0kUQ= +go.opentelemetry.io/otel v1.2.0/go.mod h1:aT17Fk0Z1Nor9e0uisf98LrntPGMnk4frBO9+dkf69I= +go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.1.0/go.mod h1:/E4iniSqAEvqbq6KM5qThKZR2sd42kDvD+SrYt00vRw= +go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.1.0/go.mod h1:Gyc0evUosTBVNRqTFGuu0xqebkEWLkLwv42qggTCwro= +go.opentelemetry.io/otel/sdk v1.1.0/go.mod h1:3aQvM6uLm6C4wJpHtT8Od3vNzeZ34Pqc6bps8MywWzo= +go.opentelemetry.io/otel/sdk v1.2.0/go.mod h1:jNN8QtpvbsKhgaC6V5lHiejMoKD+V8uadoSafgHPx1U= +go.opentelemetry.io/otel/trace v1.1.0/go.mod h1:i47XtdcBQiktu5IsrPqOHe8w+sBmnLwwHt8wiUsWGTI= +go.opentelemetry.io/otel/trace v1.2.0 h1:Ys3iqbqZhcf28hHzrm5WAquMkDHNZTUkw7KHbuNjej0= +go.opentelemetry.io/otel/trace v1.2.0/go.mod h1:N5FLswTubnxKxOJHM7XZC074qpeEdLy3CgAVsdMucK0= go.opentelemetry.io/proto/otlp v0.7.0/go.mod h1:PqfVotwruBrMGOCsRd/89rSnXhoiJIqeYNgFYFoEGnI= go.opentelemetry.io/proto/otlp v0.9.0/go.mod h1:1vKfU9rv61e9EVGthD1zNvUbiwPcimSsOPU9brfSHJg= +go.opentelemetry.io/proto/otlp v0.10.0/go.mod h1:zG20xCK0szZ1xdokeSOwEcmlXu+x9kkdRe6N1DhKcfU= go.uber.org/atomic v1.4.0/go.mod h1:gD2HeocX3+yG+ygLZcrzQJaqmWj9AIm7n08wl/qW/PE= go.uber.org/atomic v1.7.0 h1:ADUqmZGgLDDfbSL9ZmPxKTybcoEYHgpYfELNoN+7hsw= go.uber.org/atomic v1.7.0/go.mod h1:fEN4uk6kAWBTFdckzkM89CLk9XfWZrxpCo0nPH17wJc= @@ -352,15 +354,12 @@ golang.org/x/lint v0.0.0-20190313153728-d0100b6bd8b3/go.mod h1:6SW0HCj/g11FgYtHl golang.org/x/lint v0.0.0-20190409202823-959b441ac422/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= golang.org/x/lint v0.0.0-20190909230951-414d861bb4ac/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= golang.org/x/lint v0.0.0-20190930215403-16217165b5de/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= -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-20190719004257-d2bd2a29d028/go.mod h1:E/iHnbuqvinMTCcRqshq8CkpyQDoeVncDDYHnLhea+o= golang.org/x/mod v0.0.0-20190513183733-4bf6d317e70e/go.mod h1:mXi4GBBbnImb6dmsKGUJ2LatrhH/nqhxcFungHvyanc= golang.org/x/mod v0.1.0/go.mod h1:0QHyrYULN0/3qlju5TqG8bIK38QM8yzMo5ekMj3DlcY= -golang.org/x/mod v0.1.1-0.20191105210325-c90efee705ee/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg= 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.4.2/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= 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-20181023162649-9b4f9f5ad519/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= @@ -383,8 +382,8 @@ golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwY golang.org/x/net v0.0.0-20201202161906-c7110b5ffcbb/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= golang.org/x/net v0.0.0-20210405180319-a5a99cb37ef4/go.mod h1:p54w0d4576C0XHj96bSt6lcn1PtDYWL6XObtHCRCNQM= -golang.org/x/net v0.0.0-20210525063256-abc453219eb5 h1:wjuX4b5yYQnEQHzd+CBcrcC6OVR2J1CN6mUy0oSxIPo= -golang.org/x/net v0.0.0-20210525063256-abc453219eb5/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= +golang.org/x/net v0.0.0-20211123203042-d83791d6bcd9 h1:0qxwC5n+ttVOINCBeRHO0nq9X7uy8SDsPoi5OaCdIEI= +golang.org/x/net v0.0.0-20211123203042-d83791d6bcd9/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= 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-20190604053449-0f29369cfe45/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= @@ -398,7 +397,6 @@ golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJ golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/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-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sys v0.0.0-20180823144017-11551d06cbcc/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= @@ -427,16 +425,18 @@ golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7w 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-20210603081109-ebe580a85c40/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20210603125802-9665404d3644 h1:CA1DEQ4NdKphKeL70tvsWNdT5oFh1lOjihRcEDROi0I= golang.org/x/sys v0.0.0-20210603125802-9665404d3644/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20211123173158-ef496fb156ab h1:rfJ1bsoJQQIAoAxTxB7bme+vHrNkRw8CqfsYh9w54cw= +golang.org/x/sys v0.0.0-20211123173158-ef496fb156ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.1-0.20180807135948-17ff2d5776d2/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.2/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.5/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= -golang.org/x/text v0.3.6 h1:aRYxNxv6iGQlyVaZmk6ZgYEDa+Jg18DxebPSrd6bg1M= 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/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-20210220033141-f8bda1e9f3ba h1:O8mE0/t419eoIwhTFpKVkHiTs/Igowgfkj25AcZrtiE= @@ -461,10 +461,8 @@ golang.org/x/tools v0.0.0-20190911174233-4f2ddba30aff/go.mod h1:b+2E5dAYhXwXZwtn golang.org/x/tools v0.0.0-20191012152004-8de300cfc20a/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.0.0-20191112195655-aa38f8e97acc/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= -golang.org/x/tools v0.0.0-20200130002326-2f3ba24bd6e7/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= golang.org/x/tools v0.0.0-20200619180055-7c47624df98f/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= golang.org/x/tools v0.0.0-20210106214847-113979e3529a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= -golang.org/x/tools v0.1.2/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= 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-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= @@ -492,8 +490,8 @@ google.golang.org/genproto v0.0.0-20191108220845-16a3f7862a1a/go.mod h1:n3cpQtvx google.golang.org/genproto v0.0.0-20200423170343-7949de9c1215/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= google.golang.org/genproto v0.0.0-20200513103714-09dca8ec2884/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= google.golang.org/genproto v0.0.0-20200526211855-cb27e3aa2013/go.mod h1:NbSheEEYHJ7i3ixzK3sjbqSGDJWnxyFXZblF3eUsNvo= -google.golang.org/genproto v0.0.0-20210602131652-f16073e35f0c h1:wtujag7C+4D6KMoulW9YauvK2lgdvCMS260jsqqBXr0= -google.golang.org/genproto v0.0.0-20210602131652-f16073e35f0c/go.mod h1:UODoCrxHCcBojKKwX1terBiRUaqAsFqJiF615XL43r0= +google.golang.org/genproto v0.0.0-20211118181313-81c1377c94b1 h1:b9mVrqYfq3P4bCdaLg1qtBnPzUYgglsIdjZkL/fQVOE= +google.golang.org/genproto v0.0.0-20211118181313-81c1377c94b1/go.mod h1:5CzLGKJ67TSI2B9POpiiyGha0AjJvZIUgRMt1dSmuhc= 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.21.1/go.mod h1:oYelfM1adQP15Ek0mdvEgi9Df8B9CZIaU1084ijfRaM= @@ -504,7 +502,6 @@ google.golang.org/grpc v1.29.1/go.mod h1:itym6AZVZYACWQqET3MqgPpjcuV5QH3BxFS3Iji google.golang.org/grpc v1.33.1/go.mod h1:fr5YgcSWrqhRRxogOsw7RzIpsmvOZ6IcH4kBYTpR3n0= google.golang.org/grpc v1.36.0/go.mod h1:qjiiYl8FncCW8feJPdyg3v6XW24KsRHe+dy9BAGRRjU= 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.40.0/go.mod h1:ogyxbiOoUXAkP+4+xa6PZSE9DZgIHtSpzjDTB9KAK34= google.golang.org/grpc v1.41.0 h1:f+PlOh7QV4iIJkPrx5NQ7qaNGFQ3OTse67yaDHfju4E= google.golang.org/grpc v1.41.0/go.mod h1:U3l9uK9J0sini8mHphKoXyaqDA/8VyGnDee1zzIUK6k= diff --git a/etcdutl/go.mod b/etcdutl/go.mod index 6ea6bc7710de..36acdf8ab910 100644 --- a/etcdutl/go.mod +++ b/etcdutl/go.mod @@ -54,17 +54,17 @@ require ( github.com/spf13/pflag v1.0.5 // indirect github.com/xiang90/probing v0.0.0-20190116061207-43a291ad63a2 // indirect go.etcd.io/etcd/client/v2 v2.305.0 // indirect - go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.25.0 // indirect - go.opentelemetry.io/otel v1.0.1 // indirect - go.opentelemetry.io/otel/trace v1.0.1 // indirect + go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.26.1 // indirect + go.opentelemetry.io/otel v1.2.0 // indirect + go.opentelemetry.io/otel/trace v1.2.0 // indirect go.uber.org/atomic v1.7.0 // indirect go.uber.org/multierr v1.7.0 // indirect golang.org/x/crypto v0.0.0-20210513164829-c07d793c2f9a // indirect - golang.org/x/net v0.0.0-20210525063256-abc453219eb5 // indirect - golang.org/x/sys v0.0.0-20210603125802-9665404d3644 // indirect - golang.org/x/text v0.3.6 // indirect + golang.org/x/net v0.0.0-20211123203042-d83791d6bcd9 // indirect + golang.org/x/sys v0.0.0-20211123173158-ef496fb156ab // indirect + golang.org/x/text v0.3.7 // indirect golang.org/x/time v0.0.0-20210220033141-f8bda1e9f3ba // indirect - google.golang.org/genproto v0.0.0-20210602131652-f16073e35f0c // indirect + google.golang.org/genproto v0.0.0-20211118181313-81c1377c94b1 // indirect google.golang.org/grpc v1.41.0 // indirect google.golang.org/protobuf v1.27.1 // indirect sigs.k8s.io/json v0.0.0-20211020170558-c049b76a60c6 // indirect diff --git a/etcdutl/go.sum b/etcdutl/go.sum index 40502ee95672..a602b0288081 100644 --- a/etcdutl/go.sum +++ b/etcdutl/go.sum @@ -117,7 +117,6 @@ github.com/golang/protobuf v1.4.1/go.mod h1:U8fpvMrcmy5pZrNK1lt4xCsGvpyWQ/VVv6QD github.com/golang/protobuf v1.4.2/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI= github.com/golang/protobuf v1.4.3/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI= 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/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY= github.com/google/btree v0.0.0-20180813153112-4030bb1f1f0c/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ= @@ -292,23 +291,26 @@ github.com/xiang90/probing v0.0.0-20190116061207-43a291ad63a2 h1:eY9dn8+vbi4tKz5 github.com/xiang90/probing v0.0.0-20190116061207-43a291ad63a2/go.mod h1:UETIi67q53MR2AWcXfiuqkDkRtnGDLqkBTpCHuJHxtU= github.com/yuin/goldmark v1.1.27/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= go.etcd.io/bbolt v1.3.2/go.mod h1:IbVyRI1SCnLcuJnV2u8VeU0CEYM7e686BmAb1XKL+uU= go.etcd.io/bbolt v1.3.6 h1:/ecaJf0sk1l4l6V4awd65v2C3ILy7MSj+s/x1ADCIMU= go.etcd.io/bbolt v1.3.6/go.mod h1:qXsaaIqmgQH0T+OPdb99Bf+PKfBBQVAdyD6TY9G8XM4= go.opencensus.io v0.21.0/go.mod h1:mSImk1erAIZhrmZN+AvHh14ztQfjbGwt4TtuofqLduU= go.opencensus.io v0.22.0/go.mod h1:+kGneAE2xo2IficOXnaByMWTGM9T73dGwxeWcUqIpI8= -go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.25.0 h1:Wx7nFnvCaissIUZxPkBqDz2963Z+Cl+PkYbDKzTxDqQ= -go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.25.0/go.mod h1:E5NNboN0UqSAki0Atn9kVwaN7I+l25gGxDqBueo/74E= -go.opentelemetry.io/otel v1.0.1 h1:4XKyXmfqJLOQ7feyV5DB6gsBFZ0ltB8vLtp6pj4JIcc= -go.opentelemetry.io/otel v1.0.1/go.mod h1:OPEOD4jIT2SlZPMmwT6FqZz2C0ZNdQqiWcoK6M0SNFU= -go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.0.1/go.mod h1:Kv8liBeVNFkkkbilbgWRpV+wWuu+H5xdOT6HAgd30iw= -go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.0.1/go.mod h1:xOvWoTOrQjxjW61xtOmD/WKGRYb/P4NzRo3bs65U6Rk= -go.opentelemetry.io/otel/sdk v1.0.1/go.mod h1:HrdXne+BiwsOHYYkBE5ysIcv2bvdZstxzmCQhxTcZkI= -go.opentelemetry.io/otel/trace v1.0.1 h1:StTeIH6Q3G4r0Fiw34LTokUFESZgIDUr0qIJ7mKmAfw= -go.opentelemetry.io/otel/trace v1.0.1/go.mod h1:5g4i4fKLaX2BQpSBsxw8YYcgKpMMSW3x7ZTuYBr3sUk= +go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.26.1 h1:puWrOArBwWlr5dq6vyZ6fKykHyS8JgMIVhTBA8XsGuU= +go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.26.1/go.mod h1:4wsfAAW5N9wUHM0QTmZS8z7fvYZ1rv3m+sVeSpf8NhU= +go.opentelemetry.io/otel v1.1.0/go.mod h1:7cww0OW51jQ8IaZChIEdqLwgh+44+7uiTdWsAL0wQpA= +go.opentelemetry.io/otel v1.2.0 h1:YOQDvxO1FayUcT9MIhJhgMyNO1WqoduiyvQHzGN0kUQ= +go.opentelemetry.io/otel v1.2.0/go.mod h1:aT17Fk0Z1Nor9e0uisf98LrntPGMnk4frBO9+dkf69I= +go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.1.0/go.mod h1:/E4iniSqAEvqbq6KM5qThKZR2sd42kDvD+SrYt00vRw= +go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.1.0/go.mod h1:Gyc0evUosTBVNRqTFGuu0xqebkEWLkLwv42qggTCwro= +go.opentelemetry.io/otel/sdk v1.1.0/go.mod h1:3aQvM6uLm6C4wJpHtT8Od3vNzeZ34Pqc6bps8MywWzo= +go.opentelemetry.io/otel/sdk v1.2.0/go.mod h1:jNN8QtpvbsKhgaC6V5lHiejMoKD+V8uadoSafgHPx1U= +go.opentelemetry.io/otel/trace v1.1.0/go.mod h1:i47XtdcBQiktu5IsrPqOHe8w+sBmnLwwHt8wiUsWGTI= +go.opentelemetry.io/otel/trace v1.2.0 h1:Ys3iqbqZhcf28hHzrm5WAquMkDHNZTUkw7KHbuNjej0= +go.opentelemetry.io/otel/trace v1.2.0/go.mod h1:N5FLswTubnxKxOJHM7XZC074qpeEdLy3CgAVsdMucK0= go.opentelemetry.io/proto/otlp v0.7.0/go.mod h1:PqfVotwruBrMGOCsRd/89rSnXhoiJIqeYNgFYFoEGnI= go.opentelemetry.io/proto/otlp v0.9.0/go.mod h1:1vKfU9rv61e9EVGthD1zNvUbiwPcimSsOPU9brfSHJg= +go.opentelemetry.io/proto/otlp v0.10.0/go.mod h1:zG20xCK0szZ1xdokeSOwEcmlXu+x9kkdRe6N1DhKcfU= go.uber.org/atomic v1.4.0/go.mod h1:gD2HeocX3+yG+ygLZcrzQJaqmWj9AIm7n08wl/qW/PE= go.uber.org/atomic v1.7.0 h1:ADUqmZGgLDDfbSL9ZmPxKTybcoEYHgpYfELNoN+7hsw= go.uber.org/atomic v1.7.0/go.mod h1:fEN4uk6kAWBTFdckzkM89CLk9XfWZrxpCo0nPH17wJc= @@ -342,15 +344,12 @@ golang.org/x/lint v0.0.0-20190313153728-d0100b6bd8b3/go.mod h1:6SW0HCj/g11FgYtHl golang.org/x/lint v0.0.0-20190409202823-959b441ac422/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= golang.org/x/lint v0.0.0-20190909230951-414d861bb4ac/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= golang.org/x/lint v0.0.0-20190930215403-16217165b5de/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= -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-20190719004257-d2bd2a29d028/go.mod h1:E/iHnbuqvinMTCcRqshq8CkpyQDoeVncDDYHnLhea+o= golang.org/x/mod v0.0.0-20190513183733-4bf6d317e70e/go.mod h1:mXi4GBBbnImb6dmsKGUJ2LatrhH/nqhxcFungHvyanc= golang.org/x/mod v0.1.0/go.mod h1:0QHyrYULN0/3qlju5TqG8bIK38QM8yzMo5ekMj3DlcY= -golang.org/x/mod v0.1.1-0.20191105210325-c90efee705ee/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg= 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.4.2/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= 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-20181023162649-9b4f9f5ad519/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= @@ -373,8 +372,8 @@ golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwY golang.org/x/net v0.0.0-20201202161906-c7110b5ffcbb/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= golang.org/x/net v0.0.0-20210405180319-a5a99cb37ef4/go.mod h1:p54w0d4576C0XHj96bSt6lcn1PtDYWL6XObtHCRCNQM= -golang.org/x/net v0.0.0-20210525063256-abc453219eb5 h1:wjuX4b5yYQnEQHzd+CBcrcC6OVR2J1CN6mUy0oSxIPo= -golang.org/x/net v0.0.0-20210525063256-abc453219eb5/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= +golang.org/x/net v0.0.0-20211123203042-d83791d6bcd9 h1:0qxwC5n+ttVOINCBeRHO0nq9X7uy8SDsPoi5OaCdIEI= +golang.org/x/net v0.0.0-20211123203042-d83791d6bcd9/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= 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-20190604053449-0f29369cfe45/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= @@ -388,7 +387,6 @@ golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJ golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/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-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sys v0.0.0-20180823144017-11551d06cbcc/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= @@ -417,16 +415,18 @@ golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7w 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-20210603081109-ebe580a85c40/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20210603125802-9665404d3644 h1:CA1DEQ4NdKphKeL70tvsWNdT5oFh1lOjihRcEDROi0I= golang.org/x/sys v0.0.0-20210603125802-9665404d3644/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20211123173158-ef496fb156ab h1:rfJ1bsoJQQIAoAxTxB7bme+vHrNkRw8CqfsYh9w54cw= +golang.org/x/sys v0.0.0-20211123173158-ef496fb156ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.1-0.20180807135948-17ff2d5776d2/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.2/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.5/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= -golang.org/x/text v0.3.6 h1:aRYxNxv6iGQlyVaZmk6ZgYEDa+Jg18DxebPSrd6bg1M= 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/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-20210220033141-f8bda1e9f3ba h1:O8mE0/t419eoIwhTFpKVkHiTs/Igowgfkj25AcZrtiE= @@ -451,10 +451,8 @@ golang.org/x/tools v0.0.0-20190911174233-4f2ddba30aff/go.mod h1:b+2E5dAYhXwXZwtn golang.org/x/tools v0.0.0-20191012152004-8de300cfc20a/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.0.0-20191112195655-aa38f8e97acc/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= -golang.org/x/tools v0.0.0-20200130002326-2f3ba24bd6e7/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= golang.org/x/tools v0.0.0-20200619180055-7c47624df98f/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= golang.org/x/tools v0.0.0-20210106214847-113979e3529a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= -golang.org/x/tools v0.1.2/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= 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-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= @@ -482,8 +480,8 @@ google.golang.org/genproto v0.0.0-20191108220845-16a3f7862a1a/go.mod h1:n3cpQtvx google.golang.org/genproto v0.0.0-20200423170343-7949de9c1215/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= google.golang.org/genproto v0.0.0-20200513103714-09dca8ec2884/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= google.golang.org/genproto v0.0.0-20200526211855-cb27e3aa2013/go.mod h1:NbSheEEYHJ7i3ixzK3sjbqSGDJWnxyFXZblF3eUsNvo= -google.golang.org/genproto v0.0.0-20210602131652-f16073e35f0c h1:wtujag7C+4D6KMoulW9YauvK2lgdvCMS260jsqqBXr0= -google.golang.org/genproto v0.0.0-20210602131652-f16073e35f0c/go.mod h1:UODoCrxHCcBojKKwX1terBiRUaqAsFqJiF615XL43r0= +google.golang.org/genproto v0.0.0-20211118181313-81c1377c94b1 h1:b9mVrqYfq3P4bCdaLg1qtBnPzUYgglsIdjZkL/fQVOE= +google.golang.org/genproto v0.0.0-20211118181313-81c1377c94b1/go.mod h1:5CzLGKJ67TSI2B9POpiiyGha0AjJvZIUgRMt1dSmuhc= 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.21.1/go.mod h1:oYelfM1adQP15Ek0mdvEgi9Df8B9CZIaU1084ijfRaM= @@ -494,7 +492,6 @@ google.golang.org/grpc v1.29.1/go.mod h1:itym6AZVZYACWQqET3MqgPpjcuV5QH3BxFS3Iji google.golang.org/grpc v1.33.1/go.mod h1:fr5YgcSWrqhRRxogOsw7RzIpsmvOZ6IcH4kBYTpR3n0= google.golang.org/grpc v1.36.0/go.mod h1:qjiiYl8FncCW8feJPdyg3v6XW24KsRHe+dy9BAGRRjU= 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.40.0/go.mod h1:ogyxbiOoUXAkP+4+xa6PZSE9DZgIHtSpzjDTB9KAK34= google.golang.org/grpc v1.41.0 h1:f+PlOh7QV4iIJkPrx5NQ7qaNGFQ3OTse67yaDHfju4E= google.golang.org/grpc v1.41.0/go.mod h1:U3l9uK9J0sini8mHphKoXyaqDA/8VyGnDee1zzIUK6k= diff --git a/go.mod b/go.mod index 0656d079f29b..0c8ef7897fa6 100644 --- a/go.mod +++ b/go.mod @@ -24,12 +24,12 @@ require ( go.etcd.io/etcd/client/pkg/v3 v3.5.0 go.etcd.io/etcd/client/v2 v2.305.0 go.etcd.io/etcd/client/v3 v3.5.0 - go.etcd.io/etcd/etcdctl/v3 v3.5.0 + go.etcd.io/etcd/etcdctl/v3 v3.0.0-00010101000000-000000000000 go.etcd.io/etcd/etcdutl/v3 v3.5.0 go.etcd.io/etcd/pkg/v3 v3.5.0 go.etcd.io/etcd/raft/v3 v3.5.0 go.etcd.io/etcd/server/v3 v3.5.0 - go.etcd.io/etcd/tests/v3 v3.5.0 + go.etcd.io/etcd/tests/v3 v3.0.0-00010101000000-000000000000 go.uber.org/zap v1.17.0 golang.org/x/time v0.0.0-20210220033141-f8bda1e9f3ba google.golang.org/grpc v1.41.0 @@ -68,20 +68,20 @@ require ( github.com/stretchr/testify v1.7.0 // indirect github.com/tmc/grpc-websocket-proxy v0.0.0-20201229170055-e5319fda7802 // indirect github.com/xiang90/probing v0.0.0-20190116061207-43a291ad63a2 // indirect - go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.25.0 // indirect - go.opentelemetry.io/otel v1.0.1 // indirect - go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.0.1 // indirect - go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.0.1 // indirect - go.opentelemetry.io/otel/sdk v1.0.1 // indirect - go.opentelemetry.io/otel/trace v1.0.1 // indirect - go.opentelemetry.io/proto/otlp v0.9.0 // indirect + go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.26.1 // indirect + go.opentelemetry.io/otel v1.2.0 // indirect + go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.1.0 // indirect + go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.1.0 // indirect + go.opentelemetry.io/otel/sdk v1.2.0 // indirect + go.opentelemetry.io/otel/trace v1.2.0 // indirect + go.opentelemetry.io/proto/otlp v0.10.0 // indirect go.uber.org/atomic v1.7.0 // indirect go.uber.org/multierr v1.7.0 // indirect golang.org/x/crypto v0.0.0-20210513164829-c07d793c2f9a // indirect - golang.org/x/net v0.0.0-20210525063256-abc453219eb5 // indirect - golang.org/x/sys v0.0.0-20210603125802-9665404d3644 // indirect - golang.org/x/text v0.3.6 // indirect - google.golang.org/genproto v0.0.0-20210602131652-f16073e35f0c // indirect + golang.org/x/net v0.0.0-20211123203042-d83791d6bcd9 // indirect + golang.org/x/sys v0.0.0-20211123173158-ef496fb156ab // indirect + golang.org/x/text v0.3.7 // indirect + google.golang.org/genproto v0.0.0-20211118181313-81c1377c94b1 // indirect google.golang.org/protobuf v1.27.1 // indirect gopkg.in/natefinch/lumberjack.v2 v2.0.0 // indirect gopkg.in/yaml.v2 v2.4.0 // indirect diff --git a/go.sum b/go.sum index ae3b058bda29..5b24ff5fd3f7 100644 --- a/go.sum +++ b/go.sum @@ -123,7 +123,6 @@ github.com/golang/protobuf v1.4.1/go.mod h1:U8fpvMrcmy5pZrNK1lt4xCsGvpyWQ/VVv6QD github.com/golang/protobuf v1.4.2/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI= github.com/golang/protobuf v1.4.3/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI= 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/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY= github.com/google/btree v0.0.0-20180813153112-4030bb1f1f0c/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ= @@ -309,27 +308,30 @@ github.com/xiang90/probing v0.0.0-20190116061207-43a291ad63a2 h1:eY9dn8+vbi4tKz5 github.com/xiang90/probing v0.0.0-20190116061207-43a291ad63a2/go.mod h1:UETIi67q53MR2AWcXfiuqkDkRtnGDLqkBTpCHuJHxtU= github.com/yuin/goldmark v1.1.27/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= go.etcd.io/bbolt v1.3.2/go.mod h1:IbVyRI1SCnLcuJnV2u8VeU0CEYM7e686BmAb1XKL+uU= go.etcd.io/bbolt v1.3.6 h1:/ecaJf0sk1l4l6V4awd65v2C3ILy7MSj+s/x1ADCIMU= go.etcd.io/bbolt v1.3.6/go.mod h1:qXsaaIqmgQH0T+OPdb99Bf+PKfBBQVAdyD6TY9G8XM4= go.opencensus.io v0.21.0/go.mod h1:mSImk1erAIZhrmZN+AvHh14ztQfjbGwt4TtuofqLduU= go.opencensus.io v0.22.0/go.mod h1:+kGneAE2xo2IficOXnaByMWTGM9T73dGwxeWcUqIpI8= -go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.25.0 h1:Wx7nFnvCaissIUZxPkBqDz2963Z+Cl+PkYbDKzTxDqQ= -go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.25.0/go.mod h1:E5NNboN0UqSAki0Atn9kVwaN7I+l25gGxDqBueo/74E= -go.opentelemetry.io/otel v1.0.1 h1:4XKyXmfqJLOQ7feyV5DB6gsBFZ0ltB8vLtp6pj4JIcc= -go.opentelemetry.io/otel v1.0.1/go.mod h1:OPEOD4jIT2SlZPMmwT6FqZz2C0ZNdQqiWcoK6M0SNFU= -go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.0.1 h1:ofMbch7i29qIUf7VtF+r0HRF6ac0SBaPSziSsKp7wkk= -go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.0.1/go.mod h1:Kv8liBeVNFkkkbilbgWRpV+wWuu+H5xdOT6HAgd30iw= -go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.0.1 h1:CFMFNoz+CGprjFAFy+RJFrfEe4GBia3RRm2a4fREvCA= -go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.0.1/go.mod h1:xOvWoTOrQjxjW61xtOmD/WKGRYb/P4NzRo3bs65U6Rk= -go.opentelemetry.io/otel/sdk v1.0.1 h1:wXxFEWGo7XfXupPwVJvTBOaPBC9FEg0wB8hMNrKk+cA= -go.opentelemetry.io/otel/sdk v1.0.1/go.mod h1:HrdXne+BiwsOHYYkBE5ysIcv2bvdZstxzmCQhxTcZkI= -go.opentelemetry.io/otel/trace v1.0.1 h1:StTeIH6Q3G4r0Fiw34LTokUFESZgIDUr0qIJ7mKmAfw= -go.opentelemetry.io/otel/trace v1.0.1/go.mod h1:5g4i4fKLaX2BQpSBsxw8YYcgKpMMSW3x7ZTuYBr3sUk= +go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.26.1 h1:puWrOArBwWlr5dq6vyZ6fKykHyS8JgMIVhTBA8XsGuU= +go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.26.1/go.mod h1:4wsfAAW5N9wUHM0QTmZS8z7fvYZ1rv3m+sVeSpf8NhU= +go.opentelemetry.io/otel v1.1.0/go.mod h1:7cww0OW51jQ8IaZChIEdqLwgh+44+7uiTdWsAL0wQpA= +go.opentelemetry.io/otel v1.2.0 h1:YOQDvxO1FayUcT9MIhJhgMyNO1WqoduiyvQHzGN0kUQ= +go.opentelemetry.io/otel v1.2.0/go.mod h1:aT17Fk0Z1Nor9e0uisf98LrntPGMnk4frBO9+dkf69I= +go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.1.0 h1:PxBRMkrJnY4HRgToPzoLrTdQDHQf9MeFg5oGzTqtzco= +go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.1.0/go.mod h1:/E4iniSqAEvqbq6KM5qThKZR2sd42kDvD+SrYt00vRw= +go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.1.0 h1:4UC7muAl2UqSoTV0RqgmpTz/cRLH6R9cHt9BvVcq5Bo= +go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.1.0/go.mod h1:Gyc0evUosTBVNRqTFGuu0xqebkEWLkLwv42qggTCwro= +go.opentelemetry.io/otel/sdk v1.1.0/go.mod h1:3aQvM6uLm6C4wJpHtT8Od3vNzeZ34Pqc6bps8MywWzo= +go.opentelemetry.io/otel/sdk v1.2.0 h1:wKN260u4DesJYhyjxDa7LRFkuhH7ncEVKU37LWcyNIo= +go.opentelemetry.io/otel/sdk v1.2.0/go.mod h1:jNN8QtpvbsKhgaC6V5lHiejMoKD+V8uadoSafgHPx1U= +go.opentelemetry.io/otel/trace v1.1.0/go.mod h1:i47XtdcBQiktu5IsrPqOHe8w+sBmnLwwHt8wiUsWGTI= +go.opentelemetry.io/otel/trace v1.2.0 h1:Ys3iqbqZhcf28hHzrm5WAquMkDHNZTUkw7KHbuNjej0= +go.opentelemetry.io/otel/trace v1.2.0/go.mod h1:N5FLswTubnxKxOJHM7XZC074qpeEdLy3CgAVsdMucK0= go.opentelemetry.io/proto/otlp v0.7.0/go.mod h1:PqfVotwruBrMGOCsRd/89rSnXhoiJIqeYNgFYFoEGnI= -go.opentelemetry.io/proto/otlp v0.9.0 h1:C0g6TWmQYvjKRnljRULLWUVJGy8Uvu0NEL/5frY2/t4= go.opentelemetry.io/proto/otlp v0.9.0/go.mod h1:1vKfU9rv61e9EVGthD1zNvUbiwPcimSsOPU9brfSHJg= +go.opentelemetry.io/proto/otlp v0.10.0 h1:n7brgtEbDvXEgGyKKo8SobKT1e9FewlDtXzkVP5djoE= +go.opentelemetry.io/proto/otlp v0.10.0/go.mod h1:zG20xCK0szZ1xdokeSOwEcmlXu+x9kkdRe6N1DhKcfU= go.uber.org/atomic v1.4.0/go.mod h1:gD2HeocX3+yG+ygLZcrzQJaqmWj9AIm7n08wl/qW/PE= go.uber.org/atomic v1.7.0 h1:ADUqmZGgLDDfbSL9ZmPxKTybcoEYHgpYfELNoN+7hsw= go.uber.org/atomic v1.7.0/go.mod h1:fEN4uk6kAWBTFdckzkM89CLk9XfWZrxpCo0nPH17wJc= @@ -363,15 +365,12 @@ golang.org/x/lint v0.0.0-20190313153728-d0100b6bd8b3/go.mod h1:6SW0HCj/g11FgYtHl golang.org/x/lint v0.0.0-20190409202823-959b441ac422/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= golang.org/x/lint v0.0.0-20190909230951-414d861bb4ac/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= golang.org/x/lint v0.0.0-20190930215403-16217165b5de/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= -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-20190719004257-d2bd2a29d028/go.mod h1:E/iHnbuqvinMTCcRqshq8CkpyQDoeVncDDYHnLhea+o= golang.org/x/mod v0.0.0-20190513183733-4bf6d317e70e/go.mod h1:mXi4GBBbnImb6dmsKGUJ2LatrhH/nqhxcFungHvyanc= golang.org/x/mod v0.1.0/go.mod h1:0QHyrYULN0/3qlju5TqG8bIK38QM8yzMo5ekMj3DlcY= -golang.org/x/mod v0.1.1-0.20191105210325-c90efee705ee/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg= 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.4.2/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= 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-20181023162649-9b4f9f5ad519/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= @@ -394,8 +393,8 @@ golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwY golang.org/x/net v0.0.0-20201202161906-c7110b5ffcbb/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= golang.org/x/net v0.0.0-20210405180319-a5a99cb37ef4/go.mod h1:p54w0d4576C0XHj96bSt6lcn1PtDYWL6XObtHCRCNQM= -golang.org/x/net v0.0.0-20210525063256-abc453219eb5 h1:wjuX4b5yYQnEQHzd+CBcrcC6OVR2J1CN6mUy0oSxIPo= -golang.org/x/net v0.0.0-20210525063256-abc453219eb5/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= +golang.org/x/net v0.0.0-20211123203042-d83791d6bcd9 h1:0qxwC5n+ttVOINCBeRHO0nq9X7uy8SDsPoi5OaCdIEI= +golang.org/x/net v0.0.0-20211123203042-d83791d6bcd9/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= 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-20190604053449-0f29369cfe45/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= @@ -439,16 +438,18 @@ golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7w 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-20210603081109-ebe580a85c40/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20210603125802-9665404d3644 h1:CA1DEQ4NdKphKeL70tvsWNdT5oFh1lOjihRcEDROi0I= golang.org/x/sys v0.0.0-20210603125802-9665404d3644/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20211123173158-ef496fb156ab h1:rfJ1bsoJQQIAoAxTxB7bme+vHrNkRw8CqfsYh9w54cw= +golang.org/x/sys v0.0.0-20211123173158-ef496fb156ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.1-0.20180807135948-17ff2d5776d2/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.2/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.5/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= -golang.org/x/text v0.3.6 h1:aRYxNxv6iGQlyVaZmk6ZgYEDa+Jg18DxebPSrd6bg1M= 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/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-20210220033141-f8bda1e9f3ba h1:O8mE0/t419eoIwhTFpKVkHiTs/Igowgfkj25AcZrtiE= @@ -473,10 +474,8 @@ golang.org/x/tools v0.0.0-20190911174233-4f2ddba30aff/go.mod h1:b+2E5dAYhXwXZwtn golang.org/x/tools v0.0.0-20191012152004-8de300cfc20a/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.0.0-20191112195655-aa38f8e97acc/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= -golang.org/x/tools v0.0.0-20200130002326-2f3ba24bd6e7/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= golang.org/x/tools v0.0.0-20200619180055-7c47624df98f/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= golang.org/x/tools v0.0.0-20210106214847-113979e3529a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= -golang.org/x/tools v0.1.2/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= 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-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= @@ -504,8 +503,8 @@ google.golang.org/genproto v0.0.0-20191108220845-16a3f7862a1a/go.mod h1:n3cpQtvx google.golang.org/genproto v0.0.0-20200423170343-7949de9c1215/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= google.golang.org/genproto v0.0.0-20200513103714-09dca8ec2884/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= google.golang.org/genproto v0.0.0-20200526211855-cb27e3aa2013/go.mod h1:NbSheEEYHJ7i3ixzK3sjbqSGDJWnxyFXZblF3eUsNvo= -google.golang.org/genproto v0.0.0-20210602131652-f16073e35f0c h1:wtujag7C+4D6KMoulW9YauvK2lgdvCMS260jsqqBXr0= -google.golang.org/genproto v0.0.0-20210602131652-f16073e35f0c/go.mod h1:UODoCrxHCcBojKKwX1terBiRUaqAsFqJiF615XL43r0= +google.golang.org/genproto v0.0.0-20211118181313-81c1377c94b1 h1:b9mVrqYfq3P4bCdaLg1qtBnPzUYgglsIdjZkL/fQVOE= +google.golang.org/genproto v0.0.0-20211118181313-81c1377c94b1/go.mod h1:5CzLGKJ67TSI2B9POpiiyGha0AjJvZIUgRMt1dSmuhc= 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.21.1/go.mod h1:oYelfM1adQP15Ek0mdvEgi9Df8B9CZIaU1084ijfRaM= @@ -516,7 +515,6 @@ google.golang.org/grpc v1.29.1/go.mod h1:itym6AZVZYACWQqET3MqgPpjcuV5QH3BxFS3Iji google.golang.org/grpc v1.33.1/go.mod h1:fr5YgcSWrqhRRxogOsw7RzIpsmvOZ6IcH4kBYTpR3n0= google.golang.org/grpc v1.36.0/go.mod h1:qjiiYl8FncCW8feJPdyg3v6XW24KsRHe+dy9BAGRRjU= 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.40.0/go.mod h1:ogyxbiOoUXAkP+4+xa6PZSE9DZgIHtSpzjDTB9KAK34= google.golang.org/grpc v1.41.0 h1:f+PlOh7QV4iIJkPrx5NQ7qaNGFQ3OTse67yaDHfju4E= google.golang.org/grpc v1.41.0/go.mod h1:U3l9uK9J0sini8mHphKoXyaqDA/8VyGnDee1zzIUK6k= diff --git a/pkg/go.mod b/pkg/go.mod index 86c8a98f51ef..35c24342a97d 100644 --- a/pkg/go.mod +++ b/pkg/go.mod @@ -5,7 +5,7 @@ go 1.17 require ( github.com/creack/pty v1.1.11 github.com/dustin/go-humanize v1.0.0 - github.com/golang/protobuf v1.5.1 // indirect + github.com/golang/protobuf v1.5.2 // indirect github.com/spf13/cobra v1.1.3 github.com/spf13/pflag v1.0.5 github.com/stretchr/testify v1.7.0 @@ -20,11 +20,11 @@ require ( github.com/pmezard/go-difflib v1.0.0 // indirect go.uber.org/atomic v1.7.0 // indirect go.uber.org/multierr v1.6.0 // indirect - golang.org/x/net v0.0.0-20200822124328-c89045814202 // indirect + golang.org/x/net v0.0.0-20210405180319-a5a99cb37ef4 // indirect golang.org/x/sys v0.0.0-20210603125802-9665404d3644 // indirect - golang.org/x/text v0.3.2 // indirect - google.golang.org/genproto v0.0.0-20200526211855-cb27e3aa2013 // indirect - google.golang.org/protobuf v1.26.0 // indirect + golang.org/x/text v0.3.5 // indirect + google.golang.org/genproto v0.0.0-20211118181313-81c1377c94b1 // indirect + google.golang.org/protobuf v1.27.1 // indirect gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b // indirect ) diff --git a/pkg/go.sum b/pkg/go.sum index 8d29dd4682e4..a8edcc41fe67 100644 --- a/pkg/go.sum +++ b/pkg/go.sum @@ -30,6 +30,7 @@ github.com/cespare/xxhash/v2 v2.1.1/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XL github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw= github.com/cncf/udpa/go v0.0.0-20191209042840-269d4d468f6f/go.mod h1:M8M6+tZqaGXZJjfX53e64911xZQV5JYwmTeXPW+k8Sc= github.com/cncf/udpa/go v0.0.0-20201120205902-5459f2c99403/go.mod h1:WmhPx2Nbnhtbo57+VJT5O0JRkEi1Wbu0z5j0R8u5Hbk= +github.com/cncf/xds/go v0.0.0-20210312221358-fbca930ec8ed/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs= github.com/cncf/xds/go v0.0.0-20210805033703-aa0b78936158/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs= github.com/coreos/bbolt v1.3.2/go.mod h1:iRUV2dpdMOn7Bo10OQBFzIJO9kkE559Wcmn+qkEiiKk= github.com/coreos/etcd v3.3.13+incompatible/go.mod h1:uF7uidLiAD3TWHmW31ZFd/JWoc32PjwdhPthX9715RE= @@ -51,6 +52,7 @@ github.com/envoyproxy/go-control-plane v0.9.0/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymF 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.9-0.20201210154907-fd9021fe5dad/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.10-0.20210907150352-cf90f659a021/go.mod h1:AFq3mo9L8Lqqiid3OhADV3RfLJnjiw63cSpi+fDTRC0= github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c= github.com/fatih/color v1.7.0/go.mod h1:Zm6kSWBoL9eyXnKyktHP6abPY2pDugNf5KwzbycvMj4= @@ -82,8 +84,8 @@ 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.3/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI= github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk= -github.com/golang/protobuf v1.5.1 h1:jAbXjIeW2ZSW2AwFxlGTDoc2CjI2XujLkV3ArsZFCvc= -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/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY= github.com/google/btree v0.0.0-20180813153112-4030bb1f1f0c/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ= github.com/google/btree v1.0.0/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ= github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M= @@ -259,8 +261,9 @@ golang.org/x/net v0.0.0-20190501004415-9ce7a6920f09/go.mod h1:t9HGtf8HONx5eT2rtn golang.org/x/net v0.0.0-20190503192946-f4e77d36d62c/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= golang.org/x/net v0.0.0-20190603091049-60506f45cf65/go.mod h1:HSz+uSET+XFnRR8LxR5pz3Of3rY3CfYBVs4xY44aLks= golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= -golang.org/x/net v0.0.0-20200822124328-c89045814202 h1:VvcQYSHwXgi7W+TpUR6A9g6Up98WAHf3f/ulnJ62IyA= golang.org/x/net v0.0.0-20200822124328-c89045814202/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA= +golang.org/x/net v0.0.0-20210405180319-a5a99cb37ef4 h1:4nGaVu0QrbjT/AK2PRLuQfQuh6DJve+pELhqTdAj3x0= +golang.org/x/net v0.0.0-20210405180319-a5a99cb37ef4/go.mod h1:p54w0d4576C0XHj96bSt6lcn1PtDYWL6XObtHCRCNQM= 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-20190604053449-0f29369cfe45/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= @@ -284,12 +287,18 @@ golang.org/x/sys v0.0.0-20190507160741-ecd444e8653b/go.mod h1:h1NjWce9XRLGQEsW7w golang.org/x/sys v0.0.0-20190606165138-5da285871e9c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190624142023-c5567b49c5d0/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210330210617-4fbd30eecc44/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-20210603125802-9665404d3644 h1:CA1DEQ4NdKphKeL70tvsWNdT5oFh1lOjihRcEDROi0I= golang.org/x/sys v0.0.0-20210603125802-9665404d3644/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.1-0.20180807135948-17ff2d5776d2/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= -golang.org/x/text v0.3.2 h1:tW2bmiBqwgJj/UpqtC8EpXEZVYOwU0yG4iWbprSVAcs= golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk= +golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= +golang.org/x/text v0.3.5 h1:i6eZZ+zk0SOf0xgBpEpPD18qWcJda6q1sxt3S0kzyUQ= +golang.org/x/text v0.3.5/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/tools v0.0.0-20180221164845-07fd8470d635/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= @@ -333,8 +342,9 @@ google.golang.org/genproto v0.0.0-20190819201941-24fa4b261c55/go.mod h1:DMBHOl98 google.golang.org/genproto v0.0.0-20190911173649-1774047e7e51/go.mod h1:IbNlFCBrqXvoKpeg0TB2l7cyZUmoaFKYIwrEpbDKLA8= google.golang.org/genproto v0.0.0-20191108220845-16a3f7862a1a/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= google.golang.org/genproto v0.0.0-20200513103714-09dca8ec2884/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= -google.golang.org/genproto v0.0.0-20200526211855-cb27e3aa2013 h1:+kGHl1aib/qcwaRi1CbqBZ1rk19r85MNUf8HaBghugY= google.golang.org/genproto v0.0.0-20200526211855-cb27e3aa2013/go.mod h1:NbSheEEYHJ7i3ixzK3sjbqSGDJWnxyFXZblF3eUsNvo= +google.golang.org/genproto v0.0.0-20211118181313-81c1377c94b1 h1:b9mVrqYfq3P4bCdaLg1qtBnPzUYgglsIdjZkL/fQVOE= +google.golang.org/genproto v0.0.0-20211118181313-81c1377c94b1/go.mod h1:5CzLGKJ67TSI2B9POpiiyGha0AjJvZIUgRMt1dSmuhc= 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.21.1/go.mod h1:oYelfM1adQP15Ek0mdvEgi9Df8B9CZIaU1084ijfRaM= @@ -343,6 +353,7 @@ google.golang.org/grpc v1.25.1/go.mod h1:c3i+UQWmh7LiEpx4sFZnkU36qjEYZ0imhYfXVyQ google.golang.org/grpc v1.27.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk= google.golang.org/grpc v1.33.1/go.mod h1:fr5YgcSWrqhRRxogOsw7RzIpsmvOZ6IcH4kBYTpR3n0= google.golang.org/grpc v1.36.0/go.mod h1:qjiiYl8FncCW8feJPdyg3v6XW24KsRHe+dy9BAGRRjU= +google.golang.org/grpc v1.40.0/go.mod h1:ogyxbiOoUXAkP+4+xa6PZSE9DZgIHtSpzjDTB9KAK34= google.golang.org/grpc v1.41.0 h1:f+PlOh7QV4iIJkPrx5NQ7qaNGFQ3OTse67yaDHfju4E= google.golang.org/grpc v1.41.0/go.mod h1:U3l9uK9J0sini8mHphKoXyaqDA/8VyGnDee1zzIUK6k= google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8= @@ -355,8 +366,9 @@ google.golang.org/protobuf v1.23.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2 google.golang.org/protobuf v1.23.1-0.20200526195155-81db48ad09cc/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= google.golang.org/protobuf v1.25.0/go.mod h1:9JNX74DMeImyA3h4bdi1ymwjUzf21/xIlbajtzgsN7c= google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw= -google.golang.org/protobuf v1.26.0 h1:bxAC2xTBsZGibn2RTntX0oH50xLsqy1OxA9tTL3p/lk= google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc= +google.golang.org/protobuf v1.27.1 h1:SnqbnDw1V7RiZcXPx5MEeqPv2s79L9i7BJUlG/+RurQ= +google.golang.org/protobuf v1.27.1/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc= gopkg.in/alecthomas/kingpin.v2 v2.2.6/go.mod h1:FMv+mEhP44yOT+4EoQTLFTRgOQ1FBLkstjWtayDeSgw= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127 h1:qIbj1fsPNlZgppZ+VLlY7N33q108Sa+fhmuc+sWQYwY= diff --git a/raft/go.mod b/raft/go.mod index fca4a99c92c0..10fb463ac37c 100644 --- a/raft/go.mod +++ b/raft/go.mod @@ -19,7 +19,7 @@ require ( github.com/getsentry/raven-go v0.2.0 // indirect github.com/pmezard/go-difflib v1.0.0 // indirect github.com/stretchr/testify v1.7.0 // indirect - google.golang.org/protobuf v1.26.0 // indirect + google.golang.org/protobuf v1.27.1 // indirect gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b // indirect ) diff --git a/raft/go.sum b/raft/go.sum index 306f6e6da0f8..8612475354c7 100644 --- a/raft/go.sum +++ b/raft/go.sum @@ -1,15 +1,18 @@ cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= cloud.google.com/go v0.34.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= +github.com/OneOfOne/xxhash v1.2.2/go.mod h1:HSdplMjZKSmBqAxg5vPj2TmRDmfkzw+cTzAElWljhcU= github.com/antihax/optional v1.0.0/go.mod h1:uupD/76wgC+ih3iEmQUL+0Ugr19nfwCT1kdvxnR2qWY= github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU= github.com/certifi/gocertifi v0.0.0-20191021191039-0944d244cd40/go.mod h1:sGbDF6GwGcLpkNXPUTkMRoywsNa/ol15pxFe6ERfguA= github.com/certifi/gocertifi v0.0.0-20200922220541-2c3bb06c6054 h1:uH66TXeswKn5PW5zdZ39xEwfS9an067BirqA+P4QaLI= github.com/certifi/gocertifi v0.0.0-20200922220541-2c3bb06c6054/go.mod h1:sGbDF6GwGcLpkNXPUTkMRoywsNa/ol15pxFe6ERfguA= +github.com/cespare/xxhash v1.1.0/go.mod h1:XrSqR1VqqWfGrhpAt58auRo0WTKS1nRRg3ghfAqPWnc= github.com/cespare/xxhash/v2 v2.1.1/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw= github.com/cncf/udpa/go v0.0.0-20191209042840-269d4d468f6f/go.mod h1:M8M6+tZqaGXZJjfX53e64911xZQV5JYwmTeXPW+k8Sc= github.com/cncf/udpa/go v0.0.0-20201120205902-5459f2c99403/go.mod h1:WmhPx2Nbnhtbo57+VJT5O0JRkEi1Wbu0z5j0R8u5Hbk= +github.com/cncf/xds/go v0.0.0-20210312221358-fbca930ec8ed/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs= github.com/cncf/xds/go v0.0.0-20210805033703-aa0b78936158/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs= github.com/cockroachdb/datadriven v0.0.0-20200714090401-bf6692d28da5 h1:xD/lrqdvwsc+O2bjSSi3YqY73Ke3LAiSCx49aCesA0E= github.com/cockroachdb/datadriven v0.0.0-20200714090401-bf6692d28da5/go.mod h1:h6jFvWxBdQXxjopDMZyH2UVceIRfR84bdzbkoKrsWNo= @@ -26,7 +29,7 @@ github.com/envoyproxy/go-control-plane v0.9.0/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymF 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.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.20210512163311-63b5d3c536b0/go.mod h1:hliV/p42l8fGbc6Y9bQ70uLwIvmJyVE5k4iMKlh8wCQ= github.com/envoyproxy/go-control-plane v0.9.10-0.20210907150352-cf90f659a021/go.mod h1:AFq3mo9L8Lqqiid3OhADV3RfLJnjiw63cSpi+fDTRC0= github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c= github.com/getsentry/raven-go v0.2.0 h1:no+xWJRb5ZI7eE8TWgIq1jLulQiIoLG0IfYxv5JYMGs= @@ -76,6 +79,7 @@ github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZb github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= github.com/rogpeppe/fastuuid v1.2.0/go.mod h1:jVj6XXZzXRy/MSR5jhDC/2q6DgLz+nrA6LYCDYWNEvQ= +github.com/spaolacci/murmur3 v0.0.0-20180118202830-f09979ecbc72/go.mod h1:JwIasOWyU6f++ZhiEuf87xNszmSA2myDM2Kzu9HwQUA= github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA= @@ -83,7 +87,6 @@ github.com/stretchr/testify v1.7.0 h1:nwc3DEeHmmLAfoZucVR881uASk0Mfjw8xYJ99tb5Cc github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/yuin/goldmark v1.1.27/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= go.opentelemetry.io/proto/otlp v0.7.0/go.mod h1:PqfVotwruBrMGOCsRd/89rSnXhoiJIqeYNgFYFoEGnI= go.uber.org/atomic v1.7.0/go.mod h1:fEN4uk6kAWBTFdckzkM89CLk9XfWZrxpCo0nPH17wJc= go.uber.org/multierr v1.6.0/go.mod h1:cdWPpRnG4AhwMwsgIHip0KRBQjJy5kYEpYjJxpXp9iU= @@ -95,11 +98,8 @@ golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE= golang.org/x/lint v0.0.0-20190227174305-5b3e6a55c961/go.mod h1:wehouNa3lNwaWXcvxsM5YxQ5yQlVC4a0KAMCusXpPoU= golang.org/x/lint v0.0.0-20190313153728-d0100b6bd8b3/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= -golang.org/x/lint v0.0.0-20210508222113-6edffad5e616/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY= -golang.org/x/mod v0.1.1-0.20191105210325-c90efee705ee/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg= 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.4.2/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= 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-20190108225652-1e06a53dbb7e/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= @@ -119,7 +119,6 @@ golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJ golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/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-20210220032951-036812b2e83c/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-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= @@ -140,10 +139,8 @@ golang.org/x/tools v0.0.0-20190226205152-f727befe758c/go.mod h1:9Yl7xja0Znq3iFh3 golang.org/x/tools v0.0.0-20190311212946-11955173bddd/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= golang.org/x/tools v0.0.0-20190524140312-2c0ae7006135/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q= golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= -golang.org/x/tools v0.0.0-20200130002326-2f3ba24bd6e7/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= golang.org/x/tools v0.0.0-20200619180055-7c47624df98f/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= golang.org/x/tools v0.0.0-20210106214847-113979e3529a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= -golang.org/x/tools v0.1.2/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= 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-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= @@ -155,14 +152,14 @@ google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8/go.mod h1:JiN7NxoA google.golang.org/genproto v0.0.0-20190819201941-24fa4b261c55/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc= google.golang.org/genproto v0.0.0-20200513103714-09dca8ec2884/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= google.golang.org/genproto v0.0.0-20200526211855-cb27e3aa2013/go.mod h1:NbSheEEYHJ7i3ixzK3sjbqSGDJWnxyFXZblF3eUsNvo= -google.golang.org/genproto v0.0.0-20210602131652-f16073e35f0c/go.mod h1:UODoCrxHCcBojKKwX1terBiRUaqAsFqJiF615XL43r0= +google.golang.org/genproto v0.0.0-20211118181313-81c1377c94b1/go.mod h1:5CzLGKJ67TSI2B9POpiiyGha0AjJvZIUgRMt1dSmuhc= google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c= google.golang.org/grpc v1.23.0/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg= google.golang.org/grpc v1.25.1/go.mod h1:c3i+UQWmh7LiEpx4sFZnkU36qjEYZ0imhYfXVyQciAY= google.golang.org/grpc v1.27.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk= google.golang.org/grpc v1.33.1/go.mod h1:fr5YgcSWrqhRRxogOsw7RzIpsmvOZ6IcH4kBYTpR3n0= google.golang.org/grpc v1.36.0/go.mod h1:qjiiYl8FncCW8feJPdyg3v6XW24KsRHe+dy9BAGRRjU= -google.golang.org/grpc v1.38.0/go.mod h1:NREThFqKR1f3iQ6oBuvc5LadQuXVGo9rkm5ZGrQdJfM= +google.golang.org/grpc v1.40.0/go.mod h1:ogyxbiOoUXAkP+4+xa6PZSE9DZgIHtSpzjDTB9KAK34= google.golang.org/grpc v1.41.0/go.mod h1:U3l9uK9J0sini8mHphKoXyaqDA/8VyGnDee1zzIUK6k= 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= @@ -174,8 +171,9 @@ google.golang.org/protobuf v1.23.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2 google.golang.org/protobuf v1.23.1-0.20200526195155-81db48ad09cc/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= google.golang.org/protobuf v1.25.0/go.mod h1:9JNX74DMeImyA3h4bdi1ymwjUzf21/xIlbajtzgsN7c= google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw= -google.golang.org/protobuf v1.26.0 h1:bxAC2xTBsZGibn2RTntX0oH50xLsqy1OxA9tTL3p/lk= google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc= +google.golang.org/protobuf v1.27.1 h1:SnqbnDw1V7RiZcXPx5MEeqPv2s79L9i7BJUlG/+RurQ= +google.golang.org/protobuf v1.27.1/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= diff --git a/server/go.mod b/server/go.mod index bcd07353d251..79941642cd01 100644 --- a/server/go.mod +++ b/server/go.mod @@ -29,16 +29,16 @@ require ( go.etcd.io/etcd/client/v3 v3.5.0 go.etcd.io/etcd/pkg/v3 v3.5.0 go.etcd.io/etcd/raft/v3 v3.5.0 - go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.25.0 - go.opentelemetry.io/otel v1.0.1 - go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.0.1 - go.opentelemetry.io/otel/sdk v1.0.1 + go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.26.1 + go.opentelemetry.io/otel v1.2.0 + go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.1.0 + go.opentelemetry.io/otel/sdk v1.2.0 go.uber.org/multierr v1.7.0 go.uber.org/zap v1.17.0 golang.org/x/crypto v0.0.0-20210513164829-c07d793c2f9a - golang.org/x/net v0.0.0-20210525063256-abc453219eb5 + golang.org/x/net v0.0.0-20211123203042-d83791d6bcd9 golang.org/x/time v0.0.0-20210220033141-f8bda1e9f3ba - google.golang.org/genproto v0.0.0-20210602131652-f16073e35f0c + google.golang.org/genproto v0.0.0-20211118181313-81c1377c94b1 google.golang.org/grpc v1.41.0 google.golang.org/protobuf v1.27.1 gopkg.in/natefinch/lumberjack.v2 v2.0.0 @@ -59,12 +59,12 @@ require ( github.com/prometheus/procfs v0.6.0 // indirect github.com/sirupsen/logrus v1.8.1 // indirect github.com/spf13/pflag v1.0.5 // indirect - go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.0.1 // indirect - go.opentelemetry.io/otel/trace v1.0.1 // indirect - go.opentelemetry.io/proto/otlp v0.9.0 // indirect + go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.1.0 // indirect + go.opentelemetry.io/otel/trace v1.2.0 // indirect + go.opentelemetry.io/proto/otlp v0.10.0 // indirect go.uber.org/atomic v1.7.0 // indirect - golang.org/x/sys v0.0.0-20210603125802-9665404d3644 // indirect - golang.org/x/text v0.3.6 // indirect + golang.org/x/sys v0.0.0-20211123173158-ef496fb156ab // indirect + golang.org/x/text v0.3.7 // indirect gopkg.in/yaml.v2 v2.4.0 // indirect gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b // indirect sigs.k8s.io/json v0.0.0-20211020170558-c049b76a60c6 // indirect diff --git a/server/go.sum b/server/go.sum index b3ddb8f5b931..914b7082fcdb 100644 --- a/server/go.sum +++ b/server/go.sum @@ -120,7 +120,6 @@ github.com/golang/protobuf v1.4.1/go.mod h1:U8fpvMrcmy5pZrNK1lt4xCsGvpyWQ/VVv6QD github.com/golang/protobuf v1.4.2/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI= github.com/golang/protobuf v1.4.3/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI= 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/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY= github.com/google/btree v0.0.0-20180813153112-4030bb1f1f0c/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ= @@ -299,27 +298,30 @@ github.com/xiang90/probing v0.0.0-20190116061207-43a291ad63a2 h1:eY9dn8+vbi4tKz5 github.com/xiang90/probing v0.0.0-20190116061207-43a291ad63a2/go.mod h1:UETIi67q53MR2AWcXfiuqkDkRtnGDLqkBTpCHuJHxtU= github.com/yuin/goldmark v1.1.27/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= go.etcd.io/bbolt v1.3.2/go.mod h1:IbVyRI1SCnLcuJnV2u8VeU0CEYM7e686BmAb1XKL+uU= go.etcd.io/bbolt v1.3.6 h1:/ecaJf0sk1l4l6V4awd65v2C3ILy7MSj+s/x1ADCIMU= go.etcd.io/bbolt v1.3.6/go.mod h1:qXsaaIqmgQH0T+OPdb99Bf+PKfBBQVAdyD6TY9G8XM4= go.opencensus.io v0.21.0/go.mod h1:mSImk1erAIZhrmZN+AvHh14ztQfjbGwt4TtuofqLduU= go.opencensus.io v0.22.0/go.mod h1:+kGneAE2xo2IficOXnaByMWTGM9T73dGwxeWcUqIpI8= -go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.25.0 h1:Wx7nFnvCaissIUZxPkBqDz2963Z+Cl+PkYbDKzTxDqQ= -go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.25.0/go.mod h1:E5NNboN0UqSAki0Atn9kVwaN7I+l25gGxDqBueo/74E= -go.opentelemetry.io/otel v1.0.1 h1:4XKyXmfqJLOQ7feyV5DB6gsBFZ0ltB8vLtp6pj4JIcc= -go.opentelemetry.io/otel v1.0.1/go.mod h1:OPEOD4jIT2SlZPMmwT6FqZz2C0ZNdQqiWcoK6M0SNFU= -go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.0.1 h1:ofMbch7i29qIUf7VtF+r0HRF6ac0SBaPSziSsKp7wkk= -go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.0.1/go.mod h1:Kv8liBeVNFkkkbilbgWRpV+wWuu+H5xdOT6HAgd30iw= -go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.0.1 h1:CFMFNoz+CGprjFAFy+RJFrfEe4GBia3RRm2a4fREvCA= -go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.0.1/go.mod h1:xOvWoTOrQjxjW61xtOmD/WKGRYb/P4NzRo3bs65U6Rk= -go.opentelemetry.io/otel/sdk v1.0.1 h1:wXxFEWGo7XfXupPwVJvTBOaPBC9FEg0wB8hMNrKk+cA= -go.opentelemetry.io/otel/sdk v1.0.1/go.mod h1:HrdXne+BiwsOHYYkBE5ysIcv2bvdZstxzmCQhxTcZkI= -go.opentelemetry.io/otel/trace v1.0.1 h1:StTeIH6Q3G4r0Fiw34LTokUFESZgIDUr0qIJ7mKmAfw= -go.opentelemetry.io/otel/trace v1.0.1/go.mod h1:5g4i4fKLaX2BQpSBsxw8YYcgKpMMSW3x7ZTuYBr3sUk= +go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.26.1 h1:puWrOArBwWlr5dq6vyZ6fKykHyS8JgMIVhTBA8XsGuU= +go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.26.1/go.mod h1:4wsfAAW5N9wUHM0QTmZS8z7fvYZ1rv3m+sVeSpf8NhU= +go.opentelemetry.io/otel v1.1.0/go.mod h1:7cww0OW51jQ8IaZChIEdqLwgh+44+7uiTdWsAL0wQpA= +go.opentelemetry.io/otel v1.2.0 h1:YOQDvxO1FayUcT9MIhJhgMyNO1WqoduiyvQHzGN0kUQ= +go.opentelemetry.io/otel v1.2.0/go.mod h1:aT17Fk0Z1Nor9e0uisf98LrntPGMnk4frBO9+dkf69I= +go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.1.0 h1:PxBRMkrJnY4HRgToPzoLrTdQDHQf9MeFg5oGzTqtzco= +go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.1.0/go.mod h1:/E4iniSqAEvqbq6KM5qThKZR2sd42kDvD+SrYt00vRw= +go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.1.0 h1:4UC7muAl2UqSoTV0RqgmpTz/cRLH6R9cHt9BvVcq5Bo= +go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.1.0/go.mod h1:Gyc0evUosTBVNRqTFGuu0xqebkEWLkLwv42qggTCwro= +go.opentelemetry.io/otel/sdk v1.1.0/go.mod h1:3aQvM6uLm6C4wJpHtT8Od3vNzeZ34Pqc6bps8MywWzo= +go.opentelemetry.io/otel/sdk v1.2.0 h1:wKN260u4DesJYhyjxDa7LRFkuhH7ncEVKU37LWcyNIo= +go.opentelemetry.io/otel/sdk v1.2.0/go.mod h1:jNN8QtpvbsKhgaC6V5lHiejMoKD+V8uadoSafgHPx1U= +go.opentelemetry.io/otel/trace v1.1.0/go.mod h1:i47XtdcBQiktu5IsrPqOHe8w+sBmnLwwHt8wiUsWGTI= +go.opentelemetry.io/otel/trace v1.2.0 h1:Ys3iqbqZhcf28hHzrm5WAquMkDHNZTUkw7KHbuNjej0= +go.opentelemetry.io/otel/trace v1.2.0/go.mod h1:N5FLswTubnxKxOJHM7XZC074qpeEdLy3CgAVsdMucK0= go.opentelemetry.io/proto/otlp v0.7.0/go.mod h1:PqfVotwruBrMGOCsRd/89rSnXhoiJIqeYNgFYFoEGnI= -go.opentelemetry.io/proto/otlp v0.9.0 h1:C0g6TWmQYvjKRnljRULLWUVJGy8Uvu0NEL/5frY2/t4= go.opentelemetry.io/proto/otlp v0.9.0/go.mod h1:1vKfU9rv61e9EVGthD1zNvUbiwPcimSsOPU9brfSHJg= +go.opentelemetry.io/proto/otlp v0.10.0 h1:n7brgtEbDvXEgGyKKo8SobKT1e9FewlDtXzkVP5djoE= +go.opentelemetry.io/proto/otlp v0.10.0/go.mod h1:zG20xCK0szZ1xdokeSOwEcmlXu+x9kkdRe6N1DhKcfU= go.uber.org/atomic v1.4.0/go.mod h1:gD2HeocX3+yG+ygLZcrzQJaqmWj9AIm7n08wl/qW/PE= go.uber.org/atomic v1.7.0 h1:ADUqmZGgLDDfbSL9ZmPxKTybcoEYHgpYfELNoN+7hsw= go.uber.org/atomic v1.7.0/go.mod h1:fEN4uk6kAWBTFdckzkM89CLk9XfWZrxpCo0nPH17wJc= @@ -353,15 +355,12 @@ golang.org/x/lint v0.0.0-20190313153728-d0100b6bd8b3/go.mod h1:6SW0HCj/g11FgYtHl golang.org/x/lint v0.0.0-20190409202823-959b441ac422/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= golang.org/x/lint v0.0.0-20190909230951-414d861bb4ac/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= golang.org/x/lint v0.0.0-20190930215403-16217165b5de/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= -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-20190719004257-d2bd2a29d028/go.mod h1:E/iHnbuqvinMTCcRqshq8CkpyQDoeVncDDYHnLhea+o= golang.org/x/mod v0.0.0-20190513183733-4bf6d317e70e/go.mod h1:mXi4GBBbnImb6dmsKGUJ2LatrhH/nqhxcFungHvyanc= golang.org/x/mod v0.1.0/go.mod h1:0QHyrYULN0/3qlju5TqG8bIK38QM8yzMo5ekMj3DlcY= -golang.org/x/mod v0.1.1-0.20191105210325-c90efee705ee/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg= 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.4.2/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= 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-20181023162649-9b4f9f5ad519/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= @@ -384,8 +383,8 @@ golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwY golang.org/x/net v0.0.0-20201202161906-c7110b5ffcbb/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= golang.org/x/net v0.0.0-20210405180319-a5a99cb37ef4/go.mod h1:p54w0d4576C0XHj96bSt6lcn1PtDYWL6XObtHCRCNQM= -golang.org/x/net v0.0.0-20210525063256-abc453219eb5 h1:wjuX4b5yYQnEQHzd+CBcrcC6OVR2J1CN6mUy0oSxIPo= -golang.org/x/net v0.0.0-20210525063256-abc453219eb5/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= +golang.org/x/net v0.0.0-20211123203042-d83791d6bcd9 h1:0qxwC5n+ttVOINCBeRHO0nq9X7uy8SDsPoi5OaCdIEI= +golang.org/x/net v0.0.0-20211123203042-d83791d6bcd9/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= 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-20190604053449-0f29369cfe45/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= @@ -399,7 +398,6 @@ golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJ golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/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-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sys v0.0.0-20180823144017-11551d06cbcc/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= @@ -428,16 +426,18 @@ golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7w 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-20210603081109-ebe580a85c40/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20210603125802-9665404d3644 h1:CA1DEQ4NdKphKeL70tvsWNdT5oFh1lOjihRcEDROi0I= golang.org/x/sys v0.0.0-20210603125802-9665404d3644/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20211123173158-ef496fb156ab h1:rfJ1bsoJQQIAoAxTxB7bme+vHrNkRw8CqfsYh9w54cw= +golang.org/x/sys v0.0.0-20211123173158-ef496fb156ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.1-0.20180807135948-17ff2d5776d2/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.2/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.5/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= -golang.org/x/text v0.3.6 h1:aRYxNxv6iGQlyVaZmk6ZgYEDa+Jg18DxebPSrd6bg1M= 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/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-20210220033141-f8bda1e9f3ba h1:O8mE0/t419eoIwhTFpKVkHiTs/Igowgfkj25AcZrtiE= @@ -462,10 +462,8 @@ golang.org/x/tools v0.0.0-20190911174233-4f2ddba30aff/go.mod h1:b+2E5dAYhXwXZwtn golang.org/x/tools v0.0.0-20191012152004-8de300cfc20a/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.0.0-20191112195655-aa38f8e97acc/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= -golang.org/x/tools v0.0.0-20200130002326-2f3ba24bd6e7/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= golang.org/x/tools v0.0.0-20200619180055-7c47624df98f/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= golang.org/x/tools v0.0.0-20210106214847-113979e3529a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= -golang.org/x/tools v0.1.2/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= 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-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= @@ -493,8 +491,8 @@ google.golang.org/genproto v0.0.0-20191108220845-16a3f7862a1a/go.mod h1:n3cpQtvx google.golang.org/genproto v0.0.0-20200423170343-7949de9c1215/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= google.golang.org/genproto v0.0.0-20200513103714-09dca8ec2884/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= google.golang.org/genproto v0.0.0-20200526211855-cb27e3aa2013/go.mod h1:NbSheEEYHJ7i3ixzK3sjbqSGDJWnxyFXZblF3eUsNvo= -google.golang.org/genproto v0.0.0-20210602131652-f16073e35f0c h1:wtujag7C+4D6KMoulW9YauvK2lgdvCMS260jsqqBXr0= -google.golang.org/genproto v0.0.0-20210602131652-f16073e35f0c/go.mod h1:UODoCrxHCcBojKKwX1terBiRUaqAsFqJiF615XL43r0= +google.golang.org/genproto v0.0.0-20211118181313-81c1377c94b1 h1:b9mVrqYfq3P4bCdaLg1qtBnPzUYgglsIdjZkL/fQVOE= +google.golang.org/genproto v0.0.0-20211118181313-81c1377c94b1/go.mod h1:5CzLGKJ67TSI2B9POpiiyGha0AjJvZIUgRMt1dSmuhc= 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.21.1/go.mod h1:oYelfM1adQP15Ek0mdvEgi9Df8B9CZIaU1084ijfRaM= @@ -505,7 +503,6 @@ google.golang.org/grpc v1.29.1/go.mod h1:itym6AZVZYACWQqET3MqgPpjcuV5QH3BxFS3Iji google.golang.org/grpc v1.33.1/go.mod h1:fr5YgcSWrqhRRxogOsw7RzIpsmvOZ6IcH4kBYTpR3n0= google.golang.org/grpc v1.36.0/go.mod h1:qjiiYl8FncCW8feJPdyg3v6XW24KsRHe+dy9BAGRRjU= 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.40.0/go.mod h1:ogyxbiOoUXAkP+4+xa6PZSE9DZgIHtSpzjDTB9KAK34= google.golang.org/grpc v1.41.0 h1:f+PlOh7QV4iIJkPrx5NQ7qaNGFQ3OTse67yaDHfju4E= google.golang.org/grpc v1.41.0/go.mod h1:U3l9uK9J0sini8mHphKoXyaqDA/8VyGnDee1zzIUK6k= diff --git a/tests/go.mod b/tests/go.mod index 84ce5720ba44..c731dbc22edd 100644 --- a/tests/go.mod +++ b/tests/go.mod @@ -65,19 +65,19 @@ require ( github.com/sirupsen/logrus v1.8.1 // indirect github.com/tmc/grpc-websocket-proxy v0.0.0-20201229170055-e5319fda7802 // indirect github.com/xiang90/probing v0.0.0-20190116061207-43a291ad63a2 // indirect - go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.25.0 // indirect - go.opentelemetry.io/otel v1.0.1 // indirect - go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.0.1 // indirect - go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.0.1 // indirect - go.opentelemetry.io/otel/sdk v1.0.1 // indirect - go.opentelemetry.io/otel/trace v1.0.1 // indirect - go.opentelemetry.io/proto/otlp v0.9.0 // indirect + go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.26.1 // indirect + go.opentelemetry.io/otel v1.2.0 // indirect + go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.1.0 // indirect + go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.1.0 // indirect + go.opentelemetry.io/otel/sdk v1.2.0 // indirect + go.opentelemetry.io/otel/trace v1.2.0 // indirect + go.opentelemetry.io/proto/otlp v0.10.0 // indirect go.uber.org/atomic v1.7.0 // indirect go.uber.org/multierr v1.7.0 // indirect - golang.org/x/net v0.0.0-20210525063256-abc453219eb5 // indirect - golang.org/x/sys v0.0.0-20210603125802-9665404d3644 // indirect - golang.org/x/text v0.3.6 // indirect - google.golang.org/genproto v0.0.0-20210602131652-f16073e35f0c // indirect + golang.org/x/net v0.0.0-20211123203042-d83791d6bcd9 // indirect + golang.org/x/sys v0.0.0-20211123173158-ef496fb156ab // indirect + golang.org/x/text v0.3.7 // indirect + google.golang.org/genproto v0.0.0-20211118181313-81c1377c94b1 // indirect google.golang.org/protobuf v1.27.1 // indirect gopkg.in/natefinch/lumberjack.v2 v2.0.0 // indirect gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b // indirect diff --git a/tests/go.sum b/tests/go.sum index 10bfd3275536..12df68590eaf 100644 --- a/tests/go.sum +++ b/tests/go.sum @@ -121,7 +121,6 @@ github.com/golang/protobuf v1.4.1/go.mod h1:U8fpvMrcmy5pZrNK1lt4xCsGvpyWQ/VVv6QD github.com/golang/protobuf v1.4.2/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI= github.com/golang/protobuf v1.4.3/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI= 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/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY= github.com/google/btree v0.0.0-20180813153112-4030bb1f1f0c/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ= @@ -302,27 +301,30 @@ github.com/xiang90/probing v0.0.0-20190116061207-43a291ad63a2 h1:eY9dn8+vbi4tKz5 github.com/xiang90/probing v0.0.0-20190116061207-43a291ad63a2/go.mod h1:UETIi67q53MR2AWcXfiuqkDkRtnGDLqkBTpCHuJHxtU= github.com/yuin/goldmark v1.1.27/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= go.etcd.io/bbolt v1.3.2/go.mod h1:IbVyRI1SCnLcuJnV2u8VeU0CEYM7e686BmAb1XKL+uU= go.etcd.io/bbolt v1.3.6 h1:/ecaJf0sk1l4l6V4awd65v2C3ILy7MSj+s/x1ADCIMU= go.etcd.io/bbolt v1.3.6/go.mod h1:qXsaaIqmgQH0T+OPdb99Bf+PKfBBQVAdyD6TY9G8XM4= go.opencensus.io v0.21.0/go.mod h1:mSImk1erAIZhrmZN+AvHh14ztQfjbGwt4TtuofqLduU= go.opencensus.io v0.22.0/go.mod h1:+kGneAE2xo2IficOXnaByMWTGM9T73dGwxeWcUqIpI8= -go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.25.0 h1:Wx7nFnvCaissIUZxPkBqDz2963Z+Cl+PkYbDKzTxDqQ= -go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.25.0/go.mod h1:E5NNboN0UqSAki0Atn9kVwaN7I+l25gGxDqBueo/74E= -go.opentelemetry.io/otel v1.0.1 h1:4XKyXmfqJLOQ7feyV5DB6gsBFZ0ltB8vLtp6pj4JIcc= -go.opentelemetry.io/otel v1.0.1/go.mod h1:OPEOD4jIT2SlZPMmwT6FqZz2C0ZNdQqiWcoK6M0SNFU= -go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.0.1 h1:ofMbch7i29qIUf7VtF+r0HRF6ac0SBaPSziSsKp7wkk= -go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.0.1/go.mod h1:Kv8liBeVNFkkkbilbgWRpV+wWuu+H5xdOT6HAgd30iw= -go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.0.1 h1:CFMFNoz+CGprjFAFy+RJFrfEe4GBia3RRm2a4fREvCA= -go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.0.1/go.mod h1:xOvWoTOrQjxjW61xtOmD/WKGRYb/P4NzRo3bs65U6Rk= -go.opentelemetry.io/otel/sdk v1.0.1 h1:wXxFEWGo7XfXupPwVJvTBOaPBC9FEg0wB8hMNrKk+cA= -go.opentelemetry.io/otel/sdk v1.0.1/go.mod h1:HrdXne+BiwsOHYYkBE5ysIcv2bvdZstxzmCQhxTcZkI= -go.opentelemetry.io/otel/trace v1.0.1 h1:StTeIH6Q3G4r0Fiw34LTokUFESZgIDUr0qIJ7mKmAfw= -go.opentelemetry.io/otel/trace v1.0.1/go.mod h1:5g4i4fKLaX2BQpSBsxw8YYcgKpMMSW3x7ZTuYBr3sUk= +go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.26.1 h1:puWrOArBwWlr5dq6vyZ6fKykHyS8JgMIVhTBA8XsGuU= +go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.26.1/go.mod h1:4wsfAAW5N9wUHM0QTmZS8z7fvYZ1rv3m+sVeSpf8NhU= +go.opentelemetry.io/otel v1.1.0/go.mod h1:7cww0OW51jQ8IaZChIEdqLwgh+44+7uiTdWsAL0wQpA= +go.opentelemetry.io/otel v1.2.0 h1:YOQDvxO1FayUcT9MIhJhgMyNO1WqoduiyvQHzGN0kUQ= +go.opentelemetry.io/otel v1.2.0/go.mod h1:aT17Fk0Z1Nor9e0uisf98LrntPGMnk4frBO9+dkf69I= +go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.1.0 h1:PxBRMkrJnY4HRgToPzoLrTdQDHQf9MeFg5oGzTqtzco= +go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.1.0/go.mod h1:/E4iniSqAEvqbq6KM5qThKZR2sd42kDvD+SrYt00vRw= +go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.1.0 h1:4UC7muAl2UqSoTV0RqgmpTz/cRLH6R9cHt9BvVcq5Bo= +go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.1.0/go.mod h1:Gyc0evUosTBVNRqTFGuu0xqebkEWLkLwv42qggTCwro= +go.opentelemetry.io/otel/sdk v1.1.0/go.mod h1:3aQvM6uLm6C4wJpHtT8Od3vNzeZ34Pqc6bps8MywWzo= +go.opentelemetry.io/otel/sdk v1.2.0 h1:wKN260u4DesJYhyjxDa7LRFkuhH7ncEVKU37LWcyNIo= +go.opentelemetry.io/otel/sdk v1.2.0/go.mod h1:jNN8QtpvbsKhgaC6V5lHiejMoKD+V8uadoSafgHPx1U= +go.opentelemetry.io/otel/trace v1.1.0/go.mod h1:i47XtdcBQiktu5IsrPqOHe8w+sBmnLwwHt8wiUsWGTI= +go.opentelemetry.io/otel/trace v1.2.0 h1:Ys3iqbqZhcf28hHzrm5WAquMkDHNZTUkw7KHbuNjej0= +go.opentelemetry.io/otel/trace v1.2.0/go.mod h1:N5FLswTubnxKxOJHM7XZC074qpeEdLy3CgAVsdMucK0= go.opentelemetry.io/proto/otlp v0.7.0/go.mod h1:PqfVotwruBrMGOCsRd/89rSnXhoiJIqeYNgFYFoEGnI= -go.opentelemetry.io/proto/otlp v0.9.0 h1:C0g6TWmQYvjKRnljRULLWUVJGy8Uvu0NEL/5frY2/t4= go.opentelemetry.io/proto/otlp v0.9.0/go.mod h1:1vKfU9rv61e9EVGthD1zNvUbiwPcimSsOPU9brfSHJg= +go.opentelemetry.io/proto/otlp v0.10.0 h1:n7brgtEbDvXEgGyKKo8SobKT1e9FewlDtXzkVP5djoE= +go.opentelemetry.io/proto/otlp v0.10.0/go.mod h1:zG20xCK0szZ1xdokeSOwEcmlXu+x9kkdRe6N1DhKcfU= go.uber.org/atomic v1.4.0/go.mod h1:gD2HeocX3+yG+ygLZcrzQJaqmWj9AIm7n08wl/qW/PE= go.uber.org/atomic v1.7.0 h1:ADUqmZGgLDDfbSL9ZmPxKTybcoEYHgpYfELNoN+7hsw= go.uber.org/atomic v1.7.0/go.mod h1:fEN4uk6kAWBTFdckzkM89CLk9XfWZrxpCo0nPH17wJc= @@ -356,15 +358,12 @@ golang.org/x/lint v0.0.0-20190313153728-d0100b6bd8b3/go.mod h1:6SW0HCj/g11FgYtHl golang.org/x/lint v0.0.0-20190409202823-959b441ac422/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= golang.org/x/lint v0.0.0-20190909230951-414d861bb4ac/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= golang.org/x/lint v0.0.0-20190930215403-16217165b5de/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= -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-20190719004257-d2bd2a29d028/go.mod h1:E/iHnbuqvinMTCcRqshq8CkpyQDoeVncDDYHnLhea+o= golang.org/x/mod v0.0.0-20190513183733-4bf6d317e70e/go.mod h1:mXi4GBBbnImb6dmsKGUJ2LatrhH/nqhxcFungHvyanc= golang.org/x/mod v0.1.0/go.mod h1:0QHyrYULN0/3qlju5TqG8bIK38QM8yzMo5ekMj3DlcY= -golang.org/x/mod v0.1.1-0.20191105210325-c90efee705ee/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg= 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.4.2/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= 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-20181023162649-9b4f9f5ad519/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= @@ -387,8 +386,8 @@ golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwY golang.org/x/net v0.0.0-20201202161906-c7110b5ffcbb/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= golang.org/x/net v0.0.0-20210405180319-a5a99cb37ef4/go.mod h1:p54w0d4576C0XHj96bSt6lcn1PtDYWL6XObtHCRCNQM= -golang.org/x/net v0.0.0-20210525063256-abc453219eb5 h1:wjuX4b5yYQnEQHzd+CBcrcC6OVR2J1CN6mUy0oSxIPo= -golang.org/x/net v0.0.0-20210525063256-abc453219eb5/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= +golang.org/x/net v0.0.0-20211123203042-d83791d6bcd9 h1:0qxwC5n+ttVOINCBeRHO0nq9X7uy8SDsPoi5OaCdIEI= +golang.org/x/net v0.0.0-20211123203042-d83791d6bcd9/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= 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-20190604053449-0f29369cfe45/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= @@ -432,16 +431,18 @@ golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7w 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-20210603081109-ebe580a85c40/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20210603125802-9665404d3644 h1:CA1DEQ4NdKphKeL70tvsWNdT5oFh1lOjihRcEDROi0I= golang.org/x/sys v0.0.0-20210603125802-9665404d3644/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20211123173158-ef496fb156ab h1:rfJ1bsoJQQIAoAxTxB7bme+vHrNkRw8CqfsYh9w54cw= +golang.org/x/sys v0.0.0-20211123173158-ef496fb156ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.1-0.20180807135948-17ff2d5776d2/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.2/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.5/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= -golang.org/x/text v0.3.6 h1:aRYxNxv6iGQlyVaZmk6ZgYEDa+Jg18DxebPSrd6bg1M= 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/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-20210220033141-f8bda1e9f3ba h1:O8mE0/t419eoIwhTFpKVkHiTs/Igowgfkj25AcZrtiE= @@ -466,10 +467,8 @@ golang.org/x/tools v0.0.0-20190911174233-4f2ddba30aff/go.mod h1:b+2E5dAYhXwXZwtn golang.org/x/tools v0.0.0-20191012152004-8de300cfc20a/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.0.0-20191112195655-aa38f8e97acc/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= -golang.org/x/tools v0.0.0-20200130002326-2f3ba24bd6e7/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= golang.org/x/tools v0.0.0-20200619180055-7c47624df98f/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= golang.org/x/tools v0.0.0-20210106214847-113979e3529a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= -golang.org/x/tools v0.1.2/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= 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-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= @@ -497,8 +496,8 @@ google.golang.org/genproto v0.0.0-20191108220845-16a3f7862a1a/go.mod h1:n3cpQtvx google.golang.org/genproto v0.0.0-20200423170343-7949de9c1215/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= google.golang.org/genproto v0.0.0-20200513103714-09dca8ec2884/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= google.golang.org/genproto v0.0.0-20200526211855-cb27e3aa2013/go.mod h1:NbSheEEYHJ7i3ixzK3sjbqSGDJWnxyFXZblF3eUsNvo= -google.golang.org/genproto v0.0.0-20210602131652-f16073e35f0c h1:wtujag7C+4D6KMoulW9YauvK2lgdvCMS260jsqqBXr0= -google.golang.org/genproto v0.0.0-20210602131652-f16073e35f0c/go.mod h1:UODoCrxHCcBojKKwX1terBiRUaqAsFqJiF615XL43r0= +google.golang.org/genproto v0.0.0-20211118181313-81c1377c94b1 h1:b9mVrqYfq3P4bCdaLg1qtBnPzUYgglsIdjZkL/fQVOE= +google.golang.org/genproto v0.0.0-20211118181313-81c1377c94b1/go.mod h1:5CzLGKJ67TSI2B9POpiiyGha0AjJvZIUgRMt1dSmuhc= 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.21.1/go.mod h1:oYelfM1adQP15Ek0mdvEgi9Df8B9CZIaU1084ijfRaM= @@ -509,7 +508,6 @@ google.golang.org/grpc v1.29.1/go.mod h1:itym6AZVZYACWQqET3MqgPpjcuV5QH3BxFS3Iji google.golang.org/grpc v1.33.1/go.mod h1:fr5YgcSWrqhRRxogOsw7RzIpsmvOZ6IcH4kBYTpR3n0= google.golang.org/grpc v1.36.0/go.mod h1:qjiiYl8FncCW8feJPdyg3v6XW24KsRHe+dy9BAGRRjU= 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.40.0/go.mod h1:ogyxbiOoUXAkP+4+xa6PZSE9DZgIHtSpzjDTB9KAK34= google.golang.org/grpc v1.41.0 h1:f+PlOh7QV4iIJkPrx5NQ7qaNGFQ3OTse67yaDHfju4E= google.golang.org/grpc v1.41.0/go.mod h1:U3l9uK9J0sini8mHphKoXyaqDA/8VyGnDee1zzIUK6k= From 63ff6d403d107ed6cc36b09703c9f9d86e775be9 Mon Sep 17 00:00:00 2001 From: ahrtr Date: Sun, 3 Oct 2021 06:12:36 +0800 Subject: [PATCH 015/258] correct the public key comparison logic --- server/auth/options.go | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/server/auth/options.go b/server/auth/options.go index 5151076d9c44..970171da9273 100644 --- a/server/auth/options.go +++ b/server/auth/options.go @@ -145,7 +145,7 @@ func (opts *jwtOptions) rsaKey() (interface{}, error) { } // both keys provided, make sure they match - if pub != nil && pub.E != priv.E && pub.N.Cmp(priv.N) != 0 { + if pub != nil && !pub.Equal(priv.Public()) { return nil, ErrKeyMismatch } @@ -183,8 +183,7 @@ func (opts *jwtOptions) ecKey() (interface{}, error) { } // both keys provided, make sure they match - if pub != nil && pub.Curve != priv.Curve && - pub.X.Cmp(priv.X) != 0 && pub.Y.Cmp(priv.Y) != 0 { + if pub != nil && !pub.Equal(priv.Public()) { return nil, ErrKeyMismatch } From 7e6c29c19897a788194e5e649994151c6e84ccee Mon Sep 17 00:00:00 2001 From: "leoyang.yl" Date: Thu, 25 Nov 2021 20:11:05 +0800 Subject: [PATCH 016/258] fix runlock bug --- server/storage/mvcc/watchable_store.go | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/server/storage/mvcc/watchable_store.go b/server/storage/mvcc/watchable_store.go index c2a8832db1d0..5a201d4edbe7 100644 --- a/server/storage/mvcc/watchable_store.go +++ b/server/storage/mvcc/watchable_store.go @@ -355,8 +355,11 @@ func (s *watchableStore) syncWatchers() int { tx := s.store.b.ReadTx() tx.RLock() revs, vs := tx.UnsafeRange(schema.Key, minBytes, maxBytes, 0) - tx.RUnlock() evs := kvsToEvents(s.store.lg, wg, revs, vs) + // Must unlock after kvsToEvents, because vs (come from boltdb memory) is not deep copy. + // We can only unlock after Unmarshal, which will do deep copy. + // Otherwise we will trigger SIGSEGV during boltdb re-mmap. + tx.RUnlock() victims := make(watcherBatch) wb := newWatcherBatch(wg, evs) From 48a360aad03a666e0154d728806bd64a932c0288 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C5=82=20Jasionowski?= Date: Fri, 19 Nov 2021 14:52:30 +0000 Subject: [PATCH 017/258] lease,integration: add checkpoint scheduling after leader change Current checkpointing mechanism is buggy. New checkpoints for any lease are scheduled only until the first leader change. Added fix for that and a test that will check it. --- server/lease/lessor.go | 1 + server/lease/lessor_test.go | 5 +- tests/integration/v3_lease_test.go | 128 +++++++++++++++++++---------- 3 files changed, 87 insertions(+), 47 deletions(-) diff --git a/server/lease/lessor.go b/server/lease/lessor.go index 715b820793a8..f4902d275ce7 100644 --- a/server/lease/lessor.go +++ b/server/lease/lessor.go @@ -446,6 +446,7 @@ func (le *lessor) Promote(extend time.Duration) { l.refresh(extend) item := &LeaseWithTime{id: l.ID, time: l.expiry} le.leaseExpiredNotifier.RegisterOrUpdate(item) + le.scheduleCheckpointIfNeeded(l) } if len(le.leaseMap) < leaseRevokeRate { diff --git a/server/lease/lessor_test.go b/server/lease/lessor_test.go index e5fb16e0d588..9d67bedf5603 100644 --- a/server/lease/lessor_test.go +++ b/server/lease/lessor_test.go @@ -532,6 +532,7 @@ func TestLessorCheckpointScheduling(t *testing.T) { defer be.Close() le := newLessor(lg, be, LessorConfig{MinLeaseTTL: minLeaseTTL, CheckpointInterval: 1 * time.Second}) + defer le.Stop() le.minLeaseTTL = 1 checkpointedC := make(chan struct{}) le.SetCheckpointer(func(ctx context.Context, lc *pb.LeaseCheckpointRequest) { @@ -544,13 +545,11 @@ func TestLessorCheckpointScheduling(t *testing.T) { t.Errorf("expected checkpoint to be called with Remaining_TTL=%d but got %d", 1, c.Remaining_TTL) } }) - defer le.Stop() - le.Promote(0) - _, err := le.Grant(1, 2) if err != nil { t.Fatal(err) } + le.Promote(0) // TODO: Is there any way to avoid doing this wait? Lease TTL granularity is in seconds. select { diff --git a/tests/integration/v3_lease_test.go b/tests/integration/v3_lease_test.go index 40bced9c34ac..0e649fd803e2 100644 --- a/tests/integration/v3_lease_test.go +++ b/tests/integration/v3_lease_test.go @@ -230,56 +230,96 @@ func TestV3LeaseKeepAlive(t *testing.T) { // TestV3LeaseCheckpoint ensures a lease checkpoint results in a remaining TTL being persisted // across leader elections. func TestV3LeaseCheckpoint(t *testing.T) { - integration.BeforeTest(t) - - var ttl int64 = 300 - leaseInterval := 2 * time.Second - clus := integration.NewClusterV3(t, &integration.ClusterConfig{ - Size: 3, - EnableLeaseCheckpoint: true, - LeaseCheckpointInterval: leaseInterval, - UseBridge: true, - }) - defer clus.Terminate(t) - - // create lease - ctx, cancel := context.WithCancel(context.Background()) - defer cancel() - c := integration.ToGRPC(clus.RandClient()) - lresp, err := c.Lease.LeaseGrant(ctx, &pb.LeaseGrantRequest{TTL: ttl}) - if err != nil { - t.Fatal(err) - } + tcs := []struct { + name string + checkpointingEnabled bool + ttl time.Duration + checkpointingInterval time.Duration + leaderChanges int + expectTTLIsGT time.Duration + expectTTLIsLT time.Duration + }{ + { + name: "Checkpointing disabled, lease TTL is reset", + ttl: 300 * time.Second, + leaderChanges: 1, + expectTTLIsGT: 298 * time.Second, + }, + { + name: "Checkpointing enabled 10s, lease TTL is preserved after leader change", + ttl: 300 * time.Second, + checkpointingEnabled: true, + checkpointingInterval: 10 * time.Second, + leaderChanges: 1, + expectTTLIsLT: 290 * time.Second, + }, + { + // Checking if checkpointing continues after the first leader change. + name: "Checkpointing enabled 10s, lease TTL is preserved after 2 leader changes", + ttl: 300 * time.Second, + checkpointingEnabled: true, + checkpointingInterval: 10 * time.Second, + leaderChanges: 2, + expectTTLIsLT: 280 * time.Second, + }, + } + for _, tc := range tcs { + t.Run(tc.name, func(t *testing.T) { + integration.BeforeTest(t) + config := &integration.ClusterConfig{ + Size: 3, + EnableLeaseCheckpoint: tc.checkpointingEnabled, + LeaseCheckpointInterval: tc.checkpointingInterval, + } + clus := integration.NewClusterV3(t, config) + defer clus.Terminate(t) + + // create lease + ctx, cancel := context.WithCancel(context.Background()) + defer cancel() + c := integration.ToGRPC(clus.RandClient()) + lresp, err := c.Lease.LeaseGrant(ctx, &pb.LeaseGrantRequest{TTL: int64(tc.ttl.Seconds())}) + if err != nil { + t.Fatal(err) + } - // wait for a checkpoint to occur - time.Sleep(leaseInterval + 1*time.Second) + for i := 0; i < tc.leaderChanges; i++ { + // wait for a checkpoint to occur + time.Sleep(tc.checkpointingInterval + 1*time.Second) - // Force a leader election - leaderId := clus.WaitLeader(t) - leader := clus.Members[leaderId] - leader.Stop(t) - time.Sleep(time.Duration(3*integration.ElectionTicks) * integration.TickDuration) - leader.Restart(t) - newLeaderId := clus.WaitLeader(t) - c2 := integration.ToGRPC(clus.Client(newLeaderId)) + // Force a leader election + leaderId := clus.WaitLeader(t) + leader := clus.Members[leaderId] + leader.Stop(t) + time.Sleep(time.Duration(3*integration.ElectionTicks) * integration.TickDuration) + leader.Restart(t) + } - time.Sleep(250 * time.Millisecond) + newLeaderId := clus.WaitLeader(t) + c2 := integration.ToGRPC(clus.Client(newLeaderId)) + + time.Sleep(250 * time.Millisecond) + + // Check the TTL of the new leader + var ttlresp *pb.LeaseTimeToLiveResponse + for i := 0; i < 10; i++ { + if ttlresp, err = c2.Lease.LeaseTimeToLive(ctx, &pb.LeaseTimeToLiveRequest{ID: lresp.ID}); err != nil { + if status, ok := status.FromError(err); ok && status.Code() == codes.Unavailable { + time.Sleep(time.Millisecond * 250) + } else { + t.Fatal(err) + } + } + } - // Check the TTL of the new leader - var ttlresp *pb.LeaseTimeToLiveResponse - for i := 0; i < 10; i++ { - if ttlresp, err = c2.Lease.LeaseTimeToLive(ctx, &pb.LeaseTimeToLiveRequest{ID: lresp.ID}); err != nil { - if status, ok := status.FromError(err); ok && status.Code() == codes.Unavailable { - time.Sleep(time.Millisecond * 250) - } else { - t.Fatal(err) + if tc.expectTTLIsGT != 0 && time.Duration(ttlresp.TTL)*time.Second <= tc.expectTTLIsGT { + t.Errorf("Expected lease ttl (%v) to be greather than (%v)", time.Duration(ttlresp.TTL)*time.Second, tc.expectTTLIsGT) } - } - } - expectedTTL := ttl - int64(leaseInterval.Seconds()) - if ttlresp.TTL < expectedTTL-1 || ttlresp.TTL > expectedTTL { - t.Fatalf("expected lease to be checkpointed after restart such that %d < TTL <%d, but got TTL=%d", expectedTTL-1, expectedTTL, ttlresp.TTL) + if tc.expectTTLIsLT != 0 && time.Duration(ttlresp.TTL)*time.Second > tc.expectTTLIsLT { + t.Errorf("Expected lease ttl (%v) to be lower than (%v)", time.Duration(ttlresp.TTL)*time.Second, tc.expectTTLIsLT) + } + }) } } From fd77b2700c6083fb4f80e565e320ba367e9c6a04 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C5=82=20Jasionowski?= Date: Fri, 19 Nov 2021 15:02:25 +0000 Subject: [PATCH 018/258] etcdserver,integration: Store remaining TTL on checkpoint To extend lease checkpointing mechanism to cases when the whole etcd cluster is restarted. --- server/lease/lessor.go | 8 +++++--- tests/integration/v3_lease_test.go | 15 ++++++++++++++- 2 files changed, 19 insertions(+), 4 deletions(-) diff --git a/server/lease/lessor.go b/server/lease/lessor.go index f4902d275ce7..f82fe5cc1335 100644 --- a/server/lease/lessor.go +++ b/server/lease/lessor.go @@ -351,6 +351,7 @@ func (le *lessor) Checkpoint(id LeaseID, remainingTTL int64) error { if l, ok := le.leaseMap[id]; ok { // when checkpointing, we only update the remainingTTL, Promote is responsible for applying this to lease expiry l.remainingTTL = remainingTTL + l.persistTo(le.b) if le.isPrimary() { // schedule the next checkpoint as needed le.scheduleCheckpointIfNeeded(l) @@ -784,9 +785,10 @@ func (le *lessor) initAndRecover() { ttl: lpb.TTL, // itemSet will be filled in when recover key-value pairs // set expiry to forever, refresh when promoted - itemSet: make(map[LeaseItem]struct{}), - expiry: forever, - revokec: make(chan struct{}), + itemSet: make(map[LeaseItem]struct{}), + expiry: forever, + revokec: make(chan struct{}), + remainingTTL: lpb.RemainingTTL, } } le.leaseExpiredNotifier.Init() diff --git a/tests/integration/v3_lease_test.go b/tests/integration/v3_lease_test.go index 0e649fd803e2..240e6bcbaf8f 100644 --- a/tests/integration/v3_lease_test.go +++ b/tests/integration/v3_lease_test.go @@ -236,6 +236,7 @@ func TestV3LeaseCheckpoint(t *testing.T) { ttl time.Duration checkpointingInterval time.Duration leaderChanges int + clusterSize int expectTTLIsGT time.Duration expectTTLIsLT time.Duration }{ @@ -243,6 +244,7 @@ func TestV3LeaseCheckpoint(t *testing.T) { name: "Checkpointing disabled, lease TTL is reset", ttl: 300 * time.Second, leaderChanges: 1, + clusterSize: 3, expectTTLIsGT: 298 * time.Second, }, { @@ -251,6 +253,16 @@ func TestV3LeaseCheckpoint(t *testing.T) { checkpointingEnabled: true, checkpointingInterval: 10 * time.Second, leaderChanges: 1, + clusterSize: 3, + expectTTLIsLT: 290 * time.Second, + }, + { + name: "Checkpointing enabled 10s, lease TTL is preserved after cluster restart", + ttl: 300 * time.Second, + checkpointingEnabled: true, + checkpointingInterval: 10 * time.Second, + leaderChanges: 1, + clusterSize: 1, expectTTLIsLT: 290 * time.Second, }, { @@ -260,6 +272,7 @@ func TestV3LeaseCheckpoint(t *testing.T) { checkpointingEnabled: true, checkpointingInterval: 10 * time.Second, leaderChanges: 2, + clusterSize: 3, expectTTLIsLT: 280 * time.Second, }, } @@ -267,7 +280,7 @@ func TestV3LeaseCheckpoint(t *testing.T) { t.Run(tc.name, func(t *testing.T) { integration.BeforeTest(t) config := &integration.ClusterConfig{ - Size: 3, + Size: tc.clusterSize, EnableLeaseCheckpoint: tc.checkpointingEnabled, LeaseCheckpointInterval: tc.checkpointingInterval, } From 8b3405bdb8862bdee56e3e710e425b6d64aaa019 Mon Sep 17 00:00:00 2001 From: ahrtr Date: Tue, 30 Nov 2021 06:14:52 +0800 Subject: [PATCH 019/258] etcdctl: enhance the make-mirror command to return error asap with wrong command line parameters --- etcdctl/ctlv3/command/make_mirror_command.go | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/etcdctl/ctlv3/command/make_mirror_command.go b/etcdctl/ctlv3/command/make_mirror_command.go index aaa51eae9e7b..777c1dd0c07f 100644 --- a/etcdctl/ctlv3/command/make_mirror_command.go +++ b/etcdctl/ctlv3/command/make_mirror_command.go @@ -130,6 +130,11 @@ func makeMirrorCommandFunc(cmd *cobra.Command, args []string) { func makeMirror(ctx context.Context, c *clientv3.Client, dc *clientv3.Client) error { total := int64(0) + // if destination prefix is specified and remove destination prefix is true return error + if mmnodestprefix && len(mmdestprefix) > 0 { + cobrautl.ExitWithError(cobrautl.ExitBadArgs, errors.New("`--dest-prefix` and `--no-dest-prefix` cannot be set at the same time, choose one")) + } + go func() { for { time.Sleep(30 * time.Second) @@ -141,11 +146,6 @@ func makeMirror(ctx context.Context, c *clientv3.Client, dc *clientv3.Client) er rc, errc := s.SyncBase(ctx) - // if destination prefix is specified and remove destination prefix is true return error - if mmnodestprefix && len(mmdestprefix) > 0 { - cobrautl.ExitWithError(cobrautl.ExitBadArgs, fmt.Errorf("`--dest-prefix` and `--no-dest-prefix` cannot be set at the same time, choose one")) - } - // if remove destination prefix is false and destination prefix is empty set the value of destination prefix same as prefix if !mmnodestprefix && len(mmdestprefix) == 0 { mmdestprefix = mmprefix From e24796e8eb43762611da892e361ca0551a46919c Mon Sep 17 00:00:00 2001 From: Piotr Resztak Date: Sun, 29 Aug 2021 22:18:31 +0200 Subject: [PATCH 020/258] e2e: Call WithStopSignal on proxyV2 object --- tests/framework/e2e/cluster_proxy.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/framework/e2e/cluster_proxy.go b/tests/framework/e2e/cluster_proxy.go index 192079c48cbd..20242e1b04d3 100644 --- a/tests/framework/e2e/cluster_proxy.go +++ b/tests/framework/e2e/cluster_proxy.go @@ -110,7 +110,7 @@ func (p *proxyEtcdProcess) Close() error { } func (p *proxyEtcdProcess) WithStopSignal(sig os.Signal) os.Signal { - p.proxyV3.WithStopSignal(sig) + p.proxyV2.WithStopSignal(sig) p.proxyV3.WithStopSignal(sig) return p.etcdProc.WithStopSignal(sig) } From 7d10899d7f40caea98685e40343c4f68f24f8a9b Mon Sep 17 00:00:00 2001 From: Marek Siarkowicz Date: Wed, 1 Dec 2021 15:24:25 +0100 Subject: [PATCH 021/258] server: Require either cluster version v3.6 or --experimental-enable-lease-checkpoint-persist to persist lease remainingTTL To avoid inconsistant behavior during cluster upgrade we are feature gating persistance behind cluster version. This should ensure that all cluster members are upgraded to v3.6 before changing behavior. To allow backporting this fix to v3.5 we are also introducing flag --experimental-enable-lease-checkpoint-persist that will allow for smooth upgrade in v3.5 clusters with this feature enabled. --- server/config/config.go | 4 +- server/embed/config.go | 17 +++- server/embed/config_test.go | 50 ++++++++++ server/embed/etcd.go | 1 + server/etcdmain/config.go | 4 +- server/etcdserver/server.go | 3 +- server/lease/leasehttp/http_test.go | 6 +- server/lease/lessor.go | 34 ++++++- server/lease/lessor_bench_test.go | 2 +- server/lease/lessor_test.go | 121 ++++++++++++++++++++++--- tests/framework/integration/cluster.go | 4 + 11 files changed, 218 insertions(+), 28 deletions(-) diff --git a/server/config/config.go b/server/config/config.go index 74587efd6a04..43ecab7ecd5f 100644 --- a/server/config/config.go +++ b/server/config/config.go @@ -149,10 +149,12 @@ type ServerConfig struct { ForceNewCluster bool - // EnableLeaseCheckpoint enables primary lessor to persist lease remainingTTL to prevent indefinite auto-renewal of long lived leases. + // EnableLeaseCheckpoint enables leader to send regular checkpoints to other members to prevent reset of remaining TTL on leader change. EnableLeaseCheckpoint bool // LeaseCheckpointInterval time.Duration is the wait duration between lease checkpoints. LeaseCheckpointInterval time.Duration + // LeaseCheckpointPersist enables persisting remainingTTL to prevent indefinite auto-renewal of long lived leases. Always enabled in v3.6. Should be used to ensure smooth upgrade from v3.5 clusters with this feature enabled. + LeaseCheckpointPersist bool EnableGRPCGateway bool diff --git a/server/embed/config.go b/server/embed/config.go index ecec546a0e0b..c168fe8411fe 100644 --- a/server/embed/config.go +++ b/server/embed/config.go @@ -315,9 +315,14 @@ type Config struct { // Deprecated in v3.5. // TODO: Delete in v3.6 (https://github.com/etcd-io/etcd/issues/12913) ExperimentalEnableV2V3 string `json:"experimental-enable-v2v3"` - // ExperimentalEnableLeaseCheckpoint enables primary lessor to persist lease remainingTTL to prevent indefinite auto-renewal of long lived leases. + // ExperimentalEnableLeaseCheckpoint enables leader to send regular checkpoints to other members to prevent reset of remaining TTL on leader change. ExperimentalEnableLeaseCheckpoint bool `json:"experimental-enable-lease-checkpoint"` - ExperimentalCompactionBatchLimit int `json:"experimental-compaction-batch-limit"` + // ExperimentalEnableLeaseCheckpointPersist enables persisting remainingTTL to prevent indefinite auto-renewal of long lived leases. Always enabled in v3.6. Should be used to ensure smooth upgrade from v3.5 clusters with this feature enabled. + // Requires experimental-enable-lease-checkpoint to be enabled. + // Deprecated in v3.6. + // TODO: Delete in v3.7 + ExperimentalEnableLeaseCheckpointPersist bool `json:"experimental-enable-lease-checkpoint-persist"` + ExperimentalCompactionBatchLimit int `json:"experimental-compaction-batch-limit"` // ExperimentalCompactionSleepInterval is the sleep interval between every etcd compaction loop. ExperimentalCompactionSleepInterval time.Duration `json:"experimental-compaction-sleep-interval"` ExperimentalWatchProgressNotifyInterval time.Duration `json:"experimental-watch-progress-notify-interval"` @@ -704,6 +709,14 @@ func (cfg *Config) Validate() error { } } + if !cfg.ExperimentalEnableLeaseCheckpointPersist && cfg.ExperimentalEnableLeaseCheckpoint { + cfg.logger.Warn("Detected that checkpointing is enabled without persistence. Consider enabling experimental-enable-lease-checkpoint-persist") + } + + if cfg.ExperimentalEnableLeaseCheckpointPersist && !cfg.ExperimentalEnableLeaseCheckpoint { + return fmt.Errorf("setting experimental-enable-lease-checkpoint-persist requires experimental-enable-lease-checkpoint") + } + return nil } diff --git a/server/embed/config_test.go b/server/embed/config_test.go index e7da274b2854..bb5c088805fd 100644 --- a/server/embed/config_test.go +++ b/server/embed/config_test.go @@ -297,6 +297,56 @@ func TestPeerURLsMapAndTokenFromSRV(t *testing.T) { } } +func TestLeaseCheckpointValidate(t *testing.T) { + tcs := []struct { + name string + configFunc func() Config + expectError bool + }{ + { + name: "Default config should pass", + configFunc: func() Config { + return *NewConfig() + }, + }, + { + name: "Enabling checkpoint leases should pass", + configFunc: func() Config { + cfg := *NewConfig() + cfg.ExperimentalEnableLeaseCheckpoint = true + return cfg + }, + }, + { + name: "Enabling checkpoint leases and persist should pass", + configFunc: func() Config { + cfg := *NewConfig() + cfg.ExperimentalEnableLeaseCheckpoint = true + cfg.ExperimentalEnableLeaseCheckpointPersist = true + return cfg + }, + }, + { + name: "Enabling checkpoint leases persist without checkpointing itself should fail", + configFunc: func() Config { + cfg := *NewConfig() + cfg.ExperimentalEnableLeaseCheckpointPersist = true + return cfg + }, + expectError: true, + }, + } + for _, tc := range tcs { + t.Run(tc.name, func(t *testing.T) { + cfg := tc.configFunc() + err := cfg.Validate() + if (err != nil) != tc.expectError { + t.Errorf("config.Validate() = %q, expected error: %v", err, tc.expectError) + } + }) + } +} + func TestLogRotation(t *testing.T) { tests := []struct { name string diff --git a/server/embed/etcd.go b/server/embed/etcd.go index 5970437f0f07..a3ba75a56f8e 100644 --- a/server/embed/etcd.go +++ b/server/embed/etcd.go @@ -210,6 +210,7 @@ func StartEtcd(inCfg *Config) (e *Etcd, err error) { ExperimentalEnableDistributedTracing: cfg.ExperimentalEnableDistributedTracing, UnsafeNoFsync: cfg.UnsafeNoFsync, EnableLeaseCheckpoint: cfg.ExperimentalEnableLeaseCheckpoint, + LeaseCheckpointPersist: cfg.ExperimentalEnableLeaseCheckpointPersist, CompactionBatchLimit: cfg.ExperimentalCompactionBatchLimit, CompactionSleepInterval: cfg.ExperimentalCompactionSleepInterval, WatchProgressNotifyInterval: cfg.ExperimentalWatchProgressNotifyInterval, diff --git a/server/etcdmain/config.go b/server/etcdmain/config.go index 52c99eb6b7e1..eadc5d637eaf 100644 --- a/server/etcdmain/config.go +++ b/server/etcdmain/config.go @@ -282,7 +282,9 @@ func newConfig() *config { fs.BoolVar(&cfg.ec.ExperimentalInitialCorruptCheck, "experimental-initial-corrupt-check", cfg.ec.ExperimentalInitialCorruptCheck, "Enable to check data corruption before serving any client/peer traffic.") fs.DurationVar(&cfg.ec.ExperimentalCorruptCheckTime, "experimental-corrupt-check-time", cfg.ec.ExperimentalCorruptCheckTime, "Duration of time between cluster corruption check passes.") - fs.BoolVar(&cfg.ec.ExperimentalEnableLeaseCheckpoint, "experimental-enable-lease-checkpoint", false, "Enable to persist lease remaining TTL to prevent indefinite auto-renewal of long lived leases.") + fs.BoolVar(&cfg.ec.ExperimentalEnableLeaseCheckpoint, "experimental-enable-lease-checkpoint", false, "Enable leader to send regular checkpoints to other members to prevent reset of remaining TTL on leader change.") + // TODO: delete in v3.7 + fs.BoolVar(&cfg.ec.ExperimentalEnableLeaseCheckpointPersist, "experimental-enable-lease-checkpoint-persist", false, "Enable persisting remainingTTL to prevent indefinite auto-renewal of long lived leases. Always enabled in v3.6. Should be used to ensure smooth upgrade from v3.5 clusters with this feature enabled. Requires experimental-enable-lease-checkpoint to be enabled.") fs.IntVar(&cfg.ec.ExperimentalCompactionBatchLimit, "experimental-compaction-batch-limit", cfg.ec.ExperimentalCompactionBatchLimit, "Sets the maximum revisions deleted in each compaction batch.") fs.DurationVar(&cfg.ec.ExperimentalCompactionSleepInterval, "experimental-compaction-sleep-interval", cfg.ec.ExperimentalCompactionSleepInterval, "Sets the sleep interval between each compaction batch.") fs.DurationVar(&cfg.ec.ExperimentalWatchProgressNotifyInterval, "experimental-watch-progress-notify-interval", cfg.ec.ExperimentalWatchProgressNotifyInterval, "Duration of periodic watch progress notifications.") diff --git a/server/etcdserver/server.go b/server/etcdserver/server.go index 2de2477ec7f6..884caf411aad 100644 --- a/server/etcdserver/server.go +++ b/server/etcdserver/server.go @@ -344,9 +344,10 @@ func NewServer(cfg config.ServerConfig) (srv *EtcdServer, err error) { // always recover lessor before kv. When we recover the mvcc.KV it will reattach keys to its leases. // If we recover mvcc.KV first, it will attach the keys to the wrong lessor before it recovers. - srv.lessor = lease.NewLessor(srv.Logger(), srv.be, lease.LessorConfig{ + srv.lessor = lease.NewLessor(srv.Logger(), srv.be, srv.cluster, lease.LessorConfig{ MinLeaseTTL: int64(math.Ceil(minTTL.Seconds())), CheckpointInterval: cfg.LeaseCheckpointInterval, + CheckpointPersist: cfg.LeaseCheckpointPersist, ExpiredLeasesRetryInterval: srv.Cfg.ReqTimeout(), }) diff --git a/server/lease/leasehttp/http_test.go b/server/lease/leasehttp/http_test.go index 4fb8fd7eb799..e614b4033a37 100644 --- a/server/lease/leasehttp/http_test.go +++ b/server/lease/leasehttp/http_test.go @@ -31,7 +31,7 @@ func TestRenewHTTP(t *testing.T) { be, _ := betesting.NewTmpBackend(t, time.Hour, 10000) defer betesting.Close(t, be) - le := lease.NewLessor(lg, be, lease.LessorConfig{MinLeaseTTL: int64(5)}) + le := lease.NewLessor(lg, be, nil, lease.LessorConfig{MinLeaseTTL: int64(5)}) le.Promote(time.Second) l, err := le.Grant(1, int64(5)) if err != nil { @@ -55,7 +55,7 @@ func TestTimeToLiveHTTP(t *testing.T) { be, _ := betesting.NewTmpBackend(t, time.Hour, 10000) defer betesting.Close(t, be) - le := lease.NewLessor(lg, be, lease.LessorConfig{MinLeaseTTL: int64(5)}) + le := lease.NewLessor(lg, be, nil, lease.LessorConfig{MinLeaseTTL: int64(5)}) le.Promote(time.Second) l, err := le.Grant(1, int64(5)) if err != nil { @@ -96,7 +96,7 @@ func testApplyTimeout(t *testing.T, f func(*lease.Lease, string) error) { be, _ := betesting.NewTmpBackend(t, time.Hour, 10000) defer betesting.Close(t, be) - le := lease.NewLessor(lg, be, lease.LessorConfig{MinLeaseTTL: int64(5)}) + le := lease.NewLessor(lg, be, nil, lease.LessorConfig{MinLeaseTTL: int64(5)}) le.Promote(time.Second) l, err := le.Grant(1, int64(5)) if err != nil { diff --git a/server/lease/lessor.go b/server/lease/lessor.go index f82fe5cc1335..0a77fd669da4 100644 --- a/server/lease/lessor.go +++ b/server/lease/lessor.go @@ -24,6 +24,7 @@ import ( "sync" "time" + "github.com/coreos/go-semver/semver" pb "go.etcd.io/etcd/api/v3/etcdserverpb" "go.etcd.io/etcd/server/v3/lease/leasepb" "go.etcd.io/etcd/server/v3/storage/backend" @@ -37,6 +38,8 @@ const NoLease = LeaseID(0) // MaxLeaseTTL is the maximum lease TTL value const MaxLeaseTTL = 9000000000 +var v3_6 = semver.Version{Major: 3, Minor: 6} + var ( forever = time.Time{} @@ -180,19 +183,29 @@ type lessor struct { checkpointInterval time.Duration // the interval to check if the expired lease is revoked expiredLeaseRetryInterval time.Duration + // whether lessor should always persist remaining TTL (always enabled in v3.6). + checkpointPersist bool + // cluster is used to adapt lessor logic based on cluster version + cluster cluster +} + +type cluster interface { + // Version is the cluster-wide minimum major.minor version. + Version() *semver.Version } type LessorConfig struct { MinLeaseTTL int64 CheckpointInterval time.Duration ExpiredLeasesRetryInterval time.Duration + CheckpointPersist bool } -func NewLessor(lg *zap.Logger, b backend.Backend, cfg LessorConfig) Lessor { - return newLessor(lg, b, cfg) +func NewLessor(lg *zap.Logger, b backend.Backend, cluster cluster, cfg LessorConfig) Lessor { + return newLessor(lg, b, cluster, cfg) } -func newLessor(lg *zap.Logger, b backend.Backend, cfg LessorConfig) *lessor { +func newLessor(lg *zap.Logger, b backend.Backend, cluster cluster, cfg LessorConfig) *lessor { checkpointInterval := cfg.CheckpointInterval expiredLeaseRetryInterval := cfg.ExpiredLeasesRetryInterval if checkpointInterval == 0 { @@ -210,11 +223,13 @@ func newLessor(lg *zap.Logger, b backend.Backend, cfg LessorConfig) *lessor { minLeaseTTL: cfg.MinLeaseTTL, checkpointInterval: checkpointInterval, expiredLeaseRetryInterval: expiredLeaseRetryInterval, + checkpointPersist: cfg.CheckpointPersist, // expiredC is a small buffered chan to avoid unnecessary blocking. expiredC: make(chan []*Lease, 16), stopC: make(chan struct{}), doneC: make(chan struct{}), lg: lg, + cluster: cluster, } l.initAndRecover() @@ -351,7 +366,9 @@ func (le *lessor) Checkpoint(id LeaseID, remainingTTL int64) error { if l, ok := le.leaseMap[id]; ok { // when checkpointing, we only update the remainingTTL, Promote is responsible for applying this to lease expiry l.remainingTTL = remainingTTL - l.persistTo(le.b) + if le.shouldPersistCheckpoints() { + l.persistTo(le.b) + } if le.isPrimary() { // schedule the next checkpoint as needed le.scheduleCheckpointIfNeeded(l) @@ -360,6 +377,15 @@ func (le *lessor) Checkpoint(id LeaseID, remainingTTL int64) error { return nil } +func (le *lessor) shouldPersistCheckpoints() bool { + cv := le.cluster.Version() + return le.checkpointPersist || (cv != nil && greaterOrEqual(*cv, v3_6)) +} + +func greaterOrEqual(first, second semver.Version) bool { + return !first.LessThan(second) +} + // Renew renews an existing lease. If the given lease does not exist or // has expired, an error will be returned. func (le *lessor) Renew(id LeaseID) (int64, error) { diff --git a/server/lease/lessor_bench_test.go b/server/lease/lessor_bench_test.go index 570663deb2de..86f9d1bf5146 100644 --- a/server/lease/lessor_bench_test.go +++ b/server/lease/lessor_bench_test.go @@ -68,7 +68,7 @@ func setUp(t testing.TB) (le *lessor, tearDown func()) { be, _ := betesting.NewDefaultTmpBackend(t) // MinLeaseTTL is negative, so we can grant expired lease in benchmark. // ExpiredLeasesRetryInterval should small, so benchmark of findExpired will recheck expired lease. - le = newLessor(lg, be, LessorConfig{MinLeaseTTL: -1000, ExpiredLeasesRetryInterval: 10 * time.Microsecond}) + le = newLessor(lg, be, nil, LessorConfig{MinLeaseTTL: -1000, ExpiredLeasesRetryInterval: 10 * time.Microsecond}) le.SetRangeDeleter(func() TxnDelete { ftd := &FakeTxnDelete{be.BatchTx()} ftd.Lock() diff --git a/server/lease/lessor_test.go b/server/lease/lessor_test.go index 9d67bedf5603..27ca86fd8823 100644 --- a/server/lease/lessor_test.go +++ b/server/lease/lessor_test.go @@ -25,7 +25,9 @@ import ( "testing" "time" + "github.com/coreos/go-semver/semver" pb "go.etcd.io/etcd/api/v3/etcdserverpb" + "go.etcd.io/etcd/api/v3/version" "go.etcd.io/etcd/server/v3/storage/backend" "go.etcd.io/etcd/server/v3/storage/schema" "go.uber.org/zap" @@ -45,7 +47,7 @@ func TestLessorGrant(t *testing.T) { defer os.RemoveAll(dir) defer be.Close() - le := newLessor(lg, be, LessorConfig{MinLeaseTTL: minLeaseTTL}) + le := newLessor(lg, be, clusterLatest(), LessorConfig{MinLeaseTTL: minLeaseTTL}) defer le.Stop() le.Promote(0) @@ -108,7 +110,7 @@ func TestLeaseConcurrentKeys(t *testing.T) { defer os.RemoveAll(dir) defer be.Close() - le := newLessor(lg, be, LessorConfig{MinLeaseTTL: minLeaseTTL}) + le := newLessor(lg, be, clusterLatest(), LessorConfig{MinLeaseTTL: minLeaseTTL}) defer le.Stop() le.SetRangeDeleter(func() TxnDelete { return newFakeDeleter(be) }) @@ -157,7 +159,7 @@ func TestLessorRevoke(t *testing.T) { defer os.RemoveAll(dir) defer be.Close() - le := newLessor(lg, be, LessorConfig{MinLeaseTTL: minLeaseTTL}) + le := newLessor(lg, be, clusterLatest(), LessorConfig{MinLeaseTTL: minLeaseTTL}) defer le.Stop() var fd *fakeDeleter le.SetRangeDeleter(func() TxnDelete { @@ -211,7 +213,7 @@ func TestLessorRenew(t *testing.T) { defer be.Close() defer os.RemoveAll(dir) - le := newLessor(lg, be, LessorConfig{MinLeaseTTL: minLeaseTTL}) + le := newLessor(lg, be, clusterLatest(), LessorConfig{MinLeaseTTL: minLeaseTTL}) defer le.Stop() le.Promote(0) @@ -244,7 +246,7 @@ func TestLessorRenewWithCheckpointer(t *testing.T) { defer be.Close() defer os.RemoveAll(dir) - le := newLessor(lg, be, LessorConfig{MinLeaseTTL: minLeaseTTL}) + le := newLessor(lg, be, clusterLatest(), LessorConfig{MinLeaseTTL: minLeaseTTL}) fakerCheckerpointer := func(ctx context.Context, cp *pb.LeaseCheckpointRequest) { for _, cp := range cp.GetCheckpoints() { le.Checkpoint(LeaseID(cp.GetID()), cp.GetRemaining_TTL()) @@ -293,7 +295,7 @@ func TestLessorRenewExtendPileup(t *testing.T) { dir, be := NewTestBackend(t) defer os.RemoveAll(dir) - le := newLessor(lg, be, LessorConfig{MinLeaseTTL: minLeaseTTL}) + le := newLessor(lg, be, clusterLatest(), LessorConfig{MinLeaseTTL: minLeaseTTL}) ttl := int64(10) for i := 1; i <= leaseRevokeRate*10; i++ { if _, err := le.Grant(LeaseID(2*i), ttl); err != nil { @@ -312,7 +314,7 @@ func TestLessorRenewExtendPileup(t *testing.T) { bcfg.Path = filepath.Join(dir, "be") be = backend.New(bcfg) defer be.Close() - le = newLessor(lg, be, LessorConfig{MinLeaseTTL: minLeaseTTL}) + le = newLessor(lg, be, clusterLatest(), LessorConfig{MinLeaseTTL: minLeaseTTL}) defer le.Stop() // extend after recovery should extend expiration on lease pile-up @@ -342,7 +344,7 @@ func TestLessorDetach(t *testing.T) { defer os.RemoveAll(dir) defer be.Close() - le := newLessor(lg, be, LessorConfig{MinLeaseTTL: minLeaseTTL}) + le := newLessor(lg, be, clusterLatest(), LessorConfig{MinLeaseTTL: minLeaseTTL}) defer le.Stop() le.SetRangeDeleter(func() TxnDelete { return newFakeDeleter(be) }) @@ -383,7 +385,7 @@ func TestLessorRecover(t *testing.T) { defer os.RemoveAll(dir) defer be.Close() - le := newLessor(lg, be, LessorConfig{MinLeaseTTL: minLeaseTTL}) + le := newLessor(lg, be, clusterLatest(), LessorConfig{MinLeaseTTL: minLeaseTTL}) defer le.Stop() l1, err1 := le.Grant(1, 10) l2, err2 := le.Grant(2, 20) @@ -392,7 +394,7 @@ func TestLessorRecover(t *testing.T) { } // Create a new lessor with the same backend - nle := newLessor(lg, be, LessorConfig{MinLeaseTTL: minLeaseTTL}) + nle := newLessor(lg, be, clusterLatest(), LessorConfig{MinLeaseTTL: minLeaseTTL}) defer nle.Stop() nl1 := nle.Lookup(l1.ID) if nl1 == nil || nl1.ttl != l1.ttl { @@ -413,7 +415,7 @@ func TestLessorExpire(t *testing.T) { testMinTTL := int64(1) - le := newLessor(lg, be, LessorConfig{MinLeaseTTL: testMinTTL}) + le := newLessor(lg, be, clusterLatest(), LessorConfig{MinLeaseTTL: testMinTTL}) defer le.Stop() le.Promote(1 * time.Second) @@ -466,7 +468,7 @@ func TestLessorExpireAndDemote(t *testing.T) { testMinTTL := int64(1) - le := newLessor(lg, be, LessorConfig{MinLeaseTTL: testMinTTL}) + le := newLessor(lg, be, clusterLatest(), LessorConfig{MinLeaseTTL: testMinTTL}) defer le.Stop() le.Promote(1 * time.Second) @@ -515,7 +517,7 @@ func TestLessorMaxTTL(t *testing.T) { defer os.RemoveAll(dir) defer be.Close() - le := newLessor(lg, be, LessorConfig{MinLeaseTTL: minLeaseTTL}) + le := newLessor(lg, be, clusterLatest(), LessorConfig{MinLeaseTTL: minLeaseTTL}) defer le.Stop() _, err := le.Grant(1, MaxLeaseTTL+1) @@ -531,7 +533,7 @@ func TestLessorCheckpointScheduling(t *testing.T) { defer os.RemoveAll(dir) defer be.Close() - le := newLessor(lg, be, LessorConfig{MinLeaseTTL: minLeaseTTL, CheckpointInterval: 1 * time.Second}) + le := newLessor(lg, be, clusterLatest(), LessorConfig{MinLeaseTTL: minLeaseTTL, CheckpointInterval: 1 * time.Second}) defer le.Stop() le.minLeaseTTL = 1 checkpointedC := make(chan struct{}) @@ -565,7 +567,7 @@ func TestLessorCheckpointsRestoredOnPromote(t *testing.T) { defer os.RemoveAll(dir) defer be.Close() - le := newLessor(lg, be, LessorConfig{MinLeaseTTL: minLeaseTTL}) + le := newLessor(lg, be, clusterLatest(), LessorConfig{MinLeaseTTL: minLeaseTTL}) defer le.Stop() l, err := le.Grant(1, 10) if err != nil { @@ -579,6 +581,75 @@ func TestLessorCheckpointsRestoredOnPromote(t *testing.T) { } } +func TestLessorCheckpointPersistenceAfterRestart(t *testing.T) { + const ttl int64 = 10 + const checkpointTTL int64 = 5 + + tcs := []struct { + name string + cluster cluster + checkpointPersist bool + expectRemainingTTL int64 + }{ + { + name: "Etcd v3.6 and newer persist remainingTTL on checkpoint", + cluster: clusterLatest(), + expectRemainingTTL: checkpointTTL, + }, + { + name: "Etcd v3.5 and older persist remainingTTL if CheckpointPersist is set", + cluster: clusterV3_5(), + checkpointPersist: true, + expectRemainingTTL: checkpointTTL, + }, + { + name: "Etcd with version unknown persists remainingTTL if CheckpointPersist is set", + cluster: clusterNil(), + checkpointPersist: true, + expectRemainingTTL: checkpointTTL, + }, + { + name: "Etcd v3.5 and older reset remainingTTL on checkpoint", + cluster: clusterV3_5(), + expectRemainingTTL: ttl, + }, + { + name: "Etcd with version unknown fallbacks to v3.5 behavior", + cluster: clusterNil(), + expectRemainingTTL: ttl, + }, + } + for _, tc := range tcs { + t.Run(tc.name, func(t *testing.T) { + lg := zap.NewNop() + dir, be := NewTestBackend(t) + defer os.RemoveAll(dir) + defer be.Close() + + cfg := LessorConfig{MinLeaseTTL: minLeaseTTL} + cfg.CheckpointPersist = tc.checkpointPersist + le := newLessor(lg, be, tc.cluster, cfg) + l, err := le.Grant(2, ttl) + if err != nil { + t.Fatal(err) + } + if l.RemainingTTL() != ttl { + t.Errorf("remainingTTL() = %d, expected: %d", l.RemainingTTL(), ttl) + } + le.Checkpoint(2, checkpointTTL) + if l.RemainingTTL() != checkpointTTL { + t.Errorf("remainingTTL() = %d, expected: %d", l.RemainingTTL(), checkpointTTL) + } + le.Stop() + le2 := newLessor(lg, be, clusterLatest(), cfg) + l = le2.Lookup(2) + if l.RemainingTTL() != tc.expectRemainingTTL { + t.Errorf("remainingTTL() = %d, expected: %d", l.RemainingTTL(), tc.expectRemainingTTL) + } + }) + } +} + type fakeDeleter struct { deleted []string tx backend.BatchTx @@ -606,3 +677,23 @@ func NewTestBackend(t *testing.T) (string, backend.Backend) { bcfg.Path = filepath.Join(tmpPath, "be") return tmpPath, backend.New(bcfg) } + +func clusterLatest() cluster { + return fakeCluster{semver.New(version.Cluster(version.Version) + ".0")} +} + +func clusterV3_5() cluster { + return fakeCluster{semver.New("3.5.0")} +} + +func clusterNil() cluster { + return fakeCluster{} +} + +type fakeCluster struct { + version *semver.Version +} + +func (c fakeCluster) Version() *semver.Version { + return c.version +} diff --git a/tests/framework/integration/cluster.go b/tests/framework/integration/cluster.go index 631e00689bcb..4021ff676a2f 100644 --- a/tests/framework/integration/cluster.go +++ b/tests/framework/integration/cluster.go @@ -168,6 +168,7 @@ type ClusterConfig struct { EnableLeaseCheckpoint bool LeaseCheckpointInterval time.Duration + LeaseCheckpointPersist bool WatchProgressNotifyInterval time.Duration ExperimentalMaxLearners int @@ -331,6 +332,7 @@ func (c *Cluster) mustNewMember(t testutil.TB, memberNumber int64) *Member { UseTCP: c.Cfg.UseTCP, EnableLeaseCheckpoint: c.Cfg.EnableLeaseCheckpoint, LeaseCheckpointInterval: c.Cfg.LeaseCheckpointInterval, + LeaseCheckpointPersist: c.Cfg.LeaseCheckpointPersist, WatchProgressNotifyInterval: c.Cfg.WatchProgressNotifyInterval, ExperimentalMaxLearners: c.Cfg.ExperimentalMaxLearners, }) @@ -634,6 +636,7 @@ type MemberConfig struct { UseTCP bool EnableLeaseCheckpoint bool LeaseCheckpointInterval time.Duration + LeaseCheckpointPersist bool WatchProgressNotifyInterval time.Duration ExperimentalMaxLearners int } @@ -733,6 +736,7 @@ func MustNewMember(t testutil.TB, mcfg MemberConfig) *Member { m.UseTCP = mcfg.UseTCP m.EnableLeaseCheckpoint = mcfg.EnableLeaseCheckpoint m.LeaseCheckpointInterval = mcfg.LeaseCheckpointInterval + m.LeaseCheckpointPersist = mcfg.LeaseCheckpointPersist m.WatchProgressNotifyInterval = mcfg.WatchProgressNotifyInterval From 48a7aab2bc0796f7177fcef059c358220968c5cd Mon Sep 17 00:00:00 2001 From: Marek Siarkowicz Date: Wed, 1 Dec 2021 16:40:54 +0100 Subject: [PATCH 022/258] server: Add lease checkpointing fix information to CHANGELOG --- CHANGELOG-3.5.md | 2 ++ CHANGELOG-3.6.md | 2 ++ 2 files changed, 4 insertions(+) diff --git a/CHANGELOG-3.5.md b/CHANGELOG-3.5.md index cc38797ed998..0e66b7d705d2 100644 --- a/CHANGELOG-3.5.md +++ b/CHANGELOG-3.5.md @@ -14,6 +14,8 @@ See [code changes](https://github.com/etcd-io/etcd/compare/v3.5.1...v3.5.2) and ### etcd server - Fix [exclude the same alarm type activated by multiple peers](https://github.com/etcd-io/etcd/pull/13476). +- Add [`etcd --experimental-enable-lease-checkpoint-persist`](https://github.com/etcd-io/etcd/pull/13508) flag to enable checkpoint persisting. +- Fix [Lease checkpoints don't prevent to reset ttl on leader change](https://github.com/etcd-io/etcd/pull/13508), requires enabling checkpoint persisting.
diff --git a/CHANGELOG-3.6.md b/CHANGELOG-3.6.md index 3f6b28d5f432..9f23560d729f 100644 --- a/CHANGELOG-3.6.md +++ b/CHANGELOG-3.6.md @@ -33,9 +33,11 @@ See [code changes](https://github.com/etcd-io/etcd/compare/v3.5.0...v3.6.0). - Add [`etcd --log-format`](https://github.com/etcd-io/etcd/pull/13339) flag to support log format. - Add [`etcd --experimental-max-learners`](https://github.com/etcd-io/etcd/pull/13377) flag to allow configuration of learner max membership. +- Add [`etcd --experimental-enable-lease-checkpoint-persist`](https://github.com/etcd-io/etcd/pull/13508) flag to handle upgrade from v3.5.2 clusters with this feature enabled. - Fix [non mutating requests pass through quotaKVServer when NOSPACE](https://github.com/etcd-io/etcd/pull/13435) - Fix [exclude the same alarm type activated by multiple peers](https://github.com/etcd-io/etcd/pull/13467). - Fix [Provide a better liveness probe for when etcd runs as a Kubernetes pod](https://github.com/etcd-io/etcd/pull/13399) +- Fix [Lease checkpoints don't prevent to reset ttl on leader change](https://github.com/etcd-io/etcd/pull/13508). ### tools/benchmark From 7be1464ef1e305c964dbff69da415d6c5d9bee70 Mon Sep 17 00:00:00 2001 From: ahrtr Date: Thu, 25 Nov 2021 05:16:50 +0800 Subject: [PATCH 023/258] set the backend again after recovering v3 backend from snapshot --- CHANGELOG-3.6.md | 1 + server/etcdserver/bootstrap.go | 4 + server/etcdserver/bootstrap_test.go | 165 ++++++++++++++++++++++++++++ 3 files changed, 170 insertions(+) diff --git a/CHANGELOG-3.6.md b/CHANGELOG-3.6.md index 9f23560d729f..e97c3e1a63dd 100644 --- a/CHANGELOG-3.6.md +++ b/CHANGELOG-3.6.md @@ -38,6 +38,7 @@ See [code changes](https://github.com/etcd-io/etcd/compare/v3.5.0...v3.6.0). - Fix [exclude the same alarm type activated by multiple peers](https://github.com/etcd-io/etcd/pull/13467). - Fix [Provide a better liveness probe for when etcd runs as a Kubernetes pod](https://github.com/etcd-io/etcd/pull/13399) - Fix [Lease checkpoints don't prevent to reset ttl on leader change](https://github.com/etcd-io/etcd/pull/13508). +- Fix [assertion failed due to tx closed when recovering v3 backend from a snapshot db](https://github.com/etcd-io/etcd/pull/13500) ### tools/benchmark diff --git a/server/etcdserver/bootstrap.go b/server/etcdserver/bootstrap.go index d1b8bbe643ed..0c1297afee50 100644 --- a/server/etcdserver/bootstrap.go +++ b/server/etcdserver/bootstrap.go @@ -408,6 +408,10 @@ func recoverSnapshot(cfg config.ServerConfig, st v2store.Store, be backend.Backe if be, err = serverstorage.RecoverSnapshotBackend(cfg, be, *snapshot, beExist, beHooks); err != nil { cfg.Logger.Panic("failed to recover v3 backend from snapshot", zap.Error(err)) } + // A snapshot db may have already been recovered, and the old db should have + // already been closed in this case, so we should set the backend again. + ci.SetBackend(be) + s1, s2 := be.Size(), be.SizeInUse() cfg.Logger.Info( "recovered v3 backend from snapshot", diff --git a/server/etcdserver/bootstrap_test.go b/server/etcdserver/bootstrap_test.go index 8d6effd450f9..3db684d56747 100644 --- a/server/etcdserver/bootstrap_test.go +++ b/server/etcdserver/bootstrap_test.go @@ -19,16 +19,28 @@ package etcdserver import ( "encoding/json" + "fmt" + bolt "go.etcd.io/bbolt" + "go.etcd.io/etcd/server/v3/storage/datadir" + "go.etcd.io/etcd/server/v3/storage/schema" + "go.etcd.io/etcd/server/v3/storage/wal" + "go.etcd.io/etcd/server/v3/storage/wal/walpb" "io" "net/http" + "os" + "path/filepath" "strings" "testing" "go.etcd.io/etcd/api/v3/etcdserverpb" "go.etcd.io/etcd/api/v3/version" "go.etcd.io/etcd/client/pkg/v3/types" + "go.etcd.io/etcd/raft/v3/raftpb" "go.etcd.io/etcd/server/v3/config" "go.etcd.io/etcd/server/v3/etcdserver/api/membership" + "go.etcd.io/etcd/server/v3/etcdserver/api/snap" + "go.etcd.io/etcd/server/v3/etcdserver/api/v2store" + serverstorage "go.etcd.io/etcd/server/v3/storage" "go.uber.org/zap" ) @@ -138,3 +150,156 @@ func mockMembersJSON(m []etcdserverpb.Member) string { members, _ := json.Marshal(m) return string(members) } + +func TestBootstrapBackend(t *testing.T) { + tests := []struct { + name string + prepareData func(config.ServerConfig) error + expectedConsistentIdx uint64 + expectedError error + }{ + { + name: "bootstrap backend success: no data files", + prepareData: nil, + expectedConsistentIdx: 0, + expectedError: nil, + }, + { + name: "bootstrap backend success: have data files and snapshot db file", + prepareData: prepareData, + expectedConsistentIdx: 5, + expectedError: nil, + }, + // TODO(ahrtr): add more test cases + // https://github.com/etcd-io/etcd/issues/13507 + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + dataDir, err := createDataDir(t) + if err != nil { + t.Fatalf("Failed to create the data dir, unexpected error: %v", err) + } + + cfg := config.ServerConfig{ + Name: "demoNode", + DataDir: dataDir, + BackendFreelistType: bolt.FreelistArrayType, + Logger: zap.NewExample(), + } + + if tt.prepareData != nil { + if err := tt.prepareData(cfg); err != nil { + t.Fatalf("failed to prepare data, unexpected error: %v", err) + } + } + + haveWAL := wal.Exist(cfg.WALDir()) + st := v2store.New(StoreClusterPrefix, StoreKeysPrefix) + ss := snap.New(cfg.Logger, cfg.SnapDir()) + backend, err := bootstrapBackend(cfg, haveWAL, st, ss) + + hasError := err != nil + expectedHasError := tt.expectedError != nil + if hasError != expectedHasError { + t.Errorf("expected error: %v got: %v", expectedHasError, err) + } + if hasError && !strings.Contains(err.Error(), tt.expectedError.Error()) { + t.Fatalf("expected error to contain: %q, got: %q", tt.expectedError.Error(), err.Error()) + } + + if backend.ci.ConsistentIndex() != tt.expectedConsistentIdx { + t.Errorf("expected consistent index: %d, got: %d", tt.expectedConsistentIdx, backend.ci.ConsistentIndex()) + } + }) + } +} + +func createDataDir(t *testing.T) (dataDir string, err error) { + // create the temporary data dir + dataDir = t.TempDir() + + // create ${dataDir}/member/snap + if err = os.MkdirAll(datadir.ToSnapDir(dataDir), 0700); err != nil { + return + } + + // create ${dataDir}/member/wal + err = os.MkdirAll(datadir.ToWalDir(dataDir), 0700) + + return +} + +// prepare data for the test case +func prepareData(cfg config.ServerConfig) (err error) { + var snapshotTerm, snapshotIndex uint64 = 2, 5 + + if err = createWALFileWithSnapshotRecord(cfg, snapshotTerm, snapshotIndex); err != nil { + return + } + + return createSnapshotAndBackendDB(cfg, snapshotTerm, snapshotIndex) +} + +func createWALFileWithSnapshotRecord(cfg config.ServerConfig, snapshotTerm, snapshotIndex uint64) (err error) { + var w *wal.WAL + if w, err = wal.Create(cfg.Logger, cfg.WALDir(), []byte("somedata")); err != nil { + return + } + + defer func() { + err = w.Close() + }() + + walSnap := walpb.Snapshot{ + Index: snapshotIndex, + Term: snapshotTerm, + ConfState: &raftpb.ConfState{ + Voters: []uint64{0x00ffca74}, + AutoLeave: false, + }, + } + + if err = w.SaveSnapshot(walSnap); err != nil { + return + } + + return w.Save(raftpb.HardState{Term: snapshotTerm, Vote: 3, Commit: snapshotIndex}, nil) +} + +func createSnapshotAndBackendDB(cfg config.ServerConfig, snapshotTerm, snapshotIndex uint64) (err error) { + confState := raftpb.ConfState{ + Voters: []uint64{1, 2, 3}, + } + + // create snapshot file + ss := snap.New(cfg.Logger, cfg.SnapDir()) + if err = ss.SaveSnap(raftpb.Snapshot{ + Data: []byte("{}"), + Metadata: raftpb.SnapshotMetadata{ + ConfState: confState, + Index: snapshotIndex, + Term: snapshotTerm, + }, + }); err != nil { + return + } + + // create snapshot db file: "%016x.snap.db" + be := serverstorage.OpenBackend(cfg, nil) + schema.CreateMetaBucket(be.BatchTx()) + schema.UnsafeUpdateConsistentIndex(be.BatchTx(), snapshotIndex, snapshotTerm, false) + schema.MustUnsafeSaveConfStateToBackend(cfg.Logger, be.BatchTx(), &confState) + if err = be.Close(); err != nil { + return + } + sdb := filepath.Join(cfg.SnapDir(), fmt.Sprintf("%016x.snap.db", snapshotIndex)) + if err = os.Rename(cfg.BackendPath(), sdb); err != nil { + return + } + + // create backend db file + be = serverstorage.OpenBackend(cfg, nil) + schema.CreateMetaBucket(be.BatchTx()) + schema.UnsafeUpdateConsistentIndex(be.BatchTx(), 1, 1, false) + return be.Close() +} From 793e081a5b7dfd07b0c539f78f3fbe37d7745f0a Mon Sep 17 00:00:00 2001 From: ahrtr Date: Fri, 10 Dec 2021 05:05:48 +0800 Subject: [PATCH 024/258] remove the redundant line from test.sh --- test.sh | 2 -- 1 file changed, 2 deletions(-) diff --git a/test.sh b/test.sh index 95567152f9ae..f26f7f780d35 100755 --- a/test.sh +++ b/test.sh @@ -32,8 +32,6 @@ # $ COVERDIR=coverage PASSES="build build_cov cov" ./test.sh # $ go tool cover -html ./coverage/cover.out set -e -set -o pipefail - # Consider command as failed when any component of the pipe fails: # https://stackoverflow.com/questions/1221833/pipe-output-and-capture-exit-status-in-bash From d1194977eb0c9849f2a7d39a7414a0e4c9393465 Mon Sep 17 00:00:00 2001 From: Linhai Date: Wed, 15 Dec 2021 01:22:56 -0500 Subject: [PATCH 025/258] fix potential goroutine leaks in TestTxnPanics --- client/v3/txn_test.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/client/v3/txn_test.go b/client/v3/txn_test.go index 012c965a5121..0ee6e71d6be8 100644 --- a/client/v3/txn_test.go +++ b/client/v3/txn_test.go @@ -27,7 +27,7 @@ func TestTxnPanics(t *testing.T) { kv := &kv{} - errc := make(chan string, 1) + errc := make(chan string, 6) df := func() { if s := recover(); s != nil { errc <- s.(string) From 3ebd0a7d0084ffa8b0c4a304508aedd9bebcf89f Mon Sep 17 00:00:00 2001 From: Linhai Date: Wed, 15 Dec 2021 01:54:51 -0500 Subject: [PATCH 026/258] fixing the goroutine leak in TestBackendClose --- server/storage/backend/backend_test.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/server/storage/backend/backend_test.go b/server/storage/backend/backend_test.go index 6434ba931cad..389fa73bed15 100644 --- a/server/storage/backend/backend_test.go +++ b/server/storage/backend/backend_test.go @@ -32,7 +32,7 @@ func TestBackendClose(t *testing.T) { b, _ := betesting.NewTmpBackend(t, time.Hour, 10000) // check close could work - done := make(chan struct{}) + done := make(chan struct{}, 1) go func() { err := b.Close() if err != nil { From 0213b8baeddb969a95a5da64f34c1f533c749caa Mon Sep 17 00:00:00 2001 From: Linhai Date: Wed, 15 Dec 2021 02:43:49 -0500 Subject: [PATCH 027/258] fixing goroutine leaks in testServer --- pkg/proxy/server_test.go | 3 +++ 1 file changed, 3 insertions(+) diff --git a/pkg/proxy/server_test.go b/pkg/proxy/server_test.go index d2d98990ef3c..6424cbb7cda4 100644 --- a/pkg/proxy/server_test.go +++ b/pkg/proxy/server_test.go @@ -96,6 +96,7 @@ func testServer(t *testing.T, scheme string, secure bool, delayTx bool) { writec <- data1 now := time.Now() if d := <-recvc; !bytes.Equal(data1, d) { + close(writec) t.Fatalf("expected %q, got %q", string(data1), string(d)) } took1 := time.Since(now) @@ -110,6 +111,7 @@ func testServer(t *testing.T, scheme string, secure bool, delayTx bool) { writec <- data2 now = time.Now() if d := <-recvc; !bytes.Equal(data2, d) { + close(writec) t.Fatalf("expected %q, got %q", string(data2), string(d)) } took2 := time.Since(now) @@ -122,6 +124,7 @@ func testServer(t *testing.T, scheme string, secure bool, delayTx bool) { if delayTx { p.UndelayTx() if took2 < lat-rv { + close(writec) t.Fatalf("expected took2 %v (with latency) > delay: %v", took2, lat-rv) } } From 0098dbf3507f3f139eb40e05ace82d02bca317f5 Mon Sep 17 00:00:00 2001 From: Linhai Song Date: Wed, 15 Dec 2021 22:38:25 -0500 Subject: [PATCH 028/258] fixing two goroutine leaks and one panic --- client/v2/client.go | 4 +++- server/storage/mvcc/watchable_store_test.go | 4 ++++ 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/client/v2/client.go b/client/v2/client.go index b1223964ee5c..c34bc9d7c849 100644 --- a/client/v2/client.go +++ b/client/v2/client.go @@ -607,7 +607,9 @@ func (c *simpleHTTPClient) Do(ctx context.Context, act httpAction) (*http.Respon select { case <-ctx.Done(): - resp.Body.Close() + if resp != nil { + resp.Body.Close() + } <-done return nil, nil, ctx.Err() case <-done: diff --git a/server/storage/mvcc/watchable_store_test.go b/server/storage/mvcc/watchable_store_test.go index c34e7446bb19..0ea27156088e 100644 --- a/server/storage/mvcc/watchable_store_test.go +++ b/server/storage/mvcc/watchable_store_test.go @@ -35,6 +35,8 @@ func TestWatch(t *testing.T) { s := newWatchableStore(zap.NewExample(), b, &lease.FakeLessor{}, StoreConfig{}) defer func() { + b.Close() + s.Close() s.store.Close() os.Remove(tmpPath) }() @@ -536,6 +538,8 @@ func TestWatchVictims(t *testing.T) { s := newWatchableStore(zap.NewExample(), b, &lease.FakeLessor{}, StoreConfig{}) defer func() { + b.Close() + s.Close() s.store.Close() os.Remove(tmpPath) chanBufLen, maxWatchersPerSync = oldChanBufLen, oldMaxWatchersPerSync From ddb9554eeccdce49b81d469a42d575e004bb0564 Mon Sep 17 00:00:00 2001 From: Dirkjan Bussink Date: Fri, 17 Dec 2021 16:41:38 +0100 Subject: [PATCH 029/258] server/etcdmain: add build support for Apple M1 This has been additionally verified by running the tests locally as a basic smoke test. GitHub Actions doesn't provide MacOS M1 (arm64) yet, so there's no good way to automate testing. Ran `TMPDIR=/tmp make test` locally. The `TMPDIR` bit is needed so there's no really long path used that breaks Unix socket setup in one of the tests. --- .github/workflows/build.yaml | 4 ++++ scripts/build-binary | 4 ++++ 2 files changed, 8 insertions(+) diff --git a/.github/workflows/build.yaml b/.github/workflows/build.yaml index dd12ca5e7ac5..3098ef2f6b9a 100644 --- a/.github/workflows/build.yaml +++ b/.github/workflows/build.yaml @@ -10,6 +10,7 @@ jobs: - linux-amd64 - linux-386 - darwin-amd64 + - darwin-arm64 - windows-amd64 - linux-arm - linux-arm64 @@ -34,6 +35,9 @@ jobs: darwin-amd64) ARCH=amd64 GOOS=darwin GO_BUILD_FLAGS='-v -mod=readonly' ./build.sh ;; + darwin-arm64) + ARCH=arm64 GOOS=darwin GO_BUILD_FLAGS='-v -mod=readonly' ./build.sh + ;; windows-amd64) ARCH=amd64 GOOS=windows GO_BUILD_FLAGS='-v -mod=readonly' ./build.sh ;; diff --git a/scripts/build-binary b/scripts/build-binary index 6186424aa9ef..b819a3e57575 100755 --- a/scripts/build-binary +++ b/scripts/build-binary @@ -79,6 +79,10 @@ function main { TARGET_ARCHS+=("s390x") fi + if [ ${GOOS} == "darwin" ]; then + TARGET_ARCHS+=("arm64") + fi + for TARGET_ARCH in "${TARGET_ARCHS[@]}"; do export GOARCH=${TARGET_ARCH} From bbb187dcc0431f8316310065abb2d92bb2c76332 Mon Sep 17 00:00:00 2001 From: Stephen Augustus Date: Fri, 17 Dec 2021 16:06:37 -0500 Subject: [PATCH 030/258] images: Use Kubernetes debian-base:bullseye-v1.1.0 as base image Signed-off-by: Stephen Augustus --- Dockerfile-release.amd64 | 4 ++-- Dockerfile-release.arm64 | 4 ++-- Dockerfile-release.ppc64le | 4 ++-- Dockerfile-release.s390x | 4 ++-- 4 files changed, 8 insertions(+), 8 deletions(-) diff --git a/Dockerfile-release.amd64 b/Dockerfile-release.amd64 index ad9bd068f48b..deeefc853bdf 100644 --- a/Dockerfile-release.amd64 +++ b/Dockerfile-release.amd64 @@ -1,5 +1,5 @@ -# TODO: move to k8s.gcr.io/build-image/debian-base:bullseye-v1.y.z when patched -FROM debian:bullseye-20210927 +# base image source: https://git.k8s.io/release/images/build/debian-base +FROM --platform=linux/amd64 k8s.gcr.io/build-image/debian-base:bullseye-v1.1.0 ADD etcd /usr/local/bin/ ADD etcdctl /usr/local/bin/ diff --git a/Dockerfile-release.arm64 b/Dockerfile-release.arm64 index c023d215f66a..5afcafe5f917 100644 --- a/Dockerfile-release.arm64 +++ b/Dockerfile-release.arm64 @@ -1,5 +1,5 @@ -# TODO: move to k8s.gcr.io/build-image/debian-base-arm64:bullseye-1.y.z when patched -FROM arm64v8/debian:bullseye-20210927 +# base image source: https://git.k8s.io/release/images/build/debian-base +FROM --platform=linux/arm64 k8s.gcr.io/build-image/debian-base:bullseye-v1.1.0 ADD etcd /usr/local/bin/ ADD etcdctl /usr/local/bin/ diff --git a/Dockerfile-release.ppc64le b/Dockerfile-release.ppc64le index 6e1e94625912..12f84938d343 100644 --- a/Dockerfile-release.ppc64le +++ b/Dockerfile-release.ppc64le @@ -1,5 +1,5 @@ -# TODO: move to k8s.gcr.io/build-image/debian-base-ppc64le:bullseye-1.y.z when patched -FROM ppc64le/debian:bullseye-20210927 +# base image source: https://git.k8s.io/release/images/build/debian-base +FROM --platform=linux/ppc64le k8s.gcr.io/build-image/debian-base:bullseye-v1.1.0 ADD etcd /usr/local/bin/ ADD etcdctl /usr/local/bin/ diff --git a/Dockerfile-release.s390x b/Dockerfile-release.s390x index a98c6452af44..546596f75afb 100644 --- a/Dockerfile-release.s390x +++ b/Dockerfile-release.s390x @@ -1,5 +1,5 @@ -# TODO: move to k8s.gcr.io/build-image/debian-base-s390x:bullseye-1.y.z when patched -FROM s390x/debian:bullseye-20210927 +# base image source: https://git.k8s.io/release/images/build/debian-base +FROM --platform=linux/s390x k8s.gcr.io/build-image/debian-base:bullseye-v1.1.0 ADD etcd /usr/local/bin/ ADD etcdctl /usr/local/bin/ From 5e8f50bb09d407873eccc3641a021557b4437fdb Mon Sep 17 00:00:00 2001 From: Linhai Song Date: Fri, 17 Dec 2021 20:03:19 -0500 Subject: [PATCH 031/258] remove the extra stop --- server/storage/mvcc/watchable_store_test.go | 2 -- 1 file changed, 2 deletions(-) diff --git a/server/storage/mvcc/watchable_store_test.go b/server/storage/mvcc/watchable_store_test.go index 0ea27156088e..7fe881884f58 100644 --- a/server/storage/mvcc/watchable_store_test.go +++ b/server/storage/mvcc/watchable_store_test.go @@ -37,7 +37,6 @@ func TestWatch(t *testing.T) { defer func() { b.Close() s.Close() - s.store.Close() os.Remove(tmpPath) }() @@ -540,7 +539,6 @@ func TestWatchVictims(t *testing.T) { defer func() { b.Close() s.Close() - s.store.Close() os.Remove(tmpPath) chanBufLen, maxWatchersPerSync = oldChanBufLen, oldMaxWatchersPerSync }() From 246e7eba095888a443dc115be1b032405c32086f Mon Sep 17 00:00:00 2001 From: Linhai Date: Tue, 21 Dec 2021 04:46:39 -0500 Subject: [PATCH 032/258] fixing the goroutine in two unit tests --- server/storage/mvcc/kvstore_test.go | 2 ++ server/storage/mvcc/watchable_store_test.go | 3 ++- 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/server/storage/mvcc/kvstore_test.go b/server/storage/mvcc/kvstore_test.go index 0274308142c2..99e95ade1927 100644 --- a/server/storage/mvcc/kvstore_test.go +++ b/server/storage/mvcc/kvstore_test.go @@ -536,6 +536,8 @@ type hashKVResult struct { func TestHashKVWhenCompacting(t *testing.T) { b, tmpPath := betesting.NewDefaultTmpBackend(t) s := NewStore(zap.NewExample(), b, &lease.FakeLessor{}, StoreConfig{}) + defer s.Close() + defer b.Close() defer os.Remove(tmpPath) rev := 10000 diff --git a/server/storage/mvcc/watchable_store_test.go b/server/storage/mvcc/watchable_store_test.go index c34e7446bb19..3fc85729566e 100644 --- a/server/storage/mvcc/watchable_store_test.go +++ b/server/storage/mvcc/watchable_store_test.go @@ -536,7 +536,8 @@ func TestWatchVictims(t *testing.T) { s := newWatchableStore(zap.NewExample(), b, &lease.FakeLessor{}, StoreConfig{}) defer func() { - s.store.Close() + s.Close() + b.Close() os.Remove(tmpPath) chanBufLen, maxWatchersPerSync = oldChanBufLen, oldMaxWatchersPerSync }() From a45c73d9b12da436a4a36ac1c344492c1eb3ea67 Mon Sep 17 00:00:00 2001 From: Linhai Date: Tue, 21 Dec 2021 17:49:47 -0500 Subject: [PATCH 033/258] resolve the conflict --- server/storage/mvcc/watchable_store_test.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/server/storage/mvcc/watchable_store_test.go b/server/storage/mvcc/watchable_store_test.go index 3fc85729566e..2b53206ef88b 100644 --- a/server/storage/mvcc/watchable_store_test.go +++ b/server/storage/mvcc/watchable_store_test.go @@ -536,8 +536,8 @@ func TestWatchVictims(t *testing.T) { s := newWatchableStore(zap.NewExample(), b, &lease.FakeLessor{}, StoreConfig{}) defer func() { - s.Close() b.Close() + s.Close() os.Remove(tmpPath) chanBufLen, maxWatchersPerSync = oldChanBufLen, oldMaxWatchersPerSync }() From 661e0a91ef115fc5ebcb3bfc717161082f924525 Mon Sep 17 00:00:00 2001 From: ahrtr Date: Tue, 7 Dec 2021 10:57:10 +0800 Subject: [PATCH 034/258] added a new flag --rev to make-mirror command to support incremental mirror --- CHANGELOG-3.6.md | 1 + etcdctl/ctlv3/command/make_mirror_command.go | 43 ++++++++++++-------- tests/e2e/ctl_v3_make_mirror_test.go | 13 ++++++ 3 files changed, 41 insertions(+), 16 deletions(-) diff --git a/CHANGELOG-3.6.md b/CHANGELOG-3.6.md index e97c3e1a63dd..2ab8a5ddd969 100644 --- a/CHANGELOG-3.6.md +++ b/CHANGELOG-3.6.md @@ -34,6 +34,7 @@ See [code changes](https://github.com/etcd-io/etcd/compare/v3.5.0...v3.6.0). - Add [`etcd --log-format`](https://github.com/etcd-io/etcd/pull/13339) flag to support log format. - Add [`etcd --experimental-max-learners`](https://github.com/etcd-io/etcd/pull/13377) flag to allow configuration of learner max membership. - Add [`etcd --experimental-enable-lease-checkpoint-persist`](https://github.com/etcd-io/etcd/pull/13508) flag to handle upgrade from v3.5.2 clusters with this feature enabled. +- Add [`etcdctl make-mirror --rev`](https://github.com/etcd-io/etcd/pull/13519) flag to support incremental mirror. - Fix [non mutating requests pass through quotaKVServer when NOSPACE](https://github.com/etcd-io/etcd/pull/13435) - Fix [exclude the same alarm type activated by multiple peers](https://github.com/etcd-io/etcd/pull/13467). - Fix [Provide a better liveness probe for when etcd runs as a Kubernetes pod](https://github.com/etcd-io/etcd/pull/13399) diff --git a/etcdctl/ctlv3/command/make_mirror_command.go b/etcdctl/ctlv3/command/make_mirror_command.go index 777c1dd0c07f..3d8b869d0c87 100644 --- a/etcdctl/ctlv3/command/make_mirror_command.go +++ b/etcdctl/ctlv3/command/make_mirror_command.go @@ -43,6 +43,7 @@ var ( mmuser string mmpassword string mmnodestprefix bool + mmrev int64 ) // NewMakeMirrorCommand returns the cobra command for "makeMirror". @@ -54,6 +55,7 @@ func NewMakeMirrorCommand() *cobra.Command { } c.Flags().StringVar(&mmprefix, "prefix", "", "Key-value prefix to mirror") + c.Flags().Int64Var(&mmrev, "rev", 0, "Specify the kv revision to start to mirror") c.Flags().StringVar(&mmdestprefix, "dest-prefix", "", "destination prefix to mirror a prefix to a different prefix in the destination cluster") c.Flags().BoolVar(&mmnodestprefix, "no-dest-prefix", false, "mirror key-values to the root of the destination cluster") c.Flags().StringVar(&mmcert, "dest-cert", "", "Identify secure client using this TLS certificate file for the destination cluster") @@ -142,28 +144,37 @@ func makeMirror(ctx context.Context, c *clientv3.Client, dc *clientv3.Client) er } }() - s := mirror.NewSyncer(c, mmprefix, 0) + startRev := mmrev - 1 + if startRev < 0 { + startRev = 0 + } - rc, errc := s.SyncBase(ctx) + s := mirror.NewSyncer(c, mmprefix, startRev) - // if remove destination prefix is false and destination prefix is empty set the value of destination prefix same as prefix - if !mmnodestprefix && len(mmdestprefix) == 0 { - mmdestprefix = mmprefix - } + // If a rev is provided, then do not sync the whole key space. + // Instead, just start watching the key space starting from the rev + if startRev == 0 { + rc, errc := s.SyncBase(ctx) - for r := range rc { - for _, kv := range r.Kvs { - _, err := dc.Put(ctx, modifyPrefix(string(kv.Key)), string(kv.Value)) - if err != nil { - return err + // if remove destination prefix is false and destination prefix is empty set the value of destination prefix same as prefix + if !mmnodestprefix && len(mmdestprefix) == 0 { + mmdestprefix = mmprefix + } + + for r := range rc { + for _, kv := range r.Kvs { + _, err := dc.Put(ctx, modifyPrefix(string(kv.Key)), string(kv.Value)) + if err != nil { + return err + } + atomic.AddInt64(&total, 1) } - atomic.AddInt64(&total, 1) } - } - err := <-errc - if err != nil { - return err + err := <-errc + if err != nil { + return err + } } wc := s.SyncUpdates(ctx) diff --git a/tests/e2e/ctl_v3_make_mirror_test.go b/tests/e2e/ctl_v3_make_mirror_test.go index deb4b50e46d8..bc4f36f36cce 100644 --- a/tests/e2e/ctl_v3_make_mirror_test.go +++ b/tests/e2e/ctl_v3_make_mirror_test.go @@ -25,6 +25,7 @@ import ( func TestCtlV3MakeMirror(t *testing.T) { testCtl(t, makeMirrorTest) } func TestCtlV3MakeMirrorModifyDestPrefix(t *testing.T) { testCtl(t, makeMirrorModifyDestPrefixTest) } func TestCtlV3MakeMirrorNoDestPrefix(t *testing.T) { testCtl(t, makeMirrorNoDestPrefixTest) } +func TestCtlV3MakeMirrorWithWatchRev(t *testing.T) { testCtl(t, makeMirrorWithWatchRev) } func makeMirrorTest(cx ctlCtx) { var ( @@ -59,6 +60,18 @@ func makeMirrorNoDestPrefixTest(cx ctlCtx) { testMirrorCommand(cx, flags, kvs, kvs2, srcprefix, destprefix) } +func makeMirrorWithWatchRev(cx ctlCtx) { + var ( + flags = []string{"--prefix", "o_", "--no-dest-prefix", "--rev", "4"} + kvs = []kv{{"o_key1", "val1"}, {"o_key2", "val2"}, {"o_key3", "val3"}, {"o_key4", "val4"}} + kvs2 = []kvExec{{key: "key3", val: "val3"}, {key: "key4", val: "val4"}} + srcprefix = "o_" + destprefix = "key" + ) + + testMirrorCommand(cx, flags, kvs, kvs2, srcprefix, destprefix) +} + func testMirrorCommand(cx ctlCtx, flags []string, sourcekvs []kv, destkvs []kvExec, srcprefix, destprefix string) { // set up another cluster to mirror with mirrorcfg := e2e.NewConfigAutoTLS() From f24e0234b33bedc1254e9ccb88f4d16cb891f03f Mon Sep 17 00:00:00 2001 From: yankay Date: Thu, 23 Dec 2021 21:23:58 +0800 Subject: [PATCH 035/258] Use Distroless as base image Signed-off-by: yankay --- Dockerfile-release.amd64 | 7 +++++-- Dockerfile-release.arm64 | 7 +++++-- Dockerfile-release.ppc64le | 8 ++++++-- Dockerfile-release.s390x | 8 ++++++-- 4 files changed, 22 insertions(+), 8 deletions(-) diff --git a/Dockerfile-release.amd64 b/Dockerfile-release.amd64 index deeefc853bdf..cb93afe76e66 100644 --- a/Dockerfile-release.amd64 +++ b/Dockerfile-release.amd64 @@ -1,5 +1,8 @@ -# base image source: https://git.k8s.io/release/images/build/debian-base -FROM --platform=linux/amd64 k8s.gcr.io/build-image/debian-base:bullseye-v1.1.0 +FROM --platform=linux/amd64 busybox:1.34.1 as source +FROM --platform=linux/amd64 gcr.io/distroless/base-debian11 + +COPY --from=source /bin/sh /bin/sh +COPY --from=source /bin/mkdir /bin/mkdir ADD etcd /usr/local/bin/ ADD etcdctl /usr/local/bin/ diff --git a/Dockerfile-release.arm64 b/Dockerfile-release.arm64 index 5afcafe5f917..53d3c274151c 100644 --- a/Dockerfile-release.arm64 +++ b/Dockerfile-release.arm64 @@ -1,5 +1,8 @@ -# base image source: https://git.k8s.io/release/images/build/debian-base -FROM --platform=linux/arm64 k8s.gcr.io/build-image/debian-base:bullseye-v1.1.0 +FROM --platform=linux/arm64 busybox:1.34.1 as source +FROM --platform=linux/arm64 gcr.io/distroless/base-debian11 + +COPY --from=source /bin/sh /bin/sh +COPY --from=source /bin/mkdir /bin/mkdir ADD etcd /usr/local/bin/ ADD etcdctl /usr/local/bin/ diff --git a/Dockerfile-release.ppc64le b/Dockerfile-release.ppc64le index 12f84938d343..81fc64bc67d8 100644 --- a/Dockerfile-release.ppc64le +++ b/Dockerfile-release.ppc64le @@ -1,5 +1,9 @@ -# base image source: https://git.k8s.io/release/images/build/debian-base -FROM --platform=linux/ppc64le k8s.gcr.io/build-image/debian-base:bullseye-v1.1.0 +FROM --platform=linux/ppc64le busybox:1.34.1 as source +FROM --platform=linux/ppc64le gcr.io/distroless/base-debian11 + +COPY --from=source /bin/sh /bin/sh +COPY --from=source /bin/mkdir /bin/mkdir + ADD etcd /usr/local/bin/ ADD etcdctl /usr/local/bin/ diff --git a/Dockerfile-release.s390x b/Dockerfile-release.s390x index 546596f75afb..42bc5d5a018f 100644 --- a/Dockerfile-release.s390x +++ b/Dockerfile-release.s390x @@ -1,5 +1,9 @@ -# base image source: https://git.k8s.io/release/images/build/debian-base -FROM --platform=linux/s390x k8s.gcr.io/build-image/debian-base:bullseye-v1.1.0 +FROM --platform=linux/s390x busybox:1.34.1 as source +FROM --platform=linux/s390x gcr.io/distroless/base-debian11 + +COPY --from=source /bin/sh /bin/sh +COPY --from=source /bin/mkdir /bin/mkdir + ADD etcd /usr/local/bin/ ADD etcdctl /usr/local/bin/ From 98b0d901e81adc02ee7c6097a4c4844f75fb0fd2 Mon Sep 17 00:00:00 2001 From: Linhai Date: Fri, 24 Dec 2021 15:57:38 -0500 Subject: [PATCH 036/258] fixing goroutine leaks --- server/auth/store_test.go | 2 +- server/storage/mvcc/kvstore_test.go | 2 ++ server/storage/mvcc/watchable_store_test.go | 3 ++- server/storage/mvcc/watcher_test.go | 3 ++- 4 files changed, 7 insertions(+), 3 deletions(-) diff --git a/server/auth/store_test.go b/server/auth/store_test.go index 71accbd3eb88..9b637dfe2d62 100644 --- a/server/auth/store_test.go +++ b/server/auth/store_test.go @@ -33,7 +33,7 @@ import ( ) func dummyIndexWaiter(index uint64) <-chan struct{} { - ch := make(chan struct{}) + ch := make(chan struct{}, 1) go func() { ch <- struct{}{} }() diff --git a/server/storage/mvcc/kvstore_test.go b/server/storage/mvcc/kvstore_test.go index 0274308142c2..be92f13d9ba7 100644 --- a/server/storage/mvcc/kvstore_test.go +++ b/server/storage/mvcc/kvstore_test.go @@ -722,6 +722,8 @@ func TestConcurrentReadTxAndWrite(t *testing.T) { ) b, tmpPath := betesting.NewDefaultTmpBackend(t) s := NewStore(zap.NewExample(), b, &lease.FakeLessor{}, StoreConfig{}) + defer b.Close() + defer s.Close() defer os.Remove(tmpPath) var wg sync.WaitGroup diff --git a/server/storage/mvcc/watchable_store_test.go b/server/storage/mvcc/watchable_store_test.go index 7fe881884f58..75574d6ee317 100644 --- a/server/storage/mvcc/watchable_store_test.go +++ b/server/storage/mvcc/watchable_store_test.go @@ -265,7 +265,8 @@ func TestWatchFutureRev(t *testing.T) { s := newWatchableStore(zap.NewExample(), b, &lease.FakeLessor{}, StoreConfig{}) defer func() { - s.store.Close() + b.Close() + s.Close() os.Remove(tmpPath) }() diff --git a/server/storage/mvcc/watcher_test.go b/server/storage/mvcc/watcher_test.go index 1086635f46a5..ebf0181adc34 100644 --- a/server/storage/mvcc/watcher_test.go +++ b/server/storage/mvcc/watcher_test.go @@ -216,7 +216,8 @@ func TestWatchDeleteRange(t *testing.T) { s := newWatchableStore(zap.NewExample(), b, &lease.FakeLessor{}, StoreConfig{}) defer func() { - s.store.Close() + b.Close() + s.Close() os.Remove(tmpPath) }() From e6f28dbeb2a91a7278ccaadd3f7d6aaa07d25d56 Mon Sep 17 00:00:00 2001 From: Ting Yuan Date: Mon, 27 Dec 2021 20:36:26 +0800 Subject: [PATCH 037/258] Fix goroutine leaks in TestNodeProposeAddDuplicateNode raft: fix goroutine leaks in TestNodeProposeAddDuplicateNode The goroutine created with `n.run()` will leak if we forget to call `n.Stop()` --- raft/node_test.go | 1 + 1 file changed, 1 insertion(+) diff --git a/raft/node_test.go b/raft/node_test.go index e44d073e2686..e56a1cabe45b 100644 --- a/raft/node_test.go +++ b/raft/node_test.go @@ -860,6 +860,7 @@ func TestNodeProposeAddLearnerNode(t *testing.T) { <-applyConfChan close(stop) <-done + n.Stop() } func TestAppendPagination(t *testing.T) { From df8efd385328e3a8a1014074654faba93f9e43e6 Mon Sep 17 00:00:00 2001 From: Ting Yuan Date: Mon, 27 Dec 2021 20:55:02 +0800 Subject: [PATCH 038/258] Fix goroutine leaks in TestCommitPagination raft: fix goroutine leaks in TestCommitPagination The goroutine created with n.run() will leak if we forget to call n.Stop(). We can replay the goroutine leaks by using [goleak](https://github.com/uber-go/goleak): ``` $ cd raft && env go test -short -v -timeout=3m --race -run=TestCommitPagination. ... ... raft2021/12/27 20:47:15 INFO: raft.node: 1 elected leader 1 at term 1 leaks.go:78: found unexpected goroutines: [Goroutine 20 in state select, with go.etcd.io/etcd/raft/v3.(*node).run on top of the stack: goroutine 20 [select]: go.etcd.io/etcd/raft/v3.(*node).run(0xc00036f260) /home/yuanting/work/dev/goprojects/etcd/raft/node.go:344 +0xc1d created by go.etcd.io/etcd/raft/v3.TestCommitPagination /home/yuanting/work/dev/goprojects/etcd/raft/node_test.go:920 +0x554 ] --- FAIL: TestCommitPagination (0.45s) FAIL FAIL go.etcd.io/etcd/raft/v3 0.508s FAIL ``` --- raft/node_test.go | 1 + 1 file changed, 1 insertion(+) diff --git a/raft/node_test.go b/raft/node_test.go index e44d073e2686..b3dc88bada26 100644 --- a/raft/node_test.go +++ b/raft/node_test.go @@ -945,6 +945,7 @@ func TestCommitPagination(t *testing.T) { } s.Append(rd.Entries) n.Advance() + n.Stop() } type ignoreSizeHintMemStorage struct { From 97d1f935f67b084089d2d55c8812560b02d64250 Mon Sep 17 00:00:00 2001 From: horizonzy Date: Wed, 29 Dec 2021 11:23:38 +0800 Subject: [PATCH 039/258] avoid always update meta term. --- server/storage/schema/cindex.go | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/server/storage/schema/cindex.go b/server/storage/schema/cindex.go index 5fb4d5bf6cae..52d9ef126cd8 100644 --- a/server/storage/schema/cindex.go +++ b/server/storage/schema/cindex.go @@ -70,6 +70,17 @@ func UnsafeUpdateConsistentIndex(tx backend.BatchTx, index uint64, term uint64, if term == oldTerm && index <= oldi { return } + bs1 := make([]byte, 8) + binary.BigEndian.PutUint64(bs1, index) + // put the index into the underlying backend + // tx has been locked in TxnBegin, so there is no need to lock it again + tx.UnsafePut(Meta, MetaConsistentIndexKeyName, bs1) + if term > 0 && term > oldTerm { + bs2 := make([]byte, 8) + binary.BigEndian.PutUint64(bs2, term) + tx.UnsafePut(Meta, MetaTermKeyName, bs2) + } + return } bs1 := make([]byte, 8) From 77bf0a5a9e3c40055595dd7d03a9ed6886f2fb43 Mon Sep 17 00:00:00 2001 From: Your Name Date: Wed, 29 Dec 2021 17:34:18 +0800 Subject: [PATCH 040/258] update cobra version to 1.2.1 Signed-off-by: yankay --- etcdctl/go.mod | 2 +- etcdctl/go.sum | 298 +++++++++++++++++++++++++++++++++++------ etcdutl/go.mod | 2 +- etcdutl/go.sum | 298 +++++++++++++++++++++++++++++++++++------ go.mod | 2 +- go.sum | 297 +++++++++++++++++++++++++++++++++++------ pkg/go.mod | 13 +- pkg/go.sum | 355 ++++++++++++++++++++++++++++++++++++++----------- server/go.mod | 2 +- server/go.sum | 298 +++++++++++++++++++++++++++++++++++------ tests/go.mod | 2 +- tests/go.sum | 297 +++++++++++++++++++++++++++++++++++------ 12 files changed, 1561 insertions(+), 305 deletions(-) diff --git a/etcdctl/go.mod b/etcdctl/go.mod index f08655bde072..f3eb943ba6fc 100644 --- a/etcdctl/go.mod +++ b/etcdctl/go.mod @@ -6,7 +6,7 @@ require ( github.com/bgentry/speakeasy v0.1.0 github.com/dustin/go-humanize v1.0.0 github.com/olekukonko/tablewriter v0.0.5 - github.com/spf13/cobra v1.1.3 + github.com/spf13/cobra v1.2.1 github.com/spf13/pflag v1.0.5 github.com/urfave/cli v1.22.4 go.etcd.io/etcd/api/v3 v3.5.0 diff --git a/etcdctl/go.sum b/etcdctl/go.sum index 840df2269895..9eaa92a0b980 100644 --- a/etcdctl/go.sum +++ b/etcdctl/go.sum @@ -4,13 +4,39 @@ cloud.google.com/go v0.38.0/go.mod h1:990N+gfupTy94rShfmMCWGDn0LpTmnzTp2qbd1dvSR cloud.google.com/go v0.44.1/go.mod h1:iSa0KzasP4Uvy3f1mN/7PiObzGgflwredwwASm/v6AU= cloud.google.com/go v0.44.2/go.mod h1:60680Gw3Yr4ikxnPRS/oxxkBccT6SA1yMk63TGekxKY= cloud.google.com/go v0.45.1/go.mod h1:RpBamKRgapWJb87xiFSdk4g1CME7QZg3uwTez+TSTjc= -cloud.google.com/go v0.46.3 h1:AVXDdKsrtX33oR9fbCMu/+c1o8Ofjq6Ku/MInaLVg5Y= cloud.google.com/go v0.46.3/go.mod h1:a6bKKbmY7er1mI7TEI4lsAkts/mkhTSZK8w33B4RAg0= +cloud.google.com/go v0.50.0/go.mod h1:r9sluTvynVuxRIOHXQEHMFffphuXHOMZMycpNR5e6To= +cloud.google.com/go v0.52.0/go.mod h1:pXajvRH/6o3+F9jDHZWQ5PbGhn+o8w9qiu/CffaVdO4= +cloud.google.com/go v0.53.0/go.mod h1:fp/UouUEsRkN6ryDKNW/Upv/JBKnv6WDthjR6+vze6M= +cloud.google.com/go v0.54.0/go.mod h1:1rq2OEkV3YMf6n/9ZvGWI3GWw0VoqH/1x2nd8Is/bPc= +cloud.google.com/go v0.56.0/go.mod h1:jr7tqZxxKOVYizybht9+26Z/gUq7tiRzu+ACVAMbKVk= +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.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 h1:at8Tk2zUz63cLPR0JPWm5vp77pEZmzxEQBEfRKn1VV8= +cloud.google.com/go v0.81.0/go.mod h1:mk/AM35KwGk/Nm2YSeZbxXdrNK3KZOYHmLkOqC2V6E0= 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.4.0/go.mod h1:S8dzgnTigyfTmLBfrtrhyYhwRxG72rYxvftPBK2Dvzc= +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.8.0/go.mod h1:J5hqkt3O0uAFnINi6JXValWIb1v0goeZM77hZzJN/fQ= 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/firestore v1.1.0/go.mod h1:ulACoGHTpvq5r8rxGJ4ddJZBZqakUQqClKRT5SZwBmk= 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.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/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.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.10.0/go.mod h1:FLPqc6j+Ki4BU591ie1oL6qBQGu2Bl/tZ9ullr3+Kg0= dmitri.shuralyov.com/gpu/mtl v0.0.0-20190408044501-666a987793e9/go.mod h1:H6x//7gZCb22OMCxBHrMx7a5I7Hp++hsVxbQ4BYO7hU= github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= github.com/BurntSushi/xgb v0.0.0-20160522181843-27f122750802/go.mod h1:IVnqGOEym/WlBOVXweHU+Q+/VP0lqqI8lqeDx9IjBqo= @@ -30,7 +56,7 @@ github.com/beorn7/perks v1.0.1 h1:VlbKKnNfV8bJzeqoa4cOKqO6bYr3WgKZxO8Z16+hsOM= github.com/beorn7/perks v1.0.1/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6rlkpw= github.com/bgentry/speakeasy v0.1.0 h1:ByYyxL9InA1OWqxJqqp2A5pYHUrCiAL6K3J+LKSsQkY= github.com/bgentry/speakeasy v0.1.0/go.mod h1:+zsyZBPWlz7T6j88CTgSN5bM796AkVf0kBD4zp0CCIs= -github.com/bketelsen/crypt v0.0.3-0.20200106085610-5cbc8cc4026c/go.mod h1:MKsuJmJgSg28kpZDP6UIiPt0e0Oz0kqKNGyRaWEPv84= +github.com/bketelsen/crypt v0.0.4/go.mod h1:aI6NrJ0pMGgvZKL1iVgXLnfIFJtfV+bKCoqOes/6LfM= github.com/cenkalti/backoff/v4 v4.1.1/go.mod h1:scbssz8iZGpm3xbr14ovlUdkxfGXNInqkPWOWmG2CLw= github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU= github.com/certifi/gocertifi v0.0.0-20191021191039-0944d244cd40/go.mod h1:sGbDF6GwGcLpkNXPUTkMRoywsNa/ol15pxFe6ERfguA= @@ -40,8 +66,12 @@ github.com/cespare/xxhash v1.1.0 h1:a6HrQnmkObjyL+Gs60czilIUGqrzKutQD6XZog3p+ko= github.com/cespare/xxhash v1.1.0/go.mod h1:XrSqR1VqqWfGrhpAt58auRo0WTKS1nRRg3ghfAqPWnc= github.com/cespare/xxhash/v2 v2.1.1 h1:6MnRN8NT7+YBpUIWxHtefFZOKTAPgGjpQSxqLNn0+qY= github.com/cespare/xxhash/v2 v2.1.1/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= +github.com/chzyer/logex v1.1.10/go.mod h1:+Ywpsq7O8HXn0nuIou7OrIPyXbp3wmkHB+jjWRnGsAI= +github.com/chzyer/readline v0.0.0-20180603132655-2972be24d48e/go.mod h1:nSuG5e5PlCu98SY8svDHJxuZscDgtXS6KTTbou5AhLI= +github.com/chzyer/test v0.0.0-20180213035817-a1ea475d72b1/go.mod h1:Q3SI9o4m/ZMnBNeIyt5eFwwo7qiLfzFZmjNmxjkiQlU= github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw= 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/xds/go v0.0.0-20210312221358-fbca930ec8ed/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs= github.com/cncf/xds/go v0.0.0-20210805033703-aa0b78936158/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs= @@ -51,15 +81,10 @@ github.com/cockroachdb/errors v1.2.4 h1:Lap807SXTH5tri2TivECb/4abUkMZC9zRoLarvcK github.com/cockroachdb/errors v1.2.4/go.mod h1:rQD95gz6FARkaKkQXUksEje/d9a6wBJoCr5oaCLELYA= github.com/cockroachdb/logtags v0.0.0-20190617123548-eb05cc24525f h1:o/kfcElHqOiXqcou5a3rIlMc7oJbMQkeLk0VQJ7zgqY= github.com/cockroachdb/logtags v0.0.0-20190617123548-eb05cc24525f/go.mod h1:i/u985jwjWRlyHXQbwatDASoW0RMlZ/3i9yJHE2xLkI= -github.com/coreos/bbolt v1.3.2/go.mod h1:iRUV2dpdMOn7Bo10OQBFzIJO9kkE559Wcmn+qkEiiKk= -github.com/coreos/etcd v3.3.13+incompatible/go.mod h1:uF7uidLiAD3TWHmW31ZFd/JWoc32PjwdhPthX9715RE= github.com/coreos/go-semver v0.3.0 h1:wkHLiw0WNATZnSG7epLsujiMCgPAc9xhjJ4tgnAxmfM= github.com/coreos/go-semver v0.3.0/go.mod h1:nnelYz7RCh+5ahJtPPxZlU+153eP4D4r3EedlOD2RNk= -github.com/coreos/go-systemd v0.0.0-20190321100706-95778dfbb74e h1:Wf6HqHfScWJN9/ZjdUKyjop4mf3Qdd+1TvvltAvM3m8= -github.com/coreos/go-systemd v0.0.0-20190321100706-95778dfbb74e/go.mod h1:F5haX7vjVVG0kc13fIWeqUViNPyEJxv/OmvnBo0Yme4= github.com/coreos/go-systemd/v22 v22.3.2 h1:D9/bQk5vlXQFZ6Kwuu6zaiXJ9oTPe68++AzAJc1DzSI= github.com/coreos/go-systemd/v22 v22.3.2/go.mod h1:Y58oyj3AT4RCenI/lSvhwexgC+NSVTIJ3seZv2GcEnc= -github.com/coreos/pkg v0.0.0-20180928190104-399ea9e2e55f/go.mod h1:E3G3o1h8I7cfcXa63jLwjI0eiQQMgzzUDFVpN/nH/eA= github.com/cpuguy83/go-md2man/v2 v2.0.0-20190314233015-f79a8a8ca69d/go.mod h1:maD7wRr/U5Z6m/iR4s+kqSMx2CaBsrgA7czyZG/E6dU= github.com/cpuguy83/go-md2man/v2 v2.0.0 h1:EoUDS0afbrsXAZ9YQ9jdu/mZ2sXgT1/2yyNng4PGlyM= github.com/cpuguy83/go-md2man/v2 v2.0.0/go.mod h1:maD7wRr/U5Z6m/iR4s+kqSMx2CaBsrgA7czyZG/E6dU= @@ -68,13 +93,12 @@ github.com/creack/pty v1.1.11/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= -github.com/dgrijalva/jwt-go v3.2.0+incompatible/go.mod h1:E3ru+11k8xSBh+hMPgOLZmtrrCbhqsmaPHjLKYnJCaQ= -github.com/dgryski/go-sip13 v0.0.0-20181026042036-e10d5fee7954/go.mod h1:vAd38F8PWV+bWy6jNmig1y/TA+kYO4g3RSRF0IAv0no= github.com/dustin/go-humanize v1.0.0 h1:VSnTsYCnlFHaM2/igO1h6X3HA71jcobQuxemgkq4zYo= github.com/dustin/go-humanize v1.0.0/go.mod h1:HtrtbFcZ19U5GC7JDqmcUSB87Iq5E25KnS6fMYU6eOk= 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.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.20210217033140-668b12f5399d/go.mod h1:cXg6YxExXjJnVBQHBLXeUAgxn2UodCpnH306RInaBQk= github.com/envoyproxy/go-control-plane v0.9.9-0.20210512163311-63b5d3c536b0/go.mod h1:hliV/p42l8fGbc6Y9bQ70uLwIvmJyVE5k4iMKlh8wCQ= @@ -82,11 +106,13 @@ github.com/envoyproxy/go-control-plane v0.9.10-0.20210907150352-cf90f659a021/go. github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c= github.com/fatih/color v1.7.0 h1:DkWD4oS2D8LGGgTQ6IvwJJXSL5Vp2ffcQg58nFV38Ys= github.com/fatih/color v1.7.0/go.mod h1:Zm6kSWBoL9eyXnKyktHP6abPY2pDugNf5KwzbycvMj4= -github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo= +github.com/fsnotify/fsnotify v1.4.9/go.mod h1:znqG4EE+3YCdAaPaxE2ZRY/06pZUdp0tY4IgpuI1SZQ= github.com/getsentry/raven-go v0.2.0 h1:no+xWJRb5ZI7eE8TWgIq1jLulQiIoLG0IfYxv5JYMGs= github.com/getsentry/raven-go v0.2.0/go.mod h1:KungGk8q33+aIAZUIVWZDr2OfAEBsO49PX4NzFV5kcQ= github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04= github.com/go-gl/glfw v0.0.0-20190409004039-e6da0acd62b1/go.mod h1:vR7hzQXu2zJy9AVAgeJqvqgH9Q5CA+iKCZ2gyEVpxRU= +github.com/go-gl/glfw/v3.3/glfw v0.0.0-20191125211704-12ad95a8df72/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8= +github.com/go-gl/glfw/v3.3/glfw v0.0.0-20200222043503-6f7a984d4dc4/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8= github.com/go-kit/kit v0.8.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as= github.com/go-kit/kit v0.9.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as= github.com/go-kit/log v0.1.0/go.mod h1:zbhenjAZHb184qTLMA9ZjW7ThYL0H2mk7Q6pNt4vbaY= @@ -96,22 +122,30 @@ github.com/go-logfmt/logfmt v0.5.0/go.mod h1:wCYkCAKZfumFQihp8CzCvQ3paCTfi41vtzG github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY= 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.2.1/go.mod h1:hp+jE20tsWTFYpLwKvXlhS1hjn+gTNwPg2I6zVXpSg4= github.com/gogo/protobuf v1.3.1/go.mod h1:SlYgWuQ5SjCEi6WLHjHCa1yvBfUnHcTbrrZtXPKa29o= github.com/gogo/protobuf v1.3.2 h1:Ov1cvc58UF3b5XjBnZv7+opcTcQFZebYjWzi34vdm4Q= github.com/gogo/protobuf v1.3.2/go.mod h1:P1XiOD3dCwIKUDQYPy72D8LYyHL2YPYrpS2s69NZV8Q= github.com/golang-jwt/jwt v3.2.2+incompatible h1:IfV12K8xAKAnZqdXVzCZ+TOjboZ2keLg81eXfW3O+oY= github.com/golang-jwt/jwt v3.2.2+incompatible/go.mod h1:8pz2t5EyA70fFQQSrl6XZXzqecmYZeUEB8OUGHkxJ+I= github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q= -github.com/golang/groupcache v0.0.0-20190129154638-5b532d6fd5ef/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= +github.com/golang/groupcache v0.0.0-20190702054246-869f871628b6/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= +github.com/golang/groupcache v0.0.0-20191227052852-215e87163ea7/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= +github.com/golang/groupcache v0.0.0-20200121045136-8c9f03a8e57e/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= github.com/golang/mock v1.1.1/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A= github.com/golang/mock v1.2.0/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A= github.com/golang/mock v1.3.1/go.mod h1:sBzyDLLjw3U8JLTeZvSv8jJB+tU5PVekmnlKIyFUx0Y= +github.com/golang/mock v1.4.0/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.4/go.mod h1:l3mdAwkq5BuhzHwde/uurv3sEJeZMXNpwsxVWU71h+4= +github.com/golang/mock v1.5.0/go.mod h1:CWnOUgYIOo4TcNZ0wHX3YZCqsaM1I1Jvs6v3mP3KVu8= github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= github.com/golang/protobuf v1.3.1/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= github.com/golang/protobuf v1.3.2/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= github.com/golang/protobuf v1.3.3/go.mod h1:vzj43D7+SQXF/4pzW/hwtAqwc6iTitCiVSaWz5lYuqw= +github.com/golang/protobuf v1.3.4/go.mod h1:vzj43D7+SQXF/4pzW/hwtAqwc6iTitCiVSaWz5lYuqw= +github.com/golang/protobuf v1.3.5/go.mod h1:6O5/vntMXwX2lRkT1hjjk0nAC1IDOTvTlVgjlRvqsdk= github.com/golang/protobuf v1.4.0-rc.1/go.mod h1:ceaxUfeHdC40wWswd/P6IGgMaK3YpKi5j83Wpe3EHw8= github.com/golang/protobuf v1.4.0-rc.1.0.20200221234624-67d41d38c208/go.mod h1:xKAWHe0F5eneWXFV3EuXVDTCmh+JuBKY0li0aMyXATA= github.com/golang/protobuf v1.4.0-rc.2/go.mod h1:LlEzMj4AhA7rCAGe4KMBDvJI+AwstrUpVNzEA03Pprs= @@ -121,6 +155,7 @@ 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.3/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI= 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/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY= github.com/google/btree v0.0.0-20180813153112-4030bb1f1f0c/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ= @@ -131,26 +166,39 @@ github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5a github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= +github.com/google/go-cmp v0.4.1/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.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.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.6 h1:BKbKCqvP6I+rmFHt06ZmyQtvB8xAkWdhFyr0ZUNZcxQ= github.com/google/go-cmp v0.5.6/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= 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.1.0/go.mod h1:y5Zk1BBys9G+gd6Jrk0W3cC1+ELVxBWuIGO+w/tUAp0= 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-20191218002539-d4f498aebedc/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= +github.com/google/pprof v0.0.0-20200212024743-f11f1df84d12/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-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/renameio v0.1.0/go.mod h1:KWCgfxg9yswjAJkECMjeO8J8rahYeXnNhOm40UhjYkI= github.com/google/uuid v1.1.2/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= 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/gopherjs/gopherjs v0.0.0-20181017120253-0766667cb4d1/go.mod h1:wJfORRmW1u3UXTncJ5qlYoELFm8eSnnEO6hX4iZ3EWY= github.com/gorilla/websocket v1.4.2/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE= -github.com/grpc-ecosystem/go-grpc-middleware v1.0.0/go.mod h1:FiyG127CGDf3tlThmgyCl78X/SZQqEOJBCDaAfeWzPs= github.com/grpc-ecosystem/go-grpc-middleware v1.3.0/go.mod h1:z0ButlSOZa5vEBq9m2m2hlwIgKw+rp3sdCBRoJY+30Y= github.com/grpc-ecosystem/go-grpc-prometheus v1.2.0 h1:Ovs26xHkKqVztRpIrF/92BcuyuQ/YW4NSIpoGtfXNho= github.com/grpc-ecosystem/go-grpc-prometheus v1.2.0/go.mod h1:8NvIoxWQoOIhqOTXgfV/d3M/q6VIi02HzZEHgUlZvzk= -github.com/grpc-ecosystem/grpc-gateway v1.9.0/go.mod h1:vNeuVxBJEsws4ogUvrchl83t/GYV9WGTSLVdBhOQFDY= github.com/grpc-ecosystem/grpc-gateway v1.16.0/go.mod h1:BDjrQk3hbvj6Nolgz8mAMFbcEtjT1g+wF4CSlocrBnw= github.com/hashicorp/consul/api v1.1.0/go.mod h1:VmuI/Lkw1nC05EYQWNKwWGbkg+FbDBtguAZLlVdkD9Q= github.com/hashicorp/consul/sdk v0.1.1/go.mod h1:VKf9jXwCTEY1QZP2MOLRhb5i/I/ssyNV1vwHyQBF0x8= @@ -172,9 +220,10 @@ github.com/hashicorp/logutils v1.0.0/go.mod h1:QIAnNjmIWmVIIkWDTG1z5v++HQmx9WQRO github.com/hashicorp/mdns v1.0.0/go.mod h1:tL+uN++7HEJ6SQLQ2/p+z2pH24WQKWjBPkE0mNTz8vQ= github.com/hashicorp/memberlist v0.1.3/go.mod h1:ajVTdAv/9Im8oMAAj5G31PhhMCZJV2pPBoIllUwCN7I= github.com/hashicorp/serf v0.8.2/go.mod h1:6hOLApaqBFA1NXqRQAsxw9QxuDEvNxSQRwA/JwenrHc= +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/inconshreveable/mousetrap v1.0.0 h1:Z8tu5sraLXCXIcARxBp/8cbvlwVa7Z1NHg9XEKhtSvM= github.com/inconshreveable/mousetrap v1.0.0/go.mod h1:PxqpIevigyE2G7u3NXJIT2ANytuPF1OarO4DADm73n8= -github.com/jonboulle/clockwork v0.1.0/go.mod h1:Ii8DK3G1RaLaWxj9trq07+26W01tbo22gdxWY5EU2bo= github.com/jonboulle/clockwork v0.2.2 h1:UOGuzwb1PwsrDAObMuhUnj0p5ULPj8V/xJ7Kx9qUBdQ= github.com/jonboulle/clockwork v0.2.2/go.mod h1:Pkfl5aHPm1nk2H9h0bjmnJD/BcgbGXUBGnn1kMkgxc8= github.com/jpillora/backoff v1.0.0/go.mod h1:J/6gKK9jxlEcS3zixgDgUAsiuZ7yrSoa/FX5e0EB2j4= @@ -182,21 +231,22 @@ github.com/json-iterator/go v1.1.6/go.mod h1:+SdeFBvtyEkXs7REEP0seUULqWtbJapLOCV github.com/json-iterator/go v1.1.10/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4= github.com/json-iterator/go v1.1.11/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4= github.com/jstemmer/go-junit-report v0.0.0-20190106144839-af01ea7f8024/go.mod h1:6v2b51hI/fHJwM22ozAgKL4VKDeJcHhJFhtBdhmNjmU= +github.com/jstemmer/go-junit-report v0.9.1/go.mod h1:Brl9GWCQeLvo8nXZwPNNblvFj/XSXhF0NWZEnDohbsk= github.com/jtolds/gls v4.20.0+incompatible/go.mod h1:QJZ7F/aHp+rZTRtaJ1ow/lLfFfVYBRgL+9YlvaHOwJU= github.com/julienschmidt/httprouter v1.2.0/go.mod h1:SYymIcj16QtmaHHD7aYtjjsJG7VTCxuUUipMqKk8s4w= github.com/julienschmidt/httprouter v1.3.0/go.mod h1:JR6WtHb+2LUe8TCKY3cZOxFyyO8IZAc4RVcycCCAKdM= -github.com/kisielk/errcheck v1.1.0/go.mod h1:EZBBE59ingxPouuu3KfxchcWSUPOHkagtvWXihfKN4Q= github.com/kisielk/errcheck v1.2.0/go.mod h1:/BMXB+zMLi60iA8Vv6Ksmxu/1UDYcXs4uQLJ+jE2L00= github.com/kisielk/errcheck v1.5.0/go.mod h1:pFxgyoBC7bSaBwPgfKdkLd5X25qrDl4LWUI2bnpBCr8= github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck= github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= github.com/konsorten/go-windows-terminal-sequences v1.0.3/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= +github.com/kr/fs v0.1.0/go.mod h1:FFnZGqtBN9Gxj7eW1uZ42v5BccTP0vu6NEaFoC2HwRg= github.com/kr/logfmt v0.0.0-20140226030751-b84e30acd515/go.mod h1:+0opPa2QZZtGFBFZlji/RkVcI2GknAs/DXo4wKdlNEc= github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo= github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE= -github.com/magiconair/properties v1.8.1/go.mod h1:PppfXfuXeibc/6YijjN8zIbojt8czPbwD3XqdrwzmxQ= +github.com/magiconair/properties v1.8.5/go.mod h1:y3VJvCyxH9uVvJTWEGAELF3aiYNyPKd5NZ3oSwXrF60= github.com/mattn/go-colorable v0.0.9 h1:UVL0vNpWh04HeJXV0KLcaT7r06gOH2l4OW6ddYRUIY4= github.com/mattn/go-colorable v0.0.9/go.mod h1:9vuHe8Xs5qXnSaW/c/ABM9alt+Vo+STaOChaDxuIBZU= github.com/mattn/go-isatty v0.0.3 h1:ns/ykhmWi7G9O+8a448SecJU3nSMBXJfqQkl0upE1jI= @@ -208,33 +258,32 @@ github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5 github.com/miekg/dns v1.0.14/go.mod h1:W1PPwlIAgtquWBMBEV9nkV9Cazfe8ScdGz/Lj7v3Nrg= github.com/mitchellh/cli v1.0.0/go.mod h1:hNIlj7HEI86fIcpObd7a0FcrxTWetlwJDGcceTlRvqc= github.com/mitchellh/go-homedir v1.0.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0= -github.com/mitchellh/go-homedir v1.1.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0= github.com/mitchellh/go-testing-interface v1.0.0/go.mod h1:kRemZodwjscx+RGhAo8eIhFbs2+BFgRtFPeD/KE+zxI= github.com/mitchellh/gox v0.4.0/go.mod h1:Sd9lOJ0+aimLBi73mGofS1ycjY8lL3uZM3JPS42BGNg= github.com/mitchellh/iochan v1.0.0/go.mod h1:JwYml1nuB7xOzsp52dPpHFffvOCDupsG0QubkSMEySY= github.com/mitchellh/mapstructure v0.0.0-20160808181253-ca63d7c062ee/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y= github.com/mitchellh/mapstructure v1.1.2/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y= +github.com/mitchellh/mapstructure v1.4.1/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo= github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= github.com/modern-go/reflect2 v0.0.0-20180701023420-4b7aa43c6742/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0= github.com/modern-go/reflect2 v1.0.1/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0= github.com/mwitkow/go-conntrack v0.0.0-20161129095857-cc309e4a2223/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U= github.com/mwitkow/go-conntrack v0.0.0-20190716064945-2f068394615f/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U= -github.com/oklog/ulid v1.3.1/go.mod h1:CirwcVhetQ6Lv90oh/F+FBtV6XMibvdAFo93nm5qn4U= github.com/olekukonko/tablewriter v0.0.5 h1:P2Ga83D34wi1o9J6Wh1mRuqd4mF/x/lgBS7N7AbDhec= github.com/olekukonko/tablewriter v0.0.5/go.mod h1:hPp6KlRPjbx+hW8ykQs1w3UBbZlj6HuIJcUGPhkA7kY= github.com/opentracing/opentracing-go v1.1.0/go.mod h1:UkNAQd3GIcIGf0SeVgPpRdFStlNbqXla1AfSYxPUl2o= github.com/pascaldekloe/goe v0.0.0-20180627143212-57f6aae5913c/go.mod h1:lzWF7FIEvWOWxwDKqyGYQf6ZUaNfKdP144TG7ZOy1lc= -github.com/pelletier/go-toml v1.2.0/go.mod h1:5z9KED0ma1S8pY6P1sdut58dfprrGBbd/94hg7ilaic= +github.com/pelletier/go-toml v1.9.3/go.mod h1:u1nR/EPcESfeI/szUZKdtJ0xRNbUoANCkoOuaOx1Y+c= github.com/pkg/errors v0.8.0/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4= github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= +github.com/pkg/sftp v1.10.1/go.mod h1:lYOWFsE0bwd1+KfKJaKeuokY15vzFx25BLbzYYoAxZI= github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= github.com/posener/complete v1.1.1/go.mod h1:em0nMJCgc9GFtwrmVmEMR/ZL6WyhyjMBndrE9hABlRI= github.com/prometheus/client_golang v0.9.1/go.mod h1:7SWBe2y4D6OKWSNQJUaRYU/AaXPKyh/dDVn+NZz0KFw= -github.com/prometheus/client_golang v0.9.3/go.mod h1:/TN21ttK/J9q6uSwhBd54HahCDft0ttaMvbicHlPoso= github.com/prometheus/client_golang v1.0.0/go.mod h1:db9x61etRT2tGnBNRi70OPL5FsnadC4Ky3P0J6CfImo= github.com/prometheus/client_golang v1.7.1/go.mod h1:PY5Wy2awLA44sXw4AOSfFBetzPP4j5+D6mVACh+pe2M= github.com/prometheus/client_golang v1.11.0 h1:HNkLOAEQMIDv/K+04rukrLx6ch7msSRwf3/SASFAGtQ= @@ -244,20 +293,15 @@ github.com/prometheus/client_model v0.0.0-20190129233127-fd36f4220a90/go.mod h1: github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= github.com/prometheus/client_model v0.2.0 h1:uq5h0d+GuxiXLJLNABMgp2qUWDPiLvgCzz2dUR+/W/M= github.com/prometheus/client_model v0.2.0/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= -github.com/prometheus/common v0.0.0-20181113130724-41aa239b4cce/go.mod h1:daVV7qP5qjZbuso7PdcryaAu0sAZbrN9i7WWcTMWvro= -github.com/prometheus/common v0.4.0/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y86RQel1bk4= github.com/prometheus/common v0.4.1/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y86RQel1bk4= github.com/prometheus/common v0.10.0/go.mod h1:Tlit/dnDKsSWFlCLTWaA1cyBgKHSMdTB80sz/V91rCo= github.com/prometheus/common v0.26.0 h1:iMAkS2TDoNWnKM+Kopnx/8tnEStIfpYA0ur0xQzzhMQ= github.com/prometheus/common v0.26.0/go.mod h1:M7rCNAaPfAosfx8veZJCuw84e35h3Cfd9VFqTh1DIvc= github.com/prometheus/procfs v0.0.0-20181005140218-185b4288413d/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk= -github.com/prometheus/procfs v0.0.0-20190507164030-5867b95ac084/go.mod h1:TjEm7ze935MbeOT/UhFTIMYKhuLP4wbCsTZCD3I8kEA= github.com/prometheus/procfs v0.0.2/go.mod h1:TjEm7ze935MbeOT/UhFTIMYKhuLP4wbCsTZCD3I8kEA= github.com/prometheus/procfs v0.1.3/go.mod h1:lV6e/gmhEcM9IjHGsFOCxxuZ+z1YqCvr4OA4YeYWdaU= github.com/prometheus/procfs v0.6.0 h1:mxy4L2jP6qMonqmq+aTtOx1ifVWUgG/TAmntgbh3xv4= github.com/prometheus/procfs v0.6.0/go.mod h1:cz+aTbrPOrUb4q7XlbU9ygM+/jj0fzG6c1xBZuNvfVA= -github.com/prometheus/tsdb v0.7.1/go.mod h1:qhTCs0VvXwvX/y3TZrWD7rabWM+ijKTux40TwIPHuXU= -github.com/rogpeppe/fastuuid v0.0.0-20150106093220-6724a57986af/go.mod h1:XWv6SoW27p1b0cqNHllgS5HIMJraePCO15w5zCzIWYg= github.com/rogpeppe/fastuuid v1.2.0/go.mod h1:jVj6XXZzXRy/MSR5jhDC/2q6DgLz+nrA6LYCDYWNEvQ= github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4= github.com/russross/blackfriday/v2 v2.0.1 h1:lPqVAte+HuHNfhJ/0LC98ESWRz8afy9tM/0RK8m9o+Q= @@ -272,40 +316,44 @@ github.com/sirupsen/logrus v1.6.0/go.mod h1:7uNnSEd1DgxDLC74fIahvMZmmYsHGZGEOFrf github.com/sirupsen/logrus v1.8.1/go.mod h1:yWOB1SBYBC5VeMP7gHvWumXLIWorT60ONWic61uBYv0= github.com/smartystreets/assertions v0.0.0-20180927180507-b2de0cb4f26d/go.mod h1:OnSkiWE9lh6wB0YB77sQom3nweQdgAjqCqsofrRNTgc= github.com/smartystreets/goconvey v1.6.4/go.mod h1:syvi0/a8iFYH4r/RixwvyeAJjdLS9QV7WQ/tjFTllLA= -github.com/soheilhy/cmux v0.1.4/go.mod h1:IM3LyeVVIOuxMH7sFAkER9+bJ4dT7Ms6E4xg4kGIyLM= github.com/soheilhy/cmux v0.1.5/go.mod h1:T7TcVDs9LWfQgPlPsdngu6I6QIoyIFZDDC6sNE1GqG0= github.com/spaolacci/murmur3 v0.0.0-20180118202830-f09979ecbc72/go.mod h1:JwIasOWyU6f++ZhiEuf87xNszmSA2myDM2Kzu9HwQUA= -github.com/spf13/afero v1.1.2/go.mod h1:j4pytiNVoe2o6bmDsKpLACNPDBIoEAkihy7loJ1B0CQ= -github.com/spf13/cast v1.3.0/go.mod h1:Qx5cxh0v+4UWYiBimWS+eyWzqEqokIECu5etghLkUJE= -github.com/spf13/cobra v1.1.3 h1:xghbfqPkxzxP3C/f3n5DdpAbdKLj4ZE4BWQI362l53M= -github.com/spf13/cobra v1.1.3/go.mod h1:pGADOWyqRD/YMrPZigI/zbliZ2wVD/23d+is3pSWzOo= -github.com/spf13/jwalterweatherman v1.0.0/go.mod h1:cQK4TGJAtQXfYWX+Ddv3mKDzgVb68N+wFjFa4jdeBTo= -github.com/spf13/pflag v1.0.3/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4= +github.com/spf13/afero v1.6.0/go.mod h1:Ai8FlHk4v/PARR026UzYexafAt9roJ7LcLMAmO6Z93I= +github.com/spf13/cast v1.3.1/go.mod h1:Qx5cxh0v+4UWYiBimWS+eyWzqEqokIECu5etghLkUJE= +github.com/spf13/cobra v1.2.1 h1:+KmjbUw1hriSNMF55oPrkZcb27aECyrj8V2ytv7kWDw= +github.com/spf13/cobra v1.2.1/go.mod h1:ExllRjgxM/piMAM+3tAZvg8fsklGAf3tPfi+i8t68Nk= +github.com/spf13/jwalterweatherman v1.1.0/go.mod h1:aNWZUN0dPAAO/Ljvb5BEdw96iTZ0EXowPYD95IqWIGo= github.com/spf13/pflag v1.0.5 h1:iy+VFUOCP1a+8yFto/drg2CJ5u0yRoB7fZw3DKv/JXA= github.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg= -github.com/spf13/viper v1.7.0/go.mod h1:8WkrPz2fc9jxqZNCJI/76HCieCp4Q8HaLFoCha5qpdg= +github.com/spf13/viper v1.8.1/go.mod h1:o0Pch8wJ9BVSWGQMbra6iw0oQ5oktSIBaujf1rJH9Ns= github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= 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.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA= +github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/stretchr/testify v1.7.0 h1:nwc3DEeHmmLAfoZucVR881uASk0Mfjw8xYJ99tb5CcY= github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/subosito/gotenv v1.2.0/go.mod h1:N0PQaV/YGNqwC0u51sEeR/aUtSLEXKX9iv69rRypqCw= -github.com/tmc/grpc-websocket-proxy v0.0.0-20190109142713-0ad062ec5ee5/go.mod h1:ncp9v5uamzpCO7NfCPTXjqaC+bZgJeR0sMTm6dMHP7U= github.com/tmc/grpc-websocket-proxy v0.0.0-20201229170055-e5319fda7802/go.mod h1:ncp9v5uamzpCO7NfCPTXjqaC+bZgJeR0sMTm6dMHP7U= github.com/urfave/cli v1.22.4 h1:u7tSpNPPswAFymm8IehJhy4uJMlUuU/GmqSkvJ1InXA= github.com/urfave/cli v1.22.4/go.mod h1:Gos4lmkARVdJ6EkW0WaNv/tZAAMe9V7XWyB60NtXRu0= github.com/xiang90/probing v0.0.0-20190116061207-43a291ad63a2 h1:eY9dn8+vbi4tKz5Qo6v2eYzo7kUS51QINcR5jNpbZS8= github.com/xiang90/probing v0.0.0-20190116061207-43a291ad63a2/go.mod h1:UETIi67q53MR2AWcXfiuqkDkRtnGDLqkBTpCHuJHxtU= +github.com/yuin/goldmark v1.1.25/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= +github.com/yuin/goldmark v1.1.32/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= -go.etcd.io/bbolt v1.3.2/go.mod h1:IbVyRI1SCnLcuJnV2u8VeU0CEYM7e686BmAb1XKL+uU= go.etcd.io/bbolt v1.3.6 h1:/ecaJf0sk1l4l6V4awd65v2C3ILy7MSj+s/x1ADCIMU= go.etcd.io/bbolt v1.3.6/go.mod h1:qXsaaIqmgQH0T+OPdb99Bf+PKfBBQVAdyD6TY9G8XM4= 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.2/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.5/go.mod h1:5pWMHQbX5EPX2/62yrJeAkowc+lfs/XD7Uxpq3pI6kk= +go.opencensus.io v0.23.0/go.mod h1:XItmlyltB5F7CS4xOC1DcqMoFqwtC6OG2xF7mCv7P7E= go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.26.1 h1:puWrOArBwWlr5dq6vyZ6fKykHyS8JgMIVhTBA8XsGuU= go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.26.1/go.mod h1:4wsfAAW5N9wUHM0QTmZS8z7fvYZ1rv3m+sVeSpf8NhU= go.opentelemetry.io/otel v1.1.0/go.mod h1:7cww0OW51jQ8IaZChIEdqLwgh+44+7uiTdWsAL0wQpA= @@ -336,6 +384,7 @@ golang.org/x/crypto v0.0.0-20181029021203-45a5f77698d3/go.mod h1:6SG95UA2DQfeDnf golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= golang.org/x/crypto v0.0.0-20190510104115-cbcb75029529/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20190605123033-f99c8df09eb5/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= +golang.org/x/crypto v0.0.0-20190820162420-60c769a6c586/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= golang.org/x/crypto v0.0.0-20210513164829-c07d793c2f9a h1:kr2P4QFmQr29mSLA43kwrOcgcReGTfbE9N577tCTuBc= @@ -345,6 +394,11 @@ golang.org/x/exp v0.0.0-20190306152737-a1d7652674e8/go.mod h1:CJ0aWSM057203Lf6IL golang.org/x/exp v0.0.0-20190510132918-efd6b22b2522/go.mod h1:ZjyILWgesfNpC6sMxTJOJm9Kp84zZh5NQWvqDGG3Qr8= golang.org/x/exp v0.0.0-20190829153037-c13cbed26979/go.mod h1:86+5VVa7VpoJ4kLfm080zCjGlMRFzhUhsZKEZO7MGek= golang.org/x/exp v0.0.0-20191030013958-a1ab85dbe136/go.mod h1:JXzH8nQsPlswgeRAPE3MuO9GYsAcnJvJ4vnMwN/5qkY= +golang.org/x/exp v0.0.0-20191129062945-2f5052295587/go.mod h1:2RIsYlXP63K8oxa1u096TMicItID8zy7Y6sNkU49FU4= +golang.org/x/exp v0.0.0-20191227195350-da58074b4299/go.mod h1:2RIsYlXP63K8oxa1u096TMicItID8zy7Y6sNkU49FU4= +golang.org/x/exp v0.0.0-20200119233911-0405dc783f0a/go.mod h1:2RIsYlXP63K8oxa1u096TMicItID8zy7Y6sNkU49FU4= +golang.org/x/exp v0.0.0-20200207192155-f17229e696bd/go.mod h1:J/WKrq2StrnmMY6+EHIKF9dgMWnmCNThgcyBT1FY9mM= +golang.org/x/exp v0.0.0-20200224162631-6cc2880d07d6/go.mod h1:3jZMyOhIsHpP37uCMkUooju7aAi5cS1Q23tOzKc+0MU= golang.org/x/image v0.0.0-20190227222117-0694c2d4d067/go.mod h1:kZ7UVZpmo3dzQBMxlp+ypCbDeSB+sBbTgSJuh5dn5js= golang.org/x/image v0.0.0-20190802002840-cff245a6509b/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0= golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE= @@ -354,18 +408,25 @@ golang.org/x/lint v0.0.0-20190313153728-d0100b6bd8b3/go.mod h1:6SW0HCj/g11FgYtHl golang.org/x/lint v0.0.0-20190409202823-959b441ac422/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= golang.org/x/lint v0.0.0-20190909230951-414d861bb4ac/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= golang.org/x/lint v0.0.0-20190930215403-16217165b5de/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= +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-20200302205851-738671d3881b/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY= +golang.org/x/lint v0.0.0-20201208152925-83fdc39ff7b5/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-20190719004257-d2bd2a29d028/go.mod h1:E/iHnbuqvinMTCcRqshq8CkpyQDoeVncDDYHnLhea+o= golang.org/x/mod v0.0.0-20190513183733-4bf6d317e70e/go.mod h1:mXi4GBBbnImb6dmsKGUJ2LatrhH/nqhxcFungHvyanc= golang.org/x/mod v0.1.0/go.mod h1:0QHyrYULN0/3qlju5TqG8bIK38QM8yzMo5ekMj3DlcY= +golang.org/x/mod v0.1.1-0.20191105210325-c90efee705ee/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.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/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-20181023162649-9b4f9f5ad519/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20181114220301-adae6a3d119a/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20181201002055-351d144fa1fc/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= -golang.org/x/net v0.0.0-20181220203305-927f97764cc3/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20190108225652-1e06a53dbb7e/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20190213061140-3a22650c66bd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= @@ -375,33 +436,61 @@ golang.org/x/net v0.0.0-20190503192946-f4e77d36d62c/go.mod h1:t9HGtf8HONx5eT2rtn golang.org/x/net v0.0.0-20190603091049-60506f45cf65/go.mod h1:HSz+uSET+XFnRR8LxR5pz3Of3rY3CfYBVs4xY44aLks= golang.org/x/net v0.0.0-20190613194153-d28f0bde5980/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20190628185345-da137c7871d7/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20190724013045-ca1201d0de80/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20191209160850-c0dbc17a3553/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20200114155413-6afb5195e5aa/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20200202094626-16171245cfb2/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20200222125558-5a598a2470a0/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20200226121028-0de0cce0169b/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20200301022130-244492dfa37a/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20200324143707-d3edc9973b7e/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= +golang.org/x/net v0.0.0-20200501053045-e0ff5e5a1de5/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= +golang.org/x/net v0.0.0-20200506145744-7e3656a0809f/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= +golang.org/x/net v0.0.0-20200513185701-a91f0712d120/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= +golang.org/x/net v0.0.0-20200520182314-0ba52f642ac2/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= golang.org/x/net v0.0.0-20200625001655-4c5254603344/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-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-20201202161906-c7110b5ffcbb/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-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-20211123203042-d83791d6bcd9 h1:0qxwC5n+ttVOINCBeRHO0nq9X7uy8SDsPoi5OaCdIEI= golang.org/x/net v0.0.0-20211123203042-d83791d6bcd9/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= 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-20190604053449-0f29369cfe45/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= -golang.org/x/oauth2 v0.0.0-20200107190931-bf48bf16ab8d h1:TzXSXBo42m9gQenoE3b9BGiEpg5IG2JkU5FkPIawgtw= +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-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-20210402161424-2e8d93401602 h1:0Ja1LBD+yisY6RWM/BH7TJVXWsSjs2VwBSmvSX4HdBc= +golang.org/x/oauth2 v0.0.0-20210402161424-2e8d93401602/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= 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-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20190227155943-e225da77a7e6/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20200317015054-43a5402ce75a/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20200625203802-6e8e738ad208/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-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sys v0.0.0-20180823144017-11551d06cbcc/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20181026203630-95b1ffbd15a5/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= -golang.org/x/sys v0.0.0-20181107165924-66b7b1311ac8/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20181116152217-5ac8a444bdc5/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190312061237-fead79001313/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= @@ -411,16 +500,42 @@ golang.org/x/sys v0.0.0-20190502145724-3ef323f4f1fd/go.mod h1:h1NjWce9XRLGQEsW7w golang.org/x/sys v0.0.0-20190507160741-ecd444e8653b/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190606165138-5da285871e9c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190624142023-c5567b49c5d0/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190726091711-fc99dfbffb4e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20191001151750-bb3f8db39f24/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20191005200804-aed5e4c7ecf9/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20191026070338-33540a1f6037/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20191204072324-ce4227a45e2e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20191228213918-04cbcbbfeed8/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200106162015-b016eb3dc98e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200113162924-86b910548bc1/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200122134326-e047566fdf82/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200202164722-d101bd2416d5/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200212091648-12a6c2dcc1e4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200223170610-d5e6a3e2c0ae/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200302150141-5c8b2ff67527/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200331124033-c3d80250170d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200501052902-10377860bb8e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200511232937-7e40ca221e25/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200515095857-1151b9dac4a9/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200523222454-059865788121/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-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-20200923182605-d9f96fdee20d/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-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-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-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-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-20210423185535-09eb48e85fd7/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210510120138-977fb7262007/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= @@ -429,19 +544,21 @@ golang.org/x/sys v0.0.0-20210603125802-9665404d3644/go.mod h1:oPkhp1MJrh7nUepCBc golang.org/x/sys v0.0.0-20211123173158-ef496fb156ab h1:rfJ1bsoJQQIAoAxTxB7bme+vHrNkRw8CqfsYh9w54cw= golang.org/x/sys v0.0.0-20211123173158-ef496fb156ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= +golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.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.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.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/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-20191024005414-555d28b269f0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.0.0-20210220033141-f8bda1e9f3ba h1:O8mE0/t419eoIwhTFpKVkHiTs/Igowgfkj25AcZrtiE= golang.org/x/time v0.0.0-20210220033141-f8bda1e9f3ba/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= -golang.org/x/tools v0.0.0-20180221164845-07fd8470d635/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-20181030221726-6c7e314b6563/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20190114222345-bf090417da8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= @@ -460,9 +577,39 @@ golang.org/x/tools v0.0.0-20190816200558-6889da9d5479/go.mod h1:b+2E5dAYhXwXZwtn golang.org/x/tools v0.0.0-20190911174233-4f2ddba30aff/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.0.0-20191012152004-8de300cfc20a/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.0.0-20191112195655-aa38f8e97acc/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-20191113191852-77e3bb0ad9e7/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-20191115202509-3a792d9c32b2/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-20191125144606-a911d9008d1f/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-20191130070609-6e064ea0cf2d/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-20191216173652-a0e659d51361/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= +golang.org/x/tools v0.0.0-20191227053925-7b8e75db28f4/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= +golang.org/x/tools v0.0.0-20200117161641-43d50277825c/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= +golang.org/x/tools v0.0.0-20200122220014-bf1340f18c4a/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= +golang.org/x/tools v0.0.0-20200130002326-2f3ba24bd6e7/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= +golang.org/x/tools v0.0.0-20200204074204-1cc6d1ef6c74/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= +golang.org/x/tools v0.0.0-20200207183749-b753a1ba74fa/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= +golang.org/x/tools v0.0.0-20200212150539-ea181f53ac56/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= +golang.org/x/tools v0.0.0-20200224181240-023911ca70b2/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= +golang.org/x/tools v0.0.0-20200227222343-706bc42d1f0d/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= +golang.org/x/tools v0.0.0-20200304193943-95d2e580d8eb/go.mod h1:o4KQGtdN14AW+yjsvvwRTJJuXz8XRtIHtEnmAXLyFUw= +golang.org/x/tools v0.0.0-20200312045724-11d5b4c81c7d/go.mod h1:o4KQGtdN14AW+yjsvvwRTJJuXz8XRtIHtEnmAXLyFUw= +golang.org/x/tools v0.0.0-20200331025713-a30bf2db82d4/go.mod h1:Sl4aGygMT6LrqrWclx+PTx3U+LnKx/seiNR+3G19Ar8= +golang.org/x/tools v0.0.0-20200501065659-ab2804fb9c9d/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= +golang.org/x/tools v0.0.0-20200512131952-2bc93b1c0c88/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= +golang.org/x/tools v0.0.0-20200515010526-7d3b6ebf133d/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= +golang.org/x/tools v0.0.0-20200618134242-20370b0cb4b2/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= golang.org/x/tools v0.0.0-20200619180055-7c47624df98f/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= +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-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-20210105154028-b0ab187a4818/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/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-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= @@ -473,11 +620,31 @@ google.golang.org/api v0.7.0/go.mod h1:WtwebWUNSVBH/HAw79HIFXZNqEvBhG+Ra+ax0hx3E google.golang.org/api v0.8.0/go.mod h1:o4eAsZoiT+ibD93RtjEohWalFOjRDx6CVaqeizhEnKg= google.golang.org/api v0.9.0/go.mod h1:o4eAsZoiT+ibD93RtjEohWalFOjRDx6CVaqeizhEnKg= google.golang.org/api v0.13.0/go.mod h1:iLdEw5Ide6rF15KTC1Kkl0iskquN2gFfn9o9XIsbkAI= +google.golang.org/api v0.14.0/go.mod h1:iLdEw5Ide6rF15KTC1Kkl0iskquN2gFfn9o9XIsbkAI= +google.golang.org/api v0.15.0/go.mod h1:iLdEw5Ide6rF15KTC1Kkl0iskquN2gFfn9o9XIsbkAI= +google.golang.org/api v0.17.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE= +google.golang.org/api v0.18.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE= +google.golang.org/api v0.19.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE= +google.golang.org/api v0.20.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE= +google.golang.org/api v0.22.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE= +google.golang.org/api v0.24.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.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.44.0/go.mod h1:EBOGZqzyhtvMDoxwS97ctnh0zUmYY6CxqXsc1AvkYD8= 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.5.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= -google.golang.org/appengine v1.6.1 h1:QzqyMA1tlu6CgqCDUtU9V+ZKhLFT2dkJuANu5QaxI3I= google.golang.org/appengine v1.6.1/go.mod h1:i06prIuMbXzDqacNJfV5OdTW448YApPu5ww/cMBSeb0= +google.golang.org/appengine v1.6.5/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-20190307195333-5fe7a883aa19/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= google.golang.org/genproto v0.0.0-20190418145605-e7d98fc518a7/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= @@ -487,9 +654,38 @@ google.golang.org/genproto v0.0.0-20190801165951-fa694d86fc64/go.mod h1:DMBHOl98 google.golang.org/genproto v0.0.0-20190819201941-24fa4b261c55/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc= google.golang.org/genproto v0.0.0-20190911173649-1774047e7e51/go.mod h1:IbNlFCBrqXvoKpeg0TB2l7cyZUmoaFKYIwrEpbDKLA8= google.golang.org/genproto v0.0.0-20191108220845-16a3f7862a1a/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= +google.golang.org/genproto v0.0.0-20191115194625-c23dd37a84c9/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= +google.golang.org/genproto v0.0.0-20191216164720-4f79533eabd1/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= +google.golang.org/genproto v0.0.0-20191230161307-f3c370f40bfb/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= +google.golang.org/genproto v0.0.0-20200115191322-ca5a22157cba/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= +google.golang.org/genproto v0.0.0-20200122232147-0452cf42e150/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= +google.golang.org/genproto v0.0.0-20200204135345-fa8e72b47b90/go.mod h1:GmwEX6Z4W5gMy59cAlVYjN9JhxgbQH6Gn+gFDQe2lzA= +google.golang.org/genproto v0.0.0-20200212174721-66ed5ce911ce/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= +google.golang.org/genproto v0.0.0-20200224152610-e50cd9704f63/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= +google.golang.org/genproto v0.0.0-20200228133532-8c2c7df3a383/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= +google.golang.org/genproto v0.0.0-20200305110556-506484158171/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= +google.golang.org/genproto v0.0.0-20200312145019-da6875a35672/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= +google.golang.org/genproto v0.0.0-20200331122359-1ee6d9798940/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= google.golang.org/genproto v0.0.0-20200423170343-7949de9c1215/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= +google.golang.org/genproto v0.0.0-20200430143042-b979b6f78d84/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= +google.golang.org/genproto v0.0.0-20200511104702-f5ebc3bea380/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= google.golang.org/genproto v0.0.0-20200513103714-09dca8ec2884/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= +google.golang.org/genproto v0.0.0-20200515170657-fc4c6c6a6587/go.mod h1:YsZOwe1myG/8QRHRsmBRE1LrgQY60beZKjly0O1fX9U= google.golang.org/genproto v0.0.0-20200526211855-cb27e3aa2013/go.mod h1:NbSheEEYHJ7i3ixzK3sjbqSGDJWnxyFXZblF3eUsNvo= +google.golang.org/genproto v0.0.0-20200618031413-b414f8b61790/go.mod h1:jDfRM7FcilCzHH/e9qn6dsT145K34l5v+OpcnNgKAAA= +google.golang.org/genproto v0.0.0-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-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-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-20210402141018-6c239bbf2bb1/go.mod h1:9lPAdzaEmUacj36I+k7YKbEc5CXzPIeORRgDAUOu28A= google.golang.org/genproto v0.0.0-20211118181313-81c1377c94b1 h1:b9mVrqYfq3P4bCdaLg1qtBnPzUYgglsIdjZkL/fQVOE= google.golang.org/genproto v0.0.0-20211118181313-81c1377c94b1/go.mod h1:5CzLGKJ67TSI2B9POpiiyGha0AjJvZIUgRMt1dSmuhc= google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c= @@ -497,11 +693,22 @@ google.golang.org/grpc v1.20.1/go.mod h1:10oTOabMzJvdu6/UiuZezV6QK5dSlG84ov/aaiq google.golang.org/grpc v1.21.1/go.mod h1:oYelfM1adQP15Ek0mdvEgi9Df8B9CZIaU1084ijfRaM= google.golang.org/grpc v1.23.0/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg= google.golang.org/grpc v1.25.1/go.mod h1:c3i+UQWmh7LiEpx4sFZnkU36qjEYZ0imhYfXVyQciAY= +google.golang.org/grpc v1.26.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk= google.golang.org/grpc v1.27.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk= +google.golang.org/grpc v1.27.1/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk= +google.golang.org/grpc v1.28.0/go.mod h1:rpkK4SK4GF4Ach/+MFLZUBavHOvF2JJB5uozKKal+60= 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.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.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.1/go.mod h1:qjiiYl8FncCW8feJPdyg3v6XW24KsRHe+dy9BAGRRjU= 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.40.0/go.mod h1:ogyxbiOoUXAkP+4+xa6PZSE9DZgIHtSpzjDTB9KAK34= google.golang.org/grpc v1.41.0 h1:f+PlOh7QV4iIJkPrx5NQ7qaNGFQ3OTse67yaDHfju4E= google.golang.org/grpc v1.41.0/go.mod h1:U3l9uK9J0sini8mHphKoXyaqDA/8VyGnDee1zzIUK6k= @@ -513,6 +720,7 @@ google.golang.org/protobuf v1.21.0/go.mod h1:47Nbq4nVaFHyn7ilMalzfO3qCViNmqZ2kzi google.golang.org/protobuf v1.22.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= google.golang.org/protobuf v1.23.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= google.golang.org/protobuf v1.23.1-0.20200526195155-81db48ad09cc/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= +google.golang.org/protobuf v1.24.0/go.mod h1:r/3tXBNzIEhYS9I1OUVjXDlt8tc493IdKGjtUeSXeh4= google.golang.org/protobuf v1.25.0/go.mod h1:9JNX74DMeImyA3h4bdi1ymwjUzf21/xIlbajtzgsN7c= google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw= google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc= @@ -525,10 +733,8 @@ gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8 gopkg.in/cheggaaa/pb.v1 v1.0.28 h1:n1tBJnnK2r7g9OW2btFH91V92STTUevLXYFb8gy9EMk= gopkg.in/cheggaaa/pb.v1 v1.0.28/go.mod h1:V/YB90LKu/1FcN3WVnfiiE5oMCibMjukxqG/qStrOgw= gopkg.in/errgo.v2 v2.1.0/go.mod h1:hNsd1EY+bozCKY1Ytp96fpM3vjJbqLJn88ws8XvfDNI= -gopkg.in/ini.v1 v1.51.0/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k= +gopkg.in/ini.v1 v1.62.0/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k= gopkg.in/natefinch/lumberjack.v2 v2.0.0/go.mod h1:l0ndWWf7gzL7RNwBG7wST/UCcT4T24xpD6X8LsfU/+k= -gopkg.in/resty.v1 v1.12.0/go.mod h1:mDo4pnntr5jdWRML875a/NmxYqAlA73dVijT2AXvQQo= -gopkg.in/yaml.v2 v2.0.0-20170812160011-eb3733d160e7/go.mod h1:JAlM8MvJe8wmxCU4Bli9HhUf9+ttbYbLASfIpnQbh74= gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.2.3/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= @@ -546,7 +752,11 @@ honnef.co/go/tools v0.0.0-20190106161140-3f1c8253044a/go.mod h1:rf3lG4BRIbNafJWh honnef.co/go/tools v0.0.0-20190418001031-e561f6794a2a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= honnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= honnef.co/go/tools v0.0.1-2019.2.3/go.mod h1:a3bituU0lyd329TUQxRnasdCoJDkEUEAqEt0JzvZhAg= +honnef.co/go/tools v0.0.1-2020.1.3/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9vFzvIQ3k= +honnef.co/go/tools v0.0.1-2020.1.4/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9vFzvIQ3k= 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/sampler v1.3.0/go.mod h1:T1hPZKmBbMNahiBKFy5HrXp6adAjACjK9JXDnKaTXpA= sigs.k8s.io/json v0.0.0-20211020170558-c049b76a60c6 h1:fD1pz4yfdADVNfFmcP2aBEtudwUQ1AlLnRBALr33v3s= sigs.k8s.io/json v0.0.0-20211020170558-c049b76a60c6/go.mod h1:p4QtZmO4uMYipTQNzagwnNoseA6OxSUutVw05NhYDRs= sigs.k8s.io/yaml v1.2.0/go.mod h1:yfXDCHCao9+ENCvLSE62v9VSji2MKu5jeNfTrofGhJc= diff --git a/etcdutl/go.mod b/etcdutl/go.mod index 36acdf8ab910..99eba175e2f8 100644 --- a/etcdutl/go.mod +++ b/etcdutl/go.mod @@ -24,7 +24,7 @@ require ( github.com/coreos/go-semver v0.3.0 github.com/dustin/go-humanize v1.0.0 github.com/olekukonko/tablewriter v0.0.5 - github.com/spf13/cobra v1.1.3 + github.com/spf13/cobra v1.2.1 go.etcd.io/bbolt v1.3.6 go.etcd.io/etcd/api/v3 v3.5.0 go.etcd.io/etcd/client/pkg/v3 v3.5.0 diff --git a/etcdutl/go.sum b/etcdutl/go.sum index a602b0288081..9cf1020bec81 100644 --- a/etcdutl/go.sum +++ b/etcdutl/go.sum @@ -4,13 +4,39 @@ cloud.google.com/go v0.38.0/go.mod h1:990N+gfupTy94rShfmMCWGDn0LpTmnzTp2qbd1dvSR cloud.google.com/go v0.44.1/go.mod h1:iSa0KzasP4Uvy3f1mN/7PiObzGgflwredwwASm/v6AU= cloud.google.com/go v0.44.2/go.mod h1:60680Gw3Yr4ikxnPRS/oxxkBccT6SA1yMk63TGekxKY= cloud.google.com/go v0.45.1/go.mod h1:RpBamKRgapWJb87xiFSdk4g1CME7QZg3uwTez+TSTjc= -cloud.google.com/go v0.46.3 h1:AVXDdKsrtX33oR9fbCMu/+c1o8Ofjq6Ku/MInaLVg5Y= cloud.google.com/go v0.46.3/go.mod h1:a6bKKbmY7er1mI7TEI4lsAkts/mkhTSZK8w33B4RAg0= +cloud.google.com/go v0.50.0/go.mod h1:r9sluTvynVuxRIOHXQEHMFffphuXHOMZMycpNR5e6To= +cloud.google.com/go v0.52.0/go.mod h1:pXajvRH/6o3+F9jDHZWQ5PbGhn+o8w9qiu/CffaVdO4= +cloud.google.com/go v0.53.0/go.mod h1:fp/UouUEsRkN6ryDKNW/Upv/JBKnv6WDthjR6+vze6M= +cloud.google.com/go v0.54.0/go.mod h1:1rq2OEkV3YMf6n/9ZvGWI3GWw0VoqH/1x2nd8Is/bPc= +cloud.google.com/go v0.56.0/go.mod h1:jr7tqZxxKOVYizybht9+26Z/gUq7tiRzu+ACVAMbKVk= +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.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 h1:at8Tk2zUz63cLPR0JPWm5vp77pEZmzxEQBEfRKn1VV8= +cloud.google.com/go v0.81.0/go.mod h1:mk/AM35KwGk/Nm2YSeZbxXdrNK3KZOYHmLkOqC2V6E0= 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.4.0/go.mod h1:S8dzgnTigyfTmLBfrtrhyYhwRxG72rYxvftPBK2Dvzc= +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.8.0/go.mod h1:J5hqkt3O0uAFnINi6JXValWIb1v0goeZM77hZzJN/fQ= 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/firestore v1.1.0/go.mod h1:ulACoGHTpvq5r8rxGJ4ddJZBZqakUQqClKRT5SZwBmk= 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.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/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.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.10.0/go.mod h1:FLPqc6j+Ki4BU591ie1oL6qBQGu2Bl/tZ9ullr3+Kg0= dmitri.shuralyov.com/gpu/mtl v0.0.0-20190408044501-666a987793e9/go.mod h1:H6x//7gZCb22OMCxBHrMx7a5I7Hp++hsVxbQ4BYO7hU= github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= github.com/BurntSushi/xgb v0.0.0-20160522181843-27f122750802/go.mod h1:IVnqGOEym/WlBOVXweHU+Q+/VP0lqqI8lqeDx9IjBqo= @@ -29,7 +55,7 @@ github.com/beorn7/perks v1.0.0/go.mod h1:KWe93zE9D1o94FZ5RNwFwVgaQK1VOXiVxmqh+Ce github.com/beorn7/perks v1.0.1 h1:VlbKKnNfV8bJzeqoa4cOKqO6bYr3WgKZxO8Z16+hsOM= github.com/beorn7/perks v1.0.1/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6rlkpw= github.com/bgentry/speakeasy v0.1.0/go.mod h1:+zsyZBPWlz7T6j88CTgSN5bM796AkVf0kBD4zp0CCIs= -github.com/bketelsen/crypt v0.0.3-0.20200106085610-5cbc8cc4026c/go.mod h1:MKsuJmJgSg28kpZDP6UIiPt0e0Oz0kqKNGyRaWEPv84= +github.com/bketelsen/crypt v0.0.4/go.mod h1:aI6NrJ0pMGgvZKL1iVgXLnfIFJtfV+bKCoqOes/6LfM= github.com/cenkalti/backoff/v4 v4.1.1/go.mod h1:scbssz8iZGpm3xbr14ovlUdkxfGXNInqkPWOWmG2CLw= github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU= github.com/certifi/gocertifi v0.0.0-20191021191039-0944d244cd40/go.mod h1:sGbDF6GwGcLpkNXPUTkMRoywsNa/ol15pxFe6ERfguA= @@ -39,8 +65,12 @@ github.com/cespare/xxhash v1.1.0 h1:a6HrQnmkObjyL+Gs60czilIUGqrzKutQD6XZog3p+ko= github.com/cespare/xxhash v1.1.0/go.mod h1:XrSqR1VqqWfGrhpAt58auRo0WTKS1nRRg3ghfAqPWnc= github.com/cespare/xxhash/v2 v2.1.1 h1:6MnRN8NT7+YBpUIWxHtefFZOKTAPgGjpQSxqLNn0+qY= github.com/cespare/xxhash/v2 v2.1.1/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= +github.com/chzyer/logex v1.1.10/go.mod h1:+Ywpsq7O8HXn0nuIou7OrIPyXbp3wmkHB+jjWRnGsAI= +github.com/chzyer/readline v0.0.0-20180603132655-2972be24d48e/go.mod h1:nSuG5e5PlCu98SY8svDHJxuZscDgtXS6KTTbou5AhLI= +github.com/chzyer/test v0.0.0-20180213035817-a1ea475d72b1/go.mod h1:Q3SI9o4m/ZMnBNeIyt5eFwwo7qiLfzFZmjNmxjkiQlU= github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw= 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/xds/go v0.0.0-20210312221358-fbca930ec8ed/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs= github.com/cncf/xds/go v0.0.0-20210805033703-aa0b78936158/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs= @@ -50,39 +80,35 @@ github.com/cockroachdb/errors v1.2.4 h1:Lap807SXTH5tri2TivECb/4abUkMZC9zRoLarvcK github.com/cockroachdb/errors v1.2.4/go.mod h1:rQD95gz6FARkaKkQXUksEje/d9a6wBJoCr5oaCLELYA= github.com/cockroachdb/logtags v0.0.0-20190617123548-eb05cc24525f h1:o/kfcElHqOiXqcou5a3rIlMc7oJbMQkeLk0VQJ7zgqY= github.com/cockroachdb/logtags v0.0.0-20190617123548-eb05cc24525f/go.mod h1:i/u985jwjWRlyHXQbwatDASoW0RMlZ/3i9yJHE2xLkI= -github.com/coreos/bbolt v1.3.2/go.mod h1:iRUV2dpdMOn7Bo10OQBFzIJO9kkE559Wcmn+qkEiiKk= -github.com/coreos/etcd v3.3.13+incompatible/go.mod h1:uF7uidLiAD3TWHmW31ZFd/JWoc32PjwdhPthX9715RE= github.com/coreos/go-semver v0.3.0 h1:wkHLiw0WNATZnSG7epLsujiMCgPAc9xhjJ4tgnAxmfM= github.com/coreos/go-semver v0.3.0/go.mod h1:nnelYz7RCh+5ahJtPPxZlU+153eP4D4r3EedlOD2RNk= -github.com/coreos/go-systemd v0.0.0-20190321100706-95778dfbb74e h1:Wf6HqHfScWJN9/ZjdUKyjop4mf3Qdd+1TvvltAvM3m8= -github.com/coreos/go-systemd v0.0.0-20190321100706-95778dfbb74e/go.mod h1:F5haX7vjVVG0kc13fIWeqUViNPyEJxv/OmvnBo0Yme4= github.com/coreos/go-systemd/v22 v22.3.2 h1:D9/bQk5vlXQFZ6Kwuu6zaiXJ9oTPe68++AzAJc1DzSI= github.com/coreos/go-systemd/v22 v22.3.2/go.mod h1:Y58oyj3AT4RCenI/lSvhwexgC+NSVTIJ3seZv2GcEnc= -github.com/coreos/pkg v0.0.0-20180928190104-399ea9e2e55f/go.mod h1:E3G3o1h8I7cfcXa63jLwjI0eiQQMgzzUDFVpN/nH/eA= github.com/cpuguy83/go-md2man/v2 v2.0.0/go.mod h1:maD7wRr/U5Z6m/iR4s+kqSMx2CaBsrgA7czyZG/E6dU= github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E= github.com/creack/pty v1.1.11/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E= github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= -github.com/dgrijalva/jwt-go v3.2.0+incompatible/go.mod h1:E3ru+11k8xSBh+hMPgOLZmtrrCbhqsmaPHjLKYnJCaQ= -github.com/dgryski/go-sip13 v0.0.0-20181026042036-e10d5fee7954/go.mod h1:vAd38F8PWV+bWy6jNmig1y/TA+kYO4g3RSRF0IAv0no= github.com/dustin/go-humanize v1.0.0 h1:VSnTsYCnlFHaM2/igO1h6X3HA71jcobQuxemgkq4zYo= github.com/dustin/go-humanize v1.0.0/go.mod h1:HtrtbFcZ19U5GC7JDqmcUSB87Iq5E25KnS6fMYU6eOk= 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.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.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.10-0.20210907150352-cf90f659a021/go.mod h1:AFq3mo9L8Lqqiid3OhADV3RfLJnjiw63cSpi+fDTRC0= github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c= github.com/fatih/color v1.7.0/go.mod h1:Zm6kSWBoL9eyXnKyktHP6abPY2pDugNf5KwzbycvMj4= -github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo= +github.com/fsnotify/fsnotify v1.4.9/go.mod h1:znqG4EE+3YCdAaPaxE2ZRY/06pZUdp0tY4IgpuI1SZQ= github.com/getsentry/raven-go v0.2.0 h1:no+xWJRb5ZI7eE8TWgIq1jLulQiIoLG0IfYxv5JYMGs= github.com/getsentry/raven-go v0.2.0/go.mod h1:KungGk8q33+aIAZUIVWZDr2OfAEBsO49PX4NzFV5kcQ= github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04= github.com/go-gl/glfw v0.0.0-20190409004039-e6da0acd62b1/go.mod h1:vR7hzQXu2zJy9AVAgeJqvqgH9Q5CA+iKCZ2gyEVpxRU= +github.com/go-gl/glfw/v3.3/glfw v0.0.0-20191125211704-12ad95a8df72/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8= +github.com/go-gl/glfw/v3.3/glfw v0.0.0-20200222043503-6f7a984d4dc4/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8= github.com/go-kit/kit v0.8.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as= github.com/go-kit/kit v0.9.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as= github.com/go-kit/log v0.1.0/go.mod h1:zbhenjAZHb184qTLMA9ZjW7ThYL0H2mk7Q6pNt4vbaY= @@ -92,22 +118,30 @@ github.com/go-logfmt/logfmt v0.5.0/go.mod h1:wCYkCAKZfumFQihp8CzCvQ3paCTfi41vtzG github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY= 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.2.1/go.mod h1:hp+jE20tsWTFYpLwKvXlhS1hjn+gTNwPg2I6zVXpSg4= github.com/gogo/protobuf v1.3.1/go.mod h1:SlYgWuQ5SjCEi6WLHjHCa1yvBfUnHcTbrrZtXPKa29o= github.com/gogo/protobuf v1.3.2 h1:Ov1cvc58UF3b5XjBnZv7+opcTcQFZebYjWzi34vdm4Q= github.com/gogo/protobuf v1.3.2/go.mod h1:P1XiOD3dCwIKUDQYPy72D8LYyHL2YPYrpS2s69NZV8Q= github.com/golang-jwt/jwt v3.2.2+incompatible h1:IfV12K8xAKAnZqdXVzCZ+TOjboZ2keLg81eXfW3O+oY= github.com/golang-jwt/jwt v3.2.2+incompatible/go.mod h1:8pz2t5EyA70fFQQSrl6XZXzqecmYZeUEB8OUGHkxJ+I= github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q= -github.com/golang/groupcache v0.0.0-20190129154638-5b532d6fd5ef/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= +github.com/golang/groupcache v0.0.0-20190702054246-869f871628b6/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= +github.com/golang/groupcache v0.0.0-20191227052852-215e87163ea7/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= +github.com/golang/groupcache v0.0.0-20200121045136-8c9f03a8e57e/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= github.com/golang/mock v1.1.1/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A= github.com/golang/mock v1.2.0/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A= github.com/golang/mock v1.3.1/go.mod h1:sBzyDLLjw3U8JLTeZvSv8jJB+tU5PVekmnlKIyFUx0Y= +github.com/golang/mock v1.4.0/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.4/go.mod h1:l3mdAwkq5BuhzHwde/uurv3sEJeZMXNpwsxVWU71h+4= +github.com/golang/mock v1.5.0/go.mod h1:CWnOUgYIOo4TcNZ0wHX3YZCqsaM1I1Jvs6v3mP3KVu8= github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= github.com/golang/protobuf v1.3.1/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= github.com/golang/protobuf v1.3.2/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= github.com/golang/protobuf v1.3.3/go.mod h1:vzj43D7+SQXF/4pzW/hwtAqwc6iTitCiVSaWz5lYuqw= +github.com/golang/protobuf v1.3.4/go.mod h1:vzj43D7+SQXF/4pzW/hwtAqwc6iTitCiVSaWz5lYuqw= +github.com/golang/protobuf v1.3.5/go.mod h1:6O5/vntMXwX2lRkT1hjjk0nAC1IDOTvTlVgjlRvqsdk= github.com/golang/protobuf v1.4.0-rc.1/go.mod h1:ceaxUfeHdC40wWswd/P6IGgMaK3YpKi5j83Wpe3EHw8= github.com/golang/protobuf v1.4.0-rc.1.0.20200221234624-67d41d38c208/go.mod h1:xKAWHe0F5eneWXFV3EuXVDTCmh+JuBKY0li0aMyXATA= github.com/golang/protobuf v1.4.0-rc.2/go.mod h1:LlEzMj4AhA7rCAGe4KMBDvJI+AwstrUpVNzEA03Pprs= @@ -117,6 +151,7 @@ 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.3/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI= 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/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY= github.com/google/btree v0.0.0-20180813153112-4030bb1f1f0c/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ= @@ -127,26 +162,39 @@ github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5a github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= +github.com/google/go-cmp v0.4.1/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.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.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.6 h1:BKbKCqvP6I+rmFHt06ZmyQtvB8xAkWdhFyr0ZUNZcxQ= github.com/google/go-cmp v0.5.6/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= 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.1.0/go.mod h1:y5Zk1BBys9G+gd6Jrk0W3cC1+ELVxBWuIGO+w/tUAp0= 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-20191218002539-d4f498aebedc/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= +github.com/google/pprof v0.0.0-20200212024743-f11f1df84d12/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-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/renameio v0.1.0/go.mod h1:KWCgfxg9yswjAJkECMjeO8J8rahYeXnNhOm40UhjYkI= github.com/google/uuid v1.1.2/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= 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/gopherjs/gopherjs v0.0.0-20181017120253-0766667cb4d1/go.mod h1:wJfORRmW1u3UXTncJ5qlYoELFm8eSnnEO6hX4iZ3EWY= github.com/gorilla/websocket v1.4.2/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE= -github.com/grpc-ecosystem/go-grpc-middleware v1.0.0/go.mod h1:FiyG127CGDf3tlThmgyCl78X/SZQqEOJBCDaAfeWzPs= github.com/grpc-ecosystem/go-grpc-middleware v1.3.0/go.mod h1:z0ButlSOZa5vEBq9m2m2hlwIgKw+rp3sdCBRoJY+30Y= github.com/grpc-ecosystem/go-grpc-prometheus v1.2.0 h1:Ovs26xHkKqVztRpIrF/92BcuyuQ/YW4NSIpoGtfXNho= github.com/grpc-ecosystem/go-grpc-prometheus v1.2.0/go.mod h1:8NvIoxWQoOIhqOTXgfV/d3M/q6VIi02HzZEHgUlZvzk= -github.com/grpc-ecosystem/grpc-gateway v1.9.0/go.mod h1:vNeuVxBJEsws4ogUvrchl83t/GYV9WGTSLVdBhOQFDY= github.com/grpc-ecosystem/grpc-gateway v1.16.0/go.mod h1:BDjrQk3hbvj6Nolgz8mAMFbcEtjT1g+wF4CSlocrBnw= github.com/hashicorp/consul/api v1.1.0/go.mod h1:VmuI/Lkw1nC05EYQWNKwWGbkg+FbDBtguAZLlVdkD9Q= github.com/hashicorp/consul/sdk v0.1.1/go.mod h1:VKf9jXwCTEY1QZP2MOLRhb5i/I/ssyNV1vwHyQBF0x8= @@ -168,9 +216,10 @@ github.com/hashicorp/logutils v1.0.0/go.mod h1:QIAnNjmIWmVIIkWDTG1z5v++HQmx9WQRO github.com/hashicorp/mdns v1.0.0/go.mod h1:tL+uN++7HEJ6SQLQ2/p+z2pH24WQKWjBPkE0mNTz8vQ= github.com/hashicorp/memberlist v0.1.3/go.mod h1:ajVTdAv/9Im8oMAAj5G31PhhMCZJV2pPBoIllUwCN7I= github.com/hashicorp/serf v0.8.2/go.mod h1:6hOLApaqBFA1NXqRQAsxw9QxuDEvNxSQRwA/JwenrHc= +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/inconshreveable/mousetrap v1.0.0 h1:Z8tu5sraLXCXIcARxBp/8cbvlwVa7Z1NHg9XEKhtSvM= github.com/inconshreveable/mousetrap v1.0.0/go.mod h1:PxqpIevigyE2G7u3NXJIT2ANytuPF1OarO4DADm73n8= -github.com/jonboulle/clockwork v0.1.0/go.mod h1:Ii8DK3G1RaLaWxj9trq07+26W01tbo22gdxWY5EU2bo= github.com/jonboulle/clockwork v0.2.2 h1:UOGuzwb1PwsrDAObMuhUnj0p5ULPj8V/xJ7Kx9qUBdQ= github.com/jonboulle/clockwork v0.2.2/go.mod h1:Pkfl5aHPm1nk2H9h0bjmnJD/BcgbGXUBGnn1kMkgxc8= github.com/jpillora/backoff v1.0.0/go.mod h1:J/6gKK9jxlEcS3zixgDgUAsiuZ7yrSoa/FX5e0EB2j4= @@ -178,21 +227,22 @@ github.com/json-iterator/go v1.1.6/go.mod h1:+SdeFBvtyEkXs7REEP0seUULqWtbJapLOCV github.com/json-iterator/go v1.1.10/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4= github.com/json-iterator/go v1.1.11/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4= github.com/jstemmer/go-junit-report v0.0.0-20190106144839-af01ea7f8024/go.mod h1:6v2b51hI/fHJwM22ozAgKL4VKDeJcHhJFhtBdhmNjmU= +github.com/jstemmer/go-junit-report v0.9.1/go.mod h1:Brl9GWCQeLvo8nXZwPNNblvFj/XSXhF0NWZEnDohbsk= github.com/jtolds/gls v4.20.0+incompatible/go.mod h1:QJZ7F/aHp+rZTRtaJ1ow/lLfFfVYBRgL+9YlvaHOwJU= github.com/julienschmidt/httprouter v1.2.0/go.mod h1:SYymIcj16QtmaHHD7aYtjjsJG7VTCxuUUipMqKk8s4w= github.com/julienschmidt/httprouter v1.3.0/go.mod h1:JR6WtHb+2LUe8TCKY3cZOxFyyO8IZAc4RVcycCCAKdM= -github.com/kisielk/errcheck v1.1.0/go.mod h1:EZBBE59ingxPouuu3KfxchcWSUPOHkagtvWXihfKN4Q= github.com/kisielk/errcheck v1.2.0/go.mod h1:/BMXB+zMLi60iA8Vv6Ksmxu/1UDYcXs4uQLJ+jE2L00= github.com/kisielk/errcheck v1.5.0/go.mod h1:pFxgyoBC7bSaBwPgfKdkLd5X25qrDl4LWUI2bnpBCr8= github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck= github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= github.com/konsorten/go-windows-terminal-sequences v1.0.3/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= +github.com/kr/fs v0.1.0/go.mod h1:FFnZGqtBN9Gxj7eW1uZ42v5BccTP0vu6NEaFoC2HwRg= github.com/kr/logfmt v0.0.0-20140226030751-b84e30acd515/go.mod h1:+0opPa2QZZtGFBFZlji/RkVcI2GknAs/DXo4wKdlNEc= github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo= github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE= -github.com/magiconair/properties v1.8.1/go.mod h1:PppfXfuXeibc/6YijjN8zIbojt8czPbwD3XqdrwzmxQ= +github.com/magiconair/properties v1.8.5/go.mod h1:y3VJvCyxH9uVvJTWEGAELF3aiYNyPKd5NZ3oSwXrF60= github.com/mattn/go-colorable v0.0.9/go.mod h1:9vuHe8Xs5qXnSaW/c/ABM9alt+Vo+STaOChaDxuIBZU= github.com/mattn/go-isatty v0.0.3/go.mod h1:M+lRXTBqGeGNdLjl/ufCoiOlB5xdOkqRJdNxMWT7Zi4= github.com/mattn/go-runewidth v0.0.9 h1:Lm995f3rfxdpd6TSmuVCHVb/QhupuXlYr8sCI/QdE+0= @@ -202,33 +252,32 @@ github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5 github.com/miekg/dns v1.0.14/go.mod h1:W1PPwlIAgtquWBMBEV9nkV9Cazfe8ScdGz/Lj7v3Nrg= github.com/mitchellh/cli v1.0.0/go.mod h1:hNIlj7HEI86fIcpObd7a0FcrxTWetlwJDGcceTlRvqc= github.com/mitchellh/go-homedir v1.0.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0= -github.com/mitchellh/go-homedir v1.1.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0= github.com/mitchellh/go-testing-interface v1.0.0/go.mod h1:kRemZodwjscx+RGhAo8eIhFbs2+BFgRtFPeD/KE+zxI= github.com/mitchellh/gox v0.4.0/go.mod h1:Sd9lOJ0+aimLBi73mGofS1ycjY8lL3uZM3JPS42BGNg= github.com/mitchellh/iochan v1.0.0/go.mod h1:JwYml1nuB7xOzsp52dPpHFffvOCDupsG0QubkSMEySY= github.com/mitchellh/mapstructure v0.0.0-20160808181253-ca63d7c062ee/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y= github.com/mitchellh/mapstructure v1.1.2/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y= +github.com/mitchellh/mapstructure v1.4.1/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo= github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= github.com/modern-go/reflect2 v0.0.0-20180701023420-4b7aa43c6742/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0= github.com/modern-go/reflect2 v1.0.1/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0= github.com/mwitkow/go-conntrack v0.0.0-20161129095857-cc309e4a2223/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U= github.com/mwitkow/go-conntrack v0.0.0-20190716064945-2f068394615f/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U= -github.com/oklog/ulid v1.3.1/go.mod h1:CirwcVhetQ6Lv90oh/F+FBtV6XMibvdAFo93nm5qn4U= github.com/olekukonko/tablewriter v0.0.5 h1:P2Ga83D34wi1o9J6Wh1mRuqd4mF/x/lgBS7N7AbDhec= github.com/olekukonko/tablewriter v0.0.5/go.mod h1:hPp6KlRPjbx+hW8ykQs1w3UBbZlj6HuIJcUGPhkA7kY= github.com/opentracing/opentracing-go v1.1.0/go.mod h1:UkNAQd3GIcIGf0SeVgPpRdFStlNbqXla1AfSYxPUl2o= github.com/pascaldekloe/goe v0.0.0-20180627143212-57f6aae5913c/go.mod h1:lzWF7FIEvWOWxwDKqyGYQf6ZUaNfKdP144TG7ZOy1lc= -github.com/pelletier/go-toml v1.2.0/go.mod h1:5z9KED0ma1S8pY6P1sdut58dfprrGBbd/94hg7ilaic= +github.com/pelletier/go-toml v1.9.3/go.mod h1:u1nR/EPcESfeI/szUZKdtJ0xRNbUoANCkoOuaOx1Y+c= github.com/pkg/errors v0.8.0/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4= github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= +github.com/pkg/sftp v1.10.1/go.mod h1:lYOWFsE0bwd1+KfKJaKeuokY15vzFx25BLbzYYoAxZI= github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= github.com/posener/complete v1.1.1/go.mod h1:em0nMJCgc9GFtwrmVmEMR/ZL6WyhyjMBndrE9hABlRI= github.com/prometheus/client_golang v0.9.1/go.mod h1:7SWBe2y4D6OKWSNQJUaRYU/AaXPKyh/dDVn+NZz0KFw= -github.com/prometheus/client_golang v0.9.3/go.mod h1:/TN21ttK/J9q6uSwhBd54HahCDft0ttaMvbicHlPoso= github.com/prometheus/client_golang v1.0.0/go.mod h1:db9x61etRT2tGnBNRi70OPL5FsnadC4Ky3P0J6CfImo= github.com/prometheus/client_golang v1.7.1/go.mod h1:PY5Wy2awLA44sXw4AOSfFBetzPP4j5+D6mVACh+pe2M= github.com/prometheus/client_golang v1.11.0 h1:HNkLOAEQMIDv/K+04rukrLx6ch7msSRwf3/SASFAGtQ= @@ -238,20 +287,15 @@ github.com/prometheus/client_model v0.0.0-20190129233127-fd36f4220a90/go.mod h1: github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= github.com/prometheus/client_model v0.2.0 h1:uq5h0d+GuxiXLJLNABMgp2qUWDPiLvgCzz2dUR+/W/M= github.com/prometheus/client_model v0.2.0/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= -github.com/prometheus/common v0.0.0-20181113130724-41aa239b4cce/go.mod h1:daVV7qP5qjZbuso7PdcryaAu0sAZbrN9i7WWcTMWvro= -github.com/prometheus/common v0.4.0/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y86RQel1bk4= github.com/prometheus/common v0.4.1/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y86RQel1bk4= github.com/prometheus/common v0.10.0/go.mod h1:Tlit/dnDKsSWFlCLTWaA1cyBgKHSMdTB80sz/V91rCo= github.com/prometheus/common v0.26.0 h1:iMAkS2TDoNWnKM+Kopnx/8tnEStIfpYA0ur0xQzzhMQ= github.com/prometheus/common v0.26.0/go.mod h1:M7rCNAaPfAosfx8veZJCuw84e35h3Cfd9VFqTh1DIvc= github.com/prometheus/procfs v0.0.0-20181005140218-185b4288413d/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk= -github.com/prometheus/procfs v0.0.0-20190507164030-5867b95ac084/go.mod h1:TjEm7ze935MbeOT/UhFTIMYKhuLP4wbCsTZCD3I8kEA= github.com/prometheus/procfs v0.0.2/go.mod h1:TjEm7ze935MbeOT/UhFTIMYKhuLP4wbCsTZCD3I8kEA= github.com/prometheus/procfs v0.1.3/go.mod h1:lV6e/gmhEcM9IjHGsFOCxxuZ+z1YqCvr4OA4YeYWdaU= github.com/prometheus/procfs v0.6.0 h1:mxy4L2jP6qMonqmq+aTtOx1ifVWUgG/TAmntgbh3xv4= github.com/prometheus/procfs v0.6.0/go.mod h1:cz+aTbrPOrUb4q7XlbU9ygM+/jj0fzG6c1xBZuNvfVA= -github.com/prometheus/tsdb v0.7.1/go.mod h1:qhTCs0VvXwvX/y3TZrWD7rabWM+ijKTux40TwIPHuXU= -github.com/rogpeppe/fastuuid v0.0.0-20150106093220-6724a57986af/go.mod h1:XWv6SoW27p1b0cqNHllgS5HIMJraePCO15w5zCzIWYg= github.com/rogpeppe/fastuuid v1.2.0/go.mod h1:jVj6XXZzXRy/MSR5jhDC/2q6DgLz+nrA6LYCDYWNEvQ= github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4= github.com/russross/blackfriday/v2 v2.0.1/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= @@ -264,38 +308,42 @@ github.com/sirupsen/logrus v1.6.0/go.mod h1:7uNnSEd1DgxDLC74fIahvMZmmYsHGZGEOFrf github.com/sirupsen/logrus v1.8.1/go.mod h1:yWOB1SBYBC5VeMP7gHvWumXLIWorT60ONWic61uBYv0= github.com/smartystreets/assertions v0.0.0-20180927180507-b2de0cb4f26d/go.mod h1:OnSkiWE9lh6wB0YB77sQom3nweQdgAjqCqsofrRNTgc= github.com/smartystreets/goconvey v1.6.4/go.mod h1:syvi0/a8iFYH4r/RixwvyeAJjdLS9QV7WQ/tjFTllLA= -github.com/soheilhy/cmux v0.1.4/go.mod h1:IM3LyeVVIOuxMH7sFAkER9+bJ4dT7Ms6E4xg4kGIyLM= github.com/soheilhy/cmux v0.1.5/go.mod h1:T7TcVDs9LWfQgPlPsdngu6I6QIoyIFZDDC6sNE1GqG0= github.com/spaolacci/murmur3 v0.0.0-20180118202830-f09979ecbc72/go.mod h1:JwIasOWyU6f++ZhiEuf87xNszmSA2myDM2Kzu9HwQUA= -github.com/spf13/afero v1.1.2/go.mod h1:j4pytiNVoe2o6bmDsKpLACNPDBIoEAkihy7loJ1B0CQ= -github.com/spf13/cast v1.3.0/go.mod h1:Qx5cxh0v+4UWYiBimWS+eyWzqEqokIECu5etghLkUJE= -github.com/spf13/cobra v1.1.3 h1:xghbfqPkxzxP3C/f3n5DdpAbdKLj4ZE4BWQI362l53M= -github.com/spf13/cobra v1.1.3/go.mod h1:pGADOWyqRD/YMrPZigI/zbliZ2wVD/23d+is3pSWzOo= -github.com/spf13/jwalterweatherman v1.0.0/go.mod h1:cQK4TGJAtQXfYWX+Ddv3mKDzgVb68N+wFjFa4jdeBTo= -github.com/spf13/pflag v1.0.3/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4= +github.com/spf13/afero v1.6.0/go.mod h1:Ai8FlHk4v/PARR026UzYexafAt9roJ7LcLMAmO6Z93I= +github.com/spf13/cast v1.3.1/go.mod h1:Qx5cxh0v+4UWYiBimWS+eyWzqEqokIECu5etghLkUJE= +github.com/spf13/cobra v1.2.1 h1:+KmjbUw1hriSNMF55oPrkZcb27aECyrj8V2ytv7kWDw= +github.com/spf13/cobra v1.2.1/go.mod h1:ExllRjgxM/piMAM+3tAZvg8fsklGAf3tPfi+i8t68Nk= +github.com/spf13/jwalterweatherman v1.1.0/go.mod h1:aNWZUN0dPAAO/Ljvb5BEdw96iTZ0EXowPYD95IqWIGo= github.com/spf13/pflag v1.0.5 h1:iy+VFUOCP1a+8yFto/drg2CJ5u0yRoB7fZw3DKv/JXA= github.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg= -github.com/spf13/viper v1.7.0/go.mod h1:8WkrPz2fc9jxqZNCJI/76HCieCp4Q8HaLFoCha5qpdg= +github.com/spf13/viper v1.8.1/go.mod h1:o0Pch8wJ9BVSWGQMbra6iw0oQ5oktSIBaujf1rJH9Ns= github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= 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.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA= +github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/stretchr/testify v1.7.0 h1:nwc3DEeHmmLAfoZucVR881uASk0Mfjw8xYJ99tb5CcY= github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/subosito/gotenv v1.2.0/go.mod h1:N0PQaV/YGNqwC0u51sEeR/aUtSLEXKX9iv69rRypqCw= -github.com/tmc/grpc-websocket-proxy v0.0.0-20190109142713-0ad062ec5ee5/go.mod h1:ncp9v5uamzpCO7NfCPTXjqaC+bZgJeR0sMTm6dMHP7U= github.com/tmc/grpc-websocket-proxy v0.0.0-20201229170055-e5319fda7802/go.mod h1:ncp9v5uamzpCO7NfCPTXjqaC+bZgJeR0sMTm6dMHP7U= github.com/xiang90/probing v0.0.0-20190116061207-43a291ad63a2 h1:eY9dn8+vbi4tKz5Qo6v2eYzo7kUS51QINcR5jNpbZS8= github.com/xiang90/probing v0.0.0-20190116061207-43a291ad63a2/go.mod h1:UETIi67q53MR2AWcXfiuqkDkRtnGDLqkBTpCHuJHxtU= +github.com/yuin/goldmark v1.1.25/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= +github.com/yuin/goldmark v1.1.32/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= -go.etcd.io/bbolt v1.3.2/go.mod h1:IbVyRI1SCnLcuJnV2u8VeU0CEYM7e686BmAb1XKL+uU= go.etcd.io/bbolt v1.3.6 h1:/ecaJf0sk1l4l6V4awd65v2C3ILy7MSj+s/x1ADCIMU= go.etcd.io/bbolt v1.3.6/go.mod h1:qXsaaIqmgQH0T+OPdb99Bf+PKfBBQVAdyD6TY9G8XM4= 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.2/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.5/go.mod h1:5pWMHQbX5EPX2/62yrJeAkowc+lfs/XD7Uxpq3pI6kk= +go.opencensus.io v0.23.0/go.mod h1:XItmlyltB5F7CS4xOC1DcqMoFqwtC6OG2xF7mCv7P7E= go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.26.1 h1:puWrOArBwWlr5dq6vyZ6fKykHyS8JgMIVhTBA8XsGuU= go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.26.1/go.mod h1:4wsfAAW5N9wUHM0QTmZS8z7fvYZ1rv3m+sVeSpf8NhU= go.opentelemetry.io/otel v1.1.0/go.mod h1:7cww0OW51jQ8IaZChIEdqLwgh+44+7uiTdWsAL0wQpA= @@ -326,6 +374,7 @@ golang.org/x/crypto v0.0.0-20181029021203-45a5f77698d3/go.mod h1:6SG95UA2DQfeDnf golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= golang.org/x/crypto v0.0.0-20190510104115-cbcb75029529/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20190605123033-f99c8df09eb5/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= +golang.org/x/crypto v0.0.0-20190820162420-60c769a6c586/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= golang.org/x/crypto v0.0.0-20210513164829-c07d793c2f9a h1:kr2P4QFmQr29mSLA43kwrOcgcReGTfbE9N577tCTuBc= @@ -335,6 +384,11 @@ golang.org/x/exp v0.0.0-20190306152737-a1d7652674e8/go.mod h1:CJ0aWSM057203Lf6IL golang.org/x/exp v0.0.0-20190510132918-efd6b22b2522/go.mod h1:ZjyILWgesfNpC6sMxTJOJm9Kp84zZh5NQWvqDGG3Qr8= golang.org/x/exp v0.0.0-20190829153037-c13cbed26979/go.mod h1:86+5VVa7VpoJ4kLfm080zCjGlMRFzhUhsZKEZO7MGek= golang.org/x/exp v0.0.0-20191030013958-a1ab85dbe136/go.mod h1:JXzH8nQsPlswgeRAPE3MuO9GYsAcnJvJ4vnMwN/5qkY= +golang.org/x/exp v0.0.0-20191129062945-2f5052295587/go.mod h1:2RIsYlXP63K8oxa1u096TMicItID8zy7Y6sNkU49FU4= +golang.org/x/exp v0.0.0-20191227195350-da58074b4299/go.mod h1:2RIsYlXP63K8oxa1u096TMicItID8zy7Y6sNkU49FU4= +golang.org/x/exp v0.0.0-20200119233911-0405dc783f0a/go.mod h1:2RIsYlXP63K8oxa1u096TMicItID8zy7Y6sNkU49FU4= +golang.org/x/exp v0.0.0-20200207192155-f17229e696bd/go.mod h1:J/WKrq2StrnmMY6+EHIKF9dgMWnmCNThgcyBT1FY9mM= +golang.org/x/exp v0.0.0-20200224162631-6cc2880d07d6/go.mod h1:3jZMyOhIsHpP37uCMkUooju7aAi5cS1Q23tOzKc+0MU= golang.org/x/image v0.0.0-20190227222117-0694c2d4d067/go.mod h1:kZ7UVZpmo3dzQBMxlp+ypCbDeSB+sBbTgSJuh5dn5js= golang.org/x/image v0.0.0-20190802002840-cff245a6509b/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0= golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE= @@ -344,18 +398,25 @@ golang.org/x/lint v0.0.0-20190313153728-d0100b6bd8b3/go.mod h1:6SW0HCj/g11FgYtHl golang.org/x/lint v0.0.0-20190409202823-959b441ac422/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= golang.org/x/lint v0.0.0-20190909230951-414d861bb4ac/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= golang.org/x/lint v0.0.0-20190930215403-16217165b5de/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= +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-20200302205851-738671d3881b/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY= +golang.org/x/lint v0.0.0-20201208152925-83fdc39ff7b5/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-20190719004257-d2bd2a29d028/go.mod h1:E/iHnbuqvinMTCcRqshq8CkpyQDoeVncDDYHnLhea+o= golang.org/x/mod v0.0.0-20190513183733-4bf6d317e70e/go.mod h1:mXi4GBBbnImb6dmsKGUJ2LatrhH/nqhxcFungHvyanc= golang.org/x/mod v0.1.0/go.mod h1:0QHyrYULN0/3qlju5TqG8bIK38QM8yzMo5ekMj3DlcY= +golang.org/x/mod v0.1.1-0.20191105210325-c90efee705ee/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.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/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-20181023162649-9b4f9f5ad519/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20181114220301-adae6a3d119a/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20181201002055-351d144fa1fc/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= -golang.org/x/net v0.0.0-20181220203305-927f97764cc3/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20190108225652-1e06a53dbb7e/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20190213061140-3a22650c66bd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= @@ -365,33 +426,61 @@ golang.org/x/net v0.0.0-20190503192946-f4e77d36d62c/go.mod h1:t9HGtf8HONx5eT2rtn golang.org/x/net v0.0.0-20190603091049-60506f45cf65/go.mod h1:HSz+uSET+XFnRR8LxR5pz3Of3rY3CfYBVs4xY44aLks= golang.org/x/net v0.0.0-20190613194153-d28f0bde5980/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20190628185345-da137c7871d7/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20190724013045-ca1201d0de80/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20191209160850-c0dbc17a3553/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20200114155413-6afb5195e5aa/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20200202094626-16171245cfb2/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20200222125558-5a598a2470a0/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20200226121028-0de0cce0169b/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20200301022130-244492dfa37a/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20200324143707-d3edc9973b7e/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= +golang.org/x/net v0.0.0-20200501053045-e0ff5e5a1de5/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= +golang.org/x/net v0.0.0-20200506145744-7e3656a0809f/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= +golang.org/x/net v0.0.0-20200513185701-a91f0712d120/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= +golang.org/x/net v0.0.0-20200520182314-0ba52f642ac2/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= golang.org/x/net v0.0.0-20200625001655-4c5254603344/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-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-20201202161906-c7110b5ffcbb/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-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-20211123203042-d83791d6bcd9 h1:0qxwC5n+ttVOINCBeRHO0nq9X7uy8SDsPoi5OaCdIEI= golang.org/x/net v0.0.0-20211123203042-d83791d6bcd9/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= 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-20190604053449-0f29369cfe45/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= -golang.org/x/oauth2 v0.0.0-20200107190931-bf48bf16ab8d h1:TzXSXBo42m9gQenoE3b9BGiEpg5IG2JkU5FkPIawgtw= +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-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-20210402161424-2e8d93401602 h1:0Ja1LBD+yisY6RWM/BH7TJVXWsSjs2VwBSmvSX4HdBc= +golang.org/x/oauth2 v0.0.0-20210402161424-2e8d93401602/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= 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-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20190227155943-e225da77a7e6/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20200317015054-43a5402ce75a/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20200625203802-6e8e738ad208/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-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sys v0.0.0-20180823144017-11551d06cbcc/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20181026203630-95b1ffbd15a5/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= -golang.org/x/sys v0.0.0-20181107165924-66b7b1311ac8/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20181116152217-5ac8a444bdc5/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190312061237-fead79001313/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= @@ -401,16 +490,42 @@ golang.org/x/sys v0.0.0-20190502145724-3ef323f4f1fd/go.mod h1:h1NjWce9XRLGQEsW7w golang.org/x/sys v0.0.0-20190507160741-ecd444e8653b/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190606165138-5da285871e9c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190624142023-c5567b49c5d0/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190726091711-fc99dfbffb4e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20191001151750-bb3f8db39f24/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20191005200804-aed5e4c7ecf9/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20191026070338-33540a1f6037/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20191204072324-ce4227a45e2e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20191228213918-04cbcbbfeed8/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200106162015-b016eb3dc98e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200113162924-86b910548bc1/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200122134326-e047566fdf82/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200202164722-d101bd2416d5/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200212091648-12a6c2dcc1e4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200223170610-d5e6a3e2c0ae/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200302150141-5c8b2ff67527/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200331124033-c3d80250170d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200501052902-10377860bb8e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200511232937-7e40ca221e25/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200515095857-1151b9dac4a9/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200523222454-059865788121/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-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-20200923182605-d9f96fdee20d/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-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-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-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-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-20210423185535-09eb48e85fd7/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210510120138-977fb7262007/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= @@ -419,19 +534,21 @@ golang.org/x/sys v0.0.0-20210603125802-9665404d3644/go.mod h1:oPkhp1MJrh7nUepCBc golang.org/x/sys v0.0.0-20211123173158-ef496fb156ab h1:rfJ1bsoJQQIAoAxTxB7bme+vHrNkRw8CqfsYh9w54cw= golang.org/x/sys v0.0.0-20211123173158-ef496fb156ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= +golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.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.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.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/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-20191024005414-555d28b269f0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.0.0-20210220033141-f8bda1e9f3ba h1:O8mE0/t419eoIwhTFpKVkHiTs/Igowgfkj25AcZrtiE= golang.org/x/time v0.0.0-20210220033141-f8bda1e9f3ba/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= -golang.org/x/tools v0.0.0-20180221164845-07fd8470d635/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-20181030221726-6c7e314b6563/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20190114222345-bf090417da8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= @@ -450,9 +567,39 @@ golang.org/x/tools v0.0.0-20190816200558-6889da9d5479/go.mod h1:b+2E5dAYhXwXZwtn golang.org/x/tools v0.0.0-20190911174233-4f2ddba30aff/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.0.0-20191012152004-8de300cfc20a/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.0.0-20191112195655-aa38f8e97acc/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-20191113191852-77e3bb0ad9e7/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-20191115202509-3a792d9c32b2/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-20191125144606-a911d9008d1f/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-20191130070609-6e064ea0cf2d/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-20191216173652-a0e659d51361/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= +golang.org/x/tools v0.0.0-20191227053925-7b8e75db28f4/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= +golang.org/x/tools v0.0.0-20200117161641-43d50277825c/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= +golang.org/x/tools v0.0.0-20200122220014-bf1340f18c4a/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= +golang.org/x/tools v0.0.0-20200130002326-2f3ba24bd6e7/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= +golang.org/x/tools v0.0.0-20200204074204-1cc6d1ef6c74/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= +golang.org/x/tools v0.0.0-20200207183749-b753a1ba74fa/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= +golang.org/x/tools v0.0.0-20200212150539-ea181f53ac56/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= +golang.org/x/tools v0.0.0-20200224181240-023911ca70b2/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= +golang.org/x/tools v0.0.0-20200227222343-706bc42d1f0d/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= +golang.org/x/tools v0.0.0-20200304193943-95d2e580d8eb/go.mod h1:o4KQGtdN14AW+yjsvvwRTJJuXz8XRtIHtEnmAXLyFUw= +golang.org/x/tools v0.0.0-20200312045724-11d5b4c81c7d/go.mod h1:o4KQGtdN14AW+yjsvvwRTJJuXz8XRtIHtEnmAXLyFUw= +golang.org/x/tools v0.0.0-20200331025713-a30bf2db82d4/go.mod h1:Sl4aGygMT6LrqrWclx+PTx3U+LnKx/seiNR+3G19Ar8= +golang.org/x/tools v0.0.0-20200501065659-ab2804fb9c9d/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= +golang.org/x/tools v0.0.0-20200512131952-2bc93b1c0c88/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= +golang.org/x/tools v0.0.0-20200515010526-7d3b6ebf133d/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= +golang.org/x/tools v0.0.0-20200618134242-20370b0cb4b2/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= golang.org/x/tools v0.0.0-20200619180055-7c47624df98f/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= +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-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-20210105154028-b0ab187a4818/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/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-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= @@ -463,11 +610,31 @@ google.golang.org/api v0.7.0/go.mod h1:WtwebWUNSVBH/HAw79HIFXZNqEvBhG+Ra+ax0hx3E google.golang.org/api v0.8.0/go.mod h1:o4eAsZoiT+ibD93RtjEohWalFOjRDx6CVaqeizhEnKg= google.golang.org/api v0.9.0/go.mod h1:o4eAsZoiT+ibD93RtjEohWalFOjRDx6CVaqeizhEnKg= google.golang.org/api v0.13.0/go.mod h1:iLdEw5Ide6rF15KTC1Kkl0iskquN2gFfn9o9XIsbkAI= +google.golang.org/api v0.14.0/go.mod h1:iLdEw5Ide6rF15KTC1Kkl0iskquN2gFfn9o9XIsbkAI= +google.golang.org/api v0.15.0/go.mod h1:iLdEw5Ide6rF15KTC1Kkl0iskquN2gFfn9o9XIsbkAI= +google.golang.org/api v0.17.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE= +google.golang.org/api v0.18.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE= +google.golang.org/api v0.19.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE= +google.golang.org/api v0.20.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE= +google.golang.org/api v0.22.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE= +google.golang.org/api v0.24.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.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.44.0/go.mod h1:EBOGZqzyhtvMDoxwS97ctnh0zUmYY6CxqXsc1AvkYD8= 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.5.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= -google.golang.org/appengine v1.6.1 h1:QzqyMA1tlu6CgqCDUtU9V+ZKhLFT2dkJuANu5QaxI3I= google.golang.org/appengine v1.6.1/go.mod h1:i06prIuMbXzDqacNJfV5OdTW448YApPu5ww/cMBSeb0= +google.golang.org/appengine v1.6.5/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-20190307195333-5fe7a883aa19/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= google.golang.org/genproto v0.0.0-20190418145605-e7d98fc518a7/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= @@ -477,9 +644,38 @@ google.golang.org/genproto v0.0.0-20190801165951-fa694d86fc64/go.mod h1:DMBHOl98 google.golang.org/genproto v0.0.0-20190819201941-24fa4b261c55/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc= google.golang.org/genproto v0.0.0-20190911173649-1774047e7e51/go.mod h1:IbNlFCBrqXvoKpeg0TB2l7cyZUmoaFKYIwrEpbDKLA8= google.golang.org/genproto v0.0.0-20191108220845-16a3f7862a1a/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= +google.golang.org/genproto v0.0.0-20191115194625-c23dd37a84c9/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= +google.golang.org/genproto v0.0.0-20191216164720-4f79533eabd1/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= +google.golang.org/genproto v0.0.0-20191230161307-f3c370f40bfb/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= +google.golang.org/genproto v0.0.0-20200115191322-ca5a22157cba/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= +google.golang.org/genproto v0.0.0-20200122232147-0452cf42e150/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= +google.golang.org/genproto v0.0.0-20200204135345-fa8e72b47b90/go.mod h1:GmwEX6Z4W5gMy59cAlVYjN9JhxgbQH6Gn+gFDQe2lzA= +google.golang.org/genproto v0.0.0-20200212174721-66ed5ce911ce/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= +google.golang.org/genproto v0.0.0-20200224152610-e50cd9704f63/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= +google.golang.org/genproto v0.0.0-20200228133532-8c2c7df3a383/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= +google.golang.org/genproto v0.0.0-20200305110556-506484158171/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= +google.golang.org/genproto v0.0.0-20200312145019-da6875a35672/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= +google.golang.org/genproto v0.0.0-20200331122359-1ee6d9798940/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= google.golang.org/genproto v0.0.0-20200423170343-7949de9c1215/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= +google.golang.org/genproto v0.0.0-20200430143042-b979b6f78d84/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= +google.golang.org/genproto v0.0.0-20200511104702-f5ebc3bea380/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= google.golang.org/genproto v0.0.0-20200513103714-09dca8ec2884/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= +google.golang.org/genproto v0.0.0-20200515170657-fc4c6c6a6587/go.mod h1:YsZOwe1myG/8QRHRsmBRE1LrgQY60beZKjly0O1fX9U= google.golang.org/genproto v0.0.0-20200526211855-cb27e3aa2013/go.mod h1:NbSheEEYHJ7i3ixzK3sjbqSGDJWnxyFXZblF3eUsNvo= +google.golang.org/genproto v0.0.0-20200618031413-b414f8b61790/go.mod h1:jDfRM7FcilCzHH/e9qn6dsT145K34l5v+OpcnNgKAAA= +google.golang.org/genproto v0.0.0-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-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-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-20210402141018-6c239bbf2bb1/go.mod h1:9lPAdzaEmUacj36I+k7YKbEc5CXzPIeORRgDAUOu28A= google.golang.org/genproto v0.0.0-20211118181313-81c1377c94b1 h1:b9mVrqYfq3P4bCdaLg1qtBnPzUYgglsIdjZkL/fQVOE= google.golang.org/genproto v0.0.0-20211118181313-81c1377c94b1/go.mod h1:5CzLGKJ67TSI2B9POpiiyGha0AjJvZIUgRMt1dSmuhc= google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c= @@ -487,11 +683,22 @@ google.golang.org/grpc v1.20.1/go.mod h1:10oTOabMzJvdu6/UiuZezV6QK5dSlG84ov/aaiq google.golang.org/grpc v1.21.1/go.mod h1:oYelfM1adQP15Ek0mdvEgi9Df8B9CZIaU1084ijfRaM= google.golang.org/grpc v1.23.0/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg= google.golang.org/grpc v1.25.1/go.mod h1:c3i+UQWmh7LiEpx4sFZnkU36qjEYZ0imhYfXVyQciAY= +google.golang.org/grpc v1.26.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk= google.golang.org/grpc v1.27.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk= +google.golang.org/grpc v1.27.1/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk= +google.golang.org/grpc v1.28.0/go.mod h1:rpkK4SK4GF4Ach/+MFLZUBavHOvF2JJB5uozKKal+60= 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.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.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.1/go.mod h1:qjiiYl8FncCW8feJPdyg3v6XW24KsRHe+dy9BAGRRjU= 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.40.0/go.mod h1:ogyxbiOoUXAkP+4+xa6PZSE9DZgIHtSpzjDTB9KAK34= google.golang.org/grpc v1.41.0 h1:f+PlOh7QV4iIJkPrx5NQ7qaNGFQ3OTse67yaDHfju4E= google.golang.org/grpc v1.41.0/go.mod h1:U3l9uK9J0sini8mHphKoXyaqDA/8VyGnDee1zzIUK6k= @@ -503,6 +710,7 @@ google.golang.org/protobuf v1.21.0/go.mod h1:47Nbq4nVaFHyn7ilMalzfO3qCViNmqZ2kzi google.golang.org/protobuf v1.22.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= google.golang.org/protobuf v1.23.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= google.golang.org/protobuf v1.23.1-0.20200526195155-81db48ad09cc/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= +google.golang.org/protobuf v1.24.0/go.mod h1:r/3tXBNzIEhYS9I1OUVjXDlt8tc493IdKGjtUeSXeh4= google.golang.org/protobuf v1.25.0/go.mod h1:9JNX74DMeImyA3h4bdi1ymwjUzf21/xIlbajtzgsN7c= google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw= google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc= @@ -513,10 +721,8 @@ gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8 gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/errgo.v2 v2.1.0/go.mod h1:hNsd1EY+bozCKY1Ytp96fpM3vjJbqLJn88ws8XvfDNI= -gopkg.in/ini.v1 v1.51.0/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k= +gopkg.in/ini.v1 v1.62.0/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k= gopkg.in/natefinch/lumberjack.v2 v2.0.0/go.mod h1:l0ndWWf7gzL7RNwBG7wST/UCcT4T24xpD6X8LsfU/+k= -gopkg.in/resty.v1 v1.12.0/go.mod h1:mDo4pnntr5jdWRML875a/NmxYqAlA73dVijT2AXvQQo= -gopkg.in/yaml.v2 v2.0.0-20170812160011-eb3733d160e7/go.mod h1:JAlM8MvJe8wmxCU4Bli9HhUf9+ttbYbLASfIpnQbh74= gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.2.3/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= @@ -534,7 +740,11 @@ honnef.co/go/tools v0.0.0-20190106161140-3f1c8253044a/go.mod h1:rf3lG4BRIbNafJWh honnef.co/go/tools v0.0.0-20190418001031-e561f6794a2a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= honnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= honnef.co/go/tools v0.0.1-2019.2.3/go.mod h1:a3bituU0lyd329TUQxRnasdCoJDkEUEAqEt0JzvZhAg= +honnef.co/go/tools v0.0.1-2020.1.3/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9vFzvIQ3k= +honnef.co/go/tools v0.0.1-2020.1.4/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9vFzvIQ3k= 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/sampler v1.3.0/go.mod h1:T1hPZKmBbMNahiBKFy5HrXp6adAjACjK9JXDnKaTXpA= sigs.k8s.io/json v0.0.0-20211020170558-c049b76a60c6 h1:fD1pz4yfdADVNfFmcP2aBEtudwUQ1AlLnRBALr33v3s= sigs.k8s.io/json v0.0.0-20211020170558-c049b76a60c6/go.mod h1:p4QtZmO4uMYipTQNzagwnNoseA6OxSUutVw05NhYDRs= sigs.k8s.io/yaml v1.2.0/go.mod h1:yfXDCHCao9+ENCvLSE62v9VSji2MKu5jeNfTrofGhJc= diff --git a/go.mod b/go.mod index 0c8ef7897fa6..a00aacf320cf 100644 --- a/go.mod +++ b/go.mod @@ -18,7 +18,7 @@ replace ( require ( github.com/bgentry/speakeasy v0.1.0 github.com/dustin/go-humanize v1.0.0 - github.com/spf13/cobra v1.1.3 + github.com/spf13/cobra v1.2.1 go.etcd.io/bbolt v1.3.6 go.etcd.io/etcd/api/v3 v3.5.0 go.etcd.io/etcd/client/pkg/v3 v3.5.0 diff --git a/go.sum b/go.sum index 5b24ff5fd3f7..5370a57f8a04 100644 --- a/go.sum +++ b/go.sum @@ -4,13 +4,39 @@ cloud.google.com/go v0.38.0/go.mod h1:990N+gfupTy94rShfmMCWGDn0LpTmnzTp2qbd1dvSR cloud.google.com/go v0.44.1/go.mod h1:iSa0KzasP4Uvy3f1mN/7PiObzGgflwredwwASm/v6AU= cloud.google.com/go v0.44.2/go.mod h1:60680Gw3Yr4ikxnPRS/oxxkBccT6SA1yMk63TGekxKY= cloud.google.com/go v0.45.1/go.mod h1:RpBamKRgapWJb87xiFSdk4g1CME7QZg3uwTez+TSTjc= -cloud.google.com/go v0.46.3 h1:AVXDdKsrtX33oR9fbCMu/+c1o8Ofjq6Ku/MInaLVg5Y= cloud.google.com/go v0.46.3/go.mod h1:a6bKKbmY7er1mI7TEI4lsAkts/mkhTSZK8w33B4RAg0= +cloud.google.com/go v0.50.0/go.mod h1:r9sluTvynVuxRIOHXQEHMFffphuXHOMZMycpNR5e6To= +cloud.google.com/go v0.52.0/go.mod h1:pXajvRH/6o3+F9jDHZWQ5PbGhn+o8w9qiu/CffaVdO4= +cloud.google.com/go v0.53.0/go.mod h1:fp/UouUEsRkN6ryDKNW/Upv/JBKnv6WDthjR6+vze6M= +cloud.google.com/go v0.54.0/go.mod h1:1rq2OEkV3YMf6n/9ZvGWI3GWw0VoqH/1x2nd8Is/bPc= +cloud.google.com/go v0.56.0/go.mod h1:jr7tqZxxKOVYizybht9+26Z/gUq7tiRzu+ACVAMbKVk= +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.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 h1:at8Tk2zUz63cLPR0JPWm5vp77pEZmzxEQBEfRKn1VV8= +cloud.google.com/go v0.81.0/go.mod h1:mk/AM35KwGk/Nm2YSeZbxXdrNK3KZOYHmLkOqC2V6E0= 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.4.0/go.mod h1:S8dzgnTigyfTmLBfrtrhyYhwRxG72rYxvftPBK2Dvzc= +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.8.0/go.mod h1:J5hqkt3O0uAFnINi6JXValWIb1v0goeZM77hZzJN/fQ= 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/firestore v1.1.0/go.mod h1:ulACoGHTpvq5r8rxGJ4ddJZBZqakUQqClKRT5SZwBmk= 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.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/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.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.10.0/go.mod h1:FLPqc6j+Ki4BU591ie1oL6qBQGu2Bl/tZ9ullr3+Kg0= dmitri.shuralyov.com/gpu/mtl v0.0.0-20190408044501-666a987793e9/go.mod h1:H6x//7gZCb22OMCxBHrMx7a5I7Hp++hsVxbQ4BYO7hU= github.com/BurntSushi/toml v0.3.1 h1:WXkYYl6Yr3qBf1K79EBnL4mak0OimBfB0XUf9Vl28OQ= github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= @@ -31,7 +57,7 @@ github.com/beorn7/perks v1.0.1 h1:VlbKKnNfV8bJzeqoa4cOKqO6bYr3WgKZxO8Z16+hsOM= github.com/beorn7/perks v1.0.1/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6rlkpw= github.com/bgentry/speakeasy v0.1.0 h1:ByYyxL9InA1OWqxJqqp2A5pYHUrCiAL6K3J+LKSsQkY= github.com/bgentry/speakeasy v0.1.0/go.mod h1:+zsyZBPWlz7T6j88CTgSN5bM796AkVf0kBD4zp0CCIs= -github.com/bketelsen/crypt v0.0.3-0.20200106085610-5cbc8cc4026c/go.mod h1:MKsuJmJgSg28kpZDP6UIiPt0e0Oz0kqKNGyRaWEPv84= +github.com/bketelsen/crypt v0.0.4/go.mod h1:aI6NrJ0pMGgvZKL1iVgXLnfIFJtfV+bKCoqOes/6LfM= github.com/cenkalti/backoff/v4 v4.1.1 h1:G2HAfAmvm/GcKan2oOQpBXOd2tT2G57ZnZGWa1PxPBQ= github.com/cenkalti/backoff/v4 v4.1.1/go.mod h1:scbssz8iZGpm3xbr14ovlUdkxfGXNInqkPWOWmG2CLw= github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU= @@ -42,8 +68,12 @@ github.com/cespare/xxhash v1.1.0 h1:a6HrQnmkObjyL+Gs60czilIUGqrzKutQD6XZog3p+ko= github.com/cespare/xxhash v1.1.0/go.mod h1:XrSqR1VqqWfGrhpAt58auRo0WTKS1nRRg3ghfAqPWnc= github.com/cespare/xxhash/v2 v2.1.1 h1:6MnRN8NT7+YBpUIWxHtefFZOKTAPgGjpQSxqLNn0+qY= github.com/cespare/xxhash/v2 v2.1.1/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= +github.com/chzyer/logex v1.1.10/go.mod h1:+Ywpsq7O8HXn0nuIou7OrIPyXbp3wmkHB+jjWRnGsAI= +github.com/chzyer/readline v0.0.0-20180603132655-2972be24d48e/go.mod h1:nSuG5e5PlCu98SY8svDHJxuZscDgtXS6KTTbou5AhLI= +github.com/chzyer/test v0.0.0-20180213035817-a1ea475d72b1/go.mod h1:Q3SI9o4m/ZMnBNeIyt5eFwwo7qiLfzFZmjNmxjkiQlU= github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw= 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/xds/go v0.0.0-20210312221358-fbca930ec8ed/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs= github.com/cncf/xds/go v0.0.0-20210805033703-aa0b78936158/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs= @@ -53,15 +83,10 @@ github.com/cockroachdb/errors v1.2.4 h1:Lap807SXTH5tri2TivECb/4abUkMZC9zRoLarvcK github.com/cockroachdb/errors v1.2.4/go.mod h1:rQD95gz6FARkaKkQXUksEje/d9a6wBJoCr5oaCLELYA= github.com/cockroachdb/logtags v0.0.0-20190617123548-eb05cc24525f h1:o/kfcElHqOiXqcou5a3rIlMc7oJbMQkeLk0VQJ7zgqY= github.com/cockroachdb/logtags v0.0.0-20190617123548-eb05cc24525f/go.mod h1:i/u985jwjWRlyHXQbwatDASoW0RMlZ/3i9yJHE2xLkI= -github.com/coreos/bbolt v1.3.2/go.mod h1:iRUV2dpdMOn7Bo10OQBFzIJO9kkE559Wcmn+qkEiiKk= -github.com/coreos/etcd v3.3.13+incompatible/go.mod h1:uF7uidLiAD3TWHmW31ZFd/JWoc32PjwdhPthX9715RE= github.com/coreos/go-semver v0.3.0 h1:wkHLiw0WNATZnSG7epLsujiMCgPAc9xhjJ4tgnAxmfM= github.com/coreos/go-semver v0.3.0/go.mod h1:nnelYz7RCh+5ahJtPPxZlU+153eP4D4r3EedlOD2RNk= -github.com/coreos/go-systemd v0.0.0-20190321100706-95778dfbb74e h1:Wf6HqHfScWJN9/ZjdUKyjop4mf3Qdd+1TvvltAvM3m8= -github.com/coreos/go-systemd v0.0.0-20190321100706-95778dfbb74e/go.mod h1:F5haX7vjVVG0kc13fIWeqUViNPyEJxv/OmvnBo0Yme4= github.com/coreos/go-systemd/v22 v22.3.2 h1:D9/bQk5vlXQFZ6Kwuu6zaiXJ9oTPe68++AzAJc1DzSI= github.com/coreos/go-systemd/v22 v22.3.2/go.mod h1:Y58oyj3AT4RCenI/lSvhwexgC+NSVTIJ3seZv2GcEnc= -github.com/coreos/pkg v0.0.0-20180928190104-399ea9e2e55f/go.mod h1:E3G3o1h8I7cfcXa63jLwjI0eiQQMgzzUDFVpN/nH/eA= github.com/cpuguy83/go-md2man/v2 v2.0.0-20190314233015-f79a8a8ca69d/go.mod h1:maD7wRr/U5Z6m/iR4s+kqSMx2CaBsrgA7czyZG/E6dU= github.com/cpuguy83/go-md2man/v2 v2.0.0/go.mod h1:maD7wRr/U5Z6m/iR4s+kqSMx2CaBsrgA7czyZG/E6dU= github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E= @@ -69,13 +94,12 @@ github.com/creack/pty v1.1.11/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= -github.com/dgrijalva/jwt-go v3.2.0+incompatible/go.mod h1:E3ru+11k8xSBh+hMPgOLZmtrrCbhqsmaPHjLKYnJCaQ= -github.com/dgryski/go-sip13 v0.0.0-20181026042036-e10d5fee7954/go.mod h1:vAd38F8PWV+bWy6jNmig1y/TA+kYO4g3RSRF0IAv0no= github.com/dustin/go-humanize v1.0.0 h1:VSnTsYCnlFHaM2/igO1h6X3HA71jcobQuxemgkq4zYo= github.com/dustin/go-humanize v1.0.0/go.mod h1:HtrtbFcZ19U5GC7JDqmcUSB87Iq5E25KnS6fMYU6eOk= 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.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.20210217033140-668b12f5399d/go.mod h1:cXg6YxExXjJnVBQHBLXeUAgxn2UodCpnH306RInaBQk= github.com/envoyproxy/go-control-plane v0.9.9-0.20210512163311-63b5d3c536b0/go.mod h1:hliV/p42l8fGbc6Y9bQ70uLwIvmJyVE5k4iMKlh8wCQ= @@ -83,11 +107,13 @@ github.com/envoyproxy/go-control-plane v0.9.10-0.20210907150352-cf90f659a021/go. github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c= github.com/fatih/color v1.7.0 h1:DkWD4oS2D8LGGgTQ6IvwJJXSL5Vp2ffcQg58nFV38Ys= github.com/fatih/color v1.7.0/go.mod h1:Zm6kSWBoL9eyXnKyktHP6abPY2pDugNf5KwzbycvMj4= -github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo= +github.com/fsnotify/fsnotify v1.4.9/go.mod h1:znqG4EE+3YCdAaPaxE2ZRY/06pZUdp0tY4IgpuI1SZQ= github.com/getsentry/raven-go v0.2.0 h1:no+xWJRb5ZI7eE8TWgIq1jLulQiIoLG0IfYxv5JYMGs= github.com/getsentry/raven-go v0.2.0/go.mod h1:KungGk8q33+aIAZUIVWZDr2OfAEBsO49PX4NzFV5kcQ= github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04= github.com/go-gl/glfw v0.0.0-20190409004039-e6da0acd62b1/go.mod h1:vR7hzQXu2zJy9AVAgeJqvqgH9Q5CA+iKCZ2gyEVpxRU= +github.com/go-gl/glfw/v3.3/glfw v0.0.0-20191125211704-12ad95a8df72/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8= +github.com/go-gl/glfw/v3.3/glfw v0.0.0-20200222043503-6f7a984d4dc4/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8= github.com/go-kit/kit v0.8.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as= github.com/go-kit/kit v0.9.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as= github.com/go-kit/log v0.1.0/go.mod h1:zbhenjAZHb184qTLMA9ZjW7ThYL0H2mk7Q6pNt4vbaY= @@ -97,23 +123,31 @@ github.com/go-logfmt/logfmt v0.5.0/go.mod h1:wCYkCAKZfumFQihp8CzCvQ3paCTfi41vtzG github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY= 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.2.1/go.mod h1:hp+jE20tsWTFYpLwKvXlhS1hjn+gTNwPg2I6zVXpSg4= github.com/gogo/protobuf v1.3.1/go.mod h1:SlYgWuQ5SjCEi6WLHjHCa1yvBfUnHcTbrrZtXPKa29o= github.com/gogo/protobuf v1.3.2 h1:Ov1cvc58UF3b5XjBnZv7+opcTcQFZebYjWzi34vdm4Q= github.com/gogo/protobuf v1.3.2/go.mod h1:P1XiOD3dCwIKUDQYPy72D8LYyHL2YPYrpS2s69NZV8Q= github.com/golang-jwt/jwt v3.2.2+incompatible h1:IfV12K8xAKAnZqdXVzCZ+TOjboZ2keLg81eXfW3O+oY= github.com/golang-jwt/jwt v3.2.2+incompatible/go.mod h1:8pz2t5EyA70fFQQSrl6XZXzqecmYZeUEB8OUGHkxJ+I= github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q= -github.com/golang/groupcache v0.0.0-20190129154638-5b532d6fd5ef/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= +github.com/golang/groupcache v0.0.0-20190702054246-869f871628b6/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= +github.com/golang/groupcache v0.0.0-20191227052852-215e87163ea7/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= +github.com/golang/groupcache v0.0.0-20200121045136-8c9f03a8e57e/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da h1:oI5xCqsCo564l8iNU+DwB5epxmsaqB+rhGL0m5jtYqE= github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= github.com/golang/mock v1.1.1/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A= github.com/golang/mock v1.2.0/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A= github.com/golang/mock v1.3.1/go.mod h1:sBzyDLLjw3U8JLTeZvSv8jJB+tU5PVekmnlKIyFUx0Y= +github.com/golang/mock v1.4.0/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.4/go.mod h1:l3mdAwkq5BuhzHwde/uurv3sEJeZMXNpwsxVWU71h+4= +github.com/golang/mock v1.5.0/go.mod h1:CWnOUgYIOo4TcNZ0wHX3YZCqsaM1I1Jvs6v3mP3KVu8= github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= github.com/golang/protobuf v1.3.1/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= github.com/golang/protobuf v1.3.2/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= github.com/golang/protobuf v1.3.3/go.mod h1:vzj43D7+SQXF/4pzW/hwtAqwc6iTitCiVSaWz5lYuqw= +github.com/golang/protobuf v1.3.4/go.mod h1:vzj43D7+SQXF/4pzW/hwtAqwc6iTitCiVSaWz5lYuqw= +github.com/golang/protobuf v1.3.5/go.mod h1:6O5/vntMXwX2lRkT1hjjk0nAC1IDOTvTlVgjlRvqsdk= github.com/golang/protobuf v1.4.0-rc.1/go.mod h1:ceaxUfeHdC40wWswd/P6IGgMaK3YpKi5j83Wpe3EHw8= github.com/golang/protobuf v1.4.0-rc.1.0.20200221234624-67d41d38c208/go.mod h1:xKAWHe0F5eneWXFV3EuXVDTCmh+JuBKY0li0aMyXATA= github.com/golang/protobuf v1.4.0-rc.2/go.mod h1:LlEzMj4AhA7rCAGe4KMBDvJI+AwstrUpVNzEA03Pprs= @@ -123,6 +157,7 @@ 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.3/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI= 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/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY= github.com/google/btree v0.0.0-20180813153112-4030bb1f1f0c/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ= @@ -133,15 +168,30 @@ github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5a github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= +github.com/google/go-cmp v0.4.1/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.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.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.6 h1:BKbKCqvP6I+rmFHt06ZmyQtvB8xAkWdhFyr0ZUNZcxQ= github.com/google/go-cmp v0.5.6/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= 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.1.0/go.mod h1:y5Zk1BBys9G+gd6Jrk0W3cC1+ELVxBWuIGO+w/tUAp0= 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-20191218002539-d4f498aebedc/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= +github.com/google/pprof v0.0.0-20200212024743-f11f1df84d12/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-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/renameio v0.1.0/go.mod h1:KWCgfxg9yswjAJkECMjeO8J8rahYeXnNhOm40UhjYkI= github.com/google/uuid v1.1.2/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/googleapis/gax-go/v2 v2.0.4/go.mod h1:0Wqv26UfaUD9n4G6kQubkQ+KchISgw+vpHVxEJEs9eg= @@ -149,12 +199,10 @@ github.com/googleapis/gax-go/v2 v2.0.5/go.mod h1:DWXyrwAJ9X0FpwwEdw+IPEYBICEFu5m github.com/gopherjs/gopherjs v0.0.0-20181017120253-0766667cb4d1/go.mod h1:wJfORRmW1u3UXTncJ5qlYoELFm8eSnnEO6hX4iZ3EWY= github.com/gorilla/websocket v1.4.2 h1:+/TMaTYc4QFitKJxsQ7Yye35DkWvkdLcvGKqM+x0Ufc= github.com/gorilla/websocket v1.4.2/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE= -github.com/grpc-ecosystem/go-grpc-middleware v1.0.0/go.mod h1:FiyG127CGDf3tlThmgyCl78X/SZQqEOJBCDaAfeWzPs= github.com/grpc-ecosystem/go-grpc-middleware v1.3.0 h1:+9834+KizmvFV7pXQGSXQTsaWhq2GjuNUt0aUU0YBYw= github.com/grpc-ecosystem/go-grpc-middleware v1.3.0/go.mod h1:z0ButlSOZa5vEBq9m2m2hlwIgKw+rp3sdCBRoJY+30Y= github.com/grpc-ecosystem/go-grpc-prometheus v1.2.0 h1:Ovs26xHkKqVztRpIrF/92BcuyuQ/YW4NSIpoGtfXNho= github.com/grpc-ecosystem/go-grpc-prometheus v1.2.0/go.mod h1:8NvIoxWQoOIhqOTXgfV/d3M/q6VIi02HzZEHgUlZvzk= -github.com/grpc-ecosystem/grpc-gateway v1.9.0/go.mod h1:vNeuVxBJEsws4ogUvrchl83t/GYV9WGTSLVdBhOQFDY= github.com/grpc-ecosystem/grpc-gateway v1.16.0 h1:gmcG1KaJ57LophUzW0Hy8NmPhnMZb4M0+kPpLofRdBo= github.com/grpc-ecosystem/grpc-gateway v1.16.0/go.mod h1:BDjrQk3hbvj6Nolgz8mAMFbcEtjT1g+wF4CSlocrBnw= github.com/hashicorp/consul/api v1.1.0/go.mod h1:VmuI/Lkw1nC05EYQWNKwWGbkg+FbDBtguAZLlVdkD9Q= @@ -177,9 +225,10 @@ github.com/hashicorp/logutils v1.0.0/go.mod h1:QIAnNjmIWmVIIkWDTG1z5v++HQmx9WQRO github.com/hashicorp/mdns v1.0.0/go.mod h1:tL+uN++7HEJ6SQLQ2/p+z2pH24WQKWjBPkE0mNTz8vQ= github.com/hashicorp/memberlist v0.1.3/go.mod h1:ajVTdAv/9Im8oMAAj5G31PhhMCZJV2pPBoIllUwCN7I= github.com/hashicorp/serf v0.8.2/go.mod h1:6hOLApaqBFA1NXqRQAsxw9QxuDEvNxSQRwA/JwenrHc= +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/inconshreveable/mousetrap v1.0.0 h1:Z8tu5sraLXCXIcARxBp/8cbvlwVa7Z1NHg9XEKhtSvM= github.com/inconshreveable/mousetrap v1.0.0/go.mod h1:PxqpIevigyE2G7u3NXJIT2ANytuPF1OarO4DADm73n8= -github.com/jonboulle/clockwork v0.1.0/go.mod h1:Ii8DK3G1RaLaWxj9trq07+26W01tbo22gdxWY5EU2bo= github.com/jonboulle/clockwork v0.2.2 h1:UOGuzwb1PwsrDAObMuhUnj0p5ULPj8V/xJ7Kx9qUBdQ= github.com/jonboulle/clockwork v0.2.2/go.mod h1:Pkfl5aHPm1nk2H9h0bjmnJD/BcgbGXUBGnn1kMkgxc8= github.com/jpillora/backoff v1.0.0/go.mod h1:J/6gKK9jxlEcS3zixgDgUAsiuZ7yrSoa/FX5e0EB2j4= @@ -187,15 +236,16 @@ github.com/json-iterator/go v1.1.6/go.mod h1:+SdeFBvtyEkXs7REEP0seUULqWtbJapLOCV github.com/json-iterator/go v1.1.10/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4= github.com/json-iterator/go v1.1.11/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4= github.com/jstemmer/go-junit-report v0.0.0-20190106144839-af01ea7f8024/go.mod h1:6v2b51hI/fHJwM22ozAgKL4VKDeJcHhJFhtBdhmNjmU= +github.com/jstemmer/go-junit-report v0.9.1/go.mod h1:Brl9GWCQeLvo8nXZwPNNblvFj/XSXhF0NWZEnDohbsk= github.com/jtolds/gls v4.20.0+incompatible/go.mod h1:QJZ7F/aHp+rZTRtaJ1ow/lLfFfVYBRgL+9YlvaHOwJU= github.com/julienschmidt/httprouter v1.2.0/go.mod h1:SYymIcj16QtmaHHD7aYtjjsJG7VTCxuUUipMqKk8s4w= github.com/julienschmidt/httprouter v1.3.0/go.mod h1:JR6WtHb+2LUe8TCKY3cZOxFyyO8IZAc4RVcycCCAKdM= -github.com/kisielk/errcheck v1.1.0/go.mod h1:EZBBE59ingxPouuu3KfxchcWSUPOHkagtvWXihfKN4Q= github.com/kisielk/errcheck v1.2.0/go.mod h1:/BMXB+zMLi60iA8Vv6Ksmxu/1UDYcXs4uQLJ+jE2L00= github.com/kisielk/errcheck v1.5.0/go.mod h1:pFxgyoBC7bSaBwPgfKdkLd5X25qrDl4LWUI2bnpBCr8= github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck= github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= github.com/konsorten/go-windows-terminal-sequences v1.0.3/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= +github.com/kr/fs v0.1.0/go.mod h1:FFnZGqtBN9Gxj7eW1uZ42v5BccTP0vu6NEaFoC2HwRg= github.com/kr/logfmt v0.0.0-20140226030751-b84e30acd515/go.mod h1:+0opPa2QZZtGFBFZlji/RkVcI2GknAs/DXo4wKdlNEc= github.com/kr/pretty v0.1.0 h1:L/CwN0zerZDmRFUapSPitk6f+Q3+0za1rQkzVuMiMFI= github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo= @@ -203,7 +253,7 @@ github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY= github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE= -github.com/magiconair/properties v1.8.1/go.mod h1:PppfXfuXeibc/6YijjN8zIbojt8czPbwD3XqdrwzmxQ= +github.com/magiconair/properties v1.8.5/go.mod h1:y3VJvCyxH9uVvJTWEGAELF3aiYNyPKd5NZ3oSwXrF60= github.com/mattn/go-colorable v0.0.9 h1:UVL0vNpWh04HeJXV0KLcaT7r06gOH2l4OW6ddYRUIY4= github.com/mattn/go-colorable v0.0.9/go.mod h1:9vuHe8Xs5qXnSaW/c/ABM9alt+Vo+STaOChaDxuIBZU= github.com/mattn/go-isatty v0.0.3 h1:ns/ykhmWi7G9O+8a448SecJU3nSMBXJfqQkl0upE1jI= @@ -215,33 +265,32 @@ github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5 github.com/miekg/dns v1.0.14/go.mod h1:W1PPwlIAgtquWBMBEV9nkV9Cazfe8ScdGz/Lj7v3Nrg= github.com/mitchellh/cli v1.0.0/go.mod h1:hNIlj7HEI86fIcpObd7a0FcrxTWetlwJDGcceTlRvqc= github.com/mitchellh/go-homedir v1.0.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0= -github.com/mitchellh/go-homedir v1.1.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0= github.com/mitchellh/go-testing-interface v1.0.0/go.mod h1:kRemZodwjscx+RGhAo8eIhFbs2+BFgRtFPeD/KE+zxI= github.com/mitchellh/gox v0.4.0/go.mod h1:Sd9lOJ0+aimLBi73mGofS1ycjY8lL3uZM3JPS42BGNg= github.com/mitchellh/iochan v1.0.0/go.mod h1:JwYml1nuB7xOzsp52dPpHFffvOCDupsG0QubkSMEySY= github.com/mitchellh/mapstructure v0.0.0-20160808181253-ca63d7c062ee/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y= github.com/mitchellh/mapstructure v1.1.2/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y= +github.com/mitchellh/mapstructure v1.4.1/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo= github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= github.com/modern-go/reflect2 v0.0.0-20180701023420-4b7aa43c6742/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0= github.com/modern-go/reflect2 v1.0.1/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0= github.com/mwitkow/go-conntrack v0.0.0-20161129095857-cc309e4a2223/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U= github.com/mwitkow/go-conntrack v0.0.0-20190716064945-2f068394615f/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U= -github.com/oklog/ulid v1.3.1/go.mod h1:CirwcVhetQ6Lv90oh/F+FBtV6XMibvdAFo93nm5qn4U= github.com/olekukonko/tablewriter v0.0.5 h1:P2Ga83D34wi1o9J6Wh1mRuqd4mF/x/lgBS7N7AbDhec= github.com/olekukonko/tablewriter v0.0.5/go.mod h1:hPp6KlRPjbx+hW8ykQs1w3UBbZlj6HuIJcUGPhkA7kY= github.com/opentracing/opentracing-go v1.1.0/go.mod h1:UkNAQd3GIcIGf0SeVgPpRdFStlNbqXla1AfSYxPUl2o= github.com/pascaldekloe/goe v0.0.0-20180627143212-57f6aae5913c/go.mod h1:lzWF7FIEvWOWxwDKqyGYQf6ZUaNfKdP144TG7ZOy1lc= -github.com/pelletier/go-toml v1.2.0/go.mod h1:5z9KED0ma1S8pY6P1sdut58dfprrGBbd/94hg7ilaic= +github.com/pelletier/go-toml v1.9.3/go.mod h1:u1nR/EPcESfeI/szUZKdtJ0xRNbUoANCkoOuaOx1Y+c= github.com/pkg/errors v0.8.0/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4= github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= +github.com/pkg/sftp v1.10.1/go.mod h1:lYOWFsE0bwd1+KfKJaKeuokY15vzFx25BLbzYYoAxZI= github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= github.com/posener/complete v1.1.1/go.mod h1:em0nMJCgc9GFtwrmVmEMR/ZL6WyhyjMBndrE9hABlRI= github.com/prometheus/client_golang v0.9.1/go.mod h1:7SWBe2y4D6OKWSNQJUaRYU/AaXPKyh/dDVn+NZz0KFw= -github.com/prometheus/client_golang v0.9.3/go.mod h1:/TN21ttK/J9q6uSwhBd54HahCDft0ttaMvbicHlPoso= github.com/prometheus/client_golang v1.0.0/go.mod h1:db9x61etRT2tGnBNRi70OPL5FsnadC4Ky3P0J6CfImo= github.com/prometheus/client_golang v1.7.1/go.mod h1:PY5Wy2awLA44sXw4AOSfFBetzPP4j5+D6mVACh+pe2M= github.com/prometheus/client_golang v1.11.0 h1:HNkLOAEQMIDv/K+04rukrLx6ch7msSRwf3/SASFAGtQ= @@ -251,20 +300,15 @@ github.com/prometheus/client_model v0.0.0-20190129233127-fd36f4220a90/go.mod h1: github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= github.com/prometheus/client_model v0.2.0 h1:uq5h0d+GuxiXLJLNABMgp2qUWDPiLvgCzz2dUR+/W/M= github.com/prometheus/client_model v0.2.0/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= -github.com/prometheus/common v0.0.0-20181113130724-41aa239b4cce/go.mod h1:daVV7qP5qjZbuso7PdcryaAu0sAZbrN9i7WWcTMWvro= -github.com/prometheus/common v0.4.0/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y86RQel1bk4= github.com/prometheus/common v0.4.1/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y86RQel1bk4= github.com/prometheus/common v0.10.0/go.mod h1:Tlit/dnDKsSWFlCLTWaA1cyBgKHSMdTB80sz/V91rCo= github.com/prometheus/common v0.26.0 h1:iMAkS2TDoNWnKM+Kopnx/8tnEStIfpYA0ur0xQzzhMQ= github.com/prometheus/common v0.26.0/go.mod h1:M7rCNAaPfAosfx8veZJCuw84e35h3Cfd9VFqTh1DIvc= github.com/prometheus/procfs v0.0.0-20181005140218-185b4288413d/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk= -github.com/prometheus/procfs v0.0.0-20190507164030-5867b95ac084/go.mod h1:TjEm7ze935MbeOT/UhFTIMYKhuLP4wbCsTZCD3I8kEA= github.com/prometheus/procfs v0.0.2/go.mod h1:TjEm7ze935MbeOT/UhFTIMYKhuLP4wbCsTZCD3I8kEA= github.com/prometheus/procfs v0.1.3/go.mod h1:lV6e/gmhEcM9IjHGsFOCxxuZ+z1YqCvr4OA4YeYWdaU= github.com/prometheus/procfs v0.6.0 h1:mxy4L2jP6qMonqmq+aTtOx1ifVWUgG/TAmntgbh3xv4= github.com/prometheus/procfs v0.6.0/go.mod h1:cz+aTbrPOrUb4q7XlbU9ygM+/jj0fzG6c1xBZuNvfVA= -github.com/prometheus/tsdb v0.7.1/go.mod h1:qhTCs0VvXwvX/y3TZrWD7rabWM+ijKTux40TwIPHuXU= -github.com/rogpeppe/fastuuid v0.0.0-20150106093220-6724a57986af/go.mod h1:XWv6SoW27p1b0cqNHllgS5HIMJraePCO15w5zCzIWYg= github.com/rogpeppe/fastuuid v1.2.0/go.mod h1:jVj6XXZzXRy/MSR5jhDC/2q6DgLz+nrA6LYCDYWNEvQ= github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4= github.com/russross/blackfriday/v2 v2.0.1/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= @@ -278,41 +322,45 @@ github.com/sirupsen/logrus v1.8.1 h1:dJKuHgqk1NNQlqoA6BTlM1Wf9DOH3NBjQyu0h9+AZZE github.com/sirupsen/logrus v1.8.1/go.mod h1:yWOB1SBYBC5VeMP7gHvWumXLIWorT60ONWic61uBYv0= github.com/smartystreets/assertions v0.0.0-20180927180507-b2de0cb4f26d/go.mod h1:OnSkiWE9lh6wB0YB77sQom3nweQdgAjqCqsofrRNTgc= github.com/smartystreets/goconvey v1.6.4/go.mod h1:syvi0/a8iFYH4r/RixwvyeAJjdLS9QV7WQ/tjFTllLA= -github.com/soheilhy/cmux v0.1.4/go.mod h1:IM3LyeVVIOuxMH7sFAkER9+bJ4dT7Ms6E4xg4kGIyLM= github.com/soheilhy/cmux v0.1.5 h1:jjzc5WVemNEDTLwv9tlmemhC73tI08BNOIGwBOo10Js= github.com/soheilhy/cmux v0.1.5/go.mod h1:T7TcVDs9LWfQgPlPsdngu6I6QIoyIFZDDC6sNE1GqG0= github.com/spaolacci/murmur3 v0.0.0-20180118202830-f09979ecbc72/go.mod h1:JwIasOWyU6f++ZhiEuf87xNszmSA2myDM2Kzu9HwQUA= -github.com/spf13/afero v1.1.2/go.mod h1:j4pytiNVoe2o6bmDsKpLACNPDBIoEAkihy7loJ1B0CQ= -github.com/spf13/cast v1.3.0/go.mod h1:Qx5cxh0v+4UWYiBimWS+eyWzqEqokIECu5etghLkUJE= -github.com/spf13/cobra v1.1.3 h1:xghbfqPkxzxP3C/f3n5DdpAbdKLj4ZE4BWQI362l53M= -github.com/spf13/cobra v1.1.3/go.mod h1:pGADOWyqRD/YMrPZigI/zbliZ2wVD/23d+is3pSWzOo= -github.com/spf13/jwalterweatherman v1.0.0/go.mod h1:cQK4TGJAtQXfYWX+Ddv3mKDzgVb68N+wFjFa4jdeBTo= -github.com/spf13/pflag v1.0.3/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4= +github.com/spf13/afero v1.6.0/go.mod h1:Ai8FlHk4v/PARR026UzYexafAt9roJ7LcLMAmO6Z93I= +github.com/spf13/cast v1.3.1/go.mod h1:Qx5cxh0v+4UWYiBimWS+eyWzqEqokIECu5etghLkUJE= +github.com/spf13/cobra v1.2.1 h1:+KmjbUw1hriSNMF55oPrkZcb27aECyrj8V2ytv7kWDw= +github.com/spf13/cobra v1.2.1/go.mod h1:ExllRjgxM/piMAM+3tAZvg8fsklGAf3tPfi+i8t68Nk= +github.com/spf13/jwalterweatherman v1.1.0/go.mod h1:aNWZUN0dPAAO/Ljvb5BEdw96iTZ0EXowPYD95IqWIGo= github.com/spf13/pflag v1.0.5 h1:iy+VFUOCP1a+8yFto/drg2CJ5u0yRoB7fZw3DKv/JXA= github.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg= -github.com/spf13/viper v1.7.0/go.mod h1:8WkrPz2fc9jxqZNCJI/76HCieCp4Q8HaLFoCha5qpdg= +github.com/spf13/viper v1.8.1/go.mod h1:o0Pch8wJ9BVSWGQMbra6iw0oQ5oktSIBaujf1rJH9Ns= github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= 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.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA= +github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/stretchr/testify v1.7.0 h1:nwc3DEeHmmLAfoZucVR881uASk0Mfjw8xYJ99tb5CcY= github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/subosito/gotenv v1.2.0/go.mod h1:N0PQaV/YGNqwC0u51sEeR/aUtSLEXKX9iv69rRypqCw= -github.com/tmc/grpc-websocket-proxy v0.0.0-20190109142713-0ad062ec5ee5/go.mod h1:ncp9v5uamzpCO7NfCPTXjqaC+bZgJeR0sMTm6dMHP7U= github.com/tmc/grpc-websocket-proxy v0.0.0-20201229170055-e5319fda7802 h1:uruHq4dN7GR16kFc5fp3d1RIYzJW5onx8Ybykw2YQFA= github.com/tmc/grpc-websocket-proxy v0.0.0-20201229170055-e5319fda7802/go.mod h1:ncp9v5uamzpCO7NfCPTXjqaC+bZgJeR0sMTm6dMHP7U= github.com/urfave/cli v1.22.4/go.mod h1:Gos4lmkARVdJ6EkW0WaNv/tZAAMe9V7XWyB60NtXRu0= github.com/xiang90/probing v0.0.0-20190116061207-43a291ad63a2 h1:eY9dn8+vbi4tKz5Qo6v2eYzo7kUS51QINcR5jNpbZS8= github.com/xiang90/probing v0.0.0-20190116061207-43a291ad63a2/go.mod h1:UETIi67q53MR2AWcXfiuqkDkRtnGDLqkBTpCHuJHxtU= +github.com/yuin/goldmark v1.1.25/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= +github.com/yuin/goldmark v1.1.32/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= -go.etcd.io/bbolt v1.3.2/go.mod h1:IbVyRI1SCnLcuJnV2u8VeU0CEYM7e686BmAb1XKL+uU= go.etcd.io/bbolt v1.3.6 h1:/ecaJf0sk1l4l6V4awd65v2C3ILy7MSj+s/x1ADCIMU= go.etcd.io/bbolt v1.3.6/go.mod h1:qXsaaIqmgQH0T+OPdb99Bf+PKfBBQVAdyD6TY9G8XM4= 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.2/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.5/go.mod h1:5pWMHQbX5EPX2/62yrJeAkowc+lfs/XD7Uxpq3pI6kk= +go.opencensus.io v0.23.0/go.mod h1:XItmlyltB5F7CS4xOC1DcqMoFqwtC6OG2xF7mCv7P7E= go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.26.1 h1:puWrOArBwWlr5dq6vyZ6fKykHyS8JgMIVhTBA8XsGuU= go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.26.1/go.mod h1:4wsfAAW5N9wUHM0QTmZS8z7fvYZ1rv3m+sVeSpf8NhU= go.opentelemetry.io/otel v1.1.0/go.mod h1:7cww0OW51jQ8IaZChIEdqLwgh+44+7uiTdWsAL0wQpA= @@ -347,6 +395,7 @@ golang.org/x/crypto v0.0.0-20181029021203-45a5f77698d3/go.mod h1:6SG95UA2DQfeDnf golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= golang.org/x/crypto v0.0.0-20190510104115-cbcb75029529/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20190605123033-f99c8df09eb5/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= +golang.org/x/crypto v0.0.0-20190820162420-60c769a6c586/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= golang.org/x/crypto v0.0.0-20210513164829-c07d793c2f9a h1:kr2P4QFmQr29mSLA43kwrOcgcReGTfbE9N577tCTuBc= @@ -356,6 +405,11 @@ golang.org/x/exp v0.0.0-20190306152737-a1d7652674e8/go.mod h1:CJ0aWSM057203Lf6IL golang.org/x/exp v0.0.0-20190510132918-efd6b22b2522/go.mod h1:ZjyILWgesfNpC6sMxTJOJm9Kp84zZh5NQWvqDGG3Qr8= golang.org/x/exp v0.0.0-20190829153037-c13cbed26979/go.mod h1:86+5VVa7VpoJ4kLfm080zCjGlMRFzhUhsZKEZO7MGek= golang.org/x/exp v0.0.0-20191030013958-a1ab85dbe136/go.mod h1:JXzH8nQsPlswgeRAPE3MuO9GYsAcnJvJ4vnMwN/5qkY= +golang.org/x/exp v0.0.0-20191129062945-2f5052295587/go.mod h1:2RIsYlXP63K8oxa1u096TMicItID8zy7Y6sNkU49FU4= +golang.org/x/exp v0.0.0-20191227195350-da58074b4299/go.mod h1:2RIsYlXP63K8oxa1u096TMicItID8zy7Y6sNkU49FU4= +golang.org/x/exp v0.0.0-20200119233911-0405dc783f0a/go.mod h1:2RIsYlXP63K8oxa1u096TMicItID8zy7Y6sNkU49FU4= +golang.org/x/exp v0.0.0-20200207192155-f17229e696bd/go.mod h1:J/WKrq2StrnmMY6+EHIKF9dgMWnmCNThgcyBT1FY9mM= +golang.org/x/exp v0.0.0-20200224162631-6cc2880d07d6/go.mod h1:3jZMyOhIsHpP37uCMkUooju7aAi5cS1Q23tOzKc+0MU= golang.org/x/image v0.0.0-20190227222117-0694c2d4d067/go.mod h1:kZ7UVZpmo3dzQBMxlp+ypCbDeSB+sBbTgSJuh5dn5js= golang.org/x/image v0.0.0-20190802002840-cff245a6509b/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0= golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE= @@ -365,18 +419,25 @@ golang.org/x/lint v0.0.0-20190313153728-d0100b6bd8b3/go.mod h1:6SW0HCj/g11FgYtHl golang.org/x/lint v0.0.0-20190409202823-959b441ac422/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= golang.org/x/lint v0.0.0-20190909230951-414d861bb4ac/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= golang.org/x/lint v0.0.0-20190930215403-16217165b5de/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= +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-20200302205851-738671d3881b/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY= +golang.org/x/lint v0.0.0-20201208152925-83fdc39ff7b5/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-20190719004257-d2bd2a29d028/go.mod h1:E/iHnbuqvinMTCcRqshq8CkpyQDoeVncDDYHnLhea+o= golang.org/x/mod v0.0.0-20190513183733-4bf6d317e70e/go.mod h1:mXi4GBBbnImb6dmsKGUJ2LatrhH/nqhxcFungHvyanc= golang.org/x/mod v0.1.0/go.mod h1:0QHyrYULN0/3qlju5TqG8bIK38QM8yzMo5ekMj3DlcY= +golang.org/x/mod v0.1.1-0.20191105210325-c90efee705ee/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.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/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-20181023162649-9b4f9f5ad519/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20181114220301-adae6a3d119a/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20181201002055-351d144fa1fc/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= -golang.org/x/net v0.0.0-20181220203305-927f97764cc3/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20190108225652-1e06a53dbb7e/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20190213061140-3a22650c66bd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= @@ -386,26 +447,54 @@ golang.org/x/net v0.0.0-20190503192946-f4e77d36d62c/go.mod h1:t9HGtf8HONx5eT2rtn golang.org/x/net v0.0.0-20190603091049-60506f45cf65/go.mod h1:HSz+uSET+XFnRR8LxR5pz3Of3rY3CfYBVs4xY44aLks= golang.org/x/net v0.0.0-20190613194153-d28f0bde5980/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20190628185345-da137c7871d7/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20190724013045-ca1201d0de80/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20191209160850-c0dbc17a3553/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20200114155413-6afb5195e5aa/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20200202094626-16171245cfb2/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20200222125558-5a598a2470a0/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20200226121028-0de0cce0169b/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20200301022130-244492dfa37a/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20200324143707-d3edc9973b7e/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= +golang.org/x/net v0.0.0-20200501053045-e0ff5e5a1de5/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= +golang.org/x/net v0.0.0-20200506145744-7e3656a0809f/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= +golang.org/x/net v0.0.0-20200513185701-a91f0712d120/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= +golang.org/x/net v0.0.0-20200520182314-0ba52f642ac2/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= golang.org/x/net v0.0.0-20200625001655-4c5254603344/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-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-20201202161906-c7110b5ffcbb/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-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-20211123203042-d83791d6bcd9 h1:0qxwC5n+ttVOINCBeRHO0nq9X7uy8SDsPoi5OaCdIEI= golang.org/x/net v0.0.0-20211123203042-d83791d6bcd9/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= 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-20190604053449-0f29369cfe45/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= -golang.org/x/oauth2 v0.0.0-20200107190931-bf48bf16ab8d h1:TzXSXBo42m9gQenoE3b9BGiEpg5IG2JkU5FkPIawgtw= +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-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-20210402161424-2e8d93401602 h1:0Ja1LBD+yisY6RWM/BH7TJVXWsSjs2VwBSmvSX4HdBc= +golang.org/x/oauth2 v0.0.0-20210402161424-2e8d93401602/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= 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-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20190227155943-e225da77a7e6/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20200317015054-43a5402ce75a/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20200625203802-6e8e738ad208/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-20210220032951-036812b2e83c h1:5KslGYwFpkhGh+Q16bwMP3cOontH8FOep7tGV86Y7SQ= @@ -414,7 +503,6 @@ golang.org/x/sys v0.0.0-20180823144017-11551d06cbcc/go.mod h1:STP8DvDyc/dI5b8T5h 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-20181026203630-95b1ffbd15a5/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= -golang.org/x/sys v0.0.0-20181107165924-66b7b1311ac8/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20181116152217-5ac8a444bdc5/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190312061237-fead79001313/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= @@ -424,16 +512,42 @@ golang.org/x/sys v0.0.0-20190502145724-3ef323f4f1fd/go.mod h1:h1NjWce9XRLGQEsW7w golang.org/x/sys v0.0.0-20190507160741-ecd444e8653b/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190606165138-5da285871e9c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190624142023-c5567b49c5d0/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190726091711-fc99dfbffb4e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20191001151750-bb3f8db39f24/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20191005200804-aed5e4c7ecf9/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20191026070338-33540a1f6037/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20191204072324-ce4227a45e2e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20191228213918-04cbcbbfeed8/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200106162015-b016eb3dc98e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200113162924-86b910548bc1/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200122134326-e047566fdf82/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200202164722-d101bd2416d5/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200212091648-12a6c2dcc1e4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200223170610-d5e6a3e2c0ae/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200302150141-5c8b2ff67527/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200331124033-c3d80250170d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200501052902-10377860bb8e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200511232937-7e40ca221e25/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200515095857-1151b9dac4a9/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200523222454-059865788121/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-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-20200923182605-d9f96fdee20d/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-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-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-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-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-20210423185535-09eb48e85fd7/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210510120138-977fb7262007/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= @@ -442,19 +556,21 @@ golang.org/x/sys v0.0.0-20210603125802-9665404d3644/go.mod h1:oPkhp1MJrh7nUepCBc golang.org/x/sys v0.0.0-20211123173158-ef496fb156ab h1:rfJ1bsoJQQIAoAxTxB7bme+vHrNkRw8CqfsYh9w54cw= golang.org/x/sys v0.0.0-20211123173158-ef496fb156ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= +golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.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.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.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/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-20191024005414-555d28b269f0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.0.0-20210220033141-f8bda1e9f3ba h1:O8mE0/t419eoIwhTFpKVkHiTs/Igowgfkj25AcZrtiE= golang.org/x/time v0.0.0-20210220033141-f8bda1e9f3ba/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= -golang.org/x/tools v0.0.0-20180221164845-07fd8470d635/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-20181030221726-6c7e314b6563/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20190114222345-bf090417da8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= @@ -473,9 +589,39 @@ golang.org/x/tools v0.0.0-20190816200558-6889da9d5479/go.mod h1:b+2E5dAYhXwXZwtn golang.org/x/tools v0.0.0-20190911174233-4f2ddba30aff/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.0.0-20191012152004-8de300cfc20a/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.0.0-20191112195655-aa38f8e97acc/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-20191113191852-77e3bb0ad9e7/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-20191115202509-3a792d9c32b2/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-20191125144606-a911d9008d1f/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-20191130070609-6e064ea0cf2d/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-20191216173652-a0e659d51361/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= +golang.org/x/tools v0.0.0-20191227053925-7b8e75db28f4/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= +golang.org/x/tools v0.0.0-20200117161641-43d50277825c/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= +golang.org/x/tools v0.0.0-20200122220014-bf1340f18c4a/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= +golang.org/x/tools v0.0.0-20200130002326-2f3ba24bd6e7/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= +golang.org/x/tools v0.0.0-20200204074204-1cc6d1ef6c74/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= +golang.org/x/tools v0.0.0-20200207183749-b753a1ba74fa/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= +golang.org/x/tools v0.0.0-20200212150539-ea181f53ac56/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= +golang.org/x/tools v0.0.0-20200224181240-023911ca70b2/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= +golang.org/x/tools v0.0.0-20200227222343-706bc42d1f0d/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= +golang.org/x/tools v0.0.0-20200304193943-95d2e580d8eb/go.mod h1:o4KQGtdN14AW+yjsvvwRTJJuXz8XRtIHtEnmAXLyFUw= +golang.org/x/tools v0.0.0-20200312045724-11d5b4c81c7d/go.mod h1:o4KQGtdN14AW+yjsvvwRTJJuXz8XRtIHtEnmAXLyFUw= +golang.org/x/tools v0.0.0-20200331025713-a30bf2db82d4/go.mod h1:Sl4aGygMT6LrqrWclx+PTx3U+LnKx/seiNR+3G19Ar8= +golang.org/x/tools v0.0.0-20200501065659-ab2804fb9c9d/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= +golang.org/x/tools v0.0.0-20200512131952-2bc93b1c0c88/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= +golang.org/x/tools v0.0.0-20200515010526-7d3b6ebf133d/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= +golang.org/x/tools v0.0.0-20200618134242-20370b0cb4b2/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= golang.org/x/tools v0.0.0-20200619180055-7c47624df98f/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= +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-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-20210105154028-b0ab187a4818/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/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-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= @@ -486,11 +632,31 @@ google.golang.org/api v0.7.0/go.mod h1:WtwebWUNSVBH/HAw79HIFXZNqEvBhG+Ra+ax0hx3E google.golang.org/api v0.8.0/go.mod h1:o4eAsZoiT+ibD93RtjEohWalFOjRDx6CVaqeizhEnKg= google.golang.org/api v0.9.0/go.mod h1:o4eAsZoiT+ibD93RtjEohWalFOjRDx6CVaqeizhEnKg= google.golang.org/api v0.13.0/go.mod h1:iLdEw5Ide6rF15KTC1Kkl0iskquN2gFfn9o9XIsbkAI= +google.golang.org/api v0.14.0/go.mod h1:iLdEw5Ide6rF15KTC1Kkl0iskquN2gFfn9o9XIsbkAI= +google.golang.org/api v0.15.0/go.mod h1:iLdEw5Ide6rF15KTC1Kkl0iskquN2gFfn9o9XIsbkAI= +google.golang.org/api v0.17.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE= +google.golang.org/api v0.18.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE= +google.golang.org/api v0.19.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE= +google.golang.org/api v0.20.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE= +google.golang.org/api v0.22.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE= +google.golang.org/api v0.24.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.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.44.0/go.mod h1:EBOGZqzyhtvMDoxwS97ctnh0zUmYY6CxqXsc1AvkYD8= 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.5.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= -google.golang.org/appengine v1.6.1 h1:QzqyMA1tlu6CgqCDUtU9V+ZKhLFT2dkJuANu5QaxI3I= google.golang.org/appengine v1.6.1/go.mod h1:i06prIuMbXzDqacNJfV5OdTW448YApPu5ww/cMBSeb0= +google.golang.org/appengine v1.6.5/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-20190307195333-5fe7a883aa19/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= google.golang.org/genproto v0.0.0-20190418145605-e7d98fc518a7/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= @@ -500,9 +666,38 @@ google.golang.org/genproto v0.0.0-20190801165951-fa694d86fc64/go.mod h1:DMBHOl98 google.golang.org/genproto v0.0.0-20190819201941-24fa4b261c55/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc= google.golang.org/genproto v0.0.0-20190911173649-1774047e7e51/go.mod h1:IbNlFCBrqXvoKpeg0TB2l7cyZUmoaFKYIwrEpbDKLA8= google.golang.org/genproto v0.0.0-20191108220845-16a3f7862a1a/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= +google.golang.org/genproto v0.0.0-20191115194625-c23dd37a84c9/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= +google.golang.org/genproto v0.0.0-20191216164720-4f79533eabd1/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= +google.golang.org/genproto v0.0.0-20191230161307-f3c370f40bfb/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= +google.golang.org/genproto v0.0.0-20200115191322-ca5a22157cba/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= +google.golang.org/genproto v0.0.0-20200122232147-0452cf42e150/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= +google.golang.org/genproto v0.0.0-20200204135345-fa8e72b47b90/go.mod h1:GmwEX6Z4W5gMy59cAlVYjN9JhxgbQH6Gn+gFDQe2lzA= +google.golang.org/genproto v0.0.0-20200212174721-66ed5ce911ce/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= +google.golang.org/genproto v0.0.0-20200224152610-e50cd9704f63/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= +google.golang.org/genproto v0.0.0-20200228133532-8c2c7df3a383/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= +google.golang.org/genproto v0.0.0-20200305110556-506484158171/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= +google.golang.org/genproto v0.0.0-20200312145019-da6875a35672/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= +google.golang.org/genproto v0.0.0-20200331122359-1ee6d9798940/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= google.golang.org/genproto v0.0.0-20200423170343-7949de9c1215/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= +google.golang.org/genproto v0.0.0-20200430143042-b979b6f78d84/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= +google.golang.org/genproto v0.0.0-20200511104702-f5ebc3bea380/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= google.golang.org/genproto v0.0.0-20200513103714-09dca8ec2884/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= +google.golang.org/genproto v0.0.0-20200515170657-fc4c6c6a6587/go.mod h1:YsZOwe1myG/8QRHRsmBRE1LrgQY60beZKjly0O1fX9U= google.golang.org/genproto v0.0.0-20200526211855-cb27e3aa2013/go.mod h1:NbSheEEYHJ7i3ixzK3sjbqSGDJWnxyFXZblF3eUsNvo= +google.golang.org/genproto v0.0.0-20200618031413-b414f8b61790/go.mod h1:jDfRM7FcilCzHH/e9qn6dsT145K34l5v+OpcnNgKAAA= +google.golang.org/genproto v0.0.0-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-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-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-20210402141018-6c239bbf2bb1/go.mod h1:9lPAdzaEmUacj36I+k7YKbEc5CXzPIeORRgDAUOu28A= google.golang.org/genproto v0.0.0-20211118181313-81c1377c94b1 h1:b9mVrqYfq3P4bCdaLg1qtBnPzUYgglsIdjZkL/fQVOE= google.golang.org/genproto v0.0.0-20211118181313-81c1377c94b1/go.mod h1:5CzLGKJ67TSI2B9POpiiyGha0AjJvZIUgRMt1dSmuhc= google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c= @@ -510,11 +705,22 @@ google.golang.org/grpc v1.20.1/go.mod h1:10oTOabMzJvdu6/UiuZezV6QK5dSlG84ov/aaiq google.golang.org/grpc v1.21.1/go.mod h1:oYelfM1adQP15Ek0mdvEgi9Df8B9CZIaU1084ijfRaM= google.golang.org/grpc v1.23.0/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg= google.golang.org/grpc v1.25.1/go.mod h1:c3i+UQWmh7LiEpx4sFZnkU36qjEYZ0imhYfXVyQciAY= +google.golang.org/grpc v1.26.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk= google.golang.org/grpc v1.27.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk= +google.golang.org/grpc v1.27.1/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk= +google.golang.org/grpc v1.28.0/go.mod h1:rpkK4SK4GF4Ach/+MFLZUBavHOvF2JJB5uozKKal+60= 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.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.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.1/go.mod h1:qjiiYl8FncCW8feJPdyg3v6XW24KsRHe+dy9BAGRRjU= 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.40.0/go.mod h1:ogyxbiOoUXAkP+4+xa6PZSE9DZgIHtSpzjDTB9KAK34= google.golang.org/grpc v1.41.0 h1:f+PlOh7QV4iIJkPrx5NQ7qaNGFQ3OTse67yaDHfju4E= google.golang.org/grpc v1.41.0/go.mod h1:U3l9uK9J0sini8mHphKoXyaqDA/8VyGnDee1zzIUK6k= @@ -526,6 +732,7 @@ google.golang.org/protobuf v1.21.0/go.mod h1:47Nbq4nVaFHyn7ilMalzfO3qCViNmqZ2kzi google.golang.org/protobuf v1.22.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= google.golang.org/protobuf v1.23.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= google.golang.org/protobuf v1.23.1-0.20200526195155-81db48ad09cc/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= +google.golang.org/protobuf v1.24.0/go.mod h1:r/3tXBNzIEhYS9I1OUVjXDlt8tc493IdKGjtUeSXeh4= google.golang.org/protobuf v1.25.0/go.mod h1:9JNX74DMeImyA3h4bdi1ymwjUzf21/xIlbajtzgsN7c= google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw= google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc= @@ -539,11 +746,9 @@ gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8 gopkg.in/cheggaaa/pb.v1 v1.0.28 h1:n1tBJnnK2r7g9OW2btFH91V92STTUevLXYFb8gy9EMk= gopkg.in/cheggaaa/pb.v1 v1.0.28/go.mod h1:V/YB90LKu/1FcN3WVnfiiE5oMCibMjukxqG/qStrOgw= gopkg.in/errgo.v2 v2.1.0/go.mod h1:hNsd1EY+bozCKY1Ytp96fpM3vjJbqLJn88ws8XvfDNI= -gopkg.in/ini.v1 v1.51.0/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k= +gopkg.in/ini.v1 v1.62.0/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k= gopkg.in/natefinch/lumberjack.v2 v2.0.0 h1:1Lc07Kr7qY4U2YPouBjpCLxpiyxIVoxqXgkXLknAOE8= gopkg.in/natefinch/lumberjack.v2 v2.0.0/go.mod h1:l0ndWWf7gzL7RNwBG7wST/UCcT4T24xpD6X8LsfU/+k= -gopkg.in/resty.v1 v1.12.0/go.mod h1:mDo4pnntr5jdWRML875a/NmxYqAlA73dVijT2AXvQQo= -gopkg.in/yaml.v2 v2.0.0-20170812160011-eb3733d160e7/go.mod h1:JAlM8MvJe8wmxCU4Bli9HhUf9+ttbYbLASfIpnQbh74= gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.2.3/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= @@ -561,7 +766,11 @@ honnef.co/go/tools v0.0.0-20190106161140-3f1c8253044a/go.mod h1:rf3lG4BRIbNafJWh honnef.co/go/tools v0.0.0-20190418001031-e561f6794a2a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= honnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= honnef.co/go/tools v0.0.1-2019.2.3/go.mod h1:a3bituU0lyd329TUQxRnasdCoJDkEUEAqEt0JzvZhAg= +honnef.co/go/tools v0.0.1-2020.1.3/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9vFzvIQ3k= +honnef.co/go/tools v0.0.1-2020.1.4/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9vFzvIQ3k= 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/sampler v1.3.0/go.mod h1:T1hPZKmBbMNahiBKFy5HrXp6adAjACjK9JXDnKaTXpA= sigs.k8s.io/json v0.0.0-20211020170558-c049b76a60c6 h1:fD1pz4yfdADVNfFmcP2aBEtudwUQ1AlLnRBALr33v3s= sigs.k8s.io/json v0.0.0-20211020170558-c049b76a60c6/go.mod h1:p4QtZmO4uMYipTQNzagwnNoseA6OxSUutVw05NhYDRs= sigs.k8s.io/yaml v1.2.0 h1:kr/MCeFWJWTwyaHoR9c8EjH9OumOmoF9YGiZd7lFm/Q= diff --git a/pkg/go.mod b/pkg/go.mod index 35c24342a97d..37d0306b0782 100644 --- a/pkg/go.mod +++ b/pkg/go.mod @@ -6,7 +6,7 @@ require ( github.com/creack/pty v1.1.11 github.com/dustin/go-humanize v1.0.0 github.com/golang/protobuf v1.5.2 // indirect - github.com/spf13/cobra v1.1.3 + github.com/spf13/cobra v1.2.1 github.com/spf13/pflag v1.0.5 github.com/stretchr/testify v1.7.0 go.etcd.io/etcd/client/pkg/v3 v3.5.0 @@ -29,9 +29,14 @@ require ( ) replace ( - go.etcd.io/etcd => ./FORBIDDEN_DEPENDENCY - go.etcd.io/etcd/api/v3 => ./FORBIDDEN_DEPENDENCY + go.etcd.io/etcd/api/v3 => ../api go.etcd.io/etcd/client/pkg/v3 => ../client/pkg - go.etcd.io/etcd/tests/v3 => ./FORBIDDEN_DEPENDENCY +) + +// Bad imports are sometimes causing attempts to pull that code. +// This makes the error more explicit. +replace ( + go.etcd.io/etcd => ./FORBIDDEN_DEPENDENCY go.etcd.io/etcd/v3 => ./FORBIDDEN_DEPENDENCY + go.etcd.io/tests/v3 => ./FORBIDDEN_DEPENDENCY ) diff --git a/pkg/go.sum b/pkg/go.sum index a8edcc41fe67..7657ad489756 100644 --- a/pkg/go.sum +++ b/pkg/go.sum @@ -5,76 +5,104 @@ cloud.google.com/go v0.44.1/go.mod h1:iSa0KzasP4Uvy3f1mN/7PiObzGgflwredwwASm/v6A cloud.google.com/go v0.44.2/go.mod h1:60680Gw3Yr4ikxnPRS/oxxkBccT6SA1yMk63TGekxKY= cloud.google.com/go v0.45.1/go.mod h1:RpBamKRgapWJb87xiFSdk4g1CME7QZg3uwTez+TSTjc= cloud.google.com/go v0.46.3/go.mod h1:a6bKKbmY7er1mI7TEI4lsAkts/mkhTSZK8w33B4RAg0= +cloud.google.com/go v0.50.0/go.mod h1:r9sluTvynVuxRIOHXQEHMFffphuXHOMZMycpNR5e6To= +cloud.google.com/go v0.52.0/go.mod h1:pXajvRH/6o3+F9jDHZWQ5PbGhn+o8w9qiu/CffaVdO4= +cloud.google.com/go v0.53.0/go.mod h1:fp/UouUEsRkN6ryDKNW/Upv/JBKnv6WDthjR6+vze6M= +cloud.google.com/go v0.54.0/go.mod h1:1rq2OEkV3YMf6n/9ZvGWI3GWw0VoqH/1x2nd8Is/bPc= +cloud.google.com/go v0.56.0/go.mod h1:jr7tqZxxKOVYizybht9+26Z/gUq7tiRzu+ACVAMbKVk= +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.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/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.4.0/go.mod h1:S8dzgnTigyfTmLBfrtrhyYhwRxG72rYxvftPBK2Dvzc= +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.8.0/go.mod h1:J5hqkt3O0uAFnINi6JXValWIb1v0goeZM77hZzJN/fQ= 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/firestore v1.1.0/go.mod h1:ulACoGHTpvq5r8rxGJ4ddJZBZqakUQqClKRT5SZwBmk= 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.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/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.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.10.0/go.mod h1:FLPqc6j+Ki4BU591ie1oL6qBQGu2Bl/tZ9ullr3+Kg0= dmitri.shuralyov.com/gpu/mtl v0.0.0-20190408044501-666a987793e9/go.mod h1:H6x//7gZCb22OMCxBHrMx7a5I7Hp++hsVxbQ4BYO7hU= github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= github.com/BurntSushi/xgb v0.0.0-20160522181843-27f122750802/go.mod h1:IVnqGOEym/WlBOVXweHU+Q+/VP0lqqI8lqeDx9IjBqo= github.com/OneOfOne/xxhash v1.2.2/go.mod h1:HSdplMjZKSmBqAxg5vPj2TmRDmfkzw+cTzAElWljhcU= -github.com/alecthomas/template v0.0.0-20160405071501-a0175ee3bccc/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc= -github.com/alecthomas/units v0.0.0-20151022065526-2efee857e7cf/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0= github.com/antihax/optional v1.0.0/go.mod h1:uupD/76wgC+ih3iEmQUL+0Ugr19nfwCT1kdvxnR2qWY= github.com/armon/circbuf v0.0.0-20150827004946-bbbad097214e/go.mod h1:3U/XgcO3hCbHZ8TKRvWD2dDTCfh9M9ya+I9JpbB7O8o= github.com/armon/go-metrics v0.0.0-20180917152333-f0300d1749da/go.mod h1:Q73ZrmVTwzkszR9V5SSuryQ31EELlFMUz1kKyl939pY= github.com/armon/go-radix v0.0.0-20180808171621-7fddfc383310/go.mod h1:ufUuZ+zHj4x4TnLV4JWEpy2hxWSpsRywHrMgIH9cCH8= -github.com/beorn7/perks v0.0.0-20180321164747-3a771d992973/go.mod h1:Dwedo/Wpr24TaqPxmxbtue+5NUziq4I4S80YR8gNf3Q= -github.com/beorn7/perks v1.0.0/go.mod h1:KWe93zE9D1o94FZ5RNwFwVgaQK1VOXiVxmqh+CedLV8= github.com/bgentry/speakeasy v0.1.0/go.mod h1:+zsyZBPWlz7T6j88CTgSN5bM796AkVf0kBD4zp0CCIs= -github.com/bketelsen/crypt v0.0.3-0.20200106085610-5cbc8cc4026c/go.mod h1:MKsuJmJgSg28kpZDP6UIiPt0e0Oz0kqKNGyRaWEPv84= +github.com/bketelsen/crypt v0.0.4/go.mod h1:aI6NrJ0pMGgvZKL1iVgXLnfIFJtfV+bKCoqOes/6LfM= github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU= github.com/cespare/xxhash v1.1.0/go.mod h1:XrSqR1VqqWfGrhpAt58auRo0WTKS1nRRg3ghfAqPWnc= github.com/cespare/xxhash/v2 v2.1.1/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= +github.com/chzyer/logex v1.1.10/go.mod h1:+Ywpsq7O8HXn0nuIou7OrIPyXbp3wmkHB+jjWRnGsAI= +github.com/chzyer/readline v0.0.0-20180603132655-2972be24d48e/go.mod h1:nSuG5e5PlCu98SY8svDHJxuZscDgtXS6KTTbou5AhLI= +github.com/chzyer/test v0.0.0-20180213035817-a1ea475d72b1/go.mod h1:Q3SI9o4m/ZMnBNeIyt5eFwwo7qiLfzFZmjNmxjkiQlU= github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw= 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/xds/go v0.0.0-20210312221358-fbca930ec8ed/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs= github.com/cncf/xds/go v0.0.0-20210805033703-aa0b78936158/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs= -github.com/coreos/bbolt v1.3.2/go.mod h1:iRUV2dpdMOn7Bo10OQBFzIJO9kkE559Wcmn+qkEiiKk= -github.com/coreos/etcd v3.3.13+incompatible/go.mod h1:uF7uidLiAD3TWHmW31ZFd/JWoc32PjwdhPthX9715RE= github.com/coreos/go-semver v0.3.0/go.mod h1:nnelYz7RCh+5ahJtPPxZlU+153eP4D4r3EedlOD2RNk= -github.com/coreos/go-systemd v0.0.0-20190321100706-95778dfbb74e/go.mod h1:F5haX7vjVVG0kc13fIWeqUViNPyEJxv/OmvnBo0Yme4= github.com/coreos/go-systemd/v22 v22.3.2/go.mod h1:Y58oyj3AT4RCenI/lSvhwexgC+NSVTIJ3seZv2GcEnc= -github.com/coreos/pkg v0.0.0-20180928190104-399ea9e2e55f/go.mod h1:E3G3o1h8I7cfcXa63jLwjI0eiQQMgzzUDFVpN/nH/eA= github.com/cpuguy83/go-md2man/v2 v2.0.0/go.mod h1:maD7wRr/U5Z6m/iR4s+kqSMx2CaBsrgA7czyZG/E6dU= github.com/creack/pty v1.1.11 h1:07n33Z8lZxZ2qwegKbObQohDhXDQxiMMz1NOUGYlesw= github.com/creack/pty v1.1.11/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E= github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= -github.com/dgrijalva/jwt-go v3.2.0+incompatible/go.mod h1:E3ru+11k8xSBh+hMPgOLZmtrrCbhqsmaPHjLKYnJCaQ= -github.com/dgryski/go-sip13 v0.0.0-20181026042036-e10d5fee7954/go.mod h1:vAd38F8PWV+bWy6jNmig1y/TA+kYO4g3RSRF0IAv0no= github.com/dustin/go-humanize v1.0.0 h1:VSnTsYCnlFHaM2/igO1h6X3HA71jcobQuxemgkq4zYo= github.com/dustin/go-humanize v1.0.0/go.mod h1:HtrtbFcZ19U5GC7JDqmcUSB87Iq5E25KnS6fMYU6eOk= 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.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.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.10-0.20210907150352-cf90f659a021/go.mod h1:AFq3mo9L8Lqqiid3OhADV3RfLJnjiw63cSpi+fDTRC0= github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c= github.com/fatih/color v1.7.0/go.mod h1:Zm6kSWBoL9eyXnKyktHP6abPY2pDugNf5KwzbycvMj4= -github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo= +github.com/fsnotify/fsnotify v1.4.9/go.mod h1:znqG4EE+3YCdAaPaxE2ZRY/06pZUdp0tY4IgpuI1SZQ= github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04= github.com/go-gl/glfw v0.0.0-20190409004039-e6da0acd62b1/go.mod h1:vR7hzQXu2zJy9AVAgeJqvqgH9Q5CA+iKCZ2gyEVpxRU= -github.com/go-kit/kit v0.8.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as= -github.com/go-logfmt/logfmt v0.3.0/go.mod h1:Qt1PoO58o5twSAckw1HlFXLmHsOX5/0LbT9GBnD5lWE= -github.com/go-logfmt/logfmt v0.4.0/go.mod h1:3RMwSq7FuexP4Kalkev3ejPJsZTpXXBr9+V4qmtdjCk= -github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY= +github.com/go-gl/glfw/v3.3/glfw v0.0.0-20191125211704-12ad95a8df72/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8= +github.com/go-gl/glfw/v3.3/glfw v0.0.0-20200222043503-6f7a984d4dc4/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8= github.com/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.2.1/go.mod h1:hp+jE20tsWTFYpLwKvXlhS1hjn+gTNwPg2I6zVXpSg4= +github.com/gogo/protobuf v1.3.2/go.mod h1:P1XiOD3dCwIKUDQYPy72D8LYyHL2YPYrpS2s69NZV8Q= github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q= -github.com/golang/groupcache v0.0.0-20190129154638-5b532d6fd5ef/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= +github.com/golang/groupcache v0.0.0-20190702054246-869f871628b6/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= +github.com/golang/groupcache v0.0.0-20191227052852-215e87163ea7/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= +github.com/golang/groupcache v0.0.0-20200121045136-8c9f03a8e57e/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= github.com/golang/mock v1.1.1/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A= github.com/golang/mock v1.2.0/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A= github.com/golang/mock v1.3.1/go.mod h1:sBzyDLLjw3U8JLTeZvSv8jJB+tU5PVekmnlKIyFUx0Y= +github.com/golang/mock v1.4.0/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.4/go.mod h1:l3mdAwkq5BuhzHwde/uurv3sEJeZMXNpwsxVWU71h+4= +github.com/golang/mock v1.5.0/go.mod h1:CWnOUgYIOo4TcNZ0wHX3YZCqsaM1I1Jvs6v3mP3KVu8= github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= github.com/golang/protobuf v1.3.1/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= github.com/golang/protobuf v1.3.2/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= github.com/golang/protobuf v1.3.3/go.mod h1:vzj43D7+SQXF/4pzW/hwtAqwc6iTitCiVSaWz5lYuqw= +github.com/golang/protobuf v1.3.4/go.mod h1:vzj43D7+SQXF/4pzW/hwtAqwc6iTitCiVSaWz5lYuqw= +github.com/golang/protobuf v1.3.5/go.mod h1:6O5/vntMXwX2lRkT1hjjk0nAC1IDOTvTlVgjlRvqsdk= github.com/golang/protobuf v1.4.0-rc.1/go.mod h1:ceaxUfeHdC40wWswd/P6IGgMaK3YpKi5j83Wpe3EHw8= github.com/golang/protobuf v1.4.0-rc.1.0.20200221234624-67d41d38c208/go.mod h1:xKAWHe0F5eneWXFV3EuXVDTCmh+JuBKY0li0aMyXATA= github.com/golang/protobuf v1.4.0-rc.2/go.mod h1:LlEzMj4AhA7rCAGe4KMBDvJI+AwstrUpVNzEA03Pprs= @@ -84,6 +112,7 @@ 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.3/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI= 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/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY= github.com/google/btree v0.0.0-20180813153112-4030bb1f1f0c/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ= @@ -92,21 +121,34 @@ github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5a github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= +github.com/google/go-cmp v0.4.1/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.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.5 h1:Khx7svrCpmxxtHBq5j2mp/xVjsi8hQMfNLvJFAlrGgU= github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= +github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= 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.1.0/go.mod h1:y5Zk1BBys9G+gd6Jrk0W3cC1+ELVxBWuIGO+w/tUAp0= 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-20191218002539-d4f498aebedc/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= +github.com/google/pprof v0.0.0-20200212024743-f11f1df84d12/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-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/renameio v0.1.0/go.mod h1:KWCgfxg9yswjAJkECMjeO8J8rahYeXnNhOm40UhjYkI= github.com/google/uuid v1.1.2/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= 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/gopherjs/gopherjs v0.0.0-20181017120253-0766667cb4d1/go.mod h1:wJfORRmW1u3UXTncJ5qlYoELFm8eSnnEO6hX4iZ3EWY= -github.com/gorilla/websocket v1.4.2/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE= -github.com/grpc-ecosystem/go-grpc-middleware v1.0.0/go.mod h1:FiyG127CGDf3tlThmgyCl78X/SZQqEOJBCDaAfeWzPs= -github.com/grpc-ecosystem/go-grpc-prometheus v1.2.0/go.mod h1:8NvIoxWQoOIhqOTXgfV/d3M/q6VIi02HzZEHgUlZvzk= -github.com/grpc-ecosystem/grpc-gateway v1.9.0/go.mod h1:vNeuVxBJEsws4ogUvrchl83t/GYV9WGTSLVdBhOQFDY= github.com/grpc-ecosystem/grpc-gateway v1.16.0/go.mod h1:BDjrQk3hbvj6Nolgz8mAMFbcEtjT1g+wF4CSlocrBnw= github.com/hashicorp/consul/api v1.1.0/go.mod h1:VmuI/Lkw1nC05EYQWNKwWGbkg+FbDBtguAZLlVdkD9Q= github.com/hashicorp/consul/sdk v0.1.1/go.mod h1:VKf9jXwCTEY1QZP2MOLRhb5i/I/ssyNV1vwHyQBF0x8= @@ -128,112 +170,108 @@ github.com/hashicorp/logutils v1.0.0/go.mod h1:QIAnNjmIWmVIIkWDTG1z5v++HQmx9WQRO github.com/hashicorp/mdns v1.0.0/go.mod h1:tL+uN++7HEJ6SQLQ2/p+z2pH24WQKWjBPkE0mNTz8vQ= github.com/hashicorp/memberlist v0.1.3/go.mod h1:ajVTdAv/9Im8oMAAj5G31PhhMCZJV2pPBoIllUwCN7I= github.com/hashicorp/serf v0.8.2/go.mod h1:6hOLApaqBFA1NXqRQAsxw9QxuDEvNxSQRwA/JwenrHc= +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/inconshreveable/mousetrap v1.0.0 h1:Z8tu5sraLXCXIcARxBp/8cbvlwVa7Z1NHg9XEKhtSvM= github.com/inconshreveable/mousetrap v1.0.0/go.mod h1:PxqpIevigyE2G7u3NXJIT2ANytuPF1OarO4DADm73n8= -github.com/jonboulle/clockwork v0.1.0/go.mod h1:Ii8DK3G1RaLaWxj9trq07+26W01tbo22gdxWY5EU2bo= -github.com/json-iterator/go v1.1.6/go.mod h1:+SdeFBvtyEkXs7REEP0seUULqWtbJapLOCVDaaPEHmU= +github.com/json-iterator/go v1.1.11/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4= github.com/jstemmer/go-junit-report v0.0.0-20190106144839-af01ea7f8024/go.mod h1:6v2b51hI/fHJwM22ozAgKL4VKDeJcHhJFhtBdhmNjmU= +github.com/jstemmer/go-junit-report v0.9.1/go.mod h1:Brl9GWCQeLvo8nXZwPNNblvFj/XSXhF0NWZEnDohbsk= github.com/jtolds/gls v4.20.0+incompatible/go.mod h1:QJZ7F/aHp+rZTRtaJ1ow/lLfFfVYBRgL+9YlvaHOwJU= -github.com/julienschmidt/httprouter v1.2.0/go.mod h1:SYymIcj16QtmaHHD7aYtjjsJG7VTCxuUUipMqKk8s4w= -github.com/kisielk/errcheck v1.1.0/go.mod h1:EZBBE59ingxPouuu3KfxchcWSUPOHkagtvWXihfKN4Q= +github.com/kisielk/errcheck v1.5.0/go.mod h1:pFxgyoBC7bSaBwPgfKdkLd5X25qrDl4LWUI2bnpBCr8= github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck= -github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= -github.com/kr/logfmt v0.0.0-20140226030751-b84e30acd515/go.mod h1:+0opPa2QZZtGFBFZlji/RkVcI2GknAs/DXo4wKdlNEc= +github.com/kr/fs v0.1.0/go.mod h1:FFnZGqtBN9Gxj7eW1uZ42v5BccTP0vu6NEaFoC2HwRg= github.com/kr/pretty v0.1.0 h1:L/CwN0zerZDmRFUapSPitk6f+Q3+0za1rQkzVuMiMFI= github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo= github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= github.com/kr/text v0.1.0 h1:45sCR5RtlFHMR4UwH9sdQ5TC8v0qDQCHnXt+kaKSTVE= github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= -github.com/magiconair/properties v1.8.1/go.mod h1:PppfXfuXeibc/6YijjN8zIbojt8czPbwD3XqdrwzmxQ= +github.com/magiconair/properties v1.8.5/go.mod h1:y3VJvCyxH9uVvJTWEGAELF3aiYNyPKd5NZ3oSwXrF60= github.com/mattn/go-colorable v0.0.9/go.mod h1:9vuHe8Xs5qXnSaW/c/ABM9alt+Vo+STaOChaDxuIBZU= github.com/mattn/go-isatty v0.0.3/go.mod h1:M+lRXTBqGeGNdLjl/ufCoiOlB5xdOkqRJdNxMWT7Zi4= -github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0= github.com/miekg/dns v1.0.14/go.mod h1:W1PPwlIAgtquWBMBEV9nkV9Cazfe8ScdGz/Lj7v3Nrg= github.com/mitchellh/cli v1.0.0/go.mod h1:hNIlj7HEI86fIcpObd7a0FcrxTWetlwJDGcceTlRvqc= github.com/mitchellh/go-homedir v1.0.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0= -github.com/mitchellh/go-homedir v1.1.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0= github.com/mitchellh/go-testing-interface v1.0.0/go.mod h1:kRemZodwjscx+RGhAo8eIhFbs2+BFgRtFPeD/KE+zxI= github.com/mitchellh/gox v0.4.0/go.mod h1:Sd9lOJ0+aimLBi73mGofS1ycjY8lL3uZM3JPS42BGNg= github.com/mitchellh/iochan v1.0.0/go.mod h1:JwYml1nuB7xOzsp52dPpHFffvOCDupsG0QubkSMEySY= github.com/mitchellh/mapstructure v0.0.0-20160808181253-ca63d7c062ee/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y= github.com/mitchellh/mapstructure v1.1.2/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y= -github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= +github.com/mitchellh/mapstructure v1.4.1/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo= +github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= +github.com/modern-go/reflect2 v0.0.0-20180701023420-4b7aa43c6742/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0= github.com/modern-go/reflect2 v1.0.1/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0= -github.com/mwitkow/go-conntrack v0.0.0-20161129095857-cc309e4a2223/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U= -github.com/oklog/ulid v1.3.1/go.mod h1:CirwcVhetQ6Lv90oh/F+FBtV6XMibvdAFo93nm5qn4U= github.com/pascaldekloe/goe v0.0.0-20180627143212-57f6aae5913c/go.mod h1:lzWF7FIEvWOWxwDKqyGYQf6ZUaNfKdP144TG7ZOy1lc= -github.com/pelletier/go-toml v1.2.0/go.mod h1:5z9KED0ma1S8pY6P1sdut58dfprrGBbd/94hg7ilaic= -github.com/pkg/errors v0.8.0/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= +github.com/pelletier/go-toml v1.9.3/go.mod h1:u1nR/EPcESfeI/szUZKdtJ0xRNbUoANCkoOuaOx1Y+c= github.com/pkg/errors v0.8.1 h1:iURUrRGxPUNPdy5/HRSm+Yj6okJ6UtLINN0Q9M4+h3I= github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= +github.com/pkg/sftp v1.10.1/go.mod h1:lYOWFsE0bwd1+KfKJaKeuokY15vzFx25BLbzYYoAxZI= github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= github.com/posener/complete v1.1.1/go.mod h1:em0nMJCgc9GFtwrmVmEMR/ZL6WyhyjMBndrE9hABlRI= -github.com/prometheus/client_golang v0.9.1/go.mod h1:7SWBe2y4D6OKWSNQJUaRYU/AaXPKyh/dDVn+NZz0KFw= -github.com/prometheus/client_golang v0.9.3/go.mod h1:/TN21ttK/J9q6uSwhBd54HahCDft0ttaMvbicHlPoso= -github.com/prometheus/client_model v0.0.0-20180712105110-5c3871d89910/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo= -github.com/prometheus/client_model v0.0.0-20190129233127-fd36f4220a90/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= -github.com/prometheus/common v0.0.0-20181113130724-41aa239b4cce/go.mod h1:daVV7qP5qjZbuso7PdcryaAu0sAZbrN9i7WWcTMWvro= -github.com/prometheus/common v0.4.0/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y86RQel1bk4= -github.com/prometheus/procfs v0.0.0-20181005140218-185b4288413d/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk= -github.com/prometheus/procfs v0.0.0-20190507164030-5867b95ac084/go.mod h1:TjEm7ze935MbeOT/UhFTIMYKhuLP4wbCsTZCD3I8kEA= -github.com/prometheus/tsdb v0.7.1/go.mod h1:qhTCs0VvXwvX/y3TZrWD7rabWM+ijKTux40TwIPHuXU= -github.com/rogpeppe/fastuuid v0.0.0-20150106093220-6724a57986af/go.mod h1:XWv6SoW27p1b0cqNHllgS5HIMJraePCO15w5zCzIWYg= github.com/rogpeppe/fastuuid v1.2.0/go.mod h1:jVj6XXZzXRy/MSR5jhDC/2q6DgLz+nrA6LYCDYWNEvQ= github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4= github.com/russross/blackfriday/v2 v2.0.1/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= github.com/ryanuber/columnize v0.0.0-20160712163229-9b3edd62028f/go.mod h1:sm1tb6uqfes/u+d4ooFouqFdy9/2g9QGwK3SQygK0Ts= github.com/sean-/seed v0.0.0-20170313163322-e2103e2c3529/go.mod h1:DxrIzT+xaE7yg65j358z/aeFdxmN0P9QXhEzd20vsDc= github.com/shurcooL/sanitized_anchor_name v1.0.0/go.mod h1:1NzhyTcUVG4SuEtjjoZeVRXNmyL/1OwPU0+IJeTBvfc= -github.com/sirupsen/logrus v1.2.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPxbbu5VWo= github.com/smartystreets/assertions v0.0.0-20180927180507-b2de0cb4f26d/go.mod h1:OnSkiWE9lh6wB0YB77sQom3nweQdgAjqCqsofrRNTgc= github.com/smartystreets/goconvey v1.6.4/go.mod h1:syvi0/a8iFYH4r/RixwvyeAJjdLS9QV7WQ/tjFTllLA= -github.com/soheilhy/cmux v0.1.4/go.mod h1:IM3LyeVVIOuxMH7sFAkER9+bJ4dT7Ms6E4xg4kGIyLM= github.com/spaolacci/murmur3 v0.0.0-20180118202830-f09979ecbc72/go.mod h1:JwIasOWyU6f++ZhiEuf87xNszmSA2myDM2Kzu9HwQUA= -github.com/spf13/afero v1.1.2/go.mod h1:j4pytiNVoe2o6bmDsKpLACNPDBIoEAkihy7loJ1B0CQ= -github.com/spf13/cast v1.3.0/go.mod h1:Qx5cxh0v+4UWYiBimWS+eyWzqEqokIECu5etghLkUJE= -github.com/spf13/cobra v1.1.3 h1:xghbfqPkxzxP3C/f3n5DdpAbdKLj4ZE4BWQI362l53M= -github.com/spf13/cobra v1.1.3/go.mod h1:pGADOWyqRD/YMrPZigI/zbliZ2wVD/23d+is3pSWzOo= -github.com/spf13/jwalterweatherman v1.0.0/go.mod h1:cQK4TGJAtQXfYWX+Ddv3mKDzgVb68N+wFjFa4jdeBTo= -github.com/spf13/pflag v1.0.3/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4= +github.com/spf13/afero v1.6.0/go.mod h1:Ai8FlHk4v/PARR026UzYexafAt9roJ7LcLMAmO6Z93I= +github.com/spf13/cast v1.3.1/go.mod h1:Qx5cxh0v+4UWYiBimWS+eyWzqEqokIECu5etghLkUJE= +github.com/spf13/cobra v1.2.1 h1:+KmjbUw1hriSNMF55oPrkZcb27aECyrj8V2ytv7kWDw= +github.com/spf13/cobra v1.2.1/go.mod h1:ExllRjgxM/piMAM+3tAZvg8fsklGAf3tPfi+i8t68Nk= +github.com/spf13/jwalterweatherman v1.1.0/go.mod h1:aNWZUN0dPAAO/Ljvb5BEdw96iTZ0EXowPYD95IqWIGo= github.com/spf13/pflag v1.0.5 h1:iy+VFUOCP1a+8yFto/drg2CJ5u0yRoB7fZw3DKv/JXA= github.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg= -github.com/spf13/viper v1.7.0/go.mod h1:8WkrPz2fc9jxqZNCJI/76HCieCp4Q8HaLFoCha5qpdg= +github.com/spf13/viper v1.8.1/go.mod h1:o0Pch8wJ9BVSWGQMbra6iw0oQ5oktSIBaujf1rJH9Ns= github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= -github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= 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.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA= +github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/stretchr/testify v1.7.0 h1:nwc3DEeHmmLAfoZucVR881uASk0Mfjw8xYJ99tb5CcY= github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/subosito/gotenv v1.2.0/go.mod h1:N0PQaV/YGNqwC0u51sEeR/aUtSLEXKX9iv69rRypqCw= -github.com/tmc/grpc-websocket-proxy v0.0.0-20190109142713-0ad062ec5ee5/go.mod h1:ncp9v5uamzpCO7NfCPTXjqaC+bZgJeR0sMTm6dMHP7U= -github.com/xiang90/probing v0.0.0-20190116061207-43a291ad63a2/go.mod h1:UETIi67q53MR2AWcXfiuqkDkRtnGDLqkBTpCHuJHxtU= -go.etcd.io/bbolt v1.3.2/go.mod h1:IbVyRI1SCnLcuJnV2u8VeU0CEYM7e686BmAb1XKL+uU= +github.com/yuin/goldmark v1.1.25/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= +github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= +github.com/yuin/goldmark v1.1.32/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= +github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= +go.etcd.io/etcd/client/v2 v2.305.0/go.mod h1:h9puh54ZTgAKtEbut2oe9P4L/oqKCVB6xsXlzd7alYQ= 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.2/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.5/go.mod h1:5pWMHQbX5EPX2/62yrJeAkowc+lfs/XD7Uxpq3pI6kk= +go.opencensus.io v0.23.0/go.mod h1:XItmlyltB5F7CS4xOC1DcqMoFqwtC6OG2xF7mCv7P7E= go.opentelemetry.io/proto/otlp v0.7.0/go.mod h1:PqfVotwruBrMGOCsRd/89rSnXhoiJIqeYNgFYFoEGnI= -go.uber.org/atomic v1.4.0/go.mod h1:gD2HeocX3+yG+ygLZcrzQJaqmWj9AIm7n08wl/qW/PE= go.uber.org/atomic v1.7.0 h1:ADUqmZGgLDDfbSL9ZmPxKTybcoEYHgpYfELNoN+7hsw= go.uber.org/atomic v1.7.0/go.mod h1:fEN4uk6kAWBTFdckzkM89CLk9XfWZrxpCo0nPH17wJc= -go.uber.org/multierr v1.1.0/go.mod h1:wR5kodmAFQ0UK8QlbwjlSNy0Z68gJhDJUG5sjR94q/0= go.uber.org/multierr v1.6.0 h1:y6IPFStTAIT5Ytl7/XYmHvzXQ7S3g/IeZW9hyZ5thw4= go.uber.org/multierr v1.6.0/go.mod h1:cdWPpRnG4AhwMwsgIHip0KRBQjJy5kYEpYjJxpXp9iU= -go.uber.org/zap v1.10.0/go.mod h1:vwi/ZaCAaUcBkycHslxD9B2zi4UTXhF60s6SWpuDF0Q= go.uber.org/zap v1.17.0 h1:MTjgFu6ZLKvY6Pvaqk97GlxNBuMpV4Hy/3P6tRGlI2U= go.uber.org/zap v1.17.0/go.mod h1:MXVU+bhUf/A7Xi2HNOnopQOrmycQ5Ih87HtOu4q5SSo= -golang.org/x/crypto v0.0.0-20180904163835-0709b304e793/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= golang.org/x/crypto v0.0.0-20181029021203-45a5f77698d3/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= golang.org/x/crypto v0.0.0-20190510104115-cbcb75029529/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20190605123033-f99c8df09eb5/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= +golang.org/x/crypto v0.0.0-20190820162420-60c769a6c586/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= +golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= golang.org/x/exp v0.0.0-20190306152737-a1d7652674e8/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= golang.org/x/exp v0.0.0-20190510132918-efd6b22b2522/go.mod h1:ZjyILWgesfNpC6sMxTJOJm9Kp84zZh5NQWvqDGG3Qr8= golang.org/x/exp v0.0.0-20190829153037-c13cbed26979/go.mod h1:86+5VVa7VpoJ4kLfm080zCjGlMRFzhUhsZKEZO7MGek= golang.org/x/exp v0.0.0-20191030013958-a1ab85dbe136/go.mod h1:JXzH8nQsPlswgeRAPE3MuO9GYsAcnJvJ4vnMwN/5qkY= +golang.org/x/exp v0.0.0-20191129062945-2f5052295587/go.mod h1:2RIsYlXP63K8oxa1u096TMicItID8zy7Y6sNkU49FU4= +golang.org/x/exp v0.0.0-20191227195350-da58074b4299/go.mod h1:2RIsYlXP63K8oxa1u096TMicItID8zy7Y6sNkU49FU4= +golang.org/x/exp v0.0.0-20200119233911-0405dc783f0a/go.mod h1:2RIsYlXP63K8oxa1u096TMicItID8zy7Y6sNkU49FU4= +golang.org/x/exp v0.0.0-20200207192155-f17229e696bd/go.mod h1:J/WKrq2StrnmMY6+EHIKF9dgMWnmCNThgcyBT1FY9mM= +golang.org/x/exp v0.0.0-20200224162631-6cc2880d07d6/go.mod h1:3jZMyOhIsHpP37uCMkUooju7aAi5cS1Q23tOzKc+0MU= golang.org/x/image v0.0.0-20190227222117-0694c2d4d067/go.mod h1:kZ7UVZpmo3dzQBMxlp+ypCbDeSB+sBbTgSJuh5dn5js= golang.org/x/image v0.0.0-20190802002840-cff245a6509b/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0= golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE= @@ -243,16 +281,24 @@ golang.org/x/lint v0.0.0-20190313153728-d0100b6bd8b3/go.mod h1:6SW0HCj/g11FgYtHl golang.org/x/lint v0.0.0-20190409202823-959b441ac422/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= golang.org/x/lint v0.0.0-20190909230951-414d861bb4ac/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= golang.org/x/lint v0.0.0-20190930215403-16217165b5de/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= +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-20200302205851-738671d3881b/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY= +golang.org/x/lint v0.0.0-20201208152925-83fdc39ff7b5/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-20190719004257-d2bd2a29d028/go.mod h1:E/iHnbuqvinMTCcRqshq8CkpyQDoeVncDDYHnLhea+o= golang.org/x/mod v0.0.0-20190513183733-4bf6d317e70e/go.mod h1:mXi4GBBbnImb6dmsKGUJ2LatrhH/nqhxcFungHvyanc= golang.org/x/mod v0.1.0/go.mod h1:0QHyrYULN0/3qlju5TqG8bIK38QM8yzMo5ekMj3DlcY= +golang.org/x/mod v0.1.1-0.20191105210325-c90efee705ee/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.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/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-20181023162649-9b4f9f5ad519/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= -golang.org/x/net v0.0.0-20181114220301-adae6a3d119a/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20181201002055-351d144fa1fc/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= -golang.org/x/net v0.0.0-20181220203305-927f97764cc3/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20190108225652-1e06a53dbb7e/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20190213061140-3a22650c66bd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= @@ -261,24 +307,57 @@ golang.org/x/net v0.0.0-20190501004415-9ce7a6920f09/go.mod h1:t9HGtf8HONx5eT2rtn golang.org/x/net v0.0.0-20190503192946-f4e77d36d62c/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= golang.org/x/net v0.0.0-20190603091049-60506f45cf65/go.mod h1:HSz+uSET+XFnRR8LxR5pz3Of3rY3CfYBVs4xY44aLks= golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20190628185345-da137c7871d7/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20190724013045-ca1201d0de80/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20191209160850-c0dbc17a3553/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20200114155413-6afb5195e5aa/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20200202094626-16171245cfb2/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20200222125558-5a598a2470a0/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20200226121028-0de0cce0169b/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20200301022130-244492dfa37a/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20200324143707-d3edc9973b7e/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= +golang.org/x/net v0.0.0-20200501053045-e0ff5e5a1de5/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= +golang.org/x/net v0.0.0-20200506145744-7e3656a0809f/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= +golang.org/x/net v0.0.0-20200513185701-a91f0712d120/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= +golang.org/x/net v0.0.0-20200520182314-0ba52f642ac2/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= +golang.org/x/net v0.0.0-20200625001655-4c5254603344/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-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-20210316092652-d523dce5a7f4/go.mod h1:RBQZq4jEuRlivfhVLdyRGr576XBO4/greRjx4P4O3yc= golang.org/x/net v0.0.0-20210405180319-a5a99cb37ef4 h1:4nGaVu0QrbjT/AK2PRLuQfQuh6DJve+pELhqTdAj3x0= golang.org/x/net v0.0.0-20210405180319-a5a99cb37ef4/go.mod h1:p54w0d4576C0XHj96bSt6lcn1PtDYWL6XObtHCRCNQM= 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-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-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-20210402161424-2e8d93401602/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= 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-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20190227155943-e225da77a7e6/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20200317015054-43a5402ce75a/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20200625203802-6e8e738ad208/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-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sys v0.0.0-20180823144017-11551d06cbcc/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= -golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20181026203630-95b1ffbd15a5/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= -golang.org/x/sys v0.0.0-20181107165924-66b7b1311ac8/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= -golang.org/x/sys v0.0.0-20181116152217-5ac8a444bdc5/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190312061237-fead79001313/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= @@ -286,22 +365,51 @@ golang.org/x/sys v0.0.0-20190502145724-3ef323f4f1fd/go.mod h1:h1NjWce9XRLGQEsW7w golang.org/x/sys v0.0.0-20190507160741-ecd444e8653b/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190606165138-5da285871e9c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190624142023-c5567b49c5d0/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190726091711-fc99dfbffb4e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20191001151750-bb3f8db39f24/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20191005200804-aed5e4c7ecf9/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20191204072324-ce4227a45e2e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20191228213918-04cbcbbfeed8/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200113162924-86b910548bc1/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200122134326-e047566fdf82/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200202164722-d101bd2416d5/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200212091648-12a6c2dcc1e4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200223170610-d5e6a3e2c0ae/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200302150141-5c8b2ff67527/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200331124033-c3d80250170d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200501052902-10377860bb8e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200511232937-7e40ca221e25/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200515095857-1151b9dac4a9/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200523222454-059865788121/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-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-20210119212857-b64e53b001e4/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-20210403161142-5e06dd20ab57/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-20210603125802-9665404d3644 h1:CA1DEQ4NdKphKeL70tvsWNdT5oFh1lOjihRcEDROi0I= golang.org/x/sys v0.0.0-20210603125802-9665404d3644/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= +golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.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.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 h1:i6eZZ+zk0SOf0xgBpEpPD18qWcJda6q1sxt3S0kzyUQ= golang.org/x/text v0.3.5/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= -golang.org/x/tools v0.0.0-20180221164845-07fd8470d635/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= +golang.org/x/time v0.0.0-20191024005414-555d28b269f0/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-20190114222345-bf090417da8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20190226205152-f727befe758c/go.mod h1:9Yl7xja0Znq3iFh3HoIrodX9oNMXvdceNzlUR8zjMvY= @@ -319,7 +427,41 @@ golang.org/x/tools v0.0.0-20190816200558-6889da9d5479/go.mod h1:b+2E5dAYhXwXZwtn golang.org/x/tools v0.0.0-20190911174233-4f2ddba30aff/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.0.0-20191012152004-8de300cfc20a/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.0.0-20191112195655-aa38f8e97acc/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-20191113191852-77e3bb0ad9e7/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-20191115202509-3a792d9c32b2/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-20191125144606-a911d9008d1f/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-20191130070609-6e064ea0cf2d/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-20191216173652-a0e659d51361/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= +golang.org/x/tools v0.0.0-20191227053925-7b8e75db28f4/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= +golang.org/x/tools v0.0.0-20200117161641-43d50277825c/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= +golang.org/x/tools v0.0.0-20200122220014-bf1340f18c4a/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= +golang.org/x/tools v0.0.0-20200130002326-2f3ba24bd6e7/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= +golang.org/x/tools v0.0.0-20200204074204-1cc6d1ef6c74/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= +golang.org/x/tools v0.0.0-20200207183749-b753a1ba74fa/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= +golang.org/x/tools v0.0.0-20200212150539-ea181f53ac56/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= +golang.org/x/tools v0.0.0-20200224181240-023911ca70b2/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= +golang.org/x/tools v0.0.0-20200227222343-706bc42d1f0d/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= +golang.org/x/tools v0.0.0-20200304193943-95d2e580d8eb/go.mod h1:o4KQGtdN14AW+yjsvvwRTJJuXz8XRtIHtEnmAXLyFUw= +golang.org/x/tools v0.0.0-20200312045724-11d5b4c81c7d/go.mod h1:o4KQGtdN14AW+yjsvvwRTJJuXz8XRtIHtEnmAXLyFUw= +golang.org/x/tools v0.0.0-20200331025713-a30bf2db82d4/go.mod h1:Sl4aGygMT6LrqrWclx+PTx3U+LnKx/seiNR+3G19Ar8= +golang.org/x/tools v0.0.0-20200501065659-ab2804fb9c9d/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= +golang.org/x/tools v0.0.0-20200512131952-2bc93b1c0c88/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= +golang.org/x/tools v0.0.0-20200515010526-7d3b6ebf133d/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= +golang.org/x/tools v0.0.0-20200618134242-20370b0cb4b2/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= +golang.org/x/tools v0.0.0-20200619180055-7c47624df98f/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= +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-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-20210105154028-b0ab187a4818/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/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-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1 h1:go1bK/D/BFZV2I8cIQd1NKEZ+0owSTG1fDTci4IqFcE= golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= @@ -328,10 +470,30 @@ google.golang.org/api v0.7.0/go.mod h1:WtwebWUNSVBH/HAw79HIFXZNqEvBhG+Ra+ax0hx3E google.golang.org/api v0.8.0/go.mod h1:o4eAsZoiT+ibD93RtjEohWalFOjRDx6CVaqeizhEnKg= google.golang.org/api v0.9.0/go.mod h1:o4eAsZoiT+ibD93RtjEohWalFOjRDx6CVaqeizhEnKg= google.golang.org/api v0.13.0/go.mod h1:iLdEw5Ide6rF15KTC1Kkl0iskquN2gFfn9o9XIsbkAI= +google.golang.org/api v0.14.0/go.mod h1:iLdEw5Ide6rF15KTC1Kkl0iskquN2gFfn9o9XIsbkAI= +google.golang.org/api v0.15.0/go.mod h1:iLdEw5Ide6rF15KTC1Kkl0iskquN2gFfn9o9XIsbkAI= +google.golang.org/api v0.17.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE= +google.golang.org/api v0.18.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE= +google.golang.org/api v0.19.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE= +google.golang.org/api v0.20.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE= +google.golang.org/api v0.22.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE= +google.golang.org/api v0.24.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.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.44.0/go.mod h1:EBOGZqzyhtvMDoxwS97ctnh0zUmYY6CxqXsc1AvkYD8= 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.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.5/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc= +google.golang.org/appengine v1.6.6/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc= +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-20190307195333-5fe7a883aa19/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= google.golang.org/genproto v0.0.0-20190418145605-e7d98fc518a7/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= @@ -341,8 +503,37 @@ google.golang.org/genproto v0.0.0-20190801165951-fa694d86fc64/go.mod h1:DMBHOl98 google.golang.org/genproto v0.0.0-20190819201941-24fa4b261c55/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc= google.golang.org/genproto v0.0.0-20190911173649-1774047e7e51/go.mod h1:IbNlFCBrqXvoKpeg0TB2l7cyZUmoaFKYIwrEpbDKLA8= google.golang.org/genproto v0.0.0-20191108220845-16a3f7862a1a/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= +google.golang.org/genproto v0.0.0-20191115194625-c23dd37a84c9/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= +google.golang.org/genproto v0.0.0-20191216164720-4f79533eabd1/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= +google.golang.org/genproto v0.0.0-20191230161307-f3c370f40bfb/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= +google.golang.org/genproto v0.0.0-20200115191322-ca5a22157cba/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= +google.golang.org/genproto v0.0.0-20200122232147-0452cf42e150/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= +google.golang.org/genproto v0.0.0-20200204135345-fa8e72b47b90/go.mod h1:GmwEX6Z4W5gMy59cAlVYjN9JhxgbQH6Gn+gFDQe2lzA= +google.golang.org/genproto v0.0.0-20200212174721-66ed5ce911ce/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= +google.golang.org/genproto v0.0.0-20200224152610-e50cd9704f63/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= +google.golang.org/genproto v0.0.0-20200228133532-8c2c7df3a383/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= +google.golang.org/genproto v0.0.0-20200305110556-506484158171/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= +google.golang.org/genproto v0.0.0-20200312145019-da6875a35672/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= +google.golang.org/genproto v0.0.0-20200331122359-1ee6d9798940/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= +google.golang.org/genproto v0.0.0-20200430143042-b979b6f78d84/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= +google.golang.org/genproto v0.0.0-20200511104702-f5ebc3bea380/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= google.golang.org/genproto v0.0.0-20200513103714-09dca8ec2884/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= +google.golang.org/genproto v0.0.0-20200515170657-fc4c6c6a6587/go.mod h1:YsZOwe1myG/8QRHRsmBRE1LrgQY60beZKjly0O1fX9U= google.golang.org/genproto v0.0.0-20200526211855-cb27e3aa2013/go.mod h1:NbSheEEYHJ7i3ixzK3sjbqSGDJWnxyFXZblF3eUsNvo= +google.golang.org/genproto v0.0.0-20200618031413-b414f8b61790/go.mod h1:jDfRM7FcilCzHH/e9qn6dsT145K34l5v+OpcnNgKAAA= +google.golang.org/genproto v0.0.0-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-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-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-20210402141018-6c239bbf2bb1/go.mod h1:9lPAdzaEmUacj36I+k7YKbEc5CXzPIeORRgDAUOu28A= google.golang.org/genproto v0.0.0-20211118181313-81c1377c94b1 h1:b9mVrqYfq3P4bCdaLg1qtBnPzUYgglsIdjZkL/fQVOE= google.golang.org/genproto v0.0.0-20211118181313-81c1377c94b1/go.mod h1:5CzLGKJ67TSI2B9POpiiyGha0AjJvZIUgRMt1dSmuhc= google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c= @@ -350,9 +541,21 @@ google.golang.org/grpc v1.20.1/go.mod h1:10oTOabMzJvdu6/UiuZezV6QK5dSlG84ov/aaiq google.golang.org/grpc v1.21.1/go.mod h1:oYelfM1adQP15Ek0mdvEgi9Df8B9CZIaU1084ijfRaM= google.golang.org/grpc v1.23.0/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg= google.golang.org/grpc v1.25.1/go.mod h1:c3i+UQWmh7LiEpx4sFZnkU36qjEYZ0imhYfXVyQciAY= +google.golang.org/grpc v1.26.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk= google.golang.org/grpc v1.27.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk= +google.golang.org/grpc v1.27.1/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk= +google.golang.org/grpc v1.28.0/go.mod h1:rpkK4SK4GF4Ach/+MFLZUBavHOvF2JJB5uozKKal+60= +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.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.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.1/go.mod h1:qjiiYl8FncCW8feJPdyg3v6XW24KsRHe+dy9BAGRRjU= +google.golang.org/grpc v1.38.0/go.mod h1:NREThFqKR1f3iQ6oBuvc5LadQuXVGo9rkm5ZGrQdJfM= google.golang.org/grpc v1.40.0/go.mod h1:ogyxbiOoUXAkP+4+xa6PZSE9DZgIHtSpzjDTB9KAK34= google.golang.org/grpc v1.41.0 h1:f+PlOh7QV4iIJkPrx5NQ7qaNGFQ3OTse67yaDHfju4E= google.golang.org/grpc v1.41.0/go.mod h1:U3l9uK9J0sini8mHphKoXyaqDA/8VyGnDee1zzIUK6k= @@ -364,23 +567,19 @@ google.golang.org/protobuf v1.21.0/go.mod h1:47Nbq4nVaFHyn7ilMalzfO3qCViNmqZ2kzi google.golang.org/protobuf v1.22.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= google.golang.org/protobuf v1.23.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= google.golang.org/protobuf v1.23.1-0.20200526195155-81db48ad09cc/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= +google.golang.org/protobuf v1.24.0/go.mod h1:r/3tXBNzIEhYS9I1OUVjXDlt8tc493IdKGjtUeSXeh4= google.golang.org/protobuf v1.25.0/go.mod h1:9JNX74DMeImyA3h4bdi1ymwjUzf21/xIlbajtzgsN7c= google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw= google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc= google.golang.org/protobuf v1.27.1 h1:SnqbnDw1V7RiZcXPx5MEeqPv2s79L9i7BJUlG/+RurQ= google.golang.org/protobuf v1.27.1/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc= -gopkg.in/alecthomas/kingpin.v2 v2.2.6/go.mod h1:FMv+mEhP44yOT+4EoQTLFTRgOQ1FBLkstjWtayDeSgw= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127 h1:qIbj1fsPNlZgppZ+VLlY7N33q108Sa+fhmuc+sWQYwY= gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/errgo.v2 v2.1.0/go.mod h1:hNsd1EY+bozCKY1Ytp96fpM3vjJbqLJn88ws8XvfDNI= -gopkg.in/ini.v1 v1.51.0/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k= -gopkg.in/resty.v1 v1.12.0/go.mod h1:mDo4pnntr5jdWRML875a/NmxYqAlA73dVijT2AXvQQo= -gopkg.in/yaml.v2 v2.0.0-20170812160011-eb3733d160e7/go.mod h1:JAlM8MvJe8wmxCU4Bli9HhUf9+ttbYbLASfIpnQbh74= -gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= +gopkg.in/ini.v1 v1.62.0/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k= gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.2.3/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= -gopkg.in/yaml.v2 v2.2.4/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.2.8/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY= gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ= @@ -392,4 +591,8 @@ honnef.co/go/tools v0.0.0-20190106161140-3f1c8253044a/go.mod h1:rf3lG4BRIbNafJWh honnef.co/go/tools v0.0.0-20190418001031-e561f6794a2a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= honnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= honnef.co/go/tools v0.0.1-2019.2.3/go.mod h1:a3bituU0lyd329TUQxRnasdCoJDkEUEAqEt0JzvZhAg= +honnef.co/go/tools v0.0.1-2020.1.3/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9vFzvIQ3k= +honnef.co/go/tools v0.0.1-2020.1.4/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9vFzvIQ3k= 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/sampler v1.3.0/go.mod h1:T1hPZKmBbMNahiBKFy5HrXp6adAjACjK9JXDnKaTXpA= diff --git a/server/go.mod b/server/go.mod index 79941642cd01..22e7505a94b7 100644 --- a/server/go.mod +++ b/server/go.mod @@ -18,7 +18,7 @@ require ( github.com/prometheus/client_golang v1.11.0 github.com/prometheus/client_model v0.2.0 github.com/soheilhy/cmux v0.1.5 - github.com/spf13/cobra v1.1.3 + github.com/spf13/cobra v1.2.1 github.com/stretchr/testify v1.7.0 github.com/tmc/grpc-websocket-proxy v0.0.0-20201229170055-e5319fda7802 github.com/xiang90/probing v0.0.0-20190116061207-43a291ad63a2 diff --git a/server/go.sum b/server/go.sum index 914b7082fcdb..dc3ceddc0112 100644 --- a/server/go.sum +++ b/server/go.sum @@ -4,13 +4,39 @@ cloud.google.com/go v0.38.0/go.mod h1:990N+gfupTy94rShfmMCWGDn0LpTmnzTp2qbd1dvSR cloud.google.com/go v0.44.1/go.mod h1:iSa0KzasP4Uvy3f1mN/7PiObzGgflwredwwASm/v6AU= cloud.google.com/go v0.44.2/go.mod h1:60680Gw3Yr4ikxnPRS/oxxkBccT6SA1yMk63TGekxKY= cloud.google.com/go v0.45.1/go.mod h1:RpBamKRgapWJb87xiFSdk4g1CME7QZg3uwTez+TSTjc= -cloud.google.com/go v0.46.3 h1:AVXDdKsrtX33oR9fbCMu/+c1o8Ofjq6Ku/MInaLVg5Y= cloud.google.com/go v0.46.3/go.mod h1:a6bKKbmY7er1mI7TEI4lsAkts/mkhTSZK8w33B4RAg0= +cloud.google.com/go v0.50.0/go.mod h1:r9sluTvynVuxRIOHXQEHMFffphuXHOMZMycpNR5e6To= +cloud.google.com/go v0.52.0/go.mod h1:pXajvRH/6o3+F9jDHZWQ5PbGhn+o8w9qiu/CffaVdO4= +cloud.google.com/go v0.53.0/go.mod h1:fp/UouUEsRkN6ryDKNW/Upv/JBKnv6WDthjR6+vze6M= +cloud.google.com/go v0.54.0/go.mod h1:1rq2OEkV3YMf6n/9ZvGWI3GWw0VoqH/1x2nd8Is/bPc= +cloud.google.com/go v0.56.0/go.mod h1:jr7tqZxxKOVYizybht9+26Z/gUq7tiRzu+ACVAMbKVk= +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.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 h1:at8Tk2zUz63cLPR0JPWm5vp77pEZmzxEQBEfRKn1VV8= +cloud.google.com/go v0.81.0/go.mod h1:mk/AM35KwGk/Nm2YSeZbxXdrNK3KZOYHmLkOqC2V6E0= 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.4.0/go.mod h1:S8dzgnTigyfTmLBfrtrhyYhwRxG72rYxvftPBK2Dvzc= +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.8.0/go.mod h1:J5hqkt3O0uAFnINi6JXValWIb1v0goeZM77hZzJN/fQ= 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/firestore v1.1.0/go.mod h1:ulACoGHTpvq5r8rxGJ4ddJZBZqakUQqClKRT5SZwBmk= 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.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/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.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.10.0/go.mod h1:FLPqc6j+Ki4BU591ie1oL6qBQGu2Bl/tZ9ullr3+Kg0= dmitri.shuralyov.com/gpu/mtl v0.0.0-20190408044501-666a987793e9/go.mod h1:H6x//7gZCb22OMCxBHrMx7a5I7Hp++hsVxbQ4BYO7hU= github.com/BurntSushi/toml v0.3.1 h1:WXkYYl6Yr3qBf1K79EBnL4mak0OimBfB0XUf9Vl28OQ= github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= @@ -30,7 +56,7 @@ github.com/beorn7/perks v1.0.0/go.mod h1:KWe93zE9D1o94FZ5RNwFwVgaQK1VOXiVxmqh+Ce github.com/beorn7/perks v1.0.1 h1:VlbKKnNfV8bJzeqoa4cOKqO6bYr3WgKZxO8Z16+hsOM= github.com/beorn7/perks v1.0.1/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6rlkpw= github.com/bgentry/speakeasy v0.1.0/go.mod h1:+zsyZBPWlz7T6j88CTgSN5bM796AkVf0kBD4zp0CCIs= -github.com/bketelsen/crypt v0.0.3-0.20200106085610-5cbc8cc4026c/go.mod h1:MKsuJmJgSg28kpZDP6UIiPt0e0Oz0kqKNGyRaWEPv84= +github.com/bketelsen/crypt v0.0.4/go.mod h1:aI6NrJ0pMGgvZKL1iVgXLnfIFJtfV+bKCoqOes/6LfM= github.com/cenkalti/backoff/v4 v4.1.1 h1:G2HAfAmvm/GcKan2oOQpBXOd2tT2G57ZnZGWa1PxPBQ= github.com/cenkalti/backoff/v4 v4.1.1/go.mod h1:scbssz8iZGpm3xbr14ovlUdkxfGXNInqkPWOWmG2CLw= github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU= @@ -41,8 +67,12 @@ github.com/cespare/xxhash v1.1.0 h1:a6HrQnmkObjyL+Gs60czilIUGqrzKutQD6XZog3p+ko= github.com/cespare/xxhash v1.1.0/go.mod h1:XrSqR1VqqWfGrhpAt58auRo0WTKS1nRRg3ghfAqPWnc= github.com/cespare/xxhash/v2 v2.1.1 h1:6MnRN8NT7+YBpUIWxHtefFZOKTAPgGjpQSxqLNn0+qY= github.com/cespare/xxhash/v2 v2.1.1/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= +github.com/chzyer/logex v1.1.10/go.mod h1:+Ywpsq7O8HXn0nuIou7OrIPyXbp3wmkHB+jjWRnGsAI= +github.com/chzyer/readline v0.0.0-20180603132655-2972be24d48e/go.mod h1:nSuG5e5PlCu98SY8svDHJxuZscDgtXS6KTTbou5AhLI= +github.com/chzyer/test v0.0.0-20180213035817-a1ea475d72b1/go.mod h1:Q3SI9o4m/ZMnBNeIyt5eFwwo7qiLfzFZmjNmxjkiQlU= github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw= 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/xds/go v0.0.0-20210312221358-fbca930ec8ed/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs= github.com/cncf/xds/go v0.0.0-20210805033703-aa0b78936158/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs= @@ -52,39 +82,35 @@ github.com/cockroachdb/errors v1.2.4 h1:Lap807SXTH5tri2TivECb/4abUkMZC9zRoLarvcK github.com/cockroachdb/errors v1.2.4/go.mod h1:rQD95gz6FARkaKkQXUksEje/d9a6wBJoCr5oaCLELYA= github.com/cockroachdb/logtags v0.0.0-20190617123548-eb05cc24525f h1:o/kfcElHqOiXqcou5a3rIlMc7oJbMQkeLk0VQJ7zgqY= github.com/cockroachdb/logtags v0.0.0-20190617123548-eb05cc24525f/go.mod h1:i/u985jwjWRlyHXQbwatDASoW0RMlZ/3i9yJHE2xLkI= -github.com/coreos/bbolt v1.3.2/go.mod h1:iRUV2dpdMOn7Bo10OQBFzIJO9kkE559Wcmn+qkEiiKk= -github.com/coreos/etcd v3.3.13+incompatible/go.mod h1:uF7uidLiAD3TWHmW31ZFd/JWoc32PjwdhPthX9715RE= github.com/coreos/go-semver v0.3.0 h1:wkHLiw0WNATZnSG7epLsujiMCgPAc9xhjJ4tgnAxmfM= github.com/coreos/go-semver v0.3.0/go.mod h1:nnelYz7RCh+5ahJtPPxZlU+153eP4D4r3EedlOD2RNk= -github.com/coreos/go-systemd v0.0.0-20190321100706-95778dfbb74e h1:Wf6HqHfScWJN9/ZjdUKyjop4mf3Qdd+1TvvltAvM3m8= -github.com/coreos/go-systemd v0.0.0-20190321100706-95778dfbb74e/go.mod h1:F5haX7vjVVG0kc13fIWeqUViNPyEJxv/OmvnBo0Yme4= github.com/coreos/go-systemd/v22 v22.3.2 h1:D9/bQk5vlXQFZ6Kwuu6zaiXJ9oTPe68++AzAJc1DzSI= github.com/coreos/go-systemd/v22 v22.3.2/go.mod h1:Y58oyj3AT4RCenI/lSvhwexgC+NSVTIJ3seZv2GcEnc= -github.com/coreos/pkg v0.0.0-20180928190104-399ea9e2e55f/go.mod h1:E3G3o1h8I7cfcXa63jLwjI0eiQQMgzzUDFVpN/nH/eA= github.com/cpuguy83/go-md2man/v2 v2.0.0/go.mod h1:maD7wRr/U5Z6m/iR4s+kqSMx2CaBsrgA7czyZG/E6dU= github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E= github.com/creack/pty v1.1.11/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E= github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= -github.com/dgrijalva/jwt-go v3.2.0+incompatible/go.mod h1:E3ru+11k8xSBh+hMPgOLZmtrrCbhqsmaPHjLKYnJCaQ= -github.com/dgryski/go-sip13 v0.0.0-20181026042036-e10d5fee7954/go.mod h1:vAd38F8PWV+bWy6jNmig1y/TA+kYO4g3RSRF0IAv0no= github.com/dustin/go-humanize v1.0.0 h1:VSnTsYCnlFHaM2/igO1h6X3HA71jcobQuxemgkq4zYo= github.com/dustin/go-humanize v1.0.0/go.mod h1:HtrtbFcZ19U5GC7JDqmcUSB87Iq5E25KnS6fMYU6eOk= 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.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.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.10-0.20210907150352-cf90f659a021/go.mod h1:AFq3mo9L8Lqqiid3OhADV3RfLJnjiw63cSpi+fDTRC0= github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c= github.com/fatih/color v1.7.0/go.mod h1:Zm6kSWBoL9eyXnKyktHP6abPY2pDugNf5KwzbycvMj4= -github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo= +github.com/fsnotify/fsnotify v1.4.9/go.mod h1:znqG4EE+3YCdAaPaxE2ZRY/06pZUdp0tY4IgpuI1SZQ= github.com/getsentry/raven-go v0.2.0 h1:no+xWJRb5ZI7eE8TWgIq1jLulQiIoLG0IfYxv5JYMGs= github.com/getsentry/raven-go v0.2.0/go.mod h1:KungGk8q33+aIAZUIVWZDr2OfAEBsO49PX4NzFV5kcQ= github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04= github.com/go-gl/glfw v0.0.0-20190409004039-e6da0acd62b1/go.mod h1:vR7hzQXu2zJy9AVAgeJqvqgH9Q5CA+iKCZ2gyEVpxRU= +github.com/go-gl/glfw/v3.3/glfw v0.0.0-20191125211704-12ad95a8df72/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8= +github.com/go-gl/glfw/v3.3/glfw v0.0.0-20200222043503-6f7a984d4dc4/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8= github.com/go-kit/kit v0.8.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as= github.com/go-kit/kit v0.9.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as= github.com/go-kit/log v0.1.0/go.mod h1:zbhenjAZHb184qTLMA9ZjW7ThYL0H2mk7Q6pNt4vbaY= @@ -94,23 +120,31 @@ github.com/go-logfmt/logfmt v0.5.0/go.mod h1:wCYkCAKZfumFQihp8CzCvQ3paCTfi41vtzG github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY= 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.2.1/go.mod h1:hp+jE20tsWTFYpLwKvXlhS1hjn+gTNwPg2I6zVXpSg4= github.com/gogo/protobuf v1.3.1/go.mod h1:SlYgWuQ5SjCEi6WLHjHCa1yvBfUnHcTbrrZtXPKa29o= github.com/gogo/protobuf v1.3.2 h1:Ov1cvc58UF3b5XjBnZv7+opcTcQFZebYjWzi34vdm4Q= github.com/gogo/protobuf v1.3.2/go.mod h1:P1XiOD3dCwIKUDQYPy72D8LYyHL2YPYrpS2s69NZV8Q= github.com/golang-jwt/jwt v3.2.2+incompatible h1:IfV12K8xAKAnZqdXVzCZ+TOjboZ2keLg81eXfW3O+oY= github.com/golang-jwt/jwt v3.2.2+incompatible/go.mod h1:8pz2t5EyA70fFQQSrl6XZXzqecmYZeUEB8OUGHkxJ+I= github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q= -github.com/golang/groupcache v0.0.0-20190129154638-5b532d6fd5ef/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= +github.com/golang/groupcache v0.0.0-20190702054246-869f871628b6/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= +github.com/golang/groupcache v0.0.0-20191227052852-215e87163ea7/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= +github.com/golang/groupcache v0.0.0-20200121045136-8c9f03a8e57e/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da h1:oI5xCqsCo564l8iNU+DwB5epxmsaqB+rhGL0m5jtYqE= github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= github.com/golang/mock v1.1.1/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A= github.com/golang/mock v1.2.0/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A= github.com/golang/mock v1.3.1/go.mod h1:sBzyDLLjw3U8JLTeZvSv8jJB+tU5PVekmnlKIyFUx0Y= +github.com/golang/mock v1.4.0/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.4/go.mod h1:l3mdAwkq5BuhzHwde/uurv3sEJeZMXNpwsxVWU71h+4= +github.com/golang/mock v1.5.0/go.mod h1:CWnOUgYIOo4TcNZ0wHX3YZCqsaM1I1Jvs6v3mP3KVu8= github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= github.com/golang/protobuf v1.3.1/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= github.com/golang/protobuf v1.3.2/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= github.com/golang/protobuf v1.3.3/go.mod h1:vzj43D7+SQXF/4pzW/hwtAqwc6iTitCiVSaWz5lYuqw= +github.com/golang/protobuf v1.3.4/go.mod h1:vzj43D7+SQXF/4pzW/hwtAqwc6iTitCiVSaWz5lYuqw= +github.com/golang/protobuf v1.3.5/go.mod h1:6O5/vntMXwX2lRkT1hjjk0nAC1IDOTvTlVgjlRvqsdk= github.com/golang/protobuf v1.4.0-rc.1/go.mod h1:ceaxUfeHdC40wWswd/P6IGgMaK3YpKi5j83Wpe3EHw8= github.com/golang/protobuf v1.4.0-rc.1.0.20200221234624-67d41d38c208/go.mod h1:xKAWHe0F5eneWXFV3EuXVDTCmh+JuBKY0li0aMyXATA= github.com/golang/protobuf v1.4.0-rc.2/go.mod h1:LlEzMj4AhA7rCAGe4KMBDvJI+AwstrUpVNzEA03Pprs= @@ -120,6 +154,7 @@ 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.3/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI= 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/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY= github.com/google/btree v0.0.0-20180813153112-4030bb1f1f0c/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ= @@ -130,15 +165,30 @@ github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5a github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= +github.com/google/go-cmp v0.4.1/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.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.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.6 h1:BKbKCqvP6I+rmFHt06ZmyQtvB8xAkWdhFyr0ZUNZcxQ= github.com/google/go-cmp v0.5.6/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= 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.1.0/go.mod h1:y5Zk1BBys9G+gd6Jrk0W3cC1+ELVxBWuIGO+w/tUAp0= 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-20191218002539-d4f498aebedc/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= +github.com/google/pprof v0.0.0-20200212024743-f11f1df84d12/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-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/renameio v0.1.0/go.mod h1:KWCgfxg9yswjAJkECMjeO8J8rahYeXnNhOm40UhjYkI= github.com/google/uuid v1.1.2/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/googleapis/gax-go/v2 v2.0.4/go.mod h1:0Wqv26UfaUD9n4G6kQubkQ+KchISgw+vpHVxEJEs9eg= @@ -146,12 +196,10 @@ github.com/googleapis/gax-go/v2 v2.0.5/go.mod h1:DWXyrwAJ9X0FpwwEdw+IPEYBICEFu5m github.com/gopherjs/gopherjs v0.0.0-20181017120253-0766667cb4d1/go.mod h1:wJfORRmW1u3UXTncJ5qlYoELFm8eSnnEO6hX4iZ3EWY= github.com/gorilla/websocket v1.4.2 h1:+/TMaTYc4QFitKJxsQ7Yye35DkWvkdLcvGKqM+x0Ufc= github.com/gorilla/websocket v1.4.2/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE= -github.com/grpc-ecosystem/go-grpc-middleware v1.0.0/go.mod h1:FiyG127CGDf3tlThmgyCl78X/SZQqEOJBCDaAfeWzPs= github.com/grpc-ecosystem/go-grpc-middleware v1.3.0 h1:+9834+KizmvFV7pXQGSXQTsaWhq2GjuNUt0aUU0YBYw= github.com/grpc-ecosystem/go-grpc-middleware v1.3.0/go.mod h1:z0ButlSOZa5vEBq9m2m2hlwIgKw+rp3sdCBRoJY+30Y= github.com/grpc-ecosystem/go-grpc-prometheus v1.2.0 h1:Ovs26xHkKqVztRpIrF/92BcuyuQ/YW4NSIpoGtfXNho= github.com/grpc-ecosystem/go-grpc-prometheus v1.2.0/go.mod h1:8NvIoxWQoOIhqOTXgfV/d3M/q6VIi02HzZEHgUlZvzk= -github.com/grpc-ecosystem/grpc-gateway v1.9.0/go.mod h1:vNeuVxBJEsws4ogUvrchl83t/GYV9WGTSLVdBhOQFDY= github.com/grpc-ecosystem/grpc-gateway v1.16.0 h1:gmcG1KaJ57LophUzW0Hy8NmPhnMZb4M0+kPpLofRdBo= github.com/grpc-ecosystem/grpc-gateway v1.16.0/go.mod h1:BDjrQk3hbvj6Nolgz8mAMFbcEtjT1g+wF4CSlocrBnw= github.com/hashicorp/consul/api v1.1.0/go.mod h1:VmuI/Lkw1nC05EYQWNKwWGbkg+FbDBtguAZLlVdkD9Q= @@ -174,9 +222,10 @@ github.com/hashicorp/logutils v1.0.0/go.mod h1:QIAnNjmIWmVIIkWDTG1z5v++HQmx9WQRO github.com/hashicorp/mdns v1.0.0/go.mod h1:tL+uN++7HEJ6SQLQ2/p+z2pH24WQKWjBPkE0mNTz8vQ= github.com/hashicorp/memberlist v0.1.3/go.mod h1:ajVTdAv/9Im8oMAAj5G31PhhMCZJV2pPBoIllUwCN7I= github.com/hashicorp/serf v0.8.2/go.mod h1:6hOLApaqBFA1NXqRQAsxw9QxuDEvNxSQRwA/JwenrHc= +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/inconshreveable/mousetrap v1.0.0 h1:Z8tu5sraLXCXIcARxBp/8cbvlwVa7Z1NHg9XEKhtSvM= github.com/inconshreveable/mousetrap v1.0.0/go.mod h1:PxqpIevigyE2G7u3NXJIT2ANytuPF1OarO4DADm73n8= -github.com/jonboulle/clockwork v0.1.0/go.mod h1:Ii8DK3G1RaLaWxj9trq07+26W01tbo22gdxWY5EU2bo= github.com/jonboulle/clockwork v0.2.2 h1:UOGuzwb1PwsrDAObMuhUnj0p5ULPj8V/xJ7Kx9qUBdQ= github.com/jonboulle/clockwork v0.2.2/go.mod h1:Pkfl5aHPm1nk2H9h0bjmnJD/BcgbGXUBGnn1kMkgxc8= github.com/jpillora/backoff v1.0.0/go.mod h1:J/6gKK9jxlEcS3zixgDgUAsiuZ7yrSoa/FX5e0EB2j4= @@ -184,15 +233,16 @@ github.com/json-iterator/go v1.1.6/go.mod h1:+SdeFBvtyEkXs7REEP0seUULqWtbJapLOCV github.com/json-iterator/go v1.1.10/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4= github.com/json-iterator/go v1.1.11/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4= github.com/jstemmer/go-junit-report v0.0.0-20190106144839-af01ea7f8024/go.mod h1:6v2b51hI/fHJwM22ozAgKL4VKDeJcHhJFhtBdhmNjmU= +github.com/jstemmer/go-junit-report v0.9.1/go.mod h1:Brl9GWCQeLvo8nXZwPNNblvFj/XSXhF0NWZEnDohbsk= github.com/jtolds/gls v4.20.0+incompatible/go.mod h1:QJZ7F/aHp+rZTRtaJ1ow/lLfFfVYBRgL+9YlvaHOwJU= github.com/julienschmidt/httprouter v1.2.0/go.mod h1:SYymIcj16QtmaHHD7aYtjjsJG7VTCxuUUipMqKk8s4w= github.com/julienschmidt/httprouter v1.3.0/go.mod h1:JR6WtHb+2LUe8TCKY3cZOxFyyO8IZAc4RVcycCCAKdM= -github.com/kisielk/errcheck v1.1.0/go.mod h1:EZBBE59ingxPouuu3KfxchcWSUPOHkagtvWXihfKN4Q= github.com/kisielk/errcheck v1.2.0/go.mod h1:/BMXB+zMLi60iA8Vv6Ksmxu/1UDYcXs4uQLJ+jE2L00= github.com/kisielk/errcheck v1.5.0/go.mod h1:pFxgyoBC7bSaBwPgfKdkLd5X25qrDl4LWUI2bnpBCr8= github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck= github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= github.com/konsorten/go-windows-terminal-sequences v1.0.3/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= +github.com/kr/fs v0.1.0/go.mod h1:FFnZGqtBN9Gxj7eW1uZ42v5BccTP0vu6NEaFoC2HwRg= github.com/kr/logfmt v0.0.0-20140226030751-b84e30acd515/go.mod h1:+0opPa2QZZtGFBFZlji/RkVcI2GknAs/DXo4wKdlNEc= github.com/kr/pretty v0.1.0 h1:L/CwN0zerZDmRFUapSPitk6f+Q3+0za1rQkzVuMiMFI= github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo= @@ -200,7 +250,7 @@ github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY= github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE= -github.com/magiconair/properties v1.8.1/go.mod h1:PppfXfuXeibc/6YijjN8zIbojt8czPbwD3XqdrwzmxQ= +github.com/magiconair/properties v1.8.5/go.mod h1:y3VJvCyxH9uVvJTWEGAELF3aiYNyPKd5NZ3oSwXrF60= github.com/mattn/go-colorable v0.0.9/go.mod h1:9vuHe8Xs5qXnSaW/c/ABM9alt+Vo+STaOChaDxuIBZU= github.com/mattn/go-isatty v0.0.3/go.mod h1:M+lRXTBqGeGNdLjl/ufCoiOlB5xdOkqRJdNxMWT7Zi4= github.com/matttproud/golang_protobuf_extensions v1.0.1 h1:4hp9jkHxhMHkqkrB3Ix0jegS5sx/RkqARlsWZ6pIwiU= @@ -208,31 +258,30 @@ github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5 github.com/miekg/dns v1.0.14/go.mod h1:W1PPwlIAgtquWBMBEV9nkV9Cazfe8ScdGz/Lj7v3Nrg= github.com/mitchellh/cli v1.0.0/go.mod h1:hNIlj7HEI86fIcpObd7a0FcrxTWetlwJDGcceTlRvqc= github.com/mitchellh/go-homedir v1.0.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0= -github.com/mitchellh/go-homedir v1.1.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0= github.com/mitchellh/go-testing-interface v1.0.0/go.mod h1:kRemZodwjscx+RGhAo8eIhFbs2+BFgRtFPeD/KE+zxI= github.com/mitchellh/gox v0.4.0/go.mod h1:Sd9lOJ0+aimLBi73mGofS1ycjY8lL3uZM3JPS42BGNg= github.com/mitchellh/iochan v1.0.0/go.mod h1:JwYml1nuB7xOzsp52dPpHFffvOCDupsG0QubkSMEySY= github.com/mitchellh/mapstructure v0.0.0-20160808181253-ca63d7c062ee/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y= github.com/mitchellh/mapstructure v1.1.2/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y= +github.com/mitchellh/mapstructure v1.4.1/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo= github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= github.com/modern-go/reflect2 v0.0.0-20180701023420-4b7aa43c6742/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0= github.com/modern-go/reflect2 v1.0.1/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0= github.com/mwitkow/go-conntrack v0.0.0-20161129095857-cc309e4a2223/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U= github.com/mwitkow/go-conntrack v0.0.0-20190716064945-2f068394615f/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U= -github.com/oklog/ulid v1.3.1/go.mod h1:CirwcVhetQ6Lv90oh/F+FBtV6XMibvdAFo93nm5qn4U= github.com/opentracing/opentracing-go v1.1.0/go.mod h1:UkNAQd3GIcIGf0SeVgPpRdFStlNbqXla1AfSYxPUl2o= github.com/pascaldekloe/goe v0.0.0-20180627143212-57f6aae5913c/go.mod h1:lzWF7FIEvWOWxwDKqyGYQf6ZUaNfKdP144TG7ZOy1lc= -github.com/pelletier/go-toml v1.2.0/go.mod h1:5z9KED0ma1S8pY6P1sdut58dfprrGBbd/94hg7ilaic= +github.com/pelletier/go-toml v1.9.3/go.mod h1:u1nR/EPcESfeI/szUZKdtJ0xRNbUoANCkoOuaOx1Y+c= github.com/pkg/errors v0.8.0/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4= github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= +github.com/pkg/sftp v1.10.1/go.mod h1:lYOWFsE0bwd1+KfKJaKeuokY15vzFx25BLbzYYoAxZI= github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= github.com/posener/complete v1.1.1/go.mod h1:em0nMJCgc9GFtwrmVmEMR/ZL6WyhyjMBndrE9hABlRI= github.com/prometheus/client_golang v0.9.1/go.mod h1:7SWBe2y4D6OKWSNQJUaRYU/AaXPKyh/dDVn+NZz0KFw= -github.com/prometheus/client_golang v0.9.3/go.mod h1:/TN21ttK/J9q6uSwhBd54HahCDft0ttaMvbicHlPoso= github.com/prometheus/client_golang v1.0.0/go.mod h1:db9x61etRT2tGnBNRi70OPL5FsnadC4Ky3P0J6CfImo= github.com/prometheus/client_golang v1.7.1/go.mod h1:PY5Wy2awLA44sXw4AOSfFBetzPP4j5+D6mVACh+pe2M= github.com/prometheus/client_golang v1.11.0 h1:HNkLOAEQMIDv/K+04rukrLx6ch7msSRwf3/SASFAGtQ= @@ -242,20 +291,15 @@ github.com/prometheus/client_model v0.0.0-20190129233127-fd36f4220a90/go.mod h1: github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= github.com/prometheus/client_model v0.2.0 h1:uq5h0d+GuxiXLJLNABMgp2qUWDPiLvgCzz2dUR+/W/M= github.com/prometheus/client_model v0.2.0/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= -github.com/prometheus/common v0.0.0-20181113130724-41aa239b4cce/go.mod h1:daVV7qP5qjZbuso7PdcryaAu0sAZbrN9i7WWcTMWvro= -github.com/prometheus/common v0.4.0/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y86RQel1bk4= github.com/prometheus/common v0.4.1/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y86RQel1bk4= github.com/prometheus/common v0.10.0/go.mod h1:Tlit/dnDKsSWFlCLTWaA1cyBgKHSMdTB80sz/V91rCo= github.com/prometheus/common v0.26.0 h1:iMAkS2TDoNWnKM+Kopnx/8tnEStIfpYA0ur0xQzzhMQ= github.com/prometheus/common v0.26.0/go.mod h1:M7rCNAaPfAosfx8veZJCuw84e35h3Cfd9VFqTh1DIvc= github.com/prometheus/procfs v0.0.0-20181005140218-185b4288413d/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk= -github.com/prometheus/procfs v0.0.0-20190507164030-5867b95ac084/go.mod h1:TjEm7ze935MbeOT/UhFTIMYKhuLP4wbCsTZCD3I8kEA= github.com/prometheus/procfs v0.0.2/go.mod h1:TjEm7ze935MbeOT/UhFTIMYKhuLP4wbCsTZCD3I8kEA= github.com/prometheus/procfs v0.1.3/go.mod h1:lV6e/gmhEcM9IjHGsFOCxxuZ+z1YqCvr4OA4YeYWdaU= github.com/prometheus/procfs v0.6.0 h1:mxy4L2jP6qMonqmq+aTtOx1ifVWUgG/TAmntgbh3xv4= github.com/prometheus/procfs v0.6.0/go.mod h1:cz+aTbrPOrUb4q7XlbU9ygM+/jj0fzG6c1xBZuNvfVA= -github.com/prometheus/tsdb v0.7.1/go.mod h1:qhTCs0VvXwvX/y3TZrWD7rabWM+ijKTux40TwIPHuXU= -github.com/rogpeppe/fastuuid v0.0.0-20150106093220-6724a57986af/go.mod h1:XWv6SoW27p1b0cqNHllgS5HIMJraePCO15w5zCzIWYg= github.com/rogpeppe/fastuuid v1.2.0/go.mod h1:jVj6XXZzXRy/MSR5jhDC/2q6DgLz+nrA6LYCDYWNEvQ= github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4= github.com/russross/blackfriday/v2 v2.0.1/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= @@ -269,40 +313,44 @@ github.com/sirupsen/logrus v1.8.1 h1:dJKuHgqk1NNQlqoA6BTlM1Wf9DOH3NBjQyu0h9+AZZE github.com/sirupsen/logrus v1.8.1/go.mod h1:yWOB1SBYBC5VeMP7gHvWumXLIWorT60ONWic61uBYv0= github.com/smartystreets/assertions v0.0.0-20180927180507-b2de0cb4f26d/go.mod h1:OnSkiWE9lh6wB0YB77sQom3nweQdgAjqCqsofrRNTgc= github.com/smartystreets/goconvey v1.6.4/go.mod h1:syvi0/a8iFYH4r/RixwvyeAJjdLS9QV7WQ/tjFTllLA= -github.com/soheilhy/cmux v0.1.4/go.mod h1:IM3LyeVVIOuxMH7sFAkER9+bJ4dT7Ms6E4xg4kGIyLM= github.com/soheilhy/cmux v0.1.5 h1:jjzc5WVemNEDTLwv9tlmemhC73tI08BNOIGwBOo10Js= github.com/soheilhy/cmux v0.1.5/go.mod h1:T7TcVDs9LWfQgPlPsdngu6I6QIoyIFZDDC6sNE1GqG0= github.com/spaolacci/murmur3 v0.0.0-20180118202830-f09979ecbc72/go.mod h1:JwIasOWyU6f++ZhiEuf87xNszmSA2myDM2Kzu9HwQUA= -github.com/spf13/afero v1.1.2/go.mod h1:j4pytiNVoe2o6bmDsKpLACNPDBIoEAkihy7loJ1B0CQ= -github.com/spf13/cast v1.3.0/go.mod h1:Qx5cxh0v+4UWYiBimWS+eyWzqEqokIECu5etghLkUJE= -github.com/spf13/cobra v1.1.3 h1:xghbfqPkxzxP3C/f3n5DdpAbdKLj4ZE4BWQI362l53M= -github.com/spf13/cobra v1.1.3/go.mod h1:pGADOWyqRD/YMrPZigI/zbliZ2wVD/23d+is3pSWzOo= -github.com/spf13/jwalterweatherman v1.0.0/go.mod h1:cQK4TGJAtQXfYWX+Ddv3mKDzgVb68N+wFjFa4jdeBTo= -github.com/spf13/pflag v1.0.3/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4= +github.com/spf13/afero v1.6.0/go.mod h1:Ai8FlHk4v/PARR026UzYexafAt9roJ7LcLMAmO6Z93I= +github.com/spf13/cast v1.3.1/go.mod h1:Qx5cxh0v+4UWYiBimWS+eyWzqEqokIECu5etghLkUJE= +github.com/spf13/cobra v1.2.1 h1:+KmjbUw1hriSNMF55oPrkZcb27aECyrj8V2ytv7kWDw= +github.com/spf13/cobra v1.2.1/go.mod h1:ExllRjgxM/piMAM+3tAZvg8fsklGAf3tPfi+i8t68Nk= +github.com/spf13/jwalterweatherman v1.1.0/go.mod h1:aNWZUN0dPAAO/Ljvb5BEdw96iTZ0EXowPYD95IqWIGo= github.com/spf13/pflag v1.0.5 h1:iy+VFUOCP1a+8yFto/drg2CJ5u0yRoB7fZw3DKv/JXA= github.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg= -github.com/spf13/viper v1.7.0/go.mod h1:8WkrPz2fc9jxqZNCJI/76HCieCp4Q8HaLFoCha5qpdg= +github.com/spf13/viper v1.8.1/go.mod h1:o0Pch8wJ9BVSWGQMbra6iw0oQ5oktSIBaujf1rJH9Ns= github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= 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.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA= +github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/stretchr/testify v1.7.0 h1:nwc3DEeHmmLAfoZucVR881uASk0Mfjw8xYJ99tb5CcY= github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/subosito/gotenv v1.2.0/go.mod h1:N0PQaV/YGNqwC0u51sEeR/aUtSLEXKX9iv69rRypqCw= -github.com/tmc/grpc-websocket-proxy v0.0.0-20190109142713-0ad062ec5ee5/go.mod h1:ncp9v5uamzpCO7NfCPTXjqaC+bZgJeR0sMTm6dMHP7U= github.com/tmc/grpc-websocket-proxy v0.0.0-20201229170055-e5319fda7802 h1:uruHq4dN7GR16kFc5fp3d1RIYzJW5onx8Ybykw2YQFA= github.com/tmc/grpc-websocket-proxy v0.0.0-20201229170055-e5319fda7802/go.mod h1:ncp9v5uamzpCO7NfCPTXjqaC+bZgJeR0sMTm6dMHP7U= github.com/xiang90/probing v0.0.0-20190116061207-43a291ad63a2 h1:eY9dn8+vbi4tKz5Qo6v2eYzo7kUS51QINcR5jNpbZS8= github.com/xiang90/probing v0.0.0-20190116061207-43a291ad63a2/go.mod h1:UETIi67q53MR2AWcXfiuqkDkRtnGDLqkBTpCHuJHxtU= +github.com/yuin/goldmark v1.1.25/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= +github.com/yuin/goldmark v1.1.32/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= -go.etcd.io/bbolt v1.3.2/go.mod h1:IbVyRI1SCnLcuJnV2u8VeU0CEYM7e686BmAb1XKL+uU= go.etcd.io/bbolt v1.3.6 h1:/ecaJf0sk1l4l6V4awd65v2C3ILy7MSj+s/x1ADCIMU= go.etcd.io/bbolt v1.3.6/go.mod h1:qXsaaIqmgQH0T+OPdb99Bf+PKfBBQVAdyD6TY9G8XM4= 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.2/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.5/go.mod h1:5pWMHQbX5EPX2/62yrJeAkowc+lfs/XD7Uxpq3pI6kk= +go.opencensus.io v0.23.0/go.mod h1:XItmlyltB5F7CS4xOC1DcqMoFqwtC6OG2xF7mCv7P7E= go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.26.1 h1:puWrOArBwWlr5dq6vyZ6fKykHyS8JgMIVhTBA8XsGuU= go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.26.1/go.mod h1:4wsfAAW5N9wUHM0QTmZS8z7fvYZ1rv3m+sVeSpf8NhU= go.opentelemetry.io/otel v1.1.0/go.mod h1:7cww0OW51jQ8IaZChIEdqLwgh+44+7uiTdWsAL0wQpA= @@ -337,6 +385,7 @@ golang.org/x/crypto v0.0.0-20181029021203-45a5f77698d3/go.mod h1:6SG95UA2DQfeDnf golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= golang.org/x/crypto v0.0.0-20190510104115-cbcb75029529/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20190605123033-f99c8df09eb5/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= +golang.org/x/crypto v0.0.0-20190820162420-60c769a6c586/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= golang.org/x/crypto v0.0.0-20210513164829-c07d793c2f9a h1:kr2P4QFmQr29mSLA43kwrOcgcReGTfbE9N577tCTuBc= @@ -346,6 +395,11 @@ golang.org/x/exp v0.0.0-20190306152737-a1d7652674e8/go.mod h1:CJ0aWSM057203Lf6IL golang.org/x/exp v0.0.0-20190510132918-efd6b22b2522/go.mod h1:ZjyILWgesfNpC6sMxTJOJm9Kp84zZh5NQWvqDGG3Qr8= golang.org/x/exp v0.0.0-20190829153037-c13cbed26979/go.mod h1:86+5VVa7VpoJ4kLfm080zCjGlMRFzhUhsZKEZO7MGek= golang.org/x/exp v0.0.0-20191030013958-a1ab85dbe136/go.mod h1:JXzH8nQsPlswgeRAPE3MuO9GYsAcnJvJ4vnMwN/5qkY= +golang.org/x/exp v0.0.0-20191129062945-2f5052295587/go.mod h1:2RIsYlXP63K8oxa1u096TMicItID8zy7Y6sNkU49FU4= +golang.org/x/exp v0.0.0-20191227195350-da58074b4299/go.mod h1:2RIsYlXP63K8oxa1u096TMicItID8zy7Y6sNkU49FU4= +golang.org/x/exp v0.0.0-20200119233911-0405dc783f0a/go.mod h1:2RIsYlXP63K8oxa1u096TMicItID8zy7Y6sNkU49FU4= +golang.org/x/exp v0.0.0-20200207192155-f17229e696bd/go.mod h1:J/WKrq2StrnmMY6+EHIKF9dgMWnmCNThgcyBT1FY9mM= +golang.org/x/exp v0.0.0-20200224162631-6cc2880d07d6/go.mod h1:3jZMyOhIsHpP37uCMkUooju7aAi5cS1Q23tOzKc+0MU= golang.org/x/image v0.0.0-20190227222117-0694c2d4d067/go.mod h1:kZ7UVZpmo3dzQBMxlp+ypCbDeSB+sBbTgSJuh5dn5js= golang.org/x/image v0.0.0-20190802002840-cff245a6509b/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0= golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE= @@ -355,18 +409,25 @@ golang.org/x/lint v0.0.0-20190313153728-d0100b6bd8b3/go.mod h1:6SW0HCj/g11FgYtHl golang.org/x/lint v0.0.0-20190409202823-959b441ac422/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= golang.org/x/lint v0.0.0-20190909230951-414d861bb4ac/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= golang.org/x/lint v0.0.0-20190930215403-16217165b5de/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= +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-20200302205851-738671d3881b/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY= +golang.org/x/lint v0.0.0-20201208152925-83fdc39ff7b5/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-20190719004257-d2bd2a29d028/go.mod h1:E/iHnbuqvinMTCcRqshq8CkpyQDoeVncDDYHnLhea+o= golang.org/x/mod v0.0.0-20190513183733-4bf6d317e70e/go.mod h1:mXi4GBBbnImb6dmsKGUJ2LatrhH/nqhxcFungHvyanc= golang.org/x/mod v0.1.0/go.mod h1:0QHyrYULN0/3qlju5TqG8bIK38QM8yzMo5ekMj3DlcY= +golang.org/x/mod v0.1.1-0.20191105210325-c90efee705ee/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.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/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-20181023162649-9b4f9f5ad519/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20181114220301-adae6a3d119a/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20181201002055-351d144fa1fc/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= -golang.org/x/net v0.0.0-20181220203305-927f97764cc3/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20190108225652-1e06a53dbb7e/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20190213061140-3a22650c66bd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= @@ -376,33 +437,61 @@ golang.org/x/net v0.0.0-20190503192946-f4e77d36d62c/go.mod h1:t9HGtf8HONx5eT2rtn golang.org/x/net v0.0.0-20190603091049-60506f45cf65/go.mod h1:HSz+uSET+XFnRR8LxR5pz3Of3rY3CfYBVs4xY44aLks= golang.org/x/net v0.0.0-20190613194153-d28f0bde5980/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20190628185345-da137c7871d7/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20190724013045-ca1201d0de80/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20191209160850-c0dbc17a3553/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20200114155413-6afb5195e5aa/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20200202094626-16171245cfb2/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20200222125558-5a598a2470a0/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20200226121028-0de0cce0169b/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20200301022130-244492dfa37a/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20200324143707-d3edc9973b7e/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= +golang.org/x/net v0.0.0-20200501053045-e0ff5e5a1de5/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= +golang.org/x/net v0.0.0-20200506145744-7e3656a0809f/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= +golang.org/x/net v0.0.0-20200513185701-a91f0712d120/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= +golang.org/x/net v0.0.0-20200520182314-0ba52f642ac2/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= golang.org/x/net v0.0.0-20200625001655-4c5254603344/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-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-20201202161906-c7110b5ffcbb/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-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-20211123203042-d83791d6bcd9 h1:0qxwC5n+ttVOINCBeRHO0nq9X7uy8SDsPoi5OaCdIEI= golang.org/x/net v0.0.0-20211123203042-d83791d6bcd9/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= 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-20190604053449-0f29369cfe45/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= -golang.org/x/oauth2 v0.0.0-20200107190931-bf48bf16ab8d h1:TzXSXBo42m9gQenoE3b9BGiEpg5IG2JkU5FkPIawgtw= +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-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-20210402161424-2e8d93401602 h1:0Ja1LBD+yisY6RWM/BH7TJVXWsSjs2VwBSmvSX4HdBc= +golang.org/x/oauth2 v0.0.0-20210402161424-2e8d93401602/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= 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-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20190227155943-e225da77a7e6/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20200317015054-43a5402ce75a/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20200625203802-6e8e738ad208/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-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sys v0.0.0-20180823144017-11551d06cbcc/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20181026203630-95b1ffbd15a5/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= -golang.org/x/sys v0.0.0-20181107165924-66b7b1311ac8/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20181116152217-5ac8a444bdc5/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190312061237-fead79001313/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= @@ -412,16 +501,42 @@ golang.org/x/sys v0.0.0-20190502145724-3ef323f4f1fd/go.mod h1:h1NjWce9XRLGQEsW7w golang.org/x/sys v0.0.0-20190507160741-ecd444e8653b/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190606165138-5da285871e9c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190624142023-c5567b49c5d0/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190726091711-fc99dfbffb4e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20191001151750-bb3f8db39f24/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20191005200804-aed5e4c7ecf9/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20191026070338-33540a1f6037/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20191204072324-ce4227a45e2e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20191228213918-04cbcbbfeed8/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200106162015-b016eb3dc98e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200113162924-86b910548bc1/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200122134326-e047566fdf82/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200202164722-d101bd2416d5/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200212091648-12a6c2dcc1e4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200223170610-d5e6a3e2c0ae/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200302150141-5c8b2ff67527/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200331124033-c3d80250170d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200501052902-10377860bb8e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200511232937-7e40ca221e25/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200515095857-1151b9dac4a9/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200523222454-059865788121/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-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-20200923182605-d9f96fdee20d/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-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-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-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-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-20210423185535-09eb48e85fd7/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210510120138-977fb7262007/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= @@ -430,19 +545,21 @@ golang.org/x/sys v0.0.0-20210603125802-9665404d3644/go.mod h1:oPkhp1MJrh7nUepCBc golang.org/x/sys v0.0.0-20211123173158-ef496fb156ab h1:rfJ1bsoJQQIAoAxTxB7bme+vHrNkRw8CqfsYh9w54cw= golang.org/x/sys v0.0.0-20211123173158-ef496fb156ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= +golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.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.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.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/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-20191024005414-555d28b269f0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.0.0-20210220033141-f8bda1e9f3ba h1:O8mE0/t419eoIwhTFpKVkHiTs/Igowgfkj25AcZrtiE= golang.org/x/time v0.0.0-20210220033141-f8bda1e9f3ba/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= -golang.org/x/tools v0.0.0-20180221164845-07fd8470d635/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-20181030221726-6c7e314b6563/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20190114222345-bf090417da8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= @@ -461,9 +578,39 @@ golang.org/x/tools v0.0.0-20190816200558-6889da9d5479/go.mod h1:b+2E5dAYhXwXZwtn golang.org/x/tools v0.0.0-20190911174233-4f2ddba30aff/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.0.0-20191012152004-8de300cfc20a/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.0.0-20191112195655-aa38f8e97acc/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-20191113191852-77e3bb0ad9e7/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-20191115202509-3a792d9c32b2/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-20191125144606-a911d9008d1f/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-20191130070609-6e064ea0cf2d/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-20191216173652-a0e659d51361/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= +golang.org/x/tools v0.0.0-20191227053925-7b8e75db28f4/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= +golang.org/x/tools v0.0.0-20200117161641-43d50277825c/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= +golang.org/x/tools v0.0.0-20200122220014-bf1340f18c4a/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= +golang.org/x/tools v0.0.0-20200130002326-2f3ba24bd6e7/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= +golang.org/x/tools v0.0.0-20200204074204-1cc6d1ef6c74/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= +golang.org/x/tools v0.0.0-20200207183749-b753a1ba74fa/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= +golang.org/x/tools v0.0.0-20200212150539-ea181f53ac56/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= +golang.org/x/tools v0.0.0-20200224181240-023911ca70b2/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= +golang.org/x/tools v0.0.0-20200227222343-706bc42d1f0d/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= +golang.org/x/tools v0.0.0-20200304193943-95d2e580d8eb/go.mod h1:o4KQGtdN14AW+yjsvvwRTJJuXz8XRtIHtEnmAXLyFUw= +golang.org/x/tools v0.0.0-20200312045724-11d5b4c81c7d/go.mod h1:o4KQGtdN14AW+yjsvvwRTJJuXz8XRtIHtEnmAXLyFUw= +golang.org/x/tools v0.0.0-20200331025713-a30bf2db82d4/go.mod h1:Sl4aGygMT6LrqrWclx+PTx3U+LnKx/seiNR+3G19Ar8= +golang.org/x/tools v0.0.0-20200501065659-ab2804fb9c9d/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= +golang.org/x/tools v0.0.0-20200512131952-2bc93b1c0c88/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= +golang.org/x/tools v0.0.0-20200515010526-7d3b6ebf133d/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= +golang.org/x/tools v0.0.0-20200618134242-20370b0cb4b2/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= golang.org/x/tools v0.0.0-20200619180055-7c47624df98f/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= +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-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-20210105154028-b0ab187a4818/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/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-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= @@ -474,11 +621,31 @@ google.golang.org/api v0.7.0/go.mod h1:WtwebWUNSVBH/HAw79HIFXZNqEvBhG+Ra+ax0hx3E google.golang.org/api v0.8.0/go.mod h1:o4eAsZoiT+ibD93RtjEohWalFOjRDx6CVaqeizhEnKg= google.golang.org/api v0.9.0/go.mod h1:o4eAsZoiT+ibD93RtjEohWalFOjRDx6CVaqeizhEnKg= google.golang.org/api v0.13.0/go.mod h1:iLdEw5Ide6rF15KTC1Kkl0iskquN2gFfn9o9XIsbkAI= +google.golang.org/api v0.14.0/go.mod h1:iLdEw5Ide6rF15KTC1Kkl0iskquN2gFfn9o9XIsbkAI= +google.golang.org/api v0.15.0/go.mod h1:iLdEw5Ide6rF15KTC1Kkl0iskquN2gFfn9o9XIsbkAI= +google.golang.org/api v0.17.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE= +google.golang.org/api v0.18.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE= +google.golang.org/api v0.19.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE= +google.golang.org/api v0.20.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE= +google.golang.org/api v0.22.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE= +google.golang.org/api v0.24.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.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.44.0/go.mod h1:EBOGZqzyhtvMDoxwS97ctnh0zUmYY6CxqXsc1AvkYD8= 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.5.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= -google.golang.org/appengine v1.6.1 h1:QzqyMA1tlu6CgqCDUtU9V+ZKhLFT2dkJuANu5QaxI3I= google.golang.org/appengine v1.6.1/go.mod h1:i06prIuMbXzDqacNJfV5OdTW448YApPu5ww/cMBSeb0= +google.golang.org/appengine v1.6.5/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-20190307195333-5fe7a883aa19/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= google.golang.org/genproto v0.0.0-20190418145605-e7d98fc518a7/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= @@ -488,9 +655,38 @@ google.golang.org/genproto v0.0.0-20190801165951-fa694d86fc64/go.mod h1:DMBHOl98 google.golang.org/genproto v0.0.0-20190819201941-24fa4b261c55/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc= google.golang.org/genproto v0.0.0-20190911173649-1774047e7e51/go.mod h1:IbNlFCBrqXvoKpeg0TB2l7cyZUmoaFKYIwrEpbDKLA8= google.golang.org/genproto v0.0.0-20191108220845-16a3f7862a1a/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= +google.golang.org/genproto v0.0.0-20191115194625-c23dd37a84c9/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= +google.golang.org/genproto v0.0.0-20191216164720-4f79533eabd1/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= +google.golang.org/genproto v0.0.0-20191230161307-f3c370f40bfb/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= +google.golang.org/genproto v0.0.0-20200115191322-ca5a22157cba/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= +google.golang.org/genproto v0.0.0-20200122232147-0452cf42e150/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= +google.golang.org/genproto v0.0.0-20200204135345-fa8e72b47b90/go.mod h1:GmwEX6Z4W5gMy59cAlVYjN9JhxgbQH6Gn+gFDQe2lzA= +google.golang.org/genproto v0.0.0-20200212174721-66ed5ce911ce/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= +google.golang.org/genproto v0.0.0-20200224152610-e50cd9704f63/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= +google.golang.org/genproto v0.0.0-20200228133532-8c2c7df3a383/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= +google.golang.org/genproto v0.0.0-20200305110556-506484158171/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= +google.golang.org/genproto v0.0.0-20200312145019-da6875a35672/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= +google.golang.org/genproto v0.0.0-20200331122359-1ee6d9798940/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= google.golang.org/genproto v0.0.0-20200423170343-7949de9c1215/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= +google.golang.org/genproto v0.0.0-20200430143042-b979b6f78d84/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= +google.golang.org/genproto v0.0.0-20200511104702-f5ebc3bea380/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= google.golang.org/genproto v0.0.0-20200513103714-09dca8ec2884/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= +google.golang.org/genproto v0.0.0-20200515170657-fc4c6c6a6587/go.mod h1:YsZOwe1myG/8QRHRsmBRE1LrgQY60beZKjly0O1fX9U= google.golang.org/genproto v0.0.0-20200526211855-cb27e3aa2013/go.mod h1:NbSheEEYHJ7i3ixzK3sjbqSGDJWnxyFXZblF3eUsNvo= +google.golang.org/genproto v0.0.0-20200618031413-b414f8b61790/go.mod h1:jDfRM7FcilCzHH/e9qn6dsT145K34l5v+OpcnNgKAAA= +google.golang.org/genproto v0.0.0-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-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-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-20210402141018-6c239bbf2bb1/go.mod h1:9lPAdzaEmUacj36I+k7YKbEc5CXzPIeORRgDAUOu28A= google.golang.org/genproto v0.0.0-20211118181313-81c1377c94b1 h1:b9mVrqYfq3P4bCdaLg1qtBnPzUYgglsIdjZkL/fQVOE= google.golang.org/genproto v0.0.0-20211118181313-81c1377c94b1/go.mod h1:5CzLGKJ67TSI2B9POpiiyGha0AjJvZIUgRMt1dSmuhc= google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c= @@ -498,11 +694,22 @@ google.golang.org/grpc v1.20.1/go.mod h1:10oTOabMzJvdu6/UiuZezV6QK5dSlG84ov/aaiq google.golang.org/grpc v1.21.1/go.mod h1:oYelfM1adQP15Ek0mdvEgi9Df8B9CZIaU1084ijfRaM= google.golang.org/grpc v1.23.0/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg= google.golang.org/grpc v1.25.1/go.mod h1:c3i+UQWmh7LiEpx4sFZnkU36qjEYZ0imhYfXVyQciAY= +google.golang.org/grpc v1.26.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk= google.golang.org/grpc v1.27.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk= +google.golang.org/grpc v1.27.1/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk= +google.golang.org/grpc v1.28.0/go.mod h1:rpkK4SK4GF4Ach/+MFLZUBavHOvF2JJB5uozKKal+60= 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.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.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.1/go.mod h1:qjiiYl8FncCW8feJPdyg3v6XW24KsRHe+dy9BAGRRjU= 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.40.0/go.mod h1:ogyxbiOoUXAkP+4+xa6PZSE9DZgIHtSpzjDTB9KAK34= google.golang.org/grpc v1.41.0 h1:f+PlOh7QV4iIJkPrx5NQ7qaNGFQ3OTse67yaDHfju4E= google.golang.org/grpc v1.41.0/go.mod h1:U3l9uK9J0sini8mHphKoXyaqDA/8VyGnDee1zzIUK6k= @@ -514,6 +721,7 @@ google.golang.org/protobuf v1.21.0/go.mod h1:47Nbq4nVaFHyn7ilMalzfO3qCViNmqZ2kzi google.golang.org/protobuf v1.22.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= google.golang.org/protobuf v1.23.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= google.golang.org/protobuf v1.23.1-0.20200526195155-81db48ad09cc/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= +google.golang.org/protobuf v1.24.0/go.mod h1:r/3tXBNzIEhYS9I1OUVjXDlt8tc493IdKGjtUeSXeh4= google.golang.org/protobuf v1.25.0/go.mod h1:9JNX74DMeImyA3h4bdi1ymwjUzf21/xIlbajtzgsN7c= google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw= google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc= @@ -525,11 +733,9 @@ gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8 gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15 h1:YR8cESwS4TdDjEe65xsg0ogRM/Nc3DYOhEAlW+xobZo= gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/errgo.v2 v2.1.0/go.mod h1:hNsd1EY+bozCKY1Ytp96fpM3vjJbqLJn88ws8XvfDNI= -gopkg.in/ini.v1 v1.51.0/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k= +gopkg.in/ini.v1 v1.62.0/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k= gopkg.in/natefinch/lumberjack.v2 v2.0.0 h1:1Lc07Kr7qY4U2YPouBjpCLxpiyxIVoxqXgkXLknAOE8= gopkg.in/natefinch/lumberjack.v2 v2.0.0/go.mod h1:l0ndWWf7gzL7RNwBG7wST/UCcT4T24xpD6X8LsfU/+k= -gopkg.in/resty.v1 v1.12.0/go.mod h1:mDo4pnntr5jdWRML875a/NmxYqAlA73dVijT2AXvQQo= -gopkg.in/yaml.v2 v2.0.0-20170812160011-eb3733d160e7/go.mod h1:JAlM8MvJe8wmxCU4Bli9HhUf9+ttbYbLASfIpnQbh74= gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.2.3/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= @@ -547,7 +753,11 @@ honnef.co/go/tools v0.0.0-20190106161140-3f1c8253044a/go.mod h1:rf3lG4BRIbNafJWh honnef.co/go/tools v0.0.0-20190418001031-e561f6794a2a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= honnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= honnef.co/go/tools v0.0.1-2019.2.3/go.mod h1:a3bituU0lyd329TUQxRnasdCoJDkEUEAqEt0JzvZhAg= +honnef.co/go/tools v0.0.1-2020.1.3/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9vFzvIQ3k= +honnef.co/go/tools v0.0.1-2020.1.4/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9vFzvIQ3k= 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/sampler v1.3.0/go.mod h1:T1hPZKmBbMNahiBKFy5HrXp6adAjACjK9JXDnKaTXpA= sigs.k8s.io/json v0.0.0-20211020170558-c049b76a60c6 h1:fD1pz4yfdADVNfFmcP2aBEtudwUQ1AlLnRBALr33v3s= sigs.k8s.io/json v0.0.0-20211020170558-c049b76a60c6/go.mod h1:p4QtZmO4uMYipTQNzagwnNoseA6OxSUutVw05NhYDRs= sigs.k8s.io/yaml v1.2.0 h1:kr/MCeFWJWTwyaHoR9c8EjH9OumOmoF9YGiZd7lFm/Q= diff --git a/tests/go.mod b/tests/go.mod index c731dbc22edd..e3da092bd9e0 100644 --- a/tests/go.mod +++ b/tests/go.mod @@ -24,7 +24,7 @@ require ( github.com/grpc-ecosystem/grpc-gateway v1.16.0 github.com/prometheus/client_golang v1.11.0 github.com/soheilhy/cmux v0.1.5 - github.com/spf13/cobra v1.1.3 + github.com/spf13/cobra v1.2.1 github.com/spf13/pflag v1.0.5 github.com/stretchr/testify v1.7.0 go.etcd.io/bbolt v1.3.6 diff --git a/tests/go.sum b/tests/go.sum index 12df68590eaf..f519405c9d2f 100644 --- a/tests/go.sum +++ b/tests/go.sum @@ -4,13 +4,39 @@ cloud.google.com/go v0.38.0/go.mod h1:990N+gfupTy94rShfmMCWGDn0LpTmnzTp2qbd1dvSR cloud.google.com/go v0.44.1/go.mod h1:iSa0KzasP4Uvy3f1mN/7PiObzGgflwredwwASm/v6AU= cloud.google.com/go v0.44.2/go.mod h1:60680Gw3Yr4ikxnPRS/oxxkBccT6SA1yMk63TGekxKY= cloud.google.com/go v0.45.1/go.mod h1:RpBamKRgapWJb87xiFSdk4g1CME7QZg3uwTez+TSTjc= -cloud.google.com/go v0.46.3 h1:AVXDdKsrtX33oR9fbCMu/+c1o8Ofjq6Ku/MInaLVg5Y= cloud.google.com/go v0.46.3/go.mod h1:a6bKKbmY7er1mI7TEI4lsAkts/mkhTSZK8w33B4RAg0= +cloud.google.com/go v0.50.0/go.mod h1:r9sluTvynVuxRIOHXQEHMFffphuXHOMZMycpNR5e6To= +cloud.google.com/go v0.52.0/go.mod h1:pXajvRH/6o3+F9jDHZWQ5PbGhn+o8w9qiu/CffaVdO4= +cloud.google.com/go v0.53.0/go.mod h1:fp/UouUEsRkN6ryDKNW/Upv/JBKnv6WDthjR6+vze6M= +cloud.google.com/go v0.54.0/go.mod h1:1rq2OEkV3YMf6n/9ZvGWI3GWw0VoqH/1x2nd8Is/bPc= +cloud.google.com/go v0.56.0/go.mod h1:jr7tqZxxKOVYizybht9+26Z/gUq7tiRzu+ACVAMbKVk= +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.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 h1:at8Tk2zUz63cLPR0JPWm5vp77pEZmzxEQBEfRKn1VV8= +cloud.google.com/go v0.81.0/go.mod h1:mk/AM35KwGk/Nm2YSeZbxXdrNK3KZOYHmLkOqC2V6E0= 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.4.0/go.mod h1:S8dzgnTigyfTmLBfrtrhyYhwRxG72rYxvftPBK2Dvzc= +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.8.0/go.mod h1:J5hqkt3O0uAFnINi6JXValWIb1v0goeZM77hZzJN/fQ= 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/firestore v1.1.0/go.mod h1:ulACoGHTpvq5r8rxGJ4ddJZBZqakUQqClKRT5SZwBmk= 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.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/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.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.10.0/go.mod h1:FLPqc6j+Ki4BU591ie1oL6qBQGu2Bl/tZ9ullr3+Kg0= dmitri.shuralyov.com/gpu/mtl v0.0.0-20190408044501-666a987793e9/go.mod h1:H6x//7gZCb22OMCxBHrMx7a5I7Hp++hsVxbQ4BYO7hU= github.com/BurntSushi/toml v0.3.1 h1:WXkYYl6Yr3qBf1K79EBnL4mak0OimBfB0XUf9Vl28OQ= github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= @@ -30,7 +56,7 @@ github.com/beorn7/perks v1.0.0/go.mod h1:KWe93zE9D1o94FZ5RNwFwVgaQK1VOXiVxmqh+Ce github.com/beorn7/perks v1.0.1 h1:VlbKKnNfV8bJzeqoa4cOKqO6bYr3WgKZxO8Z16+hsOM= github.com/beorn7/perks v1.0.1/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6rlkpw= github.com/bgentry/speakeasy v0.1.0/go.mod h1:+zsyZBPWlz7T6j88CTgSN5bM796AkVf0kBD4zp0CCIs= -github.com/bketelsen/crypt v0.0.3-0.20200106085610-5cbc8cc4026c/go.mod h1:MKsuJmJgSg28kpZDP6UIiPt0e0Oz0kqKNGyRaWEPv84= +github.com/bketelsen/crypt v0.0.4/go.mod h1:aI6NrJ0pMGgvZKL1iVgXLnfIFJtfV+bKCoqOes/6LfM= github.com/cenkalti/backoff/v4 v4.1.1 h1:G2HAfAmvm/GcKan2oOQpBXOd2tT2G57ZnZGWa1PxPBQ= github.com/cenkalti/backoff/v4 v4.1.1/go.mod h1:scbssz8iZGpm3xbr14ovlUdkxfGXNInqkPWOWmG2CLw= github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU= @@ -41,8 +67,12 @@ github.com/cespare/xxhash v1.1.0 h1:a6HrQnmkObjyL+Gs60czilIUGqrzKutQD6XZog3p+ko= github.com/cespare/xxhash v1.1.0/go.mod h1:XrSqR1VqqWfGrhpAt58auRo0WTKS1nRRg3ghfAqPWnc= github.com/cespare/xxhash/v2 v2.1.1 h1:6MnRN8NT7+YBpUIWxHtefFZOKTAPgGjpQSxqLNn0+qY= github.com/cespare/xxhash/v2 v2.1.1/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= +github.com/chzyer/logex v1.1.10/go.mod h1:+Ywpsq7O8HXn0nuIou7OrIPyXbp3wmkHB+jjWRnGsAI= +github.com/chzyer/readline v0.0.0-20180603132655-2972be24d48e/go.mod h1:nSuG5e5PlCu98SY8svDHJxuZscDgtXS6KTTbou5AhLI= +github.com/chzyer/test v0.0.0-20180213035817-a1ea475d72b1/go.mod h1:Q3SI9o4m/ZMnBNeIyt5eFwwo7qiLfzFZmjNmxjkiQlU= github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw= 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/xds/go v0.0.0-20210312221358-fbca930ec8ed/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs= github.com/cncf/xds/go v0.0.0-20210805033703-aa0b78936158/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs= @@ -52,15 +82,10 @@ github.com/cockroachdb/errors v1.2.4 h1:Lap807SXTH5tri2TivECb/4abUkMZC9zRoLarvcK github.com/cockroachdb/errors v1.2.4/go.mod h1:rQD95gz6FARkaKkQXUksEje/d9a6wBJoCr5oaCLELYA= github.com/cockroachdb/logtags v0.0.0-20190617123548-eb05cc24525f h1:o/kfcElHqOiXqcou5a3rIlMc7oJbMQkeLk0VQJ7zgqY= github.com/cockroachdb/logtags v0.0.0-20190617123548-eb05cc24525f/go.mod h1:i/u985jwjWRlyHXQbwatDASoW0RMlZ/3i9yJHE2xLkI= -github.com/coreos/bbolt v1.3.2/go.mod h1:iRUV2dpdMOn7Bo10OQBFzIJO9kkE559Wcmn+qkEiiKk= -github.com/coreos/etcd v3.3.13+incompatible/go.mod h1:uF7uidLiAD3TWHmW31ZFd/JWoc32PjwdhPthX9715RE= github.com/coreos/go-semver v0.3.0 h1:wkHLiw0WNATZnSG7epLsujiMCgPAc9xhjJ4tgnAxmfM= github.com/coreos/go-semver v0.3.0/go.mod h1:nnelYz7RCh+5ahJtPPxZlU+153eP4D4r3EedlOD2RNk= -github.com/coreos/go-systemd v0.0.0-20190321100706-95778dfbb74e h1:Wf6HqHfScWJN9/ZjdUKyjop4mf3Qdd+1TvvltAvM3m8= -github.com/coreos/go-systemd v0.0.0-20190321100706-95778dfbb74e/go.mod h1:F5haX7vjVVG0kc13fIWeqUViNPyEJxv/OmvnBo0Yme4= github.com/coreos/go-systemd/v22 v22.3.2 h1:D9/bQk5vlXQFZ6Kwuu6zaiXJ9oTPe68++AzAJc1DzSI= github.com/coreos/go-systemd/v22 v22.3.2/go.mod h1:Y58oyj3AT4RCenI/lSvhwexgC+NSVTIJ3seZv2GcEnc= -github.com/coreos/pkg v0.0.0-20180928190104-399ea9e2e55f/go.mod h1:E3G3o1h8I7cfcXa63jLwjI0eiQQMgzzUDFVpN/nH/eA= github.com/cpuguy83/go-md2man/v2 v2.0.0/go.mod h1:maD7wRr/U5Z6m/iR4s+kqSMx2CaBsrgA7czyZG/E6dU= github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E= github.com/creack/pty v1.1.11 h1:07n33Z8lZxZ2qwegKbObQohDhXDQxiMMz1NOUGYlesw= @@ -68,24 +93,25 @@ github.com/creack/pty v1.1.11/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= -github.com/dgrijalva/jwt-go v3.2.0+incompatible/go.mod h1:E3ru+11k8xSBh+hMPgOLZmtrrCbhqsmaPHjLKYnJCaQ= -github.com/dgryski/go-sip13 v0.0.0-20181026042036-e10d5fee7954/go.mod h1:vAd38F8PWV+bWy6jNmig1y/TA+kYO4g3RSRF0IAv0no= github.com/dustin/go-humanize v1.0.0 h1:VSnTsYCnlFHaM2/igO1h6X3HA71jcobQuxemgkq4zYo= github.com/dustin/go-humanize v1.0.0/go.mod h1:HtrtbFcZ19U5GC7JDqmcUSB87Iq5E25KnS6fMYU6eOk= 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.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.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.10-0.20210907150352-cf90f659a021/go.mod h1:AFq3mo9L8Lqqiid3OhADV3RfLJnjiw63cSpi+fDTRC0= github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c= github.com/fatih/color v1.7.0/go.mod h1:Zm6kSWBoL9eyXnKyktHP6abPY2pDugNf5KwzbycvMj4= -github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo= +github.com/fsnotify/fsnotify v1.4.9/go.mod h1:znqG4EE+3YCdAaPaxE2ZRY/06pZUdp0tY4IgpuI1SZQ= github.com/getsentry/raven-go v0.2.0 h1:no+xWJRb5ZI7eE8TWgIq1jLulQiIoLG0IfYxv5JYMGs= github.com/getsentry/raven-go v0.2.0/go.mod h1:KungGk8q33+aIAZUIVWZDr2OfAEBsO49PX4NzFV5kcQ= github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04= github.com/go-gl/glfw v0.0.0-20190409004039-e6da0acd62b1/go.mod h1:vR7hzQXu2zJy9AVAgeJqvqgH9Q5CA+iKCZ2gyEVpxRU= +github.com/go-gl/glfw/v3.3/glfw v0.0.0-20191125211704-12ad95a8df72/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8= +github.com/go-gl/glfw/v3.3/glfw v0.0.0-20200222043503-6f7a984d4dc4/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8= github.com/go-kit/kit v0.8.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as= github.com/go-kit/kit v0.9.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as= github.com/go-kit/log v0.1.0/go.mod h1:zbhenjAZHb184qTLMA9ZjW7ThYL0H2mk7Q6pNt4vbaY= @@ -95,23 +121,31 @@ github.com/go-logfmt/logfmt v0.5.0/go.mod h1:wCYkCAKZfumFQihp8CzCvQ3paCTfi41vtzG github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY= 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.2.1/go.mod h1:hp+jE20tsWTFYpLwKvXlhS1hjn+gTNwPg2I6zVXpSg4= github.com/gogo/protobuf v1.3.1/go.mod h1:SlYgWuQ5SjCEi6WLHjHCa1yvBfUnHcTbrrZtXPKa29o= github.com/gogo/protobuf v1.3.2 h1:Ov1cvc58UF3b5XjBnZv7+opcTcQFZebYjWzi34vdm4Q= github.com/gogo/protobuf v1.3.2/go.mod h1:P1XiOD3dCwIKUDQYPy72D8LYyHL2YPYrpS2s69NZV8Q= github.com/golang-jwt/jwt v3.2.2+incompatible h1:IfV12K8xAKAnZqdXVzCZ+TOjboZ2keLg81eXfW3O+oY= github.com/golang-jwt/jwt v3.2.2+incompatible/go.mod h1:8pz2t5EyA70fFQQSrl6XZXzqecmYZeUEB8OUGHkxJ+I= github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q= -github.com/golang/groupcache v0.0.0-20190129154638-5b532d6fd5ef/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= +github.com/golang/groupcache v0.0.0-20190702054246-869f871628b6/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= +github.com/golang/groupcache v0.0.0-20191227052852-215e87163ea7/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= +github.com/golang/groupcache v0.0.0-20200121045136-8c9f03a8e57e/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da h1:oI5xCqsCo564l8iNU+DwB5epxmsaqB+rhGL0m5jtYqE= github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= github.com/golang/mock v1.1.1/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A= github.com/golang/mock v1.2.0/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A= github.com/golang/mock v1.3.1/go.mod h1:sBzyDLLjw3U8JLTeZvSv8jJB+tU5PVekmnlKIyFUx0Y= +github.com/golang/mock v1.4.0/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.4/go.mod h1:l3mdAwkq5BuhzHwde/uurv3sEJeZMXNpwsxVWU71h+4= +github.com/golang/mock v1.5.0/go.mod h1:CWnOUgYIOo4TcNZ0wHX3YZCqsaM1I1Jvs6v3mP3KVu8= github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= github.com/golang/protobuf v1.3.1/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= github.com/golang/protobuf v1.3.2/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= github.com/golang/protobuf v1.3.3/go.mod h1:vzj43D7+SQXF/4pzW/hwtAqwc6iTitCiVSaWz5lYuqw= +github.com/golang/protobuf v1.3.4/go.mod h1:vzj43D7+SQXF/4pzW/hwtAqwc6iTitCiVSaWz5lYuqw= +github.com/golang/protobuf v1.3.5/go.mod h1:6O5/vntMXwX2lRkT1hjjk0nAC1IDOTvTlVgjlRvqsdk= github.com/golang/protobuf v1.4.0-rc.1/go.mod h1:ceaxUfeHdC40wWswd/P6IGgMaK3YpKi5j83Wpe3EHw8= github.com/golang/protobuf v1.4.0-rc.1.0.20200221234624-67d41d38c208/go.mod h1:xKAWHe0F5eneWXFV3EuXVDTCmh+JuBKY0li0aMyXATA= github.com/golang/protobuf v1.4.0-rc.2/go.mod h1:LlEzMj4AhA7rCAGe4KMBDvJI+AwstrUpVNzEA03Pprs= @@ -121,6 +155,7 @@ 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.3/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI= 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/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY= github.com/google/btree v0.0.0-20180813153112-4030bb1f1f0c/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ= @@ -131,15 +166,30 @@ github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5a github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= +github.com/google/go-cmp v0.4.1/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.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.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.6 h1:BKbKCqvP6I+rmFHt06ZmyQtvB8xAkWdhFyr0ZUNZcxQ= github.com/google/go-cmp v0.5.6/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= 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.1.0/go.mod h1:y5Zk1BBys9G+gd6Jrk0W3cC1+ELVxBWuIGO+w/tUAp0= 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-20191218002539-d4f498aebedc/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= +github.com/google/pprof v0.0.0-20200212024743-f11f1df84d12/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-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/renameio v0.1.0/go.mod h1:KWCgfxg9yswjAJkECMjeO8J8rahYeXnNhOm40UhjYkI= github.com/google/uuid v1.1.2/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/googleapis/gax-go/v2 v2.0.4/go.mod h1:0Wqv26UfaUD9n4G6kQubkQ+KchISgw+vpHVxEJEs9eg= @@ -147,12 +197,10 @@ github.com/googleapis/gax-go/v2 v2.0.5/go.mod h1:DWXyrwAJ9X0FpwwEdw+IPEYBICEFu5m github.com/gopherjs/gopherjs v0.0.0-20181017120253-0766667cb4d1/go.mod h1:wJfORRmW1u3UXTncJ5qlYoELFm8eSnnEO6hX4iZ3EWY= github.com/gorilla/websocket v1.4.2 h1:+/TMaTYc4QFitKJxsQ7Yye35DkWvkdLcvGKqM+x0Ufc= github.com/gorilla/websocket v1.4.2/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE= -github.com/grpc-ecosystem/go-grpc-middleware v1.0.0/go.mod h1:FiyG127CGDf3tlThmgyCl78X/SZQqEOJBCDaAfeWzPs= github.com/grpc-ecosystem/go-grpc-middleware v1.3.0 h1:+9834+KizmvFV7pXQGSXQTsaWhq2GjuNUt0aUU0YBYw= github.com/grpc-ecosystem/go-grpc-middleware v1.3.0/go.mod h1:z0ButlSOZa5vEBq9m2m2hlwIgKw+rp3sdCBRoJY+30Y= github.com/grpc-ecosystem/go-grpc-prometheus v1.2.0 h1:Ovs26xHkKqVztRpIrF/92BcuyuQ/YW4NSIpoGtfXNho= github.com/grpc-ecosystem/go-grpc-prometheus v1.2.0/go.mod h1:8NvIoxWQoOIhqOTXgfV/d3M/q6VIi02HzZEHgUlZvzk= -github.com/grpc-ecosystem/grpc-gateway v1.9.0/go.mod h1:vNeuVxBJEsws4ogUvrchl83t/GYV9WGTSLVdBhOQFDY= github.com/grpc-ecosystem/grpc-gateway v1.16.0 h1:gmcG1KaJ57LophUzW0Hy8NmPhnMZb4M0+kPpLofRdBo= github.com/grpc-ecosystem/grpc-gateway v1.16.0/go.mod h1:BDjrQk3hbvj6Nolgz8mAMFbcEtjT1g+wF4CSlocrBnw= github.com/hashicorp/consul/api v1.1.0/go.mod h1:VmuI/Lkw1nC05EYQWNKwWGbkg+FbDBtguAZLlVdkD9Q= @@ -175,9 +223,10 @@ github.com/hashicorp/logutils v1.0.0/go.mod h1:QIAnNjmIWmVIIkWDTG1z5v++HQmx9WQRO github.com/hashicorp/mdns v1.0.0/go.mod h1:tL+uN++7HEJ6SQLQ2/p+z2pH24WQKWjBPkE0mNTz8vQ= github.com/hashicorp/memberlist v0.1.3/go.mod h1:ajVTdAv/9Im8oMAAj5G31PhhMCZJV2pPBoIllUwCN7I= github.com/hashicorp/serf v0.8.2/go.mod h1:6hOLApaqBFA1NXqRQAsxw9QxuDEvNxSQRwA/JwenrHc= +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/inconshreveable/mousetrap v1.0.0 h1:Z8tu5sraLXCXIcARxBp/8cbvlwVa7Z1NHg9XEKhtSvM= github.com/inconshreveable/mousetrap v1.0.0/go.mod h1:PxqpIevigyE2G7u3NXJIT2ANytuPF1OarO4DADm73n8= -github.com/jonboulle/clockwork v0.1.0/go.mod h1:Ii8DK3G1RaLaWxj9trq07+26W01tbo22gdxWY5EU2bo= github.com/jonboulle/clockwork v0.2.2 h1:UOGuzwb1PwsrDAObMuhUnj0p5ULPj8V/xJ7Kx9qUBdQ= github.com/jonboulle/clockwork v0.2.2/go.mod h1:Pkfl5aHPm1nk2H9h0bjmnJD/BcgbGXUBGnn1kMkgxc8= github.com/jpillora/backoff v1.0.0/go.mod h1:J/6gKK9jxlEcS3zixgDgUAsiuZ7yrSoa/FX5e0EB2j4= @@ -185,15 +234,16 @@ github.com/json-iterator/go v1.1.6/go.mod h1:+SdeFBvtyEkXs7REEP0seUULqWtbJapLOCV github.com/json-iterator/go v1.1.10/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4= github.com/json-iterator/go v1.1.11/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4= github.com/jstemmer/go-junit-report v0.0.0-20190106144839-af01ea7f8024/go.mod h1:6v2b51hI/fHJwM22ozAgKL4VKDeJcHhJFhtBdhmNjmU= +github.com/jstemmer/go-junit-report v0.9.1/go.mod h1:Brl9GWCQeLvo8nXZwPNNblvFj/XSXhF0NWZEnDohbsk= github.com/jtolds/gls v4.20.0+incompatible/go.mod h1:QJZ7F/aHp+rZTRtaJ1ow/lLfFfVYBRgL+9YlvaHOwJU= github.com/julienschmidt/httprouter v1.2.0/go.mod h1:SYymIcj16QtmaHHD7aYtjjsJG7VTCxuUUipMqKk8s4w= github.com/julienschmidt/httprouter v1.3.0/go.mod h1:JR6WtHb+2LUe8TCKY3cZOxFyyO8IZAc4RVcycCCAKdM= -github.com/kisielk/errcheck v1.1.0/go.mod h1:EZBBE59ingxPouuu3KfxchcWSUPOHkagtvWXihfKN4Q= github.com/kisielk/errcheck v1.2.0/go.mod h1:/BMXB+zMLi60iA8Vv6Ksmxu/1UDYcXs4uQLJ+jE2L00= github.com/kisielk/errcheck v1.5.0/go.mod h1:pFxgyoBC7bSaBwPgfKdkLd5X25qrDl4LWUI2bnpBCr8= github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck= github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= github.com/konsorten/go-windows-terminal-sequences v1.0.3/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= +github.com/kr/fs v0.1.0/go.mod h1:FFnZGqtBN9Gxj7eW1uZ42v5BccTP0vu6NEaFoC2HwRg= github.com/kr/logfmt v0.0.0-20140226030751-b84e30acd515/go.mod h1:+0opPa2QZZtGFBFZlji/RkVcI2GknAs/DXo4wKdlNEc= github.com/kr/pretty v0.1.0 h1:L/CwN0zerZDmRFUapSPitk6f+Q3+0za1rQkzVuMiMFI= github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo= @@ -201,7 +251,7 @@ github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY= github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE= -github.com/magiconair/properties v1.8.1/go.mod h1:PppfXfuXeibc/6YijjN8zIbojt8czPbwD3XqdrwzmxQ= +github.com/magiconair/properties v1.8.5/go.mod h1:y3VJvCyxH9uVvJTWEGAELF3aiYNyPKd5NZ3oSwXrF60= github.com/mattn/go-colorable v0.0.9/go.mod h1:9vuHe8Xs5qXnSaW/c/ABM9alt+Vo+STaOChaDxuIBZU= github.com/mattn/go-isatty v0.0.3/go.mod h1:M+lRXTBqGeGNdLjl/ufCoiOlB5xdOkqRJdNxMWT7Zi4= github.com/mattn/go-runewidth v0.0.9/go.mod h1:H031xJmbD/WCDINGzjvQ9THkh0rPKHF+m2gUSrubnMI= @@ -210,32 +260,31 @@ github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5 github.com/miekg/dns v1.0.14/go.mod h1:W1PPwlIAgtquWBMBEV9nkV9Cazfe8ScdGz/Lj7v3Nrg= github.com/mitchellh/cli v1.0.0/go.mod h1:hNIlj7HEI86fIcpObd7a0FcrxTWetlwJDGcceTlRvqc= github.com/mitchellh/go-homedir v1.0.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0= -github.com/mitchellh/go-homedir v1.1.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0= github.com/mitchellh/go-testing-interface v1.0.0/go.mod h1:kRemZodwjscx+RGhAo8eIhFbs2+BFgRtFPeD/KE+zxI= github.com/mitchellh/gox v0.4.0/go.mod h1:Sd9lOJ0+aimLBi73mGofS1ycjY8lL3uZM3JPS42BGNg= github.com/mitchellh/iochan v1.0.0/go.mod h1:JwYml1nuB7xOzsp52dPpHFffvOCDupsG0QubkSMEySY= github.com/mitchellh/mapstructure v0.0.0-20160808181253-ca63d7c062ee/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y= github.com/mitchellh/mapstructure v1.1.2/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y= +github.com/mitchellh/mapstructure v1.4.1/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo= github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= github.com/modern-go/reflect2 v0.0.0-20180701023420-4b7aa43c6742/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0= github.com/modern-go/reflect2 v1.0.1/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0= github.com/mwitkow/go-conntrack v0.0.0-20161129095857-cc309e4a2223/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U= github.com/mwitkow/go-conntrack v0.0.0-20190716064945-2f068394615f/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U= -github.com/oklog/ulid v1.3.1/go.mod h1:CirwcVhetQ6Lv90oh/F+FBtV6XMibvdAFo93nm5qn4U= github.com/olekukonko/tablewriter v0.0.5/go.mod h1:hPp6KlRPjbx+hW8ykQs1w3UBbZlj6HuIJcUGPhkA7kY= github.com/opentracing/opentracing-go v1.1.0/go.mod h1:UkNAQd3GIcIGf0SeVgPpRdFStlNbqXla1AfSYxPUl2o= github.com/pascaldekloe/goe v0.0.0-20180627143212-57f6aae5913c/go.mod h1:lzWF7FIEvWOWxwDKqyGYQf6ZUaNfKdP144TG7ZOy1lc= -github.com/pelletier/go-toml v1.2.0/go.mod h1:5z9KED0ma1S8pY6P1sdut58dfprrGBbd/94hg7ilaic= +github.com/pelletier/go-toml v1.9.3/go.mod h1:u1nR/EPcESfeI/szUZKdtJ0xRNbUoANCkoOuaOx1Y+c= github.com/pkg/errors v0.8.0/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4= github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= +github.com/pkg/sftp v1.10.1/go.mod h1:lYOWFsE0bwd1+KfKJaKeuokY15vzFx25BLbzYYoAxZI= github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= github.com/posener/complete v1.1.1/go.mod h1:em0nMJCgc9GFtwrmVmEMR/ZL6WyhyjMBndrE9hABlRI= github.com/prometheus/client_golang v0.9.1/go.mod h1:7SWBe2y4D6OKWSNQJUaRYU/AaXPKyh/dDVn+NZz0KFw= -github.com/prometheus/client_golang v0.9.3/go.mod h1:/TN21ttK/J9q6uSwhBd54HahCDft0ttaMvbicHlPoso= github.com/prometheus/client_golang v1.0.0/go.mod h1:db9x61etRT2tGnBNRi70OPL5FsnadC4Ky3P0J6CfImo= github.com/prometheus/client_golang v1.7.1/go.mod h1:PY5Wy2awLA44sXw4AOSfFBetzPP4j5+D6mVACh+pe2M= github.com/prometheus/client_golang v1.11.0 h1:HNkLOAEQMIDv/K+04rukrLx6ch7msSRwf3/SASFAGtQ= @@ -245,20 +294,15 @@ github.com/prometheus/client_model v0.0.0-20190129233127-fd36f4220a90/go.mod h1: github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= github.com/prometheus/client_model v0.2.0 h1:uq5h0d+GuxiXLJLNABMgp2qUWDPiLvgCzz2dUR+/W/M= github.com/prometheus/client_model v0.2.0/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= -github.com/prometheus/common v0.0.0-20181113130724-41aa239b4cce/go.mod h1:daVV7qP5qjZbuso7PdcryaAu0sAZbrN9i7WWcTMWvro= -github.com/prometheus/common v0.4.0/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y86RQel1bk4= github.com/prometheus/common v0.4.1/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y86RQel1bk4= github.com/prometheus/common v0.10.0/go.mod h1:Tlit/dnDKsSWFlCLTWaA1cyBgKHSMdTB80sz/V91rCo= github.com/prometheus/common v0.26.0 h1:iMAkS2TDoNWnKM+Kopnx/8tnEStIfpYA0ur0xQzzhMQ= github.com/prometheus/common v0.26.0/go.mod h1:M7rCNAaPfAosfx8veZJCuw84e35h3Cfd9VFqTh1DIvc= github.com/prometheus/procfs v0.0.0-20181005140218-185b4288413d/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk= -github.com/prometheus/procfs v0.0.0-20190507164030-5867b95ac084/go.mod h1:TjEm7ze935MbeOT/UhFTIMYKhuLP4wbCsTZCD3I8kEA= github.com/prometheus/procfs v0.0.2/go.mod h1:TjEm7ze935MbeOT/UhFTIMYKhuLP4wbCsTZCD3I8kEA= github.com/prometheus/procfs v0.1.3/go.mod h1:lV6e/gmhEcM9IjHGsFOCxxuZ+z1YqCvr4OA4YeYWdaU= github.com/prometheus/procfs v0.6.0 h1:mxy4L2jP6qMonqmq+aTtOx1ifVWUgG/TAmntgbh3xv4= github.com/prometheus/procfs v0.6.0/go.mod h1:cz+aTbrPOrUb4q7XlbU9ygM+/jj0fzG6c1xBZuNvfVA= -github.com/prometheus/tsdb v0.7.1/go.mod h1:qhTCs0VvXwvX/y3TZrWD7rabWM+ijKTux40TwIPHuXU= -github.com/rogpeppe/fastuuid v0.0.0-20150106093220-6724a57986af/go.mod h1:XWv6SoW27p1b0cqNHllgS5HIMJraePCO15w5zCzIWYg= github.com/rogpeppe/fastuuid v1.2.0/go.mod h1:jVj6XXZzXRy/MSR5jhDC/2q6DgLz+nrA6LYCDYWNEvQ= github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4= github.com/russross/blackfriday/v2 v2.0.1/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= @@ -272,40 +316,44 @@ github.com/sirupsen/logrus v1.8.1 h1:dJKuHgqk1NNQlqoA6BTlM1Wf9DOH3NBjQyu0h9+AZZE github.com/sirupsen/logrus v1.8.1/go.mod h1:yWOB1SBYBC5VeMP7gHvWumXLIWorT60ONWic61uBYv0= github.com/smartystreets/assertions v0.0.0-20180927180507-b2de0cb4f26d/go.mod h1:OnSkiWE9lh6wB0YB77sQom3nweQdgAjqCqsofrRNTgc= github.com/smartystreets/goconvey v1.6.4/go.mod h1:syvi0/a8iFYH4r/RixwvyeAJjdLS9QV7WQ/tjFTllLA= -github.com/soheilhy/cmux v0.1.4/go.mod h1:IM3LyeVVIOuxMH7sFAkER9+bJ4dT7Ms6E4xg4kGIyLM= github.com/soheilhy/cmux v0.1.5 h1:jjzc5WVemNEDTLwv9tlmemhC73tI08BNOIGwBOo10Js= github.com/soheilhy/cmux v0.1.5/go.mod h1:T7TcVDs9LWfQgPlPsdngu6I6QIoyIFZDDC6sNE1GqG0= github.com/spaolacci/murmur3 v0.0.0-20180118202830-f09979ecbc72/go.mod h1:JwIasOWyU6f++ZhiEuf87xNszmSA2myDM2Kzu9HwQUA= -github.com/spf13/afero v1.1.2/go.mod h1:j4pytiNVoe2o6bmDsKpLACNPDBIoEAkihy7loJ1B0CQ= -github.com/spf13/cast v1.3.0/go.mod h1:Qx5cxh0v+4UWYiBimWS+eyWzqEqokIECu5etghLkUJE= -github.com/spf13/cobra v1.1.3 h1:xghbfqPkxzxP3C/f3n5DdpAbdKLj4ZE4BWQI362l53M= -github.com/spf13/cobra v1.1.3/go.mod h1:pGADOWyqRD/YMrPZigI/zbliZ2wVD/23d+is3pSWzOo= -github.com/spf13/jwalterweatherman v1.0.0/go.mod h1:cQK4TGJAtQXfYWX+Ddv3mKDzgVb68N+wFjFa4jdeBTo= -github.com/spf13/pflag v1.0.3/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4= +github.com/spf13/afero v1.6.0/go.mod h1:Ai8FlHk4v/PARR026UzYexafAt9roJ7LcLMAmO6Z93I= +github.com/spf13/cast v1.3.1/go.mod h1:Qx5cxh0v+4UWYiBimWS+eyWzqEqokIECu5etghLkUJE= +github.com/spf13/cobra v1.2.1 h1:+KmjbUw1hriSNMF55oPrkZcb27aECyrj8V2ytv7kWDw= +github.com/spf13/cobra v1.2.1/go.mod h1:ExllRjgxM/piMAM+3tAZvg8fsklGAf3tPfi+i8t68Nk= +github.com/spf13/jwalterweatherman v1.1.0/go.mod h1:aNWZUN0dPAAO/Ljvb5BEdw96iTZ0EXowPYD95IqWIGo= github.com/spf13/pflag v1.0.5 h1:iy+VFUOCP1a+8yFto/drg2CJ5u0yRoB7fZw3DKv/JXA= github.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg= -github.com/spf13/viper v1.7.0/go.mod h1:8WkrPz2fc9jxqZNCJI/76HCieCp4Q8HaLFoCha5qpdg= +github.com/spf13/viper v1.8.1/go.mod h1:o0Pch8wJ9BVSWGQMbra6iw0oQ5oktSIBaujf1rJH9Ns= github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= 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.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA= +github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/stretchr/testify v1.7.0 h1:nwc3DEeHmmLAfoZucVR881uASk0Mfjw8xYJ99tb5CcY= github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/subosito/gotenv v1.2.0/go.mod h1:N0PQaV/YGNqwC0u51sEeR/aUtSLEXKX9iv69rRypqCw= -github.com/tmc/grpc-websocket-proxy v0.0.0-20190109142713-0ad062ec5ee5/go.mod h1:ncp9v5uamzpCO7NfCPTXjqaC+bZgJeR0sMTm6dMHP7U= github.com/tmc/grpc-websocket-proxy v0.0.0-20201229170055-e5319fda7802 h1:uruHq4dN7GR16kFc5fp3d1RIYzJW5onx8Ybykw2YQFA= github.com/tmc/grpc-websocket-proxy v0.0.0-20201229170055-e5319fda7802/go.mod h1:ncp9v5uamzpCO7NfCPTXjqaC+bZgJeR0sMTm6dMHP7U= github.com/xiang90/probing v0.0.0-20190116061207-43a291ad63a2 h1:eY9dn8+vbi4tKz5Qo6v2eYzo7kUS51QINcR5jNpbZS8= github.com/xiang90/probing v0.0.0-20190116061207-43a291ad63a2/go.mod h1:UETIi67q53MR2AWcXfiuqkDkRtnGDLqkBTpCHuJHxtU= +github.com/yuin/goldmark v1.1.25/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= +github.com/yuin/goldmark v1.1.32/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= -go.etcd.io/bbolt v1.3.2/go.mod h1:IbVyRI1SCnLcuJnV2u8VeU0CEYM7e686BmAb1XKL+uU= go.etcd.io/bbolt v1.3.6 h1:/ecaJf0sk1l4l6V4awd65v2C3ILy7MSj+s/x1ADCIMU= go.etcd.io/bbolt v1.3.6/go.mod h1:qXsaaIqmgQH0T+OPdb99Bf+PKfBBQVAdyD6TY9G8XM4= 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.2/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.5/go.mod h1:5pWMHQbX5EPX2/62yrJeAkowc+lfs/XD7Uxpq3pI6kk= +go.opencensus.io v0.23.0/go.mod h1:XItmlyltB5F7CS4xOC1DcqMoFqwtC6OG2xF7mCv7P7E= go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.26.1 h1:puWrOArBwWlr5dq6vyZ6fKykHyS8JgMIVhTBA8XsGuU= go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.26.1/go.mod h1:4wsfAAW5N9wUHM0QTmZS8z7fvYZ1rv3m+sVeSpf8NhU= go.opentelemetry.io/otel v1.1.0/go.mod h1:7cww0OW51jQ8IaZChIEdqLwgh+44+7uiTdWsAL0wQpA= @@ -340,6 +388,7 @@ golang.org/x/crypto v0.0.0-20181029021203-45a5f77698d3/go.mod h1:6SG95UA2DQfeDnf golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= golang.org/x/crypto v0.0.0-20190510104115-cbcb75029529/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20190605123033-f99c8df09eb5/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= +golang.org/x/crypto v0.0.0-20190820162420-60c769a6c586/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= golang.org/x/crypto v0.0.0-20210513164829-c07d793c2f9a h1:kr2P4QFmQr29mSLA43kwrOcgcReGTfbE9N577tCTuBc= @@ -349,6 +398,11 @@ golang.org/x/exp v0.0.0-20190306152737-a1d7652674e8/go.mod h1:CJ0aWSM057203Lf6IL golang.org/x/exp v0.0.0-20190510132918-efd6b22b2522/go.mod h1:ZjyILWgesfNpC6sMxTJOJm9Kp84zZh5NQWvqDGG3Qr8= golang.org/x/exp v0.0.0-20190829153037-c13cbed26979/go.mod h1:86+5VVa7VpoJ4kLfm080zCjGlMRFzhUhsZKEZO7MGek= golang.org/x/exp v0.0.0-20191030013958-a1ab85dbe136/go.mod h1:JXzH8nQsPlswgeRAPE3MuO9GYsAcnJvJ4vnMwN/5qkY= +golang.org/x/exp v0.0.0-20191129062945-2f5052295587/go.mod h1:2RIsYlXP63K8oxa1u096TMicItID8zy7Y6sNkU49FU4= +golang.org/x/exp v0.0.0-20191227195350-da58074b4299/go.mod h1:2RIsYlXP63K8oxa1u096TMicItID8zy7Y6sNkU49FU4= +golang.org/x/exp v0.0.0-20200119233911-0405dc783f0a/go.mod h1:2RIsYlXP63K8oxa1u096TMicItID8zy7Y6sNkU49FU4= +golang.org/x/exp v0.0.0-20200207192155-f17229e696bd/go.mod h1:J/WKrq2StrnmMY6+EHIKF9dgMWnmCNThgcyBT1FY9mM= +golang.org/x/exp v0.0.0-20200224162631-6cc2880d07d6/go.mod h1:3jZMyOhIsHpP37uCMkUooju7aAi5cS1Q23tOzKc+0MU= golang.org/x/image v0.0.0-20190227222117-0694c2d4d067/go.mod h1:kZ7UVZpmo3dzQBMxlp+ypCbDeSB+sBbTgSJuh5dn5js= golang.org/x/image v0.0.0-20190802002840-cff245a6509b/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0= golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE= @@ -358,18 +412,25 @@ golang.org/x/lint v0.0.0-20190313153728-d0100b6bd8b3/go.mod h1:6SW0HCj/g11FgYtHl golang.org/x/lint v0.0.0-20190409202823-959b441ac422/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= golang.org/x/lint v0.0.0-20190909230951-414d861bb4ac/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= golang.org/x/lint v0.0.0-20190930215403-16217165b5de/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= +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-20200302205851-738671d3881b/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY= +golang.org/x/lint v0.0.0-20201208152925-83fdc39ff7b5/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-20190719004257-d2bd2a29d028/go.mod h1:E/iHnbuqvinMTCcRqshq8CkpyQDoeVncDDYHnLhea+o= golang.org/x/mod v0.0.0-20190513183733-4bf6d317e70e/go.mod h1:mXi4GBBbnImb6dmsKGUJ2LatrhH/nqhxcFungHvyanc= golang.org/x/mod v0.1.0/go.mod h1:0QHyrYULN0/3qlju5TqG8bIK38QM8yzMo5ekMj3DlcY= +golang.org/x/mod v0.1.1-0.20191105210325-c90efee705ee/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.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/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-20181023162649-9b4f9f5ad519/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20181114220301-adae6a3d119a/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20181201002055-351d144fa1fc/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= -golang.org/x/net v0.0.0-20181220203305-927f97764cc3/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20190108225652-1e06a53dbb7e/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20190213061140-3a22650c66bd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= @@ -379,26 +440,54 @@ golang.org/x/net v0.0.0-20190503192946-f4e77d36d62c/go.mod h1:t9HGtf8HONx5eT2rtn golang.org/x/net v0.0.0-20190603091049-60506f45cf65/go.mod h1:HSz+uSET+XFnRR8LxR5pz3Of3rY3CfYBVs4xY44aLks= golang.org/x/net v0.0.0-20190613194153-d28f0bde5980/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20190628185345-da137c7871d7/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20190724013045-ca1201d0de80/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20191209160850-c0dbc17a3553/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20200114155413-6afb5195e5aa/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20200202094626-16171245cfb2/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20200222125558-5a598a2470a0/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20200226121028-0de0cce0169b/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20200301022130-244492dfa37a/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20200324143707-d3edc9973b7e/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= +golang.org/x/net v0.0.0-20200501053045-e0ff5e5a1de5/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= +golang.org/x/net v0.0.0-20200506145744-7e3656a0809f/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= +golang.org/x/net v0.0.0-20200513185701-a91f0712d120/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= +golang.org/x/net v0.0.0-20200520182314-0ba52f642ac2/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= golang.org/x/net v0.0.0-20200625001655-4c5254603344/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-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-20201202161906-c7110b5ffcbb/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-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-20211123203042-d83791d6bcd9 h1:0qxwC5n+ttVOINCBeRHO0nq9X7uy8SDsPoi5OaCdIEI= golang.org/x/net v0.0.0-20211123203042-d83791d6bcd9/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= 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-20190604053449-0f29369cfe45/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= -golang.org/x/oauth2 v0.0.0-20200107190931-bf48bf16ab8d h1:TzXSXBo42m9gQenoE3b9BGiEpg5IG2JkU5FkPIawgtw= +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-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-20210402161424-2e8d93401602 h1:0Ja1LBD+yisY6RWM/BH7TJVXWsSjs2VwBSmvSX4HdBc= +golang.org/x/oauth2 v0.0.0-20210402161424-2e8d93401602/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= 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-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20190227155943-e225da77a7e6/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20200317015054-43a5402ce75a/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20200625203802-6e8e738ad208/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-20210220032951-036812b2e83c h1:5KslGYwFpkhGh+Q16bwMP3cOontH8FOep7tGV86Y7SQ= @@ -407,7 +496,6 @@ golang.org/x/sys v0.0.0-20180823144017-11551d06cbcc/go.mod h1:STP8DvDyc/dI5b8T5h 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-20181026203630-95b1ffbd15a5/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= -golang.org/x/sys v0.0.0-20181107165924-66b7b1311ac8/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20181116152217-5ac8a444bdc5/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190312061237-fead79001313/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= @@ -417,16 +505,42 @@ golang.org/x/sys v0.0.0-20190502145724-3ef323f4f1fd/go.mod h1:h1NjWce9XRLGQEsW7w golang.org/x/sys v0.0.0-20190507160741-ecd444e8653b/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190606165138-5da285871e9c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190624142023-c5567b49c5d0/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190726091711-fc99dfbffb4e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20191001151750-bb3f8db39f24/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20191005200804-aed5e4c7ecf9/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20191026070338-33540a1f6037/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20191204072324-ce4227a45e2e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20191228213918-04cbcbbfeed8/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200106162015-b016eb3dc98e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200113162924-86b910548bc1/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200122134326-e047566fdf82/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200202164722-d101bd2416d5/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200212091648-12a6c2dcc1e4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200223170610-d5e6a3e2c0ae/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200302150141-5c8b2ff67527/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200331124033-c3d80250170d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200501052902-10377860bb8e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200511232937-7e40ca221e25/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200515095857-1151b9dac4a9/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200523222454-059865788121/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-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-20200923182605-d9f96fdee20d/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-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-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-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-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-20210423185535-09eb48e85fd7/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210510120138-977fb7262007/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= @@ -435,19 +549,21 @@ golang.org/x/sys v0.0.0-20210603125802-9665404d3644/go.mod h1:oPkhp1MJrh7nUepCBc golang.org/x/sys v0.0.0-20211123173158-ef496fb156ab h1:rfJ1bsoJQQIAoAxTxB7bme+vHrNkRw8CqfsYh9w54cw= golang.org/x/sys v0.0.0-20211123173158-ef496fb156ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= +golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.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.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.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/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-20191024005414-555d28b269f0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.0.0-20210220033141-f8bda1e9f3ba h1:O8mE0/t419eoIwhTFpKVkHiTs/Igowgfkj25AcZrtiE= golang.org/x/time v0.0.0-20210220033141-f8bda1e9f3ba/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= -golang.org/x/tools v0.0.0-20180221164845-07fd8470d635/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-20181030221726-6c7e314b6563/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20190114222345-bf090417da8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= @@ -466,9 +582,39 @@ golang.org/x/tools v0.0.0-20190816200558-6889da9d5479/go.mod h1:b+2E5dAYhXwXZwtn golang.org/x/tools v0.0.0-20190911174233-4f2ddba30aff/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.0.0-20191012152004-8de300cfc20a/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.0.0-20191112195655-aa38f8e97acc/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-20191113191852-77e3bb0ad9e7/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-20191115202509-3a792d9c32b2/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-20191125144606-a911d9008d1f/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-20191130070609-6e064ea0cf2d/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-20191216173652-a0e659d51361/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= +golang.org/x/tools v0.0.0-20191227053925-7b8e75db28f4/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= +golang.org/x/tools v0.0.0-20200117161641-43d50277825c/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= +golang.org/x/tools v0.0.0-20200122220014-bf1340f18c4a/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= +golang.org/x/tools v0.0.0-20200130002326-2f3ba24bd6e7/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= +golang.org/x/tools v0.0.0-20200204074204-1cc6d1ef6c74/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= +golang.org/x/tools v0.0.0-20200207183749-b753a1ba74fa/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= +golang.org/x/tools v0.0.0-20200212150539-ea181f53ac56/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= +golang.org/x/tools v0.0.0-20200224181240-023911ca70b2/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= +golang.org/x/tools v0.0.0-20200227222343-706bc42d1f0d/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= +golang.org/x/tools v0.0.0-20200304193943-95d2e580d8eb/go.mod h1:o4KQGtdN14AW+yjsvvwRTJJuXz8XRtIHtEnmAXLyFUw= +golang.org/x/tools v0.0.0-20200312045724-11d5b4c81c7d/go.mod h1:o4KQGtdN14AW+yjsvvwRTJJuXz8XRtIHtEnmAXLyFUw= +golang.org/x/tools v0.0.0-20200331025713-a30bf2db82d4/go.mod h1:Sl4aGygMT6LrqrWclx+PTx3U+LnKx/seiNR+3G19Ar8= +golang.org/x/tools v0.0.0-20200501065659-ab2804fb9c9d/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= +golang.org/x/tools v0.0.0-20200512131952-2bc93b1c0c88/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= +golang.org/x/tools v0.0.0-20200515010526-7d3b6ebf133d/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= +golang.org/x/tools v0.0.0-20200618134242-20370b0cb4b2/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= golang.org/x/tools v0.0.0-20200619180055-7c47624df98f/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= +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-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-20210105154028-b0ab187a4818/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/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-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= @@ -479,11 +625,31 @@ google.golang.org/api v0.7.0/go.mod h1:WtwebWUNSVBH/HAw79HIFXZNqEvBhG+Ra+ax0hx3E google.golang.org/api v0.8.0/go.mod h1:o4eAsZoiT+ibD93RtjEohWalFOjRDx6CVaqeizhEnKg= google.golang.org/api v0.9.0/go.mod h1:o4eAsZoiT+ibD93RtjEohWalFOjRDx6CVaqeizhEnKg= google.golang.org/api v0.13.0/go.mod h1:iLdEw5Ide6rF15KTC1Kkl0iskquN2gFfn9o9XIsbkAI= +google.golang.org/api v0.14.0/go.mod h1:iLdEw5Ide6rF15KTC1Kkl0iskquN2gFfn9o9XIsbkAI= +google.golang.org/api v0.15.0/go.mod h1:iLdEw5Ide6rF15KTC1Kkl0iskquN2gFfn9o9XIsbkAI= +google.golang.org/api v0.17.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE= +google.golang.org/api v0.18.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE= +google.golang.org/api v0.19.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE= +google.golang.org/api v0.20.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE= +google.golang.org/api v0.22.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE= +google.golang.org/api v0.24.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.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.44.0/go.mod h1:EBOGZqzyhtvMDoxwS97ctnh0zUmYY6CxqXsc1AvkYD8= 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.5.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= -google.golang.org/appengine v1.6.1 h1:QzqyMA1tlu6CgqCDUtU9V+ZKhLFT2dkJuANu5QaxI3I= google.golang.org/appengine v1.6.1/go.mod h1:i06prIuMbXzDqacNJfV5OdTW448YApPu5ww/cMBSeb0= +google.golang.org/appengine v1.6.5/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-20190307195333-5fe7a883aa19/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= google.golang.org/genproto v0.0.0-20190418145605-e7d98fc518a7/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= @@ -493,9 +659,38 @@ google.golang.org/genproto v0.0.0-20190801165951-fa694d86fc64/go.mod h1:DMBHOl98 google.golang.org/genproto v0.0.0-20190819201941-24fa4b261c55/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc= google.golang.org/genproto v0.0.0-20190911173649-1774047e7e51/go.mod h1:IbNlFCBrqXvoKpeg0TB2l7cyZUmoaFKYIwrEpbDKLA8= google.golang.org/genproto v0.0.0-20191108220845-16a3f7862a1a/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= +google.golang.org/genproto v0.0.0-20191115194625-c23dd37a84c9/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= +google.golang.org/genproto v0.0.0-20191216164720-4f79533eabd1/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= +google.golang.org/genproto v0.0.0-20191230161307-f3c370f40bfb/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= +google.golang.org/genproto v0.0.0-20200115191322-ca5a22157cba/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= +google.golang.org/genproto v0.0.0-20200122232147-0452cf42e150/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= +google.golang.org/genproto v0.0.0-20200204135345-fa8e72b47b90/go.mod h1:GmwEX6Z4W5gMy59cAlVYjN9JhxgbQH6Gn+gFDQe2lzA= +google.golang.org/genproto v0.0.0-20200212174721-66ed5ce911ce/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= +google.golang.org/genproto v0.0.0-20200224152610-e50cd9704f63/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= +google.golang.org/genproto v0.0.0-20200228133532-8c2c7df3a383/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= +google.golang.org/genproto v0.0.0-20200305110556-506484158171/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= +google.golang.org/genproto v0.0.0-20200312145019-da6875a35672/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= +google.golang.org/genproto v0.0.0-20200331122359-1ee6d9798940/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= google.golang.org/genproto v0.0.0-20200423170343-7949de9c1215/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= +google.golang.org/genproto v0.0.0-20200430143042-b979b6f78d84/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= +google.golang.org/genproto v0.0.0-20200511104702-f5ebc3bea380/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= google.golang.org/genproto v0.0.0-20200513103714-09dca8ec2884/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= +google.golang.org/genproto v0.0.0-20200515170657-fc4c6c6a6587/go.mod h1:YsZOwe1myG/8QRHRsmBRE1LrgQY60beZKjly0O1fX9U= google.golang.org/genproto v0.0.0-20200526211855-cb27e3aa2013/go.mod h1:NbSheEEYHJ7i3ixzK3sjbqSGDJWnxyFXZblF3eUsNvo= +google.golang.org/genproto v0.0.0-20200618031413-b414f8b61790/go.mod h1:jDfRM7FcilCzHH/e9qn6dsT145K34l5v+OpcnNgKAAA= +google.golang.org/genproto v0.0.0-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-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-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-20210402141018-6c239bbf2bb1/go.mod h1:9lPAdzaEmUacj36I+k7YKbEc5CXzPIeORRgDAUOu28A= google.golang.org/genproto v0.0.0-20211118181313-81c1377c94b1 h1:b9mVrqYfq3P4bCdaLg1qtBnPzUYgglsIdjZkL/fQVOE= google.golang.org/genproto v0.0.0-20211118181313-81c1377c94b1/go.mod h1:5CzLGKJ67TSI2B9POpiiyGha0AjJvZIUgRMt1dSmuhc= google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c= @@ -503,11 +698,22 @@ google.golang.org/grpc v1.20.1/go.mod h1:10oTOabMzJvdu6/UiuZezV6QK5dSlG84ov/aaiq google.golang.org/grpc v1.21.1/go.mod h1:oYelfM1adQP15Ek0mdvEgi9Df8B9CZIaU1084ijfRaM= google.golang.org/grpc v1.23.0/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg= google.golang.org/grpc v1.25.1/go.mod h1:c3i+UQWmh7LiEpx4sFZnkU36qjEYZ0imhYfXVyQciAY= +google.golang.org/grpc v1.26.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk= google.golang.org/grpc v1.27.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk= +google.golang.org/grpc v1.27.1/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk= +google.golang.org/grpc v1.28.0/go.mod h1:rpkK4SK4GF4Ach/+MFLZUBavHOvF2JJB5uozKKal+60= 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.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.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.1/go.mod h1:qjiiYl8FncCW8feJPdyg3v6XW24KsRHe+dy9BAGRRjU= 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.40.0/go.mod h1:ogyxbiOoUXAkP+4+xa6PZSE9DZgIHtSpzjDTB9KAK34= google.golang.org/grpc v1.41.0 h1:f+PlOh7QV4iIJkPrx5NQ7qaNGFQ3OTse67yaDHfju4E= google.golang.org/grpc v1.41.0/go.mod h1:U3l9uK9J0sini8mHphKoXyaqDA/8VyGnDee1zzIUK6k= @@ -519,6 +725,7 @@ google.golang.org/protobuf v1.21.0/go.mod h1:47Nbq4nVaFHyn7ilMalzfO3qCViNmqZ2kzi google.golang.org/protobuf v1.22.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= google.golang.org/protobuf v1.23.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= google.golang.org/protobuf v1.23.1-0.20200526195155-81db48ad09cc/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= +google.golang.org/protobuf v1.24.0/go.mod h1:r/3tXBNzIEhYS9I1OUVjXDlt8tc493IdKGjtUeSXeh4= google.golang.org/protobuf v1.25.0/go.mod h1:9JNX74DMeImyA3h4bdi1ymwjUzf21/xIlbajtzgsN7c= google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw= google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc= @@ -530,11 +737,9 @@ gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8 gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15 h1:YR8cESwS4TdDjEe65xsg0ogRM/Nc3DYOhEAlW+xobZo= gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/errgo.v2 v2.1.0/go.mod h1:hNsd1EY+bozCKY1Ytp96fpM3vjJbqLJn88ws8XvfDNI= -gopkg.in/ini.v1 v1.51.0/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k= +gopkg.in/ini.v1 v1.62.0/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k= gopkg.in/natefinch/lumberjack.v2 v2.0.0 h1:1Lc07Kr7qY4U2YPouBjpCLxpiyxIVoxqXgkXLknAOE8= gopkg.in/natefinch/lumberjack.v2 v2.0.0/go.mod h1:l0ndWWf7gzL7RNwBG7wST/UCcT4T24xpD6X8LsfU/+k= -gopkg.in/resty.v1 v1.12.0/go.mod h1:mDo4pnntr5jdWRML875a/NmxYqAlA73dVijT2AXvQQo= -gopkg.in/yaml.v2 v2.0.0-20170812160011-eb3733d160e7/go.mod h1:JAlM8MvJe8wmxCU4Bli9HhUf9+ttbYbLASfIpnQbh74= gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.2.3/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= @@ -552,7 +757,11 @@ honnef.co/go/tools v0.0.0-20190106161140-3f1c8253044a/go.mod h1:rf3lG4BRIbNafJWh honnef.co/go/tools v0.0.0-20190418001031-e561f6794a2a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= honnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= honnef.co/go/tools v0.0.1-2019.2.3/go.mod h1:a3bituU0lyd329TUQxRnasdCoJDkEUEAqEt0JzvZhAg= +honnef.co/go/tools v0.0.1-2020.1.3/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9vFzvIQ3k= +honnef.co/go/tools v0.0.1-2020.1.4/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9vFzvIQ3k= 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/sampler v1.3.0/go.mod h1:T1hPZKmBbMNahiBKFy5HrXp6adAjACjK9JXDnKaTXpA= sigs.k8s.io/json v0.0.0-20211020170558-c049b76a60c6 h1:fD1pz4yfdADVNfFmcP2aBEtudwUQ1AlLnRBALr33v3s= sigs.k8s.io/json v0.0.0-20211020170558-c049b76a60c6/go.mod h1:p4QtZmO4uMYipTQNzagwnNoseA6OxSUutVw05NhYDRs= sigs.k8s.io/yaml v1.2.0 h1:kr/MCeFWJWTwyaHoR9c8EjH9OumOmoF9YGiZd7lFm/Q= From 5620a9c2270988c817eba6d0560bfa22c948441e Mon Sep 17 00:00:00 2001 From: Brian Cunnie Date: Wed, 29 Dec 2021 13:34:18 -0800 Subject: [PATCH 041/258] Golang Client docs: defer cancel(), avoid erroring In the sample code demonstrating how to specify a client request timeout, the `cancel()` is called immediately after the Put, but it should be deferred instead, giving the Put enough time to complete. In the canonical Golang context [docs](https://pkg.go.dev/context#WithTimeout), the sample code sets a `defer cancel()` immediately after context creation, and with this commit we adhere to that convention. fixes: ```json { "level": "warn", "ts": "2021-12-29T09:56:42.439-0800", "logger": "etcd-client", "caller": "v3@v3.5.1/retry_interceptor.go:62", "msg": "retrying of unary invoker failed", "target": "etcd-endpoints://0xc000213340/localhost:2379", "attempt": 0, "error": "rpc error: code = Canceled desc = context canceled" } ``` --- client/v3/doc.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/client/v3/doc.go b/client/v3/doc.go index 645d744a5a7f..7cb31f93977b 100644 --- a/client/v3/doc.go +++ b/client/v3/doc.go @@ -47,8 +47,8 @@ // To specify a client request timeout, wrap the context with context.WithTimeout: // // ctx, cancel := context.WithTimeout(context.Background(), timeout) +// defer cancel() // resp, err := kvc.Put(ctx, "sample_key", "sample_value") -// cancel() // if err != nil { // // handle error! // } From 17fd2e72822146e9a486bb4c08ae620af0946052 Mon Sep 17 00:00:00 2001 From: Yap Sok Ann Date: Fri, 31 Dec 2021 13:17:02 +0700 Subject: [PATCH 042/258] Disable auth gracefully without impacting existing watchers This attempts to fix a special case of the problem described in #12385, where trying to do `clientv3.Watch` with an expired token would result in `ErrGRPCPermissionDenied`, due to the failing authorization check in `isWatchPermitted`. Furthermore, the client can't auto recover, since `shouldRefreshToken` rightly returns false for the permission denied error. In this case, we would like to have a runbook to dynamically disable auth, without causing any disruption. Doing so would immediately expire all existing tokens, which would then cause the behavior described above. This means existing watchers would still work for a period of time after disabling auth, until they have to reconnect, e.g. due to a rolling restart of server nodes. This commit adds a client-side fix and a server-side fix, either of which is sufficient to get the added test case to pass. Note that it is an e2e test case instead of an integration one, as the reconnect only happens if the server node is stopped via SIGINT or SIGTERM. A generic fix for the problem described in #12385 would be better, as that shall also fix this special case. However, the fix would likely be a lot more involved, as some untangling of authn/authz is required. --- client/v3/client.go | 1 + server/auth/store.go | 4 ++++ tests/e2e/ctl_v3_auth_test.go | 45 +++++++++++++++++++++++++++++++++++ 3 files changed, 50 insertions(+) diff --git a/client/v3/client.go b/client/v3/client.go index c39f00421578..971fea607cf9 100644 --- a/client/v3/client.go +++ b/client/v3/client.go @@ -263,6 +263,7 @@ func (c *Client) getToken(ctx context.Context) error { resp, err := c.Auth.Authenticate(ctx, c.Username, c.Password) if err != nil { if err == rpctypes.ErrAuthNotEnabled { + c.authTokenBundle.UpdateAuthToken("") return nil } return err diff --git a/server/auth/store.go b/server/auth/store.go index 4d0e8d6b20c7..408b235babd7 100644 --- a/server/auth/store.go +++ b/server/auth/store.go @@ -1026,6 +1026,10 @@ func (as *authStore) AuthInfoFromTLS(ctx context.Context) (ai *AuthInfo) { } func (as *authStore) AuthInfoFromCtx(ctx context.Context) (*AuthInfo, error) { + if !as.IsAuthEnabled() { + return nil, nil + } + md, ok := metadata.FromIncomingContext(ctx) if !ok { return nil, nil diff --git a/tests/e2e/ctl_v3_auth_test.go b/tests/e2e/ctl_v3_auth_test.go index ed3ffc416ea0..4d376f64c8c6 100644 --- a/tests/e2e/ctl_v3_auth_test.go +++ b/tests/e2e/ctl_v3_auth_test.go @@ -30,6 +30,7 @@ func TestCtlV3AuthEnable(t *testing.T) { testCtl(t, authEnableTest) } func TestCtlV3AuthDisable(t *testing.T) { testCtl(t, authDisableTest) } +func TestCtlV3AuthGracefulDisable(t *testing.T) { testCtl(t, authGracefulDisableTest) } func TestCtlV3AuthStatus(t *testing.T) { testCtl(t, authStatusTest) } func TestCtlV3AuthWriteKey(t *testing.T) { testCtl(t, authCredWriteKeyTest) } func TestCtlV3AuthRoleUpdate(t *testing.T) { testCtl(t, authRoleUpdateTest) } @@ -142,6 +143,50 @@ func authDisableTest(cx ctlCtx) { } } +func authGracefulDisableTest(cx ctlCtx) { + if err := authEnable(cx); err != nil { + cx.t.Fatal(err) + } + + cx.user, cx.pass = "root", "root" + + donec := make(chan struct{}) + + go func() { + defer close(donec) + + // sleep a bit to let the watcher connects while auth is still enabled + time.Sleep(1000 * time.Millisecond) + + // now disable auth... + if err := ctlV3AuthDisable(cx); err != nil { + cx.t.Fatalf("authGracefulDisableTest ctlV3AuthDisable error (%v)", err) + } + + // ...and restart the node + node0 := cx.epc.Procs[0] + node0.WithStopSignal(syscall.SIGINT) + if rerr := node0.Restart(); rerr != nil { + cx.t.Fatal(rerr) + } + + // the watcher should still work after reconnecting + if perr := ctlV3Put(cx, "key", "value", ""); perr != nil { + cx.t.Errorf("authGracefulDisableTest ctlV3Put error (%v)", perr) + } + }() + + err := ctlV3Watch(cx, []string{"key"}, kvExec{key: "key", val: "value"}) + + if err != nil { + if cx.dialTimeout > 0 && !isGRPCTimedout(err) { + cx.t.Errorf("authGracefulDisableTest ctlV3Watch error (%v)", err) + } + } + + <-donec +} + func ctlV3AuthDisable(cx ctlCtx) error { cmdArgs := append(cx.PrefixArgs(), "auth", "disable") return e2e.SpawnWithExpectWithEnv(cmdArgs, cx.envMap, "Authentication Disabled") From 0cc789d81d9ea3d8e0de2b918349280f89276f25 Mon Sep 17 00:00:00 2001 From: Liang Zheng Date: Wed, 29 Dec 2021 19:07:34 +0800 Subject: [PATCH 043/258] update dump db tool Signed-off-by: Liang Zheng --- server/lease/leasehttp/http.go | 2 +- server/storage/mvcc/index.go | 4 ++-- server/storage/mvcc/kvstore.go | 2 +- tools/etcd-dump-db/backend.go | 2 +- 4 files changed, 5 insertions(+), 5 deletions(-) diff --git a/server/lease/leasehttp/http.go b/server/lease/leasehttp/http.go index 3539305863d2..542c3a82a0cb 100644 --- a/server/lease/leasehttp/http.go +++ b/server/lease/leasehttp/http.go @@ -236,7 +236,7 @@ func TimeToLiveHTTP(ctx context.Context, id lease.LeaseID, keys bool, url string return nil, fmt.Errorf(`lease: %v. data = "%s"`, err, string(b)) } if lresp.LeaseTimeToLiveResponse.ID != int64(id) { - return nil, fmt.Errorf("lease: renew id mismatch") + return nil, fmt.Errorf("lease: TTL id mismatch") } return lresp, nil } diff --git a/server/storage/mvcc/index.go b/server/storage/mvcc/index.go index 0a5cb005160f..13cbc9b8bc2a 100644 --- a/server/storage/mvcc/index.go +++ b/server/storage/mvcc/index.go @@ -218,8 +218,8 @@ func (ti *treeIndex) Compact(rev int64) map[revision]struct{} { clone.Ascend(func(item btree.Item) bool { keyi := item.(*keyIndex) - //Lock is needed here to prevent modification to the keyIndex while - //compaction is going on or revision added to empty before deletion + // Lock is needed here to prevent modification to the keyIndex while + // compaction is going on or revision added to empty before deletion ti.Lock() keyi.compact(ti.lg, rev, available) if keyi.isEmpty() { diff --git a/server/storage/mvcc/kvstore.go b/server/storage/mvcc/kvstore.go index 3c0a60bef680..dbf59239c149 100644 --- a/server/storage/mvcc/kvstore.go +++ b/server/storage/mvcc/kvstore.go @@ -142,7 +142,7 @@ func (s *store) compactBarrier(ctx context.Context, ch chan struct{}) { select { case <-s.stopc: default: - // fix deadlock in mvcc,for more information, please refer to pr 11817. + // fix deadlock in mvcc, for more information, please refer to pr 11817. // s.stopc is only updated in restore operation, which is called by apply // snapshot call, compaction and apply snapshot requests are serialized by // raft, and do not happen at the same time. diff --git a/tools/etcd-dump-db/backend.go b/tools/etcd-dump-db/backend.go index a0e14bc679a5..7962007f8b17 100644 --- a/tools/etcd-dump-db/backend.go +++ b/tools/etcd-dump-db/backend.go @@ -95,7 +95,7 @@ func leaseDecoder(k, v []byte) { if err := lpb.Unmarshal(v); err != nil { panic(err) } - fmt.Printf("lease ID=%016x, TTL=%ds\n", leaseID, lpb.TTL) + fmt.Printf("lease ID=%016x, TTL=%ds, remaining TTL=%ds\n", leaseID, lpb.TTL, lpb.RemainingTTL) } func authDecoder(k, v []byte) { From a9652b4b4e75949407a97adc110278c5b97da4d9 Mon Sep 17 00:00:00 2001 From: songlh Date: Tue, 4 Jan 2022 17:57:19 -0500 Subject: [PATCH 044/258] fixing the leaks in TestStressWatchCancelClose --- server/storage/mvcc/watchable_store_test.go | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/server/storage/mvcc/watchable_store_test.go b/server/storage/mvcc/watchable_store_test.go index 2b53206ef88b..375bbd346971 100644 --- a/server/storage/mvcc/watchable_store_test.go +++ b/server/storage/mvcc/watchable_store_test.go @@ -615,7 +615,8 @@ func TestStressWatchCancelClose(t *testing.T) { s := newWatchableStore(zap.NewExample(), b, &lease.FakeLessor{}, StoreConfig{}) defer func() { - s.store.Close() + b.Close() + s.Close() os.Remove(tmpPath) }() From 1e5bd39571519fbafe471b67e7ae0df712b900be Mon Sep 17 00:00:00 2001 From: Sahdev Zala Date: Wed, 5 Jan 2022 21:36:27 -0500 Subject: [PATCH 045/258] Update supported versions and ref to the policy We support current release and two previous minor versions, and so making changes accordingly. Also, adding link to the details of the versioning. --- CHANGELOG-3.3.md | 2 +- CHANGELOG-3.4.md | 2 +- CHANGELOG-3.5.md | 3 +-- 3 files changed, 3 insertions(+), 4 deletions(-) diff --git a/CHANGELOG-3.3.md b/CHANGELOG-3.3.md index 8256494d36b3..65246e5dd081 100644 --- a/CHANGELOG-3.3.md +++ b/CHANGELOG-3.3.md @@ -3,7 +3,7 @@ Previous change logs can be found at [CHANGELOG-3.2](https://github.com/etcd-io/etcd/blob/main/CHANGELOG-3.2.md). -The minimum recommended etcd versions to run in **production** are 3.2.28+, 3.3.18+, 3.4.2+, and 3.5.1+. +The minimum recommended etcd versions to run in **production** are 3.3.18+, 3.4.2+, and 3.5.1+. Refer to the [versioning policy](https://etcd.io/docs/v3.3/op-guide/versioning/) for more details.
diff --git a/CHANGELOG-3.4.md b/CHANGELOG-3.4.md index 4612d8910626..50aecd966140 100644 --- a/CHANGELOG-3.4.md +++ b/CHANGELOG-3.4.md @@ -3,7 +3,7 @@ Previous change logs can be found at [CHANGELOG-3.3](https://github.com/etcd-io/etcd/blob/main/CHANGELOG-3.3.md). -The minimum recommended etcd versions to run in **production** are 3.2.28+, 3.3.18+, 3.4.2+, and 3.5.1+. +The minimum recommended etcd versions to run in **production** are 3.3.18+, 3.4.2+, and 3.5.1+. Refer to the [versioning policy](https://etcd.io/docs/v3.4/op-guide/versioning/) for more details.
diff --git a/CHANGELOG-3.5.md b/CHANGELOG-3.5.md index 0e66b7d705d2..4cf6d4855886 100644 --- a/CHANGELOG-3.5.md +++ b/CHANGELOG-3.5.md @@ -3,8 +3,7 @@ Previous change logs can be found at [CHANGELOG-3.4](https://github.com/etcd-io/etcd/blob/main/CHANGELOG-3.4.md). -The minimum recommended etcd versions to run in **production** are 3.2.28+, 3.3.18+, 3.4.2+, and 3.5.1+. - +The minimum recommended etcd versions to run in **production** are 3.3.18+, 3.4.2+, and 3.5.1+. Refer to the [versioning policy](https://etcd.io/docs/v3.5/op-guide/versioning/) for more details.
From 6aac35dd3216e7965c233ff1376f9181d3c1e9e2 Mon Sep 17 00:00:00 2001 From: AdamKorcz Date: Thu, 30 Dec 2021 15:48:05 +0000 Subject: [PATCH 046/258] v2auth: fix out of bounds in test --- server/etcdserver/api/v2auth/auth_test.go | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/server/etcdserver/api/v2auth/auth_test.go b/server/etcdserver/api/v2auth/auth_test.go index 1b664e0e8531..cd9c66667b59 100644 --- a/server/etcdserver/api/v2auth/auth_test.go +++ b/server/etcdserver/api/v2auth/auth_test.go @@ -176,6 +176,11 @@ func (td *testDoer) Do(_ context.Context, req etcdserverpb.Request) (etcdserver. }, nil } if (req.Method == "GET" || req.Method == "QGET") && td.get != nil { + if td.getindex >= len(td.get) { + return etcdserver.Response{}, &v2error.Error{ + ErrorCode: v2error.EcodeKeyNotFound, + } + } res := td.get[td.getindex] if res.Event == nil { td.getindex++ @@ -187,6 +192,11 @@ func (td *testDoer) Do(_ context.Context, req etcdserverpb.Request) (etcdserver. return res, nil } if req.Method == "PUT" && td.put != nil { + if td.putindex >= len(td.put) { + return etcdserver.Response{}, &v2error.Error{ + ErrorCode: v2error.EcodeKeyNotFound, + } + } res := td.put[td.putindex] if res.Event == nil { td.putindex++ From ce50f68166c8896d2a2c3f383d4d8b00612bebfb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Manuel=20R=C3=BCger?= Date: Thu, 18 Nov 2021 14:08:54 +0100 Subject: [PATCH 047/258] *: Bump to go 1.17.5 --- .github/workflows/build.yaml | 2 +- .github/workflows/e2e.yaml | 2 +- .github/workflows/functional.yaml | 2 +- .github/workflows/grpcproxy.yaml | 2 +- .github/workflows/static-analysis.yaml | 2 +- .github/workflows/tests.yaml | 2 +- .travis.yml | 6 +++--- Makefile | 2 +- tests/functional/Dockerfile | 4 ++-- 9 files changed, 12 insertions(+), 12 deletions(-) diff --git a/.github/workflows/build.yaml b/.github/workflows/build.yaml index 3098ef2f6b9a..ec56df45d2e6 100644 --- a/.github/workflows/build.yaml +++ b/.github/workflows/build.yaml @@ -20,7 +20,7 @@ jobs: - uses: actions/checkout@v2 - uses: actions/setup-go@v2 with: - go-version: "1.17.2" + go-version: "1.17.5" - env: TARGET: ${{ matrix.target }} run: | diff --git a/.github/workflows/e2e.yaml b/.github/workflows/e2e.yaml index 2af1bbedc61f..ab7b1a51a2f6 100644 --- a/.github/workflows/e2e.yaml +++ b/.github/workflows/e2e.yaml @@ -13,7 +13,7 @@ jobs: - uses: actions/checkout@v2 - uses: actions/setup-go@v2 with: - go-version: "1.17.2" + go-version: "1.17.5" - run: date - env: TARGET: ${{ matrix.target }} diff --git a/.github/workflows/functional.yaml b/.github/workflows/functional.yaml index 28adf47e4bb8..5fbce8ac12e4 100644 --- a/.github/workflows/functional.yaml +++ b/.github/workflows/functional.yaml @@ -12,7 +12,7 @@ jobs: - uses: actions/checkout@v2 - uses: actions/setup-go@v2 with: - go-version: "1.17.2" + go-version: "1.17.5" - run: date - env: TARGET: ${{ matrix.target }} diff --git a/.github/workflows/grpcproxy.yaml b/.github/workflows/grpcproxy.yaml index 0559c123acb4..f4850a2dac5e 100644 --- a/.github/workflows/grpcproxy.yaml +++ b/.github/workflows/grpcproxy.yaml @@ -12,7 +12,7 @@ jobs: - uses: actions/checkout@v2 - uses: actions/setup-go@v2 with: - go-version: "1.17.2" + go-version: "1.17.5" - run: date - env: TARGET: ${{ matrix.target }} diff --git a/.github/workflows/static-analysis.yaml b/.github/workflows/static-analysis.yaml index 820f6114a792..5bba003c5e48 100644 --- a/.github/workflows/static-analysis.yaml +++ b/.github/workflows/static-analysis.yaml @@ -12,7 +12,7 @@ jobs: - uses: actions/checkout@v2 - uses: actions/setup-go@v2 with: - go-version: "1.17.2" + go-version: "1.17.5" - run: date - env: TARGET: ${{ matrix.target }} diff --git a/.github/workflows/tests.yaml b/.github/workflows/tests.yaml index f30e6e24490b..59a40253fa6b 100644 --- a/.github/workflows/tests.yaml +++ b/.github/workflows/tests.yaml @@ -16,7 +16,7 @@ jobs: - uses: actions/checkout@v2 - uses: actions/setup-go@v2 with: - go-version: "1.17.2" + go-version: "1.17.5" - run: date - env: TARGET: ${{ matrix.target }} diff --git a/.travis.yml b/.travis.yml index d80bc2867852..b0a2bcffc6fb 100644 --- a/.travis.yml +++ b/.travis.yml @@ -6,7 +6,7 @@ sudo: required services: docker go: - - "1.17.2" + - "1.17.5" - tip notifications: @@ -21,14 +21,14 @@ env: matrix: fast_finish: true allow_failures: - - go: "1.17.2" + - go: "1.17.5" env: TARGET=linux-amd64-coverage - go: tip env: TARGET=linux-amd64-fmt-unit-go-tip-2-cpu exclude: - go: tip env: TARGET=linux-amd64-coverage - - go: "1.17.2" + - go: "1.17.5" env: TARGET=linux-amd64-fmt-unit-go-tip-2-cpu before_install: diff --git a/Makefile b/Makefile index 9c7c1a1ae369..c293f7df8a43 100644 --- a/Makefile +++ b/Makefile @@ -39,7 +39,7 @@ clean: rm -rf ./tests/e2e/default.proxy find ./ -name "127.0.0.1:*" -o -name "localhost:*" -o -name "*.log" -o -name "agent-*" -o -name "*.coverprofile" -o -name "testname-proxy-*" | $(XARGS) -GO_VERSION ?= 1.17.2 +GO_VERSION ?= 1.17.5 ETCD_VERSION ?= $(shell git rev-parse --short HEAD || echo "GitNotFound") TEST_SUFFIX = $(shell date +%s | base64 | head -c 15) diff --git a/tests/functional/Dockerfile b/tests/functional/Dockerfile index 38c834bc77b5..52566b0f0128 100644 --- a/tests/functional/Dockerfile +++ b/tests/functional/Dockerfile @@ -1,4 +1,4 @@ -FROM fedora:28 +FROM fedora:35 RUN dnf check-update || true \ && dnf install --assumeyes \ @@ -13,7 +13,7 @@ RUN dnf check-update || true \ ENV GOROOT /usr/local/go ENV GOPATH /go ENV PATH ${GOPATH}/bin:${GOROOT}/bin:${PATH} -ENV GO_VERSION 1.14.3 +ENV GO_VERSION 1.17.5 ENV GO_DOWNLOAD_URL https://storage.googleapis.com/golang RUN rm -rf ${GOROOT} \ && curl -s ${GO_DOWNLOAD_URL}/go${GO_VERSION}.linux-amd64.tar.gz | tar -v -C /usr/local/ -xz \ From 9404d523b821df463d2f0e33911ca0b9bcf0e51d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Manuel=20R=C3=BCger?= Date: Fri, 17 Dec 2021 23:02:26 +0100 Subject: [PATCH 048/258] Build locally if docker-test container image does not exist This should make it easier to bump the golang version --- Makefile | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/Makefile b/Makefile index c293f7df8a43..d11f94d9fe7f 100644 --- a/Makefile +++ b/Makefile @@ -107,7 +107,10 @@ test-full: $(info log-file: test-$(TEST_SUFFIX).log) PASSES="fmt build release unit integration functional e2e grpcproxy" ./test.sh 2<&1 | tee test-$(TEST_SUFFIX).log -docker-test: +ensure-docker-test-image-exists: + make push-docker-test || echo "WARNING: Container Image not found in registry, building locally"; make build-docker-test + +docker-test: ensure-docker-test-image-exists $(info GO_VERSION: $(GO_VERSION)) $(info ETCD_VERSION: $(ETCD_VERSION)) $(info TEST_OPTS: $(TEST_OPTS)) From cf7e8b3535ce2b928bd125d2570543d8787806dc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Manuel=20R=C3=BCger?= Date: Fri, 17 Dec 2021 23:44:02 +0100 Subject: [PATCH 049/258] go.mod: Bump golang.org/x/net dependency; regenerate go.sum MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Bumps golang.org/x/net dependency due to fix CVE-2021-44716 as requested in https://github.com/etcd-io/etcd/pull/13487#issuecomment-997065540 Signed-off-by: Manuel Rüger --- etcdctl/go.mod | 2 +- etcdctl/go.sum | 4 ++-- etcdutl/go.mod | 2 +- etcdutl/go.sum | 4 ++-- go.mod | 2 +- go.sum | 5 ++-- server/go.mod | 2 +- server/go.sum | 4 ++-- tests/go.mod | 2 +- tests/go.sum | 5 ++-- tools/mod/go.mod | 59 +++++++++++++++++++++++++++++++++++++++++++----- 11 files changed, 70 insertions(+), 21 deletions(-) diff --git a/etcdctl/go.mod b/etcdctl/go.mod index f08655bde072..4415ebb8062b 100644 --- a/etcdctl/go.mod +++ b/etcdctl/go.mod @@ -51,7 +51,7 @@ require ( go.uber.org/atomic v1.7.0 // indirect go.uber.org/multierr v1.7.0 // indirect golang.org/x/crypto v0.0.0-20210513164829-c07d793c2f9a // indirect - golang.org/x/net v0.0.0-20211123203042-d83791d6bcd9 // indirect + golang.org/x/net v0.0.0-20220105145211-5b0dc2dfae98 // indirect golang.org/x/sys v0.0.0-20211123173158-ef496fb156ab // indirect golang.org/x/text v0.3.7 // indirect google.golang.org/genproto v0.0.0-20211118181313-81c1377c94b1 // indirect diff --git a/etcdctl/go.sum b/etcdctl/go.sum index 840df2269895..6c6ab82af702 100644 --- a/etcdctl/go.sum +++ b/etcdctl/go.sum @@ -382,8 +382,8 @@ golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwY golang.org/x/net v0.0.0-20201202161906-c7110b5ffcbb/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= golang.org/x/net v0.0.0-20210405180319-a5a99cb37ef4/go.mod h1:p54w0d4576C0XHj96bSt6lcn1PtDYWL6XObtHCRCNQM= -golang.org/x/net v0.0.0-20211123203042-d83791d6bcd9 h1:0qxwC5n+ttVOINCBeRHO0nq9X7uy8SDsPoi5OaCdIEI= -golang.org/x/net v0.0.0-20211123203042-d83791d6bcd9/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= +golang.org/x/net v0.0.0-20220105145211-5b0dc2dfae98 h1:+6WJMRLHlD7X7frgp7TUZ36RnQzSf9wVVTNakEp+nqY= +golang.org/x/net v0.0.0-20220105145211-5b0dc2dfae98/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= 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-20190604053449-0f29369cfe45/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= diff --git a/etcdutl/go.mod b/etcdutl/go.mod index 36acdf8ab910..a4e901a659ad 100644 --- a/etcdutl/go.mod +++ b/etcdutl/go.mod @@ -60,7 +60,7 @@ require ( go.uber.org/atomic v1.7.0 // indirect go.uber.org/multierr v1.7.0 // indirect golang.org/x/crypto v0.0.0-20210513164829-c07d793c2f9a // indirect - golang.org/x/net v0.0.0-20211123203042-d83791d6bcd9 // indirect + golang.org/x/net v0.0.0-20220105145211-5b0dc2dfae98 // indirect golang.org/x/sys v0.0.0-20211123173158-ef496fb156ab // indirect golang.org/x/text v0.3.7 // indirect golang.org/x/time v0.0.0-20210220033141-f8bda1e9f3ba // indirect diff --git a/etcdutl/go.sum b/etcdutl/go.sum index a602b0288081..68433db0af65 100644 --- a/etcdutl/go.sum +++ b/etcdutl/go.sum @@ -372,8 +372,8 @@ golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwY golang.org/x/net v0.0.0-20201202161906-c7110b5ffcbb/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= golang.org/x/net v0.0.0-20210405180319-a5a99cb37ef4/go.mod h1:p54w0d4576C0XHj96bSt6lcn1PtDYWL6XObtHCRCNQM= -golang.org/x/net v0.0.0-20211123203042-d83791d6bcd9 h1:0qxwC5n+ttVOINCBeRHO0nq9X7uy8SDsPoi5OaCdIEI= -golang.org/x/net v0.0.0-20211123203042-d83791d6bcd9/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= +golang.org/x/net v0.0.0-20220105145211-5b0dc2dfae98 h1:+6WJMRLHlD7X7frgp7TUZ36RnQzSf9wVVTNakEp+nqY= +golang.org/x/net v0.0.0-20220105145211-5b0dc2dfae98/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= 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-20190604053449-0f29369cfe45/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= diff --git a/go.mod b/go.mod index 0c8ef7897fa6..79187d7c775d 100644 --- a/go.mod +++ b/go.mod @@ -78,7 +78,7 @@ require ( go.uber.org/atomic v1.7.0 // indirect go.uber.org/multierr v1.7.0 // indirect golang.org/x/crypto v0.0.0-20210513164829-c07d793c2f9a // indirect - golang.org/x/net v0.0.0-20211123203042-d83791d6bcd9 // indirect + golang.org/x/net v0.0.0-20220105145211-5b0dc2dfae98 // indirect golang.org/x/sys v0.0.0-20211123173158-ef496fb156ab // indirect golang.org/x/text v0.3.7 // indirect google.golang.org/genproto v0.0.0-20211118181313-81c1377c94b1 // indirect diff --git a/go.sum b/go.sum index 5b24ff5fd3f7..0b08201c1ecb 100644 --- a/go.sum +++ b/go.sum @@ -393,8 +393,9 @@ golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwY golang.org/x/net v0.0.0-20201202161906-c7110b5ffcbb/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= golang.org/x/net v0.0.0-20210405180319-a5a99cb37ef4/go.mod h1:p54w0d4576C0XHj96bSt6lcn1PtDYWL6XObtHCRCNQM= -golang.org/x/net v0.0.0-20211123203042-d83791d6bcd9 h1:0qxwC5n+ttVOINCBeRHO0nq9X7uy8SDsPoi5OaCdIEI= -golang.org/x/net v0.0.0-20211123203042-d83791d6bcd9/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= +golang.org/x/net v0.0.0-20211216030914-fe4d6282115f/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= +golang.org/x/net v0.0.0-20220105145211-5b0dc2dfae98 h1:+6WJMRLHlD7X7frgp7TUZ36RnQzSf9wVVTNakEp+nqY= +golang.org/x/net v0.0.0-20220105145211-5b0dc2dfae98/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= 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-20190604053449-0f29369cfe45/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= diff --git a/server/go.mod b/server/go.mod index 79941642cd01..8e6f9856085c 100644 --- a/server/go.mod +++ b/server/go.mod @@ -36,7 +36,7 @@ require ( go.uber.org/multierr v1.7.0 go.uber.org/zap v1.17.0 golang.org/x/crypto v0.0.0-20210513164829-c07d793c2f9a - golang.org/x/net v0.0.0-20211123203042-d83791d6bcd9 + golang.org/x/net v0.0.0-20220105145211-5b0dc2dfae98 golang.org/x/time v0.0.0-20210220033141-f8bda1e9f3ba google.golang.org/genproto v0.0.0-20211118181313-81c1377c94b1 google.golang.org/grpc v1.41.0 diff --git a/server/go.sum b/server/go.sum index 914b7082fcdb..f63e0b1cd395 100644 --- a/server/go.sum +++ b/server/go.sum @@ -383,8 +383,8 @@ golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwY golang.org/x/net v0.0.0-20201202161906-c7110b5ffcbb/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= golang.org/x/net v0.0.0-20210405180319-a5a99cb37ef4/go.mod h1:p54w0d4576C0XHj96bSt6lcn1PtDYWL6XObtHCRCNQM= -golang.org/x/net v0.0.0-20211123203042-d83791d6bcd9 h1:0qxwC5n+ttVOINCBeRHO0nq9X7uy8SDsPoi5OaCdIEI= -golang.org/x/net v0.0.0-20211123203042-d83791d6bcd9/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= +golang.org/x/net v0.0.0-20220105145211-5b0dc2dfae98 h1:+6WJMRLHlD7X7frgp7TUZ36RnQzSf9wVVTNakEp+nqY= +golang.org/x/net v0.0.0-20220105145211-5b0dc2dfae98/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= 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-20190604053449-0f29369cfe45/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= diff --git a/tests/go.mod b/tests/go.mod index c731dbc22edd..96090ed63303 100644 --- a/tests/go.mod +++ b/tests/go.mod @@ -74,7 +74,7 @@ require ( go.opentelemetry.io/proto/otlp v0.10.0 // indirect go.uber.org/atomic v1.7.0 // indirect go.uber.org/multierr v1.7.0 // indirect - golang.org/x/net v0.0.0-20211123203042-d83791d6bcd9 // indirect + golang.org/x/net v0.0.0-20220105145211-5b0dc2dfae98 // indirect golang.org/x/sys v0.0.0-20211123173158-ef496fb156ab // indirect golang.org/x/text v0.3.7 // indirect google.golang.org/genproto v0.0.0-20211118181313-81c1377c94b1 // indirect diff --git a/tests/go.sum b/tests/go.sum index 12df68590eaf..a20e4dbfa8fe 100644 --- a/tests/go.sum +++ b/tests/go.sum @@ -386,8 +386,9 @@ golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwY golang.org/x/net v0.0.0-20201202161906-c7110b5ffcbb/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= golang.org/x/net v0.0.0-20210405180319-a5a99cb37ef4/go.mod h1:p54w0d4576C0XHj96bSt6lcn1PtDYWL6XObtHCRCNQM= -golang.org/x/net v0.0.0-20211123203042-d83791d6bcd9 h1:0qxwC5n+ttVOINCBeRHO0nq9X7uy8SDsPoi5OaCdIEI= -golang.org/x/net v0.0.0-20211123203042-d83791d6bcd9/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= +golang.org/x/net v0.0.0-20211216030914-fe4d6282115f/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= +golang.org/x/net v0.0.0-20220105145211-5b0dc2dfae98 h1:+6WJMRLHlD7X7frgp7TUZ36RnQzSf9wVVTNakEp+nqY= +golang.org/x/net v0.0.0-20220105145211-5b0dc2dfae98/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= 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-20190604053449-0f29369cfe45/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= diff --git a/tools/mod/go.mod b/tools/mod/go.mod index 6f05b8540160..0edf747f5019 100644 --- a/tools/mod/go.mod +++ b/tools/mod/go.mod @@ -3,12 +3,9 @@ module go.etcd.io/etcd/tools/v3 go 1.17 require ( - github.com/akhenakh/hunspellgo v0.0.0-20160221122622-9db38fa26e19 // indirect github.com/alexkohler/nakedret v1.0.0 github.com/chzchzchz/goword v0.0.0-20170907005317-a9744cb52b03 github.com/coreos/license-bill-of-materials v0.0.0-20190913234955-13baff47494e - github.com/go-openapi/loads v0.19.5 // indirect - github.com/go-openapi/spec v0.19.9 // indirect github.com/gogo/protobuf v1.3.2 github.com/google/addlicense v0.0.0-20210428195630-6d92264d7170 github.com/gordonklaus/ineffassign v0.0.0-20200809085317-e36bfde3bb78 @@ -18,12 +15,62 @@ require ( github.com/mdempsky/unconvert v0.0.0-20200228143138-95ecdbfc0b5f github.com/mgechev/revive v1.0.2 github.com/mikefarah/yq/v3 v3.0.0-20201125113350-f42728eef735 - github.com/trustmaster/go-aspell v0.0.0-20200701131845-c2b1f55bec8f // indirect go.etcd.io/protodoc v0.0.0-20180829002748-484ab544e116 - google.golang.org/genproto v0.0.0-20201008135153-289734e2e40c // indirect - gopkg.in/yaml.v2 v2.3.0 // indirect gotest.tools v2.2.0+incompatible gotest.tools/gotestsum v0.3.5 honnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc mvdan.cc/unparam v0.0.0-20200501210554-b37ab49443f7 ) + +require ( + github.com/BurntSushi/toml v0.3.1 // indirect + github.com/PuerkitoBio/purell v1.1.1 // indirect + github.com/PuerkitoBio/urlesc v0.0.0-20170810143723-de5bf2ad4578 // indirect + github.com/akhenakh/hunspellgo v0.0.0-20160221122622-9db38fa26e19 // indirect + github.com/asaskevich/govalidator v0.0.0-20200108200545-475eaeb16496 // indirect + github.com/fatih/color v1.9.0 // indirect + github.com/fatih/structtag v1.2.0 // indirect + github.com/ghodss/yaml v1.0.0 // indirect + github.com/go-openapi/analysis v0.19.10 // indirect + github.com/go-openapi/errors v0.19.3 // indirect + github.com/go-openapi/jsonpointer v0.19.3 // indirect + github.com/go-openapi/jsonreference v0.19.4 // indirect + github.com/go-openapi/loads v0.19.5 // indirect + github.com/go-openapi/spec v0.19.9 // indirect + github.com/go-openapi/strfmt v0.19.4 // indirect + github.com/go-openapi/swag v0.19.7 // indirect + github.com/go-stack/stack v1.8.0 // indirect + github.com/goccy/go-yaml v1.8.1 // indirect + github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b // indirect + github.com/golang/protobuf v1.4.1 // indirect + github.com/inconshreveable/mousetrap v1.0.0 // indirect + github.com/jonboulle/clockwork v0.1.0 // indirect + github.com/konsorten/go-windows-terminal-sequences v1.0.2 // indirect + github.com/kylelemons/godebug v1.1.0 // indirect + github.com/mailru/easyjson v0.7.1 // indirect + github.com/mattn/go-colorable v0.1.7 // indirect + github.com/mattn/go-isatty v0.0.12 // indirect + github.com/mattn/go-runewidth v0.0.7 // indirect + github.com/mgechev/dots v0.0.0-20190921121421-c36f7dcfbb81 // indirect + github.com/mitchellh/go-homedir v1.1.0 // indirect + github.com/mitchellh/mapstructure v1.1.2 // indirect + github.com/olekukonko/tablewriter v0.0.4 // indirect + github.com/pkg/errors v0.9.1 // indirect + github.com/sirupsen/logrus v1.4.2 // indirect + github.com/spf13/cobra v1.0.0 // indirect + github.com/spf13/pflag v1.0.5 // indirect + github.com/trustmaster/go-aspell v0.0.0-20200701131845-c2b1f55bec8f // indirect + go.mongodb.org/mongo-driver v1.3.0 // indirect + golang.org/x/mod v0.3.0 // indirect + golang.org/x/net v0.0.0-20201021035429-f5854403a974 // indirect + golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9 // indirect + golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f // indirect + golang.org/x/text v0.3.3 // indirect + golang.org/x/tools v0.0.0-20210106214847-113979e3529a // indirect + golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1 // indirect + google.golang.org/genproto v0.0.0-20201008135153-289734e2e40c // indirect + google.golang.org/protobuf v1.24.0 // indirect + gopkg.in/op/go-logging.v1 v1.0.0-20160211212156-b2cb9fa56473 // indirect + gopkg.in/yaml.v2 v2.3.0 // indirect + gopkg.in/yaml.v3 v3.0.0-20200615113413-eeeca48fe776 // indirect +) From 746c0ea276d3d02f379b548f9c9bd97264b9a74a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Manuel=20R=C3=BCger?= Date: Wed, 12 Jan 2022 02:49:14 +0100 Subject: [PATCH 050/258] tests/Dockerfile: Update base to ubuntu 21.10 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Manuel Rüger --- tests/Dockerfile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/Dockerfile b/tests/Dockerfile index 8774811f368a..f6e5e7447cf0 100644 --- a/tests/Dockerfile +++ b/tests/Dockerfile @@ -1,4 +1,4 @@ -FROM ubuntu:20.10 +FROM ubuntu:21.10 RUN rm /bin/sh && ln -s /bin/bash /bin/sh RUN echo 'debconf debconf/frontend select Noninteractive' | debconf-set-selections From ce086a4ba60afc1b27185e6b21846b2de7a30922 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Manuel=20R=C3=BCger?= Date: Wed, 12 Jan 2022 02:51:55 +0100 Subject: [PATCH 051/258] *: Bump to go 1.17.6 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Manuel Rüger --- .github/workflows/build.yaml | 2 +- .github/workflows/e2e.yaml | 2 +- .github/workflows/functional.yaml | 2 +- .github/workflows/grpcproxy.yaml | 2 +- .github/workflows/static-analysis.yaml | 2 +- .github/workflows/tests.yaml | 2 +- .travis.yml | 6 +++--- Makefile | 2 +- tests/functional/Dockerfile | 2 +- 9 files changed, 11 insertions(+), 11 deletions(-) diff --git a/.github/workflows/build.yaml b/.github/workflows/build.yaml index ec56df45d2e6..6601f89364bd 100644 --- a/.github/workflows/build.yaml +++ b/.github/workflows/build.yaml @@ -20,7 +20,7 @@ jobs: - uses: actions/checkout@v2 - uses: actions/setup-go@v2 with: - go-version: "1.17.5" + go-version: "1.17.6" - env: TARGET: ${{ matrix.target }} run: | diff --git a/.github/workflows/e2e.yaml b/.github/workflows/e2e.yaml index ab7b1a51a2f6..50e40b10ce76 100644 --- a/.github/workflows/e2e.yaml +++ b/.github/workflows/e2e.yaml @@ -13,7 +13,7 @@ jobs: - uses: actions/checkout@v2 - uses: actions/setup-go@v2 with: - go-version: "1.17.5" + go-version: "1.17.6" - run: date - env: TARGET: ${{ matrix.target }} diff --git a/.github/workflows/functional.yaml b/.github/workflows/functional.yaml index 5fbce8ac12e4..331cf96cded8 100644 --- a/.github/workflows/functional.yaml +++ b/.github/workflows/functional.yaml @@ -12,7 +12,7 @@ jobs: - uses: actions/checkout@v2 - uses: actions/setup-go@v2 with: - go-version: "1.17.5" + go-version: "1.17.6" - run: date - env: TARGET: ${{ matrix.target }} diff --git a/.github/workflows/grpcproxy.yaml b/.github/workflows/grpcproxy.yaml index f4850a2dac5e..27ec0ab6c216 100644 --- a/.github/workflows/grpcproxy.yaml +++ b/.github/workflows/grpcproxy.yaml @@ -12,7 +12,7 @@ jobs: - uses: actions/checkout@v2 - uses: actions/setup-go@v2 with: - go-version: "1.17.5" + go-version: "1.17.6" - run: date - env: TARGET: ${{ matrix.target }} diff --git a/.github/workflows/static-analysis.yaml b/.github/workflows/static-analysis.yaml index 5bba003c5e48..d6ad2384e8b9 100644 --- a/.github/workflows/static-analysis.yaml +++ b/.github/workflows/static-analysis.yaml @@ -12,7 +12,7 @@ jobs: - uses: actions/checkout@v2 - uses: actions/setup-go@v2 with: - go-version: "1.17.5" + go-version: "1.17.6" - run: date - env: TARGET: ${{ matrix.target }} diff --git a/.github/workflows/tests.yaml b/.github/workflows/tests.yaml index 59a40253fa6b..bdf47553d5d1 100644 --- a/.github/workflows/tests.yaml +++ b/.github/workflows/tests.yaml @@ -16,7 +16,7 @@ jobs: - uses: actions/checkout@v2 - uses: actions/setup-go@v2 with: - go-version: "1.17.5" + go-version: "1.17.6" - run: date - env: TARGET: ${{ matrix.target }} diff --git a/.travis.yml b/.travis.yml index b0a2bcffc6fb..9f4d26bfb721 100644 --- a/.travis.yml +++ b/.travis.yml @@ -6,7 +6,7 @@ sudo: required services: docker go: - - "1.17.5" + - "1.17.6" - tip notifications: @@ -21,14 +21,14 @@ env: matrix: fast_finish: true allow_failures: - - go: "1.17.5" + - go: "1.17.6" env: TARGET=linux-amd64-coverage - go: tip env: TARGET=linux-amd64-fmt-unit-go-tip-2-cpu exclude: - go: tip env: TARGET=linux-amd64-coverage - - go: "1.17.5" + - go: "1.17.6" env: TARGET=linux-amd64-fmt-unit-go-tip-2-cpu before_install: diff --git a/Makefile b/Makefile index d11f94d9fe7f..9f213bdb2886 100644 --- a/Makefile +++ b/Makefile @@ -39,7 +39,7 @@ clean: rm -rf ./tests/e2e/default.proxy find ./ -name "127.0.0.1:*" -o -name "localhost:*" -o -name "*.log" -o -name "agent-*" -o -name "*.coverprofile" -o -name "testname-proxy-*" | $(XARGS) -GO_VERSION ?= 1.17.5 +GO_VERSION ?= 1.17.6 ETCD_VERSION ?= $(shell git rev-parse --short HEAD || echo "GitNotFound") TEST_SUFFIX = $(shell date +%s | base64 | head -c 15) diff --git a/tests/functional/Dockerfile b/tests/functional/Dockerfile index 52566b0f0128..c59d4872ceea 100644 --- a/tests/functional/Dockerfile +++ b/tests/functional/Dockerfile @@ -13,7 +13,7 @@ RUN dnf check-update || true \ ENV GOROOT /usr/local/go ENV GOPATH /go ENV PATH ${GOPATH}/bin:${GOROOT}/bin:${PATH} -ENV GO_VERSION 1.17.5 +ENV GO_VERSION 1.17.6 ENV GO_DOWNLOAD_URL https://storage.googleapis.com/golang RUN rm -rf ${GOROOT} \ && curl -s ${GO_DOWNLOAD_URL}/go${GO_VERSION}.linux-amd64.tar.gz | tar -v -C /usr/local/ -xz \ From eac6d71352b19f2e6f8368cc8f95650d07ca1133 Mon Sep 17 00:00:00 2001 From: Marek Siarkowicz Date: Tue, 11 Jan 2022 17:00:16 +0100 Subject: [PATCH 052/258] tests: Add integration test for revision monotonic under failure injection --- .../clientv3/concurrency/revision_test.go | 164 ++++++++++++++++++ 1 file changed, 164 insertions(+) create mode 100644 tests/integration/clientv3/concurrency/revision_test.go diff --git a/tests/integration/clientv3/concurrency/revision_test.go b/tests/integration/clientv3/concurrency/revision_test.go new file mode 100644 index 000000000000..c0a08c454f90 --- /dev/null +++ b/tests/integration/clientv3/concurrency/revision_test.go @@ -0,0 +1,164 @@ +// Copyright 2022 The etcd Authors +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package concurrency_test + +import ( + "context" + "errors" + "fmt" + "strings" + "sync" + "testing" + "time" + + "go.etcd.io/etcd/tests/v3/framework/integration" + "google.golang.org/grpc/status" +) + +func TestRevisionMonotonicWithLeaderPartitions(t *testing.T) { + testRevisionMonotonicWithFailures(t, 11*time.Second, func(clus *integration.ClusterV3) { + for i := 0; i < 5; i++ { + leader := clus.WaitLeader(t) + time.Sleep(time.Second) + clus.Members[leader].InjectPartition(t, clus.Members[(leader+1)%3], clus.Members[(leader+2)%3]) + time.Sleep(time.Second) + clus.Members[leader].RecoverPartition(t, clus.Members[(leader+1)%3], clus.Members[(leader+2)%3]) + } + }) +} + +func TestRevisionMonotonicWithPartitions(t *testing.T) { + testRevisionMonotonicWithFailures(t, 11*time.Second, func(clus *integration.ClusterV3) { + for i := 0; i < 5; i++ { + time.Sleep(time.Second) + clus.Members[i%3].InjectPartition(t, clus.Members[(i+1)%3], clus.Members[(i+2)%3]) + time.Sleep(time.Second) + clus.Members[i%3].RecoverPartition(t, clus.Members[(i+1)%3], clus.Members[(i+2)%3]) + } + }) +} + +func TestRevisionMonotonicWithLeaderRestarts(t *testing.T) { + testRevisionMonotonicWithFailures(t, 11*time.Second, func(clus *integration.ClusterV3) { + for i := 0; i < 5; i++ { + leader := clus.WaitLeader(t) + time.Sleep(time.Second) + clus.Members[leader].Stop(t) + time.Sleep(time.Second) + clus.Members[leader].Restart(t) + } + }) +} + +func TestRevisionMonotonicWithRestarts(t *testing.T) { + testRevisionMonotonicWithFailures(t, 11*time.Second, func(clus *integration.ClusterV3) { + for i := 0; i < 5; i++ { + time.Sleep(time.Second) + clus.Members[i%3].Stop(t) + time.Sleep(time.Second) + clus.Members[i%3].Restart(t) + } + }) +} + +func testRevisionMonotonicWithFailures(t *testing.T, testDuration time.Duration, injectFailures func(clus *integration.ClusterV3)) { + integration.BeforeTest(t) + clus := integration.NewClusterV3(t, &integration.ClusterConfig{Size: 3, UseBridge: true}) + defer clus.Terminate(t) + + ctx, cancel := context.WithTimeout(context.Background(), testDuration) + defer cancel() + + wg := sync.WaitGroup{} + for i := 0; i < 10; i++ { + wg.Add(1) + go func() { + defer wg.Done() + putWorker(t, ctx, clus) + }() + } + + for i := 0; i < 10; i++ { + wg.Add(1) + go func() { + defer wg.Done() + getWorker(t, ctx, clus) + }() + } + + injectFailures(clus) + wg.Wait() + kv := clus.Client(0) + resp, err := kv.Get(context.Background(), "foo") + if err != nil { + t.Fatal(err) + } + t.Logf("Revision %d", resp.Header.Revision) +} + +func putWorker(t *testing.T, ctx context.Context, clus *integration.ClusterV3) { + for i := 0; ; i++ { + kv := clus.Client(i % 3) + _, err := kv.Put(ctx, "foo", fmt.Sprintf("%d", i)) + if errors.Is(err, context.DeadlineExceeded) { + return + } + if silenceConnectionErrors(err) != nil { + t.Fatal(err) + } + } +} + +func getWorker(t *testing.T, ctx context.Context, clus *integration.ClusterV3) { + var prevRev int64 + for i := 0; ; i++ { + kv := clus.Client(i % 3) + resp, err := kv.Get(ctx, "foo") + if errors.Is(err, context.DeadlineExceeded) { + return + } + if silenceConnectionErrors(err) != nil { + t.Fatal(err) + } + if resp == nil { + continue + } + if prevRev > resp.Header.Revision { + t.Fatalf("rev is less than previously observed revision, rev: %d, prevRev: %d", resp.Header.Revision, prevRev) + } + prevRev = resp.Header.Revision + } +} + +func silenceConnectionErrors(err error) error { + if err == nil { + return nil + } + s := status.Convert(err) + for _, msg := range connectionErrorMessages { + if strings.Index(s.Message(), msg) != -1 { + return nil + } + } + return err +} + +var connectionErrorMessages = []string{ + "context deadline exceeded", + "etcdserver: request timed out", + "error reading from server: EOF", + "read: connection reset by peer", + "use of closed network connection", +} From 5e06fd40da367af82aaa89360a16a8162412c600 Mon Sep 17 00:00:00 2001 From: Marek Siarkowicz Date: Wed, 12 Jan 2022 13:39:30 +0100 Subject: [PATCH 053/258] README: Cleanup community meetings video recordings --- README.md | 33 ++++----------------------------- 1 file changed, 4 insertions(+), 29 deletions(-) diff --git a/README.md b/README.md index f91eb7441148..cdbc2e31034f 100644 --- a/README.md +++ b/README.md @@ -41,40 +41,15 @@ etcd contributors and maintainers have monthly (every four weeks) meetings at 11 An initial agenda will be posted to the [shared Google docs][shared-meeting-notes] a day before each meeting, and everyone is welcome to suggest additional topics or other agendas. -[shared-meeting-notes]: https://docs.google.com/document/d/16XEGyPBisZvmmoIHSZzv__LoyOeluC5a4x353CX0SIM/edit - - -Time: -- [Jan 10th, 2019 11:00 AM video](https://www.youtube.com/watch?v=0Cphtbd1OSc&feature=youtu.be) -- [Feb 7th, 2019 11:00 AM video](https://youtu.be/U80b--oAlYM) -- [Mar 7th, 2019 11:00 AM video](https://youtu.be/w9TI5B7D1zg) -- [Apr 4th, 2019 11:00 AM video](https://youtu.be/oqQR2XH1L_A) -- [May 2nd, 2019 11:00 AM video](https://youtu.be/wFwQePuDWVw) -- [May 30th, 2019 11:00 AM video](https://youtu.be/2t1R5NATYG4) -- [Jul 11th, 2019 11:00 AM video](https://youtu.be/k_FZEipWD6Y) -- [Jul 25, 2019 11:00 AM video](https://youtu.be/VSUJTACO93I) -- [Aug 22, 2019 11:00 AM video](https://youtu.be/6IBQ-VxQmuM) -- [Sep 19, 2019 11:00 AM video](https://youtu.be/SqfxU9DhBOc) -- Nov 14, 2019 11:00 AM -- Dec 12, 2019 11:00 AM -- Jan 09, 2020 11:00 AM -- Feb 06, 2020 11:00 AM -- Mar 05, 2020 11:00 AM -- Apr 02, 2020 11:00 AM -- Apr 30, 2020 11:00 AM -- May 28, 2020 11:00 AM -- Jun 25, 2020 11:00 AM -- Jul 23, 2020 11:00 AM -- Aug 20, 2020 11:00 AM -- Sep 17, 2020 11:00 AM -- Oct 15, 2020 11:00 AM -- Nov 12, 2020 11:00 AM -- Dec 10, 2020 11:00 AM +Meeting recordings are uploaded to [Etcd YouTube channel]. Join Hangouts Meet: [meet.google.com/umg-nrxn-qvs](https://meet.google.com/umg-nrxn-qvs) Join by phone: +1 405-792-0633‬ PIN: ‪299 906‬# +[shared-meeting-notes]: https://docs.google.com/document/d/16XEGyPBisZvmmoIHSZzv__LoyOeluC5a4x353CX0SIM/edit +[Etcd YouTube channel]: https://www.youtube.com/channel/UC7tUWR24I5AR9NMsG-NYBlg + ## Maintainers [MAINTAINERS](MAINTAINERS) strive to shape an inclusive open source project culture where users are heard and contributors feel respected and empowered. MAINTAINERS maintain productive relationships across different companies and disciplines. Read more about [MAINTAINERS role and responsibilities](GOVERNANCE.md#maintainers). From 6ef154e5488ff2dce3a1a60dcc886cebb676bb87 Mon Sep 17 00:00:00 2001 From: ahrtr Date: Thu, 13 Jan 2022 14:55:08 +0800 Subject: [PATCH 054/258] update CHANGELOG-3.5.md to cover the fix for issue 13494 --- CHANGELOG-3.5.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG-3.5.md b/CHANGELOG-3.5.md index 4cf6d4855886..6699fe17034f 100644 --- a/CHANGELOG-3.5.md +++ b/CHANGELOG-3.5.md @@ -15,6 +15,7 @@ See [code changes](https://github.com/etcd-io/etcd/compare/v3.5.1...v3.5.2) and - Fix [exclude the same alarm type activated by multiple peers](https://github.com/etcd-io/etcd/pull/13476). - Add [`etcd --experimental-enable-lease-checkpoint-persist`](https://github.com/etcd-io/etcd/pull/13508) flag to enable checkpoint persisting. - Fix [Lease checkpoints don't prevent to reset ttl on leader change](https://github.com/etcd-io/etcd/pull/13508), requires enabling checkpoint persisting. +- Fix [assertion failed due to tx closed when recovering v3 backend from a snapshot db](https://github.com/etcd-io/etcd/pull/13501)
From 4032d4f66a53acda7e9e6da8d55d0e0aab65012d Mon Sep 17 00:00:00 2001 From: Marek Siarkowicz Date: Wed, 12 Jan 2022 16:24:54 +0100 Subject: [PATCH 055/258] Remove CodeQL errors --- client/v2/curl.go | 2 +- etcdutl/etcdutl/backup_command.go | 1 - tools/etcd-dump-db/backend.go | 2 +- tools/etcd-dump-logs/main.go | 4 ++++ 4 files changed, 6 insertions(+), 3 deletions(-) diff --git a/client/v2/curl.go b/client/v2/curl.go index b05ebce50e8f..8d12367541ef 100644 --- a/client/v2/curl.go +++ b/client/v2/curl.go @@ -60,7 +60,7 @@ func printcURL(req *http.Request) error { command += fmt.Sprintf(" -d %q", string(b)) } - fmt.Fprintf(os.Stderr, "cURL Command: %s\n", command) + fmt.Fprintf(os.Stderr, "cURL Command: %q\n", command) // reset body body := bytes.NewBuffer(b) diff --git a/etcdutl/etcdutl/backup_command.go b/etcdutl/etcdutl/backup_command.go index 13e6eb76b885..ce9b50bd9aa3 100644 --- a/etcdutl/etcdutl/backup_command.go +++ b/etcdutl/etcdutl/backup_command.go @@ -286,7 +286,6 @@ func saveDB(lg *zap.Logger, destDB, srcDB string, idx uint64, term uint64, desir case src = <-ch: case <-time.After(time.Second): lg.Fatal("timed out waiting to acquire lock on", zap.String("srcDB", srcDB)) - src = <-ch } defer src.Close() diff --git a/tools/etcd-dump-db/backend.go b/tools/etcd-dump-db/backend.go index 7962007f8b17..3306f7f70b4d 100644 --- a/tools/etcd-dump-db/backend.go +++ b/tools/etcd-dump-db/backend.go @@ -122,7 +122,7 @@ func authUsersDecoder(k, v []byte) { if err != nil { panic(err) } - fmt.Printf("user=%q, roles=%q, password=%q, option=%v\n", user.Name, user.Roles, string(user.Password), user.Options) + fmt.Printf("user=%q, roles=%q, option=%v\n", user.Name, user.Roles, user.Options) } func iterateBucket(dbPath, bucket string, limit uint64, decode bool) (err error) { diff --git a/tools/etcd-dump-logs/main.go b/tools/etcd-dump-logs/main.go index 15c76a40ad7f..899f40591d26 100644 --- a/tools/etcd-dump-logs/main.go +++ b/tools/etcd-dump-logs/main.go @@ -232,6 +232,10 @@ type EntryPrinter func(e raftpb.Entry) func printInternalRaftRequest(entry raftpb.Entry) { var rr etcdserverpb.InternalRaftRequest if err := rr.Unmarshal(entry.Data); err == nil { + // Ensure we don't log user password + if rr.AuthUserChangePassword != nil && rr.AuthUserChangePassword.Password != "" { + rr.AuthUserChangePassword.Password = "" + } fmt.Printf("%4d\t%10d\tnorm\t%s", entry.Term, entry.Index, rr.String()) } } From 357006172db790bea80db8decba652f930fc61ef Mon Sep 17 00:00:00 2001 From: Michael Hoffmann Date: Fri, 14 Jan 2022 12:51:04 +0100 Subject: [PATCH 056/258] ctlv3: add forgotten member promote method to printerRPC The printerRPC struct was missing a MemberPromote method, leading to panic in ectdctl when trying to print it as JSON. This PR fixes that panic. --- etcdctl/ctlv3/command/printer.go | 3 +++ 1 file changed, 3 insertions(+) diff --git a/etcdctl/ctlv3/command/printer.go b/etcdctl/ctlv3/command/printer.go index 2d31d9ec8c6b..4cb18f437713 100644 --- a/etcdctl/ctlv3/command/printer.go +++ b/etcdctl/ctlv3/command/printer.go @@ -110,6 +110,9 @@ func (p *printerRPC) MemberRemove(id uint64, r v3.MemberRemoveResponse) { func (p *printerRPC) MemberUpdate(id uint64, r v3.MemberUpdateResponse) { p.p((*pb.MemberUpdateResponse)(&r)) } +func (p *printerRPC) MemberPromote(id uint64, r v3.MemberPromoteResponse) { + p.p((*pb.MemberPromoteResponse)(&r)) +} func (p *printerRPC) MemberList(r v3.MemberListResponse) { p.p((*pb.MemberListResponse)(&r)) } func (p *printerRPC) Alarm(r v3.AlarmResponse) { p.p((*pb.AlarmResponse)(&r)) } func (p *printerRPC) MoveLeader(leader, target uint64, r v3.MoveLeaderResponse) { From ee5ef42c5c98715028f891f67add188864c872c7 Mon Sep 17 00:00:00 2001 From: Marek Siarkowicz Date: Thu, 13 Jan 2022 15:44:47 +0100 Subject: [PATCH 057/258] server: --enable-v2 and --enable-v2v3 is decomissioned --- client/v2/example_keys_test.go | 1 - etcd.conf.yml.sample | 3 - server/embed/config.go | 13 - server/embed/etcd.go | 27 +- server/etcdmain/config.go | 2 - server/etcdmain/help.go | 4 - server/etcdserver/api/v2v3/cluster.go | 31 - server/etcdserver/api/v2v3/doc.go | 16 - server/etcdserver/api/v2v3/server.go | 130 -- server/etcdserver/api/v2v3/store.go | 638 --------- server/etcdserver/api/v2v3/watcher.go | 142 -- server/etcdserver/server.go | 3 +- test.sh | 4 +- tests/e2e/ctl_v2_test.go | 535 -------- tests/e2e/ctl_v3_move_leader_test.go | 11 + tests/e2e/v2_curl_test.go | 115 -- tests/e2e/v2store_deprecation_test.go | 30 +- tests/framework/e2e/cluster.go | 1 - tests/framework/e2e/v2.go | 20 - tests/framework/e2e/v2v3.go | 22 - .../client/examples/example_keys_test.go | 111 -- .../integration/client/examples/main_test.go | 44 - tests/integration/v2_http_kv_test.go | 1152 ----------------- ...tag_not_v2v3_test.go => store_tag_test.go} | 21 +- .../v2store/store_tag_v2v3_test.go | 44 - tests/integration/v2store/store_test.go | 117 +- tests/integration/v2store/store_v2v3_test.go | 165 --- 27 files changed, 69 insertions(+), 3333 deletions(-) delete mode 120000 client/v2/example_keys_test.go delete mode 100644 server/etcdserver/api/v2v3/cluster.go delete mode 100644 server/etcdserver/api/v2v3/doc.go delete mode 100644 server/etcdserver/api/v2v3/server.go delete mode 100644 server/etcdserver/api/v2v3/store.go delete mode 100644 server/etcdserver/api/v2v3/watcher.go delete mode 100644 tests/e2e/ctl_v2_test.go delete mode 100644 tests/e2e/v2_curl_test.go delete mode 100644 tests/framework/e2e/v2.go delete mode 100644 tests/framework/e2e/v2v3.go delete mode 100644 tests/integration/client/examples/example_keys_test.go delete mode 100644 tests/integration/client/examples/main_test.go delete mode 100644 tests/integration/v2_http_kv_test.go rename tests/integration/v2store/{store_tag_not_v2v3_test.go => store_tag_test.go} (84%) delete mode 100644 tests/integration/v2store/store_tag_v2v3_test.go delete mode 100644 tests/integration/v2store/store_v2v3_test.go diff --git a/client/v2/example_keys_test.go b/client/v2/example_keys_test.go deleted file mode 120000 index 1e4520ddfe9d..000000000000 --- a/client/v2/example_keys_test.go +++ /dev/null @@ -1 +0,0 @@ -../../tests/integration/client/examples/example_keys_test.go \ No newline at end of file diff --git a/etcd.conf.yml.sample b/etcd.conf.yml.sample index 16da4f8fe76d..38d74bcb7935 100644 --- a/etcd.conf.yml.sample +++ b/etcd.conf.yml.sample @@ -69,9 +69,6 @@ initial-cluster-state: 'new' # Reject reconfiguration requests that would cause quorum loss. strict-reconfig-check: false -# Accept etcd V2 client requests -enable-v2: true - # Enable runtime profiling data via HTTP server enable-pprof: true diff --git a/server/embed/config.go b/server/embed/config.go index c168fe8411fe..46d9df0add6a 100644 --- a/server/embed/config.go +++ b/server/embed/config.go @@ -86,9 +86,6 @@ const ( // DefaultStrictReconfigCheck is the default value for "--strict-reconfig-check" flag. // It's enabled by default. DefaultStrictReconfigCheck = true - // DefaultEnableV2 is the default value for "--enable-v2" flag. - // v2 API is disabled by default. - DefaultEnableV2 = false // maxElectionMs specifies the maximum value of election timeout. // More details are listed in ../Documentation/tuning.md#time-parameters. @@ -224,11 +221,6 @@ type Config struct { InitialClusterToken string `json:"initial-cluster-token"` StrictReconfigCheck bool `json:"strict-reconfig-check"` - // EnableV2 exposes the deprecated V2 API surface. - // TODO: Delete in 3.6 (https://github.com/etcd-io/etcd/issues/12913) - // Deprecated in 3.5. - EnableV2 bool `json:"enable-v2"` - // AutoCompactionMode is either 'periodic' or 'revision'. AutoCompactionMode string `json:"auto-compaction-mode"` // AutoCompactionRetention is either duration string with time unit @@ -311,10 +303,6 @@ type Config struct { ExperimentalInitialCorruptCheck bool `json:"experimental-initial-corrupt-check"` ExperimentalCorruptCheckTime time.Duration `json:"experimental-corrupt-check-time"` - // ExperimentalEnableV2V3 configures URLs that expose deprecated V2 API working on V3 store. - // Deprecated in v3.5. - // TODO: Delete in v3.6 (https://github.com/etcd-io/etcd/issues/12913) - ExperimentalEnableV2V3 string `json:"experimental-enable-v2v3"` // ExperimentalEnableLeaseCheckpoint enables leader to send regular checkpoints to other members to prevent reset of remaining TTL on leader change. ExperimentalEnableLeaseCheckpoint bool `json:"experimental-enable-lease-checkpoint"` // ExperimentalEnableLeaseCheckpointPersist enables persisting remainingTTL to prevent indefinite auto-renewal of long lived leases. Always enabled in v3.6. Should be used to ensure smooth upgrade from v3.5 clusters with this feature enabled. @@ -488,7 +476,6 @@ func NewConfig() *Config { StrictReconfigCheck: DefaultStrictReconfigCheck, Metrics: "basic", - EnableV2: DefaultEnableV2, CORS: map[string]struct{}{"*": {}}, HostWhitelist: map[string]struct{}{"*": {}}, diff --git a/server/embed/etcd.go b/server/embed/etcd.go index a3ba75a56f8e..70484277016f 100644 --- a/server/embed/etcd.go +++ b/server/embed/etcd.go @@ -38,9 +38,6 @@ import ( "go.etcd.io/etcd/server/v3/etcdserver" "go.etcd.io/etcd/server/v3/etcdserver/api/etcdhttp" "go.etcd.io/etcd/server/v3/etcdserver/api/rafthttp" - "go.etcd.io/etcd/server/v3/etcdserver/api/v2http" - "go.etcd.io/etcd/server/v3/etcdserver/api/v2v3" - "go.etcd.io/etcd/server/v3/etcdserver/api/v3client" "go.etcd.io/etcd/server/v3/etcdserver/api/v3rpc" "go.etcd.io/etcd/server/v3/storage" "go.etcd.io/etcd/server/v3/verify" @@ -695,25 +692,9 @@ func (e *Etcd) serveClients() (err error) { } // Start a client server goroutine for each listen address - var h http.Handler - if e.Config().EnableV2 { - if e.Config().V2DeprecationEffective().IsAtLeast(config.V2_DEPR_1_WRITE_ONLY) { - return fmt.Errorf("--enable-v2 and --v2-deprecation=%s are mutually exclusive", e.Config().V2DeprecationEffective()) - } - e.cfg.logger.Warn("Flag `enable-v2` is deprecated and will get removed in etcd 3.6.") - if len(e.Config().ExperimentalEnableV2V3) > 0 { - e.cfg.logger.Warn("Flag `experimental-enable-v2v3` is deprecated and will get removed in etcd 3.6.") - srv := v2v3.NewServer(e.cfg.logger, v3client.New(e.Server), e.cfg.ExperimentalEnableV2V3) - h = v2http.NewClientHandler(e.GetLogger(), srv, e.Server.Cfg.ReqTimeout()) - } else { - h = v2http.NewClientHandler(e.GetLogger(), e.Server, e.Server.Cfg.ReqTimeout()) - } - } else { - mux := http.NewServeMux() - etcdhttp.HandleBasic(e.cfg.logger, mux, e.Server) - etcdhttp.HandleMetricsHealthForV3(e.cfg.logger, mux, e.Server) - h = mux - } + mux := http.NewServeMux() + etcdhttp.HandleBasic(e.cfg.logger, mux, e.Server) + etcdhttp.HandleMetricsHealthForV3(e.cfg.logger, mux, e.Server) gopts := []grpc.ServerOption{} if e.cfg.GRPCKeepAliveMinTime > time.Duration(0) { @@ -733,7 +714,7 @@ func (e *Etcd) serveClients() (err error) { // start client servers in each goroutine for _, sctx := range e.sctxs { go func(s *serveCtx) { - e.errHandler(s.serve(e.Server, &e.cfg.ClientTLSInfo, h, e.errHandler, gopts...)) + e.errHandler(s.serve(e.Server, &e.cfg.ClientTLSInfo, mux, e.errHandler, gopts...)) }(sctx) } return nil diff --git a/server/etcdmain/config.go b/server/etcdmain/config.go index eadc5d637eaf..4257f1ba081b 100644 --- a/server/etcdmain/config.go +++ b/server/etcdmain/config.go @@ -200,8 +200,6 @@ func newConfig() *config { fs.BoolVar(&cfg.ec.PreVote, "pre-vote", cfg.ec.PreVote, "Enable to run an additional Raft election phase.") - fs.BoolVar(&cfg.ec.EnableV2, "enable-v2", cfg.ec.EnableV2, "Accept etcd V2 client requests. Deprecated in v3.5. Will be decommission in v3.6.") - fs.StringVar(&cfg.ec.ExperimentalEnableV2V3, "experimental-enable-v2v3", cfg.ec.ExperimentalEnableV2V3, "v3 prefix for serving emulated v2 state. Deprecated in 3.5. Will be decommissioned in 3.6.") fs.Var(cfg.cf.v2deprecation, "v2-deprecation", fmt.Sprintf("v2store deprecation stage: %q. ", cfg.cf.proxy.Valids())) // proxy diff --git a/server/etcdmain/help.go b/server/etcdmain/help.go index 617e66bd7e50..b9dea2e3c4e2 100644 --- a/server/etcdmain/help.go +++ b/server/etcdmain/help.go @@ -123,8 +123,6 @@ Clustering: Auto compaction retention length. 0 means disable auto compaction. --auto-compaction-mode 'periodic' Interpret 'auto-compaction-retention' one of: periodic|revision. 'periodic' for duration based retention, defaulting to hours if no time unit is provided (e.g. '5m'). 'revision' for revision number based retention. - --enable-v2 '` + strconv.FormatBool(embed.DefaultEnableV2) + `' - Accept etcd V2 client requests. Deprecated and to be decommissioned in v3.6. --v2-deprecation '` + string(cconfig.V2_DEPR_DEFAULT) + `' Phase of v2store deprecation. Allows to opt-in for higher compatibility mode. Supported values: @@ -234,8 +232,6 @@ Experimental feature: Enable to check data corruption before serving any client/peer traffic. --experimental-corrupt-check-time '0s' Duration of time between cluster corruption check passes. - --experimental-enable-v2v3 '' - Serve v2 requests through the v3 backend under a given prefix. Deprecated and to be decommissioned in v3.6. --experimental-enable-lease-checkpoint 'false' ExperimentalEnableLeaseCheckpoint enables primary lessor to persist lease remainingTTL to prevent indefinite auto-renewal of long lived leases. --experimental-compaction-batch-limit 1000 diff --git a/server/etcdserver/api/v2v3/cluster.go b/server/etcdserver/api/v2v3/cluster.go deleted file mode 100644 index d275e0571839..000000000000 --- a/server/etcdserver/api/v2v3/cluster.go +++ /dev/null @@ -1,31 +0,0 @@ -// Copyright 2017 The etcd Authors -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -package v2v3 - -import ( - "go.etcd.io/etcd/client/pkg/v3/types" - "go.etcd.io/etcd/server/v3/etcdserver/api/membership" - - "github.com/coreos/go-semver/semver" -) - -func (s *v2v3Server) ID() types.ID { - // TODO: use an actual member ID - return types.ID(0xe7cd2f00d) -} -func (s *v2v3Server) ClientURLs() []string { panic("STUB") } -func (s *v2v3Server) Members() []*membership.Member { panic("STUB") } -func (s *v2v3Server) Member(id types.ID) *membership.Member { panic("STUB") } -func (s *v2v3Server) Version() *semver.Version { panic("STUB") } diff --git a/server/etcdserver/api/v2v3/doc.go b/server/etcdserver/api/v2v3/doc.go deleted file mode 100644 index 2ff372f18760..000000000000 --- a/server/etcdserver/api/v2v3/doc.go +++ /dev/null @@ -1,16 +0,0 @@ -// Copyright 2017 The etcd Authors -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -// Package v2v3 provides a ServerV2 implementation backed by clientv3.Client. -package v2v3 diff --git a/server/etcdserver/api/v2v3/server.go b/server/etcdserver/api/v2v3/server.go deleted file mode 100644 index 71557ceb5c84..000000000000 --- a/server/etcdserver/api/v2v3/server.go +++ /dev/null @@ -1,130 +0,0 @@ -// Copyright 2017 The etcd Authors -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -package v2v3 - -import ( - "context" - "net/http" - "time" - - pb "go.etcd.io/etcd/api/v3/etcdserverpb" - "go.etcd.io/etcd/client/pkg/v3/types" - "go.etcd.io/etcd/client/v3" - "go.etcd.io/etcd/server/v3/etcdserver" - "go.etcd.io/etcd/server/v3/etcdserver/api" - "go.etcd.io/etcd/server/v3/etcdserver/api/membership" - - "github.com/coreos/go-semver/semver" - "go.uber.org/zap" -) - -type fakeStats struct{} - -func (s *fakeStats) SelfStats() []byte { return nil } -func (s *fakeStats) LeaderStats() []byte { return nil } -func (s *fakeStats) StoreStats() []byte { return nil } - -type v2v3Server struct { - lg *zap.Logger - c *clientv3.Client - store *v2v3Store - fakeStats -} - -func NewServer(lg *zap.Logger, c *clientv3.Client, pfx string) etcdserver.ServerPeer { - return &v2v3Server{lg: lg, c: c, store: newStore(c, pfx)} -} - -func (s *v2v3Server) ClientCertAuthEnabled() bool { return false } - -func (s *v2v3Server) LeaseHandler() http.Handler { panic("STUB: lease handler") } -func (s *v2v3Server) RaftHandler() http.Handler { panic("STUB: raft handler") } - -func (s *v2v3Server) Leader() types.ID { - ctx, cancel := context.WithTimeout(context.TODO(), 5*time.Second) - defer cancel() - resp, err := s.c.Status(ctx, s.c.Endpoints()[0]) - if err != nil { - return 0 - } - return types.ID(resp.Leader) -} - -func (s *v2v3Server) AddMember(ctx context.Context, memb membership.Member) ([]*membership.Member, error) { - // adding member as learner is not supported by V2 Server. - resp, err := s.c.MemberAdd(ctx, memb.PeerURLs) - if err != nil { - return nil, err - } - return v3MembersToMembership(resp.Members), nil -} - -func (s *v2v3Server) RemoveMember(ctx context.Context, id uint64) ([]*membership.Member, error) { - resp, err := s.c.MemberRemove(ctx, id) - if err != nil { - return nil, err - } - return v3MembersToMembership(resp.Members), nil -} - -func (s *v2v3Server) PromoteMember(ctx context.Context, id uint64) ([]*membership.Member, error) { - resp, err := s.c.MemberPromote(ctx, id) - if err != nil { - return nil, err - } - return v3MembersToMembership(resp.Members), nil -} - -func (s *v2v3Server) UpdateMember(ctx context.Context, m membership.Member) ([]*membership.Member, error) { - resp, err := s.c.MemberUpdate(ctx, uint64(m.ID), m.PeerURLs) - if err != nil { - return nil, err - } - return v3MembersToMembership(resp.Members), nil -} - -func v3MembersToMembership(v3membs []*pb.Member) []*membership.Member { - membs := make([]*membership.Member, len(v3membs)) - for i, m := range v3membs { - membs[i] = &membership.Member{ - ID: types.ID(m.ID), - RaftAttributes: membership.RaftAttributes{ - PeerURLs: m.PeerURLs, - IsLearner: m.IsLearner, - }, - Attributes: membership.Attributes{ - Name: m.Name, - ClientURLs: m.ClientURLs, - }, - } - } - return membs -} - -func (s *v2v3Server) ClusterVersion() *semver.Version { return s.Version() } -func (s *v2v3Server) Cluster() api.Cluster { return s } -func (s *v2v3Server) Alarms() []*pb.AlarmMember { return nil } -func (s *v2v3Server) LeaderChangedNotify() <-chan struct{} { return nil } - -func (s *v2v3Server) Do(ctx context.Context, r pb.Request) (etcdserver.Response, error) { - applier := etcdserver.NewApplierV2(s.lg, s.store, nil) - reqHandler := etcdserver.NewStoreRequestV2Handler(s.store, applier) - req := (*etcdserver.RequestV2)(&r) - resp, err := req.Handle(ctx, reqHandler) - if resp.Err != nil { - return resp, resp.Err - } - return resp, err -} diff --git a/server/etcdserver/api/v2v3/store.go b/server/etcdserver/api/v2v3/store.go deleted file mode 100644 index 6d78cab71989..000000000000 --- a/server/etcdserver/api/v2v3/store.go +++ /dev/null @@ -1,638 +0,0 @@ -// Copyright 2017 The etcd Authors -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -package v2v3 - -import ( - "context" - "fmt" - "path" - "sort" - "strings" - "time" - - "go.etcd.io/etcd/api/v3/mvccpb" - "go.etcd.io/etcd/client/v3" - "go.etcd.io/etcd/client/v3/concurrency" - "go.etcd.io/etcd/server/v3/etcdserver/api/v2error" - "go.etcd.io/etcd/server/v3/etcdserver/api/v2store" -) - -// store implements the Store interface for V2 using -// a v3 client. -type v2v3Store struct { - c *clientv3.Client - // pfx is the v3 prefix where keys should be stored. - pfx string - ctx context.Context -} - -const maxPathDepth = 63 - -var errUnsupported = fmt.Errorf("TTLs are unsupported") - -func NewStore(c *clientv3.Client, pfx string) v2store.Store { return newStore(c, pfx) } - -func newStore(c *clientv3.Client, pfx string) *v2v3Store { return &v2v3Store{c, pfx, c.Ctx()} } - -func (s *v2v3Store) Index() uint64 { panic("STUB") } - -func (s *v2v3Store) Get(nodePath string, recursive, sorted bool) (*v2store.Event, error) { - key := s.mkPath(nodePath) - resp, err := s.c.Txn(s.ctx).Then( - clientv3.OpGet(key+"/"), - clientv3.OpGet(key), - ).Commit() - if err != nil { - return nil, err - } - - if kvs := resp.Responses[0].GetResponseRange().Kvs; len(kvs) != 0 || isRoot(nodePath) { - nodes, err := s.getDir(nodePath, recursive, sorted, resp.Header.Revision) - if err != nil { - return nil, err - } - cidx, midx := uint64(0), uint64(0) - if len(kvs) > 0 { - cidx, midx = mkV2Rev(kvs[0].CreateRevision), mkV2Rev(kvs[0].ModRevision) - } - return &v2store.Event{ - Action: v2store.Get, - Node: &v2store.NodeExtern{ - Key: nodePath, - Dir: true, - Nodes: nodes, - CreatedIndex: cidx, - ModifiedIndex: midx, - }, - EtcdIndex: mkV2Rev(resp.Header.Revision), - }, nil - } - - kvs := resp.Responses[1].GetResponseRange().Kvs - if len(kvs) == 0 { - return nil, v2error.NewError(v2error.EcodeKeyNotFound, nodePath, mkV2Rev(resp.Header.Revision)) - } - - return &v2store.Event{ - Action: v2store.Get, - Node: s.mkV2Node(kvs[0]), - EtcdIndex: mkV2Rev(resp.Header.Revision), - }, nil -} - -func (s *v2v3Store) getDir(nodePath string, recursive, sorted bool, rev int64) ([]*v2store.NodeExtern, error) { - rootNodes, err := s.getDirDepth(nodePath, 1, rev) - if err != nil || !recursive { - if sorted { - sort.Sort(v2store.NodeExterns(rootNodes)) - } - return rootNodes, err - } - nextNodes := rootNodes - nodes := make(map[string]*v2store.NodeExtern) - // Breadth walk the subdirectories - for i := 2; len(nextNodes) > 0; i++ { - for _, n := range nextNodes { - nodes[n.Key] = n - if parent := nodes[path.Dir(n.Key)]; parent != nil { - parent.Nodes = append(parent.Nodes, n) - } - } - if nextNodes, err = s.getDirDepth(nodePath, i, rev); err != nil { - return nil, err - } - } - - if sorted { - sort.Sort(v2store.NodeExterns(rootNodes)) - } - return rootNodes, nil -} - -func (s *v2v3Store) getDirDepth(nodePath string, depth int, rev int64) ([]*v2store.NodeExtern, error) { - pd := s.mkPathDepth(nodePath, depth) - resp, err := s.c.Get(s.ctx, pd, clientv3.WithPrefix(), clientv3.WithRev(rev)) - if err != nil { - return nil, err - } - - nodes := make([]*v2store.NodeExtern, len(resp.Kvs)) - for i, kv := range resp.Kvs { - nodes[i] = s.mkV2Node(kv) - } - return nodes, nil -} - -func (s *v2v3Store) Set( - nodePath string, - dir bool, - value string, - expireOpts v2store.TTLOptionSet, -) (*v2store.Event, error) { - if expireOpts.Refresh || !expireOpts.ExpireTime.IsZero() { - return nil, errUnsupported - } - - if isRoot(nodePath) { - return nil, v2error.NewError(v2error.EcodeRootROnly, nodePath, 0) - } - - ecode := 0 - applyf := func(stm concurrency.STM) error { - // build path if any directories in path do not exist - dirs := []string{} - for p := path.Dir(nodePath); !isRoot(p); p = path.Dir(p) { - pp := s.mkPath(p) - if stm.Rev(pp) > 0 { - ecode = v2error.EcodeNotDir - return nil - } - if stm.Rev(pp+"/") == 0 { - dirs = append(dirs, pp+"/") - } - } - for _, d := range dirs { - stm.Put(d, "") - } - - key := s.mkPath(nodePath) - if dir { - if stm.Rev(key) != 0 { - // exists as non-dir - ecode = v2error.EcodeNotDir - return nil - } - key = key + "/" - } else if stm.Rev(key+"/") != 0 { - ecode = v2error.EcodeNotFile - return nil - } - stm.Put(key, value, clientv3.WithPrevKV()) - stm.Put(s.mkActionKey(), v2store.Set) - return nil - } - - resp, err := s.newSTM(applyf) - if err != nil { - return nil, err - } - if ecode != 0 { - return nil, v2error.NewError(ecode, nodePath, mkV2Rev(resp.Header.Revision)) - } - - createRev := resp.Header.Revision - var pn *v2store.NodeExtern - if pkv := prevKeyFromPuts(resp); pkv != nil { - pn = s.mkV2Node(pkv) - createRev = pkv.CreateRevision - } - - vp := &value - if dir { - vp = nil - } - return &v2store.Event{ - Action: v2store.Set, - Node: &v2store.NodeExtern{ - Key: nodePath, - Value: vp, - Dir: dir, - ModifiedIndex: mkV2Rev(resp.Header.Revision), - CreatedIndex: mkV2Rev(createRev), - }, - PrevNode: pn, - EtcdIndex: mkV2Rev(resp.Header.Revision), - }, nil -} - -func (s *v2v3Store) Update(nodePath, newValue string, expireOpts v2store.TTLOptionSet) (*v2store.Event, error) { - if isRoot(nodePath) { - return nil, v2error.NewError(v2error.EcodeRootROnly, nodePath, 0) - } - - if expireOpts.Refresh || !expireOpts.ExpireTime.IsZero() { - return nil, errUnsupported - } - - key := s.mkPath(nodePath) - ecode := 0 - applyf := func(stm concurrency.STM) error { - if rev := stm.Rev(key + "/"); rev != 0 { - ecode = v2error.EcodeNotFile - return nil - } - if rev := stm.Rev(key); rev == 0 { - ecode = v2error.EcodeKeyNotFound - return nil - } - stm.Put(key, newValue, clientv3.WithPrevKV()) - stm.Put(s.mkActionKey(), v2store.Update) - return nil - } - - resp, err := s.newSTM(applyf) - if err != nil { - return nil, err - } - if ecode != 0 { - return nil, v2error.NewError(v2error.EcodeNotFile, nodePath, mkV2Rev(resp.Header.Revision)) - } - - pkv := prevKeyFromPuts(resp) - return &v2store.Event{ - Action: v2store.Update, - Node: &v2store.NodeExtern{ - Key: nodePath, - Value: &newValue, - ModifiedIndex: mkV2Rev(resp.Header.Revision), - CreatedIndex: mkV2Rev(pkv.CreateRevision), - }, - PrevNode: s.mkV2Node(pkv), - EtcdIndex: mkV2Rev(resp.Header.Revision), - }, nil -} - -func (s *v2v3Store) Create( - nodePath string, - dir bool, - value string, - unique bool, - expireOpts v2store.TTLOptionSet, -) (*v2store.Event, error) { - if isRoot(nodePath) { - return nil, v2error.NewError(v2error.EcodeRootROnly, nodePath, 0) - } - if expireOpts.Refresh || !expireOpts.ExpireTime.IsZero() { - return nil, errUnsupported - } - ecode := 0 - applyf := func(stm concurrency.STM) error { - ecode = 0 - key := s.mkPath(nodePath) - if unique { - // append unique item under the node path - for { - key = nodePath + "/" + fmt.Sprintf("%020s", time.Now()) - key = path.Clean(path.Join("/", key)) - key = s.mkPath(key) - if stm.Rev(key) == 0 { - break - } - } - } - if stm.Rev(key) > 0 || stm.Rev(key+"/") > 0 { - ecode = v2error.EcodeNodeExist - return nil - } - // build path if any directories in path do not exist - dirs := []string{} - for p := path.Dir(nodePath); !isRoot(p); p = path.Dir(p) { - pp := s.mkPath(p) - if stm.Rev(pp) > 0 { - ecode = v2error.EcodeNotDir - return nil - } - if stm.Rev(pp+"/") == 0 { - dirs = append(dirs, pp+"/") - } - } - for _, d := range dirs { - stm.Put(d, "") - } - - if dir { - // directories marked with extra slash in key name - key += "/" - } - stm.Put(key, value) - stm.Put(s.mkActionKey(), v2store.Create) - return nil - } - - resp, err := s.newSTM(applyf) - if err != nil { - return nil, err - } - if ecode != 0 { - return nil, v2error.NewError(ecode, nodePath, mkV2Rev(resp.Header.Revision)) - } - - var v *string - if !dir { - v = &value - } - - return &v2store.Event{ - Action: v2store.Create, - Node: &v2store.NodeExtern{ - Key: nodePath, - Value: v, - Dir: dir, - ModifiedIndex: mkV2Rev(resp.Header.Revision), - CreatedIndex: mkV2Rev(resp.Header.Revision), - }, - EtcdIndex: mkV2Rev(resp.Header.Revision), - }, nil -} - -func (s *v2v3Store) CompareAndSwap( - nodePath string, - prevValue string, - prevIndex uint64, - value string, - expireOpts v2store.TTLOptionSet, -) (*v2store.Event, error) { - if isRoot(nodePath) { - return nil, v2error.NewError(v2error.EcodeRootROnly, nodePath, 0) - } - if expireOpts.Refresh || !expireOpts.ExpireTime.IsZero() { - return nil, errUnsupported - } - - key := s.mkPath(nodePath) - resp, err := s.c.Txn(s.ctx).If( - s.mkCompare(nodePath, prevValue, prevIndex)..., - ).Then( - clientv3.OpPut(key, value, clientv3.WithPrevKV()), - clientv3.OpPut(s.mkActionKey(), v2store.CompareAndSwap), - ).Else( - clientv3.OpGet(key), - clientv3.OpGet(key+"/"), - ).Commit() - - if err != nil { - return nil, err - } - if !resp.Succeeded { - return nil, compareFail(nodePath, prevValue, prevIndex, resp) - } - - pkv := resp.Responses[0].GetResponsePut().PrevKv - return &v2store.Event{ - Action: v2store.CompareAndSwap, - Node: &v2store.NodeExtern{ - Key: nodePath, - Value: &value, - CreatedIndex: mkV2Rev(pkv.CreateRevision), - ModifiedIndex: mkV2Rev(resp.Header.Revision), - }, - PrevNode: s.mkV2Node(pkv), - EtcdIndex: mkV2Rev(resp.Header.Revision), - }, nil -} - -func (s *v2v3Store) Delete(nodePath string, dir, recursive bool) (*v2store.Event, error) { - if isRoot(nodePath) { - return nil, v2error.NewError(v2error.EcodeRootROnly, nodePath, 0) - } - if !dir && !recursive { - return s.deleteNode(nodePath) - } - if !recursive { - return s.deleteEmptyDir(nodePath) - } - - dels := make([]clientv3.Op, maxPathDepth+1) - dels[0] = clientv3.OpDelete(s.mkPath(nodePath)+"/", clientv3.WithPrevKV()) - for i := 1; i < maxPathDepth; i++ { - dels[i] = clientv3.OpDelete(s.mkPathDepth(nodePath, i), clientv3.WithPrefix()) - } - dels[maxPathDepth] = clientv3.OpPut(s.mkActionKey(), v2store.Delete) - - resp, err := s.c.Txn(s.ctx).If( - clientv3.Compare(clientv3.Version(s.mkPath(nodePath)+"/"), ">", 0), - clientv3.Compare(clientv3.Version(s.mkPathDepth(nodePath, maxPathDepth)+"/"), "=", 0), - ).Then( - dels..., - ).Commit() - if err != nil { - return nil, err - } - if !resp.Succeeded { - return nil, v2error.NewError(v2error.EcodeNodeExist, nodePath, mkV2Rev(resp.Header.Revision)) - } - dresp := resp.Responses[0].GetResponseDeleteRange() - return &v2store.Event{ - Action: v2store.Delete, - PrevNode: s.mkV2Node(dresp.PrevKvs[0]), - EtcdIndex: mkV2Rev(resp.Header.Revision), - }, nil -} - -func (s *v2v3Store) deleteEmptyDir(nodePath string) (*v2store.Event, error) { - resp, err := s.c.Txn(s.ctx).If( - clientv3.Compare(clientv3.Version(s.mkPathDepth(nodePath, 1)), "=", 0).WithPrefix(), - ).Then( - clientv3.OpDelete(s.mkPath(nodePath)+"/", clientv3.WithPrevKV()), - clientv3.OpPut(s.mkActionKey(), v2store.Delete), - ).Commit() - if err != nil { - return nil, err - } - if !resp.Succeeded { - return nil, v2error.NewError(v2error.EcodeDirNotEmpty, nodePath, mkV2Rev(resp.Header.Revision)) - } - dresp := resp.Responses[0].GetResponseDeleteRange() - if len(dresp.PrevKvs) == 0 { - return nil, v2error.NewError(v2error.EcodeNodeExist, nodePath, mkV2Rev(resp.Header.Revision)) - } - return &v2store.Event{ - Action: v2store.Delete, - PrevNode: s.mkV2Node(dresp.PrevKvs[0]), - EtcdIndex: mkV2Rev(resp.Header.Revision), - }, nil -} - -func (s *v2v3Store) deleteNode(nodePath string) (*v2store.Event, error) { - resp, err := s.c.Txn(s.ctx).If( - clientv3.Compare(clientv3.Version(s.mkPath(nodePath)+"/"), "=", 0), - ).Then( - clientv3.OpDelete(s.mkPath(nodePath), clientv3.WithPrevKV()), - clientv3.OpPut(s.mkActionKey(), v2store.Delete), - ).Commit() - if err != nil { - return nil, err - } - if !resp.Succeeded { - return nil, v2error.NewError(v2error.EcodeNotFile, nodePath, mkV2Rev(resp.Header.Revision)) - } - pkvs := resp.Responses[0].GetResponseDeleteRange().PrevKvs - if len(pkvs) == 0 { - return nil, v2error.NewError(v2error.EcodeKeyNotFound, nodePath, mkV2Rev(resp.Header.Revision)) - } - pkv := pkvs[0] - return &v2store.Event{ - Action: v2store.Delete, - Node: &v2store.NodeExtern{ - Key: nodePath, - CreatedIndex: mkV2Rev(pkv.CreateRevision), - ModifiedIndex: mkV2Rev(resp.Header.Revision), - }, - PrevNode: s.mkV2Node(pkv), - EtcdIndex: mkV2Rev(resp.Header.Revision), - }, nil -} - -func (s *v2v3Store) CompareAndDelete(nodePath, prevValue string, prevIndex uint64) (*v2store.Event, error) { - if isRoot(nodePath) { - return nil, v2error.NewError(v2error.EcodeRootROnly, nodePath, 0) - } - - key := s.mkPath(nodePath) - resp, err := s.c.Txn(s.ctx).If( - s.mkCompare(nodePath, prevValue, prevIndex)..., - ).Then( - clientv3.OpDelete(key, clientv3.WithPrevKV()), - clientv3.OpPut(s.mkActionKey(), v2store.CompareAndDelete), - ).Else( - clientv3.OpGet(key), - clientv3.OpGet(key+"/"), - ).Commit() - - if err != nil { - return nil, err - } - if !resp.Succeeded { - return nil, compareFail(nodePath, prevValue, prevIndex, resp) - } - - // len(pkvs) > 1 since txn only succeeds when key exists - pkv := resp.Responses[0].GetResponseDeleteRange().PrevKvs[0] - return &v2store.Event{ - Action: v2store.CompareAndDelete, - Node: &v2store.NodeExtern{ - Key: nodePath, - CreatedIndex: mkV2Rev(pkv.CreateRevision), - ModifiedIndex: mkV2Rev(resp.Header.Revision), - }, - PrevNode: s.mkV2Node(pkv), - EtcdIndex: mkV2Rev(resp.Header.Revision), - }, nil -} - -func compareFail(nodePath, prevValue string, prevIndex uint64, resp *clientv3.TxnResponse) error { - if dkvs := resp.Responses[1].GetResponseRange().Kvs; len(dkvs) > 0 { - return v2error.NewError(v2error.EcodeNotFile, nodePath, mkV2Rev(resp.Header.Revision)) - } - kvs := resp.Responses[0].GetResponseRange().Kvs - if len(kvs) == 0 { - return v2error.NewError(v2error.EcodeKeyNotFound, nodePath, mkV2Rev(resp.Header.Revision)) - } - kv := kvs[0] - indexMatch := prevIndex == 0 || kv.ModRevision == int64(prevIndex) - valueMatch := prevValue == "" || string(kv.Value) == prevValue - var cause string - switch { - case indexMatch && !valueMatch: - cause = fmt.Sprintf("[%v != %v]", prevValue, string(kv.Value)) - case valueMatch && !indexMatch: - cause = fmt.Sprintf("[%v != %v]", prevIndex, kv.ModRevision) - default: - cause = fmt.Sprintf("[%v != %v] [%v != %v]", prevValue, string(kv.Value), prevIndex, kv.ModRevision) - } - return v2error.NewError(v2error.EcodeTestFailed, cause, mkV2Rev(resp.Header.Revision)) -} - -func (s *v2v3Store) mkCompare(nodePath, prevValue string, prevIndex uint64) []clientv3.Cmp { - key := s.mkPath(nodePath) - cmps := []clientv3.Cmp{clientv3.Compare(clientv3.Version(key), ">", 0)} - if prevIndex != 0 { - cmps = append(cmps, clientv3.Compare(clientv3.ModRevision(key), "=", mkV3Rev(prevIndex))) - } - if prevValue != "" { - cmps = append(cmps, clientv3.Compare(clientv3.Value(key), "=", prevValue)) - } - return cmps -} - -func (s *v2v3Store) JsonStats() []byte { panic("STUB") } -func (s *v2v3Store) DeleteExpiredKeys(cutoff time.Time) { panic("STUB") } - -func (s *v2v3Store) Version() int { return 2 } - -// TODO: move this out of the Store interface? - -func (s *v2v3Store) Save() ([]byte, error) { panic("STUB") } -func (s *v2v3Store) Recovery(state []byte) error { panic("STUB") } -func (s *v2v3Store) Clone() v2store.Store { panic("STUB") } -func (s *v2v3Store) SaveNoCopy() ([]byte, error) { panic("STUB") } -func (s *v2v3Store) HasTTLKeys() bool { panic("STUB") } - -func (s *v2v3Store) mkPath(nodePath string) string { return s.mkPathDepth(nodePath, 0) } - -func (s *v2v3Store) mkNodePath(p string) string { - return path.Clean(p[len(s.pfx)+len("/k/000/"):]) -} - -// mkPathDepth makes a path to a key that encodes its directory depth -// for fast directory listing. If a depth is provided, it is added -// to the computed depth. -func (s *v2v3Store) mkPathDepth(nodePath string, depth int) string { - normalForm := path.Clean(path.Join("/", nodePath)) - n := strings.Count(normalForm, "/") + depth - return fmt.Sprintf("%s/%03d/k/%s", s.pfx, n, normalForm) -} - -func (s *v2v3Store) mkActionKey() string { return s.pfx + "/act" } - -func isRoot(s string) bool { return len(s) == 0 || s == "/" || s == "/0" || s == "/1" } - -func mkV2Rev(v3Rev int64) uint64 { - if v3Rev == 0 { - return 0 - } - return uint64(v3Rev - 1) -} - -func mkV3Rev(v2Rev uint64) int64 { - if v2Rev == 0 { - return 0 - } - return int64(v2Rev + 1) -} - -// mkV2Node creates a V2 NodeExtern from a V3 KeyValue -func (s *v2v3Store) mkV2Node(kv *mvccpb.KeyValue) *v2store.NodeExtern { - if kv == nil { - return nil - } - n := &v2store.NodeExtern{ - Key: s.mkNodePath(string(kv.Key)), - Dir: kv.Key[len(kv.Key)-1] == '/', - CreatedIndex: mkV2Rev(kv.CreateRevision), - ModifiedIndex: mkV2Rev(kv.ModRevision), - } - if !n.Dir { - v := string(kv.Value) - n.Value = &v - } - return n -} - -// prevKeyFromPuts gets the prev key that is being put; ignores -// the put action response. -func prevKeyFromPuts(resp *clientv3.TxnResponse) *mvccpb.KeyValue { - for _, r := range resp.Responses { - pkv := r.GetResponsePut().PrevKv - if pkv != nil && pkv.CreateRevision > 0 { - return pkv - } - } - return nil -} - -func (s *v2v3Store) newSTM(applyf func(concurrency.STM) error) (*clientv3.TxnResponse, error) { - return concurrency.NewSTM(s.c, applyf, concurrency.WithIsolation(concurrency.Serializable)) -} diff --git a/server/etcdserver/api/v2v3/watcher.go b/server/etcdserver/api/v2v3/watcher.go deleted file mode 100644 index 046c25d45095..000000000000 --- a/server/etcdserver/api/v2v3/watcher.go +++ /dev/null @@ -1,142 +0,0 @@ -// Copyright 2017 The etcd Authors -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -package v2v3 - -import ( - "context" - "strings" - - "go.etcd.io/etcd/client/v3" - "go.etcd.io/etcd/server/v3/etcdserver/api/v2error" - "go.etcd.io/etcd/server/v3/etcdserver/api/v2store" -) - -func (s *v2v3Store) Watch(prefix string, recursive, stream bool, sinceIndex uint64) (v2store.Watcher, error) { - ctx, cancel := context.WithCancel(s.ctx) - wch := s.c.Watch( - ctx, - // TODO: very pricey; use a single store-wide watch in future - s.pfx, - clientv3.WithPrefix(), - clientv3.WithRev(int64(sinceIndex)), - clientv3.WithCreatedNotify(), - clientv3.WithPrevKV()) - resp, ok := <-wch - if err := resp.Err(); err != nil || !ok { - cancel() - return nil, v2error.NewError(v2error.EcodeRaftInternal, prefix, 0) - } - - evc, donec := make(chan *v2store.Event), make(chan struct{}) - go func() { - defer func() { - close(evc) - close(donec) - }() - for resp := range wch { - for _, ev := range s.mkV2Events(resp) { - k := ev.Node.Key - if recursive { - if !strings.HasPrefix(k, prefix) { - continue - } - // accept events on hidden keys given in prefix - k = strings.Replace(k, prefix, "/", 1) - // ignore hidden keys deeper than prefix - if strings.Contains(k, "/_") { - continue - } - } - if !recursive && k != prefix { - continue - } - select { - case evc <- ev: - case <-ctx.Done(): - return - } - if !stream { - return - } - } - } - }() - - return &v2v3Watcher{ - startRev: resp.Header.Revision, - evc: evc, - donec: donec, - cancel: cancel, - }, nil -} - -func (s *v2v3Store) mkV2Events(wr clientv3.WatchResponse) (evs []*v2store.Event) { - ak := s.mkActionKey() - for _, rev := range mkRevs(wr) { - var act, key *clientv3.Event - for _, ev := range rev { - if string(ev.Kv.Key) == ak { - act = ev - } else if key != nil && len(key.Kv.Key) < len(ev.Kv.Key) { - // use longest key to ignore intermediate new - // directories from Create. - key = ev - } else if key == nil { - key = ev - } - } - if act != nil && act.Kv != nil && key != nil { - v2ev := &v2store.Event{ - Action: string(act.Kv.Value), - Node: s.mkV2Node(key.Kv), - PrevNode: s.mkV2Node(key.PrevKv), - EtcdIndex: mkV2Rev(wr.Header.Revision), - } - evs = append(evs, v2ev) - } - } - return evs -} - -func mkRevs(wr clientv3.WatchResponse) (revs [][]*clientv3.Event) { - var curRev []*clientv3.Event - for _, ev := range wr.Events { - if curRev != nil && ev.Kv.ModRevision != curRev[0].Kv.ModRevision { - revs = append(revs, curRev) - curRev = nil - } - curRev = append(curRev, ev) - } - if curRev != nil { - revs = append(revs, curRev) - } - return revs -} - -type v2v3Watcher struct { - startRev int64 - evc chan *v2store.Event - donec chan struct{} - cancel context.CancelFunc -} - -func (w *v2v3Watcher) StartIndex() uint64 { return mkV2Rev(w.startRev) } - -func (w *v2v3Watcher) Remove() { - w.cancel() - <-w.donec -} - -func (w *v2v3Watcher) EventChan() chan *v2store.Event { return w.evc } diff --git a/server/etcdserver/server.go b/server/etcdserver/server.go index 884caf411aad..1828cfd2cfa4 100644 --- a/server/etcdserver/server.go +++ b/server/etcdserver/server.go @@ -1718,8 +1718,7 @@ func (s *EtcdServer) publishV3(timeout time.Duration) { // or its server is stopped. // // Use v2 store to encode member attributes, and apply through Raft -// but does not go through v2 API endpoint, which means even with v2 -// client handler disabled (e.g. --enable-v2=false), cluster can still +// but does not go through v2 API endpoint, which means cluster can still // process publish requests through rafthttp // TODO: Remove in 3.6 (start using publishV3) func (s *EtcdServer) publish(timeout time.Duration) { diff --git a/test.sh b/test.sh index f26f7f780d35..586fa32923c5 100755 --- a/test.sh +++ b/test.sh @@ -100,7 +100,7 @@ function unit_pass { function integration_extra { if [ -z "${PKG}" ] ; then run_for_module "." go_test "./contrib/raftexample" "keep_going" : -timeout="${TIMEOUT:-5m}" "${RUN_ARG[@]}" "${COMMON_TEST_FLAGS[@]}" "$@" || return $? - run_for_module "tests" go_test "./integration/v2store/..." "keep_going" : -tags v2v3 -timeout="${TIMEOUT:-5m}" "${RUN_ARG[@]}" "${COMMON_TEST_FLAGS[@]}" "$@" || return $? + run_for_module "tests" go_test "./integration/v2store/..." "keep_going" : -timeout="${TIMEOUT:-5m}" "${RUN_ARG[@]}" "${COMMON_TEST_FLAGS[@]}" "$@" || return $? else log_warning "integration_extra ignored when PKG is specified" fi @@ -317,7 +317,7 @@ function cov_pass { -timeout=30m "${gocov_build_flags[@]}" "$@" || failed="$failed integration" # integration-store-v2 run_for_module "tests" go_test "./integration/v2store/..." "keep_going" "pkg_to_coverprofileflag store_v2" \ - -tags v2v3 -timeout=5m "${gocov_build_flags[@]}" "$@" || failed="$failed integration_v2v3" + -timeout=5m "${gocov_build_flags[@]}" "$@" || failed="$failed integration_v2" # integration_cluster_proxy run_for_module "tests" go_test "./integration/..." "parallel" "pkg_to_coverprofileflag integration_cluster_proxy" \ -tags cluster_proxy -timeout=5m "${gocov_build_flags[@]}" || failed="$failed integration_cluster_proxy" diff --git a/tests/e2e/ctl_v2_test.go b/tests/e2e/ctl_v2_test.go deleted file mode 100644 index 9340b25a994d..000000000000 --- a/tests/e2e/ctl_v2_test.go +++ /dev/null @@ -1,535 +0,0 @@ -// Copyright 2016 The etcd Authors -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -package e2e - -import ( - "fmt" - "os" - "strings" - "testing" - "time" - - "go.etcd.io/etcd/tests/v3/framework/e2e" -) - -func BeforeTestV2(t testing.TB) { - e2e.BeforeTest(t) - os.Setenv("ETCDCTL_API", "2") - t.Cleanup(func() { - os.Unsetenv("ETCDCTL_API") - }) -} - -func TestCtlV2Set(t *testing.T) { testCtlV2Set(t, e2e.NewConfigNoTLS(), false) } -func TestCtlV2SetQuorum(t *testing.T) { testCtlV2Set(t, e2e.NewConfigNoTLS(), true) } -func TestCtlV2SetClientTLS(t *testing.T) { testCtlV2Set(t, e2e.NewConfigClientTLS(), false) } -func TestCtlV2SetPeerTLS(t *testing.T) { testCtlV2Set(t, e2e.NewConfigPeerTLS(), false) } -func TestCtlV2SetTLS(t *testing.T) { testCtlV2Set(t, e2e.NewConfigTLS(), false) } -func testCtlV2Set(t *testing.T, cfg *e2e.EtcdProcessClusterConfig, quorum bool) { - BeforeTestV2(t) - - cfg.EnableV2 = true - epc := setupEtcdctlTest(t, cfg, quorum) - defer cleanupEtcdProcessCluster(epc, t) - - key, value := "foo", "bar" - - if err := etcdctlSet(epc, key, value); err != nil { - t.Fatalf("failed set (%v)", err) - } - - if err := etcdctlGet(epc, key, value, quorum); err != nil { - t.Fatalf("failed get (%v)", err) - } -} - -func TestCtlV2Mk(t *testing.T) { testCtlV2Mk(t, e2e.NewConfigNoTLS(), false) } -func TestCtlV2MkQuorum(t *testing.T) { testCtlV2Mk(t, e2e.NewConfigNoTLS(), true) } -func TestCtlV2MkTLS(t *testing.T) { testCtlV2Mk(t, e2e.NewConfigTLS(), false) } -func testCtlV2Mk(t *testing.T, cfg *e2e.EtcdProcessClusterConfig, quorum bool) { - BeforeTestV2(t) - - cfg.EnableV2 = true - epc := setupEtcdctlTest(t, cfg, quorum) - defer cleanupEtcdProcessCluster(epc, t) - - key, value := "foo", "bar" - - if err := etcdctlMk(epc, key, value, true); err != nil { - t.Fatalf("failed mk (%v)", err) - } - if err := etcdctlMk(epc, key, value, false); err != nil { - t.Fatalf("failed mk (%v)", err) - } - - if err := etcdctlGet(epc, key, value, quorum); err != nil { - t.Fatalf("failed get (%v)", err) - } -} - -func TestCtlV2Rm(t *testing.T) { testCtlV2Rm(t, e2e.NewConfigNoTLS()) } -func TestCtlV2RmTLS(t *testing.T) { testCtlV2Rm(t, e2e.NewConfigTLS()) } -func testCtlV2Rm(t *testing.T, cfg *e2e.EtcdProcessClusterConfig) { - BeforeTestV2(t) - - cfg.EnableV2 = true - epc := setupEtcdctlTest(t, cfg, true) - defer cleanupEtcdProcessCluster(epc, t) - - key, value := "foo", "bar" - - if err := etcdctlSet(epc, key, value); err != nil { - t.Fatalf("failed set (%v)", err) - } - - if err := etcdctlRm(epc, key, value, true); err != nil { - t.Fatalf("failed rm (%v)", err) - } - if err := etcdctlRm(epc, key, value, false); err != nil { - t.Fatalf("failed rm (%v)", err) - } -} - -func TestCtlV2Ls(t *testing.T) { testCtlV2Ls(t, e2e.NewConfigNoTLS(), false) } -func TestCtlV2LsQuorum(t *testing.T) { testCtlV2Ls(t, e2e.NewConfigNoTLS(), true) } -func TestCtlV2LsTLS(t *testing.T) { testCtlV2Ls(t, e2e.NewConfigTLS(), false) } -func testCtlV2Ls(t *testing.T, cfg *e2e.EtcdProcessClusterConfig, quorum bool) { - BeforeTestV2(t) - - cfg.EnableV2 = true - epc := setupEtcdctlTest(t, cfg, quorum) - defer cleanupEtcdProcessCluster(epc, t) - - key, value := "foo", "bar" - - if err := etcdctlSet(epc, key, value); err != nil { - t.Fatalf("failed set (%v)", err) - } - - if err := etcdctlLs(epc, key, quorum); err != nil { - t.Fatalf("failed ls (%v)", err) - } -} - -func TestCtlV2Watch(t *testing.T) { testCtlV2Watch(t, e2e.NewConfigNoTLS(), false) } -func TestCtlV2WatchTLS(t *testing.T) { testCtlV2Watch(t, e2e.NewConfigTLS(), false) } - -func testCtlV2Watch(t *testing.T, cfg *e2e.EtcdProcessClusterConfig, noSync bool) { - BeforeTestV2(t) - - cfg.EnableV2 = true - epc := setupEtcdctlTest(t, cfg, true) - defer cleanupEtcdProcessCluster(epc, t) - - key, value := "foo", "bar" - errc := etcdctlWatch(epc, key, value, noSync) - if err := etcdctlSet(epc, key, value); err != nil { - t.Fatalf("failed set (%v)", err) - } - - select { - case err := <-errc: - if err != nil { - t.Fatalf("failed watch (%v)", err) - } - case <-time.After(5 * time.Second): - t.Fatalf("watch timed out") - } -} - -func TestCtlV2GetRoleUser(t *testing.T) { - BeforeTestV2(t) - - copied := e2e.NewConfigNoTLS() - copied.EnableV2 = true - epc := setupEtcdctlTest(t, copied, false) - defer cleanupEtcdProcessCluster(epc, t) - - if err := etcdctlRoleAdd(epc, "foo"); err != nil { - t.Fatalf("failed to add role (%v)", err) - } - if err := etcdctlUserAdd(epc, "username", "password"); err != nil { - t.Fatalf("failed to add user (%v)", err) - } - if err := etcdctlUserGrant(epc, "username", "foo"); err != nil { - t.Fatalf("failed to grant role (%v)", err) - } - if err := etcdctlUserGet(epc, "username"); err != nil { - t.Fatalf("failed to get user (%v)", err) - } - - // ensure double grant gives an error; was crashing in 2.3.1 - regrantArgs := etcdctlPrefixArgs(epc) - regrantArgs = append(regrantArgs, "user", "grant", "--roles", "foo", "username") - if err := e2e.SpawnWithExpect(regrantArgs, "duplicate"); err != nil { - t.Fatalf("missing duplicate error on double grant role (%v)", err) - } -} - -func TestCtlV2UserListUsername(t *testing.T) { testCtlV2UserList(t, "username") } -func TestCtlV2UserListRoot(t *testing.T) { testCtlV2UserList(t, "root") } -func testCtlV2UserList(t *testing.T, username string) { - BeforeTestV2(t) - - copied := e2e.NewConfigNoTLS() - copied.EnableV2 = true - epc := setupEtcdctlTest(t, copied, false) - defer cleanupEtcdProcessCluster(epc, t) - - if err := etcdctlUserAdd(epc, username, "password"); err != nil { - t.Fatalf("failed to add user (%v)", err) - } - if err := etcdctlUserList(epc, username); err != nil { - t.Fatalf("failed to list users (%v)", err) - } -} - -func TestCtlV2RoleList(t *testing.T) { - BeforeTestV2(t) - - copied := e2e.NewConfigNoTLS() - copied.EnableV2 = true - epc := setupEtcdctlTest(t, copied, false) - defer cleanupEtcdProcessCluster(epc, t) - - if err := etcdctlRoleAdd(epc, "foo"); err != nil { - t.Fatalf("failed to add role (%v)", err) - } - if err := etcdctlRoleList(epc, "foo"); err != nil { - t.Fatalf("failed to list roles (%v)", err) - } -} - -func TestUtlCtlV2Backup(t *testing.T) { - for snap := range []int{0, 1} { - for _, v3 := range []bool{true, false} { - for _, utl := range []bool{true, false} { - t.Run(fmt.Sprintf("etcdutl:%v;snap:%v;v3:%v", utl, snap, v3), - func(t *testing.T) { - testUtlCtlV2Backup(t, snap, v3, utl) - }) - } - } - } -} - -func testUtlCtlV2Backup(t *testing.T, snapCount int, v3 bool, utl bool) { - BeforeTestV2(t) - - backupDir, err := os.MkdirTemp(t.TempDir(), "testbackup0.etcd") - if err != nil { - t.Fatal(err) - } - - etcdCfg := e2e.NewConfigNoTLS() - etcdCfg.SnapshotCount = snapCount - etcdCfg.EnableV2 = true - t.Log("Starting etcd-1") - epc1 := setupEtcdctlTest(t, etcdCfg, false) - - // v3 put before v2 set so snapshot happens after v3 operations to confirm - // v3 data is preserved after snapshot. - os.Setenv("ETCDCTL_API", "3") - if err := ctlV3Put(ctlCtx{t: t, epc: epc1}, "v3key", "123", ""); err != nil { - t.Fatal(err) - } - os.Setenv("ETCDCTL_API", "2") - - t.Log("Setting key in etcd-1") - if err := etcdctlSet(epc1, "foo1", "bar1"); err != nil { - t.Fatal(err) - } - - if v3 { - t.Log("Stopping etcd-1") - // v3 must lock the db to backup, so stop process - if err := epc1.Stop(); err != nil { - t.Fatal(err) - } - } - t.Log("Triggering etcd backup") - if err := etcdctlBackup(t, epc1, epc1.Procs[0].Config().DataDirPath, backupDir, v3, utl); err != nil { - t.Fatal(err) - } - t.Log("Closing etcd-1 backup") - if err := epc1.Close(); err != nil { - t.Fatalf("error closing etcd processes (%v)", err) - } - - t.Logf("Backup directory: %s", backupDir) - - t.Log("Starting etcd-2 (post backup)") - // restart from the backup directory - cfg2 := e2e.NewConfigNoTLS() - cfg2.DataDirPath = backupDir - cfg2.KeepDataDir = true - cfg2.ForceNewCluster = true - cfg2.EnableV2 = true - epc2 := setupEtcdctlTest(t, cfg2, false) - // Make sure a failing test is not leaking resources (running server). - defer epc2.Close() - - t.Log("Getting examplar key") - // check if backup went through correctly - if err := etcdctlGet(epc2, "foo1", "bar1", false); err != nil { - t.Fatal(err) - } - - os.Setenv("ETCDCTL_API", "3") - ctx2 := ctlCtx{t: t, epc: epc2} - if v3 { - t.Log("Getting v3 examplar key") - if err := ctlV3Get(ctx2, []string{"v3key"}, kv{"v3key", "123"}); err != nil { - t.Fatal(err) - } - } else { - if err := ctlV3Get(ctx2, []string{"v3key"}); err != nil { - t.Fatal(err) - } - } - os.Setenv("ETCDCTL_API", "2") - - t.Log("Getting examplar key foo2") - // check if it can serve client requests - if err := etcdctlSet(epc2, "foo2", "bar2"); err != nil { - t.Fatal(err) - } - if err := etcdctlGet(epc2, "foo2", "bar2", false); err != nil { - t.Fatal(err) - } - - t.Log("Closing etcd-2") - if err := epc2.Close(); err != nil { - t.Fatalf("error closing etcd processes (%v)", err) - } -} - -func TestCtlV2AuthWithCommonName(t *testing.T) { - BeforeTestV2(t) - - copiedCfg := e2e.NewConfigClientTLS() - copiedCfg.ClientCertAuthEnabled = true - copiedCfg.EnableV2 = true - epc := setupEtcdctlTest(t, copiedCfg, false) - defer cleanupEtcdProcessCluster(epc, t) - - if err := etcdctlRoleAdd(epc, "testrole"); err != nil { - t.Fatalf("failed to add role (%v)", err) - } - if err := etcdctlRoleGrant(epc, "testrole", "--rw", "--path=/foo"); err != nil { - t.Fatalf("failed to grant role (%v)", err) - } - if err := etcdctlUserAdd(epc, "root", "123"); err != nil { - t.Fatalf("failed to add user (%v)", err) - } - if err := etcdctlUserAdd(epc, "Autogenerated CA", "123"); err != nil { - t.Fatalf("failed to add user (%v)", err) - } - if err := etcdctlUserGrant(epc, "Autogenerated CA", "testrole"); err != nil { - t.Fatalf("failed to grant role (%v)", err) - } - if err := etcdctlAuthEnable(epc); err != nil { - t.Fatalf("failed to enable auth (%v)", err) - } - if err := etcdctlSet(epc, "foo", "bar"); err != nil { - t.Fatalf("failed to write (%v)", err) - } -} - -func TestCtlV2ClusterHealth(t *testing.T) { - BeforeTestV2(t) - - copied := e2e.NewConfigNoTLS() - copied.EnableV2 = true - epc := setupEtcdctlTest(t, copied, true) - defer cleanupEtcdProcessCluster(epc, t) - - // all members available - if err := etcdctlClusterHealth(epc, "cluster is healthy"); err != nil { - t.Fatalf("cluster-health expected to be healthy (%v)", err) - } - - // missing members, has quorum - epc.Procs[0].Stop() - - for i := 0; i < 3; i++ { - err := etcdctlClusterHealth(epc, "cluster is degraded") - if err == nil { - break - } else if i == 2 { - t.Fatalf("cluster-health expected to be degraded (%v)", err) - } - // possibly no leader yet; retry - time.Sleep(time.Second) - } - - // no quorum - epc.Procs[1].Stop() - if err := etcdctlClusterHealth(epc, "cluster is unavailable"); err != nil { - t.Fatalf("cluster-health expected to be unavailable (%v)", err) - } - - epc.Procs[0], epc.Procs[1] = nil, nil -} - -func etcdctlPrefixArgs(clus *e2e.EtcdProcessCluster) []string { - endpoints := strings.Join(clus.EndpointsV2(), ",") - cmdArgs := []string{e2e.CtlBinPath} - - cmdArgs = append(cmdArgs, "--endpoints", endpoints) - if clus.Cfg.ClientTLS == e2e.ClientTLS { - cmdArgs = append(cmdArgs, "--ca-file", e2e.CaPath, "--cert-file", e2e.CertPath, "--key-file", e2e.PrivateKeyPath) - } - return cmdArgs -} - -func etcductlPrefixArgs(utl bool) []string { - if utl { - return []string{e2e.UtlBinPath} - } - return []string{e2e.CtlBinPath} -} - -func etcdctlClusterHealth(clus *e2e.EtcdProcessCluster, val string) error { - cmdArgs := append(etcdctlPrefixArgs(clus), "cluster-health") - return e2e.SpawnWithExpect(cmdArgs, val) -} - -func etcdctlSet(clus *e2e.EtcdProcessCluster, key, value string) error { - cmdArgs := append(etcdctlPrefixArgs(clus), "set", key, value) - return e2e.SpawnWithExpect(cmdArgs, value) -} - -func etcdctlMk(clus *e2e.EtcdProcessCluster, key, value string, first bool) error { - cmdArgs := append(etcdctlPrefixArgs(clus), "mk", key, value) - if first { - return e2e.SpawnWithExpect(cmdArgs, value) - } - return e2e.SpawnWithExpect(cmdArgs, "Error: 105: Key already exists") -} - -func etcdctlGet(clus *e2e.EtcdProcessCluster, key, value string, quorum bool) error { - cmdArgs := append(etcdctlPrefixArgs(clus), "get", key) - if quorum { - cmdArgs = append(cmdArgs, "--quorum") - } - return e2e.SpawnWithExpect(cmdArgs, value) -} - -func etcdctlRm(clus *e2e.EtcdProcessCluster, key, value string, first bool) error { - cmdArgs := append(etcdctlPrefixArgs(clus), "rm", key) - if first { - return e2e.SpawnWithExpect(cmdArgs, "PrevNode.Value: "+value) - } - return e2e.SpawnWithExpect(cmdArgs, "Error: 100: Key not found") -} - -func etcdctlLs(clus *e2e.EtcdProcessCluster, key string, quorum bool) error { - cmdArgs := append(etcdctlPrefixArgs(clus), "ls") - if quorum { - cmdArgs = append(cmdArgs, "--quorum") - } - return e2e.SpawnWithExpect(cmdArgs, key) -} - -func etcdctlWatch(clus *e2e.EtcdProcessCluster, key, value string, noSync bool) <-chan error { - cmdArgs := append(etcdctlPrefixArgs(clus), "watch", "--after-index=1", key) - if noSync { - cmdArgs = append(cmdArgs, "--no-sync") - } - errc := make(chan error, 1) - go func() { - errc <- e2e.SpawnWithExpect(cmdArgs, value) - }() - return errc -} - -func etcdctlRoleAdd(clus *e2e.EtcdProcessCluster, role string) error { - cmdArgs := append(etcdctlPrefixArgs(clus), "role", "add", role) - return e2e.SpawnWithExpect(cmdArgs, role) -} - -func etcdctlRoleGrant(clus *e2e.EtcdProcessCluster, role string, perms ...string) error { - cmdArgs := append(etcdctlPrefixArgs(clus), "role", "grant") - cmdArgs = append(cmdArgs, perms...) - cmdArgs = append(cmdArgs, role) - return e2e.SpawnWithExpect(cmdArgs, role) -} - -func etcdctlRoleList(clus *e2e.EtcdProcessCluster, expectedRole string) error { - cmdArgs := append(etcdctlPrefixArgs(clus), "role", "list") - return e2e.SpawnWithExpect(cmdArgs, expectedRole) -} - -func etcdctlUserAdd(clus *e2e.EtcdProcessCluster, user, pass string) error { - cmdArgs := append(etcdctlPrefixArgs(clus), "user", "add", user+":"+pass) - return e2e.SpawnWithExpect(cmdArgs, "User "+user+" created") -} - -func etcdctlUserGrant(clus *e2e.EtcdProcessCluster, user, role string) error { - cmdArgs := append(etcdctlPrefixArgs(clus), "user", "grant", "--roles", role, user) - return e2e.SpawnWithExpect(cmdArgs, "User "+user+" updated") -} - -func etcdctlUserGet(clus *e2e.EtcdProcessCluster, user string) error { - cmdArgs := append(etcdctlPrefixArgs(clus), "user", "get", user) - return e2e.SpawnWithExpect(cmdArgs, "User: "+user) -} - -func etcdctlUserList(clus *e2e.EtcdProcessCluster, expectedUser string) error { - cmdArgs := append(etcdctlPrefixArgs(clus), "user", "list") - return e2e.SpawnWithExpect(cmdArgs, expectedUser) -} - -func etcdctlAuthEnable(clus *e2e.EtcdProcessCluster) error { - cmdArgs := append(etcdctlPrefixArgs(clus), "auth", "enable") - return e2e.SpawnWithExpect(cmdArgs, "Authentication Enabled") -} - -func etcdctlBackup(t testing.TB, clus *e2e.EtcdProcessCluster, dataDir, backupDir string, v3 bool, utl bool) error { - cmdArgs := append(etcductlPrefixArgs(utl), "backup", "--data-dir", dataDir, "--backup-dir", backupDir) - if v3 { - cmdArgs = append(cmdArgs, "--with-v3") - } else if utl { - cmdArgs = append(cmdArgs, "--with-v3=false") - } - t.Logf("Running: %v", cmdArgs) - proc, err := e2e.SpawnCmd(cmdArgs, nil) - if err != nil { - return err - } - err = proc.Close() - if err != nil { - return err - } - return proc.ProcessError() -} - -func setupEtcdctlTest(t *testing.T, cfg *e2e.EtcdProcessClusterConfig, quorum bool) *e2e.EtcdProcessCluster { - if !quorum { - cfg = e2e.ConfigStandalone(*cfg) - } - epc, err := e2e.NewEtcdProcessCluster(t, cfg) - if err != nil { - t.Fatalf("could not start etcd process cluster (%v)", err) - } - return epc -} - -func cleanupEtcdProcessCluster(epc *e2e.EtcdProcessCluster, t *testing.T) { - if errC := epc.Close(); errC != nil { - t.Fatalf("error closing etcd processes (%v)", errC) - } -} diff --git a/tests/e2e/ctl_v3_move_leader_test.go b/tests/e2e/ctl_v3_move_leader_test.go index c0a6a2492fca..9176ee45c182 100644 --- a/tests/e2e/ctl_v3_move_leader_test.go +++ b/tests/e2e/ctl_v3_move_leader_test.go @@ -118,3 +118,14 @@ func testCtlV3MoveLeader(t *testing.T, cfg e2e.EtcdProcessClusterConfig) { } } } + +func setupEtcdctlTest(t *testing.T, cfg *e2e.EtcdProcessClusterConfig, quorum bool) *e2e.EtcdProcessCluster { + if !quorum { + cfg = e2e.ConfigStandalone(*cfg) + } + epc, err := e2e.NewEtcdProcessCluster(t, cfg) + if err != nil { + t.Fatalf("could not start etcd process cluster (%v)", err) + } + return epc +} diff --git a/tests/e2e/v2_curl_test.go b/tests/e2e/v2_curl_test.go deleted file mode 100644 index ce647440891d..000000000000 --- a/tests/e2e/v2_curl_test.go +++ /dev/null @@ -1,115 +0,0 @@ -// Copyright 2016 The etcd Authors -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -package e2e - -import ( - "strings" - "testing" - - "go.etcd.io/etcd/tests/v3/framework/e2e" -) - -func TestV2CurlNoTLS(t *testing.T) { testCurlPutGet(t, e2e.NewConfigNoTLS()) } -func TestV2CurlAutoTLS(t *testing.T) { testCurlPutGet(t, e2e.NewConfigAutoTLS()) } -func TestV2CurlAllTLS(t *testing.T) { testCurlPutGet(t, e2e.NewConfigTLS()) } -func TestV2CurlPeerTLS(t *testing.T) { testCurlPutGet(t, e2e.NewConfigPeerTLS()) } -func TestV2CurlClientTLS(t *testing.T) { testCurlPutGet(t, e2e.NewConfigClientTLS()) } -func TestV2CurlClientBoth(t *testing.T) { testCurlPutGet(t, e2e.NewConfigClientBoth()) } -func testCurlPutGet(t *testing.T, cfg *e2e.EtcdProcessClusterConfig) { - BeforeTestV2(t) - - // test doesn't use quorum gets, so ensure there are no followers to avoid - // stale reads that will break the test - cfg = e2e.ConfigStandalone(*cfg) - - cfg.EnableV2 = true - epc, err := e2e.NewEtcdProcessCluster(t, cfg) - if err != nil { - t.Fatalf("could not start etcd process cluster (%v)", err) - } - defer func() { - if err := epc.Close(); err != nil { - t.Fatalf("error closing etcd processes (%v)", err) - } - }() - - var ( - expectPut = `{"action":"set","node":{"key":"/foo","value":"bar","` - expectGet = `{"action":"get","node":{"key":"/foo","value":"bar","` - ) - if err := e2e.CURLPut(epc, e2e.CURLReq{Endpoint: "/v2/keys/foo", Value: "bar", Expected: expectPut}); err != nil { - t.Fatalf("failed put with curl (%v)", err) - } - if err := e2e.CURLGet(epc, e2e.CURLReq{Endpoint: "/v2/keys/foo", Expected: expectGet}); err != nil { - t.Fatalf("failed get with curl (%v)", err) - } - if cfg.ClientTLS == e2e.ClientTLSAndNonTLS { - if err := e2e.CURLGet(epc, e2e.CURLReq{Endpoint: "/v2/keys/foo", Expected: expectGet, IsTLS: true}); err != nil { - t.Fatalf("failed get with curl (%v)", err) - } - } -} - -func TestV2CurlIssue5182(t *testing.T) { - BeforeTestV2(t) - - copied := e2e.NewConfigNoTLS() - copied.EnableV2 = true - epc := setupEtcdctlTest(t, copied, false) - defer func() { - if err := epc.Close(); err != nil { - t.Fatalf("error closing etcd processes (%v)", err) - } - }() - - expectPut := `{"action":"set","node":{"key":"/foo","value":"bar","` - if err := e2e.CURLPut(epc, e2e.CURLReq{Endpoint: "/v2/keys/foo", Value: "bar", Expected: expectPut}); err != nil { - t.Fatal(err) - } - - expectUserAdd := `{"user":"foo","roles":null}` - if err := e2e.CURLPut(epc, e2e.CURLReq{Endpoint: "/v2/auth/users/foo", Value: `{"user":"foo", "password":"pass"}`, Expected: expectUserAdd}); err != nil { - t.Fatal(err) - } - expectRoleAdd := `{"role":"foo","permissions":{"kv":{"read":["/foo/*"],"write":null}}` - if err := e2e.CURLPut(epc, e2e.CURLReq{Endpoint: "/v2/auth/roles/foo", Value: `{"role":"foo", "permissions": {"kv": {"read": ["/foo/*"]}}}`, Expected: expectRoleAdd}); err != nil { - t.Fatal(err) - } - expectUserUpdate := `{"user":"foo","roles":["foo"]}` - if err := e2e.CURLPut(epc, e2e.CURLReq{Endpoint: "/v2/auth/users/foo", Value: `{"user": "foo", "grant": ["foo"]}`, Expected: expectUserUpdate}); err != nil { - t.Fatal(err) - } - - if err := etcdctlUserAdd(epc, "root", "a"); err != nil { - t.Fatal(err) - } - if err := etcdctlAuthEnable(epc); err != nil { - t.Fatal(err) - } - - if err := e2e.CURLGet(epc, e2e.CURLReq{Endpoint: "/v2/keys/foo/", Username: "root", Password: "a", Expected: "bar"}); err != nil { - t.Fatal(err) - } - if err := e2e.CURLGet(epc, e2e.CURLReq{Endpoint: "/v2/keys/foo/", Username: "foo", Password: "pass", Expected: "bar"}); err != nil { - t.Fatal(err) - } - if err := e2e.CURLGet(epc, e2e.CURLReq{Endpoint: "/v2/keys/foo/", Username: "foo", Password: "", Expected: "bar"}); err != nil { - if !strings.Contains(err.Error(), `The request requires user authentication`) { - t.Fatalf("expected 'The request requires user authentication' error, got %v", err) - } - } else { - t.Fatalf("expected 'The request requires user authentication' error") - } -} diff --git a/tests/e2e/v2store_deprecation_test.go b/tests/e2e/v2store_deprecation_test.go index 52dec549b075..98442d842d9d 100644 --- a/tests/e2e/v2store_deprecation_test.go +++ b/tests/e2e/v2store_deprecation_test.go @@ -19,13 +19,14 @@ import ( "testing" "github.com/stretchr/testify/assert" + "go.etcd.io/etcd/client/pkg/v3/fileutil" "go.etcd.io/etcd/tests/v3/framework/e2e" ) -func createV2store(t testing.TB, dataDirPath string) { +func createV2store(t testing.TB, lastReleaseBinary string, dataDirPath string) { t.Log("Creating not-yet v2-deprecated etcd") - cfg := e2e.ConfigStandalone(e2e.EtcdProcessClusterConfig{EnableV2: true, DataDirPath: dataDirPath, SnapshotCount: 5}) + cfg := e2e.ConfigStandalone(e2e.EtcdProcessClusterConfig{ExecPath: lastReleaseBinary, EnableV2: true, DataDirPath: dataDirPath, SnapshotCount: 5}) epc, err := e2e.NewEtcdProcessCluster(t, cfg) assert.NoError(t, err) @@ -46,20 +47,13 @@ func createV2store(t testing.TB, dataDirPath string) { func assertVerifyCanStartV2deprecationNotYet(t testing.TB, dataDirPath string) { t.Log("verify: possible to start etcd with --v2-deprecation=not-yet mode") - cfg := e2e.ConfigStandalone(e2e.EtcdProcessClusterConfig{EnableV2: true, DataDirPath: dataDirPath, V2deprecation: "not-yet", KeepDataDir: true}) + cfg := e2e.ConfigStandalone(e2e.EtcdProcessClusterConfig{DataDirPath: dataDirPath, V2deprecation: "not-yet", KeepDataDir: true}) epc, err := e2e.NewEtcdProcessCluster(t, cfg) assert.NoError(t, err) defer func() { assert.NoError(t, epc.Stop()) }() - - if err := e2e.CURLGet(epc, e2e.CURLReq{ - Endpoint: "/v2/keys/foo", - Expected: `{"action":"get","node":{"key":"/foo","value":"bar9","modifiedIndex":13,"createdIndex":13}}`}); err != nil { - t.Fatalf("failed get with curl (%v)", err) - } - } func assertVerifyCannotStartV2deprecationWriteOnly(t testing.TB, dataDirPath string) { @@ -75,8 +69,13 @@ func TestV2Deprecation(t *testing.T) { e2e.BeforeTest(t) dataDirPath := t.TempDir() + lastReleaseBinary := e2e.BinDir + "/etcd-last-release" + if !fileutil.Exist(lastReleaseBinary) { + t.Skipf("%q does not exist", lastReleaseBinary) + } + t.Run("create-storev2-data", func(t *testing.T) { - createV2store(t, dataDirPath) + createV2store(t, lastReleaseBinary, dataDirPath) }) t.Run("--v2-deprecation=write-only fails", func(t *testing.T) { @@ -88,12 +87,3 @@ func TestV2Deprecation(t *testing.T) { }) } - -func TestV2DeprecationWriteOnlyNoV2Api(t *testing.T) { - e2e.BeforeTest(t) - proc, err := e2e.SpawnCmd([]string{e2e.BinDir + "/etcd", "--v2-deprecation=write-only", "--enable-v2"}, nil) - assert.NoError(t, err) - - _, err = proc.Expect("--enable-v2 and --v2-deprecation=write-only are mutually exclusive") - assert.NoError(t, err) -} diff --git a/tests/framework/e2e/cluster.go b/tests/framework/e2e/cluster.go index d6bc1434126f..445c84de954e 100644 --- a/tests/framework/e2e/cluster.go +++ b/tests/framework/e2e/cluster.go @@ -273,7 +273,6 @@ func (cfg *EtcdProcessClusterConfig) EtcdServerProcessConfigs(tb testing.TB) []* "--data-dir", dataDirPath, "--snapshot-count", fmt.Sprintf("%d", cfg.SnapshotCount), } - args = AddV2Args(args) if cfg.ForceNewCluster { args = append(args, "--force-new-cluster") } diff --git a/tests/framework/e2e/v2.go b/tests/framework/e2e/v2.go deleted file mode 100644 index 4610841fe347..000000000000 --- a/tests/framework/e2e/v2.go +++ /dev/null @@ -1,20 +0,0 @@ -// Copyright 2017 The etcd Authors -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -//go:build !v2v3 -// +build !v2v3 - -package e2e - -func AddV2Args(args []string) []string { return args } diff --git a/tests/framework/e2e/v2v3.go b/tests/framework/e2e/v2v3.go deleted file mode 100644 index a42bb936d0f0..000000000000 --- a/tests/framework/e2e/v2v3.go +++ /dev/null @@ -1,22 +0,0 @@ -// Copyright 2017 The etcd Authors -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -//go:build v2v3 -// +build v2v3 - -package e2e - -func AddV2Args(args []string) []string { - return append(args, "--experimental-enable-v2v3", "v2/") -} diff --git a/tests/integration/client/examples/example_keys_test.go b/tests/integration/client/examples/example_keys_test.go deleted file mode 100644 index 87a76769f0a9..000000000000 --- a/tests/integration/client/examples/example_keys_test.go +++ /dev/null @@ -1,111 +0,0 @@ -// Copyright 2017 The etcd Authors -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -package client_test - -import ( - "context" - "fmt" - "log" - "sort" - - "go.etcd.io/etcd/client/v2" -) - -func mockKeysAPI_directory() { - // TODO: Replace with proper mocking - fmt.Println(`Key: "/myNodes/key1", Value: "value1"`) - fmt.Println(`Key: "/myNodes/key2", Value: "value2"`) -} - -func ExampleKeysAPI_directory() { - forUnitTestsRunInMockedContext( - mockKeysAPI_directory, - func() { - c, err := client.New(client.Config{ - Endpoints: exampleEndpoints(), - Transport: exampleTransport(), - }) - if err != nil { - log.Fatal(err) - } - kapi := client.NewKeysAPI(c) - - // Setting '/myNodes' to create a directory that will hold some keys. - o := client.SetOptions{Dir: true} - resp, err := kapi.Set(context.Background(), "/myNodes", "", &o) - if err != nil { - log.Fatal(err) - } - - // Add keys to /myNodes directory. - resp, err = kapi.Set(context.Background(), "/myNodes/key1", "value1", nil) - if err != nil { - log.Fatal(err) - } - resp, err = kapi.Set(context.Background(), "/myNodes/key2", "value2", nil) - if err != nil { - log.Fatal(err) - } - - // fetch directory - resp, err = kapi.Get(context.Background(), "/myNodes", nil) - if err != nil { - log.Fatal(err) - } - // print directory keys - sort.Sort(resp.Node.Nodes) - for _, n := range resp.Node.Nodes { - fmt.Printf("Key: %q, Value: %q\n", n.Key, n.Value) - } - }) - - // Output: - // Key: "/myNodes/key1", Value: "value1" - // Key: "/myNodes/key2", Value: "value2" -} - -func mockKeysAPI_setget() { - fmt.Println(`"/foo" key has "bar" value`) -} - -func ExampleKeysAPI_setget() { - forUnitTestsRunInMockedContext( - mockKeysAPI_setget, - func() { - c, err := client.New(client.Config{ - Endpoints: exampleEndpoints(), - Transport: exampleTransport(), - }) - if err != nil { - log.Fatal(err) - } - kapi := client.NewKeysAPI(c) - - // Set key "/foo" to value "bar". - resp, err := kapi.Set(context.Background(), "/foo", "bar", nil) - if err != nil { - log.Fatal(err) - } - // Get key "/foo" - resp, err = kapi.Get(context.Background(), "/foo", nil) - if err != nil { - log.Fatal(err) - } - - fmt.Printf("%q key has %q value\n", resp.Node.Key, resp.Node.Value) - }) - - // Output: "/foo" key has "bar" value -} diff --git a/tests/integration/client/examples/main_test.go b/tests/integration/client/examples/main_test.go deleted file mode 100644 index 4323e95806bb..000000000000 --- a/tests/integration/client/examples/main_test.go +++ /dev/null @@ -1,44 +0,0 @@ -// Copyright 2017 The etcd Authors -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -package client_test - -import ( - "net/http" - "os" - "testing" - - "go.etcd.io/etcd/client/pkg/v3/testutil" - "go.etcd.io/etcd/tests/v3/integration" -) - -var lazyCluster = integration.NewLazyCluster() - -func exampleEndpoints() []string { return lazyCluster.EndpointsV2() } -func exampleTransport() *http.Transport { return lazyCluster.Transport() } - -func forUnitTestsRunInMockedContext(mocking func(), example func()) { - // For integration tests runs in the provided environment - example() -} - -// TestMain sets up an etcd cluster if running the examples. -func TestMain(m *testing.M) { - v := m.Run() - lazyCluster.Terminate() - if v == 0 { - testutil.MustCheckLeakedGoroutine() - } - os.Exit(v) -} diff --git a/tests/integration/v2_http_kv_test.go b/tests/integration/v2_http_kv_test.go deleted file mode 100644 index 5704d833950b..000000000000 --- a/tests/integration/v2_http_kv_test.go +++ /dev/null @@ -1,1152 +0,0 @@ -// Copyright 2015 The etcd Authors -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -package integration - -import ( - "encoding/json" - "fmt" - "io" - "net/http" - "net/url" - "reflect" - "strings" - "testing" - "time" - - "go.etcd.io/etcd/client/pkg/v3/transport" - "go.etcd.io/etcd/tests/v3/framework/integration" -) - -func TestV2Set(t *testing.T) { - integration.BeforeTest(t) - cl := integration.NewCluster(t, 1) - cl.Launch(t) - defer cl.Terminate(t) - - u := cl.URL(0) - tc := NewTestClient() - v := url.Values{} - v.Set("value", "bar") - vAndNoValue := url.Values{} - vAndNoValue.Set("value", "bar") - vAndNoValue.Set("noValueOnSuccess", "true") - - tests := []struct { - relativeURL string - value url.Values - wStatus int - w string - }{ - { - "/v2/keys/foo/bar", - v, - http.StatusCreated, - `{"action":"set","node":{"key":"/foo/bar","value":"bar","modifiedIndex":4,"createdIndex":4}}`, - }, - { - "/v2/keys/foodir?dir=true", - url.Values{}, - http.StatusCreated, - `{"action":"set","node":{"key":"/foodir","dir":true,"modifiedIndex":5,"createdIndex":5}}`, - }, - { - "/v2/keys/fooempty", - url.Values(map[string][]string{"value": {""}}), - http.StatusCreated, - `{"action":"set","node":{"key":"/fooempty","value":"","modifiedIndex":6,"createdIndex":6}}`, - }, - { - "/v2/keys/foo/novalue", - vAndNoValue, - http.StatusCreated, - `{"action":"set"}`, - }, - } - - for i, tt := range tests { - resp, err := tc.PutForm(fmt.Sprintf("%s%s", u, tt.relativeURL), tt.value) - if err != nil { - t.Errorf("#%d: err = %v, want nil", i, err) - } - g := string(tc.ReadBody(resp)) - w := tt.w + "\n" - if g != w { - t.Errorf("#%d: body = %v, want %v", i, g, w) - } - if resp.StatusCode != tt.wStatus { - t.Errorf("#%d: status = %d, want %d", i, resp.StatusCode, tt.wStatus) - } - } -} - -func TestV2CreateUpdate(t *testing.T) { - integration.BeforeTest(t) - cl := integration.NewCluster(t, 1) - cl.Launch(t) - defer cl.Terminate(t) - - u := cl.URL(0) - tc := NewTestClient() - - tests := []struct { - relativeURL string - value url.Values - wStatus int - w map[string]interface{} - }{ - // key with ttl - { - "/v2/keys/ttl/foo", - url.Values(map[string][]string{"value": {"XXX"}, "ttl": {"20"}}), - http.StatusCreated, - map[string]interface{}{ - "node": map[string]interface{}{ - "value": "XXX", - "ttl": float64(20), - }, - }, - }, - // key with bad ttl - { - "/v2/keys/ttl/foo", - url.Values(map[string][]string{"value": {"XXX"}, "ttl": {"bad_ttl"}}), - http.StatusBadRequest, - map[string]interface{}{ - "errorCode": float64(202), - "message": "The given TTL in POST form is not a number", - }, - }, - // create key - { - "/v2/keys/create/foo", - url.Values(map[string][]string{"value": {"XXX"}, "prevExist": {"false"}}), - http.StatusCreated, - map[string]interface{}{ - "node": map[string]interface{}{ - "value": "XXX", - }, - }, - }, - // created key failed - { - "/v2/keys/create/foo", - url.Values(map[string][]string{"value": {"XXX"}, "prevExist": {"false"}}), - http.StatusPreconditionFailed, - map[string]interface{}{ - "errorCode": float64(105), - "message": "Key already exists", - "cause": "/create/foo", - }, - }, - // update the newly created key with ttl - { - "/v2/keys/create/foo", - url.Values(map[string][]string{"value": {"YYY"}, "prevExist": {"true"}, "ttl": {"20"}}), - http.StatusOK, - map[string]interface{}{ - "node": map[string]interface{}{ - "value": "YYY", - "ttl": float64(20), - }, - "action": "update", - }, - }, - // update the ttl to none - { - "/v2/keys/create/foo", - url.Values(map[string][]string{"value": {"ZZZ"}, "prevExist": {"true"}}), - http.StatusOK, - map[string]interface{}{ - "node": map[string]interface{}{ - "value": "ZZZ", - }, - "action": "update", - }, - }, - // update on a non-existing key - { - "/v2/keys/nonexist", - url.Values(map[string][]string{"value": {"XXX"}, "prevExist": {"true"}}), - http.StatusNotFound, - map[string]interface{}{ - "errorCode": float64(100), - "message": "Key not found", - "cause": "/nonexist", - }, - }, - // create with no value on success - { - "/v2/keys/create/novalue", - url.Values(map[string][]string{"value": {"XXX"}, "prevExist": {"false"}, "noValueOnSuccess": {"true"}}), - http.StatusCreated, - map[string]interface{}{}, - }, - // update with no value on success - { - "/v2/keys/create/novalue", - url.Values(map[string][]string{"value": {"XXX"}, "prevExist": {"true"}, "noValueOnSuccess": {"true"}}), - http.StatusOK, - map[string]interface{}{}, - }, - // created key failed with no value on success - { - "/v2/keys/create/foo", - url.Values(map[string][]string{"value": {"XXX"}, "prevExist": {"false"}, "noValueOnSuccess": {"true"}}), - http.StatusPreconditionFailed, - map[string]interface{}{ - "errorCode": float64(105), - "message": "Key already exists", - "cause": "/create/foo", - }, - }, - } - - for i, tt := range tests { - resp, err := tc.PutForm(fmt.Sprintf("%s%s", u, tt.relativeURL), tt.value) - if err != nil { - t.Fatalf("#%d: put err = %v, want nil", i, err) - } - if resp.StatusCode != tt.wStatus { - t.Errorf("#%d: status = %d, want %d", i, resp.StatusCode, tt.wStatus) - } - if err := checkBody(tc.ReadBodyJSON(resp), tt.w); err != nil { - t.Errorf("#%d: %v", i, err) - } - } -} - -func TestV2CAS(t *testing.T) { - integration.BeforeTest(t) - cl := integration.NewCluster(t, 1) - cl.Launch(t) - defer cl.Terminate(t) - - u := cl.URL(0) - tc := NewTestClient() - - tests := []struct { - relativeURL string - value url.Values - wStatus int - w map[string]interface{} - }{ - { - "/v2/keys/cas/foo", - url.Values(map[string][]string{"value": {"XXX"}}), - http.StatusCreated, - nil, - }, - { - "/v2/keys/cas/foo", - url.Values(map[string][]string{"value": {"YYY"}, "prevIndex": {"4"}}), - http.StatusOK, - map[string]interface{}{ - "node": map[string]interface{}{ - "value": "YYY", - "modifiedIndex": float64(5), - }, - "action": "compareAndSwap", - }, - }, - { - "/v2/keys/cas/foo", - url.Values(map[string][]string{"value": {"YYY"}, "prevIndex": {"10"}}), - http.StatusPreconditionFailed, - map[string]interface{}{ - "errorCode": float64(101), - "message": "Compare failed", - "cause": "[10 != 5]", - "index": float64(5), - }, - }, - { - "/v2/keys/cas/foo", - url.Values(map[string][]string{"value": {"YYY"}, "prevIndex": {"bad_index"}}), - http.StatusBadRequest, - map[string]interface{}{ - "errorCode": float64(203), - "message": "The given index in POST form is not a number", - }, - }, - { - "/v2/keys/cas/foo", - url.Values(map[string][]string{"value": {"ZZZ"}, "prevValue": {"YYY"}}), - http.StatusOK, - map[string]interface{}{ - "node": map[string]interface{}{ - "value": "ZZZ", - }, - "action": "compareAndSwap", - }, - }, - { - "/v2/keys/cas/foo", - url.Values(map[string][]string{"value": {"XXX"}, "prevValue": {"bad_value"}}), - http.StatusPreconditionFailed, - map[string]interface{}{ - "errorCode": float64(101), - "message": "Compare failed", - "cause": "[bad_value != ZZZ]", - }, - }, - // prevValue is required - { - "/v2/keys/cas/foo", - url.Values(map[string][]string{"value": {"XXX"}, "prevValue": {""}}), - http.StatusBadRequest, - map[string]interface{}{ - "errorCode": float64(201), - }, - }, - { - "/v2/keys/cas/foo", - url.Values(map[string][]string{"value": {"XXX"}, "prevValue": {"bad_value"}, "prevIndex": {"100"}}), - http.StatusPreconditionFailed, - map[string]interface{}{ - "errorCode": float64(101), - "message": "Compare failed", - "cause": "[bad_value != ZZZ] [100 != 6]", - }, - }, - { - "/v2/keys/cas/foo", - url.Values(map[string][]string{"value": {"XXX"}, "prevValue": {"ZZZ"}, "prevIndex": {"100"}}), - http.StatusPreconditionFailed, - map[string]interface{}{ - "errorCode": float64(101), - "message": "Compare failed", - "cause": "[100 != 6]", - }, - }, - { - "/v2/keys/cas/foo", - url.Values(map[string][]string{"value": {"XXX"}, "prevValue": {"bad_value"}, "prevIndex": {"6"}}), - http.StatusPreconditionFailed, - map[string]interface{}{ - "errorCode": float64(101), - "message": "Compare failed", - "cause": "[bad_value != ZZZ]", - }, - }, - { - "/v2/keys/cas/foo", - url.Values(map[string][]string{"value": {"YYY"}, "prevIndex": {"6"}, "noValueOnSuccess": {"true"}}), - http.StatusOK, - map[string]interface{}{ - "action": "compareAndSwap", - }, - }, - { - "/v2/keys/cas/foo", - url.Values(map[string][]string{"value": {"YYY"}, "prevIndex": {"10"}, "noValueOnSuccess": {"true"}}), - http.StatusPreconditionFailed, - map[string]interface{}{ - "errorCode": float64(101), - "message": "Compare failed", - "cause": "[10 != 7]", - "index": float64(7), - }, - }, - } - - for i, tt := range tests { - resp, err := tc.PutForm(fmt.Sprintf("%s%s", u, tt.relativeURL), tt.value) - if err != nil { - t.Fatalf("#%d: put err = %v, want nil", i, err) - } - if resp.StatusCode != tt.wStatus { - t.Errorf("#%d: status = %d, want %d", i, resp.StatusCode, tt.wStatus) - } - if err := checkBody(tc.ReadBodyJSON(resp), tt.w); err != nil { - t.Errorf("#%d: %v", i, err) - } - } -} - -func TestV2Delete(t *testing.T) { - integration.BeforeTest(t) - cl := integration.NewCluster(t, 1) - cl.Launch(t) - defer cl.Terminate(t) - - u := cl.URL(0) - tc := NewTestClient() - - v := url.Values{} - v.Set("value", "XXX") - r, err := tc.PutForm(fmt.Sprintf("%s%s", u, "/v2/keys/foo"), v) - if err != nil { - t.Error(err) - } - r.Body.Close() - r, err = tc.PutForm(fmt.Sprintf("%s%s", u, "/v2/keys/emptydir?dir=true"), v) - if err != nil { - t.Error(err) - } - r.Body.Close() - r, err = tc.PutForm(fmt.Sprintf("%s%s", u, "/v2/keys/foodir/bar?dir=true"), v) - if err != nil { - t.Error(err) - } - r.Body.Close() - - tests := []struct { - relativeURL string - wStatus int - w map[string]interface{} - }{ - { - "/v2/keys/foo", - http.StatusOK, - map[string]interface{}{ - "node": map[string]interface{}{ - "key": "/foo", - }, - "prevNode": map[string]interface{}{ - "key": "/foo", - "value": "XXX", - }, - "action": "delete", - }, - }, - { - "/v2/keys/emptydir", - http.StatusForbidden, - map[string]interface{}{ - "errorCode": float64(102), - "message": "Not a file", - "cause": "/emptydir", - }, - }, - { - "/v2/keys/emptydir?dir=true", - http.StatusOK, - nil, - }, - { - "/v2/keys/foodir?dir=true", - http.StatusForbidden, - map[string]interface{}{ - "errorCode": float64(108), - "message": "Directory not empty", - "cause": "/foodir", - }, - }, - { - "/v2/keys/foodir?recursive=true", - http.StatusOK, - map[string]interface{}{ - "node": map[string]interface{}{ - "key": "/foodir", - "dir": true, - }, - "prevNode": map[string]interface{}{ - "key": "/foodir", - "dir": true, - }, - "action": "delete", - }, - }, - } - - for i, tt := range tests { - resp, err := tc.DeleteForm(fmt.Sprintf("%s%s", u, tt.relativeURL), nil) - if err != nil { - t.Fatalf("#%d: delete err = %v, want nil", i, err) - } - if resp.StatusCode != tt.wStatus { - t.Errorf("#%d: status = %d, want %d", i, resp.StatusCode, tt.wStatus) - } - if err := checkBody(tc.ReadBodyJSON(resp), tt.w); err != nil { - t.Errorf("#%d: %v", i, err) - } - } -} - -func TestV2CAD(t *testing.T) { - integration.BeforeTest(t) - cl := integration.NewCluster(t, 1) - cl.Launch(t) - defer cl.Terminate(t) - - u := cl.URL(0) - tc := NewTestClient() - - v := url.Values{} - v.Set("value", "XXX") - r, err := tc.PutForm(fmt.Sprintf("%s%s", u, "/v2/keys/foo"), v) - if err != nil { - t.Error(err) - } - r.Body.Close() - - r, err = tc.PutForm(fmt.Sprintf("%s%s", u, "/v2/keys/foovalue"), v) - if err != nil { - t.Error(err) - } - r.Body.Close() - - tests := []struct { - relativeURL string - wStatus int - w map[string]interface{} - }{ - { - "/v2/keys/foo?prevIndex=100", - http.StatusPreconditionFailed, - map[string]interface{}{ - "errorCode": float64(101), - "message": "Compare failed", - "cause": "[100 != 4]", - }, - }, - { - "/v2/keys/foo?prevIndex=bad_index", - http.StatusBadRequest, - map[string]interface{}{ - "errorCode": float64(203), - "message": "The given index in POST form is not a number", - }, - }, - { - "/v2/keys/foo?prevIndex=4", - http.StatusOK, - map[string]interface{}{ - "node": map[string]interface{}{ - "key": "/foo", - "modifiedIndex": float64(6), - }, - "action": "compareAndDelete", - }, - }, - { - "/v2/keys/foovalue?prevValue=YYY", - http.StatusPreconditionFailed, - map[string]interface{}{ - "errorCode": float64(101), - "message": "Compare failed", - "cause": "[YYY != XXX]", - }, - }, - { - "/v2/keys/foovalue?prevValue=", - http.StatusBadRequest, - map[string]interface{}{ - "errorCode": float64(201), - "cause": `"prevValue" cannot be empty`, - }, - }, - { - "/v2/keys/foovalue?prevValue=XXX", - http.StatusOK, - map[string]interface{}{ - "node": map[string]interface{}{ - "key": "/foovalue", - "modifiedIndex": float64(7), - }, - "action": "compareAndDelete", - }, - }, - } - - for i, tt := range tests { - resp, err := tc.DeleteForm(fmt.Sprintf("%s%s", u, tt.relativeURL), nil) - if err != nil { - t.Fatalf("#%d: delete err = %v, want nil", i, err) - } - if resp.StatusCode != tt.wStatus { - t.Errorf("#%d: status = %d, want %d", i, resp.StatusCode, tt.wStatus) - } - if err := checkBody(tc.ReadBodyJSON(resp), tt.w); err != nil { - t.Errorf("#%d: %v", i, err) - } - } -} - -func TestV2Unique(t *testing.T) { - integration.BeforeTest(t) - cl := integration.NewCluster(t, 1) - cl.Launch(t) - defer cl.Terminate(t) - - u := cl.URL(0) - tc := NewTestClient() - - tests := []struct { - relativeURL string - value url.Values - wStatus int - w map[string]interface{} - }{ - { - "/v2/keys/foo", - url.Values(map[string][]string{"value": {"XXX"}}), - http.StatusCreated, - map[string]interface{}{ - "node": map[string]interface{}{ - "key": "/foo/00000000000000000004", - "value": "XXX", - }, - "action": "create", - }, - }, - { - "/v2/keys/foo", - url.Values(map[string][]string{"value": {"XXX"}}), - http.StatusCreated, - map[string]interface{}{ - "node": map[string]interface{}{ - "key": "/foo/00000000000000000005", - "value": "XXX", - }, - "action": "create", - }, - }, - { - "/v2/keys/bar", - url.Values(map[string][]string{"value": {"XXX"}}), - http.StatusCreated, - map[string]interface{}{ - "node": map[string]interface{}{ - "key": "/bar/00000000000000000006", - "value": "XXX", - }, - "action": "create", - }, - }, - } - - for i, tt := range tests { - resp, err := tc.PostForm(fmt.Sprintf("%s%s", u, tt.relativeURL), tt.value) - if err != nil { - t.Fatalf("#%d: post err = %v, want nil", i, err) - } - if resp.StatusCode != tt.wStatus { - t.Errorf("#%d: status = %d, want %d", i, resp.StatusCode, tt.wStatus) - } - if err := checkBody(tc.ReadBodyJSON(resp), tt.w); err != nil { - t.Errorf("#%d: %v", i, err) - } - } -} - -func TestV2Get(t *testing.T) { - integration.BeforeTest(t) - cl := integration.NewCluster(t, 1) - cl.Launch(t) - defer cl.Terminate(t) - - u := cl.URL(0) - tc := NewTestClient() - - v := url.Values{} - v.Set("value", "XXX") - r, err := tc.PutForm(fmt.Sprintf("%s%s", u, "/v2/keys/foo/bar/zar"), v) - if err != nil { - t.Error(err) - } - r.Body.Close() - - tests := []struct { - relativeURL string - wStatus int - w map[string]interface{} - }{ - { - "/v2/keys/foo/bar/zar", - http.StatusOK, - map[string]interface{}{ - "node": map[string]interface{}{ - "key": "/foo/bar/zar", - "value": "XXX", - }, - "action": "get", - }, - }, - { - "/v2/keys/foo", - http.StatusOK, - map[string]interface{}{ - "node": map[string]interface{}{ - "key": "/foo", - "dir": true, - "nodes": []interface{}{ - map[string]interface{}{ - "key": "/foo/bar", - "dir": true, - "createdIndex": float64(4), - "modifiedIndex": float64(4), - }, - }, - }, - "action": "get", - }, - }, - { - "/v2/keys/foo?recursive=true", - http.StatusOK, - map[string]interface{}{ - "node": map[string]interface{}{ - "key": "/foo", - "dir": true, - "nodes": []interface{}{ - map[string]interface{}{ - "key": "/foo/bar", - "dir": true, - "createdIndex": float64(4), - "modifiedIndex": float64(4), - "nodes": []interface{}{ - map[string]interface{}{ - "key": "/foo/bar/zar", - "value": "XXX", - "createdIndex": float64(4), - "modifiedIndex": float64(4), - }, - }, - }, - }, - }, - "action": "get", - }, - }, - } - - for i, tt := range tests { - resp, err := tc.Get(fmt.Sprintf("%s%s", u, tt.relativeURL)) - if err != nil { - t.Fatalf("#%d: get err = %v, want nil", i, err) - } - if resp.StatusCode != tt.wStatus { - t.Errorf("#%d: status = %d, want %d", i, resp.StatusCode, tt.wStatus) - } - if resp.Header.Get("Content-Type") != "application/json" { - t.Errorf("#%d: header = %v, want %v", i, resp.Header.Get("Content-Type"), "application/json") - } - if err := checkBody(tc.ReadBodyJSON(resp), tt.w); err != nil { - t.Errorf("#%d: %v", i, err) - } - } -} - -func TestV2QuorumGet(t *testing.T) { - integration.BeforeTest(t) - cl := integration.NewCluster(t, 1) - cl.Launch(t) - defer cl.Terminate(t) - - u := cl.URL(0) - tc := NewTestClient() - - v := url.Values{} - v.Set("value", "XXX") - r, err := tc.PutForm(fmt.Sprintf("%s%s", u, "/v2/keys/foo/bar/zar?quorum=true"), v) - if err != nil { - t.Error(err) - } - r.Body.Close() - - tests := []struct { - relativeURL string - wStatus int - w map[string]interface{} - }{ - { - "/v2/keys/foo/bar/zar", - http.StatusOK, - map[string]interface{}{ - "node": map[string]interface{}{ - "key": "/foo/bar/zar", - "value": "XXX", - }, - "action": "get", - }, - }, - { - "/v2/keys/foo", - http.StatusOK, - map[string]interface{}{ - "node": map[string]interface{}{ - "key": "/foo", - "dir": true, - "nodes": []interface{}{ - map[string]interface{}{ - "key": "/foo/bar", - "dir": true, - "createdIndex": float64(4), - "modifiedIndex": float64(4), - }, - }, - }, - "action": "get", - }, - }, - { - "/v2/keys/foo?recursive=true", - http.StatusOK, - map[string]interface{}{ - "node": map[string]interface{}{ - "key": "/foo", - "dir": true, - "nodes": []interface{}{ - map[string]interface{}{ - "key": "/foo/bar", - "dir": true, - "createdIndex": float64(4), - "modifiedIndex": float64(4), - "nodes": []interface{}{ - map[string]interface{}{ - "key": "/foo/bar/zar", - "value": "XXX", - "createdIndex": float64(4), - "modifiedIndex": float64(4), - }, - }, - }, - }, - }, - "action": "get", - }, - }, - } - - for i, tt := range tests { - resp, err := tc.Get(fmt.Sprintf("%s%s", u, tt.relativeURL)) - if err != nil { - t.Fatalf("#%d: get err = %v, want nil", i, err) - } - if resp.StatusCode != tt.wStatus { - t.Errorf("#%d: status = %d, want %d", i, resp.StatusCode, tt.wStatus) - } - if resp.Header.Get("Content-Type") != "application/json" { - t.Errorf("#%d: header = %v, want %v", i, resp.Header.Get("Content-Type"), "application/json") - } - if err := checkBody(tc.ReadBodyJSON(resp), tt.w); err != nil { - t.Errorf("#%d: %v", i, err) - } - } -} - -func TestV2Watch(t *testing.T) { - integration.BeforeTest(t) - cl := integration.NewCluster(t, 1) - cl.Launch(t) - defer cl.Terminate(t) - - u := cl.URL(0) - tc := NewTestClient() - - watchResp, err := tc.Get(fmt.Sprintf("%s%s", u, "/v2/keys/foo/bar?wait=true")) - if err != nil { - t.Fatalf("watch err = %v, want nil", err) - } - - // Set a value. - v := url.Values{} - v.Set("value", "XXX") - resp, err := tc.PutForm(fmt.Sprintf("%s%s", u, "/v2/keys/foo/bar"), v) - if err != nil { - t.Fatalf("put err = %v, want nil", err) - } - resp.Body.Close() - - body := tc.ReadBodyJSON(watchResp) - w := map[string]interface{}{ - "node": map[string]interface{}{ - "key": "/foo/bar", - "value": "XXX", - "modifiedIndex": float64(4), - }, - "action": "set", - } - - if err := checkBody(body, w); err != nil { - t.Error(err) - } -} - -func TestV2WatchWithIndex(t *testing.T) { - integration.BeforeTest(t) - cl := integration.NewCluster(t, 1) - cl.Launch(t) - defer cl.Terminate(t) - - u := cl.URL(0) - tc := NewTestClient() - - var body map[string]interface{} - c := make(chan bool, 1) - go func() { - resp, err := tc.Get(fmt.Sprintf("%s%s", u, "/v2/keys/foo/bar?wait=true&waitIndex=5")) - if err != nil { - t.Errorf("watch err = %v, want nil", err) - } - body = tc.ReadBodyJSON(resp) - c <- true - }() - - select { - case <-c: - t.Fatal("should not get the watch result") - case <-time.After(time.Millisecond): - } - - // Set a value (before given index). - v := url.Values{} - v.Set("value", "XXX") - resp, err := tc.PutForm(fmt.Sprintf("%s%s", u, "/v2/keys/foo/bar"), v) - if err != nil { - t.Fatalf("put err = %v, want nil", err) - } - resp.Body.Close() - - select { - case <-c: - t.Fatal("should not get the watch result") - case <-time.After(time.Millisecond): - } - - // Set a value (before given index). - resp, err = tc.PutForm(fmt.Sprintf("%s%s", u, "/v2/keys/foo/bar"), v) - if err != nil { - t.Fatalf("put err = %v, want nil", err) - } - resp.Body.Close() - - select { - case <-c: - case <-time.After(time.Second): - t.Fatal("cannot get watch result") - } - - w := map[string]interface{}{ - "node": map[string]interface{}{ - "key": "/foo/bar", - "value": "XXX", - "modifiedIndex": float64(5), - }, - "action": "set", - } - if err := checkBody(body, w); err != nil { - t.Error(err) - } -} - -func TestV2WatchKeyInDir(t *testing.T) { - integration.BeforeTest(t) - cl := integration.NewCluster(t, 1) - cl.Launch(t) - defer cl.Terminate(t) - - u := cl.URL(0) - tc := NewTestClient() - - var body map[string]interface{} - c := make(chan bool, 1) - - // Create an expiring directory - v := url.Values{} - v.Set("dir", "true") - v.Set("ttl", "1") - resp, err := tc.PutForm(fmt.Sprintf("%s%s", u, "/v2/keys/keyindir"), v) - if err != nil { - t.Fatalf("put err = %v, want nil", err) - } - resp.Body.Close() - - // Create a permanent node within the directory - v = url.Values{} - v.Set("value", "XXX") - resp, err = tc.PutForm(fmt.Sprintf("%s%s", u, "/v2/keys/keyindir/bar"), v) - if err != nil { - t.Fatalf("put err = %v, want nil", err) - } - resp.Body.Close() - - go func() { - // Expect a notification when watching the node - resp, err := tc.Get(fmt.Sprintf("%s%s", u, "/v2/keys/keyindir/bar?wait=true")) - if err != nil { - t.Errorf("watch err = %v, want nil", err) - } - body = tc.ReadBodyJSON(resp) - c <- true - }() - - select { - case <-c: - // 1s ttl + 0.5s sync delay + 1.5s disk and network delay - // We set that long disk and network delay because travis may be slow - // when do system calls. - case <-time.After(3 * time.Second): - t.Fatal("timed out waiting for watch result") - } - - w := map[string]interface{}{ - "node": map[string]interface{}{ - "key": "/keyindir", - }, - "action": "expire", - } - if err := checkBody(body, w); err != nil { - t.Error(err) - } -} - -func TestV2Head(t *testing.T) { - integration.BeforeTest(t) - cl := integration.NewCluster(t, 1) - cl.Launch(t) - defer cl.Terminate(t) - - u := cl.URL(0) - tc := NewTestClient() - - v := url.Values{} - v.Set("value", "XXX") - fullURL := fmt.Sprintf("%s%s", u, "/v2/keys/foo/bar") - resp, err := tc.Head(fullURL) - if err != nil { - t.Fatalf("head err = %v, want nil", err) - } - resp.Body.Close() - if resp.StatusCode != http.StatusNotFound { - t.Errorf("status = %d, want %d", resp.StatusCode, http.StatusNotFound) - } - if resp.ContentLength <= 0 { - t.Errorf("ContentLength = %d, want > 0", resp.ContentLength) - } - - resp, err = tc.PutForm(fullURL, v) - if err != nil { - t.Fatalf("put err = %v, want nil", err) - } - resp.Body.Close() - - resp, err = tc.Head(fullURL) - if err != nil { - t.Fatalf("head err = %v, want nil", err) - } - resp.Body.Close() - if resp.StatusCode != http.StatusOK { - t.Errorf("status = %d, want %d", resp.StatusCode, http.StatusOK) - } - if resp.ContentLength <= 0 { - t.Errorf("ContentLength = %d, want > 0", resp.ContentLength) - } -} - -func checkBody(body map[string]interface{}, w map[string]interface{}) error { - if body["node"] != nil { - if w["node"] != nil { - wn := w["node"].(map[string]interface{}) - n := body["node"].(map[string]interface{}) - for k := range n { - if wn[k] == nil { - delete(n, k) - } - } - body["node"] = n - } - if w["prevNode"] != nil { - wn := w["prevNode"].(map[string]interface{}) - n := body["prevNode"].(map[string]interface{}) - for k := range n { - if wn[k] == nil { - delete(n, k) - } - } - body["prevNode"] = n - } - } - for k, v := range w { - g := body[k] - if !reflect.DeepEqual(g, v) { - return fmt.Errorf("%v = %+v, want %+v", k, g, v) - } - } - return nil -} - -type testHttpClient struct { - *http.Client -} - -// Creates a new HTTP client with KeepAlive disabled. -func NewTestClient() *testHttpClient { - tr, _ := transport.NewTransport(transport.TLSInfo{}, time.Second) - tr.DisableKeepAlives = true - return &testHttpClient{&http.Client{Transport: tr}} -} - -// Reads the body from the response and closes it. -func (t *testHttpClient) ReadBody(resp *http.Response) []byte { - if resp == nil { - return []byte{} - } - body, _ := io.ReadAll(resp.Body) - resp.Body.Close() - return body -} - -// Reads the body from the response and parses it as JSON. -func (t *testHttpClient) ReadBodyJSON(resp *http.Response) map[string]interface{} { - m := make(map[string]interface{}) - b := t.ReadBody(resp) - if err := json.Unmarshal(b, &m); err != nil { - panic(fmt.Sprintf("HTTP body JSON parse error: %v: %s", err, string(b))) - } - return m -} - -func (t *testHttpClient) Head(url string) (*http.Response, error) { - return t.send("HEAD", url, "application/json", nil) -} - -func (t *testHttpClient) Get(url string) (*http.Response, error) { - return t.send("GET", url, "application/json", nil) -} - -func (t *testHttpClient) Post(url string, bodyType string, body io.Reader) (*http.Response, error) { - return t.send("POST", url, bodyType, body) -} - -func (t *testHttpClient) PostForm(url string, data url.Values) (*http.Response, error) { - return t.Post(url, "application/x-www-form-urlencoded", strings.NewReader(data.Encode())) -} - -func (t *testHttpClient) Put(url string, bodyType string, body io.Reader) (*http.Response, error) { - return t.send("PUT", url, bodyType, body) -} - -func (t *testHttpClient) PutForm(url string, data url.Values) (*http.Response, error) { - return t.Put(url, "application/x-www-form-urlencoded", strings.NewReader(data.Encode())) -} - -func (t *testHttpClient) Delete(url string, bodyType string, body io.Reader) (*http.Response, error) { - return t.send("DELETE", url, bodyType, body) -} - -func (t *testHttpClient) DeleteForm(url string, data url.Values) (*http.Response, error) { - return t.Delete(url, "application/x-www-form-urlencoded", strings.NewReader(data.Encode())) -} - -func (t *testHttpClient) send(method string, url string, bodyType string, body io.Reader) (*http.Response, error) { - req, err := http.NewRequest(method, url, body) - if err != nil { - return nil, err - } - req.Header.Set("Content-Type", bodyType) - return t.Do(req) -} diff --git a/tests/integration/v2store/store_tag_not_v2v3_test.go b/tests/integration/v2store/store_tag_test.go similarity index 84% rename from tests/integration/v2store/store_tag_not_v2v3_test.go rename to tests/integration/v2store/store_tag_test.go index 012fe4c52e03..4b5722e0db0d 100644 --- a/tests/integration/v2store/store_tag_not_v2v3_test.go +++ b/tests/integration/v2store/store_tag_test.go @@ -12,9 +12,6 @@ // See the License for the specific language governing permissions and // limitations under the License. -//go:build !v2v3 -// +build !v2v3 - package v2store_test import ( @@ -26,24 +23,10 @@ import ( integration2 "go.etcd.io/etcd/tests/v3/framework/integration" ) -type v2TestStore struct { - v2store.Store -} - -func (s *v2TestStore) Close() {} - -func newTestStore(t *testing.T, ns ...string) StoreCloser { - if len(ns) == 0 { - t.Logf("new v2 store with no namespace") - } - return &v2TestStore{v2store.New(ns...)} -} - // Ensure that the store can recover from a previously saved state. func TestStoreRecover(t *testing.T) { integration2.BeforeTest(t) - s := newTestStore(t) - defer s.Close() + s := v2store.New() var eidx uint64 = 4 s.Create("/foo", true, "", false, v2store.TTLOptionSet{ExpireTime: v2store.Permanent}) s.Create("/foo/x", false, "bar", false, v2store.TTLOptionSet{ExpireTime: v2store.Permanent}) @@ -52,7 +35,7 @@ func TestStoreRecover(t *testing.T) { b, err := s.Save() testutil.AssertNil(t, err) - s2 := newTestStore(t) + s2 := v2store.New() s2.Recovery(b) e, err := s.Get("/foo/x", false, false) diff --git a/tests/integration/v2store/store_tag_v2v3_test.go b/tests/integration/v2store/store_tag_v2v3_test.go deleted file mode 100644 index 970d9643a088..000000000000 --- a/tests/integration/v2store/store_tag_v2v3_test.go +++ /dev/null @@ -1,44 +0,0 @@ -// Copyright 2017 The etcd Authors -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -//go:build v2v3 -// +build v2v3 - -package v2store_test - -import ( - "testing" - - "go.etcd.io/etcd/server/v3/etcdserver/api/v2store" - "go.etcd.io/etcd/server/v3/etcdserver/api/v2v3" - integration2 "go.etcd.io/etcd/tests/v3/framework/integration" -) - -type v2v3TestStore struct { - v2store.Store - clus *integration2.ClusterV3 - t *testing.T -} - -func (s *v2v3TestStore) Close() { s.clus.Terminate(s.t) } - -func newTestStore(t *testing.T, ns ...string) StoreCloser { - integration2.BeforeTest(t) - clus := integration2.NewClusterV3(t, &integration2.ClusterConfig{Size: 1}) - return &v2v3TestStore{ - v2v3.NewStore(clus.Client(0), "/v2/"), - clus, - t, - } -} diff --git a/tests/integration/v2store/store_test.go b/tests/integration/v2store/store_test.go index 59ee050d438e..a944e9f4cff6 100644 --- a/tests/integration/v2store/store_test.go +++ b/tests/integration/v2store/store_test.go @@ -31,8 +31,7 @@ type StoreCloser interface { } func TestNewStoreWithNamespaces(t *testing.T) { - s := newTestStore(t, "/0", "/1") - defer s.Close() + s := v2store.New("/0", "/1") _, err := s.Get("/0", false, false) testutil.AssertNil(t, err) @@ -42,8 +41,7 @@ func TestNewStoreWithNamespaces(t *testing.T) { // Ensure that the store can retrieve an existing value. func TestStoreGetValue(t *testing.T) { - s := newTestStore(t) - defer s.Close() + s := v2store.New() s.Create("/foo", false, "bar", false, v2store.TTLOptionSet{ExpireTime: v2store.Permanent}) var eidx uint64 = 1 @@ -57,8 +55,7 @@ func TestStoreGetValue(t *testing.T) { // Ensure that the store can retrieve a directory in sorted order. func TestStoreGetSorted(t *testing.T) { - s := newTestStore(t) - defer s.Close() + s := v2store.New() s.Create("/foo", true, "", false, v2store.TTLOptionSet{ExpireTime: v2store.Permanent}) s.Create("/foo/x", false, "0", false, v2store.TTLOptionSet{ExpireTime: v2store.Permanent}) @@ -93,8 +90,7 @@ func TestStoreGetSorted(t *testing.T) { } func TestSet(t *testing.T) { - s := newTestStore(t) - defer s.Close() + s := v2store.New() // Set /foo="" var eidx uint64 = 1 @@ -177,8 +173,7 @@ func TestSet(t *testing.T) { // Ensure that the store can create a new key if it doesn't already exist. func TestStoreCreateValue(t *testing.T) { - s := newTestStore(t) - defer s.Close() + s := v2store.New() // Create /foo=bar var eidx uint64 = 1 @@ -212,8 +207,7 @@ func TestStoreCreateValue(t *testing.T) { // Ensure that the store can create a new directory if it doesn't already exist. func TestStoreCreateDirectory(t *testing.T) { - s := newTestStore(t) - defer s.Close() + s := v2store.New() var eidx uint64 = 1 e, err := s.Create("/foo", true, "", false, v2store.TTLOptionSet{ExpireTime: v2store.Permanent}) @@ -226,8 +220,7 @@ func TestStoreCreateDirectory(t *testing.T) { // Ensure that the store fails to create a key if it already exists. func TestStoreCreateFailsIfExists(t *testing.T) { - s := newTestStore(t) - defer s.Close() + s := v2store.New() // create /foo as dir s.Create("/foo", true, "", false, v2store.TTLOptionSet{ExpireTime: v2store.Permanent}) @@ -244,8 +237,7 @@ func TestStoreCreateFailsIfExists(t *testing.T) { // Ensure that the store can update a key if it already exists. func TestStoreUpdateValue(t *testing.T) { - s := newTestStore(t) - defer s.Close() + s := v2store.New() // create /foo=bar s.Create("/foo", false, "bar", false, v2store.TTLOptionSet{ExpireTime: v2store.Permanent}) @@ -294,8 +286,7 @@ func TestStoreUpdateValue(t *testing.T) { // Ensure that the store cannot update a directory. func TestStoreUpdateFailsIfDirectory(t *testing.T) { - s := newTestStore(t) - defer s.Close() + s := v2store.New() s.Create("/foo", true, "", false, v2store.TTLOptionSet{ExpireTime: v2store.Permanent}) e, _err := s.Update("/foo", "baz", v2store.TTLOptionSet{ExpireTime: v2store.Permanent}) @@ -308,8 +299,7 @@ func TestStoreUpdateFailsIfDirectory(t *testing.T) { // Ensure that the store can delete a value. func TestStoreDeleteValue(t *testing.T) { - s := newTestStore(t) - defer s.Close() + s := v2store.New() var eidx uint64 = 2 s.Create("/foo", false, "bar", false, v2store.TTLOptionSet{ExpireTime: v2store.Permanent}) @@ -325,8 +315,7 @@ func TestStoreDeleteValue(t *testing.T) { // Ensure that the store can delete a directory if recursive is specified. func TestStoreDeleteDirectory(t *testing.T) { - s := newTestStore(t) - defer s.Close() + s := v2store.New() // create directory /foo var eidx uint64 = 2 @@ -363,8 +352,7 @@ func TestStoreDeleteDirectory(t *testing.T) { // Ensure that the store cannot delete a directory if both of recursive // and dir are not specified. func TestStoreDeleteDirectoryFailsIfNonRecursiveAndDir(t *testing.T) { - s := newTestStore(t) - defer s.Close() + s := v2store.New() s.Create("/foo", true, "", false, v2store.TTLOptionSet{ExpireTime: v2store.Permanent}) e, _err := s.Delete("/foo", false, false) @@ -375,8 +363,7 @@ func TestStoreDeleteDirectoryFailsIfNonRecursiveAndDir(t *testing.T) { } func TestRootRdOnly(t *testing.T) { - s := newTestStore(t, "/0") - defer s.Close() + s := v2store.New("/0") for _, tt := range []string{"/", "/0"} { _, err := s.Set(tt, true, "", v2store.TTLOptionSet{ExpireTime: v2store.Permanent}) @@ -397,8 +384,7 @@ func TestRootRdOnly(t *testing.T) { } func TestStoreCompareAndDeletePrevValue(t *testing.T) { - s := newTestStore(t) - defer s.Close() + s := v2store.New() var eidx uint64 = 2 s.Create("/foo", false, "bar", false, v2store.TTLOptionSet{ExpireTime: v2store.Permanent}) @@ -417,8 +403,7 @@ func TestStoreCompareAndDeletePrevValue(t *testing.T) { } func TestStoreCompareAndDeletePrevValueFailsIfNotMatch(t *testing.T) { - s := newTestStore(t) - defer s.Close() + s := v2store.New() var eidx uint64 = 1 s.Create("/foo", false, "bar", false, v2store.TTLOptionSet{ExpireTime: v2store.Permanent}) @@ -433,8 +418,7 @@ func TestStoreCompareAndDeletePrevValueFailsIfNotMatch(t *testing.T) { } func TestStoreCompareAndDeletePrevIndex(t *testing.T) { - s := newTestStore(t) - defer s.Close() + s := v2store.New() var eidx uint64 = 2 s.Create("/foo", false, "bar", false, v2store.TTLOptionSet{ExpireTime: v2store.Permanent}) @@ -451,8 +435,7 @@ func TestStoreCompareAndDeletePrevIndex(t *testing.T) { } func TestStoreCompareAndDeletePrevIndexFailsIfNotMatch(t *testing.T) { - s := newTestStore(t) - defer s.Close() + s := v2store.New() var eidx uint64 = 1 s.Create("/foo", false, "bar", false, v2store.TTLOptionSet{ExpireTime: v2store.Permanent}) @@ -469,8 +452,7 @@ func TestStoreCompareAndDeletePrevIndexFailsIfNotMatch(t *testing.T) { // Ensure that the store cannot delete a directory. func TestStoreCompareAndDeleteDirectoryFail(t *testing.T) { - s := newTestStore(t) - defer s.Close() + s := v2store.New() s.Create("/foo", true, "", false, v2store.TTLOptionSet{ExpireTime: v2store.Permanent}) _, _err := s.CompareAndDelete("/foo", "", 0) @@ -481,8 +463,7 @@ func TestStoreCompareAndDeleteDirectoryFail(t *testing.T) { // Ensure that the store can conditionally update a key if it has a previous value. func TestStoreCompareAndSwapPrevValue(t *testing.T) { - s := newTestStore(t) - defer s.Close() + s := v2store.New() var eidx uint64 = 2 s.Create("/foo", false, "bar", false, v2store.TTLOptionSet{ExpireTime: v2store.Permanent}) @@ -504,8 +485,7 @@ func TestStoreCompareAndSwapPrevValue(t *testing.T) { // Ensure that the store cannot conditionally update a key if it has the wrong previous value. func TestStoreCompareAndSwapPrevValueFailsIfNotMatch(t *testing.T) { - s := newTestStore(t) - defer s.Close() + s := v2store.New() var eidx uint64 = 1 s.Create("/foo", false, "bar", false, v2store.TTLOptionSet{ExpireTime: v2store.Permanent}) e, _err := s.CompareAndSwap("/foo", "wrong_value", 0, "baz", v2store.TTLOptionSet{ExpireTime: v2store.Permanent}) @@ -520,8 +500,7 @@ func TestStoreCompareAndSwapPrevValueFailsIfNotMatch(t *testing.T) { // Ensure that the store can conditionally update a key if it has a previous index. func TestStoreCompareAndSwapPrevIndex(t *testing.T) { - s := newTestStore(t) - defer s.Close() + s := v2store.New() var eidx uint64 = 2 s.Create("/foo", false, "bar", false, v2store.TTLOptionSet{ExpireTime: v2store.Permanent}) e, err := s.CompareAndSwap("/foo", "", 1, "baz", v2store.TTLOptionSet{ExpireTime: v2store.Permanent}) @@ -543,8 +522,7 @@ func TestStoreCompareAndSwapPrevIndex(t *testing.T) { // Ensure that the store cannot conditionally update a key if it has the wrong previous index. func TestStoreCompareAndSwapPrevIndexFailsIfNotMatch(t *testing.T) { - s := newTestStore(t) - defer s.Close() + s := v2store.New() var eidx uint64 = 1 s.Create("/foo", false, "bar", false, v2store.TTLOptionSet{ExpireTime: v2store.Permanent}) e, _err := s.CompareAndSwap("/foo", "", 100, "baz", v2store.TTLOptionSet{ExpireTime: v2store.Permanent}) @@ -559,8 +537,7 @@ func TestStoreCompareAndSwapPrevIndexFailsIfNotMatch(t *testing.T) { // Ensure that the store can watch for key creation. func TestStoreWatchCreate(t *testing.T) { - s := newTestStore(t) - defer s.Close() + s := v2store.New() var eidx uint64 = 0 w, _ := s.Watch("/foo", false, false, 0) c := w.EventChan() @@ -580,8 +557,7 @@ func TestStoreWatchCreate(t *testing.T) { // Ensure that the store can watch for recursive key creation. func TestStoreWatchRecursiveCreate(t *testing.T) { - s := newTestStore(t) - defer s.Close() + s := v2store.New() var eidx uint64 = 0 w, err := s.Watch("/foo", true, false, 0) testutil.AssertNil(t, err) @@ -596,8 +572,7 @@ func TestStoreWatchRecursiveCreate(t *testing.T) { // Ensure that the store can watch for key updates. func TestStoreWatchUpdate(t *testing.T) { - s := newTestStore(t) - defer s.Close() + s := v2store.New() var eidx uint64 = 1 s.Create("/foo", false, "bar", false, v2store.TTLOptionSet{ExpireTime: v2store.Permanent}) w, _ := s.Watch("/foo", false, false, 0) @@ -612,8 +587,7 @@ func TestStoreWatchUpdate(t *testing.T) { // Ensure that the store can watch for recursive key updates. func TestStoreWatchRecursiveUpdate(t *testing.T) { - s := newTestStore(t) - defer s.Close() + s := v2store.New() var eidx uint64 = 1 s.Create("/foo/bar", false, "baz", false, v2store.TTLOptionSet{ExpireTime: v2store.Permanent}) w, err := s.Watch("/foo", true, false, 0) @@ -629,8 +603,7 @@ func TestStoreWatchRecursiveUpdate(t *testing.T) { // Ensure that the store can watch for key deletions. func TestStoreWatchDelete(t *testing.T) { - s := newTestStore(t) - defer s.Close() + s := v2store.New() var eidx uint64 = 1 s.Create("/foo", false, "bar", false, v2store.TTLOptionSet{ExpireTime: v2store.Permanent}) w, _ := s.Watch("/foo", false, false, 0) @@ -645,8 +618,7 @@ func TestStoreWatchDelete(t *testing.T) { // Ensure that the store can watch for recursive key deletions. func TestStoreWatchRecursiveDelete(t *testing.T) { - s := newTestStore(t) - defer s.Close() + s := v2store.New() var eidx uint64 = 1 s.Create("/foo/bar", false, "baz", false, v2store.TTLOptionSet{ExpireTime: v2store.Permanent}) w, err := s.Watch("/foo", true, false, 0) @@ -662,8 +634,7 @@ func TestStoreWatchRecursiveDelete(t *testing.T) { // Ensure that the store can watch for CAS updates. func TestStoreWatchCompareAndSwap(t *testing.T) { - s := newTestStore(t) - defer s.Close() + s := v2store.New() var eidx uint64 = 1 s.Create("/foo", false, "bar", false, v2store.TTLOptionSet{ExpireTime: v2store.Permanent}) w, _ := s.Watch("/foo", false, false, 0) @@ -678,8 +649,7 @@ func TestStoreWatchCompareAndSwap(t *testing.T) { // Ensure that the store can watch for recursive CAS updates. func TestStoreWatchRecursiveCompareAndSwap(t *testing.T) { - s := newTestStore(t) - defer s.Close() + s := v2store.New() var eidx uint64 = 1 s.Create("/foo/bar", false, "baz", false, v2store.TTLOptionSet{ExpireTime: v2store.Permanent}) w, _ := s.Watch("/foo", true, false, 0) @@ -694,8 +664,7 @@ func TestStoreWatchRecursiveCompareAndSwap(t *testing.T) { // Ensure that the store can watch in streaming mode. func TestStoreWatchStream(t *testing.T) { - s := newTestStore(t) - defer s.Close() + s := v2store.New() var eidx uint64 = 1 w, _ := s.Watch("/foo", false, true, 0) // first modification @@ -727,8 +696,7 @@ func TestStoreWatchStream(t *testing.T) { // Ensure that the store can watch for hidden keys as long as it's an exact path match. func TestStoreWatchCreateWithHiddenKey(t *testing.T) { - s := newTestStore(t) - defer s.Close() + s := v2store.New() var eidx uint64 = 1 w, _ := s.Watch("/_foo", false, false, 0) s.Create("/_foo", false, "bar", false, v2store.TTLOptionSet{ExpireTime: v2store.Permanent}) @@ -745,8 +713,7 @@ func TestStoreWatchCreateWithHiddenKey(t *testing.T) { // Ensure that the store doesn't see hidden key creates without an exact path match in recursive mode. func TestStoreWatchRecursiveCreateWithHiddenKey(t *testing.T) { - s := newTestStore(t) - defer s.Close() + s := v2store.New() w, _ := s.Watch("/foo", true, false, 0) s.Create("/foo/_bar", false, "baz", false, v2store.TTLOptionSet{ExpireTime: v2store.Permanent}) e := nbselect(w.EventChan()) @@ -768,8 +735,7 @@ func TestStoreWatchRecursiveCreateWithHiddenKey(t *testing.T) { // Ensure that the store doesn't see hidden key updates. func TestStoreWatchUpdateWithHiddenKey(t *testing.T) { - s := newTestStore(t) - defer s.Close() + s := v2store.New() s.Create("/_foo", false, "bar", false, v2store.TTLOptionSet{ExpireTime: v2store.Permanent}) w, _ := s.Watch("/_foo", false, false, 0) s.Update("/_foo", "baz", v2store.TTLOptionSet{ExpireTime: v2store.Permanent}) @@ -782,8 +748,7 @@ func TestStoreWatchUpdateWithHiddenKey(t *testing.T) { // Ensure that the store doesn't see hidden key updates without an exact path match in recursive mode. func TestStoreWatchRecursiveUpdateWithHiddenKey(t *testing.T) { - s := newTestStore(t) - defer s.Close() + s := v2store.New() s.Create("/foo/_bar", false, "baz", false, v2store.TTLOptionSet{ExpireTime: v2store.Permanent}) w, _ := s.Watch("/foo", true, false, 0) s.Update("/foo/_bar", "baz", v2store.TTLOptionSet{ExpireTime: v2store.Permanent}) @@ -793,8 +758,7 @@ func TestStoreWatchRecursiveUpdateWithHiddenKey(t *testing.T) { // Ensure that the store can watch for key deletions. func TestStoreWatchDeleteWithHiddenKey(t *testing.T) { - s := newTestStore(t) - defer s.Close() + s := v2store.New() var eidx uint64 = 2 s.Create("/_foo", false, "bar", false, v2store.TTLOptionSet{ExpireTime: v2store.Permanent}) w, _ := s.Watch("/_foo", false, false, 0) @@ -809,8 +773,7 @@ func TestStoreWatchDeleteWithHiddenKey(t *testing.T) { // Ensure that the store doesn't see hidden key deletes without an exact path match in recursive mode. func TestStoreWatchRecursiveDeleteWithHiddenKey(t *testing.T) { - s := newTestStore(t) - defer s.Close() + s := v2store.New() s.Create("/foo/_bar", false, "baz", false, v2store.TTLOptionSet{ExpireTime: v2store.Permanent}) w, _ := s.Watch("/foo", true, false, 0) s.Delete("/foo/_bar", false, false) @@ -820,8 +783,7 @@ func TestStoreWatchRecursiveDeleteWithHiddenKey(t *testing.T) { // Ensure that the store does see hidden key creates if watching deeper than a hidden key in recursive mode. func TestStoreWatchRecursiveCreateDeeperThanHiddenKey(t *testing.T) { - s := newTestStore(t) - defer s.Close() + s := v2store.New() var eidx uint64 = 1 w, _ := s.Watch("/_foo/bar", true, false, 0) s.Create("/_foo/bar/baz", false, "baz", false, v2store.TTLOptionSet{ExpireTime: v2store.Permanent}) @@ -841,8 +803,7 @@ func TestStoreWatchRecursiveCreateDeeperThanHiddenKey(t *testing.T) { // This test ensures that after closing the channel, the store can continue // to operate correctly. func TestStoreWatchSlowConsumer(t *testing.T) { - s := newTestStore(t) - defer s.Close() + s := v2store.New() s.Watch("/foo", true, true, 0) // stream must be true // Fill watch channel with 100 events for i := 1; i <= 100; i++ { diff --git a/tests/integration/v2store/store_v2v3_test.go b/tests/integration/v2store/store_v2v3_test.go deleted file mode 100644 index 2266cb918c0b..000000000000 --- a/tests/integration/v2store/store_v2v3_test.go +++ /dev/null @@ -1,165 +0,0 @@ -// Copyright 2019 The etcd Authors -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -package v2store_test - -import ( - "strings" - "testing" - - "go.etcd.io/etcd/client/v3" - "go.etcd.io/etcd/server/v3/etcdserver/api/v2store" - "go.etcd.io/etcd/server/v3/etcdserver/api/v2v3" - integration2 "go.etcd.io/etcd/tests/v3/framework/integration" -) - -// TODO: fix tests - -func runWithCluster(t testing.TB, runner func(testing.TB, []string)) { - integration2.BeforeTest(t) - cfg := integration2.ClusterConfig{Size: 1} - clus := integration2.NewClusterV3(t, &cfg) - defer clus.Terminate(t) - endpoints := []string{clus.Client(0).Endpoints()[0]} - runner(t, endpoints) -} - -func TestCreateKV(t *testing.T) { runWithCluster(t, testCreateKV) } - -func testCreateKV(t testing.TB, endpoints []string) { - integration2.BeforeTest(t) - testCases := []struct { - key string - value string - nodes int - unique bool - wantErr bool - wantKeyMatch bool - }{ - {key: "/cdir/create", value: "1", nodes: 1, wantKeyMatch: true}, - {key: "/cdir/create", value: "4", wantErr: true}, - // TODO: unique doesn't create nodes, skip these tests for now - //{key: "hello", value: "2", unique: true, wantKeyMatch: false}, - //{key: "hello", value: "3", unique: true, wantKeyMatch: false}, - } - - cli, err := integration2.NewClient(t, clientv3.Config{Endpoints: endpoints}) - if err != nil { - t.Fatal(err) - } - defer cli.Close() - v2 := v2v3.NewStore(cli, "") - - for ti, tc := range testCases { - ev, err := v2.Create(tc.key, false, tc.value, tc.unique, v2store.TTLOptionSet{}) - if tc.wantErr && err != nil { - continue - } - if err != nil { - t.Skipf("%d: got err %v", ti, err) - } - - if tc.wantKeyMatch && tc.key != ev.Node.Key { - t.Skipf("%d: %v != %v", ti, tc.key, ev.Node.Key) - } - if !tc.wantKeyMatch && !strings.HasPrefix(ev.Node.Key, tc.key) { - t.Skipf("%d: %v is not prefix of %v", ti, tc.key, ev.Node.Key) - } - - evg, err := v2.Get(tc.key, false, false) - if err != nil { - t.Fatal(err) - } - - if evg.Node.CreatedIndex != ev.Node.CreatedIndex { - t.Skipf("%d: %v != %v", ti, evg.Node.CreatedIndex, ev.Node.CreatedIndex) - } - - t.Logf("%d: %v %s %v\n", ti, ev.Node.Key, *ev.Node.Value, ev.Node.CreatedIndex) - } -} - -func TestSetKV(t *testing.T) { runWithCluster(t, testSetKV) } - -func testSetKV(t testing.TB, endpoints []string) { - testCases := []struct { - key string - value string - wantIndexMatch bool - }{ - {key: "/sdir/set", value: "1", wantIndexMatch: true}, - {key: "/sdir/set", value: "4", wantIndexMatch: false}, - } - - cli, err := integration2.NewClient(t, clientv3.Config{Endpoints: endpoints}) - if err != nil { - t.Fatal(err) - } - defer cli.Close() - v2 := v2v3.NewStore(cli, "") - - for ti, tc := range testCases { - ev, err := v2.Set(tc.key, false, tc.value, v2store.TTLOptionSet{}) - if err != nil { - t.Skipf("%d: got err %v", ti, err) - } - - if tc.value != *ev.Node.Value { - t.Skipf("%d: %v != %v", ti, tc.value, *ev.Node.Value) - } - - if tc.wantIndexMatch && ev.Node.CreatedIndex != ev.Node.ModifiedIndex { - t.Skipf("%d: index %v != %v", ti, ev.Node.CreatedIndex, ev.Node.ModifiedIndex) - } - - t.Logf("%d: %v %s %v\n", ti, ev.Node.Key, *ev.Node.Value, ev.Node.CreatedIndex) - } -} - -func TestCreateSetDir(t *testing.T) { runWithCluster(t, testCreateSetDir) } - -func testCreateSetDir(t testing.TB, endpoints []string) { - integration2.BeforeTest(t) - testCases := []struct { - dir string - }{ - {dir: "/ddir/1/2/3"}, - {dir: "/ddir/1/2/3"}, - } - - cli, err := integration2.NewClient(t, clientv3.Config{Endpoints: endpoints}) - if err != nil { - t.Fatal(err) - } - defer cli.Close() - v2 := v2v3.NewStore(cli, "") - - for ti, tc := range testCases { - _, err := v2.Create(tc.dir, true, "", false, v2store.TTLOptionSet{}) - if err != nil { - t.Skipf("%d: got err %v", ti, err) - } - _, err = v2.Create(tc.dir, true, "", false, v2store.TTLOptionSet{}) - if err == nil { - t.Skipf("%d: expected err got nil", ti) - } - - ev, err := v2.Delete("ddir", true, true) - if err != nil { - t.Skipf("%d: got err %v", ti, err) - } - - t.Logf("%d: %v %s %v\n", ti, ev.EtcdIndex, ev.PrevNode.Key, ev.PrevNode.CreatedIndex) - } -} From 401cc1a5753ea04060f7a6299d517046f50f6885 Mon Sep 17 00:00:00 2001 From: lixd Date: Sat, 15 Jan 2022 13:16:44 +0800 Subject: [PATCH 058/258] mvcc: add a fast return at put method return when two leaseID is equal, avoid invalid operations. Fixes #13600 --- server/storage/mvcc/kvstore_txn.go | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/server/storage/mvcc/kvstore_txn.go b/server/storage/mvcc/kvstore_txn.go index 56c2335c2a61..ab04bcf5f0bb 100644 --- a/server/storage/mvcc/kvstore_txn.go +++ b/server/storage/mvcc/kvstore_txn.go @@ -220,6 +220,11 @@ func (tw *storeTxnWrite) put(key, value []byte, leaseID lease.LeaseID) { tw.changes = append(tw.changes, kv) tw.trace.Step("store kv pair into bolt db") + if oldLease == leaseID { + tw.trace.Step("attach lease to kv pair") + return + } + if oldLease != lease.NoLease { if tw.s.le == nil { panic("no lessor to detach lease") From 1d706179be981e025ca8f510ca3978644c9f92eb Mon Sep 17 00:00:00 2001 From: lixd Date: Sun, 16 Jan 2022 10:43:15 +0800 Subject: [PATCH 059/258] mvcc: add test-case a test-case for new code-path. --- server/storage/mvcc/kv_test.go | 34 ++++++++++++++++++++++++++++++++++ 1 file changed, 34 insertions(+) diff --git a/server/storage/mvcc/kv_test.go b/server/storage/mvcc/kv_test.go index f2be7f90414b..a4e13d693937 100644 --- a/server/storage/mvcc/kv_test.go +++ b/server/storage/mvcc/kv_test.go @@ -360,6 +360,40 @@ func testKVDeleteMultipleTimes(t *testing.T, f deleteRangeFunc) { } } +func TestKVPutWithSameLease(t *testing.T) { testKVPutWithSameLease(t, normalPutFunc) } +func TestKVTxnPutWithSameLease(t *testing.T) { testKVPutWithSameLease(t, txnPutFunc) } + +func testKVPutWithSameLease(t *testing.T, f putFunc) { + b, tmpPath := betesting.NewDefaultTmpBackend(t) + s := NewStore(zap.NewExample(), b, &lease.FakeLessor{}, StoreConfig{}) + defer cleanup(s, b, tmpPath) + leaseID := int64(1) + + // put foo + rev := f(s, []byte("foo"), []byte("bar"), lease.LeaseID(leaseID)) + if rev != 2 { + t.Errorf("rev = %d, want %d", 2, rev) + } + + // put foo with same lease again + rev2 := f(s, []byte("foo"), []byte("bar"), lease.LeaseID(leaseID)) + if rev2 != 3 { + t.Errorf("rev = %d, want %d", 3, rev2) + } + + // check leaseID + r, err := s.Range(context.TODO(), []byte("foo"), nil, RangeOptions{}) + if err != nil { + t.Fatal(err) + } + wkvs := []mvccpb.KeyValue{ + {Key: []byte("foo"), Value: []byte("bar"), CreateRevision: 2, ModRevision: 3, Version: 2, Lease: leaseID}, + } + if !reflect.DeepEqual(r.KVs, wkvs) { + t.Errorf("kvs = %+v, want %+v", r.KVs, wkvs) + } +} + // test that range, put, delete on single key in sequence repeatedly works correctly. func TestKVOperationInSequence(t *testing.T) { b, tmpPath := betesting.NewDefaultTmpBackend(t) From b09558844674c0431f26be7357f8c716af64ed80 Mon Sep 17 00:00:00 2001 From: ahrtr Date: Sun, 16 Jan 2022 14:55:36 +0800 Subject: [PATCH 060/258] use test.sh instead of test for linux-386-unit-1-cpu --- .github/workflows/tests.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/tests.yaml b/.github/workflows/tests.yaml index bdf47553d5d1..d33616327222 100644 --- a/.github/workflows/tests.yaml +++ b/.github/workflows/tests.yaml @@ -37,7 +37,7 @@ jobs: GOARCH=amd64 PASSES='unit' RACE='true' CPU='4' ./test.sh -p=2 ;; linux-386-unit-1-cpu) - GOARCH=386 PASSES='unit' RACE='false' CPU='1' ./test -p=4 + GOARCH=386 PASSES='unit' RACE='false' CPU='1' ./test.sh -p=4 ;; *) echo "Failed to find target" From 3710083dc398b6e0922ab06b56022f1e8d4eba45 Mon Sep 17 00:00:00 2001 From: Jille Timmermans Date: Sun, 16 Jan 2022 16:46:50 +0100 Subject: [PATCH 061/258] retry_interceptor.go: Log the method that failed When getting warnings from the retry_interceptors that RPCs failed, they provide very little context as to what exactly failed. I used this patch to try debugging https://groups.google.com/g/etcd-dev/c/3hxxr9ktdpM. --- client/v3/retry_interceptor.go | 2 ++ 1 file changed, 2 insertions(+) diff --git a/client/v3/retry_interceptor.go b/client/v3/retry_interceptor.go index 2b5d26c8f91f..36d24687d1bc 100644 --- a/client/v3/retry_interceptor.go +++ b/client/v3/retry_interceptor.go @@ -54,6 +54,7 @@ func (c *Client) unaryClientInterceptor(optFuncs ...retryOption) grpc.UnaryClien c.GetLogger().Debug( "retrying of unary invoker", zap.String("target", cc.Target()), + zap.String("method", method), zap.Uint("attempt", attempt), ) lastErr = invoker(ctx, method, req, reply, cc, grpcOpts...) @@ -63,6 +64,7 @@ func (c *Client) unaryClientInterceptor(optFuncs ...retryOption) grpc.UnaryClien c.GetLogger().Warn( "retrying of unary invoker failed", zap.String("target", cc.Target()), + zap.String("method", method), zap.Uint("attempt", attempt), zap.Error(lastErr), ) From f8aafea504874d0078348c432779f069df2c4877 Mon Sep 17 00:00:00 2001 From: ahrtr Date: Mon, 27 Dec 2021 00:26:33 +0800 Subject: [PATCH 062/258] add protection code to prevent etcd from panic when the client api version is not valid UTF-8 --- CHANGELOG-3.6.md | 1 + api/v3rpc/rpctypes/error.go | 19 ++++++++++--------- server/etcdserver/api/v3rpc/interceptor.go | 7 +++++++ 3 files changed, 18 insertions(+), 9 deletions(-) diff --git a/CHANGELOG-3.6.md b/CHANGELOG-3.6.md index 2ab8a5ddd969..03f13319f591 100644 --- a/CHANGELOG-3.6.md +++ b/CHANGELOG-3.6.md @@ -40,6 +40,7 @@ See [code changes](https://github.com/etcd-io/etcd/compare/v3.5.0...v3.6.0). - Fix [Provide a better liveness probe for when etcd runs as a Kubernetes pod](https://github.com/etcd-io/etcd/pull/13399) - Fix [Lease checkpoints don't prevent to reset ttl on leader change](https://github.com/etcd-io/etcd/pull/13508). - Fix [assertion failed due to tx closed when recovering v3 backend from a snapshot db](https://github.com/etcd-io/etcd/pull/13500) +- Fix [A client can panic etcd by passing invalid utf-8 in the client-api-version header](https://github.com/etcd-io/etcd/pull/13560) ### tools/benchmark diff --git a/api/v3rpc/rpctypes/error.go b/api/v3rpc/rpctypes/error.go index e3ffae96a360..088c03435c2d 100644 --- a/api/v3rpc/rpctypes/error.go +++ b/api/v3rpc/rpctypes/error.go @@ -21,15 +21,16 @@ import ( // server-side error var ( - ErrGRPCEmptyKey = status.New(codes.InvalidArgument, "etcdserver: key is not provided").Err() - ErrGRPCKeyNotFound = status.New(codes.InvalidArgument, "etcdserver: key not found").Err() - ErrGRPCValueProvided = status.New(codes.InvalidArgument, "etcdserver: value is provided").Err() - ErrGRPCLeaseProvided = status.New(codes.InvalidArgument, "etcdserver: lease is provided").Err() - ErrGRPCTooManyOps = status.New(codes.InvalidArgument, "etcdserver: too many operations in txn request").Err() - ErrGRPCDuplicateKey = status.New(codes.InvalidArgument, "etcdserver: duplicate key given in txn request").Err() - ErrGRPCCompacted = status.New(codes.OutOfRange, "etcdserver: mvcc: required revision has been compacted").Err() - ErrGRPCFutureRev = status.New(codes.OutOfRange, "etcdserver: mvcc: required revision is a future revision").Err() - ErrGRPCNoSpace = status.New(codes.ResourceExhausted, "etcdserver: mvcc: database space exceeded").Err() + ErrGRPCEmptyKey = status.New(codes.InvalidArgument, "etcdserver: key is not provided").Err() + ErrGRPCKeyNotFound = status.New(codes.InvalidArgument, "etcdserver: key not found").Err() + ErrGRPCValueProvided = status.New(codes.InvalidArgument, "etcdserver: value is provided").Err() + ErrGRPCLeaseProvided = status.New(codes.InvalidArgument, "etcdserver: lease is provided").Err() + ErrGRPCTooManyOps = status.New(codes.InvalidArgument, "etcdserver: too many operations in txn request").Err() + ErrGRPCDuplicateKey = status.New(codes.InvalidArgument, "etcdserver: duplicate key given in txn request").Err() + ErrGRPCInvalidClientAPIVersion = status.New(codes.InvalidArgument, "etcdserver: invalid client api version").Err() + ErrGRPCCompacted = status.New(codes.OutOfRange, "etcdserver: mvcc: required revision has been compacted").Err() + ErrGRPCFutureRev = status.New(codes.OutOfRange, "etcdserver: mvcc: required revision is a future revision").Err() + ErrGRPCNoSpace = status.New(codes.ResourceExhausted, "etcdserver: mvcc: database space exceeded").Err() ErrGRPCLeaseNotFound = status.New(codes.NotFound, "etcdserver: requested lease not found").Err() ErrGRPCLeaseExist = status.New(codes.FailedPrecondition, "etcdserver: lease already exists").Err() diff --git a/server/etcdserver/api/v3rpc/interceptor.go b/server/etcdserver/api/v3rpc/interceptor.go index 0d41ef5270d9..5e2028d1af71 100644 --- a/server/etcdserver/api/v3rpc/interceptor.go +++ b/server/etcdserver/api/v3rpc/interceptor.go @@ -18,6 +18,7 @@ import ( "context" "sync" "time" + "unicode/utf8" "go.etcd.io/etcd/api/v3/v3rpc/rpctypes" "go.etcd.io/etcd/client/pkg/v3/types" @@ -58,6 +59,9 @@ func newUnaryInterceptor(s *etcdserver.EtcdServer) grpc.UnaryServerInterceptor { if len(vs) > 0 { ver = vs[0] } + if !utf8.ValidString(ver) { + return nil, rpctypes.ErrGRPCInvalidClientAPIVersion + } clientRequests.WithLabelValues("unary", ver).Inc() if ks := md[rpctypes.MetadataRequireLeaderKey]; len(ks) > 0 && ks[0] == rpctypes.MetadataHasLeader { @@ -224,6 +228,9 @@ func newStreamInterceptor(s *etcdserver.EtcdServer) grpc.StreamServerInterceptor if len(vs) > 0 { ver = vs[0] } + if !utf8.ValidString(ver) { + return rpctypes.ErrGRPCInvalidClientAPIVersion + } clientRequests.WithLabelValues("stream", ver).Inc() if ks := md[rpctypes.MetadataRequireLeaderKey]; len(ks) > 0 && ks[0] == rpctypes.MetadataHasLeader { From 5b09de33a5f3b1eb48169a0ad1b51d48ad99ef9c Mon Sep 17 00:00:00 2001 From: horizonzy Date: Mon, 17 Jan 2022 11:12:25 +0800 Subject: [PATCH 063/258] code clean: make rangeKeys close to storeTxnRead. --- server/storage/mvcc/kvstore_txn.go | 110 ++++++++++++++--------------- 1 file changed, 55 insertions(+), 55 deletions(-) diff --git a/server/storage/mvcc/kvstore_txn.go b/server/storage/mvcc/kvstore_txn.go index 56c2335c2a61..0c74f0766b91 100644 --- a/server/storage/mvcc/kvstore_txn.go +++ b/server/storage/mvcc/kvstore_txn.go @@ -62,6 +62,61 @@ func (tr *storeTxnRead) Range(ctx context.Context, key, end []byte, ro RangeOpti return tr.rangeKeys(ctx, key, end, tr.Rev(), ro) } +func (tr *storeTxnRead) rangeKeys(ctx context.Context, key, end []byte, curRev int64, ro RangeOptions) (*RangeResult, error) { + rev := ro.Rev + if rev > curRev { + return &RangeResult{KVs: nil, Count: -1, Rev: curRev}, ErrFutureRev + } + if rev <= 0 { + rev = curRev + } + if rev < tr.s.compactMainRev { + return &RangeResult{KVs: nil, Count: -1, Rev: 0}, ErrCompacted + } + if ro.Count { + total := tr.s.kvindex.CountRevisions(key, end, rev) + tr.trace.Step("count revisions from in-memory index tree") + return &RangeResult{KVs: nil, Count: total, Rev: curRev}, nil + } + revpairs, total := tr.s.kvindex.Revisions(key, end, rev, int(ro.Limit)) + tr.trace.Step("range keys from in-memory index tree") + if len(revpairs) == 0 { + return &RangeResult{KVs: nil, Count: total, Rev: curRev}, nil + } + + limit := int(ro.Limit) + if limit <= 0 || limit > len(revpairs) { + limit = len(revpairs) + } + + kvs := make([]mvccpb.KeyValue, limit) + revBytes := newRevBytes() + for i, revpair := range revpairs[:len(kvs)] { + select { + case <-ctx.Done(): + return nil, ctx.Err() + default: + } + revToBytes(revpair, revBytes) + _, vs := tr.tx.UnsafeRange(schema.Key, revBytes, nil, 0) + if len(vs) != 1 { + tr.s.lg.Fatal( + "range failed to find revision pair", + zap.Int64("revision-main", revpair.main), + zap.Int64("revision-sub", revpair.sub), + ) + } + if err := kvs[i].Unmarshal(vs[0]); err != nil { + tr.s.lg.Fatal( + "failed to unmarshal mvccpb.KeyValue", + zap.Error(err), + ) + } + } + tr.trace.Step("range keys from bolt db") + return &RangeResult{KVs: kvs, Count: total, Rev: curRev}, nil +} + func (tr *storeTxnRead) End() { tr.tx.RUnlock() // RUnlock signals the end of concurrentReadTx. tr.s.mu.RUnlock() @@ -124,61 +179,6 @@ func (tw *storeTxnWrite) End() { tw.s.mu.RUnlock() } -func (tr *storeTxnRead) rangeKeys(ctx context.Context, key, end []byte, curRev int64, ro RangeOptions) (*RangeResult, error) { - rev := ro.Rev - if rev > curRev { - return &RangeResult{KVs: nil, Count: -1, Rev: curRev}, ErrFutureRev - } - if rev <= 0 { - rev = curRev - } - if rev < tr.s.compactMainRev { - return &RangeResult{KVs: nil, Count: -1, Rev: 0}, ErrCompacted - } - if ro.Count { - total := tr.s.kvindex.CountRevisions(key, end, rev) - tr.trace.Step("count revisions from in-memory index tree") - return &RangeResult{KVs: nil, Count: total, Rev: curRev}, nil - } - revpairs, total := tr.s.kvindex.Revisions(key, end, rev, int(ro.Limit)) - tr.trace.Step("range keys from in-memory index tree") - if len(revpairs) == 0 { - return &RangeResult{KVs: nil, Count: total, Rev: curRev}, nil - } - - limit := int(ro.Limit) - if limit <= 0 || limit > len(revpairs) { - limit = len(revpairs) - } - - kvs := make([]mvccpb.KeyValue, limit) - revBytes := newRevBytes() - for i, revpair := range revpairs[:len(kvs)] { - select { - case <-ctx.Done(): - return nil, ctx.Err() - default: - } - revToBytes(revpair, revBytes) - _, vs := tr.tx.UnsafeRange(schema.Key, revBytes, nil, 0) - if len(vs) != 1 { - tr.s.lg.Fatal( - "range failed to find revision pair", - zap.Int64("revision-main", revpair.main), - zap.Int64("revision-sub", revpair.sub), - ) - } - if err := kvs[i].Unmarshal(vs[0]); err != nil { - tr.s.lg.Fatal( - "failed to unmarshal mvccpb.KeyValue", - zap.Error(err), - ) - } - } - tr.trace.Step("range keys from bolt db") - return &RangeResult{KVs: kvs, Count: total, Rev: curRev}, nil -} - func (tw *storeTxnWrite) put(key, value []byte, leaseID lease.LeaseID) { rev := tw.beginRev + 1 c := rev From 7ef4fe3288bdc8ea9b0f89ae25e0c3c725480c2d Mon Sep 17 00:00:00 2001 From: AdamKorcz Date: Sat, 15 Jan 2022 15:45:22 +0000 Subject: [PATCH 064/258] raft: fix out-of-bounds in maybeAppend --- raft/log.go | 3 +++ 1 file changed, 3 insertions(+) diff --git a/raft/log.go b/raft/log.go index c94c41f7783e..82cf54aa2786 100644 --- a/raft/log.go +++ b/raft/log.go @@ -95,6 +95,9 @@ func (l *raftLog) maybeAppend(index, logTerm, committed uint64, ents ...pb.Entry l.logger.Panicf("entry %d conflict with committed entry [committed(%d)]", ci, l.committed) default: offset := index + 1 + if ci-offset > uint64(len(ents)) { + l.logger.Panicf("index, %d, is out of range [%d]", ci-offset, len(ents)) + } l.append(ents[ci-offset:]...) } l.commitTo(min(committed, lastnewi)) From 23f3bdd184ce07a8614aa63a31177d2c60611535 Mon Sep 17 00:00:00 2001 From: lixd Date: Mon, 17 Jan 2022 19:04:40 +0800 Subject: [PATCH 065/258] Empty Commit for CI From fdd98477ef6e3e248a70a22fb69b1c741a7a9a13 Mon Sep 17 00:00:00 2001 From: Piotr Tabor Date: Mon, 17 Jan 2022 16:05:45 +0100 Subject: [PATCH 066/258] Update dep: require gopkg.in/yaml.v2 v2.2.8 -> v2.4.0 due to: CVE-2019-11254 --- api/go.mod | 1 + api/go.sum | 3 ++- client/v2/go.mod | 1 - client/v3/go.mod | 2 +- client/v3/go.sum | 3 ++- go.sum | 1 - raft/go.sum | 1 + tests/go.sum | 1 - 8 files changed, 7 insertions(+), 6 deletions(-) diff --git a/api/go.mod b/api/go.mod index 36f0c97c1084..39d24b22a3e1 100644 --- a/api/go.mod +++ b/api/go.mod @@ -16,6 +16,7 @@ require ( golang.org/x/sys v0.0.0-20210510120138-977fb7262007 // indirect golang.org/x/text v0.3.5 // indirect google.golang.org/protobuf v1.27.1 // indirect + gopkg.in/yaml.v2 v2.4.0 // indirect ) // Bad imports are sometimes causing attempts to pull that code. diff --git a/api/go.sum b/api/go.sum index c0dacaa603be..e0d292fcdbb0 100644 --- a/api/go.sum +++ b/api/go.sum @@ -150,8 +150,9 @@ google.golang.org/protobuf v1.27.1 h1:SnqbnDw1V7RiZcXPx5MEeqPv2s79L9i7BJUlG/+Rur google.golang.org/protobuf v1.27.1/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= -gopkg.in/yaml.v2 v2.2.3 h1:fvjTMHxHEw/mxHbtzPi3JCcKXQRAnQTBRo6YCJSVHKI= gopkg.in/yaml.v2 v2.2.3/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= +gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY= +gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ= gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= honnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= diff --git a/client/v2/go.mod b/client/v2/go.mod index 7f6d6ab3b046..a473f45acfb9 100644 --- a/client/v2/go.mod +++ b/client/v2/go.mod @@ -13,7 +13,6 @@ require ( github.com/davecgh/go-spew v1.1.1 // indirect github.com/pmezard/go-difflib v1.0.0 // indirect github.com/stretchr/testify v1.7.0 // indirect - gopkg.in/yaml.v2 v2.4.0 // indirect gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b // indirect ) diff --git a/client/v3/go.mod b/client/v3/go.mod index 3c3b0f631e0c..fee83ab74edf 100644 --- a/client/v3/go.mod +++ b/client/v3/go.mod @@ -34,7 +34,7 @@ require ( golang.org/x/text v0.3.5 // indirect google.golang.org/genproto v0.0.0-20211118181313-81c1377c94b1 // indirect google.golang.org/protobuf v1.27.1 // indirect - gopkg.in/yaml.v2 v2.3.0 // indirect + gopkg.in/yaml.v2 v2.4.0 // indirect gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b // indirect ) diff --git a/client/v3/go.sum b/client/v3/go.sum index eef5c5e6ae5f..fe36400df4b4 100644 --- a/client/v3/go.sum +++ b/client/v3/go.sum @@ -263,8 +263,9 @@ gopkg.in/yaml.v2 v2.2.3/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.2.4/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.2.5/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.2.8/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= -gopkg.in/yaml.v2 v2.3.0 h1:clyUAQHOM3G0M3f5vQj7LuJrETvjVot3Z5el9nffUtU= gopkg.in/yaml.v2 v2.3.0/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= +gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY= +gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ= gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b h1:h8qDotaEPuJATrMmW04NCwg7v22aHH28wwpauUhK9Oo= gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= diff --git a/go.sum b/go.sum index edad2ccf89a3..120df214c605 100644 --- a/go.sum +++ b/go.sum @@ -472,7 +472,6 @@ golang.org/x/net v0.0.0-20210119194325-5f4716e94777/go.mod h1:m0MpNAwzfU5UDzcl9v 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-20211216030914-fe4d6282115f/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= golang.org/x/net v0.0.0-20220105145211-5b0dc2dfae98 h1:+6WJMRLHlD7X7frgp7TUZ36RnQzSf9wVVTNakEp+nqY= golang.org/x/net v0.0.0-20220105145211-5b0dc2dfae98/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= diff --git a/raft/go.sum b/raft/go.sum index 8612475354c7..5a574f3a5534 100644 --- a/raft/go.sum +++ b/raft/go.sum @@ -179,6 +179,7 @@ gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8 gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.2.3/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.2.8/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= +gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ= gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b h1:h8qDotaEPuJATrMmW04NCwg7v22aHH28wwpauUhK9Oo= gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= diff --git a/tests/go.sum b/tests/go.sum index d37937ea8db8..8c6fc404223d 100644 --- a/tests/go.sum +++ b/tests/go.sum @@ -465,7 +465,6 @@ golang.org/x/net v0.0.0-20210119194325-5f4716e94777/go.mod h1:m0MpNAwzfU5UDzcl9v 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-20211216030914-fe4d6282115f/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= golang.org/x/net v0.0.0-20220105145211-5b0dc2dfae98 h1:+6WJMRLHlD7X7frgp7TUZ36RnQzSf9wVVTNakEp+nqY= golang.org/x/net v0.0.0-20220105145211-5b0dc2dfae98/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= From 8d8247b092ebfa0ae4f3fd9ead93033302957a5c Mon Sep 17 00:00:00 2001 From: ahrtr Date: Wed, 22 Dec 2021 11:07:08 +0800 Subject: [PATCH 067/258] format listenning address correctly for IPv6 ip address --- CHANGELOG-3.6.md | 1 + server/proxy/tcpproxy/userspace.go | 19 ++++++++++++++- server/proxy/tcpproxy/userspace_test.go | 31 +++++++++++++++++++++++++ 3 files changed, 50 insertions(+), 1 deletion(-) diff --git a/CHANGELOG-3.6.md b/CHANGELOG-3.6.md index 03f13319f591..2560e057828a 100644 --- a/CHANGELOG-3.6.md +++ b/CHANGELOG-3.6.md @@ -41,6 +41,7 @@ See [code changes](https://github.com/etcd-io/etcd/compare/v3.5.0...v3.6.0). - Fix [Lease checkpoints don't prevent to reset ttl on leader change](https://github.com/etcd-io/etcd/pull/13508). - Fix [assertion failed due to tx closed when recovering v3 backend from a snapshot db](https://github.com/etcd-io/etcd/pull/13500) - Fix [A client can panic etcd by passing invalid utf-8 in the client-api-version header](https://github.com/etcd-io/etcd/pull/13560) +- Fix [etcd gateway doesn't format the endpoint of IPv6 address correctly](https://github.com/etcd-io/etcd/pull/13551) ### tools/benchmark diff --git a/server/proxy/tcpproxy/userspace.go b/server/proxy/tcpproxy/userspace.go index 81421bffa707..4df69aca8421 100644 --- a/server/proxy/tcpproxy/userspace.go +++ b/server/proxy/tcpproxy/userspace.go @@ -19,6 +19,7 @@ import ( "io" "math/rand" "net" + "strings" "sync" "time" @@ -69,13 +70,29 @@ type TCPProxy struct { pickCount int // for round robin } +// The parameter host is returned by net.SplitHostPort previously, +// so it must be a valid host. This function is only to check whether +// it's an IPv6 IP address. +func isIPv6(host string) bool { + return strings.IndexRune(host, ':') != -1 +} + +// A literal IPv6 address in hostport must be enclosed in square +// brackets, as in "[::1]:80", "[::1%lo0]:80". +func formatAddr(host string, port uint16) string { + if isIPv6(host) { + return fmt.Sprintf("[%s]:%d", host, port) + } + return fmt.Sprintf("%s:%d", host, port) +} + func (tp *TCPProxy) Run() error { tp.donec = make(chan struct{}) if tp.MonitorInterval == 0 { tp.MonitorInterval = 5 * time.Minute } for _, srv := range tp.Endpoints { - addr := fmt.Sprintf("%s:%d", srv.Target, srv.Port) + addr := formatAddr(srv.Target, srv.Port) tp.remotes = append(tp.remotes, &remote{srv: srv, addr: addr}) } diff --git a/server/proxy/tcpproxy/userspace_test.go b/server/proxy/tcpproxy/userspace_test.go index 2b98cd004d36..892e87eb8828 100644 --- a/server/proxy/tcpproxy/userspace_test.go +++ b/server/proxy/tcpproxy/userspace_test.go @@ -129,3 +129,34 @@ func TestUserspaceProxyPriority(t *testing.T) { t.Errorf("got = %s, want %s", got, want) } } + +func TestFormatAddr(t *testing.T) { + addrs := []struct { + host string + port uint16 + expectedAddr string + }{ + { + "192.168.1.10", + 2379, + "192.168.1.10:2379", + }, + { + "::1", + 2379, + "[::1]:2379", + }, + { + "2001:db8::ff00:42:8329", + 80, + "[2001:db8::ff00:42:8329]:80", + }, + } + + for _, addr := range addrs { + actualAddr := formatAddr(addr.host, addr.port) + if actualAddr != addr.expectedAddr { + t.Errorf("actualAddr: %s, expectedAddr: %s", actualAddr, addr.expectedAddr) + } + } +} From 15568f4c005a7a88b27dbde87cbfdc3b4431e69a Mon Sep 17 00:00:00 2001 From: ahrtr Date: Thu, 23 Dec 2021 05:42:26 +0800 Subject: [PATCH 068/258] add protection code for Range when the sortTarget is an invalid value --- CHANGELOG-3.6.md | 1 + api/v3rpc/rpctypes/error.go | 31 ++++++------ client/v3/kv.go | 13 +++-- client/v3/namespace/kv.go | 6 ++- client/v3/op.go | 16 ++++++ client/v3/op_test.go | 39 ++++++++++++++ server/etcdserver/api/v3rpc/key.go | 9 ++++ server/etcdserver/api/v3rpc/key_test.go | 67 +++++++++++++++++++++++++ server/etcdserver/apply.go | 4 ++ 9 files changed, 167 insertions(+), 19 deletions(-) create mode 100644 server/etcdserver/api/v3rpc/key_test.go diff --git a/CHANGELOG-3.6.md b/CHANGELOG-3.6.md index 2560e057828a..f098fb89381c 100644 --- a/CHANGELOG-3.6.md +++ b/CHANGELOG-3.6.md @@ -42,6 +42,7 @@ See [code changes](https://github.com/etcd-io/etcd/compare/v3.5.0...v3.6.0). - Fix [assertion failed due to tx closed when recovering v3 backend from a snapshot db](https://github.com/etcd-io/etcd/pull/13500) - Fix [A client can panic etcd by passing invalid utf-8 in the client-api-version header](https://github.com/etcd-io/etcd/pull/13560) - Fix [etcd gateway doesn't format the endpoint of IPv6 address correctly](https://github.com/etcd-io/etcd/pull/13551) +- Fix [A client can cause a nil dereference in etcd by passing an invalid SortTarget](https://github.com/etcd-io/etcd/pull/13555) ### tools/benchmark diff --git a/api/v3rpc/rpctypes/error.go b/api/v3rpc/rpctypes/error.go index 088c03435c2d..a00832c869dd 100644 --- a/api/v3rpc/rpctypes/error.go +++ b/api/v3rpc/rpctypes/error.go @@ -28,6 +28,7 @@ var ( ErrGRPCTooManyOps = status.New(codes.InvalidArgument, "etcdserver: too many operations in txn request").Err() ErrGRPCDuplicateKey = status.New(codes.InvalidArgument, "etcdserver: duplicate key given in txn request").Err() ErrGRPCInvalidClientAPIVersion = status.New(codes.InvalidArgument, "etcdserver: invalid client api version").Err() + ErrGRPCInvalidSortOption = status.New(codes.InvalidArgument, "etcdserver: invalid sort option").Err() ErrGRPCCompacted = status.New(codes.OutOfRange, "etcdserver: mvcc: required revision has been compacted").Err() ErrGRPCFutureRev = status.New(codes.OutOfRange, "etcdserver: mvcc: required revision is a future revision").Err() ErrGRPCNoSpace = status.New(codes.ResourceExhausted, "etcdserver: mvcc: database space exceeded").Err() @@ -96,11 +97,12 @@ var ( ErrorDesc(ErrGRPCValueProvided): ErrGRPCValueProvided, ErrorDesc(ErrGRPCLeaseProvided): ErrGRPCLeaseProvided, - ErrorDesc(ErrGRPCTooManyOps): ErrGRPCTooManyOps, - ErrorDesc(ErrGRPCDuplicateKey): ErrGRPCDuplicateKey, - ErrorDesc(ErrGRPCCompacted): ErrGRPCCompacted, - ErrorDesc(ErrGRPCFutureRev): ErrGRPCFutureRev, - ErrorDesc(ErrGRPCNoSpace): ErrGRPCNoSpace, + ErrorDesc(ErrGRPCTooManyOps): ErrGRPCTooManyOps, + ErrorDesc(ErrGRPCDuplicateKey): ErrGRPCDuplicateKey, + ErrorDesc(ErrGRPCInvalidSortOption): ErrGRPCInvalidSortOption, + ErrorDesc(ErrGRPCCompacted): ErrGRPCCompacted, + ErrorDesc(ErrGRPCFutureRev): ErrGRPCFutureRev, + ErrorDesc(ErrGRPCNoSpace): ErrGRPCNoSpace, ErrorDesc(ErrGRPCLeaseNotFound): ErrGRPCLeaseNotFound, ErrorDesc(ErrGRPCLeaseExist): ErrGRPCLeaseExist, @@ -158,15 +160,16 @@ var ( // client-side error var ( - ErrEmptyKey = Error(ErrGRPCEmptyKey) - ErrKeyNotFound = Error(ErrGRPCKeyNotFound) - ErrValueProvided = Error(ErrGRPCValueProvided) - ErrLeaseProvided = Error(ErrGRPCLeaseProvided) - ErrTooManyOps = Error(ErrGRPCTooManyOps) - ErrDuplicateKey = Error(ErrGRPCDuplicateKey) - ErrCompacted = Error(ErrGRPCCompacted) - ErrFutureRev = Error(ErrGRPCFutureRev) - ErrNoSpace = Error(ErrGRPCNoSpace) + ErrEmptyKey = Error(ErrGRPCEmptyKey) + ErrKeyNotFound = Error(ErrGRPCKeyNotFound) + ErrValueProvided = Error(ErrGRPCValueProvided) + ErrLeaseProvided = Error(ErrGRPCLeaseProvided) + ErrTooManyOps = Error(ErrGRPCTooManyOps) + ErrDuplicateKey = Error(ErrGRPCDuplicateKey) + ErrInvalidSortOption = Error(ErrGRPCInvalidSortOption) + ErrCompacted = Error(ErrGRPCCompacted) + ErrFutureRev = Error(ErrGRPCFutureRev) + ErrNoSpace = Error(ErrGRPCNoSpace) ErrLeaseNotFound = Error(ErrGRPCLeaseNotFound) ErrLeaseExist = Error(ErrGRPCLeaseExist) diff --git a/client/v3/kv.go b/client/v3/kv.go index 5e9fb7d45896..80cd80af1de8 100644 --- a/client/v3/kv.go +++ b/client/v3/kv.go @@ -16,6 +16,7 @@ package clientv3 import ( "context" + "go.etcd.io/etcd/api/v3/v3rpc/rpctypes" pb "go.etcd.io/etcd/api/v3/etcdserverpb" @@ -145,10 +146,14 @@ func (kv *kv) Do(ctx context.Context, op Op) (OpResponse, error) { var err error switch op.t { case tRange: - var resp *pb.RangeResponse - resp, err = kv.remote.Range(ctx, op.toRangeRequest(), kv.callOpts...) - if err == nil { - return OpResponse{get: (*GetResponse)(resp)}, nil + if op.IsSortOptionValid() { + var resp *pb.RangeResponse + resp, err = kv.remote.Range(ctx, op.toRangeRequest(), kv.callOpts...) + if err == nil { + return OpResponse{get: (*GetResponse)(resp)}, nil + } + } else { + err = rpctypes.ErrInvalidSortOption } case tPut: var resp *pb.PutResponse diff --git a/client/v3/namespace/kv.go b/client/v3/namespace/kv.go index f745225cacd4..9a428fa58506 100644 --- a/client/v3/namespace/kv.go +++ b/client/v3/namespace/kv.go @@ -51,7 +51,11 @@ func (kv *kvPrefix) Get(ctx context.Context, key string, opts ...clientv3.OpOpti if len(key) == 0 && !(clientv3.IsOptsWithFromKey(opts) || clientv3.IsOptsWithPrefix(opts)) { return nil, rpctypes.ErrEmptyKey } - r, err := kv.KV.Do(ctx, kv.prefixOp(clientv3.OpGet(key, opts...))) + getOp := clientv3.OpGet(key, opts...) + if !getOp.IsSortOptionValid() { + return nil, rpctypes.ErrInvalidSortOption + } + r, err := kv.KV.Do(ctx, kv.prefixOp(getOp)) if err != nil { return nil, err } diff --git a/client/v3/op.go b/client/v3/op.go index e8c0c1e08c96..6492fbdff7f7 100644 --- a/client/v3/op.go +++ b/client/v3/op.go @@ -581,3 +581,19 @@ func IsOptsWithFromKey(opts []OpOption) bool { return ret.isOptsWithFromKey } + +func (op Op) IsSortOptionValid() bool { + if op.sort != nil { + sortOrder := int32(op.sort.Order) + sortTarget := int32(op.sort.Target) + + if _, ok := pb.RangeRequest_SortOrder_name[sortOrder]; !ok { + return false + } + + if _, ok := pb.RangeRequest_SortTarget_name[sortTarget]; !ok { + return false + } + } + return true +} diff --git a/client/v3/op_test.go b/client/v3/op_test.go index 762044fc5e21..7cc189c78b5e 100644 --- a/client/v3/op_test.go +++ b/client/v3/op_test.go @@ -36,3 +36,42 @@ func TestOpWithSort(t *testing.T) { t.Fatalf("expected %+v, got %+v", wreq, req) } } + +func TestIsSortOptionValid(t *testing.T) { + rangeReqs := []struct { + sortOrder pb.RangeRequest_SortOrder + sortTarget pb.RangeRequest_SortTarget + expectedValid bool + }{ + { + sortOrder: pb.RangeRequest_ASCEND, + sortTarget: pb.RangeRequest_CREATE, + expectedValid: true, + }, + { + sortOrder: pb.RangeRequest_ASCEND, + sortTarget: 100, + expectedValid: false, + }, + { + sortOrder: 200, + sortTarget: pb.RangeRequest_MOD, + expectedValid: false, + }, + } + + for _, req := range rangeReqs { + getOp := Op{ + sort: &SortOption{ + Order: SortOrder(req.sortOrder), + Target: SortTarget(req.sortTarget), + }, + } + + actualRet := getOp.IsSortOptionValid() + if actualRet != req.expectedValid { + t.Errorf("expected sortOrder (%d) and sortTarget (%d) to be %t, but got %t", + req.sortOrder, req.sortTarget, req.expectedValid, actualRet) + } + } +} diff --git a/server/etcdserver/api/v3rpc/key.go b/server/etcdserver/api/v3rpc/key.go index d1a7ee633455..2c1de2a90de8 100644 --- a/server/etcdserver/api/v3rpc/key.go +++ b/server/etcdserver/api/v3rpc/key.go @@ -115,6 +115,15 @@ func checkRangeRequest(r *pb.RangeRequest) error { if len(r.Key) == 0 { return rpctypes.ErrGRPCEmptyKey } + + if _, ok := pb.RangeRequest_SortOrder_name[int32(r.SortOrder)]; !ok { + return rpctypes.ErrGRPCInvalidSortOption + } + + if _, ok := pb.RangeRequest_SortTarget_name[int32(r.SortTarget)]; !ok { + return rpctypes.ErrGRPCInvalidSortOption + } + return nil } diff --git a/server/etcdserver/api/v3rpc/key_test.go b/server/etcdserver/api/v3rpc/key_test.go new file mode 100644 index 000000000000..87e025fe0516 --- /dev/null +++ b/server/etcdserver/api/v3rpc/key_test.go @@ -0,0 +1,67 @@ +// Copyright 2021 The etcd Authors +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package v3rpc + +import ( + pb "go.etcd.io/etcd/api/v3/etcdserverpb" + "go.etcd.io/etcd/api/v3/v3rpc/rpctypes" + "testing" +) + +func TestCheckRangeRequest(t *testing.T) { + rangeReqs := []struct { + sortOrder pb.RangeRequest_SortOrder + sortTarget pb.RangeRequest_SortTarget + expectedError error + }{ + { + sortOrder: pb.RangeRequest_ASCEND, + sortTarget: pb.RangeRequest_CREATE, + expectedError: nil, + }, + { + sortOrder: pb.RangeRequest_ASCEND, + sortTarget: 100, + expectedError: rpctypes.ErrGRPCInvalidSortOption, + }, + { + sortOrder: 200, + sortTarget: pb.RangeRequest_MOD, + expectedError: rpctypes.ErrGRPCInvalidSortOption, + }, + } + + for _, req := range rangeReqs { + rangeReq := pb.RangeRequest{ + Key: []byte{1, 2, 3}, + SortOrder: req.sortOrder, + SortTarget: req.sortTarget, + } + + actualRet := checkRangeRequest(&rangeReq) + if getError(actualRet) != getError(req.expectedError) { + t.Errorf("expected sortOrder (%d) and sortTarget (%d) to be %q, but got %q", + req.sortOrder, req.sortTarget, getError(req.expectedError), getError(actualRet)) + } + } +} + +func getError(err error) string { + if err == nil { + return "" + } + + return err.Error() +} diff --git a/server/etcdserver/apply.go b/server/etcdserver/apply.go index c8ff51674219..ca7930696c28 100644 --- a/server/etcdserver/apply.go +++ b/server/etcdserver/apply.go @@ -337,6 +337,8 @@ func (a *applierV3backend) Range(ctx context.Context, txn mvcc.TxnRead, r *pb.Ra resp := &pb.RangeResponse{} resp.Header = &pb.ResponseHeader{} + lg := a.s.Logger() + if txn == nil { txn = a.s.kv.Read(mvcc.ConcurrentReadTxMode, trace) defer txn.End() @@ -407,6 +409,8 @@ func (a *applierV3backend) Range(ctx context.Context, txn mvcc.TxnRead, r *pb.Ra sorter = &kvSortByMod{&kvSort{rr.KVs}} case r.SortTarget == pb.RangeRequest_VALUE: sorter = &kvSortByValue{&kvSort{rr.KVs}} + default: + lg.Panic("unexpected sort target", zap.Int32("sort-target", int32(r.SortTarget))) } switch { case sortOrder == pb.RangeRequest_ASCEND: From 381752182aa6fe8b1715b31393a06db9a723cdfa Mon Sep 17 00:00:00 2001 From: yankay Date: Thu, 23 Dec 2021 21:33:20 +0800 Subject: [PATCH 069/258] Fix for code style Signed-off-by: yankay --- CHANGELOG-3.6.md | 4 ++++ Dockerfile-release.amd64 | 2 +- Dockerfile-release.arm64 | 2 +- Dockerfile-release.ppc64le | 3 +-- Dockerfile-release.s390x | 2 +- 5 files changed, 8 insertions(+), 5 deletions(-) diff --git a/CHANGELOG-3.6.md b/CHANGELOG-3.6.md index e97c3e1a63dd..94dcbc06f7ba 100644 --- a/CHANGELOG-3.6.md +++ b/CHANGELOG-3.6.md @@ -50,4 +50,8 @@ See [List of metrics](https://etcd.io/docs/latest/metrics/) for all metrics per - Add [`etcd_disk_defrag_inflight`](https://github.com/etcd-io/etcd/pull/13371). +### Other + +- Use Distroless as base image to make the image less vulnerable and reduce image size. +
diff --git a/Dockerfile-release.amd64 b/Dockerfile-release.amd64 index cb93afe76e66..67400b69686e 100644 --- a/Dockerfile-release.amd64 +++ b/Dockerfile-release.amd64 @@ -1,5 +1,5 @@ FROM --platform=linux/amd64 busybox:1.34.1 as source -FROM --platform=linux/amd64 gcr.io/distroless/base-debian11 +FROM --platform=linux/amd64 gcr.io/distroless/base-debian11 COPY --from=source /bin/sh /bin/sh COPY --from=source /bin/mkdir /bin/mkdir diff --git a/Dockerfile-release.arm64 b/Dockerfile-release.arm64 index 53d3c274151c..b8ce477afd49 100644 --- a/Dockerfile-release.arm64 +++ b/Dockerfile-release.arm64 @@ -1,5 +1,5 @@ FROM --platform=linux/arm64 busybox:1.34.1 as source -FROM --platform=linux/arm64 gcr.io/distroless/base-debian11 +FROM --platform=linux/arm64 gcr.io/distroless/base-debian11 COPY --from=source /bin/sh /bin/sh COPY --from=source /bin/mkdir /bin/mkdir diff --git a/Dockerfile-release.ppc64le b/Dockerfile-release.ppc64le index 81fc64bc67d8..9cfe5d433314 100644 --- a/Dockerfile-release.ppc64le +++ b/Dockerfile-release.ppc64le @@ -1,10 +1,9 @@ FROM --platform=linux/ppc64le busybox:1.34.1 as source -FROM --platform=linux/ppc64le gcr.io/distroless/base-debian11 +FROM --platform=linux/ppc64le gcr.io/distroless/base-debian11 COPY --from=source /bin/sh /bin/sh COPY --from=source /bin/mkdir /bin/mkdir - ADD etcd /usr/local/bin/ ADD etcdctl /usr/local/bin/ ADD etcdutl /usr/local/bin/ diff --git a/Dockerfile-release.s390x b/Dockerfile-release.s390x index 42bc5d5a018f..d901b410c98e 100644 --- a/Dockerfile-release.s390x +++ b/Dockerfile-release.s390x @@ -1,5 +1,5 @@ FROM --platform=linux/s390x busybox:1.34.1 as source -FROM --platform=linux/s390x gcr.io/distroless/base-debian11 +FROM --platform=linux/s390x gcr.io/distroless/base-debian11 COPY --from=source /bin/sh /bin/sh COPY --from=source /bin/mkdir /bin/mkdir From 282e4e6e889e5e9969cf47a052c7f38e427d8f7e Mon Sep 17 00:00:00 2001 From: horizonzy Date: Wed, 19 Jan 2022 22:24:49 +0800 Subject: [PATCH 070/258] make code more readable. --- server/storage/schema/cindex.go | 15 +++++++-------- 1 file changed, 7 insertions(+), 8 deletions(-) diff --git a/server/storage/schema/cindex.go b/server/storage/schema/cindex.go index 52d9ef126cd8..d7b06b9cef78 100644 --- a/server/storage/schema/cindex.go +++ b/server/storage/schema/cindex.go @@ -58,7 +58,7 @@ func ReadConsistentIndex(tx backend.ReadTx) (uint64, uint64) { func UnsafeUpdateConsistentIndex(tx backend.BatchTx, index uint64, term uint64, onlyGrow bool) { if index == 0 { - // Never save 0 as it means that we didn't loaded the real index yet. + // Never save 0 as it means that we didn't load the real index yet. return } @@ -67,14 +67,13 @@ func UnsafeUpdateConsistentIndex(tx backend.BatchTx, index uint64, term uint64, if term < oldTerm { return } - if term == oldTerm && index <= oldi { - return + if index > oldi { + bs1 := make([]byte, 8) + binary.BigEndian.PutUint64(bs1, index) + // put the index into the underlying backend + // tx has been locked in TxnBegin, so there is no need to lock it again + tx.UnsafePut(Meta, MetaConsistentIndexKeyName, bs1) } - bs1 := make([]byte, 8) - binary.BigEndian.PutUint64(bs1, index) - // put the index into the underlying backend - // tx has been locked in TxnBegin, so there is no need to lock it again - tx.UnsafePut(Meta, MetaConsistentIndexKeyName, bs1) if term > 0 && term > oldTerm { bs2 := make([]byte, 8) binary.BigEndian.PutUint64(bs2, term) From fff5c11ee97ce31851cbe371eb34b226c3abf956 Mon Sep 17 00:00:00 2001 From: Sahdev Zala Date: Wed, 19 Jan 2022 13:32:23 -0500 Subject: [PATCH 071/258] Update maintainers Move Brandon Philips to emeritus. Thank you Brandon for your contributions and leadership to the project. --- MAINTAINERS | 1 - README.md | 1 + 2 files changed, 1 insertion(+), 1 deletion(-) diff --git a/MAINTAINERS b/MAINTAINERS index 13f2b5494486..1ecc76a4ea74 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -9,7 +9,6 @@ # Please keep the list sorted. # MAINTAINERS -Brandon Philips (@philips) pkg:* Gyuho Lee (@gyuho) pkg:* Hitoshi Mitake (@mitake) pkg:* Jingyi Hu (@jingyih) pkg:* diff --git a/README.md b/README.md index cdbc2e31034f..e262fa38057b 100644 --- a/README.md +++ b/README.md @@ -188,6 +188,7 @@ These emeritus maintainers dedicated a part of their career to etcd and reviewed * Fanmin Shi * Anthony Romano +* Brandon Philips ### License From 7460379bad5403fcec209400d1aa7a7668287385 Mon Sep 17 00:00:00 2001 From: Matthias Lisin Date: Wed, 19 Jan 2022 19:53:24 +0100 Subject: [PATCH 072/258] contrib/mixin: add missing summary to alerts to avoid alert messages being templated with undefined values lets set summary for alerts that are currently missing one --- contrib/mixin/mixin.libsonnet | 3 +++ 1 file changed, 3 insertions(+) diff --git a/contrib/mixin/mixin.libsonnet b/contrib/mixin/mixin.libsonnet index 7a41cffdcad6..27e266545342 100644 --- a/contrib/mixin/mixin.libsonnet +++ b/contrib/mixin/mixin.libsonnet @@ -192,6 +192,7 @@ }, annotations: { description: 'etcd cluster "{{ $labels.%s }}": 99th percentile fsync durations are {{ $value }}s on etcd instance {{ $labels.instance }}.' % $._config.clusterLabel, + summary: 'etcd cluster 99th percentile fsync durations are too high.', }, }, { @@ -220,6 +221,7 @@ }, annotations: { description: 'etcd cluster "{{ $labels.%s }}": database size exceeds the defined quota on etcd instance {{ $labels.instance }}, please defrag or increase the quota as the writes to etcd will be disabled when it is full.' % $._config.clusterLabel, + summary: 'etcd cluster database is running full.', }, }, { @@ -233,6 +235,7 @@ }, annotations: { description: 'etcd cluster "{{ $labels.%s }}": Observed surge in etcd writes leading to 50%% increase in database size over the past four hours on etcd instance {{ $labels.instance }}, please check as it might be disruptive.' % $._config.clusterLabel, + summary: 'etcd cluster database growing very fast.', }, }, ], From dc90699db2d8821f87bff77de067456970bf6075 Mon Sep 17 00:00:00 2001 From: leixin Date: Thu, 20 Jan 2022 16:17:10 +0800 Subject: [PATCH 073/258] README: fix go version that development required --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index cdbc2e31034f..8fcd46dcff63 100644 --- a/README.md +++ b/README.md @@ -62,7 +62,7 @@ The easiest way to get etcd is to use one of the pre-built release binaries whic For more installation guides, please check out [play.etcd.io](http://play.etcd.io) and [operating etcd](https://etcd.io/docs/latest/op-guide). -For those wanting to try the very latest version, [build the latest version of etcd][dl-build] from the `main` branch. This first needs [*Go*](https://golang.org/) installed ([version 1.16+](/go.mod#L3) is required). All development occurs on `main`, including new features and bug fixes. Bug fixes are first targeted at `main` and subsequently ported to release branches, as described in the [branch management][branch-management] guide. +For those wanting to try the very latest version, [build the latest version of etcd][dl-build] from the `main` branch. This first needs [*Go*](https://golang.org/) installed ([version 1.17+](/go.mod#L3) is required). All development occurs on `main`, including new features and bug fixes. Bug fixes are first targeted at `main` and subsequently ported to release branches, as described in the [branch management][branch-management] guide. [github-release]: https://github.com/etcd-io/etcd/releases [branch-management]: https://etcd.io/docs/latest/branch_management From 5bcbf77980ec7eca73dabf6c7b7947c0dd2dca17 Mon Sep 17 00:00:00 2001 From: Marek Siarkowicz Date: Tue, 18 Jan 2022 11:07:26 +0100 Subject: [PATCH 074/258] tests: Move client to member struct --- tests/framework/integration/cluster.go | 42 ++++++++----------- .../clientv3/connectivity/black_hole_test.go | 5 +-- .../clientv3/connectivity/dial_test.go | 8 ++-- .../connectivity/network_partition_test.go | 12 ++---- .../connectivity/server_shutdown_test.go | 16 +++---- tests/integration/clientv3/metrics_test.go | 2 +- .../clientv3/ordering_util_test.go | 2 +- tests/integration/cluster_test.go | 1 + tests/integration/v3_alarm_test.go | 4 +- tests/integration/v3_election_test.go | 2 +- tests/integration/v3_grpc_test.go | 4 +- tests/integration/v3_lease_test.go | 6 +-- 12 files changed, 44 insertions(+), 60 deletions(-) diff --git a/tests/framework/integration/cluster.go b/tests/framework/integration/cluster.go index 4021ff676a2f..a69de7bf0b33 100644 --- a/tests/framework/integration/cluster.go +++ b/tests/framework/integration/cluster.go @@ -152,9 +152,6 @@ type ClusterConfig struct { GRPCKeepAliveInterval time.Duration GRPCKeepAliveTimeout time.Duration - // SkipCreatingClient to skip creating clients for each member. - SkipCreatingClient bool - ClientMaxCallSendMsgSize int ClientMaxCallRecvMsgSize int @@ -421,6 +418,7 @@ func (c *Cluster) RemoveMember(t testutil.TB, id uint64) error { if uint64(m.Server.ID()) != id { newMembers = append(newMembers, m) } else { + m.Client.Close() select { case <-m.Server.StopNotify(): m.Terminate(t) @@ -438,6 +436,11 @@ func (c *Cluster) RemoveMember(t testutil.TB, id uint64) error { } func (c *Cluster) Terminate(t testutil.TB) { + for _, m := range c.Members { + if m.Client != nil { + m.Client.Close() + } + } var wg sync.WaitGroup wg.Add(len(c.Members)) for _, m := range c.Members { @@ -598,6 +601,8 @@ type Member struct { // ServerClient is a clientv3 that directly calls the etcdserver. ServerClient *clientv3.Client + // Client is a clientv3 that communicates via socket, either UNIX or TCP. + Client *clientv3.Client KeepDataDirTerminate bool ClientMaxCallSendMsgSize int @@ -1086,6 +1091,12 @@ func (m *Member) Launch() error { } m.ServerClosers = append(m.ServerClosers, closer) } + if m.GrpcURL != "" && m.Client == nil { + m.Client, err = NewClientV3(m) + if err != nil { + return err + } + } m.Logger.Info( "launched a member", @@ -1391,7 +1402,6 @@ type ClusterV3 struct { *Cluster mu sync.Mutex - Clients []*clientv3.Client clusterClient *clientv3.Client } @@ -1409,35 +1419,17 @@ func NewClusterV3(t testutil.TB, cfg *ClusterConfig) *ClusterV3 { } clus.Launch(t) - if !cfg.SkipCreatingClient { - for _, m := range clus.Members { - client, err := NewClientV3(m) - if err != nil { - t.Fatalf("cannot create client: %v", err) - } - clus.Clients = append(clus.Clients, client) - } - } - return clus } func (c *ClusterV3) TakeClient(idx int) { c.mu.Lock() - c.Clients[idx] = nil + c.Members[idx].Client = nil c.mu.Unlock() } func (c *ClusterV3) Terminate(t testutil.TB) { c.mu.Lock() - for _, client := range c.Clients { - if client == nil { - continue - } - if err := client.Close(); err != nil { - t.Error(err) - } - } if c.clusterClient != nil { if err := c.clusterClient.Close(); err != nil { t.Error(err) @@ -1448,11 +1440,11 @@ func (c *ClusterV3) Terminate(t testutil.TB) { } func (c *ClusterV3) RandClient() *clientv3.Client { - return c.Clients[rand.Intn(len(c.Clients))] + return c.Members[rand.Intn(len(c.Members))].Client } func (c *ClusterV3) Client(i int) *clientv3.Client { - return c.Clients[i] + return c.Members[i].Client } func (c *ClusterV3) ClusterClient() (client *clientv3.Client, err error) { diff --git a/tests/integration/clientv3/connectivity/black_hole_test.go b/tests/integration/clientv3/connectivity/black_hole_test.go index 1c501c08aadb..6519f76ab1c0 100644 --- a/tests/integration/clientv3/connectivity/black_hole_test.go +++ b/tests/integration/clientv3/connectivity/black_hole_test.go @@ -169,9 +169,8 @@ func testBalancerUnderBlackholeNoKeepAlive(t *testing.T, op func(*clientv3.Clien integration2.BeforeTest(t) clus := integration2.NewClusterV3(t, &integration2.ClusterConfig{ - Size: 2, - SkipCreatingClient: true, - UseBridge: true, + Size: 2, + UseBridge: true, }) defer clus.Terminate(t) diff --git a/tests/integration/clientv3/connectivity/dial_test.go b/tests/integration/clientv3/connectivity/dial_test.go index 719de550a0d9..2742ad32517f 100644 --- a/tests/integration/clientv3/connectivity/dial_test.go +++ b/tests/integration/clientv3/connectivity/dial_test.go @@ -48,7 +48,7 @@ var ( // TestDialTLSExpired tests client with expired certs fails to dial. func TestDialTLSExpired(t *testing.T) { integration2.BeforeTest(t) - clus := integration2.NewClusterV3(t, &integration2.ClusterConfig{Size: 1, PeerTLS: &testTLSInfo, ClientTLS: &testTLSInfo, SkipCreatingClient: true}) + clus := integration2.NewClusterV3(t, &integration2.ClusterConfig{Size: 1, PeerTLS: &testTLSInfo, ClientTLS: &testTLSInfo}) defer clus.Terminate(t) tls, err := testTLSInfoExpired.ClientConfig() @@ -71,7 +71,7 @@ func TestDialTLSExpired(t *testing.T) { // when TLS endpoints (https, unixs) are given but no tls config. func TestDialTLSNoConfig(t *testing.T) { integration2.BeforeTest(t) - clus := integration2.NewClusterV3(t, &integration2.ClusterConfig{Size: 1, ClientTLS: &testTLSInfo, SkipCreatingClient: true}) + clus := integration2.NewClusterV3(t, &integration2.ClusterConfig{Size: 1, ClientTLS: &testTLSInfo}) defer clus.Terminate(t) // expect "signed by unknown authority" c, err := integration2.NewClient(t, clientv3.Config{ @@ -102,7 +102,7 @@ func TestDialSetEndpointsAfterFail(t *testing.T) { // testDialSetEndpoints ensures SetEndpoints can replace unavailable endpoints with available ones. func testDialSetEndpoints(t *testing.T, setBefore bool) { integration2.BeforeTest(t) - clus := integration2.NewClusterV3(t, &integration2.ClusterConfig{Size: 3, SkipCreatingClient: true}) + clus := integration2.NewClusterV3(t, &integration2.ClusterConfig{Size: 3}) defer clus.Terminate(t) // get endpoint list @@ -166,7 +166,7 @@ func TestSwitchSetEndpoints(t *testing.T) { func TestRejectOldCluster(t *testing.T) { integration2.BeforeTest(t) // 2 endpoints to test multi-endpoint Status - clus := integration2.NewClusterV3(t, &integration2.ClusterConfig{Size: 2, SkipCreatingClient: true}) + clus := integration2.NewClusterV3(t, &integration2.ClusterConfig{Size: 2}) defer clus.Terminate(t) cfg := clientv3.Config{ diff --git a/tests/integration/clientv3/connectivity/network_partition_test.go b/tests/integration/clientv3/connectivity/network_partition_test.go index 32abb6e12b0b..9e3600e03b8a 100644 --- a/tests/integration/clientv3/connectivity/network_partition_test.go +++ b/tests/integration/clientv3/connectivity/network_partition_test.go @@ -106,8 +106,7 @@ func testBalancerUnderNetworkPartition(t *testing.T, op func(*clientv3.Client, c integration2.BeforeTest(t) clus := integration2.NewClusterV3(t, &integration2.ClusterConfig{ - Size: 3, - SkipCreatingClient: true, + Size: 3, }) defer clus.Terminate(t) @@ -162,8 +161,7 @@ func TestBalancerUnderNetworkPartitionLinearizableGetLeaderElection(t *testing.T integration2.BeforeTest(t) clus := integration2.NewClusterV3(t, &integration2.ClusterConfig{ - Size: 3, - SkipCreatingClient: true, + Size: 3, }) defer clus.Terminate(t) eps := []string{clus.Members[0].GRPCURL(), clus.Members[1].GRPCURL(), clus.Members[2].GRPCURL()} @@ -217,8 +215,7 @@ func testBalancerUnderNetworkPartitionWatch(t *testing.T, isolateLeader bool) { integration2.BeforeTest(t) clus := integration2.NewClusterV3(t, &integration2.ClusterConfig{ - Size: 3, - SkipCreatingClient: true, + Size: 3, }) defer clus.Terminate(t) @@ -277,8 +274,7 @@ func TestDropReadUnderNetworkPartition(t *testing.T) { integration2.BeforeTest(t) clus := integration2.NewClusterV3(t, &integration2.ClusterConfig{ - Size: 3, - SkipCreatingClient: true, + Size: 3, }) defer clus.Terminate(t) leaderIndex := clus.WaitLeader(t) diff --git a/tests/integration/clientv3/connectivity/server_shutdown_test.go b/tests/integration/clientv3/connectivity/server_shutdown_test.go index 2d14a39990e3..f175782a8695 100644 --- a/tests/integration/clientv3/connectivity/server_shutdown_test.go +++ b/tests/integration/clientv3/connectivity/server_shutdown_test.go @@ -33,9 +33,8 @@ func TestBalancerUnderServerShutdownWatch(t *testing.T) { integration2.BeforeTest(t) clus := integration2.NewClusterV3(t, &integration2.ClusterConfig{ - Size: 3, - SkipCreatingClient: true, - UseBridge: true, + Size: 3, + UseBridge: true, }) defer clus.Terminate(t) @@ -146,8 +145,7 @@ func testBalancerUnderServerShutdownMutable(t *testing.T, op func(*clientv3.Clie integration2.BeforeTest(t) clus := integration2.NewClusterV3(t, &integration2.ClusterConfig{ - Size: 3, - SkipCreatingClient: true, + Size: 3, }) defer clus.Terminate(t) @@ -204,8 +202,7 @@ func testBalancerUnderServerShutdownImmutable(t *testing.T, op func(*clientv3.Cl integration2.BeforeTest(t) clus := integration2.NewClusterV3(t, &integration2.ClusterConfig{ - Size: 3, - SkipCreatingClient: true, + Size: 3, }) defer clus.Terminate(t) @@ -277,9 +274,8 @@ func testBalancerUnderServerStopInflightRangeOnRestart(t *testing.T, linearizabl integration2.BeforeTest(t) cfg := &integration2.ClusterConfig{ - Size: 2, - SkipCreatingClient: true, - UseBridge: true, + Size: 2, + UseBridge: true, } if linearizable { cfg.Size = 3 diff --git a/tests/integration/clientv3/metrics_test.go b/tests/integration/clientv3/metrics_test.go index 07c36a81c8fa..0c3db3dcadcf 100644 --- a/tests/integration/clientv3/metrics_test.go +++ b/tests/integration/clientv3/metrics_test.go @@ -70,7 +70,7 @@ func TestV3ClientMetrics(t *testing.T) { url := "unix://" + addr + "/metrics" - clus := integration2.NewClusterV3(t, &integration2.ClusterConfig{Size: 1, SkipCreatingClient: true}) + clus := integration2.NewClusterV3(t, &integration2.ClusterConfig{Size: 1}) defer clus.Terminate(t) cfg := clientv3.Config{ diff --git a/tests/integration/clientv3/ordering_util_test.go b/tests/integration/clientv3/ordering_util_test.go index 4c992c70248e..2fb0c1413f3a 100644 --- a/tests/integration/clientv3/ordering_util_test.go +++ b/tests/integration/clientv3/ordering_util_test.go @@ -82,7 +82,7 @@ func TestEndpointSwitchResolvesViolation(t *testing.T) { func TestUnresolvableOrderViolation(t *testing.T) { integration2.BeforeTest(t) - clus := integration2.NewClusterV3(t, &integration2.ClusterConfig{Size: 5, SkipCreatingClient: true, UseBridge: true}) + clus := integration2.NewClusterV3(t, &integration2.ClusterConfig{Size: 5, UseBridge: true}) defer clus.Terminate(t) cfg := clientv3.Config{ Endpoints: []string{ diff --git a/tests/integration/cluster_test.go b/tests/integration/cluster_test.go index 443d97d425cd..ebdcf932369c 100644 --- a/tests/integration/cluster_test.go +++ b/tests/integration/cluster_test.go @@ -309,6 +309,7 @@ func TestIssue2904(t *testing.T) { <-c.Members[1].Server.StopNotify() // terminate removed member + c.Members[1].Client.Close() c.Members[1].Terminate(t) c.Members = c.Members[:1] // wait member to be removed. diff --git a/tests/integration/v3_alarm_test.go b/tests/integration/v3_alarm_test.go index 2fce27bf80ae..08c0b40821ee 100644 --- a/tests/integration/v3_alarm_test.go +++ b/tests/integration/v3_alarm_test.go @@ -36,9 +36,8 @@ func TestV3StorageQuotaApply(t *testing.T) { integration.BeforeTest(t) quotasize := int64(16 * os.Getpagesize()) - clus := integration.NewClusterV3(t, &integration.ClusterConfig{Size: 2, UseBridge: true}) + clus := integration.NewClusterV3(t, &integration.ClusterConfig{Size: 2}) defer clus.Terminate(t) - kvc0 := integration.ToGRPC(clus.Client(0)).KV kvc1 := integration.ToGRPC(clus.Client(1)).KV // Set a quota on one node @@ -46,6 +45,7 @@ func TestV3StorageQuotaApply(t *testing.T) { clus.Members[0].Stop(t) clus.Members[0].Restart(t) clus.WaitMembersForLeader(t, clus.Members) + kvc0 := integration.ToGRPC(clus.Client(0)).KV waitForRestart(t, kvc0) key := []byte("abc") diff --git a/tests/integration/v3_election_test.go b/tests/integration/v3_election_test.go index b726f26b3c9d..761afd1f4615 100644 --- a/tests/integration/v3_election_test.go +++ b/tests/integration/v3_election_test.go @@ -120,7 +120,7 @@ func TestElectionFailover(t *testing.T) { for i := 0; i < 3; i++ { var err error - ss[i], err = concurrency.NewSession(clus.Clients[i]) + ss[i], err = concurrency.NewSession(clus.Client(i)) if err != nil { t.Error(err) } diff --git a/tests/integration/v3_grpc_test.go b/tests/integration/v3_grpc_test.go index 2b34cbb471d1..ebb1482596ef 100644 --- a/tests/integration/v3_grpc_test.go +++ b/tests/integration/v3_grpc_test.go @@ -100,14 +100,14 @@ func TestV3PutRestart(t *testing.T) { stopIdx = rand.Intn(3) } - clus.Clients[stopIdx].Close() + clus.Client(stopIdx).Close() clus.Members[stopIdx].Stop(t) clus.Members[stopIdx].Restart(t) c, cerr := integration.NewClientV3(clus.Members[stopIdx]) if cerr != nil { t.Fatalf("cannot create client: %v", cerr) } - clus.Clients[stopIdx] = c + clus.Members[stopIdx].ServerClient = c ctx, cancel := context.WithTimeout(context.TODO(), 10*time.Second) defer cancel() diff --git a/tests/integration/v3_lease_test.go b/tests/integration/v3_lease_test.go index 240e6bcbaf8f..5151264a6c1e 100644 --- a/tests/integration/v3_lease_test.go +++ b/tests/integration/v3_lease_test.go @@ -522,12 +522,12 @@ func TestV3GetNonExistLease(t *testing.T) { Keys: true, } - for _, client := range clus.Clients { + for _, m := range clus.Members { // quorum-read to ensure revoke completes before TimeToLive - if _, err := integration.ToGRPC(client).KV.Range(ctx, &pb.RangeRequest{Key: []byte("_")}); err != nil { + if _, err := integration.ToGRPC(m.Client).KV.Range(ctx, &pb.RangeRequest{Key: []byte("_")}); err != nil { t.Fatal(err) } - resp, err := integration.ToGRPC(client).Lease.LeaseTimeToLive(ctx, leaseTTLr) + resp, err := integration.ToGRPC(m.Client).Lease.LeaseTimeToLive(ctx, leaseTTLr) if err != nil { t.Fatalf("expected non nil error, but go %v", err) } From 98242da5f1cbd40c58cc243e29d7646e74658ccc Mon Sep 17 00:00:00 2001 From: Marek Siarkowicz Date: Tue, 18 Jan 2022 12:12:45 +0100 Subject: [PATCH 075/258] test: Handle adding new members for clusters with TCP enabled --- tests/framework/integration/cluster.go | 33 ++++++++++++-------------- 1 file changed, 15 insertions(+), 18 deletions(-) diff --git a/tests/framework/integration/cluster.go b/tests/framework/integration/cluster.go index a69de7bf0b33..140109d27467 100644 --- a/tests/framework/integration/cluster.go +++ b/tests/framework/integration/cluster.go @@ -83,7 +83,7 @@ var ( // LocalListenCount integration test uses unique ports, counting up, to listen for each // member, ensuring restarted members can listen on the same port again. - LocalListenCount = int64(0) + LocalListenCount = int32(0) TestTLSInfo = transport.TLSInfo{ KeyFile: MustAbsPath("../fixtures/server.key.insecure"), @@ -177,11 +177,6 @@ type Cluster struct { LastMemberNum int } -func (c *Cluster) generateMemberName() string { - c.LastMemberNum++ - return fmt.Sprintf("m%v", c.LastMemberNum-1) -} - func SchemeFromTLSInfo(tls *transport.TLSInfo) string { if tls == nil { return URLScheme @@ -219,7 +214,7 @@ func NewClusterFromConfig(t testutil.TB, cfg *ClusterConfig) *Cluster { c := &Cluster{Cfg: cfg} ms := make([]*Member, cfg.Size) for i := 0; i < cfg.Size; i++ { - ms[i] = c.mustNewMember(t, int64(i)) + ms[i] = c.mustNewMember(t) } c.Members = ms if err := c.fillClusterForMembers(); err != nil { @@ -306,10 +301,12 @@ func (c *Cluster) HTTPMembers() []client.Member { return ms } -func (c *Cluster) mustNewMember(t testutil.TB, memberNumber int64) *Member { +func (c *Cluster) mustNewMember(t testutil.TB) *Member { + memberNumber := c.LastMemberNum + c.LastMemberNum++ m := MustNewMember(t, MemberConfig{ - Name: c.generateMemberName(), + Name: fmt.Sprintf("m%v", memberNumber-1), MemberNumber: memberNumber, AuthToken: c.Cfg.AuthToken, PeerTLS: c.Cfg.PeerTLS, @@ -344,7 +341,7 @@ func (c *Cluster) mustNewMember(t testutil.TB, memberNumber int64) *Member { // addMember return PeerURLs of the added member. func (c *Cluster) addMember(t testutil.TB) types.URLs { - m := c.mustNewMember(t, 0) + m := c.mustNewMember(t) scheme := SchemeFromTLSInfo(c.Cfg.PeerTLS) @@ -563,7 +560,7 @@ func isMembersEqual(membs []client.Member, wmembs []client.Member) bool { } func newLocalListener(t testutil.TB) net.Listener { - c := atomic.AddInt64(&LocalListenCount, 1) + c := atomic.AddInt32(&LocalListenCount, 1) // Go 1.8+ allows only numbers in port addr := fmt.Sprintf("127.0.0.1:%05d%05d", c+BasePort, os.Getpid()) return NewListenerWithAddr(t, addr) @@ -579,8 +576,8 @@ func NewListenerWithAddr(t testutil.TB, addr string) net.Listener { type Member struct { config.ServerConfig - UniqNumber int64 - MemberNumber int64 + UniqNumber int + MemberNumber int PeerListeners, ClientListeners []net.Listener GrpcListener net.Listener // PeerTLSInfo enables peer TLS when set @@ -622,7 +619,7 @@ func (m *Member) GRPCURL() string { return m.GrpcURL } type MemberConfig struct { Name string UniqNumber int64 - MemberNumber int64 + MemberNumber int PeerTLS *transport.TLSInfo ClientTLS *transport.TLSInfo AuthToken string @@ -652,7 +649,7 @@ func MustNewMember(t testutil.TB, mcfg MemberConfig) *Member { var err error m := &Member{ MemberNumber: mcfg.MemberNumber, - UniqNumber: atomic.AddInt64(&LocalListenCount, 1), + UniqNumber: int(atomic.AddInt32(&LocalListenCount, 1)), } peerScheme := SchemeFromTLSInfo(mcfg.PeerTLS) @@ -852,7 +849,7 @@ func (m *Member) grpcAddr() (network, host, port string) { return network, host, port } -func GrpcPortNumber(uniqNumber, memberNumber int64) int64 { +func GrpcPortNumber(uniqNumber, memberNumber int) int { return BaseGRPCPort + uniqNumber*10 + memberNumber } @@ -1545,7 +1542,7 @@ func (c *ClusterV3) GetLearnerMembers() ([]*pb.Member, error) { // AddAndLaunchLearnerMember creates a leaner member, adds it to Cluster // via v3 MemberAdd API, and then launches the new member. func (c *ClusterV3) AddAndLaunchLearnerMember(t testutil.TB) { - m := c.mustNewMember(t, 0) + m := c.mustNewMember(t) m.IsLearner = true scheme := SchemeFromTLSInfo(c.Cfg.PeerTLS) @@ -1646,7 +1643,7 @@ func (p SortableProtoMemberSliceByPeerURLs) Swap(i, j int) { p[i], p[j] = p[j], // MustNewMember creates a new member instance based on the response of V3 Member Add API. func (c *ClusterV3) MustNewMember(t testutil.TB, resp *clientv3.MemberAddResponse) *Member { - m := c.mustNewMember(t, 0) + m := c.mustNewMember(t) m.IsLearner = resp.Member.IsLearner m.NewCluster = false From 69fc517e56b834613e0091a514c434d395e3d0c9 Mon Sep 17 00:00:00 2001 From: Marek Siarkowicz Date: Tue, 18 Jan 2022 12:53:28 +0100 Subject: [PATCH 076/258] test: Add StrictReconfigCheck to cluster --- tests/framework/integration/cluster.go | 4 ++++ tests/integration/cluster_test.go | 16 ++++------------ 2 files changed, 8 insertions(+), 12 deletions(-) diff --git a/tests/framework/integration/cluster.go b/tests/framework/integration/cluster.go index 140109d27467..aab849b5b3cc 100644 --- a/tests/framework/integration/cluster.go +++ b/tests/framework/integration/cluster.go @@ -169,6 +169,7 @@ type ClusterConfig struct { WatchProgressNotifyInterval time.Duration ExperimentalMaxLearners int + StrictReconfigCheck bool } type Cluster struct { @@ -329,6 +330,7 @@ func (c *Cluster) mustNewMember(t testutil.TB) *Member { LeaseCheckpointPersist: c.Cfg.LeaseCheckpointPersist, WatchProgressNotifyInterval: c.Cfg.WatchProgressNotifyInterval, ExperimentalMaxLearners: c.Cfg.ExperimentalMaxLearners, + StrictReconfigCheck: c.Cfg.StrictReconfigCheck, }) m.DiscoveryURL = c.Cfg.DiscoveryURL if c.Cfg.UseGRPC { @@ -641,6 +643,7 @@ type MemberConfig struct { LeaseCheckpointPersist bool WatchProgressNotifyInterval time.Duration ExperimentalMaxLearners int + StrictReconfigCheck bool } // MustNewMember return an inited member with the given name. If peerTLS is @@ -752,6 +755,7 @@ func MustNewMember(t testutil.TB, mcfg MemberConfig) *Member { m.V2Deprecation = config.V2_DEPR_DEFAULT m.GrpcServerRecorder = &grpc_testing.GrpcRecorder{} m.Logger = memberLogger(t, mcfg.Name) + m.StrictReconfigCheck = mcfg.StrictReconfigCheck t.Cleanup(func() { // if we didn't cleanup the logger, the consecutive test // might reuse this (t). diff --git a/tests/integration/cluster_test.go b/tests/integration/cluster_test.go index ebdcf932369c..f4aafdf0c5ba 100644 --- a/tests/integration/cluster_test.go +++ b/tests/integration/cluster_test.go @@ -373,10 +373,7 @@ func TestIssue3699(t *testing.T) { // TestRejectUnhealthyAdd ensures an unhealthy cluster rejects adding members. func TestRejectUnhealthyAdd(t *testing.T) { integration.BeforeTest(t) - c := integration.NewClusterFromConfig(t, &integration.ClusterConfig{Size: 3, UseBridge: true}) - for _, m := range c.Members { - m.ServerConfig.StrictReconfigCheck = true - } + c := integration.NewClusterFromConfig(t, &integration.ClusterConfig{Size: 3, UseBridge: true, StrictReconfigCheck: true}) c.Launch(t) defer c.Terminate(t) @@ -417,10 +414,7 @@ func TestRejectUnhealthyAdd(t *testing.T) { // if quorum will be lost. func TestRejectUnhealthyRemove(t *testing.T) { integration.BeforeTest(t) - c := integration.NewClusterFromConfig(t, &integration.ClusterConfig{Size: 5, UseBridge: true}) - for _, m := range c.Members { - m.ServerConfig.StrictReconfigCheck = true - } + c := integration.NewClusterFromConfig(t, &integration.ClusterConfig{Size: 5, UseBridge: true, StrictReconfigCheck: true}) c.Launch(t) defer c.Terminate(t) @@ -466,14 +460,12 @@ func TestRestartRemoved(t *testing.T) { integration.BeforeTest(t) // 1. start single-member Cluster - c := integration.NewClusterFromConfig(t, &integration.ClusterConfig{Size: 1, UseBridge: true}) - for _, m := range c.Members { - m.ServerConfig.StrictReconfigCheck = true - } + c := integration.NewClusterFromConfig(t, &integration.ClusterConfig{Size: 1, UseBridge: true, StrictReconfigCheck: true}) c.Launch(t) defer c.Terminate(t) // 2. add a new member + c.Cfg.StrictReconfigCheck = false c.AddMember(t) c.WaitLeader(t) From 87c8e8b868829de57652909a5ca09615c8390228 Mon Sep 17 00:00:00 2001 From: Marek Siarkowicz Date: Tue, 18 Jan 2022 13:59:26 +0100 Subject: [PATCH 077/258] test: Migrate to ClusterV3 cluster in integration tests --- server/etcdserver/api/membership/storev2.go | 3 +- tests/framework/integration/cluster.go | 16 +-- tests/integration/client/client_test.go | 3 +- tests/integration/cluster_test.go | 120 ++++++++------------ tests/integration/member_test.go | 9 +- tests/integration/v3_grpc_test.go | 18 +-- 6 files changed, 63 insertions(+), 106 deletions(-) diff --git a/server/etcdserver/api/membership/storev2.go b/server/etcdserver/api/membership/storev2.go index 9ed94dee9f0a..d428cb66e22c 100644 --- a/server/etcdserver/api/membership/storev2.go +++ b/server/etcdserver/api/membership/storev2.go @@ -17,9 +17,10 @@ package membership import ( "encoding/json" "fmt" - "go.etcd.io/etcd/client/pkg/v3/types" "path" + "go.etcd.io/etcd/client/pkg/v3/types" + "go.etcd.io/etcd/server/v3/etcdserver/api/v2store" "github.com/coreos/go-semver/semver" diff --git a/tests/framework/integration/cluster.go b/tests/framework/integration/cluster.go index aab849b5b3cc..33db80370d7e 100644 --- a/tests/framework/integration/cluster.go +++ b/tests/framework/integration/cluster.go @@ -209,7 +209,7 @@ func (c *Cluster) fillClusterForMembers() error { return nil } -func NewClusterFromConfig(t testutil.TB, cfg *ClusterConfig) *Cluster { +func newClusterFromConfig(t testutil.TB, cfg *ClusterConfig) *Cluster { testutil.SkipTestIfShortMode(t, "Cannot start etcd Cluster in --short tests") c := &Cluster{Cfg: cfg} @@ -225,18 +225,6 @@ func NewClusterFromConfig(t testutil.TB, cfg *ClusterConfig) *Cluster { return c } -// NewCluster returns an unlaunched Cluster of the given size which has been -// set to use static bootstrap. -func NewCluster(t testutil.TB, size int) *Cluster { - t.Helper() - return NewClusterFromConfig(t, &ClusterConfig{Size: size}) -} - -// NewClusterByConfig returns an unlaunched Cluster defined by a Cluster configuration -func NewClusterByConfig(t testutil.TB, cfg *ClusterConfig) *Cluster { - return NewClusterFromConfig(t, cfg) -} - func (c *Cluster) Launch(t testutil.TB) { errc := make(chan error) for _, m := range c.Members { @@ -1416,7 +1404,7 @@ func NewClusterV3(t testutil.TB, cfg *ClusterConfig) *ClusterV3 { cfg.UseGRPC = true clus := &ClusterV3{ - Cluster: NewClusterByConfig(t, cfg), + Cluster: newClusterFromConfig(t, cfg), } clus.Launch(t) diff --git a/tests/integration/client/client_test.go b/tests/integration/client/client_test.go index aa0271e95b10..132118b9a630 100644 --- a/tests/integration/client/client_test.go +++ b/tests/integration/client/client_test.go @@ -89,8 +89,7 @@ func TestV2NoRetryNoLeader(t *testing.T) { // TestV2RetryRefuse tests destructive api calls will retry if a connection is refused. func TestV2RetryRefuse(t *testing.T) { integration2.BeforeTest(t) - cl := integration2.NewCluster(t, 1) - cl.Launch(t) + cl := integration2.NewClusterV3(t, &integration2.ClusterConfig{Size: 1}) defer cl.Terminate(t) // test connection refused; expect no error failover cli := integration2.MustNewHTTPClient(t, []string{integration2.URLScheme + "://refuseconn:123", cl.URL(0)}, nil) diff --git a/tests/integration/cluster_test.go b/tests/integration/cluster_test.go index f4aafdf0c5ba..2b3fd3179a83 100644 --- a/tests/integration/cluster_test.go +++ b/tests/integration/cluster_test.go @@ -26,6 +26,7 @@ import ( "time" "go.etcd.io/etcd/client/v2" + clientv3 "go.etcd.io/etcd/client/v3" "go.etcd.io/etcd/server/v3/etcdserver" "go.etcd.io/etcd/tests/v3/framework/integration" ) @@ -45,16 +46,14 @@ func TestClusterOf3(t *testing.T) { testCluster(t, 3) } func testCluster(t *testing.T, size int) { integration.BeforeTest(t) - c := integration.NewCluster(t, size) - c.Launch(t) + c := integration.NewClusterV3(t, &integration.ClusterConfig{Size: size}) defer c.Terminate(t) clusterMustProgress(t, c.Members) } func TestTLSClusterOf3(t *testing.T) { integration.BeforeTest(t) - c := integration.NewClusterByConfig(t, &integration.ClusterConfig{Size: 3, PeerTLS: &integration.TestTLSInfo}) - c.Launch(t) + c := integration.NewClusterV3(t, &integration.ClusterConfig{Size: 3, PeerTLS: &integration.TestTLSInfo}) defer c.Terminate(t) clusterMustProgress(t, c.Members) } @@ -63,8 +62,7 @@ func TestTLSClusterOf3(t *testing.T) { // authorities that don't issue dual-usage certificates. func TestTLSClusterOf3WithSpecificUsage(t *testing.T) { integration.BeforeTest(t) - c := integration.NewClusterByConfig(t, &integration.ClusterConfig{Size: 3, PeerTLS: &integration.TestTLSInfoWithSpecificUsage}) - c.Launch(t) + c := integration.NewClusterV3(t, &integration.ClusterConfig{Size: 3, PeerTLS: &integration.TestTLSInfoWithSpecificUsage}) defer c.Terminate(t) clusterMustProgress(t, c.Members) } @@ -74,8 +72,7 @@ func TestClusterOf3UsingDiscovery(t *testing.T) { testClusterUsingDiscovery(t, 3 func testClusterUsingDiscovery(t *testing.T, size int) { integration.BeforeTest(t) - dc := integration.NewCluster(t, 1) - dc.Launch(t) + dc := integration.NewClusterV3(t, &integration.ClusterConfig{Size: 1, UseIP: true}) defer dc.Terminate(t) // init discovery token space dcc := integration.MustNewHTTPClient(t, dc.URLs(), nil) @@ -86,19 +83,14 @@ func testClusterUsingDiscovery(t *testing.T, size int) { } cancel() - c := integration.NewClusterByConfig( - t, - &integration.ClusterConfig{Size: size, DiscoveryURL: dc.URL(0) + "/v2/keys"}, - ) - c.Launch(t) + c := integration.NewClusterV3(t, &integration.ClusterConfig{Size: size, DiscoveryURL: dc.URL(0) + "/v2/keys"}) defer c.Terminate(t) clusterMustProgress(t, c.Members) } func TestTLSClusterOf3UsingDiscovery(t *testing.T) { integration.BeforeTest(t) - dc := integration.NewCluster(t, 1) - dc.Launch(t) + dc := integration.NewClusterV3(t, &integration.ClusterConfig{Size: 1, UseIP: true}) defer dc.Terminate(t) // init discovery token space dcc := integration.MustNewHTTPClient(t, dc.URLs(), nil) @@ -109,13 +101,11 @@ func TestTLSClusterOf3UsingDiscovery(t *testing.T) { } cancel() - c := integration.NewClusterByConfig(t, - &integration.ClusterConfig{ - Size: 3, - PeerTLS: &integration.TestTLSInfo, - DiscoveryURL: dc.URL(0) + "/v2/keys"}, + c := integration.NewClusterV3(t, &integration.ClusterConfig{ + Size: 3, + PeerTLS: &integration.TestTLSInfo, + DiscoveryURL: dc.URL(0) + "/v2/keys"}, ) - c.Launch(t) defer c.Terminate(t) clusterMustProgress(t, c.Members) } @@ -125,8 +115,7 @@ func TestDoubleClusterSizeOf3(t *testing.T) { testDoubleClusterSize(t, 3) } func testDoubleClusterSize(t *testing.T, size int) { integration.BeforeTest(t) - c := integration.NewCluster(t, size) - c.Launch(t) + c := integration.NewClusterV3(t, &integration.ClusterConfig{Size: size}) defer c.Terminate(t) for i := 0; i < size; i++ { @@ -137,8 +126,7 @@ func testDoubleClusterSize(t *testing.T, size int) { func TestDoubleTLSClusterSizeOf3(t *testing.T) { integration.BeforeTest(t) - c := integration.NewClusterByConfig(t, &integration.ClusterConfig{Size: 3, PeerTLS: &integration.TestTLSInfo}) - c.Launch(t) + c := integration.NewClusterV3(t, &integration.ClusterConfig{Size: 1, PeerTLS: &integration.TestTLSInfo}) defer c.Terminate(t) for i := 0; i < 3; i++ { @@ -152,8 +140,7 @@ func TestDecreaseClusterSizeOf5(t *testing.T) { testDecreaseClusterSize(t, 5) } func testDecreaseClusterSize(t *testing.T, size int) { integration.BeforeTest(t) - c := integration.NewCluster(t, size) - c.Launch(t) + c := integration.NewClusterV3(t, &integration.ClusterConfig{Size: size}) defer c.Terminate(t) // TODO: remove the last but one member @@ -174,8 +161,8 @@ func testDecreaseClusterSize(t *testing.T, size int) { } func TestForceNewCluster(t *testing.T) { - c := integration.NewClusterFromConfig(t, &integration.ClusterConfig{Size: 3, UseBridge: true}) - c.Launch(t) + integration.BeforeTest(t) + c := integration.NewClusterV3(t, &integration.ClusterConfig{Size: 3, UseBridge: true, UseGRPC: true}) cc := integration.MustNewHTTPClient(t, []string{c.Members[0].URL()}, nil) kapi := client.NewKeysAPI(cc) ctx, cancel := context.WithTimeout(context.Background(), integration.RequestTimeout) @@ -216,8 +203,7 @@ func TestForceNewCluster(t *testing.T) { func TestAddMemberAfterClusterFullRotation(t *testing.T) { integration.BeforeTest(t) - c := integration.NewCluster(t, 3) - c.Launch(t) + c := integration.NewClusterV3(t, &integration.ClusterConfig{Size: 3}) defer c.Terminate(t) // remove all the previous three members and add in three new members. @@ -238,8 +224,7 @@ func TestAddMemberAfterClusterFullRotation(t *testing.T) { // Ensure we can remove a member then add a new one back immediately. func TestIssue2681(t *testing.T) { integration.BeforeTest(t) - c := integration.NewCluster(t, 5) - c.Launch(t) + c := integration.NewClusterV3(t, &integration.ClusterConfig{Size: 5}) defer c.Terminate(t) c.MustRemoveMember(t, uint64(c.Members[4].Server.ID())) @@ -258,13 +243,7 @@ func TestIssue2746WithThree(t *testing.T) { testIssue2746(t, 3) } func testIssue2746(t *testing.T, members int) { integration.BeforeTest(t) - c := integration.NewCluster(t, members) - - for _, m := range c.Members { - m.SnapshotCount = 10 - } - - c.Launch(t) + c := integration.NewClusterV3(t, &integration.ClusterConfig{Size: members, SnapshotCount: 10}) defer c.Terminate(t) // force a snapshot @@ -284,8 +263,7 @@ func testIssue2746(t *testing.T, members int) { func TestIssue2904(t *testing.T) { integration.BeforeTest(t) // start 1-member Cluster to ensure member 0 is the leader of the Cluster. - c := integration.NewClusterFromConfig(t, &integration.ClusterConfig{Size: 1, UseBridge: true}) - c.Launch(t) + c := integration.NewClusterV3(t, &integration.ClusterConfig{Size: 1, UseBridge: true}) defer c.Terminate(t) c.AddMember(t) @@ -321,8 +299,7 @@ func TestIssue2904(t *testing.T) { func TestIssue3699(t *testing.T) { // start a Cluster of 3 nodes a, b, c integration.BeforeTest(t) - c := integration.NewClusterFromConfig(t, &integration.ClusterConfig{Size: 3, UseBridge: true}) - c.Launch(t) + c := integration.NewClusterV3(t, &integration.ClusterConfig{Size: 3, UseBridge: true}) defer c.Terminate(t) // make node a unavailable @@ -373,8 +350,7 @@ func TestIssue3699(t *testing.T) { // TestRejectUnhealthyAdd ensures an unhealthy cluster rejects adding members. func TestRejectUnhealthyAdd(t *testing.T) { integration.BeforeTest(t) - c := integration.NewClusterFromConfig(t, &integration.ClusterConfig{Size: 3, UseBridge: true, StrictReconfigCheck: true}) - c.Launch(t) + c := integration.NewClusterV3(t, &integration.ClusterConfig{Size: 3, UseBridge: true, StrictReconfigCheck: true}) defer c.Terminate(t) // make Cluster unhealthy and wait for downed peer @@ -414,8 +390,7 @@ func TestRejectUnhealthyAdd(t *testing.T) { // if quorum will be lost. func TestRejectUnhealthyRemove(t *testing.T) { integration.BeforeTest(t) - c := integration.NewClusterFromConfig(t, &integration.ClusterConfig{Size: 5, UseBridge: true, StrictReconfigCheck: true}) - c.Launch(t) + c := integration.NewClusterV3(t, &integration.ClusterConfig{Size: 5, UseBridge: true, StrictReconfigCheck: true}) defer c.Terminate(t) // make cluster unhealthy and wait for downed peer; (3 up, 2 down) @@ -460,8 +435,7 @@ func TestRestartRemoved(t *testing.T) { integration.BeforeTest(t) // 1. start single-member Cluster - c := integration.NewClusterFromConfig(t, &integration.ClusterConfig{Size: 1, UseBridge: true, StrictReconfigCheck: true}) - c.Launch(t) + c := integration.NewClusterV3(t, &integration.ClusterConfig{Size: 1, StrictReconfigCheck: true, UseBridge: true}) defer c.Terminate(t) // 2. add a new member @@ -469,27 +443,27 @@ func TestRestartRemoved(t *testing.T) { c.AddMember(t) c.WaitLeader(t) - oldm := c.Members[0] - oldm.KeepDataDirTerminate = true + firstMember := c.Members[0] + firstMember.KeepDataDirTerminate = true // 3. remove first member, shut down without deleting data - if err := c.RemoveMember(t, uint64(c.Members[0].Server.ID())); err != nil { + if err := c.RemoveMember(t, uint64(firstMember.Server.ID())); err != nil { t.Fatalf("expected to remove member, got error %v", err) } c.WaitLeader(t) // 4. restart first member with 'initial-cluster-state=new' // wrong config, expects exit within ReqTimeout - oldm.ServerConfig.NewCluster = false - if err := oldm.Restart(t); err != nil { + firstMember.ServerConfig.NewCluster = false + if err := firstMember.Restart(t); err != nil { t.Fatalf("unexpected ForceRestart error: %v", err) } defer func() { - oldm.Close() - os.RemoveAll(oldm.ServerConfig.DataDir) + firstMember.Close() + os.RemoveAll(firstMember.ServerConfig.DataDir) }() select { - case <-oldm.Server.StopNotify(): + case <-firstMember.Server.StopNotify(): case <-time.After(time.Minute): t.Fatalf("removed member didn't exit within %v", time.Minute) } @@ -498,35 +472,39 @@ func TestRestartRemoved(t *testing.T) { // clusterMustProgress ensures that cluster can make progress. It creates // a random key first, and check the new key could be got from all client urls // of the cluster. -func clusterMustProgress(t *testing.T, membs []*integration.Member) { - cc := integration.MustNewHTTPClient(t, []string{membs[0].URL()}, nil) - kapi := client.NewKeysAPI(cc) +func clusterMustProgress(t *testing.T, members []*integration.Member) { key := fmt.Sprintf("foo%d", rand.Int()) var ( err error - resp *client.Response + resp *clientv3.PutResponse ) // retry in case of leader loss induced by slow CI for i := 0; i < 3; i++ { ctx, cancel := context.WithTimeout(context.Background(), integration.RequestTimeout) - resp, err = kapi.Create(ctx, "/"+key, "bar") + resp, err = members[0].Client.Put(ctx, key, "bar") cancel() if err == nil { break } - t.Logf("failed to create key on %q (%v)", membs[0].URL(), err) + t.Logf("failed to create key on #0 (%v)", err) } if err != nil { - t.Fatalf("create on %s error: %v", membs[0].URL(), err) + t.Fatalf("create on #0 error: %v", err) } - for i, m := range membs { - u := m.URL() - mcc := integration.MustNewHTTPClient(t, []string{u}, nil) - mkapi := client.NewKeysAPI(mcc) + for i, m := range members { mctx, mcancel := context.WithTimeout(context.Background(), integration.RequestTimeout) - if _, err := mkapi.Watcher(key, &client.WatcherOptions{AfterIndex: resp.Node.ModifiedIndex - 1}).Next(mctx); err != nil { - t.Fatalf("#%d: watch on %s error: %v", i, u, err) + watch := m.Client.Watcher.Watch(mctx, key, clientv3.WithRev(resp.Header.Revision-1)) + for resp := range watch { + if len(resp.Events) != 0 { + break + } + if resp.Err() != nil { + t.Fatalf("#%d: watch error: %q", i, resp.Err()) + } + if resp.Canceled { + t.Fatalf("#%d: watch: cancelled", i) + } } mcancel() } diff --git a/tests/integration/member_test.go b/tests/integration/member_test.go index fe67c0ce38b0..2fb834ff0a57 100644 --- a/tests/integration/member_test.go +++ b/tests/integration/member_test.go @@ -29,8 +29,7 @@ import ( func TestPauseMember(t *testing.T) { integration.BeforeTest(t) - c := integration.NewCluster(t, 5) - c.Launch(t) + c := integration.NewClusterV3(t, &integration.ClusterConfig{Size: 5}) defer c.Terminate(t) for i := 0; i < 5; i++ { @@ -47,8 +46,7 @@ func TestPauseMember(t *testing.T) { func TestRestartMember(t *testing.T) { integration.BeforeTest(t) - c := integration.NewClusterFromConfig(t, &integration.ClusterConfig{Size: 3, UseBridge: true}) - c.Launch(t) + c := integration.NewClusterV3(t, &integration.ClusterConfig{Size: 3, UseBridge: true}) defer c.Terminate(t) for i := 0; i < 3; i++ { @@ -69,14 +67,13 @@ func TestRestartMember(t *testing.T) { func TestLaunchDuplicateMemberShouldFail(t *testing.T) { integration.BeforeTest(t) size := 3 - c := integration.NewCluster(t, size) + c := integration.NewClusterV3(t, &integration.ClusterConfig{Size: size}) m := c.Members[0].Clone(t) var err error m.DataDir, err = os.MkdirTemp(t.TempDir(), "etcd") if err != nil { t.Fatal(err) } - c.Launch(t) defer c.Terminate(t) if err := m.Launch(); err == nil { diff --git a/tests/integration/v3_grpc_test.go b/tests/integration/v3_grpc_test.go index ebb1482596ef..4f5b6a34ccad 100644 --- a/tests/integration/v3_grpc_test.go +++ b/tests/integration/v3_grpc_test.go @@ -1552,8 +1552,7 @@ func TestV3RangeRequest(t *testing.T) { func newClusterV3NoClients(t *testing.T, cfg *integration.ClusterConfig) *integration.ClusterV3 { cfg.UseGRPC = true - clus := &integration.ClusterV3{Cluster: integration.NewClusterByConfig(t, cfg)} - clus.Launch(t) + clus := integration.NewClusterV3(t, cfg) return clus } @@ -1561,8 +1560,7 @@ func newClusterV3NoClients(t *testing.T, cfg *integration.ClusterConfig) *integr func TestTLSGRPCRejectInsecureClient(t *testing.T) { integration.BeforeTest(t) - cfg := integration.ClusterConfig{Size: 3, ClientTLS: &integration.TestTLSInfo} - clus := newClusterV3NoClients(t, &cfg) + clus := integration.NewClusterV3(t, &integration.ClusterConfig{Size: 3, ClientTLS: &integration.TestTLSInfo}) defer clus.Terminate(t) // nil out TLS field so client will use an insecure connection @@ -1596,8 +1594,7 @@ func TestTLSGRPCRejectInsecureClient(t *testing.T) { func TestTLSGRPCRejectSecureClient(t *testing.T) { integration.BeforeTest(t) - cfg := integration.ClusterConfig{Size: 3} - clus := newClusterV3NoClients(t, &cfg) + clus := integration.NewClusterV3(t, &integration.ClusterConfig{Size: 3}) defer clus.Terminate(t) clus.Members[0].ClientTLSInfo = &integration.TestTLSInfo @@ -1616,8 +1613,7 @@ func TestTLSGRPCRejectSecureClient(t *testing.T) { func TestTLSGRPCAcceptSecureAll(t *testing.T) { integration.BeforeTest(t) - cfg := integration.ClusterConfig{Size: 3, ClientTLS: &integration.TestTLSInfo} - clus := newClusterV3NoClients(t, &cfg) + clus := integration.NewClusterV3(t, &integration.ClusterConfig{Size: 3, ClientTLS: &integration.TestTLSInfo}) defer clus.Terminate(t) client, err := integration.NewClientV3(clus.Members[0]) @@ -1834,8 +1830,7 @@ func testTLSReload( func TestGRPCRequireLeader(t *testing.T) { integration.BeforeTest(t) - cfg := integration.ClusterConfig{Size: 3} - clus := newClusterV3NoClients(t, &cfg) + clus := integration.NewClusterV3(t, &integration.ClusterConfig{Size: 3}) defer clus.Terminate(t) clus.Members[1].Stop(t) @@ -1861,8 +1856,7 @@ func TestGRPCRequireLeader(t *testing.T) { func TestGRPCStreamRequireLeader(t *testing.T) { integration.BeforeTest(t) - cfg := integration.ClusterConfig{Size: 3, UseBridge: true} - clus := newClusterV3NoClients(t, &cfg) + clus := integration.NewClusterV3(t, &integration.ClusterConfig{Size: 3, UseBridge: true}) defer clus.Terminate(t) client, err := integration.NewClientV3(clus.Members[0]) From 51f72915e460e455f9dab59497773f3446901cde Mon Sep 17 00:00:00 2001 From: Marek Siarkowicz Date: Tue, 18 Jan 2022 15:58:54 +0100 Subject: [PATCH 078/258] test: Move UseGRPC to member config --- tests/framework/integration/cluster.go | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/tests/framework/integration/cluster.go b/tests/framework/integration/cluster.go index 33db80370d7e..1e2d9f8cd844 100644 --- a/tests/framework/integration/cluster.go +++ b/tests/framework/integration/cluster.go @@ -319,13 +319,9 @@ func (c *Cluster) mustNewMember(t testutil.TB) *Member { WatchProgressNotifyInterval: c.Cfg.WatchProgressNotifyInterval, ExperimentalMaxLearners: c.Cfg.ExperimentalMaxLearners, StrictReconfigCheck: c.Cfg.StrictReconfigCheck, + UseGRPC: c.Cfg.UseGRPC, }) m.DiscoveryURL = c.Cfg.DiscoveryURL - if c.Cfg.UseGRPC { - if err := m.listenGRPC(); err != nil { - t.Fatal(err) - } - } return m } @@ -632,6 +628,7 @@ type MemberConfig struct { WatchProgressNotifyInterval time.Duration ExperimentalMaxLearners int StrictReconfigCheck bool + UseGRPC bool } // MustNewMember return an inited member with the given name. If peerTLS is @@ -744,6 +741,11 @@ func MustNewMember(t testutil.TB, mcfg MemberConfig) *Member { m.GrpcServerRecorder = &grpc_testing.GrpcRecorder{} m.Logger = memberLogger(t, mcfg.Name) m.StrictReconfigCheck = mcfg.StrictReconfigCheck + if mcfg.UseGRPC { + if err := m.listenGRPC(); err != nil { + t.Fatal(err) + } + } t.Cleanup(func() { // if we didn't cleanup the logger, the consecutive test // might reuse this (t). From de30257d7924086a9805e979361d0527430e3e1f Mon Sep 17 00:00:00 2001 From: Marek Siarkowicz Date: Tue, 18 Jan 2022 16:34:15 +0100 Subject: [PATCH 079/258] test: Always run server with grpc enabled --- tests/framework/integration/cluster.go | 12 ++---------- tests/integration/cluster_test.go | 2 +- tests/integration/v3_grpc_test.go | 6 ------ 3 files changed, 3 insertions(+), 17 deletions(-) diff --git a/tests/framework/integration/cluster.go b/tests/framework/integration/cluster.go index 1e2d9f8cd844..76c754e9929f 100644 --- a/tests/framework/integration/cluster.go +++ b/tests/framework/integration/cluster.go @@ -139,8 +139,6 @@ type ClusterConfig struct { AuthToken string - UseGRPC bool - QuotaBackendBytes int64 MaxTxnOps uint @@ -319,7 +317,6 @@ func (c *Cluster) mustNewMember(t testutil.TB) *Member { WatchProgressNotifyInterval: c.Cfg.WatchProgressNotifyInterval, ExperimentalMaxLearners: c.Cfg.ExperimentalMaxLearners, StrictReconfigCheck: c.Cfg.StrictReconfigCheck, - UseGRPC: c.Cfg.UseGRPC, }) m.DiscoveryURL = c.Cfg.DiscoveryURL return m @@ -628,7 +625,6 @@ type MemberConfig struct { WatchProgressNotifyInterval time.Duration ExperimentalMaxLearners int StrictReconfigCheck bool - UseGRPC bool } // MustNewMember return an inited member with the given name. If peerTLS is @@ -741,10 +737,8 @@ func MustNewMember(t testutil.TB, mcfg MemberConfig) *Member { m.GrpcServerRecorder = &grpc_testing.GrpcRecorder{} m.Logger = memberLogger(t, mcfg.Name) m.StrictReconfigCheck = mcfg.StrictReconfigCheck - if mcfg.UseGRPC { - if err := m.listenGRPC(); err != nil { - t.Fatal(err) - } + if err := m.listenGRPC(); err != nil { + t.Fatal(err) } t.Cleanup(func() { // if we didn't cleanup the logger, the consecutive test @@ -1403,8 +1397,6 @@ func NewClusterV3(t testutil.TB, cfg *ClusterConfig) *ClusterV3 { assertInTestContext(t) - cfg.UseGRPC = true - clus := &ClusterV3{ Cluster: newClusterFromConfig(t, cfg), } diff --git a/tests/integration/cluster_test.go b/tests/integration/cluster_test.go index 2b3fd3179a83..9bc985de699b 100644 --- a/tests/integration/cluster_test.go +++ b/tests/integration/cluster_test.go @@ -162,7 +162,7 @@ func testDecreaseClusterSize(t *testing.T, size int) { func TestForceNewCluster(t *testing.T) { integration.BeforeTest(t) - c := integration.NewClusterV3(t, &integration.ClusterConfig{Size: 3, UseBridge: true, UseGRPC: true}) + c := integration.NewClusterV3(t, &integration.ClusterConfig{Size: 3, UseBridge: true}) cc := integration.MustNewHTTPClient(t, []string{c.Members[0].URL()}, nil) kapi := client.NewKeysAPI(cc) ctx, cancel := context.WithTimeout(context.Background(), integration.RequestTimeout) diff --git a/tests/integration/v3_grpc_test.go b/tests/integration/v3_grpc_test.go index 4f5b6a34ccad..54165c845bc5 100644 --- a/tests/integration/v3_grpc_test.go +++ b/tests/integration/v3_grpc_test.go @@ -1550,12 +1550,6 @@ func TestV3RangeRequest(t *testing.T) { } } -func newClusterV3NoClients(t *testing.T, cfg *integration.ClusterConfig) *integration.ClusterV3 { - cfg.UseGRPC = true - clus := integration.NewClusterV3(t, cfg) - return clus -} - // TestTLSGRPCRejectInsecureClient checks that connection is rejected if server is TLS but not client. func TestTLSGRPCRejectInsecureClient(t *testing.T) { integration.BeforeTest(t) From 7b365e48d34fafb326d7afd802bdfcbbc381ce8c Mon Sep 17 00:00:00 2001 From: Marek Siarkowicz Date: Tue, 18 Jan 2022 16:37:00 +0100 Subject: [PATCH 080/258] test: Remove usage of V2 Put API in tests --- tests/integration/client/client_test.go | 130 ------------------------ tests/integration/client/doc.go | 17 ---- tests/integration/client/main_test.go | 15 --- tests/integration/cluster_test.go | 39 ++++--- tests/integration/member_test.go | 16 +-- 5 files changed, 31 insertions(+), 186 deletions(-) delete mode 100644 tests/integration/client/client_test.go delete mode 100644 tests/integration/client/doc.go delete mode 100644 tests/integration/client/main_test.go diff --git a/tests/integration/client/client_test.go b/tests/integration/client/client_test.go deleted file mode 100644 index 132118b9a630..000000000000 --- a/tests/integration/client/client_test.go +++ /dev/null @@ -1,130 +0,0 @@ -// Copyright 2016 The etcd Authors -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -package integration - -import ( - "context" - "fmt" - "net/http" - "net/http/httptest" - "os" - "strings" - "sync/atomic" - "testing" - - "go.etcd.io/etcd/client/v2" - integration2 "go.etcd.io/etcd/tests/v3/framework/integration" -) - -// TestV2NoRetryEOF tests destructive api calls won't retry on a disconnection. -func TestV2NoRetryEOF(t *testing.T) { - integration2.BeforeTest(t) - // generate an EOF response; specify address so appears first in sorted ep list - lEOF := integration2.NewListenerWithAddr(t, fmt.Sprintf("127.0.0.1:%05d", os.Getpid())) - defer lEOF.Close() - tries := uint32(0) - go func() { - for { - conn, err := lEOF.Accept() - if err != nil { - return - } - atomic.AddUint32(&tries, 1) - conn.Close() - } - }() - eofURL := integration2.URLScheme + "://" + lEOF.Addr().String() - cli := integration2.MustNewHTTPClient(t, []string{eofURL, eofURL}, nil) - kapi := client.NewKeysAPI(cli) - for i, f := range noRetryList(kapi) { - startTries := atomic.LoadUint32(&tries) - if err := f(); err == nil { - t.Errorf("#%d: expected EOF error, got nil", i) - } - endTries := atomic.LoadUint32(&tries) - if startTries+1 != endTries { - t.Errorf("#%d: expected 1 try, got %d", i, endTries-startTries) - } - } -} - -// TestV2NoRetryNoLeader tests destructive api calls won't retry if given an error code. -func TestV2NoRetryNoLeader(t *testing.T) { - integration2.BeforeTest(t) - lHTTP := integration2.NewListenerWithAddr(t, fmt.Sprintf("127.0.0.1:%05d", os.Getpid())) - eh := &errHandler{errCode: http.StatusServiceUnavailable} - srv := httptest.NewUnstartedServer(eh) - defer lHTTP.Close() - defer srv.Close() - srv.Listener = lHTTP - go srv.Start() - lHTTPURL := integration2.URLScheme + "://" + lHTTP.Addr().String() - - cli := integration2.MustNewHTTPClient(t, []string{lHTTPURL, lHTTPURL}, nil) - kapi := client.NewKeysAPI(cli) - // test error code - for i, f := range noRetryList(kapi) { - reqs := eh.reqs - if err := f(); err == nil || !strings.Contains(err.Error(), "no leader") { - t.Errorf("#%d: expected \"no leader\", got %v", i, err) - } - if eh.reqs != reqs+1 { - t.Errorf("#%d: expected 1 request, got %d", i, eh.reqs-reqs) - } - } -} - -// TestV2RetryRefuse tests destructive api calls will retry if a connection is refused. -func TestV2RetryRefuse(t *testing.T) { - integration2.BeforeTest(t) - cl := integration2.NewClusterV3(t, &integration2.ClusterConfig{Size: 1}) - defer cl.Terminate(t) - // test connection refused; expect no error failover - cli := integration2.MustNewHTTPClient(t, []string{integration2.URLScheme + "://refuseconn:123", cl.URL(0)}, nil) - kapi := client.NewKeysAPI(cli) - if _, err := kapi.Set(context.Background(), "/delkey", "def", nil); err != nil { - t.Fatal(err) - } - for i, f := range noRetryList(kapi) { - if err := f(); err != nil { - t.Errorf("#%d: unexpected retry failure (%v)", i, err) - } - } -} - -type errHandler struct { - errCode int - reqs int -} - -func (eh *errHandler) ServeHTTP(w http.ResponseWriter, req *http.Request) { - req.Body.Close() - eh.reqs++ - w.WriteHeader(eh.errCode) -} - -func noRetryList(kapi client.KeysAPI) []func() error { - return []func() error{ - func() error { - opts := &client.SetOptions{PrevExist: client.PrevNoExist} - _, err := kapi.Set(context.Background(), "/setkey", "bar", opts) - return err - }, - func() error { - _, err := kapi.Delete(context.Background(), "/delkey", nil) - return err - }, - } -} diff --git a/tests/integration/client/doc.go b/tests/integration/client/doc.go deleted file mode 100644 index e9c58d67f5c5..000000000000 --- a/tests/integration/client/doc.go +++ /dev/null @@ -1,17 +0,0 @@ -// Copyright 2016 The etcd Authors -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -// Package integration implements tests built upon embedded etcd, focusing on -// the correctness of the etcd v2 client. -package integration diff --git a/tests/integration/client/main_test.go b/tests/integration/client/main_test.go deleted file mode 100644 index e783205834f5..000000000000 --- a/tests/integration/client/main_test.go +++ /dev/null @@ -1,15 +0,0 @@ -// Copyright 2013 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -package integration - -import ( - "testing" - - "go.etcd.io/etcd/client/pkg/v3/testutil" -) - -func TestMain(m *testing.M) { - testutil.MustTestMainWithLeakDetection(m) -} diff --git a/tests/integration/cluster_test.go b/tests/integration/cluster_test.go index 9bc985de699b..5a8730170546 100644 --- a/tests/integration/cluster_test.go +++ b/tests/integration/cluster_test.go @@ -163,18 +163,27 @@ func testDecreaseClusterSize(t *testing.T, size int) { func TestForceNewCluster(t *testing.T) { integration.BeforeTest(t) c := integration.NewClusterV3(t, &integration.ClusterConfig{Size: 3, UseBridge: true}) - cc := integration.MustNewHTTPClient(t, []string{c.Members[0].URL()}, nil) - kapi := client.NewKeysAPI(cc) + defer c.Terminate(t) + ctx, cancel := context.WithTimeout(context.Background(), integration.RequestTimeout) - resp, err := kapi.Create(ctx, "/foo", "bar") + resp, err := c.Members[0].Client.Put(ctx, "/foo", "bar") if err != nil { t.Fatalf("unexpected create error: %v", err) } cancel() // ensure create has been applied in this machine ctx, cancel = context.WithTimeout(context.Background(), integration.RequestTimeout) - if _, err = kapi.Watcher("/foo", &client.WatcherOptions{AfterIndex: resp.Node.ModifiedIndex - 1}).Next(ctx); err != nil { - t.Fatalf("unexpected watch error: %v", err) + watch := c.Members[0].Client.Watcher.Watch(ctx, "/foo", clientv3.WithRev(resp.Header.Revision-1)) + for resp := range watch { + if len(resp.Events) != 0 { + break + } + if resp.Err() != nil { + t.Fatalf("unexpected watch error: %q", resp.Err()) + } + if resp.Canceled { + t.Fatalf("watch cancelled") + } } cancel() @@ -186,16 +195,22 @@ func TestForceNewCluster(t *testing.T) { if err != nil { t.Fatalf("unexpected ForceRestart error: %v", err) } - defer c.Members[0].Terminate(t) c.WaitMembersForLeader(t, c.Members[:1]) // use new http client to init new connection - cc = integration.MustNewHTTPClient(t, []string{c.Members[0].URL()}, nil) - kapi = client.NewKeysAPI(cc) // ensure force restart keep the old data, and new Cluster can make progress ctx, cancel = context.WithTimeout(context.Background(), integration.RequestTimeout) - if _, err := kapi.Watcher("/foo", &client.WatcherOptions{AfterIndex: resp.Node.ModifiedIndex - 1}).Next(ctx); err != nil { - t.Fatalf("unexpected watch error: %v", err) + watch = c.Members[0].Client.Watcher.Watch(ctx, "/foo", clientv3.WithRev(resp.Header.Revision-1)) + for resp := range watch { + if len(resp.Events) != 0 { + break + } + if resp.Err() != nil { + t.Fatalf("unexpected watch error: %q", resp.Err()) + } + if resp.Canceled { + t.Fatalf("watch cancelled") + } } cancel() clusterMustProgress(t, c.Members[:1]) @@ -338,10 +353,8 @@ func TestIssue3699(t *testing.T) { c.WaitMembersForLeader(t, c.Members) // try to participate in Cluster - cc := integration.MustNewHTTPClient(t, []string{c.URL(0)}, c.Cfg.ClientTLS) - kapi := client.NewKeysAPI(cc) ctx, cancel := context.WithTimeout(context.Background(), integration.RequestTimeout) - if _, err := kapi.Set(ctx, "/foo", "bar", nil); err != nil { + if _, err := c.Members[0].Client.Put(ctx, "/foo", "bar"); err != nil { t.Fatalf("unexpected error on Set (%v)", err) } cancel() diff --git a/tests/integration/member_test.go b/tests/integration/member_test.go index 2fb834ff0a57..0ac006e50bca 100644 --- a/tests/integration/member_test.go +++ b/tests/integration/member_test.go @@ -18,11 +18,9 @@ import ( "context" "fmt" "os" - "reflect" "testing" "github.com/stretchr/testify/assert" - "go.etcd.io/etcd/client/v2" "go.etcd.io/etcd/tests/v3/framework/integration" ) @@ -90,16 +88,14 @@ func TestSnapshotAndRestartMember(t *testing.T) { m.SnapshotCount = 100 m.Launch() defer m.Terminate(t) + defer m.Client.Close() m.WaitOK(t) - resps := make([]*client.Response, 120) var err error for i := 0; i < 120; i++ { - cc := integration.MustNewHTTPClient(t, []string{m.URL()}, nil) - kapi := client.NewKeysAPI(cc) ctx, cancel := context.WithTimeout(context.Background(), integration.RequestTimeout) key := fmt.Sprintf("foo%d", i) - resps[i], err = kapi.Create(ctx, "/"+key, "bar") + _, err = m.Client.Put(ctx, "/"+key, "bar") if err != nil { t.Fatalf("#%d: create on %s error: %v", i, m.URL(), err) } @@ -110,18 +106,16 @@ func TestSnapshotAndRestartMember(t *testing.T) { m.WaitOK(t) for i := 0; i < 120; i++ { - cc := integration.MustNewHTTPClient(t, []string{m.URL()}, nil) - kapi := client.NewKeysAPI(cc) ctx, cancel := context.WithTimeout(context.Background(), integration.RequestTimeout) key := fmt.Sprintf("foo%d", i) - resp, err := kapi.Get(ctx, "/"+key, nil) + resp, err := m.Client.Get(ctx, "/"+key) if err != nil { t.Fatalf("#%d: get on %s error: %v", i, m.URL(), err) } cancel() - if !reflect.DeepEqual(resp.Node, resps[i].Node) { - t.Errorf("#%d: node = %v, want %v", i, resp.Node, resps[i].Node) + if len(resp.Kvs) != 1 || string(resp.Kvs[0].Value) != "bar" { + t.Errorf("#%d: got = %v, want %v", i, resp.Kvs[0], "bar") } } } From 264fdbb6a1541beeb26c1f8109d9538830cda34c Mon Sep 17 00:00:00 2001 From: Marek Siarkowicz Date: Tue, 18 Jan 2022 17:22:40 +0100 Subject: [PATCH 081/258] test: Remove separation between V2 and V3 cluster in integration tests --- tests/framework/integration/cluster.go | 106 ++++++++---------- tests/integration/clientv3/cluster_test.go | 22 ++-- .../clientv3/concurrency/revision_test.go | 16 +-- .../clientv3/connectivity/black_hole_test.go | 4 +- .../clientv3/connectivity/dial_test.go | 14 +-- .../connectivity/network_partition_test.go | 8 +- .../connectivity/server_shutdown_test.go | 8 +- .../experimental/recipes/v3_barrier_test.go | 4 +- .../recipes/v3_double_barrier_test.go | 4 +- .../experimental/recipes/v3_lock_test.go | 18 +-- .../experimental/recipes/v3_queue_test.go | 16 +-- tests/integration/clientv3/kv_test.go | 42 +++---- .../integration/clientv3/lease/lease_test.go | 44 ++++---- .../clientv3/lease/leasing_test.go | 82 +++++++------- .../integration/clientv3/maintenance_test.go | 14 +-- tests/integration/clientv3/metrics_test.go | 2 +- tests/integration/clientv3/mirror_test.go | 4 +- tests/integration/clientv3/namespace_test.go | 4 +- .../clientv3/naming/endpoints_test.go | 6 +- .../clientv3/naming/resolver_test.go | 2 +- .../integration/clientv3/ordering_kv_test.go | 4 +- .../clientv3/ordering_util_test.go | 4 +- tests/integration/clientv3/role_test.go | 2 +- tests/integration/clientv3/txn_test.go | 12 +- tests/integration/clientv3/user_test.go | 6 +- .../clientv3/watch_fragment_test.go | 2 +- tests/integration/clientv3/watch_test.go | 46 ++++---- tests/integration/cluster_test.go | 40 +++---- tests/integration/grpc_test.go | 8 +- tests/integration/lazy_cluster.go | 8 +- tests/integration/member_test.go | 6 +- tests/integration/metrics_test.go | 8 +- tests/integration/network_partition_test.go | 18 +-- .../proxy/grpcproxy/cluster_test.go | 2 +- tests/integration/proxy/grpcproxy/kv_test.go | 2 +- .../proxy/grpcproxy/register_test.go | 2 +- tests/integration/v3_alarm_test.go | 6 +- tests/integration/v3_auth_test.go | 16 +-- tests/integration/v3_election_test.go | 12 +- tests/integration/v3_grpc_inflight_test.go | 4 +- tests/integration/v3_grpc_test.go | 54 ++++----- tests/integration/v3_health_test.go | 2 +- tests/integration/v3_kv_test.go | 2 +- tests/integration/v3_leadership_test.go | 10 +- tests/integration/v3_lease_test.go | 44 ++++---- tests/integration/v3_stm_test.go | 12 +- tests/integration/v3_tls_test.go | 2 +- tests/integration/v3_watch_restore_test.go | 2 +- tests/integration/v3_watch_test.go | 32 +++--- tests/integration/v3election_grpc_test.go | 4 +- tests/integration/v3lock_grpc_test.go | 2 +- 51 files changed, 389 insertions(+), 405 deletions(-) diff --git a/tests/framework/integration/cluster.go b/tests/framework/integration/cluster.go index 76c754e9929f..323398c7bb92 100644 --- a/tests/framework/integration/cluster.go +++ b/tests/framework/integration/cluster.go @@ -174,6 +174,9 @@ type Cluster struct { Cfg *ClusterConfig Members []*Member LastMemberNum int + + mu sync.Mutex + clusterClient *clientv3.Client } func SchemeFromTLSInfo(tls *transport.TLSInfo) string { @@ -207,22 +210,6 @@ func (c *Cluster) fillClusterForMembers() error { return nil } -func newClusterFromConfig(t testutil.TB, cfg *ClusterConfig) *Cluster { - testutil.SkipTestIfShortMode(t, "Cannot start etcd Cluster in --short tests") - - c := &Cluster{Cfg: cfg} - ms := make([]*Member, cfg.Size) - for i := 0; i < cfg.Size; i++ { - ms[i] = c.mustNewMember(t) - } - c.Members = ms - if err := c.fillClusterForMembers(); err != nil { - t.Fatal(err) - } - - return c -} - func (c *Cluster) Launch(t testutil.TB) { errc := make(chan error) for _, m := range c.Members { @@ -415,23 +402,6 @@ func (c *Cluster) RemoveMember(t testutil.TB, id uint64) error { return nil } -func (c *Cluster) Terminate(t testutil.TB) { - for _, m := range c.Members { - if m.Client != nil { - m.Client.Close() - } - } - var wg sync.WaitGroup - wg.Add(len(c.Members)) - for _, m := range c.Members { - go func(mm *Member) { - defer wg.Done() - mm.Terminate(t) - }(m) - } - wg.Wait() -} - func (c *Cluster) WaitMembersMatch(t testutil.TB, membs []client.Member) { for _, u := range c.URLs() { cc := MustNewHTTPClient(t, []string{u}, c.Cfg.ClientTLS) @@ -1383,35 +1353,36 @@ func (p SortableMemberSliceByPeerURLs) Less(i, j int) bool { } func (p SortableMemberSliceByPeerURLs) Swap(i, j int) { p[i], p[j] = p[j], p[i] } -type ClusterV3 struct { - *Cluster - - mu sync.Mutex - clusterClient *clientv3.Client -} - -// NewClusterV3 returns a launched Cluster with a grpc client connection +// NewCluster returns a launched Cluster with a grpc client connection // for each Cluster member. -func NewClusterV3(t testutil.TB, cfg *ClusterConfig) *ClusterV3 { +func NewCluster(t testutil.TB, cfg *ClusterConfig) *Cluster { t.Helper() assertInTestContext(t) - clus := &ClusterV3{ - Cluster: newClusterFromConfig(t, cfg), + testutil.SkipTestIfShortMode(t, "Cannot start etcd Cluster in --short tests") + + c := &Cluster{Cfg: cfg} + ms := make([]*Member, cfg.Size) + for i := 0; i < cfg.Size; i++ { + ms[i] = c.mustNewMember(t) + } + c.Members = ms + if err := c.fillClusterForMembers(); err != nil { + t.Fatal(err) } - clus.Launch(t) + c.Launch(t) - return clus + return c } -func (c *ClusterV3) TakeClient(idx int) { +func (c *Cluster) TakeClient(idx int) { c.mu.Lock() c.Members[idx].Client = nil c.mu.Unlock() } -func (c *ClusterV3) Terminate(t testutil.TB) { +func (c *Cluster) Terminate(t testutil.TB) { c.mu.Lock() if c.clusterClient != nil { if err := c.clusterClient.Close(); err != nil { @@ -1419,18 +1390,31 @@ func (c *ClusterV3) Terminate(t testutil.TB) { } } c.mu.Unlock() - c.Cluster.Terminate(t) + for _, m := range c.Members { + if m.Client != nil { + m.Client.Close() + } + } + var wg sync.WaitGroup + wg.Add(len(c.Members)) + for _, m := range c.Members { + go func(mm *Member) { + defer wg.Done() + mm.Terminate(t) + }(m) + } + wg.Wait() } -func (c *ClusterV3) RandClient() *clientv3.Client { +func (c *Cluster) RandClient() *clientv3.Client { return c.Members[rand.Intn(len(c.Members))].Client } -func (c *ClusterV3) Client(i int) *clientv3.Client { +func (c *Cluster) Client(i int) *clientv3.Client { return c.Members[i].Client } -func (c *ClusterV3) ClusterClient() (client *clientv3.Client, err error) { +func (c *Cluster) ClusterClient() (client *clientv3.Client, err error) { if c.clusterClient == nil { endpoints := []string{} for _, m := range c.Members { @@ -1450,11 +1434,11 @@ func (c *ClusterV3) ClusterClient() (client *clientv3.Client, err error) { } // NewClientV3 creates a new grpc client connection to the member -func (c *ClusterV3) NewClientV3(memberIndex int) (*clientv3.Client, error) { +func (c *Cluster) NewClientV3(memberIndex int) (*clientv3.Client, error) { return NewClientV3(c.Members[memberIndex]) } -func makeClients(t testutil.TB, clus *ClusterV3, clients *[]*clientv3.Client, chooseMemberIndex func() int) func() *clientv3.Client { +func makeClients(t testutil.TB, clus *Cluster, clients *[]*clientv3.Client, chooseMemberIndex func() int) func() *clientv3.Client { var mu sync.Mutex *clients = nil return func() *clientv3.Client { @@ -1471,13 +1455,13 @@ func makeClients(t testutil.TB, clus *ClusterV3, clients *[]*clientv3.Client, ch // MakeSingleNodeClients creates factory of clients that all connect to member 0. // All the created clients are put on the 'clients' list. The factory is thread-safe. -func MakeSingleNodeClients(t testutil.TB, clus *ClusterV3, clients *[]*clientv3.Client) func() *clientv3.Client { +func MakeSingleNodeClients(t testutil.TB, clus *Cluster, clients *[]*clientv3.Client) func() *clientv3.Client { return makeClients(t, clus, clients, func() int { return 0 }) } // MakeMultiNodeClients creates factory of clients that all connect to random members. // All the created clients are put on the 'clients' list. The factory is thread-safe. -func MakeMultiNodeClients(t testutil.TB, clus *ClusterV3, clients *[]*clientv3.Client) func() *clientv3.Client { +func MakeMultiNodeClients(t testutil.TB, clus *Cluster, clients *[]*clientv3.Client) func() *clientv3.Client { return makeClients(t, clus, clients, func() int { return rand.Intn(len(clus.Members)) }) } @@ -1510,7 +1494,7 @@ type GrpcAPI struct { } // GetLearnerMembers returns the list of learner members in Cluster using MemberList API. -func (c *ClusterV3) GetLearnerMembers() ([]*pb.Member, error) { +func (c *Cluster) GetLearnerMembers() ([]*pb.Member, error) { cli := c.Client(0) resp, err := cli.MemberList(context.Background()) if err != nil { @@ -1527,7 +1511,7 @@ func (c *ClusterV3) GetLearnerMembers() ([]*pb.Member, error) { // AddAndLaunchLearnerMember creates a leaner member, adds it to Cluster // via v3 MemberAdd API, and then launches the new member. -func (c *ClusterV3) AddAndLaunchLearnerMember(t testutil.TB) { +func (c *Cluster) AddAndLaunchLearnerMember(t testutil.TB) { m := c.mustNewMember(t) m.IsLearner = true @@ -1557,7 +1541,7 @@ func (c *ClusterV3) AddAndLaunchLearnerMember(t testutil.TB) { } // getMembers returns a list of members in Cluster, in format of etcdserverpb.Member -func (c *ClusterV3) getMembers() []*pb.Member { +func (c *Cluster) getMembers() []*pb.Member { var mems []*pb.Member for _, m := range c.Members { mem := &pb.Member{ @@ -1594,7 +1578,7 @@ func (c *ClusterV3) getMembers() []*pb.Member { // indicate that the new learner member has applied the raftpb.ConfChangeAddLearnerNode entry // which was used to add the learner itself to the Cluster, and therefore it has the correct info // on learner. -func (c *ClusterV3) waitMembersMatch(t testutil.TB) { +func (c *Cluster) waitMembersMatch(t testutil.TB) { wMembers := c.getMembers() sort.Sort(SortableProtoMemberSliceByPeerURLs(wMembers)) cli := c.Client(0) @@ -1628,7 +1612,7 @@ func (p SortableProtoMemberSliceByPeerURLs) Less(i, j int) bool { func (p SortableProtoMemberSliceByPeerURLs) Swap(i, j int) { p[i], p[j] = p[j], p[i] } // MustNewMember creates a new member instance based on the response of V3 Member Add API. -func (c *ClusterV3) MustNewMember(t testutil.TB, resp *clientv3.MemberAddResponse) *Member { +func (c *Cluster) MustNewMember(t testutil.TB, resp *clientv3.MemberAddResponse) *Member { m := c.mustNewMember(t) m.IsLearner = resp.Member.IsLearner m.NewCluster = false diff --git a/tests/integration/clientv3/cluster_test.go b/tests/integration/clientv3/cluster_test.go index edf47f29b4f2..a702e036451b 100644 --- a/tests/integration/clientv3/cluster_test.go +++ b/tests/integration/clientv3/cluster_test.go @@ -30,7 +30,7 @@ import ( func TestMemberList(t *testing.T) { integration2.BeforeTest(t) - clus := integration2.NewClusterV3(t, &integration2.ClusterConfig{Size: 3}) + clus := integration2.NewCluster(t, &integration2.ClusterConfig{Size: 3}) defer clus.Terminate(t) capi := clus.RandClient() @@ -48,7 +48,7 @@ func TestMemberList(t *testing.T) { func TestMemberAdd(t *testing.T) { integration2.BeforeTest(t) - clus := integration2.NewClusterV3(t, &integration2.ClusterConfig{Size: 3}) + clus := integration2.NewCluster(t, &integration2.ClusterConfig{Size: 3}) defer clus.Terminate(t) capi := clus.RandClient() @@ -67,7 +67,7 @@ func TestMemberAdd(t *testing.T) { func TestMemberAddWithExistingURLs(t *testing.T) { integration2.BeforeTest(t) - clus := integration2.NewClusterV3(t, &integration2.ClusterConfig{Size: 3}) + clus := integration2.NewCluster(t, &integration2.ClusterConfig{Size: 3}) defer clus.Terminate(t) capi := clus.RandClient() @@ -91,7 +91,7 @@ func TestMemberAddWithExistingURLs(t *testing.T) { func TestMemberRemove(t *testing.T) { integration2.BeforeTest(t) - clus := integration2.NewClusterV3(t, &integration2.ClusterConfig{Size: 3}) + clus := integration2.NewCluster(t, &integration2.ClusterConfig{Size: 3}) defer clus.Terminate(t) capi := clus.Client(1) @@ -129,7 +129,7 @@ func TestMemberRemove(t *testing.T) { func TestMemberUpdate(t *testing.T) { integration2.BeforeTest(t) - clus := integration2.NewClusterV3(t, &integration2.ClusterConfig{Size: 3}) + clus := integration2.NewCluster(t, &integration2.ClusterConfig{Size: 3}) defer clus.Terminate(t) capi := clus.RandClient() @@ -157,7 +157,7 @@ func TestMemberUpdate(t *testing.T) { func TestMemberAddUpdateWrongURLs(t *testing.T) { integration2.BeforeTest(t) - clus := integration2.NewClusterV3(t, &integration2.ClusterConfig{Size: 1}) + clus := integration2.NewCluster(t, &integration2.ClusterConfig{Size: 1}) defer clus.Terminate(t) capi := clus.RandClient() @@ -190,7 +190,7 @@ func TestMemberAddUpdateWrongURLs(t *testing.T) { func TestMemberAddForLearner(t *testing.T) { integration2.BeforeTest(t) - clus := integration2.NewClusterV3(t, &integration2.ClusterConfig{Size: 3}) + clus := integration2.NewCluster(t, &integration2.ClusterConfig{Size: 3}) defer clus.Terminate(t) capi := clus.RandClient() @@ -219,7 +219,7 @@ func TestMemberAddForLearner(t *testing.T) { func TestMemberPromote(t *testing.T) { integration2.BeforeTest(t) - clus := integration2.NewClusterV3(t, &integration2.ClusterConfig{Size: 3}) + clus := integration2.NewCluster(t, &integration2.ClusterConfig{Size: 3}) defer clus.Terminate(t) // member promote request can be sent to any server in cluster, @@ -296,7 +296,7 @@ func TestMemberPromote(t *testing.T) { func TestMemberPromoteMemberNotLearner(t *testing.T) { integration2.BeforeTest(t) - clus := integration2.NewClusterV3(t, &integration2.ClusterConfig{Size: 3}) + clus := integration2.NewCluster(t, &integration2.ClusterConfig{Size: 3}) defer clus.Terminate(t) // member promote request can be sent to any server in cluster, @@ -332,7 +332,7 @@ func TestMemberPromoteMemberNotLearner(t *testing.T) { func TestMemberPromoteMemberNotExist(t *testing.T) { integration2.BeforeTest(t) - clus := integration2.NewClusterV3(t, &integration2.ClusterConfig{Size: 3}) + clus := integration2.NewCluster(t, &integration2.ClusterConfig{Size: 3}) defer clus.Terminate(t) // member promote request can be sent to any server in cluster, @@ -382,7 +382,7 @@ func TestMaxLearnerInCluster(t *testing.T) { integration2.BeforeTest(t) // 1. start with a cluster with 3 voting member and max learner 2 - clus := integration2.NewClusterV3(t, &integration2.ClusterConfig{Size: 3, ExperimentalMaxLearners: 2}) + clus := integration2.NewCluster(t, &integration2.ClusterConfig{Size: 3, ExperimentalMaxLearners: 2}) defer clus.Terminate(t) // 2. adding 2 learner members should succeed diff --git a/tests/integration/clientv3/concurrency/revision_test.go b/tests/integration/clientv3/concurrency/revision_test.go index c0a08c454f90..7e6236a7a982 100644 --- a/tests/integration/clientv3/concurrency/revision_test.go +++ b/tests/integration/clientv3/concurrency/revision_test.go @@ -28,7 +28,7 @@ import ( ) func TestRevisionMonotonicWithLeaderPartitions(t *testing.T) { - testRevisionMonotonicWithFailures(t, 11*time.Second, func(clus *integration.ClusterV3) { + testRevisionMonotonicWithFailures(t, 11*time.Second, func(clus *integration.Cluster) { for i := 0; i < 5; i++ { leader := clus.WaitLeader(t) time.Sleep(time.Second) @@ -40,7 +40,7 @@ func TestRevisionMonotonicWithLeaderPartitions(t *testing.T) { } func TestRevisionMonotonicWithPartitions(t *testing.T) { - testRevisionMonotonicWithFailures(t, 11*time.Second, func(clus *integration.ClusterV3) { + testRevisionMonotonicWithFailures(t, 11*time.Second, func(clus *integration.Cluster) { for i := 0; i < 5; i++ { time.Sleep(time.Second) clus.Members[i%3].InjectPartition(t, clus.Members[(i+1)%3], clus.Members[(i+2)%3]) @@ -51,7 +51,7 @@ func TestRevisionMonotonicWithPartitions(t *testing.T) { } func TestRevisionMonotonicWithLeaderRestarts(t *testing.T) { - testRevisionMonotonicWithFailures(t, 11*time.Second, func(clus *integration.ClusterV3) { + testRevisionMonotonicWithFailures(t, 11*time.Second, func(clus *integration.Cluster) { for i := 0; i < 5; i++ { leader := clus.WaitLeader(t) time.Sleep(time.Second) @@ -63,7 +63,7 @@ func TestRevisionMonotonicWithLeaderRestarts(t *testing.T) { } func TestRevisionMonotonicWithRestarts(t *testing.T) { - testRevisionMonotonicWithFailures(t, 11*time.Second, func(clus *integration.ClusterV3) { + testRevisionMonotonicWithFailures(t, 11*time.Second, func(clus *integration.Cluster) { for i := 0; i < 5; i++ { time.Sleep(time.Second) clus.Members[i%3].Stop(t) @@ -73,9 +73,9 @@ func TestRevisionMonotonicWithRestarts(t *testing.T) { }) } -func testRevisionMonotonicWithFailures(t *testing.T, testDuration time.Duration, injectFailures func(clus *integration.ClusterV3)) { +func testRevisionMonotonicWithFailures(t *testing.T, testDuration time.Duration, injectFailures func(clus *integration.Cluster)) { integration.BeforeTest(t) - clus := integration.NewClusterV3(t, &integration.ClusterConfig{Size: 3, UseBridge: true}) + clus := integration.NewCluster(t, &integration.ClusterConfig{Size: 3, UseBridge: true}) defer clus.Terminate(t) ctx, cancel := context.WithTimeout(context.Background(), testDuration) @@ -108,7 +108,7 @@ func testRevisionMonotonicWithFailures(t *testing.T, testDuration time.Duration, t.Logf("Revision %d", resp.Header.Revision) } -func putWorker(t *testing.T, ctx context.Context, clus *integration.ClusterV3) { +func putWorker(t *testing.T, ctx context.Context, clus *integration.Cluster) { for i := 0; ; i++ { kv := clus.Client(i % 3) _, err := kv.Put(ctx, "foo", fmt.Sprintf("%d", i)) @@ -121,7 +121,7 @@ func putWorker(t *testing.T, ctx context.Context, clus *integration.ClusterV3) { } } -func getWorker(t *testing.T, ctx context.Context, clus *integration.ClusterV3) { +func getWorker(t *testing.T, ctx context.Context, clus *integration.Cluster) { var prevRev int64 for i := 0; ; i++ { kv := clus.Client(i % 3) diff --git a/tests/integration/clientv3/connectivity/black_hole_test.go b/tests/integration/clientv3/connectivity/black_hole_test.go index 6519f76ab1c0..befe703869c7 100644 --- a/tests/integration/clientv3/connectivity/black_hole_test.go +++ b/tests/integration/clientv3/connectivity/black_hole_test.go @@ -35,7 +35,7 @@ import ( func TestBalancerUnderBlackholeKeepAliveWatch(t *testing.T) { integration2.BeforeTest(t) - clus := integration2.NewClusterV3(t, &integration2.ClusterConfig{ + clus := integration2.NewCluster(t, &integration2.ClusterConfig{ Size: 2, GRPCKeepAliveMinTime: time.Millisecond, // avoid too_many_pings UseBridge: true, @@ -168,7 +168,7 @@ func TestBalancerUnderBlackholeNoKeepAliveSerializableGet(t *testing.T) { func testBalancerUnderBlackholeNoKeepAlive(t *testing.T, op func(*clientv3.Client, context.Context) error) { integration2.BeforeTest(t) - clus := integration2.NewClusterV3(t, &integration2.ClusterConfig{ + clus := integration2.NewCluster(t, &integration2.ClusterConfig{ Size: 2, UseBridge: true, }) diff --git a/tests/integration/clientv3/connectivity/dial_test.go b/tests/integration/clientv3/connectivity/dial_test.go index 2742ad32517f..7f6babe0448a 100644 --- a/tests/integration/clientv3/connectivity/dial_test.go +++ b/tests/integration/clientv3/connectivity/dial_test.go @@ -48,7 +48,7 @@ var ( // TestDialTLSExpired tests client with expired certs fails to dial. func TestDialTLSExpired(t *testing.T) { integration2.BeforeTest(t) - clus := integration2.NewClusterV3(t, &integration2.ClusterConfig{Size: 1, PeerTLS: &testTLSInfo, ClientTLS: &testTLSInfo}) + clus := integration2.NewCluster(t, &integration2.ClusterConfig{Size: 1, PeerTLS: &testTLSInfo, ClientTLS: &testTLSInfo}) defer clus.Terminate(t) tls, err := testTLSInfoExpired.ClientConfig() @@ -71,7 +71,7 @@ func TestDialTLSExpired(t *testing.T) { // when TLS endpoints (https, unixs) are given but no tls config. func TestDialTLSNoConfig(t *testing.T) { integration2.BeforeTest(t) - clus := integration2.NewClusterV3(t, &integration2.ClusterConfig{Size: 1, ClientTLS: &testTLSInfo}) + clus := integration2.NewCluster(t, &integration2.ClusterConfig{Size: 1, ClientTLS: &testTLSInfo}) defer clus.Terminate(t) // expect "signed by unknown authority" c, err := integration2.NewClient(t, clientv3.Config{ @@ -102,7 +102,7 @@ func TestDialSetEndpointsAfterFail(t *testing.T) { // testDialSetEndpoints ensures SetEndpoints can replace unavailable endpoints with available ones. func testDialSetEndpoints(t *testing.T, setBefore bool) { integration2.BeforeTest(t) - clus := integration2.NewClusterV3(t, &integration2.ClusterConfig{Size: 3}) + clus := integration2.NewCluster(t, &integration2.ClusterConfig{Size: 3}) defer clus.Terminate(t) // get endpoint list @@ -145,7 +145,7 @@ func testDialSetEndpoints(t *testing.T, setBefore bool) { // with a new one that doesn't include original endpoint. func TestSwitchSetEndpoints(t *testing.T) { integration2.BeforeTest(t) - clus := integration2.NewClusterV3(t, &integration2.ClusterConfig{Size: 3}) + clus := integration2.NewCluster(t, &integration2.ClusterConfig{Size: 3}) defer clus.Terminate(t) // get non partitioned members endpoints @@ -166,7 +166,7 @@ func TestSwitchSetEndpoints(t *testing.T) { func TestRejectOldCluster(t *testing.T) { integration2.BeforeTest(t) // 2 endpoints to test multi-endpoint Status - clus := integration2.NewClusterV3(t, &integration2.ClusterConfig{Size: 2}) + clus := integration2.NewCluster(t, &integration2.ClusterConfig{Size: 2}) defer clus.Terminate(t) cfg := clientv3.Config{ @@ -186,7 +186,7 @@ func TestRejectOldCluster(t *testing.T) { // with the balancer can be dialed. func TestDialForeignEndpoint(t *testing.T) { integration2.BeforeTest(t) - clus := integration2.NewClusterV3(t, &integration2.ClusterConfig{Size: 2}) + clus := integration2.NewCluster(t, &integration2.ClusterConfig{Size: 2}) defer clus.Terminate(t) conn, err := clus.Client(0).Dial(clus.Client(1).Endpoints()[0]) @@ -209,7 +209,7 @@ func TestDialForeignEndpoint(t *testing.T) { // to a working endpoint will always succeed. func TestSetEndpointAndPut(t *testing.T) { integration2.BeforeTest(t) - clus := integration2.NewClusterV3(t, &integration2.ClusterConfig{Size: 2}) + clus := integration2.NewCluster(t, &integration2.ClusterConfig{Size: 2}) defer clus.Terminate(t) clus.Client(1).SetEndpoints(clus.Members[0].GRPCURL()) diff --git a/tests/integration/clientv3/connectivity/network_partition_test.go b/tests/integration/clientv3/connectivity/network_partition_test.go index 9e3600e03b8a..7e01773e06da 100644 --- a/tests/integration/clientv3/connectivity/network_partition_test.go +++ b/tests/integration/clientv3/connectivity/network_partition_test.go @@ -105,7 +105,7 @@ func TestBalancerUnderNetworkPartitionSerializableGet(t *testing.T) { func testBalancerUnderNetworkPartition(t *testing.T, op func(*clientv3.Client, context.Context) error, timeout time.Duration) { integration2.BeforeTest(t) - clus := integration2.NewClusterV3(t, &integration2.ClusterConfig{ + clus := integration2.NewCluster(t, &integration2.ClusterConfig{ Size: 3, }) defer clus.Terminate(t) @@ -160,7 +160,7 @@ func testBalancerUnderNetworkPartition(t *testing.T, op func(*clientv3.Client, c func TestBalancerUnderNetworkPartitionLinearizableGetLeaderElection(t *testing.T) { integration2.BeforeTest(t) - clus := integration2.NewClusterV3(t, &integration2.ClusterConfig{ + clus := integration2.NewCluster(t, &integration2.ClusterConfig{ Size: 3, }) defer clus.Terminate(t) @@ -214,7 +214,7 @@ func TestBalancerUnderNetworkPartitionWatchFollower(t *testing.T) { func testBalancerUnderNetworkPartitionWatch(t *testing.T, isolateLeader bool) { integration2.BeforeTest(t) - clus := integration2.NewClusterV3(t, &integration2.ClusterConfig{ + clus := integration2.NewCluster(t, &integration2.ClusterConfig{ Size: 3, }) defer clus.Terminate(t) @@ -273,7 +273,7 @@ func testBalancerUnderNetworkPartitionWatch(t *testing.T, isolateLeader bool) { func TestDropReadUnderNetworkPartition(t *testing.T) { integration2.BeforeTest(t) - clus := integration2.NewClusterV3(t, &integration2.ClusterConfig{ + clus := integration2.NewCluster(t, &integration2.ClusterConfig{ Size: 3, }) defer clus.Terminate(t) diff --git a/tests/integration/clientv3/connectivity/server_shutdown_test.go b/tests/integration/clientv3/connectivity/server_shutdown_test.go index f175782a8695..4cc4fb9c0587 100644 --- a/tests/integration/clientv3/connectivity/server_shutdown_test.go +++ b/tests/integration/clientv3/connectivity/server_shutdown_test.go @@ -32,7 +32,7 @@ import ( func TestBalancerUnderServerShutdownWatch(t *testing.T) { integration2.BeforeTest(t) - clus := integration2.NewClusterV3(t, &integration2.ClusterConfig{ + clus := integration2.NewCluster(t, &integration2.ClusterConfig{ Size: 3, UseBridge: true, }) @@ -144,7 +144,7 @@ func TestBalancerUnderServerShutdownTxn(t *testing.T) { func testBalancerUnderServerShutdownMutable(t *testing.T, op func(*clientv3.Client, context.Context) error) { integration2.BeforeTest(t) - clus := integration2.NewClusterV3(t, &integration2.ClusterConfig{ + clus := integration2.NewCluster(t, &integration2.ClusterConfig{ Size: 3, }) defer clus.Terminate(t) @@ -201,7 +201,7 @@ func TestBalancerUnderServerShutdownGetSerializable(t *testing.T) { func testBalancerUnderServerShutdownImmutable(t *testing.T, op func(*clientv3.Client, context.Context) error, timeout time.Duration) { integration2.BeforeTest(t) - clus := integration2.NewClusterV3(t, &integration2.ClusterConfig{ + clus := integration2.NewCluster(t, &integration2.ClusterConfig{ Size: 3, }) defer clus.Terminate(t) @@ -281,7 +281,7 @@ func testBalancerUnderServerStopInflightRangeOnRestart(t *testing.T, linearizabl cfg.Size = 3 } - clus := integration2.NewClusterV3(t, cfg) + clus := integration2.NewCluster(t, cfg) defer clus.Terminate(t) eps := []string{clus.Members[0].GRPCURL(), clus.Members[1].GRPCURL()} if linearizable { diff --git a/tests/integration/clientv3/experimental/recipes/v3_barrier_test.go b/tests/integration/clientv3/experimental/recipes/v3_barrier_test.go index 5692db140123..e20885614cc9 100644 --- a/tests/integration/clientv3/experimental/recipes/v3_barrier_test.go +++ b/tests/integration/clientv3/experimental/recipes/v3_barrier_test.go @@ -25,14 +25,14 @@ import ( func TestBarrierSingleNode(t *testing.T) { integration2.BeforeTest(t) - clus := integration2.NewClusterV3(t, &integration2.ClusterConfig{Size: 1}) + clus := integration2.NewCluster(t, &integration2.ClusterConfig{Size: 1}) defer clus.Terminate(t) testBarrier(t, 5, func() *clientv3.Client { return clus.Client(0) }) } func TestBarrierMultiNode(t *testing.T) { integration2.BeforeTest(t) - clus := integration2.NewClusterV3(t, &integration2.ClusterConfig{Size: 3}) + clus := integration2.NewCluster(t, &integration2.ClusterConfig{Size: 3}) defer clus.Terminate(t) testBarrier(t, 5, func() *clientv3.Client { return clus.RandClient() }) } diff --git a/tests/integration/clientv3/experimental/recipes/v3_double_barrier_test.go b/tests/integration/clientv3/experimental/recipes/v3_double_barrier_test.go index e886b90b4b10..d9ffb9e82b53 100644 --- a/tests/integration/clientv3/experimental/recipes/v3_double_barrier_test.go +++ b/tests/integration/clientv3/experimental/recipes/v3_double_barrier_test.go @@ -26,7 +26,7 @@ import ( func TestDoubleBarrier(t *testing.T) { integration2.BeforeTest(t) - clus := integration2.NewClusterV3(t, &integration2.ClusterConfig{Size: 3}) + clus := integration2.NewCluster(t, &integration2.ClusterConfig{Size: 3}) defer clus.Terminate(t) waiters := 10 @@ -100,7 +100,7 @@ func TestDoubleBarrier(t *testing.T) { func TestDoubleBarrierFailover(t *testing.T) { integration2.BeforeTest(t) - clus := integration2.NewClusterV3(t, &integration2.ClusterConfig{Size: 3}) + clus := integration2.NewCluster(t, &integration2.ClusterConfig{Size: 3}) defer clus.Terminate(t) waiters := 10 diff --git a/tests/integration/clientv3/experimental/recipes/v3_lock_test.go b/tests/integration/clientv3/experimental/recipes/v3_lock_test.go index cc873adf2fda..ee130679bd02 100644 --- a/tests/integration/clientv3/experimental/recipes/v3_lock_test.go +++ b/tests/integration/clientv3/experimental/recipes/v3_lock_test.go @@ -30,7 +30,7 @@ import ( func TestMutexLockSingleNode(t *testing.T) { integration2.BeforeTest(t) - clus := integration2.NewClusterV3(t, &integration2.ClusterConfig{Size: 3}) + clus := integration2.NewCluster(t, &integration2.ClusterConfig{Size: 3}) defer clus.Terminate(t) var clients []*clientv3.Client @@ -41,7 +41,7 @@ func TestMutexLockSingleNode(t *testing.T) { func TestMutexLockMultiNode(t *testing.T) { integration2.BeforeTest(t) - clus := integration2.NewClusterV3(t, &integration2.ClusterConfig{Size: 3}) + clus := integration2.NewCluster(t, &integration2.ClusterConfig{Size: 3}) defer clus.Terminate(t) var clients []*clientv3.Client @@ -94,7 +94,7 @@ func testMutexLock(t *testing.T, waiters int, chooseClient func() *clientv3.Clie func TestMutexTryLockSingleNode(t *testing.T) { integration2.BeforeTest(t) - clus := integration2.NewClusterV3(t, &integration2.ClusterConfig{Size: 3}) + clus := integration2.NewCluster(t, &integration2.ClusterConfig{Size: 3}) defer clus.Terminate(t) var clients []*clientv3.Client @@ -104,7 +104,7 @@ func TestMutexTryLockSingleNode(t *testing.T) { func TestMutexTryLockMultiNode(t *testing.T) { integration2.BeforeTest(t) - clus := integration2.NewClusterV3(t, &integration2.ClusterConfig{Size: 3}) + clus := integration2.NewCluster(t, &integration2.ClusterConfig{Size: 3}) defer clus.Terminate(t) var clients []*clientv3.Client @@ -165,7 +165,7 @@ func testMutexTryLock(t *testing.T, lockers int, chooseClient func() *clientv3.C func TestMutexSessionRelock(t *testing.T) { integration2.BeforeTest(t) - clus := integration2.NewClusterV3(t, &integration2.ClusterConfig{Size: 3}) + clus := integration2.NewCluster(t, &integration2.ClusterConfig{Size: 3}) defer clus.Terminate(t) session, err := concurrency.NewSession(clus.RandClient()) if err != nil { @@ -189,7 +189,7 @@ func TestMutexSessionRelock(t *testing.T) { func TestMutexWaitsOnCurrentHolder(t *testing.T) { integration2.BeforeTest(t) - clus := integration2.NewClusterV3(t, &integration2.ClusterConfig{Size: 1}) + clus := integration2.NewCluster(t, &integration2.ClusterConfig{Size: 1}) defer clus.Terminate(t) cctx := context.Background() @@ -297,7 +297,7 @@ func TestMutexWaitsOnCurrentHolder(t *testing.T) { func BenchmarkMutex4Waiters(b *testing.B) { integration2.BeforeTest(b) // XXX switch tests to use TB interface - clus := integration2.NewClusterV3(nil, &integration2.ClusterConfig{Size: 3}) + clus := integration2.NewCluster(nil, &integration2.ClusterConfig{Size: 3}) defer clus.Terminate(nil) for i := 0; i < b.N; i++ { testMutexLock(nil, 4, func() *clientv3.Client { return clus.RandClient() }) @@ -306,14 +306,14 @@ func BenchmarkMutex4Waiters(b *testing.B) { func TestRWMutexSingleNode(t *testing.T) { integration2.BeforeTest(t) - clus := integration2.NewClusterV3(t, &integration2.ClusterConfig{Size: 3}) + clus := integration2.NewCluster(t, &integration2.ClusterConfig{Size: 3}) defer clus.Terminate(t) testRWMutex(t, 5, func() *clientv3.Client { return clus.Client(0) }) } func TestRWMutexMultiNode(t *testing.T) { integration2.BeforeTest(t) - clus := integration2.NewClusterV3(t, &integration2.ClusterConfig{Size: 3}) + clus := integration2.NewCluster(t, &integration2.ClusterConfig{Size: 3}) defer clus.Terminate(t) testRWMutex(t, 5, func() *clientv3.Client { return clus.RandClient() }) } diff --git a/tests/integration/clientv3/experimental/recipes/v3_queue_test.go b/tests/integration/clientv3/experimental/recipes/v3_queue_test.go index 112d55e1f747..22d01545e63a 100644 --- a/tests/integration/clientv3/experimental/recipes/v3_queue_test.go +++ b/tests/integration/clientv3/experimental/recipes/v3_queue_test.go @@ -33,7 +33,7 @@ const ( func TestQueueOneReaderOneWriter(t *testing.T) { integration2.BeforeTest(t) - clus := integration2.NewClusterV3(t, &integration2.ClusterConfig{Size: 1}) + clus := integration2.NewCluster(t, &integration2.ClusterConfig{Size: 1}) defer clus.Terminate(t) done := make(chan struct{}) @@ -81,7 +81,7 @@ func BenchmarkQueue(b *testing.B) { integration2.BeforeTest(b) // XXX switch tests to use TB interface - clus := integration2.NewClusterV3(nil, &integration2.ClusterConfig{Size: 3}) + clus := integration2.NewCluster(nil, &integration2.ClusterConfig{Size: 3}) defer clus.Terminate(nil) for i := 0; i < b.N; i++ { testQueueNReaderMWriter(nil, manyQueueClients, manyQueueClients) @@ -92,7 +92,7 @@ func BenchmarkQueue(b *testing.B) { func TestPrQueueOneReaderOneWriter(t *testing.T) { integration2.BeforeTest(t) - clus := integration2.NewClusterV3(t, &integration2.ClusterConfig{Size: 1}) + clus := integration2.NewCluster(t, &integration2.ClusterConfig{Size: 1}) defer clus.Terminate(t) // write out five items with random priority @@ -126,7 +126,7 @@ func TestPrQueueOneReaderOneWriter(t *testing.T) { func TestPrQueueManyReaderManyWriter(t *testing.T) { integration2.BeforeTest(t) - clus := integration2.NewClusterV3(t, &integration2.ClusterConfig{Size: 3}) + clus := integration2.NewCluster(t, &integration2.ClusterConfig{Size: 3}) defer clus.Terminate(t) rqs := newPriorityQueues(clus, manyQueueClients) wqs := newPriorityQueues(clus, manyQueueClients) @@ -138,7 +138,7 @@ func BenchmarkPrQueueOneReaderOneWriter(b *testing.B) { integration2.BeforeTest(b) // XXX switch tests to use TB interface - clus := integration2.NewClusterV3(nil, &integration2.ClusterConfig{Size: 3}) + clus := integration2.NewCluster(nil, &integration2.ClusterConfig{Size: 3}) defer clus.Terminate(nil) rqs := newPriorityQueues(clus, 1) wqs := newPriorityQueues(clus, 1) @@ -149,12 +149,12 @@ func BenchmarkPrQueueOneReaderOneWriter(b *testing.B) { func testQueueNReaderMWriter(t *testing.T, n int, m int) { integration2.BeforeTest(t) - clus := integration2.NewClusterV3(t, &integration2.ClusterConfig{Size: 3}) + clus := integration2.NewCluster(t, &integration2.ClusterConfig{Size: 3}) defer clus.Terminate(t) testReadersWriters(t, newQueues(clus, n), newQueues(clus, m)) } -func newQueues(clus *integration2.ClusterV3, n int) (qs []testQueue) { +func newQueues(clus *integration2.Cluster, n int) (qs []testQueue) { for i := 0; i < n; i++ { etcdc := clus.RandClient() qs = append(qs, recipe.NewQueue(etcdc, "q")) @@ -162,7 +162,7 @@ func newQueues(clus *integration2.ClusterV3, n int) (qs []testQueue) { return qs } -func newPriorityQueues(clus *integration2.ClusterV3, n int) (qs []testQueue) { +func newPriorityQueues(clus *integration2.Cluster, n int) (qs []testQueue) { for i := 0; i < n; i++ { etcdc := clus.RandClient() q := &flatPriorityQueue{recipe.NewPriorityQueue(etcdc, "prq")} diff --git a/tests/integration/clientv3/kv_test.go b/tests/integration/clientv3/kv_test.go index 43cd50fc9b84..27c7d9329ae9 100644 --- a/tests/integration/clientv3/kv_test.go +++ b/tests/integration/clientv3/kv_test.go @@ -42,7 +42,7 @@ func TestKVPutError(t *testing.T) { maxReqBytes = 1.5 * 1024 * 1024 // hard coded max in v3_server.go quota = int64(int(maxReqBytes*1.2) + 8*os.Getpagesize()) // make sure we have enough overhead in backend quota. See discussion in #6486. ) - clus := integration2.NewClusterV3(t, &integration2.ClusterConfig{Size: 1, QuotaBackendBytes: quota, ClientMaxCallSendMsgSize: 100 * 1024 * 1024}) + clus := integration2.NewCluster(t, &integration2.ClusterConfig{Size: 1, QuotaBackendBytes: quota, ClientMaxCallSendMsgSize: 100 * 1024 * 1024}) defer clus.Terminate(t) kv := clus.RandClient() @@ -74,7 +74,7 @@ func TestKVPutError(t *testing.T) { func TestKVPut(t *testing.T) { integration2.BeforeTest(t) - clus := integration2.NewClusterV3(t, &integration2.ClusterConfig{Size: 3}) + clus := integration2.NewCluster(t, &integration2.ClusterConfig{Size: 3}) defer clus.Terminate(t) lapi := clus.RandClient() @@ -119,7 +119,7 @@ func TestKVPut(t *testing.T) { func TestKVPutWithIgnoreValue(t *testing.T) { integration2.BeforeTest(t) - clus := integration2.NewClusterV3(t, &integration2.ClusterConfig{Size: 1}) + clus := integration2.NewCluster(t, &integration2.ClusterConfig{Size: 1}) defer clus.Terminate(t) kv := clus.RandClient() @@ -152,7 +152,7 @@ func TestKVPutWithIgnoreValue(t *testing.T) { func TestKVPutWithIgnoreLease(t *testing.T) { integration2.BeforeTest(t) - clus := integration2.NewClusterV3(t, &integration2.ClusterConfig{Size: 1}) + clus := integration2.NewCluster(t, &integration2.ClusterConfig{Size: 1}) defer clus.Terminate(t) kv := clus.RandClient() @@ -191,7 +191,7 @@ func TestKVPutWithIgnoreLease(t *testing.T) { func TestKVPutWithRequireLeader(t *testing.T) { integration2.BeforeTest(t) - clus := integration2.NewClusterV3(t, &integration2.ClusterConfig{Size: 3}) + clus := integration2.NewCluster(t, &integration2.ClusterConfig{Size: 3}) defer clus.Terminate(t) clus.Members[1].Stop(t) @@ -237,7 +237,7 @@ func TestKVPutWithRequireLeader(t *testing.T) { func TestKVRange(t *testing.T) { integration2.BeforeTest(t) - clus := integration2.NewClusterV3(t, &integration2.ClusterConfig{Size: 3}) + clus := integration2.NewCluster(t, &integration2.ClusterConfig{Size: 3}) defer clus.Terminate(t) kv := clus.RandClient() @@ -466,7 +466,7 @@ func TestKVRange(t *testing.T) { func TestKVGetErrConnClosed(t *testing.T) { integration2.BeforeTest(t) - clus := integration2.NewClusterV3(t, &integration2.ClusterConfig{Size: 1}) + clus := integration2.NewCluster(t, &integration2.ClusterConfig{Size: 1}) defer clus.Terminate(t) cli := clus.Client(0) @@ -495,7 +495,7 @@ func TestKVGetErrConnClosed(t *testing.T) { func TestKVNewAfterClose(t *testing.T) { integration2.BeforeTest(t) - clus := integration2.NewClusterV3(t, &integration2.ClusterConfig{Size: 1}) + clus := integration2.NewCluster(t, &integration2.ClusterConfig{Size: 1}) defer clus.Terminate(t) cli := clus.Client(0) @@ -522,7 +522,7 @@ func TestKVNewAfterClose(t *testing.T) { func TestKVDeleteRange(t *testing.T) { integration2.BeforeTest(t) - clus := integration2.NewClusterV3(t, &integration2.ClusterConfig{Size: 3}) + clus := integration2.NewCluster(t, &integration2.ClusterConfig{Size: 3}) defer clus.Terminate(t) kv := clus.RandClient() @@ -594,7 +594,7 @@ func TestKVDeleteRange(t *testing.T) { func TestKVDelete(t *testing.T) { integration2.BeforeTest(t) - clus := integration2.NewClusterV3(t, &integration2.ClusterConfig{Size: 3}) + clus := integration2.NewCluster(t, &integration2.ClusterConfig{Size: 3}) defer clus.Terminate(t) kv := clus.RandClient() @@ -626,7 +626,7 @@ func TestKVDelete(t *testing.T) { func TestKVCompactError(t *testing.T) { integration2.BeforeTest(t) - clus := integration2.NewClusterV3(t, &integration2.ClusterConfig{Size: 1}) + clus := integration2.NewCluster(t, &integration2.ClusterConfig{Size: 1}) defer clus.Terminate(t) kv := clus.RandClient() @@ -656,7 +656,7 @@ func TestKVCompactError(t *testing.T) { func TestKVCompact(t *testing.T) { integration2.BeforeTest(t) - clus := integration2.NewClusterV3(t, &integration2.ClusterConfig{Size: 3}) + clus := integration2.NewCluster(t, &integration2.ClusterConfig{Size: 3}) defer clus.Terminate(t) kv := clus.RandClient() @@ -712,7 +712,7 @@ func TestKVGetRetry(t *testing.T) { integration2.BeforeTest(t) clusterSize := 3 - clus := integration2.NewClusterV3(t, &integration2.ClusterConfig{Size: clusterSize, UseBridge: true}) + clus := integration2.NewCluster(t, &integration2.ClusterConfig{Size: clusterSize, UseBridge: true}) defer clus.Terminate(t) // because killing leader and following election @@ -765,7 +765,7 @@ func TestKVGetRetry(t *testing.T) { func TestKVPutFailGetRetry(t *testing.T) { integration2.BeforeTest(t) - clus := integration2.NewClusterV3(t, &integration2.ClusterConfig{Size: 3, UseBridge: true}) + clus := integration2.NewCluster(t, &integration2.ClusterConfig{Size: 3, UseBridge: true}) defer clus.Terminate(t) kv := clus.Client(0) @@ -805,7 +805,7 @@ func TestKVPutFailGetRetry(t *testing.T) { func TestKVGetCancel(t *testing.T) { integration2.BeforeTest(t) - clus := integration2.NewClusterV3(t, &integration2.ClusterConfig{Size: 1}) + clus := integration2.NewCluster(t, &integration2.ClusterConfig{Size: 1}) defer clus.Terminate(t) oldconn := clus.Client(0).ActiveConnection() @@ -828,7 +828,7 @@ func TestKVGetCancel(t *testing.T) { func TestKVGetStoppedServerAndClose(t *testing.T) { integration2.BeforeTest(t) - clus := integration2.NewClusterV3(t, &integration2.ClusterConfig{Size: 1}) + clus := integration2.NewCluster(t, &integration2.ClusterConfig{Size: 1}) defer clus.Terminate(t) cli := clus.Client(0) @@ -846,7 +846,7 @@ func TestKVGetStoppedServerAndClose(t *testing.T) { func TestKVPutStoppedServerAndClose(t *testing.T) { integration2.BeforeTest(t) - clus := integration2.NewClusterV3(t, &integration2.ClusterConfig{Size: 1}) + clus := integration2.NewCluster(t, &integration2.ClusterConfig{Size: 1}) defer clus.Terminate(t) cli := clus.Client(0) @@ -876,7 +876,7 @@ func TestKVPutStoppedServerAndClose(t *testing.T) { // in the presence of network errors. func TestKVPutAtMostOnce(t *testing.T) { integration2.BeforeTest(t) - clus := integration2.NewClusterV3(t, &integration2.ClusterConfig{Size: 1, UseBridge: true}) + clus := integration2.NewCluster(t, &integration2.ClusterConfig{Size: 1, UseBridge: true}) defer clus.Terminate(t) if _, err := clus.Client(0).Put(context.TODO(), "k", "1"); err != nil { @@ -970,7 +970,7 @@ func TestKVLargeRequests(t *testing.T) { }, } for i, test := range tests { - clus := integration2.NewClusterV3(t, + clus := integration2.NewCluster(t, &integration2.ClusterConfig{ Size: 1, MaxRequestBytes: test.maxRequestBytesServer, @@ -1005,7 +1005,7 @@ func TestKVLargeRequests(t *testing.T) { func TestKVForLearner(t *testing.T) { integration2.BeforeTest(t) - clus := integration2.NewClusterV3(t, &integration2.ClusterConfig{Size: 3}) + clus := integration2.NewCluster(t, &integration2.ClusterConfig{Size: 3}) defer clus.Terminate(t) // we have to add and launch learner member after initial cluster was created, because @@ -1084,7 +1084,7 @@ func TestKVForLearner(t *testing.T) { func TestBalancerSupportLearner(t *testing.T) { integration2.BeforeTest(t) - clus := integration2.NewClusterV3(t, &integration2.ClusterConfig{Size: 3}) + clus := integration2.NewCluster(t, &integration2.ClusterConfig{Size: 3}) defer clus.Terminate(t) // we have to add and launch learner member after initial cluster was created, because diff --git a/tests/integration/clientv3/lease/lease_test.go b/tests/integration/clientv3/lease/lease_test.go index d06cffe059d5..7dc6bbf4f3dc 100644 --- a/tests/integration/clientv3/lease/lease_test.go +++ b/tests/integration/clientv3/lease/lease_test.go @@ -32,7 +32,7 @@ import ( func TestLeaseNotFoundError(t *testing.T) { integration2.BeforeTest(t) - clus := integration2.NewClusterV3(t, &integration2.ClusterConfig{Size: 1}) + clus := integration2.NewCluster(t, &integration2.ClusterConfig{Size: 1}) defer clus.Terminate(t) kv := clus.RandClient() @@ -46,7 +46,7 @@ func TestLeaseNotFoundError(t *testing.T) { func TestLeaseGrant(t *testing.T) { integration2.BeforeTest(t) - clus := integration2.NewClusterV3(t, &integration2.ClusterConfig{Size: 3}) + clus := integration2.NewCluster(t, &integration2.ClusterConfig{Size: 3}) defer clus.Terminate(t) lapi := clus.RandClient() @@ -72,7 +72,7 @@ func TestLeaseGrant(t *testing.T) { func TestLeaseRevoke(t *testing.T) { integration2.BeforeTest(t) - clus := integration2.NewClusterV3(t, &integration2.ClusterConfig{Size: 3}) + clus := integration2.NewCluster(t, &integration2.ClusterConfig{Size: 3}) defer clus.Terminate(t) lapi := clus.RandClient() @@ -98,7 +98,7 @@ func TestLeaseRevoke(t *testing.T) { func TestLeaseKeepAliveOnce(t *testing.T) { integration2.BeforeTest(t) - clus := integration2.NewClusterV3(t, &integration2.ClusterConfig{Size: 3}) + clus := integration2.NewCluster(t, &integration2.ClusterConfig{Size: 3}) defer clus.Terminate(t) lapi := clus.RandClient() @@ -122,7 +122,7 @@ func TestLeaseKeepAliveOnce(t *testing.T) { func TestLeaseKeepAlive(t *testing.T) { integration2.BeforeTest(t) - clus := integration2.NewClusterV3(t, &integration2.ClusterConfig{Size: 3}) + clus := integration2.NewCluster(t, &integration2.ClusterConfig{Size: 3}) defer clus.Terminate(t) lapi := clus.Client(0) @@ -162,7 +162,7 @@ func TestLeaseKeepAlive(t *testing.T) { func TestLeaseKeepAliveOneSecond(t *testing.T) { integration2.BeforeTest(t) - clus := integration2.NewClusterV3(t, &integration2.ClusterConfig{Size: 1}) + clus := integration2.NewCluster(t, &integration2.ClusterConfig{Size: 1}) defer clus.Terminate(t) cli := clus.Client(0) @@ -190,7 +190,7 @@ func TestLeaseKeepAliveHandleFailure(t *testing.T) { integration2.BeforeTest(t) - clus := integration2.NewClusterV3(t, &integration2.ClusterConfig{Size: 3, UseBridge: true}) + clus := integration2.NewCluster(t, &integration2.ClusterConfig{Size: 3, UseBridge: true}) defer clus.Terminate(t) // TODO: change this line to get a cluster client @@ -245,7 +245,7 @@ type leaseCh struct { func TestLeaseKeepAliveNotFound(t *testing.T) { integration2.BeforeTest(t) - clus := integration2.NewClusterV3(t, &integration2.ClusterConfig{Size: 1}) + clus := integration2.NewCluster(t, &integration2.ClusterConfig{Size: 1}) defer clus.Terminate(t) cli := clus.RandClient() @@ -278,7 +278,7 @@ func TestLeaseKeepAliveNotFound(t *testing.T) { func TestLeaseGrantErrConnClosed(t *testing.T) { integration2.BeforeTest(t) - clus := integration2.NewClusterV3(t, &integration2.ClusterConfig{Size: 1}) + clus := integration2.NewCluster(t, &integration2.ClusterConfig{Size: 1}) defer clus.Terminate(t) cli := clus.Client(0) @@ -310,7 +310,7 @@ func TestLeaseGrantErrConnClosed(t *testing.T) { func TestLeaseKeepAliveFullResponseQueue(t *testing.T) { integration2.BeforeTest(t) - clus := integration2.NewClusterV3(t, &integration2.ClusterConfig{Size: 1}) + clus := integration2.NewCluster(t, &integration2.ClusterConfig{Size: 1}) defer clus.Terminate(t) lapi := clus.Client(0) @@ -350,7 +350,7 @@ func TestLeaseKeepAliveFullResponseQueue(t *testing.T) { func TestLeaseGrantNewAfterClose(t *testing.T) { integration2.BeforeTest(t) - clus := integration2.NewClusterV3(t, &integration2.ClusterConfig{Size: 1}) + clus := integration2.NewCluster(t, &integration2.ClusterConfig{Size: 1}) defer clus.Terminate(t) cli := clus.Client(0) @@ -377,7 +377,7 @@ func TestLeaseGrantNewAfterClose(t *testing.T) { func TestLeaseRevokeNewAfterClose(t *testing.T) { integration2.BeforeTest(t) - clus := integration2.NewClusterV3(t, &integration2.ClusterConfig{Size: 1}) + clus := integration2.NewCluster(t, &integration2.ClusterConfig{Size: 1}) defer clus.Terminate(t) cli := clus.Client(0) @@ -416,7 +416,7 @@ func TestLeaseRevokeNewAfterClose(t *testing.T) { func TestLeaseKeepAliveCloseAfterDisconnectRevoke(t *testing.T) { integration2.BeforeTest(t) - clus := integration2.NewClusterV3(t, &integration2.ClusterConfig{Size: 3, UseBridge: true}) + clus := integration2.NewCluster(t, &integration2.ClusterConfig{Size: 3, UseBridge: true}) defer clus.Terminate(t) cli := clus.Client(0) @@ -462,7 +462,7 @@ func TestLeaseKeepAliveCloseAfterDisconnectRevoke(t *testing.T) { func TestLeaseKeepAliveInitTimeout(t *testing.T) { integration2.BeforeTest(t) - clus := integration2.NewClusterV3(t, &integration2.ClusterConfig{Size: 1, UseBridge: true}) + clus := integration2.NewCluster(t, &integration2.ClusterConfig{Size: 1, UseBridge: true}) defer clus.Terminate(t) cli := clus.Client(0) @@ -495,7 +495,7 @@ func TestLeaseKeepAliveInitTimeout(t *testing.T) { func TestLeaseKeepAliveTTLTimeout(t *testing.T) { integration2.BeforeTest(t) - clus := integration2.NewClusterV3(t, &integration2.ClusterConfig{Size: 1, UseBridge: true}) + clus := integration2.NewCluster(t, &integration2.ClusterConfig{Size: 1, UseBridge: true}) defer clus.Terminate(t) cli := clus.Client(0) @@ -530,7 +530,7 @@ func TestLeaseKeepAliveTTLTimeout(t *testing.T) { func TestLeaseTimeToLive(t *testing.T) { integration2.BeforeTest(t) - clus := integration2.NewClusterV3(t, &integration2.ClusterConfig{Size: 3, UseBridge: true}) + clus := integration2.NewCluster(t, &integration2.ClusterConfig{Size: 3, UseBridge: true}) defer clus.Terminate(t) c := clus.RandClient() @@ -588,7 +588,7 @@ func TestLeaseTimeToLive(t *testing.T) { func TestLeaseTimeToLiveLeaseNotFound(t *testing.T) { integration2.BeforeTest(t) - clus := integration2.NewClusterV3(t, &integration2.ClusterConfig{Size: 1}) + clus := integration2.NewCluster(t, &integration2.ClusterConfig{Size: 1}) defer clus.Terminate(t) cli := clus.RandClient() @@ -623,7 +623,7 @@ func TestLeaseTimeToLiveLeaseNotFound(t *testing.T) { func TestLeaseLeases(t *testing.T) { integration2.BeforeTest(t) - clus := integration2.NewClusterV3(t, &integration2.ClusterConfig{Size: 1}) + clus := integration2.NewCluster(t, &integration2.ClusterConfig{Size: 1}) defer clus.Terminate(t) cli := clus.RandClient() @@ -656,7 +656,7 @@ func TestLeaseLeases(t *testing.T) { func TestLeaseRenewLostQuorum(t *testing.T) { integration2.BeforeTest(t) - clus := integration2.NewClusterV3(t, &integration2.ClusterConfig{Size: 3, UseBridge: true}) + clus := integration2.NewCluster(t, &integration2.ClusterConfig{Size: 3, UseBridge: true}) defer clus.Terminate(t) cli := clus.Client(0) @@ -704,7 +704,7 @@ func TestLeaseRenewLostQuorum(t *testing.T) { func TestLeaseKeepAliveLoopExit(t *testing.T) { integration2.BeforeTest(t) - clus := integration2.NewClusterV3(t, &integration2.ClusterConfig{Size: 1}) + clus := integration2.NewCluster(t, &integration2.ClusterConfig{Size: 1}) defer clus.Terminate(t) ctx := context.Background() @@ -728,7 +728,7 @@ func TestLeaseKeepAliveLoopExit(t *testing.T) { // transient cluster failure. func TestV3LeaseFailureOverlap(t *testing.T) { integration2.BeforeTest(t) - clus := integration2.NewClusterV3(t, &integration2.ClusterConfig{Size: 2, UseBridge: true}) + clus := integration2.NewCluster(t, &integration2.ClusterConfig{Size: 2, UseBridge: true}) defer clus.Terminate(t) numReqs := 5 @@ -782,7 +782,7 @@ func TestV3LeaseFailureOverlap(t *testing.T) { func TestLeaseWithRequireLeader(t *testing.T) { integration2.BeforeTest(t) - clus := integration2.NewClusterV3(t, &integration2.ClusterConfig{Size: 2, UseBridge: true}) + clus := integration2.NewCluster(t, &integration2.ClusterConfig{Size: 2, UseBridge: true}) defer clus.Terminate(t) c := clus.Client(0) diff --git a/tests/integration/clientv3/lease/leasing_test.go b/tests/integration/clientv3/lease/leasing_test.go index 60bd02719596..55a2a4bb8496 100644 --- a/tests/integration/clientv3/lease/leasing_test.go +++ b/tests/integration/clientv3/lease/leasing_test.go @@ -34,7 +34,7 @@ import ( func TestLeasingPutGet(t *testing.T) { integration2.BeforeTest(t) - clus := integration2.NewClusterV3(t, &integration2.ClusterConfig{Size: 3}) + clus := integration2.NewCluster(t, &integration2.ClusterConfig{Size: 3}) defer clus.Terminate(t) lKV1, closeLKV1, err := leasing.NewKV(clus.Client(0), "foo/") @@ -92,7 +92,7 @@ func TestLeasingPutGet(t *testing.T) { // TestLeasingInterval checks the leasing KV fetches key intervals. func TestLeasingInterval(t *testing.T) { integration2.BeforeTest(t) - clus := integration2.NewClusterV3(t, &integration2.ClusterConfig{Size: 1}) + clus := integration2.NewCluster(t, &integration2.ClusterConfig{Size: 1}) defer clus.Terminate(t) lkv, closeLKV, err := leasing.NewKV(clus.Client(0), "pfx/") @@ -131,7 +131,7 @@ func TestLeasingInterval(t *testing.T) { // TestLeasingPutInvalidateNew checks the leasing KV updates its cache on a Put to a new key. func TestLeasingPutInvalidateNew(t *testing.T) { integration2.BeforeTest(t) - clus := integration2.NewClusterV3(t, &integration2.ClusterConfig{Size: 1}) + clus := integration2.NewCluster(t, &integration2.ClusterConfig{Size: 1}) defer clus.Terminate(t) lkv, closeLKV, err := leasing.NewKV(clus.Client(0), "pfx/") @@ -161,7 +161,7 @@ func TestLeasingPutInvalidateNew(t *testing.T) { // TestLeasingPutInvalidateExisting checks the leasing KV updates its cache on a Put to an existing key. func TestLeasingPutInvalidateExisting(t *testing.T) { integration2.BeforeTest(t) - clus := integration2.NewClusterV3(t, &integration2.ClusterConfig{Size: 1}) + clus := integration2.NewCluster(t, &integration2.ClusterConfig{Size: 1}) defer clus.Terminate(t) if _, err := clus.Client(0).Put(context.TODO(), "k", "abc"); err != nil { @@ -195,7 +195,7 @@ func TestLeasingPutInvalidateExisting(t *testing.T) { // TestLeasingGetNoLeaseTTL checks a key with a TTL is not leased. func TestLeasingGetNoLeaseTTL(t *testing.T) { integration2.BeforeTest(t) - clus := integration2.NewClusterV3(t, &integration2.ClusterConfig{Size: 1, UseBridge: true}) + clus := integration2.NewCluster(t, &integration2.ClusterConfig{Size: 1, UseBridge: true}) defer clus.Terminate(t) lkv, closeLKV, err := leasing.NewKV(clus.Client(0), "pfx/") @@ -224,7 +224,7 @@ func TestLeasingGetNoLeaseTTL(t *testing.T) { // when the etcd cluster is partitioned. func TestLeasingGetSerializable(t *testing.T) { integration2.BeforeTest(t) - clus := integration2.NewClusterV3(t, &integration2.ClusterConfig{Size: 2, UseBridge: true}) + clus := integration2.NewCluster(t, &integration2.ClusterConfig{Size: 2, UseBridge: true}) defer clus.Terminate(t) lkv, closeLKV, err := leasing.NewKV(clus.Client(0), "pfx/") @@ -264,7 +264,7 @@ func TestLeasingGetSerializable(t *testing.T) { // TestLeasingPrevKey checks the cache respects WithPrevKV on puts. func TestLeasingPrevKey(t *testing.T) { integration2.BeforeTest(t) - clus := integration2.NewClusterV3(t, &integration2.ClusterConfig{Size: 2}) + clus := integration2.NewCluster(t, &integration2.ClusterConfig{Size: 2}) defer clus.Terminate(t) lkv, closeLKV, err := leasing.NewKV(clus.Client(0), "pfx/") @@ -290,7 +290,7 @@ func TestLeasingPrevKey(t *testing.T) { // TestLeasingRevGet checks the cache respects Get by Revision. func TestLeasingRevGet(t *testing.T) { integration2.BeforeTest(t) - clus := integration2.NewClusterV3(t, &integration2.ClusterConfig{Size: 1}) + clus := integration2.NewCluster(t, &integration2.ClusterConfig{Size: 1}) defer clus.Terminate(t) lkv, closeLKV, err := leasing.NewKV(clus.Client(0), "pfx/") @@ -326,7 +326,7 @@ func TestLeasingRevGet(t *testing.T) { // TestLeasingGetWithOpts checks options that can be served through the cache do not depend on the server. func TestLeasingGetWithOpts(t *testing.T) { integration2.BeforeTest(t) - clus := integration2.NewClusterV3(t, &integration2.ClusterConfig{Size: 1, UseBridge: true}) + clus := integration2.NewCluster(t, &integration2.ClusterConfig{Size: 1, UseBridge: true}) defer clus.Terminate(t) lkv, closeLKV, err := leasing.NewKV(clus.Client(0), "pfx/") @@ -371,7 +371,7 @@ func TestLeasingGetWithOpts(t *testing.T) { // the recently put data. func TestLeasingConcurrentPut(t *testing.T) { integration2.BeforeTest(t) - clus := integration2.NewClusterV3(t, &integration2.ClusterConfig{Size: 1}) + clus := integration2.NewCluster(t, &integration2.ClusterConfig{Size: 1}) defer clus.Terminate(t) lkv, closeLKV, err := leasing.NewKV(clus.Client(0), "pfx/") @@ -418,7 +418,7 @@ func TestLeasingConcurrentPut(t *testing.T) { func TestLeasingDisconnectedGet(t *testing.T) { integration2.BeforeTest(t) - clus := integration2.NewClusterV3(t, &integration2.ClusterConfig{Size: 1, UseBridge: true}) + clus := integration2.NewCluster(t, &integration2.ClusterConfig{Size: 1, UseBridge: true}) defer clus.Terminate(t) lkv, closeLKV, err := leasing.NewKV(clus.Client(0), "pfx/") @@ -447,7 +447,7 @@ func TestLeasingDisconnectedGet(t *testing.T) { func TestLeasingDeleteOwner(t *testing.T) { integration2.BeforeTest(t) - clus := integration2.NewClusterV3(t, &integration2.ClusterConfig{Size: 1}) + clus := integration2.NewCluster(t, &integration2.ClusterConfig{Size: 1}) defer clus.Terminate(t) lkv, closeLKV, err := leasing.NewKV(clus.Client(0), "pfx/") @@ -481,7 +481,7 @@ func TestLeasingDeleteOwner(t *testing.T) { func TestLeasingDeleteNonOwner(t *testing.T) { integration2.BeforeTest(t) - clus := integration2.NewClusterV3(t, &integration2.ClusterConfig{Size: 1}) + clus := integration2.NewCluster(t, &integration2.ClusterConfig{Size: 1}) defer clus.Terminate(t) lkv1, closeLKV1, err := leasing.NewKV(clus.Client(0), "pfx/") @@ -516,7 +516,7 @@ func TestLeasingDeleteNonOwner(t *testing.T) { func TestLeasingOverwriteResponse(t *testing.T) { integration2.BeforeTest(t) - clus := integration2.NewClusterV3(t, &integration2.ClusterConfig{Size: 1}) + clus := integration2.NewCluster(t, &integration2.ClusterConfig{Size: 1}) defer clus.Terminate(t) lkv, closeLKV, err := leasing.NewKV(clus.Client(0), "pfx/") @@ -550,7 +550,7 @@ func TestLeasingOverwriteResponse(t *testing.T) { func TestLeasingOwnerPutResponse(t *testing.T) { integration2.BeforeTest(t) - clus := integration2.NewClusterV3(t, &integration2.ClusterConfig{Size: 1, UseBridge: true}) + clus := integration2.NewCluster(t, &integration2.ClusterConfig{Size: 1, UseBridge: true}) defer clus.Terminate(t) lkv, closeLKV, err := leasing.NewKV(clus.Client(0), "pfx/") @@ -588,7 +588,7 @@ func TestLeasingOwnerPutResponse(t *testing.T) { func TestLeasingTxnOwnerGetRange(t *testing.T) { integration2.BeforeTest(t) - clus := integration2.NewClusterV3(t, &integration2.ClusterConfig{Size: 1}) + clus := integration2.NewCluster(t, &integration2.ClusterConfig{Size: 1}) defer clus.Terminate(t) lkv, closeLKV, err := leasing.NewKV(clus.Client(0), "pfx/") @@ -617,7 +617,7 @@ func TestLeasingTxnOwnerGetRange(t *testing.T) { func TestLeasingTxnOwnerGet(t *testing.T) { integration2.BeforeTest(t) - clus := integration2.NewClusterV3(t, &integration2.ClusterConfig{Size: 1, UseBridge: true}) + clus := integration2.NewCluster(t, &integration2.ClusterConfig{Size: 1, UseBridge: true}) defer clus.Terminate(t) client := clus.Client(0) @@ -703,7 +703,7 @@ func TestLeasingTxnOwnerGet(t *testing.T) { func TestLeasingTxnOwnerDeleteRange(t *testing.T) { integration2.BeforeTest(t) - clus := integration2.NewClusterV3(t, &integration2.ClusterConfig{Size: 1}) + clus := integration2.NewCluster(t, &integration2.ClusterConfig{Size: 1}) defer clus.Terminate(t) lkv, closeLKV, err := leasing.NewKV(clus.Client(0), "pfx/") @@ -742,7 +742,7 @@ func TestLeasingTxnOwnerDeleteRange(t *testing.T) { func TestLeasingTxnOwnerDelete(t *testing.T) { integration2.BeforeTest(t) - clus := integration2.NewClusterV3(t, &integration2.ClusterConfig{Size: 1}) + clus := integration2.NewCluster(t, &integration2.ClusterConfig{Size: 1}) defer clus.Terminate(t) lkv, closeLKV, err := leasing.NewKV(clus.Client(0), "pfx/") @@ -773,7 +773,7 @@ func TestLeasingTxnOwnerDelete(t *testing.T) { func TestLeasingTxnOwnerIf(t *testing.T) { integration2.BeforeTest(t) - clus := integration2.NewClusterV3(t, &integration2.ClusterConfig{Size: 1, UseBridge: true}) + clus := integration2.NewCluster(t, &integration2.ClusterConfig{Size: 1, UseBridge: true}) defer clus.Terminate(t) lkv, closeLKV, err := leasing.NewKV(clus.Client(0), "pfx/") @@ -867,7 +867,7 @@ func TestLeasingTxnOwnerIf(t *testing.T) { func TestLeasingTxnCancel(t *testing.T) { integration2.BeforeTest(t) - clus := integration2.NewClusterV3(t, &integration2.ClusterConfig{Size: 3, UseBridge: true}) + clus := integration2.NewCluster(t, &integration2.ClusterConfig{Size: 3, UseBridge: true}) defer clus.Terminate(t) lkv1, closeLKV1, err := leasing.NewKV(clus.Client(0), "pfx/") @@ -901,7 +901,7 @@ func TestLeasingTxnCancel(t *testing.T) { func TestLeasingTxnNonOwnerPut(t *testing.T) { integration2.BeforeTest(t) - clus := integration2.NewClusterV3(t, &integration2.ClusterConfig{Size: 1}) + clus := integration2.NewCluster(t, &integration2.ClusterConfig{Size: 1}) defer clus.Terminate(t) lkv, closeLKV, err := leasing.NewKV(clus.Client(0), "pfx/") @@ -979,7 +979,7 @@ func TestLeasingTxnNonOwnerPut(t *testing.T) { // issues a random If/{Then,Else} transaction on those keys to one client. func TestLeasingTxnRandIfThenOrElse(t *testing.T) { integration2.BeforeTest(t) - clus := integration2.NewClusterV3(t, &integration2.ClusterConfig{Size: 1}) + clus := integration2.NewCluster(t, &integration2.ClusterConfig{Size: 1}) defer clus.Terminate(t) lkv1, closeLKV1, err1 := leasing.NewKV(clus.Client(0), "pfx/") @@ -1085,7 +1085,7 @@ func TestLeasingTxnRandIfThenOrElse(t *testing.T) { func TestLeasingOwnerPutError(t *testing.T) { integration2.BeforeTest(t) - clus := integration2.NewClusterV3(t, &integration2.ClusterConfig{Size: 1, UseBridge: true}) + clus := integration2.NewCluster(t, &integration2.ClusterConfig{Size: 1, UseBridge: true}) defer clus.Terminate(t) lkv, closeLKV, err := leasing.NewKV(clus.Client(0), "pfx/") @@ -1106,7 +1106,7 @@ func TestLeasingOwnerPutError(t *testing.T) { func TestLeasingOwnerDeleteError(t *testing.T) { integration2.BeforeTest(t) - clus := integration2.NewClusterV3(t, &integration2.ClusterConfig{Size: 1, UseBridge: true}) + clus := integration2.NewCluster(t, &integration2.ClusterConfig{Size: 1, UseBridge: true}) defer clus.Terminate(t) lkv, closeLKV, err := leasing.NewKV(clus.Client(0), "pfx/") @@ -1127,7 +1127,7 @@ func TestLeasingOwnerDeleteError(t *testing.T) { func TestLeasingNonOwnerPutError(t *testing.T) { integration2.BeforeTest(t) - clus := integration2.NewClusterV3(t, &integration2.ClusterConfig{Size: 1, UseBridge: true}) + clus := integration2.NewCluster(t, &integration2.ClusterConfig{Size: 1, UseBridge: true}) defer clus.Terminate(t) lkv, closeLKV, err := leasing.NewKV(clus.Client(0), "pfx/") @@ -1152,7 +1152,7 @@ func TestLeasingOwnerDeleteFrom(t *testing.T) { func testLeasingOwnerDelete(t *testing.T, del clientv3.Op) { integration2.BeforeTest(t) - clus := integration2.NewClusterV3(t, &integration2.ClusterConfig{Size: 1}) + clus := integration2.NewCluster(t, &integration2.ClusterConfig{Size: 1}) defer clus.Terminate(t) lkv, closeLKV, err := leasing.NewKV(clus.Client(0), "0/") @@ -1201,7 +1201,7 @@ func testLeasingOwnerDelete(t *testing.T, del clientv3.Op) { func TestLeasingDeleteRangeBounds(t *testing.T) { integration2.BeforeTest(t) - clus := integration2.NewClusterV3(t, &integration2.ClusterConfig{Size: 1, UseBridge: true}) + clus := integration2.NewCluster(t, &integration2.ClusterConfig{Size: 1, UseBridge: true}) defer clus.Terminate(t) delkv, closeDelKV, err := leasing.NewKV(clus.Client(0), "0/") @@ -1259,7 +1259,7 @@ func TestLeaseDeleteRangeContendDel(t *testing.T) { func testLeasingDeleteRangeContend(t *testing.T, op clientv3.Op) { integration2.BeforeTest(t) - clus := integration2.NewClusterV3(t, &integration2.ClusterConfig{Size: 1}) + clus := integration2.NewCluster(t, &integration2.ClusterConfig{Size: 1}) defer clus.Terminate(t) delkv, closeDelKV, err := leasing.NewKV(clus.Client(0), "0/") @@ -1317,7 +1317,7 @@ func testLeasingDeleteRangeContend(t *testing.T, op clientv3.Op) { func TestLeasingPutGetDeleteConcurrent(t *testing.T) { integration2.BeforeTest(t) - clus := integration2.NewClusterV3(t, &integration2.ClusterConfig{Size: 1}) + clus := integration2.NewCluster(t, &integration2.ClusterConfig{Size: 1}) defer clus.Terminate(t) lkvs := make([]clientv3.KV, 16) @@ -1376,7 +1376,7 @@ func TestLeasingPutGetDeleteConcurrent(t *testing.T) { // disconnected when trying to submit revoke txn. func TestLeasingReconnectOwnerRevoke(t *testing.T) { integration2.BeforeTest(t) - clus := integration2.NewClusterV3(t, &integration2.ClusterConfig{Size: 3, UseBridge: true}) + clus := integration2.NewCluster(t, &integration2.ClusterConfig{Size: 3, UseBridge: true}) defer clus.Terminate(t) lkv1, closeLKV1, err1 := leasing.NewKV(clus.Client(0), "foo/") @@ -1437,7 +1437,7 @@ func TestLeasingReconnectOwnerRevoke(t *testing.T) { // disconnected and the watch is compacted. func TestLeasingReconnectOwnerRevokeCompact(t *testing.T) { integration2.BeforeTest(t) - clus := integration2.NewClusterV3(t, &integration2.ClusterConfig{Size: 3, UseBridge: true}) + clus := integration2.NewCluster(t, &integration2.ClusterConfig{Size: 3, UseBridge: true}) defer clus.Terminate(t) lkv1, closeLKV1, err1 := leasing.NewKV(clus.Client(0), "foo/") @@ -1490,7 +1490,7 @@ func TestLeasingReconnectOwnerRevokeCompact(t *testing.T) { // not cause inconsistency between the server and the client. func TestLeasingReconnectOwnerConsistency(t *testing.T) { integration2.BeforeTest(t) - clus := integration2.NewClusterV3(t, &integration2.ClusterConfig{Size: 1, UseBridge: true}) + clus := integration2.NewCluster(t, &integration2.ClusterConfig{Size: 1, UseBridge: true}) defer clus.Terminate(t) lkv, closeLKV, err := leasing.NewKV(clus.Client(0), "foo/") @@ -1564,7 +1564,7 @@ func TestLeasingReconnectOwnerConsistency(t *testing.T) { func TestLeasingTxnAtomicCache(t *testing.T) { integration2.BeforeTest(t) - clus := integration2.NewClusterV3(t, &integration2.ClusterConfig{Size: 1}) + clus := integration2.NewCluster(t, &integration2.ClusterConfig{Size: 1}) defer clus.Terminate(t) lkv, closeLKV, err := leasing.NewKV(clus.Client(0), "foo/") @@ -1650,7 +1650,7 @@ func TestLeasingTxnAtomicCache(t *testing.T) { // TestLeasingReconnectTxn checks that Txn is resilient to disconnects. func TestLeasingReconnectTxn(t *testing.T) { integration2.BeforeTest(t) - clus := integration2.NewClusterV3(t, &integration2.ClusterConfig{Size: 1, UseBridge: true}) + clus := integration2.NewCluster(t, &integration2.ClusterConfig{Size: 1, UseBridge: true}) defer clus.Terminate(t) lkv, closeLKV, err := leasing.NewKV(clus.Client(0), "foo/") @@ -1686,7 +1686,7 @@ func TestLeasingReconnectTxn(t *testing.T) { // not cause inconsistency between the server and the client. func TestLeasingReconnectNonOwnerGet(t *testing.T) { integration2.BeforeTest(t) - clus := integration2.NewClusterV3(t, &integration2.ClusterConfig{Size: 1, UseBridge: true}) + clus := integration2.NewCluster(t, &integration2.ClusterConfig{Size: 1, UseBridge: true}) defer clus.Terminate(t) lkv, closeLKV, err := leasing.NewKV(clus.Client(0), "foo/") @@ -1737,7 +1737,7 @@ func TestLeasingReconnectNonOwnerGet(t *testing.T) { func TestLeasingTxnRangeCmp(t *testing.T) { integration2.BeforeTest(t) - clus := integration2.NewClusterV3(t, &integration2.ClusterConfig{Size: 1}) + clus := integration2.NewCluster(t, &integration2.ClusterConfig{Size: 1}) defer clus.Terminate(t) lkv, closeLKV, err := leasing.NewKV(clus.Client(0), "foo/") @@ -1772,7 +1772,7 @@ func TestLeasingTxnRangeCmp(t *testing.T) { func TestLeasingDo(t *testing.T) { integration2.BeforeTest(t) - clus := integration2.NewClusterV3(t, &integration2.ClusterConfig{Size: 1}) + clus := integration2.NewCluster(t, &integration2.ClusterConfig{Size: 1}) defer clus.Terminate(t) lkv, closeLKV, err := leasing.NewKV(clus.Client(0), "foo/") @@ -1814,7 +1814,7 @@ func TestLeasingDo(t *testing.T) { func TestLeasingTxnOwnerPutBranch(t *testing.T) { integration2.BeforeTest(t) - clus := integration2.NewClusterV3(t, &integration2.ClusterConfig{Size: 3, UseBridge: true}) + clus := integration2.NewCluster(t, &integration2.ClusterConfig{Size: 3, UseBridge: true}) defer clus.Terminate(t) lkv, closeLKV, err := leasing.NewKV(clus.Client(0), "foo/") @@ -1908,7 +1908,7 @@ func randCmps(pfx string, dat []*clientv3.PutResponse) (cmps []clientv3.Cmp, the func TestLeasingSessionExpire(t *testing.T) { integration2.BeforeTest(t) - clus := integration2.NewClusterV3(t, &integration2.ClusterConfig{Size: 3, UseBridge: true}) + clus := integration2.NewCluster(t, &integration2.ClusterConfig{Size: 3, UseBridge: true}) defer clus.Terminate(t) lkv, closeLKV, err := leasing.NewKV(clus.Client(0), "foo/", concurrency.WithTTL(1)) @@ -1984,7 +1984,7 @@ func TestLeasingSessionExpireCancel(t *testing.T) { for i := range tests { t.Run(fmt.Sprintf("test %d", i), func(t *testing.T) { integration2.BeforeTest(t) - clus := integration2.NewClusterV3(t, &integration2.ClusterConfig{Size: 3, UseBridge: true}) + clus := integration2.NewCluster(t, &integration2.ClusterConfig{Size: 3, UseBridge: true}) defer clus.Terminate(t) lkv, closeLKV, err := leasing.NewKV(clus.Client(0), "foo/", concurrency.WithTTL(1)) diff --git a/tests/integration/clientv3/maintenance_test.go b/tests/integration/clientv3/maintenance_test.go index 45bbe8c5c42b..ce1e629c0105 100644 --- a/tests/integration/clientv3/maintenance_test.go +++ b/tests/integration/clientv3/maintenance_test.go @@ -39,7 +39,7 @@ import ( func TestMaintenanceHashKV(t *testing.T) { integration2.BeforeTest(t) - clus := integration2.NewClusterV3(t, &integration2.ClusterConfig{Size: 3}) + clus := integration2.NewCluster(t, &integration2.ClusterConfig{Size: 3}) defer clus.Terminate(t) for i := 0; i < 3; i++ { @@ -72,7 +72,7 @@ func TestMaintenanceHashKV(t *testing.T) { func TestMaintenanceMoveLeader(t *testing.T) { integration2.BeforeTest(t) - clus := integration2.NewClusterV3(t, &integration2.ClusterConfig{Size: 3}) + clus := integration2.NewCluster(t, &integration2.ClusterConfig{Size: 3}) defer clus.Terminate(t) oldLeadIdx := clus.WaitLeader(t) @@ -103,7 +103,7 @@ func TestMaintenanceMoveLeader(t *testing.T) { func TestMaintenanceSnapshotCancel(t *testing.T) { integration2.BeforeTest(t) - clus := integration2.NewClusterV3(t, &integration2.ClusterConfig{Size: 1}) + clus := integration2.NewCluster(t, &integration2.ClusterConfig{Size: 1}) defer clus.Terminate(t) // reading snapshot with canceled context should error out @@ -146,7 +146,7 @@ func TestMaintenanceSnapshotTimeout(t *testing.T) { func testMaintenanceSnapshotTimeout(t *testing.T, snapshot func(context.Context, *clientv3.Client) (io.ReadCloser, error)) { integration2.BeforeTest(t) - clus := integration2.NewClusterV3(t, &integration2.ClusterConfig{Size: 1}) + clus := integration2.NewCluster(t, &integration2.ClusterConfig{Size: 1}) defer clus.Terminate(t) // reading snapshot with deadline exceeded should error out @@ -191,7 +191,7 @@ func TestMaintenanceSnapshotErrorInflight(t *testing.T) { func testMaintenanceSnapshotErrorInflight(t *testing.T, snapshot func(context.Context, *clientv3.Client) (io.ReadCloser, error)) { integration2.BeforeTest(t) - clus := integration2.NewClusterV3(t, &integration2.ClusterConfig{Size: 1, UseBridge: true}) + clus := integration2.NewCluster(t, &integration2.ClusterConfig{Size: 1, UseBridge: true}) defer clus.Terminate(t) // take about 1-second to read snapshot @@ -249,7 +249,7 @@ func TestMaintenanceSnapshotWithVersionVersion(t *testing.T) { integration2.BeforeTest(t) // Set SnapshotCount to 1 to force raft snapshot to ensure that storage version is set - clus := integration2.NewClusterV3(t, &integration2.ClusterConfig{Size: 1, SnapshotCount: 1}) + clus := integration2.NewCluster(t, &integration2.ClusterConfig{Size: 1, SnapshotCount: 1}) defer clus.Terminate(t) // Put some keys to ensure that wal snapshot is triggered @@ -271,7 +271,7 @@ func TestMaintenanceSnapshotWithVersionVersion(t *testing.T) { func TestMaintenanceStatus(t *testing.T) { integration2.BeforeTest(t) - clus := integration2.NewClusterV3(t, &integration2.ClusterConfig{Size: 3}) + clus := integration2.NewCluster(t, &integration2.ClusterConfig{Size: 3}) defer clus.Terminate(t) clus.WaitLeader(t) diff --git a/tests/integration/clientv3/metrics_test.go b/tests/integration/clientv3/metrics_test.go index 0c3db3dcadcf..26b24b29530c 100644 --- a/tests/integration/clientv3/metrics_test.go +++ b/tests/integration/clientv3/metrics_test.go @@ -70,7 +70,7 @@ func TestV3ClientMetrics(t *testing.T) { url := "unix://" + addr + "/metrics" - clus := integration2.NewClusterV3(t, &integration2.ClusterConfig{Size: 1}) + clus := integration2.NewCluster(t, &integration2.ClusterConfig{Size: 1}) defer clus.Terminate(t) cfg := clientv3.Config{ diff --git a/tests/integration/clientv3/mirror_test.go b/tests/integration/clientv3/mirror_test.go index 36dc71dcc2e8..f21551bbdf08 100644 --- a/tests/integration/clientv3/mirror_test.go +++ b/tests/integration/clientv3/mirror_test.go @@ -30,7 +30,7 @@ import ( func TestMirrorSync(t *testing.T) { integration2.BeforeTest(t) - clus := integration2.NewClusterV3(t, &integration2.ClusterConfig{Size: 1}) + clus := integration2.NewCluster(t, &integration2.ClusterConfig{Size: 1}) defer clus.Terminate(t) c := clus.Client(0) @@ -74,7 +74,7 @@ func TestMirrorSync(t *testing.T) { func TestMirrorSyncBase(t *testing.T) { integration2.BeforeTest(t) - cluster := integration2.NewClusterV3(t, &integration2.ClusterConfig{Size: 1}) + cluster := integration2.NewCluster(t, &integration2.ClusterConfig{Size: 1}) defer cluster.Terminate(t) cli := cluster.Client(0) diff --git a/tests/integration/clientv3/namespace_test.go b/tests/integration/clientv3/namespace_test.go index 4b76ca34e39e..c214a17dcb59 100644 --- a/tests/integration/clientv3/namespace_test.go +++ b/tests/integration/clientv3/namespace_test.go @@ -28,7 +28,7 @@ import ( func TestNamespacePutGet(t *testing.T) { integration2.BeforeTest(t) - clus := integration2.NewClusterV3(t, &integration2.ClusterConfig{Size: 1}) + clus := integration2.NewCluster(t, &integration2.ClusterConfig{Size: 1}) defer clus.Terminate(t) c := clus.Client(0) @@ -57,7 +57,7 @@ func TestNamespacePutGet(t *testing.T) { func TestNamespaceWatch(t *testing.T) { integration2.BeforeTest(t) - clus := integration2.NewClusterV3(t, &integration2.ClusterConfig{Size: 1}) + clus := integration2.NewCluster(t, &integration2.ClusterConfig{Size: 1}) defer clus.Terminate(t) c := clus.Client(0) diff --git a/tests/integration/clientv3/naming/endpoints_test.go b/tests/integration/clientv3/naming/endpoints_test.go index d5cbbf8cfb74..2225a804beb2 100644 --- a/tests/integration/clientv3/naming/endpoints_test.go +++ b/tests/integration/clientv3/naming/endpoints_test.go @@ -27,7 +27,7 @@ import ( func TestEndpointManager(t *testing.T) { integration2.BeforeTest(t) - clus := integration2.NewClusterV3(t, &integration2.ClusterConfig{Size: 1}) + clus := integration2.NewCluster(t, &integration2.ClusterConfig{Size: 1}) defer clus.Terminate(t) em, err := endpoints.NewManager(clus.RandClient(), "foo") @@ -89,7 +89,7 @@ func TestEndpointManager(t *testing.T) { func TestEndpointManagerAtomicity(t *testing.T) { integration2.BeforeTest(t) - clus := integration2.NewClusterV3(t, &integration2.ClusterConfig{Size: 1}) + clus := integration2.NewCluster(t, &integration2.ClusterConfig{Size: 1}) defer clus.Terminate(t) c := clus.RandClient() @@ -131,7 +131,7 @@ func TestEndpointManagerAtomicity(t *testing.T) { func TestEndpointManagerCRUD(t *testing.T) { integration2.BeforeTest(t) - clus := integration2.NewClusterV3(t, &integration2.ClusterConfig{Size: 1}) + clus := integration2.NewCluster(t, &integration2.ClusterConfig{Size: 1}) defer clus.Terminate(t) em, err := endpoints.NewManager(clus.RandClient(), "foo") diff --git a/tests/integration/clientv3/naming/resolver_test.go b/tests/integration/clientv3/naming/resolver_test.go index 445ebca86d47..1f9d2a5fcb67 100644 --- a/tests/integration/clientv3/naming/resolver_test.go +++ b/tests/integration/clientv3/naming/resolver_test.go @@ -47,7 +47,7 @@ func TestEtcdGrpcResolver(t *testing.T) { } defer s2.Stop() - clus := integration2.NewClusterV3(t, &integration2.ClusterConfig{Size: 3}) + clus := integration2.NewCluster(t, &integration2.ClusterConfig{Size: 3}) defer clus.Terminate(t) em, err := endpoints.NewManager(clus.Client(0), "foo") diff --git a/tests/integration/clientv3/ordering_kv_test.go b/tests/integration/clientv3/ordering_kv_test.go index f213d497c990..93b409303e3a 100644 --- a/tests/integration/clientv3/ordering_kv_test.go +++ b/tests/integration/clientv3/ordering_kv_test.go @@ -30,7 +30,7 @@ func TestDetectKvOrderViolation(t *testing.T) { var errOrderViolation = errors.New("DetectedOrderViolation") integration2.BeforeTest(t) - clus := integration2.NewClusterV3(t, &integration2.ClusterConfig{Size: 3, UseBridge: true}) + clus := integration2.NewCluster(t, &integration2.ClusterConfig{Size: 3, UseBridge: true}) defer clus.Terminate(t) cfg := clientv3.Config{ @@ -97,7 +97,7 @@ func TestDetectTxnOrderViolation(t *testing.T) { var errOrderViolation = errors.New("DetectedOrderViolation") integration2.BeforeTest(t) - clus := integration2.NewClusterV3(t, &integration2.ClusterConfig{Size: 3, UseBridge: true}) + clus := integration2.NewCluster(t, &integration2.ClusterConfig{Size: 3, UseBridge: true}) defer clus.Terminate(t) cfg := clientv3.Config{ diff --git a/tests/integration/clientv3/ordering_util_test.go b/tests/integration/clientv3/ordering_util_test.go index 2fb0c1413f3a..9e2f5ae6d02f 100644 --- a/tests/integration/clientv3/ordering_util_test.go +++ b/tests/integration/clientv3/ordering_util_test.go @@ -26,7 +26,7 @@ import ( func TestEndpointSwitchResolvesViolation(t *testing.T) { integration2.BeforeTest(t) - clus := integration2.NewClusterV3(t, &integration2.ClusterConfig{Size: 3}) + clus := integration2.NewCluster(t, &integration2.ClusterConfig{Size: 3}) defer clus.Terminate(t) eps := []string{ clus.Members[0].GRPCURL(), @@ -82,7 +82,7 @@ func TestEndpointSwitchResolvesViolation(t *testing.T) { func TestUnresolvableOrderViolation(t *testing.T) { integration2.BeforeTest(t) - clus := integration2.NewClusterV3(t, &integration2.ClusterConfig{Size: 5, UseBridge: true}) + clus := integration2.NewCluster(t, &integration2.ClusterConfig{Size: 5, UseBridge: true}) defer clus.Terminate(t) cfg := clientv3.Config{ Endpoints: []string{ diff --git a/tests/integration/clientv3/role_test.go b/tests/integration/clientv3/role_test.go index a10e6f648eb1..38d74d90eb9a 100644 --- a/tests/integration/clientv3/role_test.go +++ b/tests/integration/clientv3/role_test.go @@ -25,7 +25,7 @@ import ( func TestRoleError(t *testing.T) { integration2.BeforeTest(t) - clus := integration2.NewClusterV3(t, &integration2.ClusterConfig{Size: 1}) + clus := integration2.NewCluster(t, &integration2.ClusterConfig{Size: 1}) defer clus.Terminate(t) authapi := clus.RandClient() diff --git a/tests/integration/clientv3/txn_test.go b/tests/integration/clientv3/txn_test.go index b23573605321..b2fa2d997673 100644 --- a/tests/integration/clientv3/txn_test.go +++ b/tests/integration/clientv3/txn_test.go @@ -29,7 +29,7 @@ import ( func TestTxnError(t *testing.T) { integration2.BeforeTest(t) - clus := integration2.NewClusterV3(t, &integration2.ClusterConfig{Size: 1}) + clus := integration2.NewCluster(t, &integration2.ClusterConfig{Size: 1}) defer clus.Terminate(t) kv := clus.RandClient() @@ -53,7 +53,7 @@ func TestTxnError(t *testing.T) { func TestTxnWriteFail(t *testing.T) { integration2.BeforeTest(t) - clus := integration2.NewClusterV3(t, &integration2.ClusterConfig{Size: 3, UseBridge: true}) + clus := integration2.NewCluster(t, &integration2.ClusterConfig{Size: 3, UseBridge: true}) defer clus.Terminate(t) kv := clus.Client(0) @@ -103,7 +103,7 @@ func TestTxnReadRetry(t *testing.T) { integration2.BeforeTest(t) - clus := integration2.NewClusterV3(t, &integration2.ClusterConfig{Size: 3, UseBridge: true}) + clus := integration2.NewCluster(t, &integration2.ClusterConfig{Size: 3, UseBridge: true}) defer clus.Terminate(t) kv := clus.Client(0) @@ -142,7 +142,7 @@ func TestTxnReadRetry(t *testing.T) { func TestTxnSuccess(t *testing.T) { integration2.BeforeTest(t) - clus := integration2.NewClusterV3(t, &integration2.ClusterConfig{Size: 3}) + clus := integration2.NewCluster(t, &integration2.ClusterConfig{Size: 3}) defer clus.Terminate(t) kv := clus.Client(0) @@ -165,7 +165,7 @@ func TestTxnSuccess(t *testing.T) { func TestTxnCompareRange(t *testing.T) { integration2.BeforeTest(t) - clus := integration2.NewClusterV3(t, &integration2.ClusterConfig{Size: 1}) + clus := integration2.NewCluster(t, &integration2.ClusterConfig{Size: 1}) defer clus.Terminate(t) kv := clus.Client(0) @@ -192,7 +192,7 @@ func TestTxnCompareRange(t *testing.T) { func TestTxnNested(t *testing.T) { integration2.BeforeTest(t) - clus := integration2.NewClusterV3(t, &integration2.ClusterConfig{Size: 3}) + clus := integration2.NewCluster(t, &integration2.ClusterConfig{Size: 3}) defer clus.Terminate(t) kv := clus.Client(0) diff --git a/tests/integration/clientv3/user_test.go b/tests/integration/clientv3/user_test.go index f0fe73a73dc1..1cd700fdef04 100644 --- a/tests/integration/clientv3/user_test.go +++ b/tests/integration/clientv3/user_test.go @@ -28,7 +28,7 @@ import ( func TestUserError(t *testing.T) { integration2.BeforeTest(t) - clus := integration2.NewClusterV3(t, &integration2.ClusterConfig{Size: 1}) + clus := integration2.NewCluster(t, &integration2.ClusterConfig{Size: 1}) defer clus.Terminate(t) authapi := clus.RandClient() @@ -57,7 +57,7 @@ func TestUserError(t *testing.T) { func TestUserErrorAuth(t *testing.T) { integration2.BeforeTest(t) - clus := integration2.NewClusterV3(t, &integration2.ClusterConfig{Size: 1}) + clus := integration2.NewCluster(t, &integration2.ClusterConfig{Size: 1}) defer clus.Terminate(t) authapi := clus.RandClient() @@ -114,7 +114,7 @@ func authSetupRoot(t *testing.T, auth clientv3.Auth) { func TestGetTokenWithoutAuth(t *testing.T) { integration2.BeforeTest(t) - clus := integration2.NewClusterV3(t, &integration2.ClusterConfig{Size: 2}) + clus := integration2.NewCluster(t, &integration2.ClusterConfig{Size: 2}) defer clus.Terminate(t) authapi := clus.RandClient() diff --git a/tests/integration/clientv3/watch_fragment_test.go b/tests/integration/clientv3/watch_fragment_test.go index ab2367932e9f..51418d82ffb0 100644 --- a/tests/integration/clientv3/watch_fragment_test.go +++ b/tests/integration/clientv3/watch_fragment_test.go @@ -73,7 +73,7 @@ func testWatchFragment(t *testing.T, fragment, exceedRecvLimit bool) { if exceedRecvLimit { cfg.ClientMaxCallRecvMsgSize = 1.5 * 1024 * 1024 } - clus := integration2.NewClusterV3(t, cfg) + clus := integration2.NewCluster(t, cfg) defer clus.Terminate(t) cli := clus.Client(0) diff --git a/tests/integration/clientv3/watch_test.go b/tests/integration/clientv3/watch_test.go index f7ca77039f99..1d472ecc55ca 100644 --- a/tests/integration/clientv3/watch_test.go +++ b/tests/integration/clientv3/watch_test.go @@ -36,7 +36,7 @@ import ( type watcherTest func(*testing.T, *watchctx) type watchctx struct { - clus *integration2.ClusterV3 + clus *integration2.Cluster w clientv3.Watcher kv clientv3.KV wclientMember int @@ -47,7 +47,7 @@ type watchctx struct { func runWatchTest(t *testing.T, f watcherTest) { integration2.BeforeTest(t) - clus := integration2.NewClusterV3(t, &integration2.ClusterConfig{Size: 3, UseBridge: true}) + clus := integration2.NewCluster(t, &integration2.ClusterConfig{Size: 3, UseBridge: true}) defer clus.Terminate(t) wclientMember := rand.Intn(3) @@ -348,7 +348,7 @@ func putAndWatch(t *testing.T, wctx *watchctx, key, val string) { func TestWatchResumeInitRev(t *testing.T) { integration2.BeforeTest(t) - clus := integration2.NewClusterV3(t, &integration2.ClusterConfig{Size: 1, UseBridge: true}) + clus := integration2.NewCluster(t, &integration2.ClusterConfig{Size: 1, UseBridge: true}) defer clus.Terminate(t) cli := clus.Client(0) @@ -404,7 +404,7 @@ func TestWatchResumeInitRev(t *testing.T) { func TestWatchResumeCompacted(t *testing.T) { integration2.BeforeTest(t) - clus := integration2.NewClusterV3(t, &integration2.ClusterConfig{Size: 3, UseBridge: true}) + clus := integration2.NewCluster(t, &integration2.ClusterConfig{Size: 3, UseBridge: true}) defer clus.Terminate(t) // create a waiting watcher at rev 1 @@ -491,7 +491,7 @@ func TestWatchResumeCompacted(t *testing.T) { func TestWatchCompactRevision(t *testing.T) { integration2.BeforeTest(t) - clus := integration2.NewClusterV3(t, &integration2.ClusterConfig{Size: 1}) + clus := integration2.NewCluster(t, &integration2.ClusterConfig{Size: 1}) defer clus.Terminate(t) // set some keys @@ -540,7 +540,7 @@ func testWatchWithProgressNotify(t *testing.T, watchOnPut bool) { pi := 3 * time.Second defer func() { v3rpc.SetProgressReportInterval(oldpi) }() - clus := integration2.NewClusterV3(t, &integration2.ClusterConfig{Size: 3}) + clus := integration2.NewCluster(t, &integration2.ClusterConfig{Size: 3}) defer clus.Terminate(t) wc := clus.RandClient() @@ -588,7 +588,7 @@ func TestConfigurableWatchProgressNotifyInterval(t *testing.T) { integration2.BeforeTest(t) progressInterval := 200 * time.Millisecond - clus := integration2.NewClusterV3(t, + clus := integration2.NewCluster(t, &integration2.ClusterConfig{ Size: 3, WatchProgressNotifyInterval: progressInterval, @@ -629,7 +629,7 @@ func TestWatchRequestProgress(t *testing.T) { watchTimeout := 3 * time.Second - clus := integration2.NewClusterV3(t, &integration2.ClusterConfig{Size: 3}) + clus := integration2.NewCluster(t, &integration2.ClusterConfig{Size: 3}) defer clus.Terminate(t) wc := clus.RandClient() @@ -688,7 +688,7 @@ func TestWatchRequestProgress(t *testing.T) { func TestWatchEventType(t *testing.T) { integration2.BeforeTest(t) - cluster := integration2.NewClusterV3(t, &integration2.ClusterConfig{Size: 1}) + cluster := integration2.NewCluster(t, &integration2.ClusterConfig{Size: 1}) defer cluster.Terminate(t) client := cluster.RandClient() @@ -762,7 +762,7 @@ func TestWatchEventType(t *testing.T) { func TestWatchErrConnClosed(t *testing.T) { integration2.BeforeTest(t) - clus := integration2.NewClusterV3(t, &integration2.ClusterConfig{Size: 1}) + clus := integration2.NewCluster(t, &integration2.ClusterConfig{Size: 1}) defer clus.Terminate(t) cli := clus.Client(0) @@ -792,7 +792,7 @@ func TestWatchErrConnClosed(t *testing.T) { func TestWatchAfterClose(t *testing.T) { integration2.BeforeTest(t) - clus := integration2.NewClusterV3(t, &integration2.ClusterConfig{Size: 1}) + clus := integration2.NewCluster(t, &integration2.ClusterConfig{Size: 1}) defer clus.Terminate(t) cli := clus.Client(0) @@ -820,7 +820,7 @@ func TestWatchAfterClose(t *testing.T) { func TestWatchWithRequireLeader(t *testing.T) { integration2.BeforeTest(t) - clus := integration2.NewClusterV3(t, &integration2.ClusterConfig{Size: 3}) + clus := integration2.NewCluster(t, &integration2.ClusterConfig{Size: 3}) defer clus.Terminate(t) // Put a key for the non-require leader watch to read as an event. @@ -894,7 +894,7 @@ func TestWatchWithRequireLeader(t *testing.T) { func TestWatchWithFilter(t *testing.T) { integration2.BeforeTest(t) - cluster := integration2.NewClusterV3(t, &integration2.ClusterConfig{Size: 1}) + cluster := integration2.NewCluster(t, &integration2.ClusterConfig{Size: 1}) defer cluster.Terminate(t) client := cluster.RandClient() @@ -933,7 +933,7 @@ func TestWatchWithFilter(t *testing.T) { func TestWatchWithCreatedNotification(t *testing.T) { integration2.BeforeTest(t) - cluster := integration2.NewClusterV3(t, &integration2.ClusterConfig{Size: 1}) + cluster := integration2.NewCluster(t, &integration2.ClusterConfig{Size: 1}) defer cluster.Terminate(t) client := cluster.RandClient() @@ -955,7 +955,7 @@ func TestWatchWithCreatedNotification(t *testing.T) { func TestWatchWithCreatedNotificationDropConn(t *testing.T) { integration2.BeforeTest(t) - cluster := integration2.NewClusterV3(t, &integration2.ClusterConfig{Size: 1, UseBridge: true}) + cluster := integration2.NewCluster(t, &integration2.ClusterConfig{Size: 1, UseBridge: true}) defer cluster.Terminate(t) client := cluster.RandClient() @@ -984,7 +984,7 @@ func TestWatchWithCreatedNotificationDropConn(t *testing.T) { func TestWatchCancelOnServer(t *testing.T) { integration2.BeforeTest(t) - cluster := integration2.NewClusterV3(t, &integration2.ClusterConfig{Size: 1}) + cluster := integration2.NewCluster(t, &integration2.ClusterConfig{Size: 1}) defer cluster.Terminate(t) client := cluster.RandClient() @@ -1050,20 +1050,20 @@ func TestWatchCancelOnServer(t *testing.T) { // 4. watcher client finishes tearing down stream on "ctx" // 5. w2 comes back canceled func TestWatchOverlapContextCancel(t *testing.T) { - f := func(clus *integration2.ClusterV3) {} + f := func(clus *integration2.Cluster) {} testWatchOverlapContextCancel(t, f) } func TestWatchOverlapDropConnContextCancel(t *testing.T) { - f := func(clus *integration2.ClusterV3) { + f := func(clus *integration2.Cluster) { clus.Members[0].Bridge().DropConnections() } testWatchOverlapContextCancel(t, f) } -func testWatchOverlapContextCancel(t *testing.T, f func(*integration2.ClusterV3)) { +func testWatchOverlapContextCancel(t *testing.T, f func(*integration2.Cluster)) { integration2.BeforeTest(t) - clus := integration2.NewClusterV3(t, &integration2.ClusterConfig{Size: 1, UseBridge: true}) + clus := integration2.NewCluster(t, &integration2.ClusterConfig{Size: 1, UseBridge: true}) defer clus.Terminate(t) n := 100 @@ -1124,7 +1124,7 @@ func testWatchOverlapContextCancel(t *testing.T, f func(*integration2.ClusterV3) // closing the client does not return a client closing error. func TestWatchCancelAndCloseClient(t *testing.T) { integration2.BeforeTest(t) - clus := integration2.NewClusterV3(t, &integration2.ClusterConfig{Size: 1}) + clus := integration2.NewCluster(t, &integration2.ClusterConfig{Size: 1}) defer clus.Terminate(t) cli := clus.Client(0) ctx, cancel := context.WithCancel(context.Background()) @@ -1154,7 +1154,7 @@ func TestWatchCancelAndCloseClient(t *testing.T) { // then closes the watcher interface to ensure correct clean up. func TestWatchStressResumeClose(t *testing.T) { integration2.BeforeTest(t) - clus := integration2.NewClusterV3(t, &integration2.ClusterConfig{Size: 1, UseBridge: true}) + clus := integration2.NewCluster(t, &integration2.ClusterConfig{Size: 1, UseBridge: true}) defer clus.Terminate(t) cli := clus.Client(0) @@ -1176,7 +1176,7 @@ func TestWatchStressResumeClose(t *testing.T) { // its grpc stream is disconnected / reconnecting. func TestWatchCancelDisconnected(t *testing.T) { integration2.BeforeTest(t) - clus := integration2.NewClusterV3(t, &integration2.ClusterConfig{Size: 1}) + clus := integration2.NewCluster(t, &integration2.ClusterConfig{Size: 1}) defer clus.Terminate(t) cli := clus.Client(0) ctx, cancel := context.WithCancel(context.Background()) diff --git a/tests/integration/cluster_test.go b/tests/integration/cluster_test.go index 5a8730170546..9cd65b40be46 100644 --- a/tests/integration/cluster_test.go +++ b/tests/integration/cluster_test.go @@ -46,14 +46,14 @@ func TestClusterOf3(t *testing.T) { testCluster(t, 3) } func testCluster(t *testing.T, size int) { integration.BeforeTest(t) - c := integration.NewClusterV3(t, &integration.ClusterConfig{Size: size}) + c := integration.NewCluster(t, &integration.ClusterConfig{Size: size}) defer c.Terminate(t) clusterMustProgress(t, c.Members) } func TestTLSClusterOf3(t *testing.T) { integration.BeforeTest(t) - c := integration.NewClusterV3(t, &integration.ClusterConfig{Size: 3, PeerTLS: &integration.TestTLSInfo}) + c := integration.NewCluster(t, &integration.ClusterConfig{Size: 3, PeerTLS: &integration.TestTLSInfo}) defer c.Terminate(t) clusterMustProgress(t, c.Members) } @@ -62,7 +62,7 @@ func TestTLSClusterOf3(t *testing.T) { // authorities that don't issue dual-usage certificates. func TestTLSClusterOf3WithSpecificUsage(t *testing.T) { integration.BeforeTest(t) - c := integration.NewClusterV3(t, &integration.ClusterConfig{Size: 3, PeerTLS: &integration.TestTLSInfoWithSpecificUsage}) + c := integration.NewCluster(t, &integration.ClusterConfig{Size: 3, PeerTLS: &integration.TestTLSInfoWithSpecificUsage}) defer c.Terminate(t) clusterMustProgress(t, c.Members) } @@ -72,7 +72,7 @@ func TestClusterOf3UsingDiscovery(t *testing.T) { testClusterUsingDiscovery(t, 3 func testClusterUsingDiscovery(t *testing.T, size int) { integration.BeforeTest(t) - dc := integration.NewClusterV3(t, &integration.ClusterConfig{Size: 1, UseIP: true}) + dc := integration.NewCluster(t, &integration.ClusterConfig{Size: 1, UseIP: true}) defer dc.Terminate(t) // init discovery token space dcc := integration.MustNewHTTPClient(t, dc.URLs(), nil) @@ -83,14 +83,14 @@ func testClusterUsingDiscovery(t *testing.T, size int) { } cancel() - c := integration.NewClusterV3(t, &integration.ClusterConfig{Size: size, DiscoveryURL: dc.URL(0) + "/v2/keys"}) + c := integration.NewCluster(t, &integration.ClusterConfig{Size: size, DiscoveryURL: dc.URL(0) + "/v2/keys"}) defer c.Terminate(t) clusterMustProgress(t, c.Members) } func TestTLSClusterOf3UsingDiscovery(t *testing.T) { integration.BeforeTest(t) - dc := integration.NewClusterV3(t, &integration.ClusterConfig{Size: 1, UseIP: true}) + dc := integration.NewCluster(t, &integration.ClusterConfig{Size: 1, UseIP: true}) defer dc.Terminate(t) // init discovery token space dcc := integration.MustNewHTTPClient(t, dc.URLs(), nil) @@ -101,7 +101,7 @@ func TestTLSClusterOf3UsingDiscovery(t *testing.T) { } cancel() - c := integration.NewClusterV3(t, &integration.ClusterConfig{ + c := integration.NewCluster(t, &integration.ClusterConfig{ Size: 3, PeerTLS: &integration.TestTLSInfo, DiscoveryURL: dc.URL(0) + "/v2/keys"}, @@ -115,7 +115,7 @@ func TestDoubleClusterSizeOf3(t *testing.T) { testDoubleClusterSize(t, 3) } func testDoubleClusterSize(t *testing.T, size int) { integration.BeforeTest(t) - c := integration.NewClusterV3(t, &integration.ClusterConfig{Size: size}) + c := integration.NewCluster(t, &integration.ClusterConfig{Size: size}) defer c.Terminate(t) for i := 0; i < size; i++ { @@ -126,7 +126,7 @@ func testDoubleClusterSize(t *testing.T, size int) { func TestDoubleTLSClusterSizeOf3(t *testing.T) { integration.BeforeTest(t) - c := integration.NewClusterV3(t, &integration.ClusterConfig{Size: 1, PeerTLS: &integration.TestTLSInfo}) + c := integration.NewCluster(t, &integration.ClusterConfig{Size: 1, PeerTLS: &integration.TestTLSInfo}) defer c.Terminate(t) for i := 0; i < 3; i++ { @@ -140,7 +140,7 @@ func TestDecreaseClusterSizeOf5(t *testing.T) { testDecreaseClusterSize(t, 5) } func testDecreaseClusterSize(t *testing.T, size int) { integration.BeforeTest(t) - c := integration.NewClusterV3(t, &integration.ClusterConfig{Size: size}) + c := integration.NewCluster(t, &integration.ClusterConfig{Size: size}) defer c.Terminate(t) // TODO: remove the last but one member @@ -162,7 +162,7 @@ func testDecreaseClusterSize(t *testing.T, size int) { func TestForceNewCluster(t *testing.T) { integration.BeforeTest(t) - c := integration.NewClusterV3(t, &integration.ClusterConfig{Size: 3, UseBridge: true}) + c := integration.NewCluster(t, &integration.ClusterConfig{Size: 3, UseBridge: true}) defer c.Terminate(t) ctx, cancel := context.WithTimeout(context.Background(), integration.RequestTimeout) @@ -218,7 +218,7 @@ func TestForceNewCluster(t *testing.T) { func TestAddMemberAfterClusterFullRotation(t *testing.T) { integration.BeforeTest(t) - c := integration.NewClusterV3(t, &integration.ClusterConfig{Size: 3}) + c := integration.NewCluster(t, &integration.ClusterConfig{Size: 3}) defer c.Terminate(t) // remove all the previous three members and add in three new members. @@ -239,7 +239,7 @@ func TestAddMemberAfterClusterFullRotation(t *testing.T) { // Ensure we can remove a member then add a new one back immediately. func TestIssue2681(t *testing.T) { integration.BeforeTest(t) - c := integration.NewClusterV3(t, &integration.ClusterConfig{Size: 5}) + c := integration.NewCluster(t, &integration.ClusterConfig{Size: 5}) defer c.Terminate(t) c.MustRemoveMember(t, uint64(c.Members[4].Server.ID())) @@ -258,7 +258,7 @@ func TestIssue2746WithThree(t *testing.T) { testIssue2746(t, 3) } func testIssue2746(t *testing.T, members int) { integration.BeforeTest(t) - c := integration.NewClusterV3(t, &integration.ClusterConfig{Size: members, SnapshotCount: 10}) + c := integration.NewCluster(t, &integration.ClusterConfig{Size: members, SnapshotCount: 10}) defer c.Terminate(t) // force a snapshot @@ -278,7 +278,7 @@ func testIssue2746(t *testing.T, members int) { func TestIssue2904(t *testing.T) { integration.BeforeTest(t) // start 1-member Cluster to ensure member 0 is the leader of the Cluster. - c := integration.NewClusterV3(t, &integration.ClusterConfig{Size: 1, UseBridge: true}) + c := integration.NewCluster(t, &integration.ClusterConfig{Size: 1, UseBridge: true}) defer c.Terminate(t) c.AddMember(t) @@ -314,7 +314,7 @@ func TestIssue2904(t *testing.T) { func TestIssue3699(t *testing.T) { // start a Cluster of 3 nodes a, b, c integration.BeforeTest(t) - c := integration.NewClusterV3(t, &integration.ClusterConfig{Size: 3, UseBridge: true}) + c := integration.NewCluster(t, &integration.ClusterConfig{Size: 3, UseBridge: true}) defer c.Terminate(t) // make node a unavailable @@ -363,7 +363,7 @@ func TestIssue3699(t *testing.T) { // TestRejectUnhealthyAdd ensures an unhealthy cluster rejects adding members. func TestRejectUnhealthyAdd(t *testing.T) { integration.BeforeTest(t) - c := integration.NewClusterV3(t, &integration.ClusterConfig{Size: 3, UseBridge: true, StrictReconfigCheck: true}) + c := integration.NewCluster(t, &integration.ClusterConfig{Size: 3, UseBridge: true, StrictReconfigCheck: true}) defer c.Terminate(t) // make Cluster unhealthy and wait for downed peer @@ -403,7 +403,7 @@ func TestRejectUnhealthyAdd(t *testing.T) { // if quorum will be lost. func TestRejectUnhealthyRemove(t *testing.T) { integration.BeforeTest(t) - c := integration.NewClusterV3(t, &integration.ClusterConfig{Size: 5, UseBridge: true, StrictReconfigCheck: true}) + c := integration.NewCluster(t, &integration.ClusterConfig{Size: 5, UseBridge: true, StrictReconfigCheck: true}) defer c.Terminate(t) // make cluster unhealthy and wait for downed peer; (3 up, 2 down) @@ -448,7 +448,7 @@ func TestRestartRemoved(t *testing.T) { integration.BeforeTest(t) // 1. start single-member Cluster - c := integration.NewClusterV3(t, &integration.ClusterConfig{Size: 1, StrictReconfigCheck: true, UseBridge: true}) + c := integration.NewCluster(t, &integration.ClusterConfig{Size: 1, StrictReconfigCheck: true, UseBridge: true}) defer c.Terminate(t) // 2. add a new member @@ -525,7 +525,7 @@ func clusterMustProgress(t *testing.T, members []*integration.Member) { func TestSpeedyTerminate(t *testing.T) { integration.BeforeTest(t) - clus := integration.NewClusterV3(t, &integration.ClusterConfig{Size: 3, UseBridge: true}) + clus := integration.NewCluster(t, &integration.ClusterConfig{Size: 3, UseBridge: true}) // Stop/Restart so requests will time out on lost leaders for i := 0; i < 3; i++ { clus.Members[i].Stop(t) diff --git a/tests/integration/grpc_test.go b/tests/integration/grpc_test.go index dfa9fadcc4f1..9e30d4c43976 100644 --- a/tests/integration/grpc_test.go +++ b/tests/integration/grpc_test.go @@ -102,7 +102,7 @@ func TestAuthority(t *testing.T) { UseIP: tc.useTCP, } cfg, tlsConfig := setupTLS(t, tc.useTLS, cfg) - clus := integration.NewClusterV3(t, &cfg) + clus := integration.NewCluster(t, &cfg) defer clus.Terminate(t) kv := setupClient(t, tc.clientURLPattern, clus, tlsConfig) @@ -132,7 +132,7 @@ func setupTLS(t *testing.T, useTLS bool, cfg integration.ClusterConfig) (integra return cfg, nil } -func setupClient(t *testing.T, endpointPattern string, clus *integration.ClusterV3, tlsConfig *tls.Config) *clientv3.Client { +func setupClient(t *testing.T, endpointPattern string, clus *integration.Cluster, tlsConfig *tls.Config) *clientv3.Client { t.Helper() endpoints := templateEndpoints(t, endpointPattern, clus) kv, err := clientv3.New(clientv3.Config{ @@ -147,7 +147,7 @@ func setupClient(t *testing.T, endpointPattern string, clus *integration.Cluster return kv } -func templateEndpoints(t *testing.T, pattern string, clus *integration.ClusterV3) []string { +func templateEndpoints(t *testing.T, pattern string, clus *integration.Cluster) []string { t.Helper() endpoints := []string{} for _, m := range clus.Members { @@ -181,7 +181,7 @@ func templateAuthority(t *testing.T, pattern string, m *integration.Member) stri return authority } -func assertAuthority(t *testing.T, expectedAuthority string, clus *integration.ClusterV3) { +func assertAuthority(t *testing.T, expectedAuthority string, clus *integration.Cluster) { t.Helper() requestsFound := 0 for _, m := range clus.Members { diff --git a/tests/integration/lazy_cluster.go b/tests/integration/lazy_cluster.go index e8ac1225d54b..02fc759dc732 100644 --- a/tests/integration/lazy_cluster.go +++ b/tests/integration/lazy_cluster.go @@ -43,7 +43,7 @@ type LazyCluster interface { EndpointsV3() []string // Cluster - calls to this method might initialize the cluster. - Cluster() *integration.ClusterV3 + Cluster() *integration.Cluster // Transport - call to this method might initialize the cluster. Transport() *http.Transport @@ -55,7 +55,7 @@ type LazyCluster interface { type lazyCluster struct { cfg integration.ClusterConfig - cluster *integration.ClusterV3 + cluster *integration.Cluster transport *http.Transport once sync.Once tb testutil.TB @@ -82,7 +82,7 @@ func (lc *lazyCluster) mustLazyInit() { if err != nil { log.Fatal(err) } - lc.cluster = integration.NewClusterV3(lc.tb, &lc.cfg) + lc.cluster = integration.NewCluster(lc.tb, &lc.cfg) }) } @@ -106,7 +106,7 @@ func (lc *lazyCluster) EndpointsV3() []string { return lc.Cluster().Client(0).Endpoints() } -func (lc *lazyCluster) Cluster() *integration.ClusterV3 { +func (lc *lazyCluster) Cluster() *integration.Cluster { lc.mustLazyInit() return lc.cluster } diff --git a/tests/integration/member_test.go b/tests/integration/member_test.go index 0ac006e50bca..f358e771df9c 100644 --- a/tests/integration/member_test.go +++ b/tests/integration/member_test.go @@ -27,7 +27,7 @@ import ( func TestPauseMember(t *testing.T) { integration.BeforeTest(t) - c := integration.NewClusterV3(t, &integration.ClusterConfig{Size: 5}) + c := integration.NewCluster(t, &integration.ClusterConfig{Size: 5}) defer c.Terminate(t) for i := 0; i < 5; i++ { @@ -44,7 +44,7 @@ func TestPauseMember(t *testing.T) { func TestRestartMember(t *testing.T) { integration.BeforeTest(t) - c := integration.NewClusterV3(t, &integration.ClusterConfig{Size: 3, UseBridge: true}) + c := integration.NewCluster(t, &integration.ClusterConfig{Size: 3, UseBridge: true}) defer c.Terminate(t) for i := 0; i < 3; i++ { @@ -65,7 +65,7 @@ func TestRestartMember(t *testing.T) { func TestLaunchDuplicateMemberShouldFail(t *testing.T) { integration.BeforeTest(t) size := 3 - c := integration.NewClusterV3(t, &integration.ClusterConfig{Size: size}) + c := integration.NewCluster(t, &integration.ClusterConfig{Size: size}) m := c.Members[0].Clone(t) var err error m.DataDir, err = os.MkdirTemp(t.TempDir(), "etcd") diff --git a/tests/integration/metrics_test.go b/tests/integration/metrics_test.go index 00efe8b1bbc0..59ce0d1d3772 100644 --- a/tests/integration/metrics_test.go +++ b/tests/integration/metrics_test.go @@ -31,7 +31,7 @@ import ( // TestMetricDbSizeBoot checks that the db size metric is set on boot. func TestMetricDbSizeBoot(t *testing.T) { integration.BeforeTest(t) - clus := integration.NewClusterV3(t, &integration.ClusterConfig{Size: 1}) + clus := integration.NewCluster(t, &integration.ClusterConfig{Size: 1}) defer clus.Terminate(t) v, err := clus.Members[0].Metric("etcd_debugging_mvcc_db_total_size_in_bytes") @@ -51,7 +51,7 @@ func TestMetricDbSizeDefrag(t *testing.T) { // testMetricDbSizeDefrag checks that the db size metric is set after defrag. func testMetricDbSizeDefrag(t *testing.T, name string) { integration.BeforeTest(t) - clus := integration.NewClusterV3(t, &integration.ClusterConfig{Size: 1}) + clus := integration.NewCluster(t, &integration.ClusterConfig{Size: 1}) defer clus.Terminate(t) kvc := integration.ToGRPC(clus.Client(0)).KV @@ -165,7 +165,7 @@ func testMetricDbSizeDefrag(t *testing.T, name string) { func TestMetricQuotaBackendBytes(t *testing.T) { integration.BeforeTest(t) - clus := integration.NewClusterV3(t, &integration.ClusterConfig{Size: 1}) + clus := integration.NewCluster(t, &integration.ClusterConfig{Size: 1}) defer clus.Terminate(t) qs, err := clus.Members[0].Metric("etcd_server_quota_backend_bytes") @@ -183,7 +183,7 @@ func TestMetricQuotaBackendBytes(t *testing.T) { func TestMetricsHealth(t *testing.T) { integration.BeforeTest(t) - clus := integration.NewClusterV3(t, &integration.ClusterConfig{Size: 1}) + clus := integration.NewCluster(t, &integration.ClusterConfig{Size: 1}) defer clus.Terminate(t) tr, err := transport.NewTransport(transport.TLSInfo{}, 5*time.Second) diff --git a/tests/integration/network_partition_test.go b/tests/integration/network_partition_test.go index 9ea4e45343cf..b5d73a30a85b 100644 --- a/tests/integration/network_partition_test.go +++ b/tests/integration/network_partition_test.go @@ -25,7 +25,7 @@ import ( func TestNetworkPartition5MembersLeaderInMinority(t *testing.T) { integration.BeforeTest(t) - clus := integration.NewClusterV3(t, &integration.ClusterConfig{Size: 5}) + clus := integration.NewCluster(t, &integration.ClusterConfig{Size: 5}) defer clus.Terminate(t) leadIndex := clus.WaitLeader(t) @@ -34,8 +34,8 @@ func TestNetworkPartition5MembersLeaderInMinority(t *testing.T) { minority := []int{leadIndex, (leadIndex + 1) % 5} majority := []int{(leadIndex + 2) % 5, (leadIndex + 3) % 5, (leadIndex + 4) % 5} - minorityMembers := getMembersByIndexSlice(clus.Cluster, minority) - majorityMembers := getMembersByIndexSlice(clus.Cluster, majority) + minorityMembers := getMembersByIndexSlice(clus, minority) + majorityMembers := getMembersByIndexSlice(clus, majority) // network partition (bi-directional) injectPartition(t, minorityMembers, majorityMembers) @@ -73,7 +73,7 @@ func TestNetworkPartition5MembersLeaderInMajority(t *testing.T) { func testNetworkPartition5MembersLeaderInMajority(t *testing.T) error { integration.BeforeTest(t) - clus := integration.NewClusterV3(t, &integration.ClusterConfig{Size: 5}) + clus := integration.NewCluster(t, &integration.ClusterConfig{Size: 5}) defer clus.Terminate(t) leadIndex := clus.WaitLeader(t) @@ -82,8 +82,8 @@ func testNetworkPartition5MembersLeaderInMajority(t *testing.T) error { majority := []int{leadIndex, (leadIndex + 1) % 5, (leadIndex + 2) % 5} minority := []int{(leadIndex + 3) % 5, (leadIndex + 4) % 5} - majorityMembers := getMembersByIndexSlice(clus.Cluster, majority) - minorityMembers := getMembersByIndexSlice(clus.Cluster, minority) + majorityMembers := getMembersByIndexSlice(clus, majority) + minorityMembers := getMembersByIndexSlice(clus, minority) // network partition (bi-directional) injectPartition(t, majorityMembers, minorityMembers) @@ -112,7 +112,7 @@ func testNetworkPartition5MembersLeaderInMajority(t *testing.T) error { func TestNetworkPartition4Members(t *testing.T) { integration.BeforeTest(t) - clus := integration.NewClusterV3(t, &integration.ClusterConfig{Size: 4}) + clus := integration.NewCluster(t, &integration.ClusterConfig{Size: 4}) defer clus.Terminate(t) leadIndex := clus.WaitLeader(t) @@ -121,8 +121,8 @@ func TestNetworkPartition4Members(t *testing.T) { groupA := []int{leadIndex, (leadIndex + 1) % 4} groupB := []int{(leadIndex + 2) % 4, (leadIndex + 3) % 4} - leaderPartition := getMembersByIndexSlice(clus.Cluster, groupA) - followerPartition := getMembersByIndexSlice(clus.Cluster, groupB) + leaderPartition := getMembersByIndexSlice(clus, groupA) + followerPartition := getMembersByIndexSlice(clus, groupB) // network partition (bi-directional) injectPartition(t, leaderPartition, followerPartition) diff --git a/tests/integration/proxy/grpcproxy/cluster_test.go b/tests/integration/proxy/grpcproxy/cluster_test.go index 22c6970c8f90..e78d2db662eb 100644 --- a/tests/integration/proxy/grpcproxy/cluster_test.go +++ b/tests/integration/proxy/grpcproxy/cluster_test.go @@ -33,7 +33,7 @@ import ( func TestClusterProxyMemberList(t *testing.T) { integration2.BeforeTest(t) - clus := integration2.NewClusterV3(t, &integration2.ClusterConfig{Size: 1}) + clus := integration2.NewCluster(t, &integration2.ClusterConfig{Size: 1}) defer clus.Terminate(t) cts := newClusterProxyServer(zaptest.NewLogger(t), []string{clus.Members[0].GRPCURL()}, t) diff --git a/tests/integration/proxy/grpcproxy/kv_test.go b/tests/integration/proxy/grpcproxy/kv_test.go index c319c54dd170..a1aacd8cbb7a 100644 --- a/tests/integration/proxy/grpcproxy/kv_test.go +++ b/tests/integration/proxy/grpcproxy/kv_test.go @@ -30,7 +30,7 @@ import ( func TestKVProxyRange(t *testing.T) { integration2.BeforeTest(t) - clus := integration2.NewClusterV3(t, &integration2.ClusterConfig{Size: 1}) + clus := integration2.NewCluster(t, &integration2.ClusterConfig{Size: 1}) defer clus.Terminate(t) kvts := newKVProxyServer([]string{clus.Members[0].GRPCURL()}, t) diff --git a/tests/integration/proxy/grpcproxy/register_test.go b/tests/integration/proxy/grpcproxy/register_test.go index d93000a5e82d..e4f8f004d450 100644 --- a/tests/integration/proxy/grpcproxy/register_test.go +++ b/tests/integration/proxy/grpcproxy/register_test.go @@ -28,7 +28,7 @@ import ( func TestRegister(t *testing.T) { integration2.BeforeTest(t) - clus := integration2.NewClusterV3(t, &integration2.ClusterConfig{Size: 1}) + clus := integration2.NewCluster(t, &integration2.ClusterConfig{Size: 1}) defer clus.Terminate(t) cli := clus.Client(0) paddr := clus.Members[0].GRPCURL() diff --git a/tests/integration/v3_alarm_test.go b/tests/integration/v3_alarm_test.go index 08c0b40821ee..89dc26abd00b 100644 --- a/tests/integration/v3_alarm_test.go +++ b/tests/integration/v3_alarm_test.go @@ -36,7 +36,7 @@ func TestV3StorageQuotaApply(t *testing.T) { integration.BeforeTest(t) quotasize := int64(16 * os.Getpagesize()) - clus := integration.NewClusterV3(t, &integration.ClusterConfig{Size: 2}) + clus := integration.NewCluster(t, &integration.ClusterConfig{Size: 2}) defer clus.Terminate(t) kvc1 := integration.ToGRPC(clus.Client(1)).KV @@ -139,7 +139,7 @@ func TestV3StorageQuotaApply(t *testing.T) { func TestV3AlarmDeactivate(t *testing.T) { integration.BeforeTest(t) - clus := integration.NewClusterV3(t, &integration.ClusterConfig{Size: 3}) + clus := integration.NewCluster(t, &integration.ClusterConfig{Size: 3}) defer clus.Terminate(t) kvc := integration.ToGRPC(clus.RandClient()).KV mt := integration.ToGRPC(clus.RandClient()).Maintenance @@ -172,7 +172,7 @@ func TestV3AlarmDeactivate(t *testing.T) { func TestV3CorruptAlarm(t *testing.T) { integration.BeforeTest(t) - clus := integration.NewClusterV3(t, &integration.ClusterConfig{Size: 3, UseBridge: true}) + clus := integration.NewCluster(t, &integration.ClusterConfig{Size: 3, UseBridge: true}) defer clus.Terminate(t) var wg sync.WaitGroup diff --git a/tests/integration/v3_auth_test.go b/tests/integration/v3_auth_test.go index 5d915a9644e4..4f4e53e97f04 100644 --- a/tests/integration/v3_auth_test.go +++ b/tests/integration/v3_auth_test.go @@ -32,7 +32,7 @@ import ( // TestV3AuthEmptyUserGet ensures that a get with an empty user will return an empty user error. func TestV3AuthEmptyUserGet(t *testing.T) { integration.BeforeTest(t) - clus := integration.NewClusterV3(t, &integration.ClusterConfig{Size: 1}) + clus := integration.NewCluster(t, &integration.ClusterConfig{Size: 1}) defer clus.Terminate(t) ctx, cancel := context.WithTimeout(context.TODO(), 30*time.Second) @@ -51,7 +51,7 @@ func TestV3AuthEmptyUserGet(t *testing.T) { // given a valid token when authentication is disabled func TestV3AuthTokenWithDisable(t *testing.T) { integration.BeforeTest(t) - clus := integration.NewClusterV3(t, &integration.ClusterConfig{Size: 1}) + clus := integration.NewCluster(t, &integration.ClusterConfig{Size: 1}) defer clus.Terminate(t) authSetupRoot(t, integration.ToGRPC(clus.Client(0)).Auth) @@ -83,7 +83,7 @@ func TestV3AuthTokenWithDisable(t *testing.T) { func TestV3AuthRevision(t *testing.T) { integration.BeforeTest(t) - clus := integration.NewClusterV3(t, &integration.ClusterConfig{Size: 1}) + clus := integration.NewCluster(t, &integration.ClusterConfig{Size: 1}) defer clus.Terminate(t) api := integration.ToGRPC(clus.Client(0)) @@ -122,7 +122,7 @@ func TestV3AuthWithLeaseRevokeWithRootJWT(t *testing.T) { func testV3AuthWithLeaseRevokeWithRoot(t *testing.T, ccfg integration.ClusterConfig) { integration.BeforeTest(t) - clus := integration.NewClusterV3(t, &ccfg) + clus := integration.NewCluster(t, &ccfg) defer clus.Terminate(t) api := integration.ToGRPC(clus.Client(0)) @@ -179,7 +179,7 @@ type user struct { func TestV3AuthWithLeaseRevoke(t *testing.T) { integration.BeforeTest(t) - clus := integration.NewClusterV3(t, &integration.ClusterConfig{Size: 1}) + clus := integration.NewCluster(t, &integration.ClusterConfig{Size: 1}) defer clus.Terminate(t) users := []user{ @@ -225,7 +225,7 @@ func TestV3AuthWithLeaseRevoke(t *testing.T) { func TestV3AuthWithLeaseAttach(t *testing.T) { integration.BeforeTest(t) - clus := integration.NewClusterV3(t, &integration.ClusterConfig{Size: 1}) + clus := integration.NewCluster(t, &integration.ClusterConfig{Size: 1}) defer clus.Terminate(t) users := []user{ @@ -337,7 +337,7 @@ func authSetupRoot(t *testing.T, auth pb.AuthClient) { func TestV3AuthNonAuthorizedRPCs(t *testing.T) { integration.BeforeTest(t) - clus := integration.NewClusterV3(t, &integration.ClusterConfig{Size: 1}) + clus := integration.NewCluster(t, &integration.ClusterConfig{Size: 1}) defer clus.Terminate(t) nonAuthedKV := clus.Client(0).KV @@ -360,7 +360,7 @@ func TestV3AuthNonAuthorizedRPCs(t *testing.T) { func TestV3AuthOldRevConcurrent(t *testing.T) { t.Skip() // TODO(jingyih): re-enable the test when #10408 is fixed. integration.BeforeTest(t) - clus := integration.NewClusterV3(t, &integration.ClusterConfig{Size: 1}) + clus := integration.NewCluster(t, &integration.ClusterConfig{Size: 1}) defer clus.Terminate(t) authSetupRoot(t, integration.ToGRPC(clus.Client(0)).Auth) diff --git a/tests/integration/v3_election_test.go b/tests/integration/v3_election_test.go index 761afd1f4615..e7f2ab0005fe 100644 --- a/tests/integration/v3_election_test.go +++ b/tests/integration/v3_election_test.go @@ -28,7 +28,7 @@ import ( // TestElectionWait tests if followers can correctly wait for elections. func TestElectionWait(t *testing.T) { integration.BeforeTest(t) - clus := integration.NewClusterV3(t, &integration.ClusterConfig{Size: 3}) + clus := integration.NewCluster(t, &integration.ClusterConfig{Size: 3}) defer clus.Terminate(t) leaders := 3 @@ -110,7 +110,7 @@ func TestElectionWait(t *testing.T) { // TestElectionFailover tests that an election will func TestElectionFailover(t *testing.T) { integration.BeforeTest(t) - clus := integration.NewClusterV3(t, &integration.ClusterConfig{Size: 3}) + clus := integration.NewCluster(t, &integration.ClusterConfig{Size: 3}) defer clus.Terminate(t) cctx, cancel := context.WithCancel(context.TODO()) @@ -178,7 +178,7 @@ func TestElectionFailover(t *testing.T) { // with the same lock will Proclaim instead of deadlocking. func TestElectionSessionRecampaign(t *testing.T) { integration.BeforeTest(t) - clus := integration.NewClusterV3(t, &integration.ClusterConfig{Size: 1}) + clus := integration.NewCluster(t, &integration.ClusterConfig{Size: 1}) defer clus.Terminate(t) cli := clus.RandClient() @@ -211,7 +211,7 @@ func TestElectionSessionRecampaign(t *testing.T) { // func TestElectionOnPrefixOfExistingKey(t *testing.T) { integration.BeforeTest(t) - clus := integration.NewClusterV3(t, &integration.ClusterConfig{Size: 1}) + clus := integration.NewCluster(t, &integration.ClusterConfig{Size: 1}) defer clus.Terminate(t) cli := clus.RandClient() @@ -238,7 +238,7 @@ func TestElectionOnPrefixOfExistingKey(t *testing.T) { // leadership. func TestElectionOnSessionRestart(t *testing.T) { integration.BeforeTest(t) - clus := integration.NewClusterV3(t, &integration.ClusterConfig{Size: 1}) + clus := integration.NewCluster(t, &integration.ClusterConfig{Size: 1}) defer clus.Terminate(t) cli := clus.RandClient() @@ -285,7 +285,7 @@ func TestElectionOnSessionRestart(t *testing.T) { // a leader key with a modrev less than the compaction revision. func TestElectionObserveCompacted(t *testing.T) { integration.BeforeTest(t) - clus := integration.NewClusterV3(t, &integration.ClusterConfig{Size: 1}) + clus := integration.NewCluster(t, &integration.ClusterConfig{Size: 1}) defer clus.Terminate(t) cli := clus.Client(0) diff --git a/tests/integration/v3_grpc_inflight_test.go b/tests/integration/v3_grpc_inflight_test.go index b96bac45a155..daf5c3bbec4a 100644 --- a/tests/integration/v3_grpc_inflight_test.go +++ b/tests/integration/v3_grpc_inflight_test.go @@ -32,7 +32,7 @@ import ( // does not panic the mvcc backend while defragment is running. func TestV3MaintenanceDefragmentInflightRange(t *testing.T) { integration.BeforeTest(t) - clus := integration.NewClusterV3(t, &integration.ClusterConfig{Size: 1}) + clus := integration.NewCluster(t, &integration.ClusterConfig{Size: 1}) defer clus.Terminate(t) cli := clus.RandClient() @@ -62,7 +62,7 @@ func TestV3MaintenanceDefragmentInflightRange(t *testing.T) { // See https://github.com/etcd-io/etcd/issues/7322 for more detail. func TestV3KVInflightRangeRequests(t *testing.T) { integration.BeforeTest(t) - clus := integration.NewClusterV3(t, &integration.ClusterConfig{Size: 1, UseBridge: true}) + clus := integration.NewCluster(t, &integration.ClusterConfig{Size: 1, UseBridge: true}) defer clus.Terminate(t) cli := clus.RandClient() diff --git a/tests/integration/v3_grpc_test.go b/tests/integration/v3_grpc_test.go index 54165c845bc5..620cc5d9c1e0 100644 --- a/tests/integration/v3_grpc_test.go +++ b/tests/integration/v3_grpc_test.go @@ -41,7 +41,7 @@ import ( // overwrites it, then checks that the change was applied. func TestV3PutOverwrite(t *testing.T) { integration.BeforeTest(t) - clus := integration.NewClusterV3(t, &integration.ClusterConfig{Size: 3}) + clus := integration.NewCluster(t, &integration.ClusterConfig{Size: 3}) defer clus.Terminate(t) kvc := integration.ToGRPC(clus.RandClient()).KV @@ -89,7 +89,7 @@ func TestV3PutOverwrite(t *testing.T) { // TestPutRestart checks if a put after an unrelated member restart succeeds func TestV3PutRestart(t *testing.T) { integration.BeforeTest(t) - clus := integration.NewClusterV3(t, &integration.ClusterConfig{Size: 3, UseBridge: true}) + clus := integration.NewCluster(t, &integration.ClusterConfig{Size: 3, UseBridge: true}) defer clus.Terminate(t) kvIdx := rand.Intn(3) @@ -121,7 +121,7 @@ func TestV3PutRestart(t *testing.T) { // TestV3CompactCurrentRev ensures keys are present when compacting on current revision. func TestV3CompactCurrentRev(t *testing.T) { integration.BeforeTest(t) - clus := integration.NewClusterV3(t, &integration.ClusterConfig{Size: 1}) + clus := integration.NewCluster(t, &integration.ClusterConfig{Size: 1}) defer clus.Terminate(t) kvc := integration.ToGRPC(clus.RandClient()).KV @@ -155,7 +155,7 @@ func TestV3CompactCurrentRev(t *testing.T) { // TestV3HashKV ensures that multiple calls of HashKV on same node return same hash and compact rev. func TestV3HashKV(t *testing.T) { integration.BeforeTest(t) - clus := integration.NewClusterV3(t, &integration.ClusterConfig{Size: 1}) + clus := integration.NewCluster(t, &integration.ClusterConfig{Size: 1}) defer clus.Terminate(t) kvc := integration.ToGRPC(clus.RandClient()).KV @@ -204,7 +204,7 @@ func TestV3HashKV(t *testing.T) { func TestV3TxnTooManyOps(t *testing.T) { integration.BeforeTest(t) maxTxnOps := uint(128) - clus := integration.NewClusterV3(t, &integration.ClusterConfig{Size: 3, MaxTxnOps: maxTxnOps}) + clus := integration.NewCluster(t, &integration.ClusterConfig{Size: 3, MaxTxnOps: maxTxnOps}) defer clus.Terminate(t) kvc := integration.ToGRPC(clus.RandClient()).KV @@ -279,7 +279,7 @@ func TestV3TxnTooManyOps(t *testing.T) { func TestV3TxnDuplicateKeys(t *testing.T) { integration.BeforeTest(t) - clus := integration.NewClusterV3(t, &integration.ClusterConfig{Size: 3}) + clus := integration.NewCluster(t, &integration.ClusterConfig{Size: 3}) defer clus.Terminate(t) putreq := &pb.RequestOp{Request: &pb.RequestOp_RequestPut{RequestPut: &pb.PutRequest{Key: []byte("abc"), Value: []byte("def")}}} @@ -397,7 +397,7 @@ func TestV3TxnDuplicateKeys(t *testing.T) { // Testv3TxnRevision tests that the transaction header revision is set as expected. func TestV3TxnRevision(t *testing.T) { integration.BeforeTest(t) - clus := integration.NewClusterV3(t, &integration.ClusterConfig{Size: 1}) + clus := integration.NewCluster(t, &integration.ClusterConfig{Size: 1}) defer clus.Terminate(t) kvc := integration.ToGRPC(clus.RandClient()).KV @@ -448,7 +448,7 @@ func TestV3TxnRevision(t *testing.T) { // when compared to the Succeeded field in the txn response. func TestV3TxnCmpHeaderRev(t *testing.T) { integration.BeforeTest(t) - clus := integration.NewClusterV3(t, &integration.ClusterConfig{Size: 1}) + clus := integration.NewCluster(t, &integration.ClusterConfig{Size: 1}) defer clus.Terminate(t) kvc := integration.ToGRPC(clus.RandClient()).KV @@ -504,7 +504,7 @@ func TestV3TxnCmpHeaderRev(t *testing.T) { // TestV3TxnRangeCompare tests range comparisons in txns func TestV3TxnRangeCompare(t *testing.T) { integration.BeforeTest(t) - clus := integration.NewClusterV3(t, &integration.ClusterConfig{Size: 1}) + clus := integration.NewCluster(t, &integration.ClusterConfig{Size: 1}) defer clus.Terminate(t) // put keys, named by expected revision @@ -615,7 +615,7 @@ func TestV3TxnRangeCompare(t *testing.T) { // TestV3TxnNested tests nested txns follow paths as expected. func TestV3TxnNestedPath(t *testing.T) { integration.BeforeTest(t) - clus := integration.NewClusterV3(t, &integration.ClusterConfig{Size: 1}) + clus := integration.NewCluster(t, &integration.ClusterConfig{Size: 1}) defer clus.Terminate(t) kvc := integration.ToGRPC(clus.RandClient()).KV @@ -669,7 +669,7 @@ func TestV3TxnNestedPath(t *testing.T) { func TestV3PutIgnoreValue(t *testing.T) { integration.BeforeTest(t) - clus := integration.NewClusterV3(t, &integration.ClusterConfig{Size: 1}) + clus := integration.NewCluster(t, &integration.ClusterConfig{Size: 1}) defer clus.Terminate(t) kvc := integration.ToGRPC(clus.RandClient()).KV @@ -802,7 +802,7 @@ func TestV3PutIgnoreValue(t *testing.T) { func TestV3PutIgnoreLease(t *testing.T) { integration.BeforeTest(t) - clus := integration.NewClusterV3(t, &integration.ClusterConfig{Size: 1}) + clus := integration.NewCluster(t, &integration.ClusterConfig{Size: 1}) defer clus.Terminate(t) kvc := integration.ToGRPC(clus.RandClient()).KV @@ -941,7 +941,7 @@ func TestV3PutIgnoreLease(t *testing.T) { // TestV3PutMissingLease ensures that a Put on a key with a bogus lease fails. func TestV3PutMissingLease(t *testing.T) { integration.BeforeTest(t) - clus := integration.NewClusterV3(t, &integration.ClusterConfig{Size: 3}) + clus := integration.NewCluster(t, &integration.ClusterConfig{Size: 3}) defer clus.Terminate(t) kvc := integration.ToGRPC(clus.RandClient()).KV @@ -1069,7 +1069,7 @@ func TestV3DeleteRange(t *testing.T) { for i, tt := range tests { t.Run(tt.name, func(t *testing.T) { - clus := integration.NewClusterV3(t, &integration.ClusterConfig{Size: 3}) + clus := integration.NewCluster(t, &integration.ClusterConfig{Size: 3}) kvc := integration.ToGRPC(clus.RandClient()).KV defer clus.Terminate(t) @@ -1124,7 +1124,7 @@ func TestV3DeleteRange(t *testing.T) { // TestV3TxnInvalidRange tests that invalid ranges are rejected in txns. func TestV3TxnInvalidRange(t *testing.T) { integration.BeforeTest(t) - clus := integration.NewClusterV3(t, &integration.ClusterConfig{Size: 3}) + clus := integration.NewCluster(t, &integration.ClusterConfig{Size: 3}) defer clus.Terminate(t) kvc := integration.ToGRPC(clus.RandClient()).KV @@ -1168,7 +1168,7 @@ func TestV3TxnInvalidRange(t *testing.T) { func TestV3TooLargeRequest(t *testing.T) { integration.BeforeTest(t) - clus := integration.NewClusterV3(t, &integration.ClusterConfig{Size: 3}) + clus := integration.NewCluster(t, &integration.ClusterConfig{Size: 3}) defer clus.Terminate(t) kvc := integration.ToGRPC(clus.RandClient()).KV @@ -1186,7 +1186,7 @@ func TestV3TooLargeRequest(t *testing.T) { // TestV3Hash tests hash. func TestV3Hash(t *testing.T) { integration.BeforeTest(t) - clus := integration.NewClusterV3(t, &integration.ClusterConfig{Size: 3}) + clus := integration.NewCluster(t, &integration.ClusterConfig{Size: 3}) defer clus.Terminate(t) cli := clus.RandClient() @@ -1211,7 +1211,7 @@ func TestV3Hash(t *testing.T) { // TestV3HashRestart ensures that hash stays the same after restart. func TestV3HashRestart(t *testing.T) { integration.BeforeTest(t) - clus := integration.NewClusterV3(t, &integration.ClusterConfig{Size: 1, UseBridge: true}) + clus := integration.NewCluster(t, &integration.ClusterConfig{Size: 1, UseBridge: true}) defer clus.Terminate(t) cli := clus.RandClient() @@ -1244,7 +1244,7 @@ func TestV3StorageQuotaAPI(t *testing.T) { integration.BeforeTest(t) quotasize := int64(16 * os.Getpagesize()) - clus := integration.NewClusterV3(t, &integration.ClusterConfig{Size: 3, UseBridge: true}) + clus := integration.NewCluster(t, &integration.ClusterConfig{Size: 3, UseBridge: true}) // Set a quota on one node clus.Members[0].QuotaBackendBytes = quotasize @@ -1508,7 +1508,7 @@ func TestV3RangeRequest(t *testing.T) { for i, tt := range tests { t.Run(tt.name, func(t *testing.T) { - clus := integration.NewClusterV3(t, &integration.ClusterConfig{Size: 3}) + clus := integration.NewCluster(t, &integration.ClusterConfig{Size: 3}) defer clus.Terminate(t) for _, k := range tt.putKeys { kvc := integration.ToGRPC(clus.RandClient()).KV @@ -1554,7 +1554,7 @@ func TestV3RangeRequest(t *testing.T) { func TestTLSGRPCRejectInsecureClient(t *testing.T) { integration.BeforeTest(t) - clus := integration.NewClusterV3(t, &integration.ClusterConfig{Size: 3, ClientTLS: &integration.TestTLSInfo}) + clus := integration.NewCluster(t, &integration.ClusterConfig{Size: 3, ClientTLS: &integration.TestTLSInfo}) defer clus.Terminate(t) // nil out TLS field so client will use an insecure connection @@ -1588,7 +1588,7 @@ func TestTLSGRPCRejectInsecureClient(t *testing.T) { func TestTLSGRPCRejectSecureClient(t *testing.T) { integration.BeforeTest(t) - clus := integration.NewClusterV3(t, &integration.ClusterConfig{Size: 3}) + clus := integration.NewCluster(t, &integration.ClusterConfig{Size: 3}) defer clus.Terminate(t) clus.Members[0].ClientTLSInfo = &integration.TestTLSInfo @@ -1607,7 +1607,7 @@ func TestTLSGRPCRejectSecureClient(t *testing.T) { func TestTLSGRPCAcceptSecureAll(t *testing.T) { integration.BeforeTest(t) - clus := integration.NewClusterV3(t, &integration.ClusterConfig{Size: 3, ClientTLS: &integration.TestTLSInfo}) + clus := integration.NewCluster(t, &integration.ClusterConfig{Size: 3, ClientTLS: &integration.TestTLSInfo}) defer clus.Terminate(t) client, err := integration.NewClientV3(clus.Members[0]) @@ -1753,7 +1753,7 @@ func testTLSReload( tlsInfo := cloneFunc() // 2. start cluster with valid certs - clus := integration.NewClusterV3(t, &integration.ClusterConfig{ + clus := integration.NewCluster(t, &integration.ClusterConfig{ Size: 1, PeerTLS: &tlsInfo, ClientTLS: &tlsInfo, @@ -1824,7 +1824,7 @@ func testTLSReload( func TestGRPCRequireLeader(t *testing.T) { integration.BeforeTest(t) - clus := integration.NewClusterV3(t, &integration.ClusterConfig{Size: 3}) + clus := integration.NewCluster(t, &integration.ClusterConfig{Size: 3}) defer clus.Terminate(t) clus.Members[1].Stop(t) @@ -1850,7 +1850,7 @@ func TestGRPCRequireLeader(t *testing.T) { func TestGRPCStreamRequireLeader(t *testing.T) { integration.BeforeTest(t) - clus := integration.NewClusterV3(t, &integration.ClusterConfig{Size: 3, UseBridge: true}) + clus := integration.NewCluster(t, &integration.ClusterConfig{Size: 3, UseBridge: true}) defer clus.Terminate(t) client, err := integration.NewClientV3(clus.Members[0]) @@ -1924,7 +1924,7 @@ func TestV3LargeRequests(t *testing.T) { } for i, test := range tests { t.Run(fmt.Sprintf("#%d", i), func(t *testing.T) { - clus := integration.NewClusterV3(t, &integration.ClusterConfig{Size: 1, MaxRequestBytes: test.maxRequestBytes}) + clus := integration.NewCluster(t, &integration.ClusterConfig{Size: 1, MaxRequestBytes: test.maxRequestBytes}) defer clus.Terminate(t) kvcli := integration.ToGRPC(clus.Client(0)).KV reqput := &pb.PutRequest{Key: []byte("foo"), Value: make([]byte, test.valueSize)} diff --git a/tests/integration/v3_health_test.go b/tests/integration/v3_health_test.go index 2bd03588df2b..98b64c63fe05 100644 --- a/tests/integration/v3_health_test.go +++ b/tests/integration/v3_health_test.go @@ -25,7 +25,7 @@ import ( func TestHealthCheck(t *testing.T) { integration.BeforeTest(t) - clus := integration.NewClusterV3(t, &integration.ClusterConfig{Size: 1}) + clus := integration.NewCluster(t, &integration.ClusterConfig{Size: 1}) defer clus.Terminate(t) cli := healthpb.NewHealthClient(clus.RandClient().ActiveConnection()) diff --git a/tests/integration/v3_kv_test.go b/tests/integration/v3_kv_test.go index 851edd294081..01a4570f51ef 100644 --- a/tests/integration/v3_kv_test.go +++ b/tests/integration/v3_kv_test.go @@ -13,7 +13,7 @@ import ( func TestKVWithEmptyValue(t *testing.T) { integration.BeforeTest(t) - clus := integration.NewClusterV3(t, &integration.ClusterConfig{Size: 1}) + clus := integration.NewCluster(t, &integration.ClusterConfig{Size: 1}) defer clus.Terminate(t) client := clus.RandClient() diff --git a/tests/integration/v3_leadership_test.go b/tests/integration/v3_leadership_test.go index 8fba02c8652f..84bd97d32843 100644 --- a/tests/integration/v3_leadership_test.go +++ b/tests/integration/v3_leadership_test.go @@ -33,7 +33,7 @@ func TestMoveLeaderService(t *testing.T) { testMoveLeader(t, false) } func testMoveLeader(t *testing.T, auto bool) { integration.BeforeTest(t) - clus := integration.NewClusterV3(t, &integration.ClusterConfig{Size: 3}) + clus := integration.NewCluster(t, &integration.ClusterConfig{Size: 3}) defer clus.Terminate(t) oldLeadIdx := clus.WaitLeader(t) @@ -101,7 +101,7 @@ func testMoveLeader(t *testing.T, auto bool) { func TestMoveLeaderError(t *testing.T) { integration.BeforeTest(t) - clus := integration.NewClusterV3(t, &integration.ClusterConfig{Size: 3}) + clus := integration.NewCluster(t, &integration.ClusterConfig{Size: 3}) defer clus.Terminate(t) oldLeadIdx := clus.WaitLeader(t) @@ -120,7 +120,7 @@ func TestMoveLeaderError(t *testing.T) { func TestMoveLeaderToLearnerError(t *testing.T) { integration.BeforeTest(t) - clus := integration.NewClusterV3(t, &integration.ClusterConfig{Size: 3}) + clus := integration.NewCluster(t, &integration.ClusterConfig{Size: 3}) defer clus.Terminate(t) // we have to add and launch learner member after initial cluster was created, because @@ -153,7 +153,7 @@ func TestMoveLeaderToLearnerError(t *testing.T) { func TestTransferLeadershipWithLearner(t *testing.T) { integration.BeforeTest(t) - clus := integration.NewClusterV3(t, &integration.ClusterConfig{Size: 1}) + clus := integration.NewCluster(t, &integration.ClusterConfig{Size: 1}) defer clus.Terminate(t) clus.AddAndLaunchLearnerMember(t) @@ -187,7 +187,7 @@ func TestFirstCommitNotification(t *testing.T) { integration.BeforeTest(t) ctx := context.Background() clusterSize := 3 - cluster := integration.NewClusterV3(t, &integration.ClusterConfig{Size: clusterSize}) + cluster := integration.NewCluster(t, &integration.ClusterConfig{Size: clusterSize}) defer cluster.Terminate(t) oldLeaderIdx := cluster.WaitLeader(t) diff --git a/tests/integration/v3_lease_test.go b/tests/integration/v3_lease_test.go index 5151264a6c1e..412dd7899e65 100644 --- a/tests/integration/v3_lease_test.go +++ b/tests/integration/v3_lease_test.go @@ -37,7 +37,7 @@ import ( func TestV3LeasePromote(t *testing.T) { integration.BeforeTest(t) - clus := integration.NewClusterV3(t, &integration.ClusterConfig{Size: 3, UseBridge: true}) + clus := integration.NewCluster(t, &integration.ClusterConfig{Size: 3, UseBridge: true}) defer clus.Terminate(t) // create lease @@ -98,7 +98,7 @@ func TestV3LeasePromote(t *testing.T) { // TestV3LeaseRevoke ensures a key is deleted once its lease is revoked. func TestV3LeaseRevoke(t *testing.T) { integration.BeforeTest(t) - testLeaseRemoveLeasedKey(t, func(clus *integration.ClusterV3, leaseID int64) error { + testLeaseRemoveLeasedKey(t, func(clus *integration.Cluster, leaseID int64) error { lc := integration.ToGRPC(clus.RandClient()).Lease _, err := lc.LeaseRevoke(context.TODO(), &pb.LeaseRevokeRequest{ID: leaseID}) return err @@ -108,7 +108,7 @@ func TestV3LeaseRevoke(t *testing.T) { // TestV3LeaseGrantById ensures leases may be created by a given id. func TestV3LeaseGrantByID(t *testing.T) { integration.BeforeTest(t) - clus := integration.NewClusterV3(t, &integration.ClusterConfig{Size: 3}) + clus := integration.NewCluster(t, &integration.ClusterConfig{Size: 3}) defer clus.Terminate(t) // create fixed lease @@ -145,7 +145,7 @@ func TestV3LeaseGrantByID(t *testing.T) { // TestV3LeaseExpire ensures a key is deleted once a key expires. func TestV3LeaseExpire(t *testing.T) { integration.BeforeTest(t) - testLeaseRemoveLeasedKey(t, func(clus *integration.ClusterV3, leaseID int64) error { + testLeaseRemoveLeasedKey(t, func(clus *integration.Cluster, leaseID int64) error { // let lease lapse; wait for deleted key ctx, cancel := context.WithCancel(context.Background()) @@ -197,7 +197,7 @@ func TestV3LeaseExpire(t *testing.T) { // TestV3LeaseKeepAlive ensures keepalive keeps the lease alive. func TestV3LeaseKeepAlive(t *testing.T) { integration.BeforeTest(t) - testLeaseRemoveLeasedKey(t, func(clus *integration.ClusterV3, leaseID int64) error { + testLeaseRemoveLeasedKey(t, func(clus *integration.Cluster, leaseID int64) error { lc := integration.ToGRPC(clus.RandClient()).Lease lreq := &pb.LeaseKeepAliveRequest{ID: leaseID} ctx, cancel := context.WithCancel(context.Background()) @@ -284,7 +284,7 @@ func TestV3LeaseCheckpoint(t *testing.T) { EnableLeaseCheckpoint: tc.checkpointingEnabled, LeaseCheckpointInterval: tc.checkpointingInterval, } - clus := integration.NewClusterV3(t, config) + clus := integration.NewCluster(t, config) defer clus.Terminate(t) // create lease @@ -339,7 +339,7 @@ func TestV3LeaseCheckpoint(t *testing.T) { // TestV3LeaseExists creates a lease on a random client and confirms it exists in the cluster. func TestV3LeaseExists(t *testing.T) { integration.BeforeTest(t) - clus := integration.NewClusterV3(t, &integration.ClusterConfig{Size: 3}) + clus := integration.NewCluster(t, &integration.ClusterConfig{Size: 3}) defer clus.Terminate(t) // create lease @@ -363,7 +363,7 @@ func TestV3LeaseExists(t *testing.T) { // TestV3LeaseLeases creates leases and confirms list RPC fetches created ones. func TestV3LeaseLeases(t *testing.T) { integration.BeforeTest(t) - clus := integration.NewClusterV3(t, &integration.ClusterConfig{Size: 1}) + clus := integration.NewCluster(t, &integration.ClusterConfig{Size: 1}) defer clus.Terminate(t) ctx0, cancel0 := context.WithCancel(context.Background()) @@ -413,7 +413,7 @@ func TestV3LeaseTimeToLiveStress(t *testing.T) { func testLeaseStress(t *testing.T, stresser func(context.Context, pb.LeaseClient) error) { integration.BeforeTest(t) - clus := integration.NewClusterV3(t, &integration.ClusterConfig{Size: 3}) + clus := integration.NewCluster(t, &integration.ClusterConfig{Size: 3}) defer clus.Terminate(t) ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second) @@ -484,7 +484,7 @@ func stressLeaseTimeToLive(tctx context.Context, lc pb.LeaseClient) (reterr erro func TestV3PutOnNonExistLease(t *testing.T) { integration.BeforeTest(t) - clus := integration.NewClusterV3(t, &integration.ClusterConfig{Size: 1}) + clus := integration.NewCluster(t, &integration.ClusterConfig{Size: 1}) defer clus.Terminate(t) ctx, cancel := context.WithCancel(context.Background()) @@ -502,7 +502,7 @@ func TestV3PutOnNonExistLease(t *testing.T) { // related issue https://github.com/etcd-io/etcd/issues/6537 func TestV3GetNonExistLease(t *testing.T) { integration.BeforeTest(t) - clus := integration.NewClusterV3(t, &integration.ClusterConfig{Size: 3}) + clus := integration.NewCluster(t, &integration.ClusterConfig{Size: 3}) defer clus.Terminate(t) ctx, cancel := context.WithCancel(context.Background()) @@ -540,7 +540,7 @@ func TestV3GetNonExistLease(t *testing.T) { // TestV3LeaseSwitch tests a key can be switched from one lease to another. func TestV3LeaseSwitch(t *testing.T) { integration.BeforeTest(t) - clus := integration.NewClusterV3(t, &integration.ClusterConfig{Size: 3}) + clus := integration.NewCluster(t, &integration.ClusterConfig{Size: 3}) defer clus.Terminate(t) key := "foo" @@ -603,7 +603,7 @@ func TestV3LeaseSwitch(t *testing.T) { func TestV3LeaseFailover(t *testing.T) { integration.BeforeTest(t) - clus := integration.NewClusterV3(t, &integration.ClusterConfig{Size: 3}) + clus := integration.NewCluster(t, &integration.ClusterConfig{Size: 3}) defer clus.Terminate(t) toIsolate := clus.WaitMembersForLeader(t, clus.Members) @@ -664,7 +664,7 @@ func TestV3LeaseFailover(t *testing.T) { func TestV3LeaseRequireLeader(t *testing.T) { integration.BeforeTest(t) - clus := integration.NewClusterV3(t, &integration.ClusterConfig{Size: 3}) + clus := integration.NewCluster(t, &integration.ClusterConfig{Size: 3}) defer clus.Terminate(t) lc := integration.ToGRPC(clus.Client(0)).Lease @@ -704,7 +704,7 @@ const fiveMinTTL int64 = 300 func TestV3LeaseRecoverAndRevoke(t *testing.T) { integration.BeforeTest(t) - clus := integration.NewClusterV3(t, &integration.ClusterConfig{Size: 1, UseBridge: true}) + clus := integration.NewCluster(t, &integration.ClusterConfig{Size: 1, UseBridge: true}) defer clus.Terminate(t) kvc := integration.ToGRPC(clus.Client(0)).KV @@ -755,7 +755,7 @@ func TestV3LeaseRecoverAndRevoke(t *testing.T) { func TestV3LeaseRevokeAndRecover(t *testing.T) { integration.BeforeTest(t) - clus := integration.NewClusterV3(t, &integration.ClusterConfig{Size: 1, UseBridge: true}) + clus := integration.NewCluster(t, &integration.ClusterConfig{Size: 1, UseBridge: true}) defer clus.Terminate(t) kvc := integration.ToGRPC(clus.Client(0)).KV @@ -807,7 +807,7 @@ func TestV3LeaseRevokeAndRecover(t *testing.T) { func TestV3LeaseRecoverKeyWithDetachedLease(t *testing.T) { integration.BeforeTest(t) - clus := integration.NewClusterV3(t, &integration.ClusterConfig{Size: 1, UseBridge: true}) + clus := integration.NewCluster(t, &integration.ClusterConfig{Size: 1, UseBridge: true}) defer clus.Terminate(t) kvc := integration.ToGRPC(clus.Client(0)).KV @@ -863,7 +863,7 @@ func TestV3LeaseRecoverKeyWithDetachedLease(t *testing.T) { func TestV3LeaseRecoverKeyWithMutipleLease(t *testing.T) { integration.BeforeTest(t) - clus := integration.NewClusterV3(t, &integration.ClusterConfig{Size: 1, UseBridge: true}) + clus := integration.NewCluster(t, &integration.ClusterConfig{Size: 1, UseBridge: true}) defer clus.Terminate(t) kvc := integration.ToGRPC(clus.Client(0)).KV @@ -935,7 +935,7 @@ func TestV3LeaseRecoverKeyWithMutipleLease(t *testing.T) { } // acquireLeaseAndKey creates a new lease and creates an attached key. -func acquireLeaseAndKey(clus *integration.ClusterV3, key string) (int64, error) { +func acquireLeaseAndKey(clus *integration.Cluster, key string) (int64, error) { // create lease lresp, err := integration.ToGRPC(clus.RandClient()).Lease.LeaseGrant( context.TODO(), @@ -956,8 +956,8 @@ func acquireLeaseAndKey(clus *integration.ClusterV3, key string) (int64, error) // testLeaseRemoveLeasedKey performs some action while holding a lease with an // attached key "foo", then confirms the key is gone. -func testLeaseRemoveLeasedKey(t *testing.T, act func(*integration.ClusterV3, int64) error) { - clus := integration.NewClusterV3(t, &integration.ClusterConfig{Size: 3}) +func testLeaseRemoveLeasedKey(t *testing.T, act func(*integration.Cluster, int64) error) { + clus := integration.NewCluster(t, &integration.ClusterConfig{Size: 3}) defer clus.Terminate(t) leaseID, err := acquireLeaseAndKey(clus, "foo") @@ -980,7 +980,7 @@ func testLeaseRemoveLeasedKey(t *testing.T, act func(*integration.ClusterV3, int } } -func leaseExist(t *testing.T, clus *integration.ClusterV3, leaseID int64) bool { +func leaseExist(t *testing.T, clus *integration.Cluster, leaseID int64) bool { l := integration.ToGRPC(clus.RandClient()).Lease _, err := l.LeaseGrant(context.Background(), &pb.LeaseGrantRequest{ID: leaseID, TTL: 5}) diff --git a/tests/integration/v3_stm_test.go b/tests/integration/v3_stm_test.go index ccd7eea1d75a..f86085bf7e71 100644 --- a/tests/integration/v3_stm_test.go +++ b/tests/integration/v3_stm_test.go @@ -31,7 +31,7 @@ import ( func TestSTMConflict(t *testing.T) { integration.BeforeTest(t) - clus := integration.NewClusterV3(t, &integration.ClusterConfig{Size: 3}) + clus := integration.NewCluster(t, &integration.ClusterConfig{Size: 3}) defer clus.Terminate(t) etcdc := clus.RandClient() @@ -99,7 +99,7 @@ func TestSTMConflict(t *testing.T) { func TestSTMPutNewKey(t *testing.T) { integration.BeforeTest(t) - clus := integration.NewClusterV3(t, &integration.ClusterConfig{Size: 1}) + clus := integration.NewCluster(t, &integration.ClusterConfig{Size: 1}) defer clus.Terminate(t) etcdc := clus.RandClient() @@ -126,7 +126,7 @@ func TestSTMPutNewKey(t *testing.T) { func TestSTMAbort(t *testing.T) { integration.BeforeTest(t) - clus := integration.NewClusterV3(t, &integration.ClusterConfig{Size: 1}) + clus := integration.NewCluster(t, &integration.ClusterConfig{Size: 1}) defer clus.Terminate(t) etcdc := clus.RandClient() @@ -157,7 +157,7 @@ func TestSTMAbort(t *testing.T) { func TestSTMSerialize(t *testing.T) { integration.BeforeTest(t) - clus := integration.NewClusterV3(t, &integration.ClusterConfig{Size: 3}) + clus := integration.NewCluster(t, &integration.ClusterConfig{Size: 3}) defer clus.Terminate(t) etcdc := clus.RandClient() @@ -220,7 +220,7 @@ func TestSTMSerialize(t *testing.T) { func TestSTMApplyOnConcurrentDeletion(t *testing.T) { integration.BeforeTest(t) - clus := integration.NewClusterV3(t, &integration.ClusterConfig{Size: 1}) + clus := integration.NewCluster(t, &integration.ClusterConfig{Size: 1}) defer clus.Terminate(t) etcdc := clus.RandClient() @@ -269,7 +269,7 @@ func TestSTMApplyOnConcurrentDeletion(t *testing.T) { func TestSTMSerializableSnapshotPut(t *testing.T) { integration.BeforeTest(t) - clus := integration.NewClusterV3(t, &integration.ClusterConfig{Size: 1}) + clus := integration.NewCluster(t, &integration.ClusterConfig{Size: 1}) defer clus.Terminate(t) cli := clus.Client(0) diff --git a/tests/integration/v3_tls_test.go b/tests/integration/v3_tls_test.go index e504192612ce..793d3d5a046b 100644 --- a/tests/integration/v3_tls_test.go +++ b/tests/integration/v3_tls_test.go @@ -48,7 +48,7 @@ func testTLSCipherSuites(t *testing.T, valid bool) { srvTLS.CipherSuites, cliTLS.CipherSuites = cipherSuites[:2], cipherSuites[2:] } - clus := integration.NewClusterV3(t, &integration.ClusterConfig{Size: 1, ClientTLS: &srvTLS}) + clus := integration.NewCluster(t, &integration.ClusterConfig{Size: 1, ClientTLS: &srvTLS}) defer clus.Terminate(t) cc, err := cliTLS.ClientConfig() diff --git a/tests/integration/v3_watch_restore_test.go b/tests/integration/v3_watch_restore_test.go index 532871bf26b3..2f3271eb96f9 100644 --- a/tests/integration/v3_watch_restore_test.go +++ b/tests/integration/v3_watch_restore_test.go @@ -53,7 +53,7 @@ func MustFetchNotEmptyMetric(tb testing.TB, member *integration.Member, metric s func TestV3WatchRestoreSnapshotUnsync(t *testing.T) { integration.BeforeTest(t) - clus := integration.NewClusterV3(t, &integration.ClusterConfig{ + clus := integration.NewCluster(t, &integration.ClusterConfig{ Size: 3, SnapshotCount: 10, SnapshotCatchUpEntries: 5, diff --git a/tests/integration/v3_watch_test.go b/tests/integration/v3_watch_test.go index 59433e0cc3bd..45b62f7acbbc 100644 --- a/tests/integration/v3_watch_test.go +++ b/tests/integration/v3_watch_test.go @@ -207,7 +207,7 @@ func TestV3WatchFromCurrentRevision(t *testing.T) { for i, tt := range tests { t.Run(tt.name, func(t *testing.T) { - clus := integration.NewClusterV3(t, &integration.ClusterConfig{Size: 3}) + clus := integration.NewCluster(t, &integration.ClusterConfig{Size: 3}) defer clus.Terminate(t) wAPI := integration.ToGRPC(clus.RandClient()).Watch @@ -294,7 +294,7 @@ func TestV3WatchFromCurrentRevision(t *testing.T) { func TestV3WatchFutureRevision(t *testing.T) { integration.BeforeTest(t) - clus := integration.NewClusterV3(t, &integration.ClusterConfig{Size: 1}) + clus := integration.NewCluster(t, &integration.ClusterConfig{Size: 1}) defer clus.Terminate(t) wAPI := integration.ToGRPC(clus.RandClient()).Watch @@ -355,7 +355,7 @@ func TestV3WatchFutureRevision(t *testing.T) { func TestV3WatchWrongRange(t *testing.T) { integration.BeforeTest(t) - clus := integration.NewClusterV3(t, &integration.ClusterConfig{Size: 1}) + clus := integration.NewCluster(t, &integration.ClusterConfig{Size: 1}) defer clus.Terminate(t) wAPI := integration.ToGRPC(clus.RandClient()).Watch @@ -409,7 +409,7 @@ func TestV3WatchCancelUnsynced(t *testing.T) { } func testV3WatchCancel(t *testing.T, startRev int64) { - clus := integration.NewClusterV3(t, &integration.ClusterConfig{Size: 3}) + clus := integration.NewCluster(t, &integration.ClusterConfig{Size: 3}) defer clus.Terminate(t) ctx, cancel := context.WithTimeout(context.Background(), 30*time.Second) @@ -465,7 +465,7 @@ func testV3WatchCancel(t *testing.T, startRev int64) { // overlapping puts. func TestV3WatchCurrentPutOverlap(t *testing.T) { integration.BeforeTest(t) - clus := integration.NewClusterV3(t, &integration.ClusterConfig{Size: 3}) + clus := integration.NewCluster(t, &integration.ClusterConfig{Size: 3}) defer clus.Terminate(t) ctx, cancel := context.WithTimeout(context.Background(), 30*time.Second) @@ -550,7 +550,7 @@ func TestV3WatchCurrentPutOverlap(t *testing.T) { func TestV3WatchEmptyKey(t *testing.T) { integration.BeforeTest(t) - clus := integration.NewClusterV3(t, &integration.ClusterConfig{Size: 1}) + clus := integration.NewCluster(t, &integration.ClusterConfig{Size: 1}) defer clus.Terminate(t) ctx, cancel := context.WithTimeout(context.Background(), 30*time.Second) @@ -608,7 +608,7 @@ func TestV3WatchMultipleWatchersUnsynced(t *testing.T) { // that matches all watchers, and another key that matches only // one watcher to test if it receives expected events. func testV3WatchMultipleWatchers(t *testing.T, startRev int64) { - clus := integration.NewClusterV3(t, &integration.ClusterConfig{Size: 3}) + clus := integration.NewCluster(t, &integration.ClusterConfig{Size: 3}) defer clus.Terminate(t) kvc := integration.ToGRPC(clus.RandClient()).KV @@ -710,7 +710,7 @@ func TestV3WatchMultipleEventsTxnUnsynced(t *testing.T) { // testV3WatchMultipleEventsTxn tests Watch APIs when it receives multiple events. func testV3WatchMultipleEventsTxn(t *testing.T, startRev int64) { - clus := integration.NewClusterV3(t, &integration.ClusterConfig{Size: 3}) + clus := integration.NewCluster(t, &integration.ClusterConfig{Size: 3}) defer clus.Terminate(t) ctx, cancel := context.WithTimeout(context.Background(), 30*time.Second) @@ -793,7 +793,7 @@ func (evs eventsSortByKey) Less(i, j int) bool { func TestV3WatchMultipleEventsPutUnsynced(t *testing.T) { integration.BeforeTest(t) - clus := integration.NewClusterV3(t, &integration.ClusterConfig{Size: 3}) + clus := integration.NewCluster(t, &integration.ClusterConfig{Size: 3}) defer clus.Terminate(t) kvc := integration.ToGRPC(clus.RandClient()).KV @@ -882,7 +882,7 @@ func TestV3WatchMultipleStreamsUnsynced(t *testing.T) { // testV3WatchMultipleStreams tests multiple watchers on the same key on multiple streams. func testV3WatchMultipleStreams(t *testing.T, startRev int64) { - clus := integration.NewClusterV3(t, &integration.ClusterConfig{Size: 3}) + clus := integration.NewCluster(t, &integration.ClusterConfig{Size: 3}) defer clus.Terminate(t) wAPI := integration.ToGRPC(clus.RandClient()).Watch @@ -985,7 +985,7 @@ func TestWatchWithProgressNotify(t *testing.T) { defer func() { v3rpc.SetProgressReportInterval(oldpi) }() integration.BeforeTest(t) - clus := integration.NewClusterV3(t, &integration.ClusterConfig{Size: 3}) + clus := integration.NewCluster(t, &integration.ClusterConfig{Size: 3}) defer clus.Terminate(t) ctx, cancel := context.WithTimeout(context.Background(), 30*time.Second) @@ -1035,7 +1035,7 @@ func TestWatchWithProgressNotify(t *testing.T) { // TestV3WatcMultiOpenhClose opens many watchers concurrently on multiple streams. func TestV3WatchClose(t *testing.T) { integration.BeforeTest(t) - clus := integration.NewClusterV3(t, &integration.ClusterConfig{Size: 1, UseBridge: true}) + clus := integration.NewCluster(t, &integration.ClusterConfig{Size: 1, UseBridge: true}) defer clus.Terminate(t) c := clus.Client(0) @@ -1071,7 +1071,7 @@ func TestV3WatchClose(t *testing.T) { func TestV3WatchWithFilter(t *testing.T) { integration.BeforeTest(t) - clus := integration.NewClusterV3(t, &integration.ClusterConfig{Size: 1}) + clus := integration.NewCluster(t, &integration.ClusterConfig{Size: 1}) defer clus.Terminate(t) ctx, cancel := context.WithTimeout(context.Background(), 30*time.Second) @@ -1139,7 +1139,7 @@ func TestV3WatchWithFilter(t *testing.T) { func TestV3WatchWithPrevKV(t *testing.T) { integration.BeforeTest(t) - clus := integration.NewClusterV3(t, &integration.ClusterConfig{Size: 1}) + clus := integration.NewCluster(t, &integration.ClusterConfig{Size: 1}) defer clus.Terminate(t) wctx, wcancel := context.WithCancel(context.Background()) @@ -1214,7 +1214,7 @@ func TestV3WatchWithPrevKV(t *testing.T) { func TestV3WatchCancellation(t *testing.T) { integration.BeforeTest(t) - clus := integration.NewClusterV3(t, &integration.ClusterConfig{Size: 1}) + clus := integration.NewCluster(t, &integration.ClusterConfig{Size: 1}) defer clus.Terminate(t) ctx, cancel := context.WithTimeout(context.Background(), 30*time.Second) @@ -1256,7 +1256,7 @@ func TestV3WatchCancellation(t *testing.T) { func TestV3WatchCloseCancelRace(t *testing.T) { integration.BeforeTest(t) - clus := integration.NewClusterV3(t, &integration.ClusterConfig{Size: 1}) + clus := integration.NewCluster(t, &integration.ClusterConfig{Size: 1}) defer clus.Terminate(t) ctx, cancel := context.WithTimeout(context.Background(), 30*time.Second) diff --git a/tests/integration/v3election_grpc_test.go b/tests/integration/v3election_grpc_test.go index 32127e50a833..c7bf7990528f 100644 --- a/tests/integration/v3election_grpc_test.go +++ b/tests/integration/v3election_grpc_test.go @@ -29,7 +29,7 @@ import ( // simultaneous leadership to multiple campaigners. func TestV3ElectionCampaign(t *testing.T) { integration.BeforeTest(t) - clus := integration.NewClusterV3(t, &integration.ClusterConfig{Size: 1}) + clus := integration.NewCluster(t, &integration.ClusterConfig{Size: 1}) defer clus.Terminate(t) lease1, err1 := integration.ToGRPC(clus.RandClient()).Lease.LeaseGrant(context.TODO(), &pb.LeaseGrantRequest{TTL: 30}) @@ -91,7 +91,7 @@ func TestV3ElectionCampaign(t *testing.T) { // proclamations from different leaders uninterrupted. func TestV3ElectionObserve(t *testing.T) { integration.BeforeTest(t) - clus := integration.NewClusterV3(t, &integration.ClusterConfig{Size: 1}) + clus := integration.NewCluster(t, &integration.ClusterConfig{Size: 1}) defer clus.Terminate(t) lc := integration.ToGRPC(clus.Client(0)).Election diff --git a/tests/integration/v3lock_grpc_test.go b/tests/integration/v3lock_grpc_test.go index 1396fb3d40ca..f293bc1a556d 100644 --- a/tests/integration/v3lock_grpc_test.go +++ b/tests/integration/v3lock_grpc_test.go @@ -28,7 +28,7 @@ import ( // once it is unlocked. func TestV3LockLockWaiter(t *testing.T) { integration.BeforeTest(t) - clus := integration.NewClusterV3(t, &integration.ClusterConfig{Size: 1}) + clus := integration.NewCluster(t, &integration.ClusterConfig{Size: 1}) defer clus.Terminate(t) lease1, err1 := integration.ToGRPC(clus.RandClient()).Lease.LeaseGrant(context.TODO(), &pb.LeaseGrantRequest{TTL: 30}) From a53074542bdd62e139fc2c268e17c77caf16ef45 Mon Sep 17 00:00:00 2001 From: Marek Siarkowicz Date: Wed, 19 Jan 2022 15:52:36 +0100 Subject: [PATCH 082/258] test: Run v2 discovery tests on previous version binary --- tests/e2e/discovery_test.go | 78 ++++++++++++++++++++++++++ tests/framework/e2e/cluster.go | 16 ++++-- tests/framework/integration/cluster.go | 2 +- tests/integration/cluster_test.go | 43 -------------- 4 files changed, 91 insertions(+), 48 deletions(-) create mode 100644 tests/e2e/discovery_test.go diff --git a/tests/e2e/discovery_test.go b/tests/e2e/discovery_test.go new file mode 100644 index 000000000000..6f6a5e1506c5 --- /dev/null +++ b/tests/e2e/discovery_test.go @@ -0,0 +1,78 @@ +// Copyright 2022 The etcd Authors +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package e2e + +import ( + "context" + "fmt" + "strings" + "testing" + + "go.etcd.io/etcd/client/pkg/v3/fileutil" + "go.etcd.io/etcd/client/v2" + "go.etcd.io/etcd/tests/v3/framework/e2e" + "go.etcd.io/etcd/tests/v3/framework/integration" +) + +func TestClusterOf1UsingDiscovery(t *testing.T) { testClusterUsingDiscovery(t, 1, false) } +func TestClusterOf3UsingDiscovery(t *testing.T) { testClusterUsingDiscovery(t, 3, false) } +func TestTLSClusterOf3UsingDiscovery(t *testing.T) { testClusterUsingDiscovery(t, 3, true) } + +func testClusterUsingDiscovery(t *testing.T, size int, peerTLS bool) { + e2e.BeforeTest(t) + + lastReleaseBinary := e2e.BinDir + "/etcd-last-release" + if !fileutil.Exist(lastReleaseBinary) { + t.Skipf("%q does not exist", lastReleaseBinary) + } + + dc, err := e2e.NewEtcdProcessCluster(t, &e2e.EtcdProcessClusterConfig{ + BasePort: 2000, + ExecPath: lastReleaseBinary, + ClusterSize: 1, + EnableV2: true, + }) + if err != nil { + t.Fatalf("could not start etcd process cluster (%v)", err) + } + defer dc.Close() + + dcc := integration.MustNewHTTPClient(t, dc.EndpointsV2(), nil) + dkapi := client.NewKeysAPI(dcc) + ctx, cancel := context.WithTimeout(context.Background(), integration.RequestTimeout) + if _, err := dkapi.Create(ctx, "/_config/size", fmt.Sprintf("%d", size)); err != nil { + t.Fatal(err) + } + cancel() + + c, err := e2e.NewEtcdProcessCluster(t, &e2e.EtcdProcessClusterConfig{ + BasePort: 3000, + ClusterSize: size, + IsPeerTLS: peerTLS, + Discovery: dc.EndpointsV2()[0] + "/v2/keys", + }) + if err != nil { + t.Fatalf("could not start etcd process cluster (%v)", err) + } + defer c.Close() + + kubectl := []string{e2e.CtlBinPath, "--endpoints", strings.Join(c.EndpointsV3(), ",")} + if err := e2e.SpawnWithExpect(append(kubectl, "put", "key", "value"), "OK"); err != nil { + t.Fatal(err) + } + if err := e2e.SpawnWithExpect(append(kubectl, "get", "key"), "value"); err != nil { + t.Fatal(err) + } +} diff --git a/tests/framework/e2e/cluster.go b/tests/framework/e2e/cluster.go index 445c84de954e..4a7c9798bffe 100644 --- a/tests/framework/e2e/cluster.go +++ b/tests/framework/e2e/cluster.go @@ -170,6 +170,7 @@ type EtcdProcessClusterConfig struct { V2deprecation string RollingStart bool + Discovery string } // NewEtcdProcessCluster launches a new cluster from etcd processes, returning @@ -273,6 +274,7 @@ func (cfg *EtcdProcessClusterConfig) EtcdServerProcessConfigs(tb testing.TB) []* "--data-dir", dataDirPath, "--snapshot-count", fmt.Sprintf("%d", cfg.SnapshotCount), } + if cfg.ForceNewCluster { args = append(args, "--force-new-cluster") } @@ -309,6 +311,10 @@ func (cfg *EtcdProcessClusterConfig) EtcdServerProcessConfigs(tb testing.TB) []* args = append(args, "--v2-deprecation", cfg.V2deprecation) } + if cfg.Discovery != "" { + args = append(args, "--discovery", cfg.Discovery) + } + etcdCfgs[i] = &EtcdServerProcessConfig{ lg: lg, ExecPath: cfg.ExecPath, @@ -325,10 +331,12 @@ func (cfg *EtcdProcessClusterConfig) EtcdServerProcessConfigs(tb testing.TB) []* } } - initialClusterArgs := []string{"--initial-cluster", strings.Join(initialCluster, ",")} - for i := range etcdCfgs { - etcdCfgs[i].InitialCluster = strings.Join(initialCluster, ",") - etcdCfgs[i].Args = append(etcdCfgs[i].Args, initialClusterArgs...) + if cfg.Discovery == "" { + for i := range etcdCfgs { + initialClusterArgs := []string{"--initial-cluster", strings.Join(initialCluster, ",")} + etcdCfgs[i].InitialCluster = strings.Join(initialCluster, ",") + etcdCfgs[i].Args = append(etcdCfgs[i].Args, initialClusterArgs...) + } } return etcdCfgs diff --git a/tests/framework/integration/cluster.go b/tests/framework/integration/cluster.go index 323398c7bb92..f7fc08677f8f 100644 --- a/tests/framework/integration/cluster.go +++ b/tests/framework/integration/cluster.go @@ -552,7 +552,7 @@ type Member struct { // ServerClient is a clientv3 that directly calls the etcdserver. ServerClient *clientv3.Client // Client is a clientv3 that communicates via socket, either UNIX or TCP. - Client *clientv3.Client + Client *clientv3.Client KeepDataDirTerminate bool ClientMaxCallSendMsgSize int diff --git a/tests/integration/cluster_test.go b/tests/integration/cluster_test.go index 9cd65b40be46..8db6f30d5798 100644 --- a/tests/integration/cluster_test.go +++ b/tests/integration/cluster_test.go @@ -67,49 +67,6 @@ func TestTLSClusterOf3WithSpecificUsage(t *testing.T) { clusterMustProgress(t, c.Members) } -func TestClusterOf1UsingDiscovery(t *testing.T) { testClusterUsingDiscovery(t, 1) } -func TestClusterOf3UsingDiscovery(t *testing.T) { testClusterUsingDiscovery(t, 3) } - -func testClusterUsingDiscovery(t *testing.T, size int) { - integration.BeforeTest(t) - dc := integration.NewCluster(t, &integration.ClusterConfig{Size: 1, UseIP: true}) - defer dc.Terminate(t) - // init discovery token space - dcc := integration.MustNewHTTPClient(t, dc.URLs(), nil) - dkapi := client.NewKeysAPI(dcc) - ctx, cancel := context.WithTimeout(context.Background(), integration.RequestTimeout) - if _, err := dkapi.Create(ctx, "/_config/size", fmt.Sprintf("%d", size)); err != nil { - t.Fatal(err) - } - cancel() - - c := integration.NewCluster(t, &integration.ClusterConfig{Size: size, DiscoveryURL: dc.URL(0) + "/v2/keys"}) - defer c.Terminate(t) - clusterMustProgress(t, c.Members) -} - -func TestTLSClusterOf3UsingDiscovery(t *testing.T) { - integration.BeforeTest(t) - dc := integration.NewCluster(t, &integration.ClusterConfig{Size: 1, UseIP: true}) - defer dc.Terminate(t) - // init discovery token space - dcc := integration.MustNewHTTPClient(t, dc.URLs(), nil) - dkapi := client.NewKeysAPI(dcc) - ctx, cancel := context.WithTimeout(context.Background(), integration.RequestTimeout) - if _, err := dkapi.Create(ctx, "/_config/size", fmt.Sprintf("%d", 3)); err != nil { - t.Fatal(err) - } - cancel() - - c := integration.NewCluster(t, &integration.ClusterConfig{ - Size: 3, - PeerTLS: &integration.TestTLSInfo, - DiscoveryURL: dc.URL(0) + "/v2/keys"}, - ) - defer c.Terminate(t) - clusterMustProgress(t, c.Members) -} - func TestDoubleClusterSizeOf1(t *testing.T) { testDoubleClusterSize(t, 1) } func TestDoubleClusterSizeOf3(t *testing.T) { testDoubleClusterSize(t, 3) } From 0ab7c7842e4884df748e9e80e4c4b6b284523116 Mon Sep 17 00:00:00 2001 From: Marek Siarkowicz Date: Fri, 21 Jan 2022 14:21:10 +0100 Subject: [PATCH 083/258] Add required permissions for CodeQL --- .github/workflows/codeql-analysis.yml | 3 +++ 1 file changed, 3 insertions(+) diff --git a/.github/workflows/codeql-analysis.yml b/.github/workflows/codeql-analysis.yml index 76e8a31e3701..55d3c69c7a9a 100644 --- a/.github/workflows/codeql-analysis.yml +++ b/.github/workflows/codeql-analysis.yml @@ -24,6 +24,9 @@ jobs: analyze: name: Analyze runs-on: ubuntu-latest + permissions: + # required for all workflows + security-events: write strategy: fail-fast: false From f8eeecc359ed42ee468f190e85e489c2d8c16c99 Mon Sep 17 00:00:00 2001 From: Sahdev Zala Date: Fri, 21 Jan 2022 16:45:08 -0500 Subject: [PATCH 084/258] Revert CodeQL permission Reverting per the latest discussion in the issue 13588 to test if we can remove the write permission. --- .github/workflows/codeql-analysis.yml | 3 --- 1 file changed, 3 deletions(-) diff --git a/.github/workflows/codeql-analysis.yml b/.github/workflows/codeql-analysis.yml index 55d3c69c7a9a..76e8a31e3701 100644 --- a/.github/workflows/codeql-analysis.yml +++ b/.github/workflows/codeql-analysis.yml @@ -24,9 +24,6 @@ jobs: analyze: name: Analyze runs-on: ubuntu-latest - permissions: - # required for all workflows - security-events: write strategy: fail-fast: false From 3788523a3e2dbfd3ca6552c97a77650516f4f7dc Mon Sep 17 00:00:00 2001 From: Marek Siarkowicz Date: Mon, 24 Jan 2022 15:33:30 +0100 Subject: [PATCH 085/258] tests: Move revision tests out of concurrency --- tests/integration/{clientv3/concurrency => }/revision_test.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) rename tests/integration/{clientv3/concurrency => }/revision_test.go (99%) diff --git a/tests/integration/clientv3/concurrency/revision_test.go b/tests/integration/revision_test.go similarity index 99% rename from tests/integration/clientv3/concurrency/revision_test.go rename to tests/integration/revision_test.go index 7e6236a7a982..6fb81b9ca5fa 100644 --- a/tests/integration/clientv3/concurrency/revision_test.go +++ b/tests/integration/revision_test.go @@ -12,7 +12,7 @@ // See the License for the specific language governing permissions and // limitations under the License. -package concurrency_test +package integration_test import ( "context" From e9edc5432cffce26d53906528ecd125dfae3a699 Mon Sep 17 00:00:00 2001 From: Eng Zer Jun Date: Mon, 24 Jan 2022 22:40:34 +0800 Subject: [PATCH 086/258] *: use `T.TempDir` to create temporary test directory The directory created by `T.TempDir()` and is automatically removed when the test and all its subtests complete. Reference: https://pkg.go.dev/testing#T.TempDir Signed-off-by: Eng Zer Jun --- client/pkg/fileutil/fileutil_test.go | 38 ++--- client/pkg/fileutil/preallocate_test.go | 6 +- client/pkg/fileutil/purge_test.go | 18 +-- client/pkg/fileutil/read_dir_test.go | 6 +- .../pkg/transport/keepalive_listener_test.go | 3 +- client/pkg/transport/listener_test.go | 48 ++---- client/pkg/transport/transport_test.go | 3 +- server/embed/auth_test.go | 7 +- server/embed/serve_test.go | 8 +- .../etcdserver/api/rafthttp/snapshot_test.go | 6 +- server/etcdserver/server_test.go | 12 +- server/lease/lessor_test.go | 5 +- server/storage/wal/file_pipeline_test.go | 19 +-- server/storage/wal/repair_test.go | 12 +- server/storage/wal/wal_bench_test.go | 7 +- server/storage/wal/wal_test.go | 149 ++++-------------- tests/e2e/etcd_config_test.go | 26 +-- tests/integration/member_test.go | 7 +- tests/integration/v3_grpc_test.go | 50 ++---- tools/etcd-dump-logs/etcd-dump-log_test.go | 6 +- 20 files changed, 98 insertions(+), 338 deletions(-) diff --git a/client/pkg/fileutil/fileutil_test.go b/client/pkg/fileutil/fileutil_test.go index 995a917786a3..2de28ec2e427 100644 --- a/client/pkg/fileutil/fileutil_test.go +++ b/client/pkg/fileutil/fileutil_test.go @@ -30,15 +30,11 @@ import ( ) func TestIsDirWriteable(t *testing.T) { - tmpdir, err := os.MkdirTemp("", "") - if err != nil { - t.Fatalf("unexpected os.MkdirTemp error: %v", err) - } - defer os.RemoveAll(tmpdir) - if err = IsDirWriteable(tmpdir); err != nil { + tmpdir := t.TempDir() + if err := IsDirWriteable(tmpdir); err != nil { t.Fatalf("unexpected IsDirWriteable error: %v", err) } - if err = os.Chmod(tmpdir, 0444); err != nil { + if err := os.Chmod(tmpdir, 0444); err != nil { t.Fatalf("unexpected os.Chmod error: %v", err) } me, err := user.Current() @@ -59,22 +55,18 @@ func TestIsDirWriteable(t *testing.T) { } func TestCreateDirAll(t *testing.T) { - tmpdir, err := os.MkdirTemp(os.TempDir(), "foo") - if err != nil { - t.Fatal(err) - } - defer os.RemoveAll(tmpdir) + tmpdir := t.TempDir() tmpdir2 := filepath.Join(tmpdir, "testdir") - if err = CreateDirAll(zaptest.NewLogger(t), tmpdir2); err != nil { + if err := CreateDirAll(zaptest.NewLogger(t), tmpdir2); err != nil { t.Fatal(err) } - if err = os.WriteFile(filepath.Join(tmpdir2, "text.txt"), []byte("test text"), PrivateFileMode); err != nil { + if err := os.WriteFile(filepath.Join(tmpdir2, "text.txt"), []byte("test text"), PrivateFileMode); err != nil { t.Fatal(err) } - if err = CreateDirAll(zaptest.NewLogger(t), tmpdir2); err == nil || !strings.Contains(err.Error(), "to be empty, got") { + if err := CreateDirAll(zaptest.NewLogger(t), tmpdir2); err == nil || !strings.Contains(err.Error(), "to be empty, got") { t.Fatalf("unexpected error %v", err) } } @@ -107,11 +99,7 @@ func TestExist(t *testing.T) { } func TestDirEmpty(t *testing.T) { - dir, err := os.MkdirTemp(os.TempDir(), "empty_dir") - if err != nil { - t.Fatal(err) - } - defer os.RemoveAll(dir) + dir := t.TempDir() if !DirEmpty(dir) { t.Fatalf("expected DirEmpty true, got %v", DirEmpty(dir)) @@ -177,19 +165,15 @@ func TestZeroToEnd(t *testing.T) { } func TestDirPermission(t *testing.T) { - tmpdir, err := os.MkdirTemp(os.TempDir(), "foo") - if err != nil { - t.Fatal(err) - } - defer os.RemoveAll(tmpdir) + tmpdir := t.TempDir() tmpdir2 := filepath.Join(tmpdir, "testpermission") // create a new dir with 0700 - if err = CreateDirAll(zaptest.NewLogger(t), tmpdir2); err != nil { + if err := CreateDirAll(zaptest.NewLogger(t), tmpdir2); err != nil { t.Fatal(err) } // check dir permission with mode different than created dir - if err = CheckDirPermission(tmpdir2, 0600); err == nil { + if err := CheckDirPermission(tmpdir2, 0600); err == nil { t.Errorf("expected error, got nil") } } diff --git a/client/pkg/fileutil/preallocate_test.go b/client/pkg/fileutil/preallocate_test.go index a3b477365a07..47a006704b24 100644 --- a/client/pkg/fileutil/preallocate_test.go +++ b/client/pkg/fileutil/preallocate_test.go @@ -62,11 +62,7 @@ func testPreallocateFixed(t *testing.T, f *os.File) { } func runPreallocTest(t *testing.T, test func(*testing.T, *os.File)) { - p, err := os.MkdirTemp(os.TempDir(), "preallocateTest") - if err != nil { - t.Fatal(err) - } - defer os.RemoveAll(p) + p := t.TempDir() f, err := os.CreateTemp(p, "") if err != nil { diff --git a/client/pkg/fileutil/purge_test.go b/client/pkg/fileutil/purge_test.go index 4f2beb2785d4..bafa11af7161 100644 --- a/client/pkg/fileutil/purge_test.go +++ b/client/pkg/fileutil/purge_test.go @@ -26,17 +26,13 @@ import ( ) func TestPurgeFile(t *testing.T) { - dir, err := os.MkdirTemp("", "purgefile") - if err != nil { - t.Fatal(err) - } - defer os.RemoveAll(dir) + dir := t.TempDir() // minimal file set for i := 0; i < 3; i++ { f, ferr := os.Create(filepath.Join(dir, fmt.Sprintf("%d.test", i))) if ferr != nil { - t.Fatal(err) + t.Fatal(ferr) } f.Close() } @@ -56,7 +52,7 @@ func TestPurgeFile(t *testing.T) { go func(n int) { f, ferr := os.Create(filepath.Join(dir, fmt.Sprintf("%d.test", n))) if ferr != nil { - t.Error(err) + t.Error(ferr) } f.Close() }(i) @@ -92,15 +88,11 @@ func TestPurgeFile(t *testing.T) { } func TestPurgeFileHoldingLockFile(t *testing.T) { - dir, err := os.MkdirTemp("", "purgefile") - if err != nil { - t.Fatal(err) - } - defer os.RemoveAll(dir) + dir := t.TempDir() for i := 0; i < 10; i++ { var f *os.File - f, err = os.Create(filepath.Join(dir, fmt.Sprintf("%d.test", i))) + f, err := os.Create(filepath.Join(dir, fmt.Sprintf("%d.test", i))) if err != nil { t.Fatal(err) } diff --git a/client/pkg/fileutil/read_dir_test.go b/client/pkg/fileutil/read_dir_test.go index ecc936cb0dcb..79a37d886cad 100644 --- a/client/pkg/fileutil/read_dir_test.go +++ b/client/pkg/fileutil/read_dir_test.go @@ -22,11 +22,7 @@ import ( ) func TestReadDir(t *testing.T) { - tmpdir, err := os.MkdirTemp("", "") - defer os.RemoveAll(tmpdir) - if err != nil { - t.Fatalf("unexpected os.MkdirTemp error: %v", err) - } + tmpdir := t.TempDir() files := []string{"def", "abc", "xyz", "ghi"} for _, f := range files { diff --git a/client/pkg/transport/keepalive_listener_test.go b/client/pkg/transport/keepalive_listener_test.go index 425f53368b54..d5020544e4ce 100644 --- a/client/pkg/transport/keepalive_listener_test.go +++ b/client/pkg/transport/keepalive_listener_test.go @@ -49,11 +49,10 @@ func TestNewKeepAliveListener(t *testing.T) { } // tls - tlsinfo, del, err := createSelfCert() + tlsinfo, err := createSelfCert(t) if err != nil { t.Fatalf("unable to create tmpfile: %v", err) } - defer del() tlsInfo := TLSInfo{CertFile: tlsinfo.CertFile, KeyFile: tlsinfo.KeyFile} tlsInfo.parseFunc = fakeCertificateParserFunc(tls.Certificate{}, nil) tlscfg, err := tlsInfo.ServerConfig() diff --git a/client/pkg/transport/listener_test.go b/client/pkg/transport/listener_test.go index f1937d694ac4..b49e56fc77b2 100644 --- a/client/pkg/transport/listener_test.go +++ b/client/pkg/transport/listener_test.go @@ -28,20 +28,17 @@ import ( "go.uber.org/zap/zaptest" ) -func createSelfCert(hosts ...string) (*TLSInfo, func(), error) { - return createSelfCertEx("127.0.0.1") +func createSelfCert(t *testing.T, hosts ...string) (*TLSInfo, error) { + return createSelfCertEx(t, "127.0.0.1") } -func createSelfCertEx(host string, additionalUsages ...x509.ExtKeyUsage) (*TLSInfo, func(), error) { - d, terr := os.MkdirTemp("", "etcd-test-tls-") - if terr != nil { - return nil, nil, terr - } +func createSelfCertEx(t *testing.T, host string, additionalUsages ...x509.ExtKeyUsage) (*TLSInfo, error) { + d := t.TempDir() info, err := SelfCert(zap.NewExample(), d, []string{host + ":0"}, 1, additionalUsages...) if err != nil { - return nil, nil, err + return nil, err } - return &info, func() { os.RemoveAll(d) }, nil + return &info, nil } func fakeCertificateParserFunc(cert tls.Certificate, err error) func(certPEMBlock, keyPEMBlock []byte) (tls.Certificate, error) { @@ -53,20 +50,18 @@ func fakeCertificateParserFunc(cert tls.Certificate, err error) func(certPEMBloc // TestNewListenerTLSInfo tests that NewListener with valid TLSInfo returns // a TLS listener that accepts TLS connections. func TestNewListenerTLSInfo(t *testing.T) { - tlsInfo, del, err := createSelfCert() + tlsInfo, err := createSelfCert(t) if err != nil { t.Fatalf("unable to create cert: %v", err) } - defer del() testNewListenerTLSInfoAccept(t, *tlsInfo) } func TestNewListenerWithOpts(t *testing.T) { - tlsInfo, del, err := createSelfCert() + tlsInfo, err := createSelfCert(t) if err != nil { t.Fatalf("unable to create cert: %v", err) } - defer del() tests := map[string]struct { opts []ListenerOption @@ -124,11 +119,10 @@ func TestNewListenerWithOpts(t *testing.T) { } func TestNewListenerWithSocketOpts(t *testing.T) { - tlsInfo, del, err := createSelfCert() + tlsInfo, err := createSelfCert(t) if err != nil { t.Fatalf("unable to create cert: %v", err) } - defer del() tests := map[string]struct { opts []ListenerOption @@ -257,21 +251,19 @@ func TestNewListenerTLSInfoSkipClientSANVerify(t *testing.T) { } func testNewListenerTLSInfoClientCheck(t *testing.T, skipClientSANVerify, goodClientHost, acceptExpected bool) { - tlsInfo, del, err := createSelfCert() + tlsInfo, err := createSelfCert(t) if err != nil { t.Fatalf("unable to create cert: %v", err) } - defer del() host := "127.0.0.222" if goodClientHost { host = "127.0.0.1" } - clientTLSInfo, del2, err := createSelfCertEx(host, x509.ExtKeyUsageClientAuth) + clientTLSInfo, err := createSelfCertEx(t, host, x509.ExtKeyUsageClientAuth) if err != nil { t.Fatalf("unable to create cert: %v", err) } - defer del2() tlsInfo.SkipClientSANVerify = skipClientSANVerify tlsInfo.TrustedCAFile = clientTLSInfo.CertFile @@ -344,11 +336,10 @@ func TestNewListenerTLSEmptyInfo(t *testing.T) { } func TestNewTransportTLSInfo(t *testing.T) { - tlsinfo, del, err := createSelfCert() + tlsinfo, err := createSelfCert(t) if err != nil { t.Fatalf("unable to create cert: %v", err) } - defer del() tests := []TLSInfo{ {}, @@ -416,11 +407,10 @@ func TestTLSInfoEmpty(t *testing.T) { } func TestTLSInfoMissingFields(t *testing.T) { - tlsinfo, del, err := createSelfCert() + tlsinfo, err := createSelfCert(t) if err != nil { t.Fatalf("unable to create cert: %v", err) } - defer del() tests := []TLSInfo{ {CertFile: tlsinfo.CertFile}, @@ -441,11 +431,10 @@ func TestTLSInfoMissingFields(t *testing.T) { } func TestTLSInfoParseFuncError(t *testing.T) { - tlsinfo, del, err := createSelfCert() + tlsinfo, err := createSelfCert(t) if err != nil { t.Fatalf("unable to create cert: %v", err) } - defer del() tests := []struct { info TLSInfo @@ -474,11 +463,10 @@ func TestTLSInfoParseFuncError(t *testing.T) { func TestTLSInfoConfigFuncs(t *testing.T) { ln := zaptest.NewLogger(t) - tlsinfo, del, err := createSelfCert() + tlsinfo, err := createSelfCert(t) if err != nil { t.Fatalf("unable to create cert: %v", err) } - defer del() tests := []struct { info TLSInfo @@ -531,11 +519,7 @@ func TestNewListenerUnixSocket(t *testing.T) { // TestNewListenerTLSInfoSelfCert tests that a new certificate accepts connections. func TestNewListenerTLSInfoSelfCert(t *testing.T) { - tmpdir, err := os.MkdirTemp(os.TempDir(), "tlsdir") - if err != nil { - t.Fatal(err) - } - defer os.RemoveAll(tmpdir) + tmpdir := t.TempDir() tlsinfo, err := SelfCert(zap.NewExample(), tmpdir, []string{"127.0.0.1"}, 1) if err != nil { t.Fatal(err) diff --git a/client/pkg/transport/transport_test.go b/client/pkg/transport/transport_test.go index afd325da4f61..315f32cf2dca 100644 --- a/client/pkg/transport/transport_test.go +++ b/client/pkg/transport/transport_test.go @@ -25,11 +25,10 @@ import ( // TestNewTransportTLSInvalidCipherSuitesTLS12 expects a client with invalid // cipher suites fail to handshake with the server. func TestNewTransportTLSInvalidCipherSuitesTLS12(t *testing.T) { - tlsInfo, del, err := createSelfCert() + tlsInfo, err := createSelfCert(t) if err != nil { t.Fatalf("unable to create cert: %v", err) } - defer del() cipherSuites := []uint16{ tls.TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256, diff --git a/server/embed/auth_test.go b/server/embed/auth_test.go index 57c0a3644bed..a09e618f66c8 100644 --- a/server/embed/auth_test.go +++ b/server/embed/auth_test.go @@ -16,18 +16,13 @@ package embed import ( "context" - "os" "testing" "go.etcd.io/etcd/server/v3/etcdserver/api/v3client" ) func TestEnableAuth(t *testing.T) { - tdir, err := os.MkdirTemp(os.TempDir(), "auth-test") - if err != nil { - t.Fatal(err) - } - defer os.RemoveAll(tdir) + tdir := t.TempDir() cfg := NewConfig() cfg.Dir = tdir e, err := StartEtcd(cfg) diff --git a/server/embed/serve_test.go b/server/embed/serve_test.go index 4773107de0a9..1d3cdec93622 100644 --- a/server/embed/serve_test.go +++ b/server/embed/serve_test.go @@ -25,11 +25,7 @@ import ( // TestStartEtcdWrongToken ensures that StartEtcd with wrong configs returns with error. func TestStartEtcdWrongToken(t *testing.T) { - tdir, err := os.MkdirTemp(t.TempDir(), "token-test") - - if err != nil { - t.Fatal(err) - } + tdir := t.TempDir() cfg := NewConfig() @@ -47,7 +43,7 @@ func TestStartEtcdWrongToken(t *testing.T) { cfg.Dir = tdir cfg.AuthToken = "wrong-token" - if _, err = StartEtcd(cfg); err != auth.ErrInvalidAuthOpts { + if _, err := StartEtcd(cfg); err != auth.ErrInvalidAuthOpts { t.Fatalf("expected %v, got %v", auth.ErrInvalidAuthOpts, err) } } diff --git a/server/etcdserver/api/rafthttp/snapshot_test.go b/server/etcdserver/api/rafthttp/snapshot_test.go index 69dfad81e227..b1d8cdbbdeb8 100644 --- a/server/etcdserver/api/rafthttp/snapshot_test.go +++ b/server/etcdserver/api/rafthttp/snapshot_test.go @@ -94,11 +94,7 @@ func TestSnapshotSend(t *testing.T) { } func testSnapshotSend(t *testing.T, sm *snap.Message) (bool, []os.DirEntry) { - d, err := os.MkdirTemp(os.TempDir(), "snapdir") - if err != nil { - t.Fatal(err) - } - defer os.RemoveAll(d) + d := t.TempDir() r := &fakeRaft{} tr := &Transport{pipelineRt: &http.Transport{}, ClusterID: types.ID(1), Raft: r} diff --git a/server/etcdserver/server_test.go b/server/etcdserver/server_test.go index 32d368d8fc63..547442abb7a3 100644 --- a/server/etcdserver/server_test.go +++ b/server/etcdserver/server_test.go @@ -1086,11 +1086,7 @@ func TestSnapshotOrdering(t *testing.T) { cl := membership.NewCluster(lg) cl.SetStore(st) - testdir, err := os.MkdirTemp(t.TempDir(), "testsnapdir") - if err != nil { - t.Fatalf("couldn't open tempdir (%v)", err) - } - defer os.RemoveAll(testdir) + testdir := t.TempDir() snapdir := filepath.Join(testdir, "member", "snap") if err := os.MkdirAll(snapdir, 0755); err != nil { @@ -1242,11 +1238,7 @@ func TestConcurrentApplyAndSnapshotV3(t *testing.T) { cl := membership.NewCluster(lg) cl.SetStore(st) - testdir, err := os.MkdirTemp(t.TempDir(), "testsnapdir") - if err != nil { - t.Fatalf("Couldn't open tempdir (%v)", err) - } - defer os.RemoveAll(testdir) + testdir := t.TempDir() if err := os.MkdirAll(testdir+"/member/snap", 0755); err != nil { t.Fatalf("Couldn't make snap dir (%v)", err) } diff --git a/server/lease/lessor_test.go b/server/lease/lessor_test.go index 27ca86fd8823..740294c50848 100644 --- a/server/lease/lessor_test.go +++ b/server/lease/lessor_test.go @@ -669,10 +669,7 @@ func (fd *fakeDeleter) DeleteRange(key, end []byte) (int64, int64) { } func NewTestBackend(t *testing.T) (string, backend.Backend) { - tmpPath, err := os.MkdirTemp("", "lease") - if err != nil { - t.Fatalf("failed to create tmpdir (%v)", err) - } + tmpPath := t.TempDir() bcfg := backend.DefaultBackendConfig() bcfg.Path = filepath.Join(tmpPath, "be") return tmpPath, backend.New(bcfg) diff --git a/server/storage/wal/file_pipeline_test.go b/server/storage/wal/file_pipeline_test.go index 49079c60ef9f..30ce5cc04acf 100644 --- a/server/storage/wal/file_pipeline_test.go +++ b/server/storage/wal/file_pipeline_test.go @@ -16,18 +16,13 @@ package wal import ( "math" - "os" "testing" "go.uber.org/zap" ) func TestFilePipeline(t *testing.T) { - tdir, err := os.MkdirTemp(os.TempDir(), "wal-test") - if err != nil { - t.Fatal(err) - } - defer os.RemoveAll(tdir) + tdir := t.TempDir() fp := newFilePipeline(zap.NewExample(), tdir, SegmentSizeBytes) defer fp.Close() @@ -40,11 +35,7 @@ func TestFilePipeline(t *testing.T) { } func TestFilePipelineFailPreallocate(t *testing.T) { - tdir, err := os.MkdirTemp(os.TempDir(), "wal-test") - if err != nil { - t.Fatal(err) - } - defer os.RemoveAll(tdir) + tdir := t.TempDir() fp := newFilePipeline(zap.NewExample(), tdir, math.MaxInt64) defer fp.Close() @@ -56,11 +47,7 @@ func TestFilePipelineFailPreallocate(t *testing.T) { } func TestFilePipelineFailLockFile(t *testing.T) { - tdir, err := os.MkdirTemp(os.TempDir(), "wal-test") - if err != nil { - t.Fatal(err) - } - os.RemoveAll(tdir) + tdir := t.TempDir() fp := newFilePipeline(zap.NewExample(), tdir, math.MaxInt64) defer fp.Close() diff --git a/server/storage/wal/repair_test.go b/server/storage/wal/repair_test.go index 4aee003f031d..e1c3e2a807d9 100644 --- a/server/storage/wal/repair_test.go +++ b/server/storage/wal/repair_test.go @@ -43,11 +43,7 @@ func TestRepairTruncate(t *testing.T) { } func testRepair(t *testing.T, ents [][]raftpb.Entry, corrupt corruptFunc, expectedEnts int) { - p, err := os.MkdirTemp(os.TempDir(), "waltest") - if err != nil { - t.Fatal(err) - } - defer os.RemoveAll(p) + p := t.TempDir() // create WAL w, err := Create(zap.NewExample(), p, nil) @@ -183,11 +179,7 @@ func TestRepairWriteTearMiddle(t *testing.T) { } func TestRepairFailDeleteDir(t *testing.T) { - p, err := os.MkdirTemp(os.TempDir(), "waltest") - if err != nil { - t.Fatal(err) - } - defer os.RemoveAll(p) + p := t.TempDir() w, err := Create(zap.NewExample(), p, nil) if err != nil { diff --git a/server/storage/wal/wal_bench_test.go b/server/storage/wal/wal_bench_test.go index b3e03bc24f56..ca7e98e1b406 100644 --- a/server/storage/wal/wal_bench_test.go +++ b/server/storage/wal/wal_bench_test.go @@ -15,7 +15,6 @@ package wal import ( - "os" "testing" "go.uber.org/zap" @@ -36,11 +35,7 @@ func BenchmarkWrite1000EntryBatch500(b *testing.B) { benchmarkWriteEntry(b, func BenchmarkWrite1000EntryBatch1000(b *testing.B) { benchmarkWriteEntry(b, 1000, 1000) } func benchmarkWriteEntry(b *testing.B, size int, batch int) { - p, err := os.MkdirTemp(os.TempDir(), "waltest") - if err != nil { - b.Fatal(err) - } - defer os.RemoveAll(p) + p := b.TempDir() w, err := Create(zap.NewExample(), p, []byte("somedata")) if err != nil { diff --git a/server/storage/wal/wal_test.go b/server/storage/wal/wal_test.go index ed698cc9f9b1..5a326476e9d8 100644 --- a/server/storage/wal/wal_test.go +++ b/server/storage/wal/wal_test.go @@ -44,11 +44,7 @@ var ( ) func TestNew(t *testing.T) { - p, err := os.MkdirTemp(t.TempDir(), "waltest") - if err != nil { - t.Fatal(err) - } - defer os.RemoveAll(p) + p := t.TempDir() w, err := Create(zap.NewExample(), p, []byte("somedata")) if err != nil { @@ -98,29 +94,21 @@ func TestNew(t *testing.T) { } func TestCreateFailFromPollutedDir(t *testing.T) { - p, err := os.MkdirTemp(t.TempDir(), "waltest") - if err != nil { - t.Fatal(err) - } - defer os.RemoveAll(p) + p := t.TempDir() os.WriteFile(filepath.Join(p, "test.wal"), []byte("data"), os.ModeTemporary) - _, err = Create(zap.NewExample(), p, []byte("data")) + _, err := Create(zap.NewExample(), p, []byte("data")) if err != os.ErrExist { t.Fatalf("expected %v, got %v", os.ErrExist, err) } } func TestWalCleanup(t *testing.T) { - testRoot, err := os.MkdirTemp(t.TempDir(), "waltestroot") - if err != nil { - t.Fatal(err) - } + testRoot := t.TempDir() p, err := os.MkdirTemp(testRoot, "waltest") if err != nil { t.Fatal(err) } - defer os.RemoveAll(testRoot) logger := zap.NewExample() w, err := Create(logger, p, []byte("")) @@ -143,11 +131,7 @@ func TestWalCleanup(t *testing.T) { } func TestCreateFailFromNoSpaceLeft(t *testing.T) { - p, err := os.MkdirTemp(t.TempDir(), "waltest") - if err != nil { - t.Fatal(err) - } - defer os.RemoveAll(p) + p := t.TempDir() oldSegmentSizeBytes := SegmentSizeBytes defer func() { @@ -155,31 +139,23 @@ func TestCreateFailFromNoSpaceLeft(t *testing.T) { }() SegmentSizeBytes = math.MaxInt64 - _, err = Create(zap.NewExample(), p, []byte("data")) + _, err := Create(zap.NewExample(), p, []byte("data")) if err == nil { // no space left on device t.Fatalf("expected error 'no space left on device', got nil") } } func TestNewForInitedDir(t *testing.T) { - p, err := os.MkdirTemp(t.TempDir(), "waltest") - if err != nil { - t.Fatal(err) - } - defer os.RemoveAll(p) + p := t.TempDir() os.Create(filepath.Join(p, walName(0, 0))) - if _, err = Create(zap.NewExample(), p, nil); err == nil || err != os.ErrExist { + if _, err := Create(zap.NewExample(), p, nil); err == nil || err != os.ErrExist { t.Errorf("err = %v, want %v", err, os.ErrExist) } } func TestOpenAtIndex(t *testing.T) { - dir, err := os.MkdirTemp(t.TempDir(), "waltest") - if err != nil { - t.Fatal(err) - } - defer os.RemoveAll(dir) + dir := t.TempDir() f, err := os.Create(filepath.Join(dir, walName(0, 0))) if err != nil { @@ -218,11 +194,7 @@ func TestOpenAtIndex(t *testing.T) { } w.Close() - emptydir, err := os.MkdirTemp(t.TempDir(), "waltestempty") - if err != nil { - t.Fatal(err) - } - defer os.RemoveAll(emptydir) + emptydir := t.TempDir() if _, err = Open(zap.NewExample(), emptydir, walpb.Snapshot{}); err != ErrFileNotFound { t.Errorf("err = %v, want %v", err, ErrFileNotFound) } @@ -233,10 +205,7 @@ func TestOpenAtIndex(t *testing.T) { // it corrupts one of the files by completely truncating it. func TestVerify(t *testing.T) { lg := zaptest.NewLogger(t) - walDir, err := os.MkdirTemp(t.TempDir(), "waltest") - if err != nil { - t.Fatal(err) - } + walDir := t.TempDir() // create WAL w, err := Create(lg, walDir, nil) @@ -285,11 +254,7 @@ func TestVerify(t *testing.T) { // TODO: split it into smaller tests for better readability func TestCut(t *testing.T) { - p, err := os.MkdirTemp(t.TempDir(), "waltest") - if err != nil { - t.Fatal(err) - } - defer os.RemoveAll(p) + p := t.TempDir() w, err := Create(zap.NewExample(), p, nil) if err != nil { @@ -347,11 +312,7 @@ func TestCut(t *testing.T) { } func TestSaveWithCut(t *testing.T) { - p, err := os.MkdirTemp(t.TempDir(), "waltest") - if err != nil { - t.Fatal(err) - } - defer os.RemoveAll(p) + p := t.TempDir() w, err := Create(zap.NewExample(), p, []byte("metadata")) if err != nil { @@ -410,11 +371,7 @@ func TestSaveWithCut(t *testing.T) { } func TestRecover(t *testing.T) { - p, err := os.MkdirTemp(t.TempDir(), "waltest") - if err != nil { - t.Fatal(err) - } - defer os.RemoveAll(p) + p := t.TempDir() w, err := Create(zap.NewExample(), p, []byte("metadata")) if err != nil { @@ -525,11 +482,7 @@ func TestScanWalName(t *testing.T) { } func TestRecoverAfterCut(t *testing.T) { - p, err := os.MkdirTemp(t.TempDir(), "waltest") - if err != nil { - t.Fatal(err) - } - defer os.RemoveAll(p) + p := t.TempDir() md, err := Create(zap.NewExample(), p, []byte("metadata")) if err != nil { @@ -583,11 +536,7 @@ func TestRecoverAfterCut(t *testing.T) { } func TestOpenAtUncommittedIndex(t *testing.T) { - p, err := os.MkdirTemp(t.TempDir(), "waltest") - if err != nil { - t.Fatal(err) - } - defer os.RemoveAll(p) + p := t.TempDir() w, err := Create(zap.NewExample(), p, nil) if err != nil { @@ -617,11 +566,7 @@ func TestOpenAtUncommittedIndex(t *testing.T) { // it releases the lock of part of data, and excepts that OpenForRead // can read out all files even if some are locked for write. func TestOpenForRead(t *testing.T) { - p, err := os.MkdirTemp(t.TempDir(), "waltest") - if err != nil { - t.Fatal(err) - } - defer os.RemoveAll(p) + p := t.TempDir() // create WAL w, err := Create(zap.NewExample(), p, nil) if err != nil { @@ -658,11 +603,7 @@ func TestOpenForRead(t *testing.T) { } func TestOpenWithMaxIndex(t *testing.T) { - p, err := os.MkdirTemp(t.TempDir(), "waltest") - if err != nil { - t.Fatal(err) - } - defer os.RemoveAll(p) + p := t.TempDir() // create WAL w, err := Create(zap.NewExample(), p, nil) if err != nil { @@ -701,11 +642,7 @@ func TestSaveEmpty(t *testing.T) { } func TestReleaseLockTo(t *testing.T) { - p, err := os.MkdirTemp(t.TempDir(), "waltest") - if err != nil { - t.Fatal(err) - } - defer os.RemoveAll(p) + p := t.TempDir() // create WAL w, err := Create(zap.NewExample(), p, nil) defer func() { @@ -773,11 +710,7 @@ func TestReleaseLockTo(t *testing.T) { // TestTailWriteNoSlackSpace ensures that tail writes append if there's no preallocated space. func TestTailWriteNoSlackSpace(t *testing.T) { - p, err := os.MkdirTemp(t.TempDir(), "waltest") - if err != nil { - t.Fatal(err) - } - defer os.RemoveAll(p) + p := t.TempDir() // create initial WAL w, err := Create(zap.NewExample(), p, []byte("metadata")) @@ -839,11 +772,8 @@ func TestTailWriteNoSlackSpace(t *testing.T) { // TestRestartCreateWal ensures that an interrupted WAL initialization is clobbered on restart func TestRestartCreateWal(t *testing.T) { - p, err := os.MkdirTemp(t.TempDir(), "waltest") - if err != nil { - t.Fatal(err) - } - defer os.RemoveAll(p) + p := t.TempDir() + var err error // make temporary directory so it looks like initialization is interrupted tmpdir := filepath.Clean(p) + ".tmp" @@ -879,11 +809,7 @@ func TestOpenOnTornWrite(t *testing.T) { clobberIdx := 20 overwriteEntries := 5 - p, err := os.MkdirTemp(t.TempDir(), "waltest") - if err != nil { - t.Fatal(err) - } - defer os.RemoveAll(p) + p := t.TempDir() w, err := Create(zap.NewExample(), p, nil) defer func() { if err = w.Close(); err != nil && err != os.ErrInvalid { @@ -964,11 +890,7 @@ func TestOpenOnTornWrite(t *testing.T) { } func TestRenameFail(t *testing.T) { - p, err := os.MkdirTemp(t.TempDir(), "waltest") - if err != nil { - t.Fatal(err) - } - defer os.RemoveAll(p) + p := t.TempDir() oldSegmentSizeBytes := SegmentSizeBytes defer func() { @@ -976,10 +898,7 @@ func TestRenameFail(t *testing.T) { }() SegmentSizeBytes = math.MaxInt64 - tp, terr := os.MkdirTemp(t.TempDir(), "waltest") - if terr != nil { - t.Fatal(terr) - } + tp := t.TempDir() os.RemoveAll(tp) w := &WAL{ @@ -994,11 +913,7 @@ func TestRenameFail(t *testing.T) { // TestReadAllFail ensure ReadAll error if used without opening the WAL func TestReadAllFail(t *testing.T) { - dir, err := os.MkdirTemp(t.TempDir(), "waltest") - if err != nil { - t.Fatal(err) - } - defer os.RemoveAll(dir) + dir := t.TempDir() // create initial WAL f, err := Create(zap.NewExample(), dir, []byte("metadata")) @@ -1016,11 +931,7 @@ func TestReadAllFail(t *testing.T) { // TestValidSnapshotEntries ensures ValidSnapshotEntries returns all valid wal snapshot entries, accounting // for hardstate func TestValidSnapshotEntries(t *testing.T) { - p, err := os.MkdirTemp(t.TempDir(), "waltest") - if err != nil { - t.Fatal(err) - } - defer os.RemoveAll(p) + p := t.TempDir() snap0 := walpb.Snapshot{} snap1 := walpb.Snapshot{Index: 1, Term: 1, ConfState: &confState} state1 := raftpb.HardState{Commit: 1, Term: 1} @@ -1073,11 +984,7 @@ func TestValidSnapshotEntriesAfterPurgeWal(t *testing.T) { defer func() { SegmentSizeBytes = oldSegmentSizeBytes }() - p, err := os.MkdirTemp(t.TempDir(), "waltest") - if err != nil { - t.Fatal(err) - } - defer os.RemoveAll(p) + p := t.TempDir() snap0 := walpb.Snapshot{} snap1 := walpb.Snapshot{Index: 1, Term: 1, ConfState: &confState} state1 := raftpb.HardState{Commit: 1, Term: 1} diff --git a/tests/e2e/etcd_config_test.go b/tests/e2e/etcd_config_test.go index 1c30d230bec2..e00421024d10 100644 --- a/tests/e2e/etcd_config_test.go +++ b/tests/e2e/etcd_config_test.go @@ -47,11 +47,7 @@ func TestEtcdMultiPeer(t *testing.T) { peers, tmpdirs := make([]string, 3), make([]string, 3) for i := range peers { peers[i] = fmt.Sprintf("e%d=http://127.0.0.1:%d", i, e2e.EtcdProcessBasePort+i) - d, err := os.MkdirTemp("", fmt.Sprintf("e%d.etcd", i)) - if err != nil { - t.Fatal(err) - } - tmpdirs[i] = d + tmpdirs[i] = t.TempDir() } ic := strings.Join(peers, ",") @@ -61,7 +57,6 @@ func TestEtcdMultiPeer(t *testing.T) { if procs[i] != nil { procs[i].Stop() } - os.RemoveAll(tmpdirs[i]) } }() for i := range procs { @@ -93,11 +88,7 @@ func TestEtcdMultiPeer(t *testing.T) { func TestEtcdUnixPeers(t *testing.T) { e2e.SkipInShortMode(t) - d, err := os.MkdirTemp("", "e1.etcd") - if err != nil { - t.Fatal(err) - } - defer os.RemoveAll(d) + d := t.TempDir() proc, err := e2e.SpawnCmd( []string{ e2e.BinDir + "/etcd", @@ -127,11 +118,7 @@ func TestEtcdPeerCNAuth(t *testing.T) { peers, tmpdirs := make([]string, 3), make([]string, 3) for i := range peers { peers[i] = fmt.Sprintf("e%d=https://127.0.0.1:%d", i, e2e.EtcdProcessBasePort+i) - d, err := os.MkdirTemp("", fmt.Sprintf("e%d.etcd", i)) - if err != nil { - t.Fatal(err) - } - tmpdirs[i] = d + tmpdirs[i] = t.TempDir() } ic := strings.Join(peers, ",") @@ -141,7 +128,6 @@ func TestEtcdPeerCNAuth(t *testing.T) { if procs[i] != nil { procs[i].Stop() } - os.RemoveAll(tmpdirs[i]) } }() @@ -210,11 +196,7 @@ func TestEtcdPeerNameAuth(t *testing.T) { peers, tmpdirs := make([]string, 3), make([]string, 3) for i := range peers { peers[i] = fmt.Sprintf("e%d=https://127.0.0.1:%d", i, e2e.EtcdProcessBasePort+i) - d, err := os.MkdirTemp("", fmt.Sprintf("e%d.etcd", i)) - if err != nil { - t.Fatal(err) - } - tmpdirs[i] = d + tmpdirs[i] = t.TempDir() } ic := strings.Join(peers, ",") diff --git a/tests/integration/member_test.go b/tests/integration/member_test.go index f358e771df9c..9443e1ba29e5 100644 --- a/tests/integration/member_test.go +++ b/tests/integration/member_test.go @@ -17,7 +17,6 @@ package integration import ( "context" "fmt" - "os" "testing" "github.com/stretchr/testify/assert" @@ -67,11 +66,7 @@ func TestLaunchDuplicateMemberShouldFail(t *testing.T) { size := 3 c := integration.NewCluster(t, &integration.ClusterConfig{Size: size}) m := c.Members[0].Clone(t) - var err error - m.DataDir, err = os.MkdirTemp(t.TempDir(), "etcd") - if err != nil { - t.Fatal(err) - } + m.DataDir = t.TempDir() defer c.Terminate(t) if err := m.Launch(); err == nil { diff --git a/tests/integration/v3_grpc_test.go b/tests/integration/v3_grpc_test.go index 620cc5d9c1e0..78b5c6c66cf7 100644 --- a/tests/integration/v3_grpc_test.go +++ b/tests/integration/v3_grpc_test.go @@ -1626,40 +1626,28 @@ func TestTLSGRPCAcceptSecureAll(t *testing.T) { // when all certs are atomically replaced by directory renaming. // And expects server to reject client requests, and vice versa. func TestTLSReloadAtomicReplace(t *testing.T) { - tmpDir, err := os.MkdirTemp(t.TempDir(), "fixtures-tmp") - if err != nil { - t.Fatal(err) - } + tmpDir := t.TempDir() os.RemoveAll(tmpDir) - defer os.RemoveAll(tmpDir) - certsDir, err := os.MkdirTemp(t.TempDir(), "fixtures-to-load") - if err != nil { - t.Fatal(err) - } - defer os.RemoveAll(certsDir) + certsDir := t.TempDir() - certsDirExp, err := os.MkdirTemp(t.TempDir(), "fixtures-expired") - if err != nil { - t.Fatal(err) - } - defer os.RemoveAll(certsDirExp) + certsDirExp := t.TempDir() cloneFunc := func() transport.TLSInfo { tlsInfo, terr := copyTLSFiles(integration.TestTLSInfo, certsDir) if terr != nil { t.Fatal(terr) } - if _, err = copyTLSFiles(integration.TestTLSInfoExpired, certsDirExp); err != nil { + if _, err := copyTLSFiles(integration.TestTLSInfoExpired, certsDirExp); err != nil { t.Fatal(err) } return tlsInfo } replaceFunc := func() { - if err = os.Rename(certsDir, tmpDir); err != nil { + if err := os.Rename(certsDir, tmpDir); err != nil { t.Fatal(err) } - if err = os.Rename(certsDirExp, certsDir); err != nil { + if err := os.Rename(certsDirExp, certsDir); err != nil { t.Fatal(err) } // after rename, @@ -1668,13 +1656,13 @@ func TestTLSReloadAtomicReplace(t *testing.T) { // 'certsDirExp' does not exist } revertFunc := func() { - if err = os.Rename(tmpDir, certsDirExp); err != nil { + if err := os.Rename(tmpDir, certsDirExp); err != nil { t.Fatal(err) } - if err = os.Rename(certsDir, tmpDir); err != nil { + if err := os.Rename(certsDir, tmpDir); err != nil { t.Fatal(err) } - if err = os.Rename(certsDirExp, certsDir); err != nil { + if err := os.Rename(certsDirExp, certsDir); err != nil { t.Fatal(err) } } @@ -1685,11 +1673,7 @@ func TestTLSReloadAtomicReplace(t *testing.T) { // when new certs are copied over, one by one. And expects server // to reject client requests, and vice versa. func TestTLSReloadCopy(t *testing.T) { - certsDir, err := os.MkdirTemp(t.TempDir(), "fixtures-to-load") - if err != nil { - t.Fatal(err) - } - defer os.RemoveAll(certsDir) + certsDir := t.TempDir() cloneFunc := func() transport.TLSInfo { tlsInfo, terr := copyTLSFiles(integration.TestTLSInfo, certsDir) @@ -1699,12 +1683,12 @@ func TestTLSReloadCopy(t *testing.T) { return tlsInfo } replaceFunc := func() { - if _, err = copyTLSFiles(integration.TestTLSInfoExpired, certsDir); err != nil { + if _, err := copyTLSFiles(integration.TestTLSInfoExpired, certsDir); err != nil { t.Fatal(err) } } revertFunc := func() { - if _, err = copyTLSFiles(integration.TestTLSInfo, certsDir); err != nil { + if _, err := copyTLSFiles(integration.TestTLSInfo, certsDir); err != nil { t.Fatal(err) } } @@ -1715,11 +1699,7 @@ func TestTLSReloadCopy(t *testing.T) { // when new certs are copied over, one by one. And expects server // to reject client requests, and vice versa. func TestTLSReloadCopyIPOnly(t *testing.T) { - certsDir, err := os.MkdirTemp(t.TempDir(), "fixtures-to-load") - if err != nil { - t.Fatal(err) - } - defer os.RemoveAll(certsDir) + certsDir := t.TempDir() cloneFunc := func() transport.TLSInfo { tlsInfo, terr := copyTLSFiles(integration.TestTLSInfoIP, certsDir) @@ -1729,12 +1709,12 @@ func TestTLSReloadCopyIPOnly(t *testing.T) { return tlsInfo } replaceFunc := func() { - if _, err = copyTLSFiles(integration.TestTLSInfoExpiredIP, certsDir); err != nil { + if _, err := copyTLSFiles(integration.TestTLSInfoExpiredIP, certsDir); err != nil { t.Fatal(err) } } revertFunc := func() { - if _, err = copyTLSFiles(integration.TestTLSInfoIP, certsDir); err != nil { + if _, err := copyTLSFiles(integration.TestTLSInfoIP, certsDir); err != nil { t.Fatal(err) } } diff --git a/tools/etcd-dump-logs/etcd-dump-log_test.go b/tools/etcd-dump-logs/etcd-dump-log_test.go index bd0cb056e8d2..bef7e0648615 100644 --- a/tools/etcd-dump-logs/etcd-dump-log_test.go +++ b/tools/etcd-dump-logs/etcd-dump-log_test.go @@ -47,11 +47,7 @@ func TestEtcdDumpLogEntryType(t *testing.T) { decoder_correctoutputformat := filepath.Join(binDir, "/testdecoder/decoder_correctoutputformat.sh") decoder_wrongoutputformat := filepath.Join(binDir, "/testdecoder/decoder_wrongoutputformat.sh") - p, err := os.MkdirTemp(os.TempDir(), "etcddumplogstest") - if err != nil { - t.Fatal(err) - } - defer os.RemoveAll(p) + p := t.TempDir() memberdir := filepath.Join(p, "member") err = os.Mkdir(memberdir, 0744) From ee6306b9f9b8650c89526b2c448121750190234c Mon Sep 17 00:00:00 2001 From: Marek Siarkowicz Date: Thu, 20 Jan 2022 16:12:07 +0100 Subject: [PATCH 087/258] Migrate RemoveMember and AddMember to V3 API --- tests/framework/integration/cluster.go | 22 +++------- tests/integration/cluster_test.go | 58 ++++++++++++++------------ 2 files changed, 37 insertions(+), 43 deletions(-) diff --git a/tests/framework/integration/cluster.go b/tests/framework/integration/cluster.go index f7fc08677f8f..f5dd7344acd5 100644 --- a/tests/framework/integration/cluster.go +++ b/tests/framework/integration/cluster.go @@ -318,9 +318,8 @@ func (c *Cluster) addMember(t testutil.TB) types.URLs { // send add request to the Cluster var err error for i := 0; i < len(c.Members); i++ { - clientURL := c.URL(i) peerURL := scheme + "://" + m.PeerListeners[0].Addr().String() - if err = c.AddMemberByURL(t, clientURL, peerURL); err == nil { + if err = c.AddMemberByURL(t, c.Members[i].Client, peerURL); err == nil { break } } @@ -343,11 +342,9 @@ func (c *Cluster) addMember(t testutil.TB) types.URLs { return m.PeerURLs } -func (c *Cluster) AddMemberByURL(t testutil.TB, clientURL, peerURL string) error { - cc := MustNewHTTPClient(t, []string{clientURL}, c.Cfg.ClientTLS) - ma := client.NewMembersAPI(cc) +func (c *Cluster) AddMemberByURL(t testutil.TB, cc *clientv3.Client, peerURL string) error { ctx, cancel := context.WithTimeout(context.Background(), RequestTimeout) - _, err := ma.Add(ctx, peerURL) + _, err := cc.MemberAdd(ctx, []string{peerURL}) cancel() if err != nil { return err @@ -364,18 +361,11 @@ func (c *Cluster) AddMember(t testutil.TB) types.URLs { return c.addMember(t) } -func (c *Cluster) MustRemoveMember(t testutil.TB, id uint64) { - if err := c.RemoveMember(t, id); err != nil { - t.Fatal(err) - } -} - -func (c *Cluster) RemoveMember(t testutil.TB, id uint64) error { +func (c *Cluster) RemoveMember(t testutil.TB, cc *clientv3.Client, id uint64) error { // send remove request to the Cluster - cc := MustNewHTTPClient(t, c.URLs(), c.Cfg.ClientTLS) - ma := client.NewMembersAPI(cc) + ctx, cancel := context.WithTimeout(context.Background(), RequestTimeout) - err := ma.Remove(ctx, types.ID(id).String()) + _, err := cc.MemberRemove(ctx, id) cancel() if err != nil { return err diff --git a/tests/integration/cluster_test.go b/tests/integration/cluster_test.go index 8db6f30d5798..5f239c91e917 100644 --- a/tests/integration/cluster_test.go +++ b/tests/integration/cluster_test.go @@ -25,7 +25,6 @@ import ( "testing" "time" - "go.etcd.io/etcd/client/v2" clientv3 "go.etcd.io/etcd/client/v3" "go.etcd.io/etcd/server/v3/etcdserver" "go.etcd.io/etcd/tests/v3/framework/integration" @@ -104,7 +103,7 @@ func testDecreaseClusterSize(t *testing.T, size int) { for i := 0; i < size-1; i++ { id := c.Members[len(c.Members)-1].Server.ID() // may hit second leader election on slow machines - if err := c.RemoveMember(t, uint64(id)); err != nil { + if err := c.RemoveMember(t, c.Members[0].Client, uint64(id)); err != nil { if strings.Contains(err.Error(), "no leader") { t.Logf("got leader error (%v)", err) i-- @@ -180,7 +179,9 @@ func TestAddMemberAfterClusterFullRotation(t *testing.T) { // remove all the previous three members and add in three new members. for i := 0; i < 3; i++ { - c.MustRemoveMember(t, uint64(c.Members[0].Server.ID())) + if err := c.RemoveMember(t, c.Members[0].Client, uint64(c.Members[1].Server.ID())); err != nil { + t.Fatal(err) + } c.WaitMembersForLeader(t, c.Members) c.AddMember(t) @@ -199,7 +200,9 @@ func TestIssue2681(t *testing.T) { c := integration.NewCluster(t, &integration.ClusterConfig{Size: 5}) defer c.Terminate(t) - c.MustRemoveMember(t, uint64(c.Members[4].Server.ID())) + if err := c.RemoveMember(t, c.Members[0].Client, uint64(c.Members[4].Server.ID())); err != nil { + t.Fatal(err) + } c.WaitMembersForLeader(t, c.Members) c.AddMember(t) @@ -223,7 +226,9 @@ func testIssue2746(t *testing.T, members int) { clusterMustProgress(t, c.Members) } - c.MustRemoveMember(t, uint64(c.Members[members-1].Server.ID())) + if err := c.RemoveMember(t, c.Members[0].Client, uint64(c.Members[members-1].Server.ID())); err != nil { + t.Fatal(err) + } c.WaitMembersForLeader(t, c.Members) c.AddMember(t) @@ -235,33 +240,32 @@ func testIssue2746(t *testing.T, members int) { func TestIssue2904(t *testing.T) { integration.BeforeTest(t) // start 1-member Cluster to ensure member 0 is the leader of the Cluster. - c := integration.NewCluster(t, &integration.ClusterConfig{Size: 1, UseBridge: true}) + c := integration.NewCluster(t, &integration.ClusterConfig{Size: 2, UseBridge: true}) defer c.Terminate(t) + c.WaitLeader(t) c.AddMember(t) - c.Members[1].Stop(t) + c.Members[2].Stop(t) // send remove member-1 request to the Cluster. - cc := integration.MustNewHTTPClient(t, c.URLs(), nil) - ma := client.NewMembersAPI(cc) ctx, cancel := context.WithTimeout(context.Background(), integration.RequestTimeout) // the proposal is not committed because member 1 is stopped, but the // proposal is appended to leader'Server raft log. - ma.Remove(ctx, c.Members[1].Server.ID().String()) + c.Members[0].Client.MemberRemove(ctx, uint64(c.Members[2].Server.ID())) cancel() // restart member, and expect it to send UpdateAttributes request. // the log in the leader is like this: // [..., remove 1, ..., update attr 1, ...] - c.Members[1].Restart(t) + c.Members[2].Restart(t) // when the member comes back, it ack the proposal to remove itself, // and apply it. - <-c.Members[1].Server.StopNotify() + <-c.Members[2].Server.StopNotify() // terminate removed member - c.Members[1].Client.Close() - c.Members[1].Terminate(t) - c.Members = c.Members[:1] + c.Members[2].Client.Close() + c.Members[2].Terminate(t) + c.Members = c.Members[:2] // wait member to be removed. c.WaitMembersMatch(t, c.HTTPMembers()) } @@ -329,12 +333,12 @@ func TestRejectUnhealthyAdd(t *testing.T) { // all attempts to add member should fail for i := 1; i < len(c.Members); i++ { - err := c.AddMemberByURL(t, c.URL(i), "unix://foo:12345") + err := c.AddMemberByURL(t, c.Members[i].Client, "unix://foo:12345") if err == nil { t.Fatalf("should have failed adding peer") } // TODO: client should return descriptive error codes for internal errors - if !strings.Contains(err.Error(), "has no leader") { + if !strings.Contains(err.Error(), "unhealthy cluster") { t.Errorf("unexpected error (%v)", err) } } @@ -347,7 +351,7 @@ func TestRejectUnhealthyAdd(t *testing.T) { // add member should succeed now that it'Server healthy var err error for i := 1; i < len(c.Members); i++ { - if err = c.AddMemberByURL(t, c.URL(i), "unix://foo:12345"); err == nil { + if err = c.AddMemberByURL(t, c.Members[i].Client, "unix://foo:12345"); err == nil { break } } @@ -366,15 +370,15 @@ func TestRejectUnhealthyRemove(t *testing.T) { // make cluster unhealthy and wait for downed peer; (3 up, 2 down) c.Members[0].Stop(t) c.Members[1].Stop(t) - c.WaitLeader(t) + leader := c.WaitLeader(t) // reject remove active member since (3,2)-(1,0) => (2,2) lacks quorum - err := c.RemoveMember(t, uint64(c.Members[2].Server.ID())) + err := c.RemoveMember(t, c.Members[leader].Client, uint64(c.Members[2].Server.ID())) if err == nil { - t.Fatalf("should reject quorum breaking remove") + t.Fatalf("should reject quorum breaking remove: %s", err) } // TODO: client should return more descriptive error codes for internal errors - if !strings.Contains(err.Error(), "has no leader") { + if !strings.Contains(err.Error(), "unhealthy cluster") { t.Errorf("unexpected error (%v)", err) } @@ -382,8 +386,8 @@ func TestRejectUnhealthyRemove(t *testing.T) { time.Sleep(time.Duration(integration.ElectionTicks * int(integration.TickDuration))) // permit remove dead member since (3,2) - (0,1) => (3,1) has quorum - if err = c.RemoveMember(t, uint64(c.Members[0].Server.ID())); err != nil { - t.Fatalf("should accept removing down member") + if err = c.RemoveMember(t, c.Members[2].Client, uint64(c.Members[0].Server.ID())); err != nil { + t.Fatalf("should accept removing down member: %s", err) } // bring cluster to (4,1) @@ -393,7 +397,7 @@ func TestRejectUnhealthyRemove(t *testing.T) { time.Sleep((3 * etcdserver.HealthInterval) / 2) // accept remove member since (4,1)-(1,0) => (3,1) has quorum - if err = c.RemoveMember(t, uint64(c.Members[0].Server.ID())); err != nil { + if err = c.RemoveMember(t, c.Members[1].Client, uint64(c.Members[0].Server.ID())); err != nil { t.Fatalf("expected to remove member, got error %v", err) } } @@ -405,7 +409,7 @@ func TestRestartRemoved(t *testing.T) { integration.BeforeTest(t) // 1. start single-member Cluster - c := integration.NewCluster(t, &integration.ClusterConfig{Size: 1, StrictReconfigCheck: true, UseBridge: true}) + c := integration.NewCluster(t, &integration.ClusterConfig{Size: 1, StrictReconfigCheck: true}) defer c.Terminate(t) // 2. add a new member @@ -417,7 +421,7 @@ func TestRestartRemoved(t *testing.T) { firstMember.KeepDataDirTerminate = true // 3. remove first member, shut down without deleting data - if err := c.RemoveMember(t, uint64(firstMember.Server.ID())); err != nil { + if err := c.RemoveMember(t, c.Members[1].Client, uint64(firstMember.Server.ID())); err != nil { t.Fatalf("expected to remove member, got error %v", err) } c.WaitLeader(t) From 81490c25d156ed2b93c03738190793618b7f8747 Mon Sep 17 00:00:00 2001 From: Marek Siarkowicz Date: Thu, 20 Jan 2022 17:02:20 +0100 Subject: [PATCH 088/258] test: Migrate WaitStarted to V3 API --- tests/framework/integration/cluster.go | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/tests/framework/integration/cluster.go b/tests/framework/integration/cluster.go index f5dd7344acd5..50d847b563ac 100644 --- a/tests/framework/integration/cluster.go +++ b/tests/framework/integration/cluster.go @@ -1065,11 +1065,9 @@ func (m *Member) WaitOK(t testutil.TB) { } func (m *Member) WaitStarted(t testutil.TB) { - cc := MustNewHTTPClient(t, []string{m.URL()}, m.ClientTLSInfo) - kapi := client.NewKeysAPI(cc) for { ctx, cancel := context.WithTimeout(context.Background(), RequestTimeout) - _, err := kapi.Get(ctx, "/", nil) + _, err := m.Client.Get(ctx, "/", clientv3.WithSerializable()) if err != nil { time.Sleep(TickDuration) continue From c59694d41eed68fb6d39a14a2d82db3334814b2f Mon Sep 17 00:00:00 2001 From: Marek Siarkowicz Date: Mon, 24 Jan 2022 13:10:45 +0100 Subject: [PATCH 089/258] test: Migrate WaitMembersForLeader to V3 API --- tests/framework/integration/cluster.go | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/tests/framework/integration/cluster.go b/tests/framework/integration/cluster.go index 50d847b563ac..5c46a1268775 100644 --- a/tests/framework/integration/cluster.go +++ b/tests/framework/integration/cluster.go @@ -419,13 +419,14 @@ func (c *Cluster) WaitMembersForLeader(t testutil.TB, membs []*Member) int { for _, m := range membs { possibleLead[uint64(m.Server.ID())] = true } - cc := MustNewHTTPClient(t, getMembersURLs(membs), nil) - kapi := client.NewKeysAPI(cc) - + cc, err := c.ClusterClient() + if err != nil { + t.Fatal(err) + } // ensure leader is up via linearizable get for { ctx, cancel := context.WithTimeout(context.Background(), 10*TickDuration+time.Second) - _, err := kapi.Get(ctx, "0", &client.GetOptions{Quorum: true}) + _, err := cc.Get(ctx, "0") cancel() if err == nil || strings.Contains(err.Error(), "Key not found") { break From 37879eb5f96fe5848f64fc6c7765291a4e2b0436 Mon Sep 17 00:00:00 2001 From: Marek Siarkowicz Date: Tue, 25 Jan 2022 13:56:17 +0100 Subject: [PATCH 090/258] test: Migrate WaitMembersMatch to V3 API --- tests/framework/integration/cluster.go | 79 ++++++++++++-------------- tests/integration/cluster_test.go | 2 +- tests/integration/grpc_test.go | 3 + 3 files changed, 40 insertions(+), 44 deletions(-) diff --git a/tests/framework/integration/cluster.go b/tests/framework/integration/cluster.go index 5c46a1268775..c5687a48616e 100644 --- a/tests/framework/integration/cluster.go +++ b/tests/framework/integration/cluster.go @@ -17,6 +17,7 @@ package integration import ( "context" "crypto/tls" + "errors" "fmt" "io" "log" @@ -226,44 +227,20 @@ func (c *Cluster) Launch(t testutil.TB) { } } // wait Cluster to be stable to receive future client requests - c.WaitMembersMatch(t, c.HTTPMembers()) + c.WaitMembersMatch(t, c.ProtoMembers()) c.waitVersion() for _, m := range c.Members { t.Logf(" - %v -> %v (%v)", m.Name, m.ID(), m.GRPCURL()) } } -func (c *Cluster) URL(i int) string { - return c.Members[i].ClientURLs[0].String() -} - -// URLs returns a list of all active client URLs in the Cluster -func (c *Cluster) URLs() []string { - return getMembersURLs(c.Members) -} - -func getMembersURLs(members []*Member) []string { - urls := make([]string, 0) - for _, m := range members { - select { - case <-m.Server.StopNotify(): - continue - default: - } - for _, u := range m.ClientURLs { - urls = append(urls, u.String()) - } - } - return urls -} - -// HTTPMembers returns a list of all active members as client.Members -func (c *Cluster) HTTPMembers() []client.Member { - ms := []client.Member{} +// ProtoMembers returns a list of all active members as client.Members +func (c *Cluster) ProtoMembers() []*pb.Member { + ms := []*pb.Member{} for _, m := range c.Members { pScheme := SchemeFromTLSInfo(m.PeerTLSInfo) cScheme := SchemeFromTLSInfo(m.ClientTLSInfo) - cm := client.Member{Name: m.Name} + cm := &pb.Member{Name: m.Name} for _, ln := range m.PeerListeners { cm.PeerURLs = append(cm.PeerURLs, pScheme+"://"+ln.Addr().String()) } @@ -338,7 +315,7 @@ func (c *Cluster) addMember(t testutil.TB) types.URLs { } c.Members = append(c.Members, m) // wait Cluster to be stable to receive future client requests - c.WaitMembersMatch(t, c.HTTPMembers()) + c.WaitMembersMatch(t, c.ProtoMembers()) return m.PeerURLs } @@ -351,7 +328,7 @@ func (c *Cluster) AddMemberByURL(t testutil.TB, cc *clientv3.Client, peerURL str } // wait for the add node entry applied in the Cluster - members := append(c.HTTPMembers(), client.Member{PeerURLs: []string{peerURL}, ClientURLs: []string{}}) + members := append(c.ProtoMembers(), &pb.Member{PeerURLs: []string{peerURL}, ClientURLs: []string{}}) c.WaitMembersMatch(t, members) return nil } @@ -388,19 +365,29 @@ func (c *Cluster) RemoveMember(t testutil.TB, cc *clientv3.Client, id uint64) er } } c.Members = newMembers - c.WaitMembersMatch(t, c.HTTPMembers()) + c.WaitMembersMatch(t, c.ProtoMembers()) return nil } -func (c *Cluster) WaitMembersMatch(t testutil.TB, membs []client.Member) { - for _, u := range c.URLs() { - cc := MustNewHTTPClient(t, []string{u}, c.Cfg.ClientTLS) - ma := client.NewMembersAPI(cc) +func (c *Cluster) WaitMembersMatch(t testutil.TB, membs []*pb.Member) { + ctx, cancel := context.WithTimeout(context.Background(), RequestTimeout) + defer cancel() + for _, m := range c.Members { + cc := ToGRPC(m.Client) + select { + case <-m.Server.StopNotify(): + continue + default: + } for { - ctx, cancel := context.WithTimeout(context.Background(), RequestTimeout) - ms, err := ma.List(ctx) - cancel() - if err == nil && isMembersEqual(ms, membs) { + resp, err := cc.Cluster.MemberList(ctx, &pb.MemberListRequest{Linearizable: false}) + if errors.Is(err, context.DeadlineExceeded) { + t.Fatal(err) + } + if err != nil { + continue + } + if isMembersEqual(resp.Members, membs) { break } time.Sleep(TickDuration) @@ -494,11 +481,17 @@ func (c *Cluster) waitVersion() { // isMembersEqual checks whether two members equal except ID field. // The given wmembs should always set ID field to empty string. -func isMembersEqual(membs []client.Member, wmembs []client.Member) bool { +func isMembersEqual(membs []*pb.Member, wmembs []*pb.Member) bool { sort.Sort(SortableMemberSliceByPeerURLs(membs)) sort.Sort(SortableMemberSliceByPeerURLs(wmembs)) for i := range membs { - membs[i].ID = "" + membs[i].ID = 0 + if membs[i].PeerURLs == nil { + membs[i].PeerURLs = []string{} + } + if membs[i].ClientURLs == nil { + membs[i].ClientURLs = []string{} + } } return reflect.DeepEqual(membs, wmembs) } @@ -1334,7 +1327,7 @@ func mustNewTransport(t testutil.TB, tlsInfo transport.TLSInfo) *http.Transport return tr } -type SortableMemberSliceByPeerURLs []client.Member +type SortableMemberSliceByPeerURLs []*pb.Member func (p SortableMemberSliceByPeerURLs) Len() int { return len(p) } func (p SortableMemberSliceByPeerURLs) Less(i, j int) bool { diff --git a/tests/integration/cluster_test.go b/tests/integration/cluster_test.go index 5f239c91e917..4e0d4a0f0fb6 100644 --- a/tests/integration/cluster_test.go +++ b/tests/integration/cluster_test.go @@ -267,7 +267,7 @@ func TestIssue2904(t *testing.T) { c.Members[2].Terminate(t) c.Members = c.Members[:2] // wait member to be removed. - c.WaitMembersMatch(t, c.HTTPMembers()) + c.WaitMembersMatch(t, c.ProtoMembers()) } // TestIssue3699 tests minority failure during cluster configuration; it was diff --git a/tests/integration/grpc_test.go b/tests/integration/grpc_test.go index 9e30d4c43976..6c1e34ae55a4 100644 --- a/tests/integration/grpc_test.go +++ b/tests/integration/grpc_test.go @@ -186,6 +186,9 @@ func assertAuthority(t *testing.T, expectedAuthority string, clus *integration.C requestsFound := 0 for _, m := range clus.Members { for _, r := range m.RecordedRequests() { + if r.FullMethod != "/etcdserverpb.KV/Put" { + continue + } requestsFound++ if r.Authority != expectedAuthority { t.Errorf("Got unexpected authority header, member: %q, request: %q, got authority: %q, expected %q", m.Name, r.FullMethod, r.Authority, expectedAuthority) From 692b3c4cd72242f9e5f8b6d1e1f46398558af8e9 Mon Sep 17 00:00:00 2001 From: Marek Siarkowicz Date: Tue, 25 Jan 2022 14:46:21 +0100 Subject: [PATCH 091/258] server: Remove most of V2 API --- server/etcdserver/api/etcdhttp/base.go | 1 - .../etcdserver/api/etcdhttp/metrics_test.go | 3 - server/etcdserver/api/v2auth/auth.go | 670 ------ server/etcdserver/api/v2auth/auth_requests.go | 177 -- server/etcdserver/api/v2auth/auth_test.go | 688 ------ server/etcdserver/api/v2error/error.go | 4 - server/etcdserver/api/v2http/capability.go | 41 - server/etcdserver/api/v2http/client.go | 728 +----- server/etcdserver/api/v2http/client_auth.go | 604 ----- .../etcdserver/api/v2http/client_auth_test.go | 913 -------- server/etcdserver/api/v2http/client_test.go | 2080 ----------------- server/etcdserver/api/v2http/doc.go | 16 - server/etcdserver/api/v2http/http.go | 82 - server/etcdserver/api/v2http/http_test.go | 192 -- .../etcdserver/api/v2http/httptypes/member.go | 69 - .../api/v2http/httptypes/member_test.go | 135 -- server/etcdserver/api/v2http/metrics.go | 98 - server/etcdserver/api/v2http/testdata/ca.pem | 19 - .../api/v2http/testdata/otheruser.pem | 20 - .../etcdserver/api/v2http/testdata/user.pem | 20 - server/etcdserver/api/v2stats/stats.go | 26 - server/etcdserver/server.go | 13 - tests/e2e/discovery_test.go | 29 +- tests/framework/integration/cluster.go | 23 - 24 files changed, 39 insertions(+), 6612 deletions(-) delete mode 100644 server/etcdserver/api/v2auth/auth.go delete mode 100644 server/etcdserver/api/v2auth/auth_requests.go delete mode 100644 server/etcdserver/api/v2auth/auth_test.go delete mode 100644 server/etcdserver/api/v2http/capability.go delete mode 100644 server/etcdserver/api/v2http/client_auth.go delete mode 100644 server/etcdserver/api/v2http/client_auth_test.go delete mode 100644 server/etcdserver/api/v2http/client_test.go delete mode 100644 server/etcdserver/api/v2http/doc.go delete mode 100644 server/etcdserver/api/v2http/http.go delete mode 100644 server/etcdserver/api/v2http/http_test.go delete mode 100644 server/etcdserver/api/v2http/httptypes/member.go delete mode 100644 server/etcdserver/api/v2http/httptypes/member_test.go delete mode 100644 server/etcdserver/api/v2http/metrics.go delete mode 100644 server/etcdserver/api/v2http/testdata/ca.pem delete mode 100644 server/etcdserver/api/v2http/testdata/otheruser.pem delete mode 100644 server/etcdserver/api/v2http/testdata/user.pem delete mode 100644 server/etcdserver/api/v2stats/stats.go diff --git a/server/etcdserver/api/etcdhttp/base.go b/server/etcdserver/api/etcdhttp/base.go index dcfa3f069594..06067cc444c9 100644 --- a/server/etcdserver/api/etcdhttp/base.go +++ b/server/etcdserver/api/etcdhttp/base.go @@ -29,7 +29,6 @@ import ( ) const ( - configPath = "/config" varsPath = "/debug/vars" versionPath = "/version" ) diff --git a/server/etcdserver/api/etcdhttp/metrics_test.go b/server/etcdserver/api/etcdhttp/metrics_test.go index 859bdf495b30..1a0605b51c93 100644 --- a/server/etcdserver/api/etcdhttp/metrics_test.go +++ b/server/etcdserver/api/etcdhttp/metrics_test.go @@ -14,7 +14,6 @@ import ( "go.etcd.io/etcd/client/pkg/v3/types" "go.etcd.io/etcd/raft/v3" "go.etcd.io/etcd/server/v3/etcdserver" - stats "go.etcd.io/etcd/server/v3/etcdserver/api/v2stats" "go.uber.org/zap" ) @@ -26,7 +25,6 @@ func (s *fakeStats) StoreStats() []byte { return nil } type fakeServerV2 struct { fakeServer - stats.Stats health string } @@ -102,7 +100,6 @@ func TestHealthHandler(t *testing.T) { mux := http.NewServeMux() HandleMetricsHealth(zap.NewExample(), mux, &fakeServerV2{ fakeServer: fakeServer{alarms: tt.alarms}, - Stats: &fakeStats{}, health: tt.health, }) ts := httptest.NewServer(mux) diff --git a/server/etcdserver/api/v2auth/auth.go b/server/etcdserver/api/v2auth/auth.go deleted file mode 100644 index e76ee8b2a170..000000000000 --- a/server/etcdserver/api/v2auth/auth.go +++ /dev/null @@ -1,670 +0,0 @@ -// Copyright 2015 The etcd Authors -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -// Package v2auth implements etcd authentication. -package v2auth - -import ( - "context" - "encoding/json" - "fmt" - "net/http" - "path" - "reflect" - "sort" - "strings" - "time" - - "go.etcd.io/etcd/api/v3/etcdserverpb" - "go.etcd.io/etcd/client/pkg/v3/types" - "go.etcd.io/etcd/server/v3/etcdserver" - "go.etcd.io/etcd/server/v3/etcdserver/api/v2error" - - "go.uber.org/zap" - "golang.org/x/crypto/bcrypt" -) - -const ( - // StorePermsPrefix is the internal prefix of the storage layer dedicated to storing user data. - StorePermsPrefix = "/2" - - // RootRoleName is the name of the ROOT role, with privileges to manage the cluster. - RootRoleName = "root" - - // GuestRoleName is the name of the role that defines the privileges of an unauthenticated user. - GuestRoleName = "guest" -) - -var rootRole = Role{ - Role: RootRoleName, - Permissions: Permissions{ - KV: RWPermission{ - Read: []string{"/*"}, - Write: []string{"/*"}, - }, - }, -} - -var guestRole = Role{ - Role: GuestRoleName, - Permissions: Permissions{ - KV: RWPermission{ - Read: []string{"/*"}, - Write: []string{"/*"}, - }, - }, -} - -type doer interface { - Do(context.Context, etcdserverpb.Request) (etcdserver.Response, error) -} - -type Store interface { - AllUsers() ([]string, error) - GetUser(name string) (User, error) - CreateOrUpdateUser(user User) (out User, created bool, err error) - CreateUser(user User) (User, error) - DeleteUser(name string) error - UpdateUser(user User) (User, error) - AllRoles() ([]string, error) - GetRole(name string) (Role, error) - CreateRole(role Role) error - DeleteRole(name string) error - UpdateRole(role Role) (Role, error) - AuthEnabled() bool - EnableAuth() error - DisableAuth() error - PasswordStore -} - -type PasswordStore interface { - CheckPassword(user User, password string) bool - HashPassword(password string) (string, error) -} - -type store struct { - lg *zap.Logger - server doer - timeout time.Duration - ensuredOnce bool - - PasswordStore -} - -type User struct { - User string `json:"user"` - Password string `json:"password,omitempty"` - Roles []string `json:"roles"` - Grant []string `json:"grant,omitempty"` - Revoke []string `json:"revoke,omitempty"` -} - -type Role struct { - Role string `json:"role"` - Permissions Permissions `json:"permissions"` - Grant *Permissions `json:"grant,omitempty"` - Revoke *Permissions `json:"revoke,omitempty"` -} - -type Permissions struct { - KV RWPermission `json:"kv"` -} - -func (p *Permissions) IsEmpty() bool { - return p == nil || (len(p.KV.Read) == 0 && len(p.KV.Write) == 0) -} - -type RWPermission struct { - Read []string `json:"read"` - Write []string `json:"write"` -} - -type Error struct { - Status int - Errmsg string -} - -func (ae Error) Error() string { return ae.Errmsg } -func (ae Error) HTTPStatus() int { return ae.Status } - -func authErr(hs int, s string, v ...interface{}) Error { - return Error{Status: hs, Errmsg: fmt.Sprintf("auth: "+s, v...)} -} - -func NewStore(lg *zap.Logger, server doer, timeout time.Duration) Store { - if lg == nil { - lg = zap.NewNop() - } - s := &store{ - lg: lg, - server: server, - timeout: timeout, - PasswordStore: passwordStore{}, - } - return s -} - -// passwordStore implements PasswordStore using bcrypt to hash user passwords -type passwordStore struct{} - -func (passwordStore) CheckPassword(user User, password string) bool { - err := bcrypt.CompareHashAndPassword([]byte(user.Password), []byte(password)) - return err == nil -} - -func (passwordStore) HashPassword(password string) (string, error) { - hash, err := bcrypt.GenerateFromPassword([]byte(password), bcrypt.DefaultCost) - return string(hash), err -} - -func (s *store) AllUsers() ([]string, error) { - resp, err := s.requestResource("/users/", false) - if err != nil { - if e, ok := err.(*v2error.Error); ok { - if e.ErrorCode == v2error.EcodeKeyNotFound { - return []string{}, nil - } - } - return nil, err - } - var nodes []string - for _, n := range resp.Event.Node.Nodes { - _, user := path.Split(n.Key) - nodes = append(nodes, user) - } - sort.Strings(nodes) - return nodes, nil -} - -func (s *store) GetUser(name string) (User, error) { return s.getUser(name, false) } - -// CreateOrUpdateUser should be only used for creating the new user or when you are not -// sure if it is a create or update. (When only password is passed in, we are not sure -// if it is a update or create) -func (s *store) CreateOrUpdateUser(user User) (out User, created bool, err error) { - _, err = s.getUser(user.User, true) - if err == nil { - out, err = s.UpdateUser(user) - return out, false, err - } - u, err := s.CreateUser(user) - return u, true, err -} - -func (s *store) CreateUser(user User) (User, error) { - // Attach root role to root user. - if user.User == "root" { - user = attachRootRole(user) - } - u, err := s.createUserInternal(user) - if err == nil { - s.lg.Info("created a user", zap.String("user-name", user.User)) - } - return u, err -} - -func (s *store) createUserInternal(user User) (User, error) { - if user.Password == "" { - return user, authErr(http.StatusBadRequest, "Cannot create user %s with an empty password", user.User) - } - hash, err := s.HashPassword(user.Password) - if err != nil { - return user, err - } - user.Password = hash - - _, err = s.createResource("/users/"+user.User, user) - if err != nil { - if e, ok := err.(*v2error.Error); ok { - if e.ErrorCode == v2error.EcodeNodeExist { - return user, authErr(http.StatusConflict, "User %s already exists.", user.User) - } - } - } - return user, err -} - -func (s *store) DeleteUser(name string) error { - if s.AuthEnabled() && name == "root" { - return authErr(http.StatusForbidden, "Cannot delete root user while auth is enabled.") - } - err := s.deleteResource("/users/" + name) - if err != nil { - if e, ok := err.(*v2error.Error); ok { - if e.ErrorCode == v2error.EcodeKeyNotFound { - return authErr(http.StatusNotFound, "User %s does not exist", name) - } - } - return err - } - s.lg.Info("deleted a user", zap.String("user-name", name)) - return nil -} - -func (s *store) UpdateUser(user User) (User, error) { - old, err := s.getUser(user.User, true) - if err != nil { - if e, ok := err.(*v2error.Error); ok { - if e.ErrorCode == v2error.EcodeKeyNotFound { - return user, authErr(http.StatusNotFound, "User %s doesn't exist.", user.User) - } - } - return old, err - } - - newUser, err := old.merge(s.lg, user, s.PasswordStore) - if err != nil { - return old, err - } - if reflect.DeepEqual(old, newUser) { - return old, authErr(http.StatusBadRequest, "User not updated. Use grant/revoke/password to update the user.") - } - _, err = s.updateResource("/users/"+user.User, newUser) - if err == nil { - s.lg.Info("updated a user", zap.String("user-name", user.User)) - } - return newUser, err -} - -func (s *store) AllRoles() ([]string, error) { - nodes := []string{RootRoleName} - resp, err := s.requestResource("/roles/", false) - if err != nil { - if e, ok := err.(*v2error.Error); ok { - if e.ErrorCode == v2error.EcodeKeyNotFound { - return nodes, nil - } - } - return nil, err - } - for _, n := range resp.Event.Node.Nodes { - _, role := path.Split(n.Key) - nodes = append(nodes, role) - } - sort.Strings(nodes) - return nodes, nil -} - -func (s *store) GetRole(name string) (Role, error) { return s.getRole(name, false) } - -func (s *store) CreateRole(role Role) error { - if role.Role == RootRoleName { - return authErr(http.StatusForbidden, "Cannot modify role %s: is root role.", role.Role) - } - _, err := s.createResource("/roles/"+role.Role, role) - if err != nil { - if e, ok := err.(*v2error.Error); ok { - if e.ErrorCode == v2error.EcodeNodeExist { - return authErr(http.StatusConflict, "Role %s already exists.", role.Role) - } - } - } - if err == nil { - s.lg.Info("created a new role", zap.String("role-name", role.Role)) - } - return err -} - -func (s *store) DeleteRole(name string) error { - if name == RootRoleName { - return authErr(http.StatusForbidden, "Cannot modify role %s: is root role.", name) - } - err := s.deleteResource("/roles/" + name) - if err != nil { - if e, ok := err.(*v2error.Error); ok { - if e.ErrorCode == v2error.EcodeKeyNotFound { - return authErr(http.StatusNotFound, "Role %s doesn't exist.", name) - } - } - } - if err == nil { - s.lg.Info("delete a new role", zap.String("role-name", name)) - } - return err -} - -func (s *store) UpdateRole(role Role) (Role, error) { - if role.Role == RootRoleName { - return Role{}, authErr(http.StatusForbidden, "Cannot modify role %s: is root role.", role.Role) - } - old, err := s.getRole(role.Role, true) - if err != nil { - if e, ok := err.(*v2error.Error); ok { - if e.ErrorCode == v2error.EcodeKeyNotFound { - return role, authErr(http.StatusNotFound, "Role %s doesn't exist.", role.Role) - } - } - return old, err - } - newRole, err := old.merge(s.lg, role) - if err != nil { - return old, err - } - if reflect.DeepEqual(old, newRole) { - return old, authErr(http.StatusBadRequest, "Role not updated. Use grant/revoke to update the role.") - } - _, err = s.updateResource("/roles/"+role.Role, newRole) - if err == nil { - s.lg.Info("updated a new role", zap.String("role-name", role.Role)) - } - return newRole, err -} - -func (s *store) AuthEnabled() bool { - return s.detectAuth() -} - -func (s *store) EnableAuth() error { - if s.AuthEnabled() { - return authErr(http.StatusConflict, "already enabled") - } - - if _, err := s.getUser("root", true); err != nil { - return authErr(http.StatusConflict, "No root user available, please create one") - } - if _, err := s.getRole(GuestRoleName, true); err != nil { - s.lg.Info( - "no guest role access found; creating default", - zap.String("role-name", GuestRoleName), - ) - if err := s.CreateRole(guestRole); err != nil { - s.lg.Warn( - "failed to create a guest role; aborting auth enable", - zap.String("role-name", GuestRoleName), - zap.Error(err), - ) - return err - } - } - - if err := s.enableAuth(); err != nil { - s.lg.Warn("failed to enable auth", zap.Error(err)) - return err - } - - s.lg.Info("enabled auth") - return nil -} - -func (s *store) DisableAuth() error { - if !s.AuthEnabled() { - return authErr(http.StatusConflict, "already disabled") - } - - err := s.disableAuth() - if err == nil { - s.lg.Info("disabled auth") - } else { - s.lg.Warn("failed to disable auth", zap.Error(err)) - } - return err -} - -// merge applies the properties of the passed-in User to the User on which it -// is called and returns a new User with these modifications applied. Think of -// all Users as immutable sets of data. Merge allows you to perform the set -// operations (desired grants and revokes) atomically -func (ou User) merge(lg *zap.Logger, nu User, s PasswordStore) (User, error) { - var out User - if ou.User != nu.User { - return out, authErr(http.StatusConflict, "Merging user data with conflicting usernames: %s %s", ou.User, nu.User) - } - out.User = ou.User - if nu.Password != "" { - hash, err := s.HashPassword(nu.Password) - if err != nil { - return ou, err - } - out.Password = hash - } else { - out.Password = ou.Password - } - currentRoles := types.NewUnsafeSet(ou.Roles...) - for _, g := range nu.Grant { - if currentRoles.Contains(g) { - lg.Warn( - "attempted to grant a duplicate role for a user", - zap.String("user-name", nu.User), - zap.String("role-name", g), - ) - return User{}, authErr(http.StatusConflict, fmt.Sprintf("Granting duplicate role %s for user %s", g, nu.User)) - } - currentRoles.Add(g) - } - for _, r := range nu.Revoke { - if !currentRoles.Contains(r) { - lg.Warn( - "attempted to revoke a ungranted role for a user", - zap.String("user-name", nu.User), - zap.String("role-name", r), - ) - return User{}, authErr(http.StatusConflict, fmt.Sprintf("Revoking ungranted role %s for user %s", r, nu.User)) - } - currentRoles.Remove(r) - } - out.Roles = currentRoles.Values() - sort.Strings(out.Roles) - return out, nil -} - -// merge for a role works the same as User above -- atomic Role application to -// each of the substructures. -func (r Role) merge(lg *zap.Logger, n Role) (Role, error) { - var out Role - var err error - if r.Role != n.Role { - return out, authErr(http.StatusConflict, "Merging role with conflicting names: %s %s", r.Role, n.Role) - } - out.Role = r.Role - out.Permissions, err = r.Permissions.Grant(n.Grant) - if err != nil { - return out, err - } - out.Permissions, err = out.Permissions.Revoke(lg, n.Revoke) - return out, err -} - -func (r Role) HasKeyAccess(key string, write bool) bool { - if r.Role == RootRoleName { - return true - } - return r.Permissions.KV.HasAccess(key, write) -} - -func (r Role) HasRecursiveAccess(key string, write bool) bool { - if r.Role == RootRoleName { - return true - } - return r.Permissions.KV.HasRecursiveAccess(key, write) -} - -// Grant adds a set of permissions to the permission object on which it is called, -// returning a new permission object. -func (p Permissions) Grant(n *Permissions) (Permissions, error) { - var out Permissions - var err error - if n == nil { - return p, nil - } - out.KV, err = p.KV.Grant(n.KV) - return out, err -} - -// Revoke removes a set of permissions to the permission object on which it is called, -// returning a new permission object. -func (p Permissions) Revoke(lg *zap.Logger, n *Permissions) (Permissions, error) { - var out Permissions - var err error - if n == nil { - return p, nil - } - out.KV, err = p.KV.Revoke(lg, n.KV) - return out, err -} - -// Grant adds a set of permissions to the permission object on which it is called, -// returning a new permission object. -func (rw RWPermission) Grant(n RWPermission) (RWPermission, error) { - var out RWPermission - currentRead := types.NewUnsafeSet(rw.Read...) - for _, r := range n.Read { - if currentRead.Contains(r) { - return out, authErr(http.StatusConflict, "Granting duplicate read permission %s", r) - } - currentRead.Add(r) - } - currentWrite := types.NewUnsafeSet(rw.Write...) - for _, w := range n.Write { - if currentWrite.Contains(w) { - return out, authErr(http.StatusConflict, "Granting duplicate write permission %s", w) - } - currentWrite.Add(w) - } - out.Read = currentRead.Values() - out.Write = currentWrite.Values() - sort.Strings(out.Read) - sort.Strings(out.Write) - return out, nil -} - -// Revoke removes a set of permissions to the permission object on which it is called, -// returning a new permission object. -func (rw RWPermission) Revoke(lg *zap.Logger, n RWPermission) (RWPermission, error) { - var out RWPermission - currentRead := types.NewUnsafeSet(rw.Read...) - for _, r := range n.Read { - if !currentRead.Contains(r) { - lg.Info( - "revoking ungranted read permission", - zap.String("read-permission", r), - ) - continue - } - currentRead.Remove(r) - } - currentWrite := types.NewUnsafeSet(rw.Write...) - for _, w := range n.Write { - if !currentWrite.Contains(w) { - lg.Info( - "revoking ungranted write permission", - zap.String("write-permission", w), - ) - continue - } - currentWrite.Remove(w) - } - out.Read = currentRead.Values() - out.Write = currentWrite.Values() - sort.Strings(out.Read) - sort.Strings(out.Write) - return out, nil -} - -func (rw RWPermission) HasAccess(key string, write bool) bool { - var list []string - if write { - list = rw.Write - } else { - list = rw.Read - } - for _, pat := range list { - match, err := simpleMatch(pat, key) - if err == nil && match { - return true - } - } - return false -} - -func (rw RWPermission) HasRecursiveAccess(key string, write bool) bool { - list := rw.Read - if write { - list = rw.Write - } - for _, pat := range list { - match, err := prefixMatch(pat, key) - if err == nil && match { - return true - } - } - return false -} - -func simpleMatch(pattern string, key string) (match bool, err error) { - if pattern[len(pattern)-1] == '*' { - return strings.HasPrefix(key, pattern[:len(pattern)-1]), nil - } - return key == pattern, nil -} - -func prefixMatch(pattern string, key string) (match bool, err error) { - if pattern[len(pattern)-1] != '*' { - return false, nil - } - return strings.HasPrefix(key, pattern[:len(pattern)-1]), nil -} - -func attachRootRole(u User) User { - inRoles := false - for _, r := range u.Roles { - if r == RootRoleName { - inRoles = true - break - } - } - if !inRoles { - u.Roles = append(u.Roles, RootRoleName) - } - return u -} - -func (s *store) getUser(name string, quorum bool) (User, error) { - resp, err := s.requestResource("/users/"+name, quorum) - if err != nil { - if e, ok := err.(*v2error.Error); ok { - if e.ErrorCode == v2error.EcodeKeyNotFound { - return User{}, authErr(http.StatusNotFound, "User %s does not exist.", name) - } - } - return User{}, err - } - var u User - err = json.Unmarshal([]byte(*resp.Event.Node.Value), &u) - if err != nil { - return u, err - } - // Attach root role to root user. - if u.User == "root" { - u = attachRootRole(u) - } - return u, nil -} - -func (s *store) getRole(name string, quorum bool) (Role, error) { - if name == RootRoleName { - return rootRole, nil - } - resp, err := s.requestResource("/roles/"+name, quorum) - if err != nil { - if e, ok := err.(*v2error.Error); ok { - if e.ErrorCode == v2error.EcodeKeyNotFound { - return Role{}, authErr(http.StatusNotFound, "Role %s does not exist.", name) - } - } - return Role{}, err - } - var r Role - err = json.Unmarshal([]byte(*resp.Event.Node.Value), &r) - return r, err -} diff --git a/server/etcdserver/api/v2auth/auth_requests.go b/server/etcdserver/api/v2auth/auth_requests.go deleted file mode 100644 index 6c8c50c8ccc2..000000000000 --- a/server/etcdserver/api/v2auth/auth_requests.go +++ /dev/null @@ -1,177 +0,0 @@ -// Copyright 2015 The etcd Authors -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -package v2auth - -import ( - "context" - "encoding/json" - "path" - - "go.etcd.io/etcd/api/v3/etcdserverpb" - "go.etcd.io/etcd/server/v3/etcdserver" - "go.etcd.io/etcd/server/v3/etcdserver/api/v2error" - - "go.uber.org/zap" -) - -func (s *store) ensureAuthDirectories() error { - if s.ensuredOnce { - return nil - } - for _, res := range []string{StorePermsPrefix, StorePermsPrefix + "/users/", StorePermsPrefix + "/roles/"} { - ctx, cancel := context.WithTimeout(context.Background(), s.timeout) - pe := false - rr := etcdserverpb.Request{ - Method: "PUT", - Path: res, - Dir: true, - PrevExist: &pe, - } - _, err := s.server.Do(ctx, rr) - cancel() - if err != nil { - if e, ok := err.(*v2error.Error); ok { - if e.ErrorCode == v2error.EcodeNodeExist { - continue - } - } - s.lg.Warn( - "failed to create auth directories", - zap.Error(err), - ) - return err - } - } - ctx, cancel := context.WithTimeout(context.Background(), s.timeout) - defer cancel() - pe := false - rr := etcdserverpb.Request{ - Method: "PUT", - Path: StorePermsPrefix + "/enabled", - Val: "false", - PrevExist: &pe, - } - _, err := s.server.Do(ctx, rr) - if err != nil { - if e, ok := err.(*v2error.Error); ok { - if e.ErrorCode == v2error.EcodeNodeExist { - s.ensuredOnce = true - return nil - } - } - return err - } - s.ensuredOnce = true - return nil -} - -func (s *store) enableAuth() error { - _, err := s.updateResource("/enabled", true) - return err -} -func (s *store) disableAuth() error { - _, err := s.updateResource("/enabled", false) - return err -} - -func (s *store) detectAuth() bool { - if s.server == nil { - return false - } - value, err := s.requestResource("/enabled", false) - if err != nil { - if e, ok := err.(*v2error.Error); ok { - if e.ErrorCode == v2error.EcodeKeyNotFound { - return false - } - } - s.lg.Warn( - "failed to detect auth settings", - zap.Error(err), - ) - return false - } - - var u bool - err = json.Unmarshal([]byte(*value.Event.Node.Value), &u) - if err != nil { - s.lg.Warn( - "internal bookkeeping value for enabled isn't valid JSON", - zap.Error(err), - ) - return false - } - return u -} - -func (s *store) requestResource(res string, quorum bool) (etcdserver.Response, error) { - ctx, cancel := context.WithTimeout(context.Background(), s.timeout) - defer cancel() - p := path.Join(StorePermsPrefix, res) - method := "GET" - if quorum { - method = "QGET" - } - rr := etcdserverpb.Request{ - Method: method, - Path: p, - Dir: false, // TODO: always false? - } - return s.server.Do(ctx, rr) -} - -func (s *store) updateResource(res string, value interface{}) (etcdserver.Response, error) { - return s.setResource(res, value, true) -} -func (s *store) createResource(res string, value interface{}) (etcdserver.Response, error) { - return s.setResource(res, value, false) -} -func (s *store) setResource(res string, value interface{}, prevexist bool) (etcdserver.Response, error) { - err := s.ensureAuthDirectories() - if err != nil { - return etcdserver.Response{}, err - } - ctx, cancel := context.WithTimeout(context.Background(), s.timeout) - defer cancel() - data, err := json.Marshal(value) - if err != nil { - return etcdserver.Response{}, err - } - p := path.Join(StorePermsPrefix, res) - rr := etcdserverpb.Request{ - Method: "PUT", - Path: p, - Val: string(data), - PrevExist: &prevexist, - } - return s.server.Do(ctx, rr) -} - -func (s *store) deleteResource(res string) error { - err := s.ensureAuthDirectories() - if err != nil { - return err - } - ctx, cancel := context.WithTimeout(context.Background(), s.timeout) - defer cancel() - pex := true - p := path.Join(StorePermsPrefix, res) - _, err = s.server.Do(ctx, etcdserverpb.Request{ - Method: "DELETE", - Path: p, - PrevExist: &pex, - }) - return err -} diff --git a/server/etcdserver/api/v2auth/auth_test.go b/server/etcdserver/api/v2auth/auth_test.go deleted file mode 100644 index cd9c66667b59..000000000000 --- a/server/etcdserver/api/v2auth/auth_test.go +++ /dev/null @@ -1,688 +0,0 @@ -// Copyright 2015 The etcd Authors -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -package v2auth - -import ( - "context" - "reflect" - "testing" - "time" - - "go.etcd.io/etcd/api/v3/etcdserverpb" - "go.etcd.io/etcd/server/v3/etcdserver" - "go.etcd.io/etcd/server/v3/etcdserver/api/v2error" - "go.etcd.io/etcd/server/v3/etcdserver/api/v2store" - - "go.uber.org/zap" -) - -type fakeDoer struct{} - -func (fakeDoer) Do(context.Context, etcdserverpb.Request) (etcdserver.Response, error) { - return etcdserver.Response{}, nil -} - -func TestCheckPassword(t *testing.T) { - st := NewStore(zap.NewExample(), fakeDoer{}, 5*time.Second) - u := User{Password: "$2a$10$I3iddh1D..EIOXXQtsra4u8AjOtgEa2ERxVvYGfXFBJDo1omXwP.q"} - matched := st.CheckPassword(u, "foo") - if matched { - t.Fatalf("expected false, got %v", matched) - } -} - -const testTimeout = time.Millisecond - -func TestMergeUser(t *testing.T) { - tbl := []struct { - input User - merge User - expect User - iserr bool - }{ - { - User{User: "foo"}, - User{User: "bar"}, - User{}, - true, - }, - { - User{User: "foo"}, - User{User: "foo"}, - User{User: "foo", Roles: []string{}}, - false, - }, - { - User{User: "foo"}, - User{User: "foo", Grant: []string{"role1"}}, - User{User: "foo", Roles: []string{"role1"}}, - false, - }, - { - User{User: "foo", Roles: []string{"role1"}}, - User{User: "foo", Grant: []string{"role1"}}, - User{}, - true, - }, - { - User{User: "foo", Roles: []string{"role1"}}, - User{User: "foo", Revoke: []string{"role2"}}, - User{}, - true, - }, - { - User{User: "foo", Roles: []string{"role1"}}, - User{User: "foo", Grant: []string{"role2"}}, - User{User: "foo", Roles: []string{"role1", "role2"}}, - false, - }, - { // empty password will not overwrite the previous password - User{User: "foo", Password: "foo", Roles: []string{}}, - User{User: "foo", Password: ""}, - User{User: "foo", Password: "foo", Roles: []string{}}, - false, - }, - } - - for i, tt := range tbl { - out, err := tt.input.merge(zap.NewExample(), tt.merge, passwordStore{}) - if err != nil && !tt.iserr { - t.Fatalf("Got unexpected error on item %d", i) - } - if !tt.iserr { - if !reflect.DeepEqual(out, tt.expect) { - t.Errorf("Unequal merge expectation on item %d: got: %#v, expect: %#v", i, out, tt.expect) - } - } - } -} - -func TestMergeRole(t *testing.T) { - tbl := []struct { - input Role - merge Role - expect Role - iserr bool - }{ - { - Role{Role: "foo"}, - Role{Role: "bar"}, - Role{}, - true, - }, - { - Role{Role: "foo"}, - Role{Role: "foo", Grant: &Permissions{KV: RWPermission{Read: []string{"/foodir"}, Write: []string{"/foodir"}}}}, - Role{Role: "foo", Permissions: Permissions{KV: RWPermission{Read: []string{"/foodir"}, Write: []string{"/foodir"}}}}, - false, - }, - { - Role{Role: "foo", Permissions: Permissions{KV: RWPermission{Read: []string{"/foodir"}, Write: []string{"/foodir"}}}}, - Role{Role: "foo", Revoke: &Permissions{KV: RWPermission{Read: []string{"/foodir"}, Write: []string{"/foodir"}}}}, - Role{Role: "foo", Permissions: Permissions{KV: RWPermission{Read: []string{}, Write: []string{}}}}, - false, - }, - { - Role{Role: "foo", Permissions: Permissions{KV: RWPermission{Read: []string{"/bardir"}}}}, - Role{Role: "foo", Revoke: &Permissions{KV: RWPermission{Read: []string{"/foodir"}}}}, - Role{}, - true, - }, - } - for i, tt := range tbl { - out, err := tt.input.merge(zap.NewExample(), tt.merge) - if err != nil && !tt.iserr { - t.Fatalf("Got unexpected error on item %d", i) - } - if !tt.iserr { - if !reflect.DeepEqual(out, tt.expect) { - t.Errorf("Unequal merge expectation on item %d: got: %#v, expect: %#v", i, out, tt.expect) - } - } - } -} - -type testDoer struct { - get []etcdserver.Response - put []etcdserver.Response - getindex int - putindex int - explicitlyEnabled bool -} - -func (td *testDoer) Do(_ context.Context, req etcdserverpb.Request) (etcdserver.Response, error) { - if td.explicitlyEnabled && (req.Path == StorePermsPrefix+"/enabled") { - t := "true" - return etcdserver.Response{ - Event: &v2store.Event{ - Action: v2store.Get, - Node: &v2store.NodeExtern{ - Key: StorePermsPrefix + "/users/cat", - Value: &t, - }, - }, - }, nil - } - if (req.Method == "GET" || req.Method == "QGET") && td.get != nil { - if td.getindex >= len(td.get) { - return etcdserver.Response{}, &v2error.Error{ - ErrorCode: v2error.EcodeKeyNotFound, - } - } - res := td.get[td.getindex] - if res.Event == nil { - td.getindex++ - return etcdserver.Response{}, &v2error.Error{ - ErrorCode: v2error.EcodeKeyNotFound, - } - } - td.getindex++ - return res, nil - } - if req.Method == "PUT" && td.put != nil { - if td.putindex >= len(td.put) { - return etcdserver.Response{}, &v2error.Error{ - ErrorCode: v2error.EcodeKeyNotFound, - } - } - res := td.put[td.putindex] - if res.Event == nil { - td.putindex++ - return etcdserver.Response{}, &v2error.Error{ - ErrorCode: v2error.EcodeNodeExist, - } - } - td.putindex++ - return res, nil - } - return etcdserver.Response{}, nil -} - -func TestAllUsers(t *testing.T) { - d := &testDoer{ - get: []etcdserver.Response{ - { - Event: &v2store.Event{ - Action: v2store.Get, - Node: &v2store.NodeExtern{ - Nodes: v2store.NodeExterns([]*v2store.NodeExtern{ - { - Key: StorePermsPrefix + "/users/cat", - }, - { - Key: StorePermsPrefix + "/users/dog", - }, - }), - }, - }, - }, - }, - } - expected := []string{"cat", "dog"} - - s := store{lg: zap.NewExample(), server: d, timeout: testTimeout, ensuredOnce: false} - users, err := s.AllUsers() - if err != nil { - t.Error("Unexpected error", err) - } - if !reflect.DeepEqual(users, expected) { - t.Error("AllUsers doesn't match given store. Got", users, "expected", expected) - } -} - -func TestGetAndDeleteUser(t *testing.T) { - data := `{"user": "cat", "roles" : ["animal"]}` - d := &testDoer{ - get: []etcdserver.Response{ - { - Event: &v2store.Event{ - Action: v2store.Get, - Node: &v2store.NodeExtern{ - Key: StorePermsPrefix + "/users/cat", - Value: &data, - }, - }, - }, - }, - explicitlyEnabled: true, - } - expected := User{User: "cat", Roles: []string{"animal"}} - - s := store{lg: zap.NewExample(), server: d, timeout: testTimeout, ensuredOnce: false} - out, err := s.GetUser("cat") - if err != nil { - t.Error("Unexpected error", err) - } - if !reflect.DeepEqual(out, expected) { - t.Error("GetUser doesn't match given store. Got", out, "expected", expected) - } - err = s.DeleteUser("cat") - if err != nil { - t.Error("Unexpected error", err) - } -} - -func TestAllRoles(t *testing.T) { - d := &testDoer{ - get: []etcdserver.Response{ - { - Event: &v2store.Event{ - Action: v2store.Get, - Node: &v2store.NodeExtern{ - Nodes: v2store.NodeExterns([]*v2store.NodeExtern{ - { - Key: StorePermsPrefix + "/roles/animal", - }, - { - Key: StorePermsPrefix + "/roles/human", - }, - }), - }, - }, - }, - }, - explicitlyEnabled: true, - } - expected := []string{"animal", "human", "root"} - - s := store{lg: zap.NewExample(), server: d, timeout: testTimeout, ensuredOnce: false} - out, err := s.AllRoles() - if err != nil { - t.Error("Unexpected error", err) - } - if !reflect.DeepEqual(out, expected) { - t.Error("AllRoles doesn't match given store. Got", out, "expected", expected) - } -} - -func TestGetAndDeleteRole(t *testing.T) { - data := `{"role": "animal"}` - d := &testDoer{ - get: []etcdserver.Response{ - { - Event: &v2store.Event{ - Action: v2store.Get, - Node: &v2store.NodeExtern{ - Key: StorePermsPrefix + "/roles/animal", - Value: &data, - }, - }, - }, - }, - explicitlyEnabled: true, - } - expected := Role{Role: "animal"} - - s := store{lg: zap.NewExample(), server: d, timeout: testTimeout, ensuredOnce: false} - out, err := s.GetRole("animal") - if err != nil { - t.Error("Unexpected error", err) - } - if !reflect.DeepEqual(out, expected) { - t.Error("GetRole doesn't match given store. Got", out, "expected", expected) - } - err = s.DeleteRole("animal") - if err != nil { - t.Error("Unexpected error", err) - } -} - -func TestEnsure(t *testing.T) { - d := &testDoer{ - get: []etcdserver.Response{ - { - Event: &v2store.Event{ - Action: v2store.Set, - Node: &v2store.NodeExtern{ - Key: StorePermsPrefix, - Dir: true, - }, - }, - }, - { - Event: &v2store.Event{ - Action: v2store.Set, - Node: &v2store.NodeExtern{ - Key: StorePermsPrefix + "/users/", - Dir: true, - }, - }, - }, - { - Event: &v2store.Event{ - Action: v2store.Set, - Node: &v2store.NodeExtern{ - Key: StorePermsPrefix + "/roles/", - Dir: true, - }, - }, - }, - }, - } - - s := store{lg: zap.NewExample(), server: d, timeout: testTimeout, ensuredOnce: false} - err := s.ensureAuthDirectories() - if err != nil { - t.Error("Unexpected error", err) - } -} - -type fastPasswordStore struct { -} - -func (fastPasswordStore) CheckPassword(user User, password string) bool { - return user.Password == password -} - -func (fastPasswordStore) HashPassword(password string) (string, error) { return password, nil } - -func TestCreateAndUpdateUser(t *testing.T) { - olduser := `{"user": "cat", "roles" : ["animal"]}` - newuser := `{"user": "cat", "roles" : ["animal", "pet"]}` - d := &testDoer{ - get: []etcdserver.Response{ - { - Event: nil, - }, - { - Event: &v2store.Event{ - Action: v2store.Get, - Node: &v2store.NodeExtern{ - Key: StorePermsPrefix + "/users/cat", - Value: &olduser, - }, - }, - }, - { - Event: &v2store.Event{ - Action: v2store.Get, - Node: &v2store.NodeExtern{ - Key: StorePermsPrefix + "/users/cat", - Value: &olduser, - }, - }, - }, - }, - put: []etcdserver.Response{ - { - Event: &v2store.Event{ - Action: v2store.Update, - Node: &v2store.NodeExtern{ - Key: StorePermsPrefix + "/users/cat", - Value: &olduser, - }, - }, - }, - { - Event: &v2store.Event{ - Action: v2store.Update, - Node: &v2store.NodeExtern{ - Key: StorePermsPrefix + "/users/cat", - Value: &newuser, - }, - }, - }, - }, - explicitlyEnabled: true, - } - user := User{User: "cat", Password: "meow", Roles: []string{"animal"}} - update := User{User: "cat", Grant: []string{"pet"}} - expected := User{User: "cat", Roles: []string{"animal", "pet"}} - - s := store{lg: zap.NewExample(), server: d, timeout: testTimeout, ensuredOnce: true, PasswordStore: fastPasswordStore{}} - out, created, err := s.CreateOrUpdateUser(user) - if !created { - t.Error("Should have created user, instead updated?") - } - if err != nil { - t.Error("Unexpected error", err) - } - out.Password = "meow" - if !reflect.DeepEqual(out, user) { - t.Error("UpdateUser doesn't match given update. Got", out, "expected", expected) - } - out, created, err = s.CreateOrUpdateUser(update) - if created { - t.Error("Should have updated user, instead created?") - } - if err != nil { - t.Error("Unexpected error", err) - } - if !reflect.DeepEqual(out, expected) { - t.Error("UpdateUser doesn't match given update. Got", out, "expected", expected) - } -} - -func TestUpdateRole(t *testing.T) { - oldrole := `{"role": "animal", "permissions" : {"kv": {"read": ["/animal"], "write": []}}}` - newrole := `{"role": "animal", "permissions" : {"kv": {"read": ["/animal"], "write": ["/animal"]}}}` - d := &testDoer{ - get: []etcdserver.Response{ - { - Event: &v2store.Event{ - Action: v2store.Get, - Node: &v2store.NodeExtern{ - Key: StorePermsPrefix + "/roles/animal", - Value: &oldrole, - }, - }, - }, - }, - put: []etcdserver.Response{ - { - Event: &v2store.Event{ - Action: v2store.Update, - Node: &v2store.NodeExtern{ - Key: StorePermsPrefix + "/roles/animal", - Value: &newrole, - }, - }, - }, - }, - explicitlyEnabled: true, - } - update := Role{Role: "animal", Grant: &Permissions{KV: RWPermission{Read: []string{}, Write: []string{"/animal"}}}} - expected := Role{Role: "animal", Permissions: Permissions{KV: RWPermission{Read: []string{"/animal"}, Write: []string{"/animal"}}}} - - s := store{lg: zap.NewExample(), server: d, timeout: testTimeout, ensuredOnce: true} - out, err := s.UpdateRole(update) - if err != nil { - t.Error("Unexpected error", err) - } - if !reflect.DeepEqual(out, expected) { - t.Error("UpdateRole doesn't match given update. Got", out, "expected", expected) - } -} - -func TestCreateRole(t *testing.T) { - role := `{"role": "animal", "permissions" : {"kv": {"read": ["/animal"], "write": []}}}` - d := &testDoer{ - put: []etcdserver.Response{ - { - Event: &v2store.Event{ - Action: v2store.Create, - Node: &v2store.NodeExtern{ - Key: StorePermsPrefix + "/roles/animal", - Value: &role, - }, - }, - }, - { - Event: nil, - }, - }, - explicitlyEnabled: true, - } - r := Role{Role: "animal", Permissions: Permissions{KV: RWPermission{Read: []string{"/animal"}, Write: []string{}}}} - - s := store{lg: zap.NewExample(), server: d, timeout: testTimeout, ensuredOnce: true} - err := s.CreateRole(Role{Role: "root"}) - if err == nil { - t.Error("Should error creating root role") - } - err = s.CreateRole(r) - if err != nil { - t.Error("Unexpected error", err) - } - err = s.CreateRole(r) - if err == nil { - t.Error("Creating duplicate role, should error") - } -} - -func TestEnableAuth(t *testing.T) { - rootUser := `{"user": "root", "password": ""}` - guestRole := `{"role": "guest", "permissions" : {"kv": {"read": ["*"], "write": ["*"]}}}` - trueval := "true" - falseval := "false" - d := &testDoer{ - get: []etcdserver.Response{ - { - Event: &v2store.Event{ - Action: v2store.Get, - Node: &v2store.NodeExtern{ - Key: StorePermsPrefix + "/enabled", - Value: &falseval, - }, - }, - }, - { - Event: &v2store.Event{ - Action: v2store.Get, - Node: &v2store.NodeExtern{ - Key: StorePermsPrefix + "/user/root", - Value: &rootUser, - }, - }, - }, - { - Event: nil, - }, - }, - put: []etcdserver.Response{ - { - Event: &v2store.Event{ - Action: v2store.Create, - Node: &v2store.NodeExtern{ - Key: StorePermsPrefix + "/roles/guest", - Value: &guestRole, - }, - }, - }, - { - Event: &v2store.Event{ - Action: v2store.Update, - Node: &v2store.NodeExtern{ - Key: StorePermsPrefix + "/enabled", - Value: &trueval, - }, - }, - }, - }, - explicitlyEnabled: false, - } - s := store{lg: zap.NewExample(), server: d, timeout: testTimeout, ensuredOnce: true} - err := s.EnableAuth() - if err != nil { - t.Error("Unexpected error", err) - } -} - -func TestDisableAuth(t *testing.T) { - trueval := "true" - falseval := "false" - d := &testDoer{ - get: []etcdserver.Response{ - { - Event: &v2store.Event{ - Action: v2store.Get, - Node: &v2store.NodeExtern{ - Key: StorePermsPrefix + "/enabled", - Value: &falseval, - }, - }, - }, - { - Event: &v2store.Event{ - Action: v2store.Get, - Node: &v2store.NodeExtern{ - Key: StorePermsPrefix + "/enabled", - Value: &trueval, - }, - }, - }, - }, - put: []etcdserver.Response{ - { - Event: &v2store.Event{ - Action: v2store.Update, - Node: &v2store.NodeExtern{ - Key: StorePermsPrefix + "/enabled", - Value: &falseval, - }, - }, - }, - }, - explicitlyEnabled: false, - } - s := store{lg: zap.NewExample(), server: d, timeout: testTimeout, ensuredOnce: true} - err := s.DisableAuth() - if err == nil { - t.Error("Expected error; already disabled") - } - - err = s.DisableAuth() - if err != nil { - t.Error("Unexpected error", err) - } -} - -func TestSimpleMatch(t *testing.T) { - role := Role{Role: "foo", Permissions: Permissions{KV: RWPermission{Read: []string{"/foodir/*", "/fookey"}, Write: []string{"/bardir/*", "/barkey"}}}} - if !role.HasKeyAccess("/foodir/foo/bar", false) { - t.Fatal("role lacks expected access") - } - if !role.HasKeyAccess("/fookey", false) { - t.Fatal("role lacks expected access") - } - if !role.HasRecursiveAccess("/foodir/*", false) { - t.Fatal("role lacks expected access") - } - if !role.HasRecursiveAccess("/foodir/foo*", false) { - t.Fatal("role lacks expected access") - } - if !role.HasRecursiveAccess("/bardir/*", true) { - t.Fatal("role lacks expected access") - } - if !role.HasKeyAccess("/bardir/bar/foo", true) { - t.Fatal("role lacks expected access") - } - if !role.HasKeyAccess("/barkey", true) { - t.Fatal("role lacks expected access") - } - - if role.HasKeyAccess("/bardir/bar/foo", false) { - t.Fatal("role has unexpected access") - } - if role.HasKeyAccess("/barkey", false) { - t.Fatal("role has unexpected access") - } - if role.HasKeyAccess("/foodir/foo/bar", true) { - t.Fatal("role has unexpected access") - } - if role.HasKeyAccess("/fookey", true) { - t.Fatal("role has unexpected access") - } -} diff --git a/server/etcdserver/api/v2error/error.go b/server/etcdserver/api/v2error/error.go index 623863254a56..ab24757d761a 100644 --- a/server/etcdserver/api/v2error/error.go +++ b/server/etcdserver/api/v2error/error.go @@ -125,10 +125,6 @@ type Error struct { Index uint64 `json:"index"` } -func NewRequestError(errorCode int, cause string) *Error { - return NewError(errorCode, cause, 0) -} - func NewError(errorCode int, cause string, index uint64) *Error { return &Error{ ErrorCode: errorCode, diff --git a/server/etcdserver/api/v2http/capability.go b/server/etcdserver/api/v2http/capability.go deleted file mode 100644 index 718b5ed502a5..000000000000 --- a/server/etcdserver/api/v2http/capability.go +++ /dev/null @@ -1,41 +0,0 @@ -// Copyright 2015 The etcd Authors -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -package v2http - -import ( - "fmt" - "net/http" - - "go.etcd.io/etcd/server/v3/etcdserver/api" - "go.etcd.io/etcd/server/v3/etcdserver/api/v2http/httptypes" -) - -func authCapabilityHandler(fn func(http.ResponseWriter, *http.Request)) http.HandlerFunc { - return func(w http.ResponseWriter, r *http.Request) { - if !api.IsCapabilityEnabled(api.AuthCapability) { - notCapable(w, r, api.AuthCapability) - return - } - fn(w, r) - } -} - -func notCapable(w http.ResponseWriter, r *http.Request, c api.Capability) { - herr := httptypes.NewHTTPError(http.StatusInternalServerError, fmt.Sprintf("Not capable of accessing %s feature during rolling upgrades.", c)) - if err := herr.WriteTo(w); err != nil { - // TODO: the following plog was removed, add the logging back if possible - // plog.Debugf("error writing HTTPError (%v) to %s", err, r.RemoteAddr) - } -} diff --git a/server/etcdserver/api/v2http/client.go b/server/etcdserver/api/v2http/client.go index fcd1fda6f833..7b56da357822 100644 --- a/server/etcdserver/api/v2http/client.go +++ b/server/etcdserver/api/v2http/client.go @@ -12,45 +12,18 @@ // See the License for the specific language governing permissions and // limitations under the License. +// Package v2http provides etcd client and server implementations. package v2http import ( - "context" - "encoding/json" - "errors" - "fmt" - "io" "net/http" - "net/url" - "path" - "strconv" - "strings" "time" - "go.etcd.io/etcd/api/v3/etcdserverpb" - "go.etcd.io/etcd/client/pkg/v3/types" "go.etcd.io/etcd/server/v3/etcdserver" - "go.etcd.io/etcd/server/v3/etcdserver/api" "go.etcd.io/etcd/server/v3/etcdserver/api/etcdhttp" - "go.etcd.io/etcd/server/v3/etcdserver/api/membership" - "go.etcd.io/etcd/server/v3/etcdserver/api/v2auth" - "go.etcd.io/etcd/server/v3/etcdserver/api/v2error" - "go.etcd.io/etcd/server/v3/etcdserver/api/v2http/httptypes" - stats "go.etcd.io/etcd/server/v3/etcdserver/api/v2stats" - "go.etcd.io/etcd/server/v3/etcdserver/api/v2store" - - "github.com/jonboulle/clockwork" "go.uber.org/zap" ) -const ( - authPrefix = "/v2/auth" - keysPrefix = "/v2/keys" - machinesPrefix = "/v2/machines" - membersPrefix = "/v2/members" - statsPrefix = "/v2/stats" -) - // NewClientHandler generates a muxed http.Handler with the given parameters to serve etcd client requests. func NewClientHandler(lg *zap.Logger, server etcdserver.ServerPeer, timeout time.Duration) http.Handler { if lg == nil { @@ -59,698 +32,19 @@ func NewClientHandler(lg *zap.Logger, server etcdserver.ServerPeer, timeout time mux := http.NewServeMux() etcdhttp.HandleBasic(lg, mux, server) etcdhttp.HandleMetricsHealth(lg, mux, server) - handleV2(lg, mux, server, timeout) return requestLogger(lg, mux) } -func handleV2(lg *zap.Logger, mux *http.ServeMux, server etcdserver.ServerV2, timeout time.Duration) { - sec := v2auth.NewStore(lg, server, timeout) - kh := &keysHandler{ - lg: lg, - sec: sec, - server: server, - cluster: server.Cluster(), - timeout: timeout, - clientCertAuthEnabled: server.ClientCertAuthEnabled(), - } - - sh := &statsHandler{ - lg: lg, - stats: server, - } - - mh := &membersHandler{ - lg: lg, - sec: sec, - server: server, - cluster: server.Cluster(), - timeout: timeout, - clock: clockwork.NewRealClock(), - clientCertAuthEnabled: server.ClientCertAuthEnabled(), - } - - mah := &machinesHandler{cluster: server.Cluster()} - - sech := &authHandler{ - lg: lg, - sec: sec, - cluster: server.Cluster(), - clientCertAuthEnabled: server.ClientCertAuthEnabled(), - } - mux.HandleFunc("/", http.NotFound) - mux.Handle(keysPrefix, kh) - mux.Handle(keysPrefix+"/", kh) - mux.HandleFunc(statsPrefix+"/store", sh.serveStore) - mux.HandleFunc(statsPrefix+"/self", sh.serveSelf) - mux.HandleFunc(statsPrefix+"/leader", sh.serveLeader) - mux.Handle(membersPrefix, mh) - mux.Handle(membersPrefix+"/", mh) - mux.Handle(machinesPrefix, mah) - handleAuth(mux, sech) -} - -type keysHandler struct { - lg *zap.Logger - sec v2auth.Store - server etcdserver.ServerV2 - cluster api.Cluster - timeout time.Duration - clientCertAuthEnabled bool -} - -func (h *keysHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) { - if !allowMethod(w, r.Method, "HEAD", "GET", "PUT", "POST", "DELETE") { - return - } - - w.Header().Set("X-Etcd-Cluster-ID", h.cluster.ID().String()) - - ctx, cancel := context.WithTimeout(context.Background(), h.timeout) - defer cancel() - clock := clockwork.NewRealClock() - startTime := clock.Now() - rr, noValueOnSuccess, err := parseKeyRequest(r, clock) - if err != nil { - writeKeyError(h.lg, w, err) - return - } - // The path must be valid at this point (we've parsed the request successfully). - if !hasKeyPrefixAccess(h.lg, h.sec, r, r.URL.Path[len(keysPrefix):], rr.Recursive, h.clientCertAuthEnabled) { - writeKeyNoAuth(w) - return - } - if !rr.Wait { - reportRequestReceived(rr) - } - resp, err := h.server.Do(ctx, rr) - if err != nil { - err = trimErrorPrefix(err, etcdserver.StoreKeysPrefix) - writeKeyError(h.lg, w, err) - reportRequestFailed(rr, err) - return - } - switch { - case resp.Event != nil: - if err := writeKeyEvent(w, resp, noValueOnSuccess); err != nil { - // Should never be reached - h.lg.Warn("failed to write key event", zap.Error(err)) - } - reportRequestCompleted(rr, startTime) - case resp.Watcher != nil: - ctx, cancel := context.WithTimeout(context.Background(), defaultWatchTimeout) - defer cancel() - handleKeyWatch(ctx, h.lg, w, resp, rr.Stream) - default: - writeKeyError(h.lg, w, errors.New("received response with no Event/Watcher")) - } -} - -type machinesHandler struct { - cluster api.Cluster -} - -func (h *machinesHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) { - if !allowMethod(w, r.Method, "GET", "HEAD") { - return - } - endpoints := h.cluster.ClientURLs() - w.Write([]byte(strings.Join(endpoints, ", "))) -} - -type membersHandler struct { - lg *zap.Logger - sec v2auth.Store - server etcdserver.ServerV2 - cluster api.Cluster - timeout time.Duration - clock clockwork.Clock - clientCertAuthEnabled bool -} - -func (h *membersHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) { - if !allowMethod(w, r.Method, "GET", "POST", "DELETE", "PUT") { - return - } - if !hasWriteRootAccess(h.lg, h.sec, r, h.clientCertAuthEnabled) { - writeNoAuth(h.lg, w, r) - return - } - w.Header().Set("X-Etcd-Cluster-ID", h.cluster.ID().String()) - - ctx, cancel := context.WithTimeout(context.Background(), h.timeout) - defer cancel() - - switch r.Method { - case "GET": - switch trimPrefix(r.URL.Path, membersPrefix) { - case "": - mc := newMemberCollection(h.cluster.Members()) - w.Header().Set("Content-Type", "application/json") - if err := json.NewEncoder(w).Encode(mc); err != nil { - h.lg.Warn("failed to encode members response", zap.Error(err)) - } - case "leader": - id := h.server.Leader() - if id == 0 { - writeError(h.lg, w, r, httptypes.NewHTTPError(http.StatusServiceUnavailable, "During election")) - return - } - m := newMember(h.cluster.Member(id)) - w.Header().Set("Content-Type", "application/json") - if err := json.NewEncoder(w).Encode(m); err != nil { - h.lg.Warn("failed to encode members response", zap.Error(err)) - } - default: - writeError(h.lg, w, r, httptypes.NewHTTPError(http.StatusNotFound, "Not found")) - } - - case "POST": - req := httptypes.MemberCreateRequest{} - if ok := unmarshalRequest(h.lg, r, &req, w); !ok { - return - } - now := h.clock.Now() - m := membership.NewMember("", req.PeerURLs, "", &now) - _, err := h.server.AddMember(ctx, *m) - switch { - case err == membership.ErrIDExists || err == membership.ErrPeerURLexists: - writeError(h.lg, w, r, httptypes.NewHTTPError(http.StatusConflict, err.Error())) - return - case err != nil: - h.lg.Warn( - "failed to add a member", - zap.String("member-id", m.ID.String()), - zap.Error(err), - ) - writeError(h.lg, w, r, err) - return - } - res := newMember(m) - w.Header().Set("Content-Type", "application/json") - w.WriteHeader(http.StatusCreated) - if err := json.NewEncoder(w).Encode(res); err != nil { - h.lg.Warn("failed to encode members response", zap.Error(err)) - } - - case "DELETE": - id, ok := getID(h.lg, r.URL.Path, w) - if !ok { - return - } - _, err := h.server.RemoveMember(ctx, uint64(id)) - switch { - case err == membership.ErrIDRemoved: - writeError(h.lg, w, r, httptypes.NewHTTPError(http.StatusGone, fmt.Sprintf("Member permanently removed: %s", id))) - case err == membership.ErrIDNotFound: - writeError(h.lg, w, r, httptypes.NewHTTPError(http.StatusNotFound, fmt.Sprintf("No such member: %s", id))) - case err != nil: - h.lg.Warn( - "failed to remove a member", - zap.String("member-id", id.String()), - zap.Error(err), - ) - writeError(h.lg, w, r, err) - default: - w.WriteHeader(http.StatusNoContent) - } - - case "PUT": - id, ok := getID(h.lg, r.URL.Path, w) - if !ok { - return - } - req := httptypes.MemberUpdateRequest{} - if ok := unmarshalRequest(h.lg, r, &req, w); !ok { - return - } - m := membership.Member{ - ID: id, - RaftAttributes: membership.RaftAttributes{PeerURLs: req.PeerURLs.StringSlice()}, - } - _, err := h.server.UpdateMember(ctx, m) - switch { - case err == membership.ErrPeerURLexists: - writeError(h.lg, w, r, httptypes.NewHTTPError(http.StatusConflict, err.Error())) - case err == membership.ErrIDNotFound: - writeError(h.lg, w, r, httptypes.NewHTTPError(http.StatusNotFound, fmt.Sprintf("No such member: %s", id))) - case err != nil: - h.lg.Warn( - "failed to update a member", - zap.String("member-id", m.ID.String()), - zap.Error(err), - ) - writeError(h.lg, w, r, err) - default: - w.WriteHeader(http.StatusNoContent) - } - } -} - -type statsHandler struct { - lg *zap.Logger - stats stats.Stats -} - -func (h *statsHandler) serveStore(w http.ResponseWriter, r *http.Request) { - if !allowMethod(w, r.Method, "GET") { - return - } - w.Header().Set("Content-Type", "application/json") - w.Write(h.stats.StoreStats()) -} - -func (h *statsHandler) serveSelf(w http.ResponseWriter, r *http.Request) { - if !allowMethod(w, r.Method, "GET") { - return - } - w.Header().Set("Content-Type", "application/json") - w.Write(h.stats.SelfStats()) -} - -func (h *statsHandler) serveLeader(w http.ResponseWriter, r *http.Request) { - if !allowMethod(w, r.Method, "GET") { - return - } - stats := h.stats.LeaderStats() - if stats == nil { - etcdhttp.WriteError(h.lg, w, r, httptypes.NewHTTPError(http.StatusForbidden, "not current leader")) - return - } - w.Header().Set("Content-Type", "application/json") - w.Write(stats) -} - -// parseKeyRequest converts a received http.Request on keysPrefix to -// a server Request, performing validation of supplied fields as appropriate. -// If any validation fails, an empty Request and non-nil error is returned. -func parseKeyRequest(r *http.Request, clock clockwork.Clock) (etcdserverpb.Request, bool, error) { - var noValueOnSuccess bool - emptyReq := etcdserverpb.Request{} - - err := r.ParseForm() - if err != nil { - return emptyReq, false, v2error.NewRequestError( - v2error.EcodeInvalidForm, - err.Error(), - ) - } - - if !strings.HasPrefix(r.URL.Path, keysPrefix) { - return emptyReq, false, v2error.NewRequestError( - v2error.EcodeInvalidForm, - "incorrect key prefix", - ) - } - p := path.Join(etcdserver.StoreKeysPrefix, r.URL.Path[len(keysPrefix):]) - - var pIdx, wIdx uint64 - if pIdx, err = getUint64(r.Form, "prevIndex"); err != nil { - return emptyReq, false, v2error.NewRequestError( - v2error.EcodeIndexNaN, - `invalid value for "prevIndex"`, - ) - } - if wIdx, err = getUint64(r.Form, "waitIndex"); err != nil { - return emptyReq, false, v2error.NewRequestError( - v2error.EcodeIndexNaN, - `invalid value for "waitIndex"`, - ) - } - - var rec, sort, wait, dir, quorum, stream bool - if rec, err = getBool(r.Form, "recursive"); err != nil { - return emptyReq, false, v2error.NewRequestError( - v2error.EcodeInvalidField, - `invalid value for "recursive"`, - ) - } - if sort, err = getBool(r.Form, "sorted"); err != nil { - return emptyReq, false, v2error.NewRequestError( - v2error.EcodeInvalidField, - `invalid value for "sorted"`, - ) - } - if wait, err = getBool(r.Form, "wait"); err != nil { - return emptyReq, false, v2error.NewRequestError( - v2error.EcodeInvalidField, - `invalid value for "wait"`, - ) - } - // TODO(jonboulle): define what parameters dir is/isn't compatible with? - if dir, err = getBool(r.Form, "dir"); err != nil { - return emptyReq, false, v2error.NewRequestError( - v2error.EcodeInvalidField, - `invalid value for "dir"`, - ) - } - if quorum, err = getBool(r.Form, "quorum"); err != nil { - return emptyReq, false, v2error.NewRequestError( - v2error.EcodeInvalidField, - `invalid value for "quorum"`, - ) - } - if stream, err = getBool(r.Form, "stream"); err != nil { - return emptyReq, false, v2error.NewRequestError( - v2error.EcodeInvalidField, - `invalid value for "stream"`, - ) - } - - if wait && r.Method != "GET" { - return emptyReq, false, v2error.NewRequestError( - v2error.EcodeInvalidField, - `"wait" can only be used with GET requests`, - ) - } - - pV := r.FormValue("prevValue") - if _, ok := r.Form["prevValue"]; ok && pV == "" { - return emptyReq, false, v2error.NewRequestError( - v2error.EcodePrevValueRequired, - `"prevValue" cannot be empty`, - ) - } - - if noValueOnSuccess, err = getBool(r.Form, "noValueOnSuccess"); err != nil { - return emptyReq, false, v2error.NewRequestError( - v2error.EcodeInvalidField, - `invalid value for "noValueOnSuccess"`, - ) - } - - // TTL is nullable, so leave it null if not specified - // or an empty string - var ttl *uint64 - if len(r.FormValue("ttl")) > 0 { - i, err := getUint64(r.Form, "ttl") - if err != nil { - return emptyReq, false, v2error.NewRequestError( - v2error.EcodeTTLNaN, - `invalid value for "ttl"`, +func requestLogger(lg *zap.Logger, handler http.Handler) http.Handler { + return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + if lg != nil { + lg.Debug( + "handling HTTP request", + zap.String("method", r.Method), + zap.String("request-uri", r.RequestURI), + zap.String("remote-addr", r.RemoteAddr), ) } - ttl = &i - } - - // prevExist is nullable, so leave it null if not specified - var pe *bool - if _, ok := r.Form["prevExist"]; ok { - bv, err := getBool(r.Form, "prevExist") - if err != nil { - return emptyReq, false, v2error.NewRequestError( - v2error.EcodeInvalidField, - "invalid value for prevExist", - ) - } - pe = &bv - } - - // refresh is nullable, so leave it null if not specified - var refresh *bool - if _, ok := r.Form["refresh"]; ok { - bv, err := getBool(r.Form, "refresh") - if err != nil { - return emptyReq, false, v2error.NewRequestError( - v2error.EcodeInvalidField, - "invalid value for refresh", - ) - } - refresh = &bv - if refresh != nil && *refresh { - val := r.FormValue("value") - if _, ok := r.Form["value"]; ok && val != "" { - return emptyReq, false, v2error.NewRequestError( - v2error.EcodeRefreshValue, - `A value was provided on a refresh`, - ) - } - if ttl == nil { - return emptyReq, false, v2error.NewRequestError( - v2error.EcodeRefreshTTLRequired, - `No TTL value set`, - ) - } - } - } - - rr := etcdserverpb.Request{ - Method: r.Method, - Path: p, - Val: r.FormValue("value"), - Dir: dir, - PrevValue: pV, - PrevIndex: pIdx, - PrevExist: pe, - Wait: wait, - Since: wIdx, - Recursive: rec, - Sorted: sort, - Quorum: quorum, - Stream: stream, - } - - if pe != nil { - rr.PrevExist = pe - } - - if refresh != nil { - rr.Refresh = refresh - } - - // Null TTL is equivalent to unset Expiration - if ttl != nil { - expr := time.Duration(*ttl) * time.Second - rr.Expiration = clock.Now().Add(expr).UnixNano() - } - - return rr, noValueOnSuccess, nil -} - -// writeKeyEvent trims the prefix of key path in a single Event under -// StoreKeysPrefix, serializes it and writes the resulting JSON to the given -// ResponseWriter, along with the appropriate headers. -func writeKeyEvent(w http.ResponseWriter, resp etcdserver.Response, noValueOnSuccess bool) error { - ev := resp.Event - if ev == nil { - return errors.New("cannot write empty Event") - } - w.Header().Set("Content-Type", "application/json") - w.Header().Set("X-Etcd-Index", fmt.Sprint(ev.EtcdIndex)) - w.Header().Set("X-Raft-Index", fmt.Sprint(resp.Index)) - w.Header().Set("X-Raft-Term", fmt.Sprint(resp.Term)) - - if ev.IsCreated() { - w.WriteHeader(http.StatusCreated) - } - - ev = trimEventPrefix(ev, etcdserver.StoreKeysPrefix) - if noValueOnSuccess && - (ev.Action == v2store.Set || ev.Action == v2store.CompareAndSwap || - ev.Action == v2store.Create || ev.Action == v2store.Update) { - ev.Node = nil - ev.PrevNode = nil - } - return json.NewEncoder(w).Encode(ev) -} - -func writeKeyNoAuth(w http.ResponseWriter) { - e := v2error.NewError(v2error.EcodeUnauthorized, "Insufficient credentials", 0) - e.WriteTo(w) -} - -// writeKeyError logs and writes the given Error to the ResponseWriter. -// If Error is not an etcdErr, the error will be converted to an etcd error. -func writeKeyError(lg *zap.Logger, w http.ResponseWriter, err error) { - if err == nil { - return - } - switch e := err.(type) { - case *v2error.Error: - e.WriteTo(w) - default: - switch err { - case etcdserver.ErrTimeoutDueToLeaderFail, etcdserver.ErrTimeoutDueToConnectionLost: - if lg != nil { - lg.Warn( - "v2 response error", - zap.String("internal-server-error", err.Error()), - ) - } - default: - if lg != nil { - lg.Warn( - "unexpected v2 response error", - zap.String("internal-server-error", err.Error()), - ) - } - } - ee := v2error.NewError(v2error.EcodeRaftInternal, err.Error(), 0) - ee.WriteTo(w) - } -} - -func handleKeyWatch(ctx context.Context, lg *zap.Logger, w http.ResponseWriter, resp etcdserver.Response, stream bool) { - wa := resp.Watcher - defer wa.Remove() - ech := wa.EventChan() - var nch <-chan bool - if x, ok := w.(http.CloseNotifier); ok { - nch = x.CloseNotify() - } - - w.Header().Set("Content-Type", "application/json") - w.Header().Set("X-Etcd-Index", fmt.Sprint(wa.StartIndex())) - w.Header().Set("X-Raft-Index", fmt.Sprint(resp.Index)) - w.Header().Set("X-Raft-Term", fmt.Sprint(resp.Term)) - w.WriteHeader(http.StatusOK) - - // Ensure headers are flushed early, in case of long polling - w.(http.Flusher).Flush() - - for { - select { - case <-nch: - // Client closed connection. Nothing to do. - return - case <-ctx.Done(): - // Timed out. net/http will close the connection for us, so nothing to do. - return - case ev, ok := <-ech: - if !ok { - // If the channel is closed this may be an indication of - // that notifications are much more than we are able to - // send to the client in time. Then we simply end streaming. - return - } - ev = trimEventPrefix(ev, etcdserver.StoreKeysPrefix) - if err := json.NewEncoder(w).Encode(ev); err != nil { - // Should never be reached - lg.Warn("failed to encode event", zap.Error(err)) - return - } - if !stream { - return - } - w.(http.Flusher).Flush() - } - } -} - -func trimEventPrefix(ev *v2store.Event, prefix string) *v2store.Event { - if ev == nil { - return nil - } - // Since the *Event may reference one in the store history - // history, we must copy it before modifying - e := ev.Clone() - trimNodeExternPrefix(e.Node, prefix) - trimNodeExternPrefix(e.PrevNode, prefix) - return e -} - -func trimNodeExternPrefix(n *v2store.NodeExtern, prefix string) { - if n == nil { - return - } - n.Key = strings.TrimPrefix(n.Key, prefix) - for _, nn := range n.Nodes { - trimNodeExternPrefix(nn, prefix) - } -} - -func trimErrorPrefix(err error, prefix string) error { - if e, ok := err.(*v2error.Error); ok { - e.Cause = strings.TrimPrefix(e.Cause, prefix) - } - return err -} - -func unmarshalRequest(lg *zap.Logger, r *http.Request, req json.Unmarshaler, w http.ResponseWriter) bool { - ctype := r.Header.Get("Content-Type") - semicolonPosition := strings.Index(ctype, ";") - if semicolonPosition != -1 { - ctype = strings.TrimSpace(strings.ToLower(ctype[0:semicolonPosition])) - } - if ctype != "application/json" { - writeError(lg, w, r, httptypes.NewHTTPError(http.StatusUnsupportedMediaType, fmt.Sprintf("Bad Content-Type %s, accept application/json", ctype))) - return false - } - b, err := io.ReadAll(r.Body) - if err != nil { - writeError(lg, w, r, httptypes.NewHTTPError(http.StatusBadRequest, err.Error())) - return false - } - if err := req.UnmarshalJSON(b); err != nil { - writeError(lg, w, r, httptypes.NewHTTPError(http.StatusBadRequest, err.Error())) - return false - } - return true -} - -func getID(lg *zap.Logger, p string, w http.ResponseWriter) (types.ID, bool) { - idStr := trimPrefix(p, membersPrefix) - if idStr == "" { - http.Error(w, "Method Not Allowed", http.StatusMethodNotAllowed) - return 0, false - } - id, err := types.IDFromString(idStr) - if err != nil { - writeError(lg, w, nil, httptypes.NewHTTPError(http.StatusNotFound, fmt.Sprintf("No such member: %s", idStr))) - return 0, false - } - return id, true -} - -// getUint64 extracts a uint64 by the given key from a Form. If the key does -// not exist in the form, 0 is returned. If the key exists but the value is -// badly formed, an error is returned. If multiple values are present only the -// first is considered. -func getUint64(form url.Values, key string) (i uint64, err error) { - if vals, ok := form[key]; ok { - i, err = strconv.ParseUint(vals[0], 10, 64) - } - return -} - -// getBool extracts a bool by the given key from a Form. If the key does not -// exist in the form, false is returned. If the key exists but the value is -// badly formed, an error is returned. If multiple values are present only the -// first is considered. -func getBool(form url.Values, key string) (b bool, err error) { - if vals, ok := form[key]; ok { - b, err = strconv.ParseBool(vals[0]) - } - return -} - -// trimPrefix removes a given prefix and any slash following the prefix -// e.g.: trimPrefix("foo", "foo") == trimPrefix("foo/", "foo") == "" -func trimPrefix(p, prefix string) (s string) { - s = strings.TrimPrefix(p, prefix) - s = strings.TrimPrefix(s, "/") - return -} - -func newMemberCollection(ms []*membership.Member) *httptypes.MemberCollection { - c := httptypes.MemberCollection(make([]httptypes.Member, len(ms))) - - for i, m := range ms { - c[i] = newMember(m) - } - - return &c -} - -func newMember(m *membership.Member) httptypes.Member { - tm := httptypes.Member{ - ID: m.ID.String(), - Name: m.Name, - PeerURLs: make([]string, len(m.PeerURLs)), - ClientURLs: make([]string, len(m.ClientURLs)), - } - - copy(tm.PeerURLs, m.PeerURLs) - copy(tm.ClientURLs, m.ClientURLs) - - return tm + handler.ServeHTTP(w, r) + }) } diff --git a/server/etcdserver/api/v2http/client_auth.go b/server/etcdserver/api/v2http/client_auth.go deleted file mode 100644 index 2c6e7744ed7b..000000000000 --- a/server/etcdserver/api/v2http/client_auth.go +++ /dev/null @@ -1,604 +0,0 @@ -// Copyright 2015 The etcd Authors -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -package v2http - -import ( - "encoding/json" - "net/http" - "path" - "strings" - - "go.etcd.io/etcd/server/v3/etcdserver/api" - "go.etcd.io/etcd/server/v3/etcdserver/api/v2auth" - "go.etcd.io/etcd/server/v3/etcdserver/api/v2http/httptypes" - - "go.uber.org/zap" -) - -type authHandler struct { - lg *zap.Logger - sec v2auth.Store - cluster api.Cluster - clientCertAuthEnabled bool -} - -func hasWriteRootAccess(lg *zap.Logger, sec v2auth.Store, r *http.Request, clientCertAuthEnabled bool) bool { - if r.Method == "GET" || r.Method == "HEAD" { - return true - } - return hasRootAccess(lg, sec, r, clientCertAuthEnabled) -} - -func userFromBasicAuth(lg *zap.Logger, sec v2auth.Store, r *http.Request) *v2auth.User { - username, password, ok := r.BasicAuth() - if !ok { - lg.Warn("malformed basic auth encoding") - return nil - } - user, err := sec.GetUser(username) - if err != nil { - return nil - } - - ok = sec.CheckPassword(user, password) - if !ok { - lg.Warn("incorrect password", zap.String("user-name", username)) - return nil - } - return &user -} - -func userFromClientCertificate(lg *zap.Logger, sec v2auth.Store, r *http.Request) *v2auth.User { - if r.TLS == nil { - return nil - } - - for _, chains := range r.TLS.VerifiedChains { - for _, chain := range chains { - lg.Debug("found common name", zap.String("common-name", chain.Subject.CommonName)) - user, err := sec.GetUser(chain.Subject.CommonName) - if err == nil { - lg.Debug( - "authenticated a user via common name", - zap.String("user-name", user.User), - zap.String("common-name", chain.Subject.CommonName), - ) - return &user - } - } - } - return nil -} - -func hasRootAccess(lg *zap.Logger, sec v2auth.Store, r *http.Request, clientCertAuthEnabled bool) bool { - if sec == nil { - // No store means no auth available, eg, tests. - return true - } - if !sec.AuthEnabled() { - return true - } - - var rootUser *v2auth.User - if r.Header.Get("Authorization") == "" && clientCertAuthEnabled { - rootUser = userFromClientCertificate(lg, sec, r) - if rootUser == nil { - return false - } - } else { - rootUser = userFromBasicAuth(lg, sec, r) - if rootUser == nil { - return false - } - } - - for _, role := range rootUser.Roles { - if role == v2auth.RootRoleName { - return true - } - } - - lg.Warn( - "a user does not have root role for resource", - zap.String("root-user", rootUser.User), - zap.String("root-role-name", v2auth.RootRoleName), - zap.String("resource-path", r.URL.Path), - ) - return false -} - -func hasKeyPrefixAccess(lg *zap.Logger, sec v2auth.Store, r *http.Request, key string, recursive, clientCertAuthEnabled bool) bool { - if sec == nil { - // No store means no auth available, eg, tests. - return true - } - if !sec.AuthEnabled() { - return true - } - - var user *v2auth.User - if r.Header.Get("Authorization") == "" { - if clientCertAuthEnabled { - user = userFromClientCertificate(lg, sec, r) - } - if user == nil { - return hasGuestAccess(lg, sec, r, key) - } - } else { - user = userFromBasicAuth(lg, sec, r) - if user == nil { - return false - } - } - - writeAccess := r.Method != "GET" && r.Method != "HEAD" - for _, roleName := range user.Roles { - role, err := sec.GetRole(roleName) - if err != nil { - continue - } - if recursive { - if role.HasRecursiveAccess(key, writeAccess) { - return true - } - } else if role.HasKeyAccess(key, writeAccess) { - return true - } - } - - lg.Warn( - "invalid access for user on key", - zap.String("user-name", user.User), - zap.String("key", key), - ) - return false -} - -func hasGuestAccess(lg *zap.Logger, sec v2auth.Store, r *http.Request, key string) bool { - writeAccess := r.Method != "GET" && r.Method != "HEAD" - role, err := sec.GetRole(v2auth.GuestRoleName) - if err != nil { - return false - } - if role.HasKeyAccess(key, writeAccess) { - return true - } - - lg.Warn( - "invalid access for a guest role on key", - zap.String("role-name", v2auth.GuestRoleName), - zap.String("key", key), - ) - return false -} - -func writeNoAuth(lg *zap.Logger, w http.ResponseWriter, r *http.Request) { - herr := httptypes.NewHTTPError(http.StatusUnauthorized, "Insufficient credentials") - if err := herr.WriteTo(w); err != nil { - lg.Debug( - "failed to write v2 HTTP error", - zap.String("remote-addr", r.RemoteAddr), - zap.Error(err), - ) - } -} - -func handleAuth(mux *http.ServeMux, sh *authHandler) { - mux.HandleFunc(authPrefix+"/roles", authCapabilityHandler(sh.baseRoles)) - mux.HandleFunc(authPrefix+"/roles/", authCapabilityHandler(sh.handleRoles)) - mux.HandleFunc(authPrefix+"/users", authCapabilityHandler(sh.baseUsers)) - mux.HandleFunc(authPrefix+"/users/", authCapabilityHandler(sh.handleUsers)) - mux.HandleFunc(authPrefix+"/enable", authCapabilityHandler(sh.enableDisable)) -} - -func (sh *authHandler) baseRoles(w http.ResponseWriter, r *http.Request) { - if !allowMethod(w, r.Method, "GET") { - return - } - if !hasRootAccess(sh.lg, sh.sec, r, sh.clientCertAuthEnabled) { - writeNoAuth(sh.lg, w, r) - return - } - - w.Header().Set("X-Etcd-Cluster-ID", sh.cluster.ID().String()) - w.Header().Set("Content-Type", "application/json") - - roles, err := sh.sec.AllRoles() - if err != nil { - writeError(sh.lg, w, r, err) - return - } - if roles == nil { - roles = make([]string, 0) - } - - err = r.ParseForm() - if err != nil { - writeError(sh.lg, w, r, err) - return - } - - var rolesCollections struct { - Roles []v2auth.Role `json:"roles"` - } - for _, roleName := range roles { - var role v2auth.Role - role, err = sh.sec.GetRole(roleName) - if err != nil { - writeError(sh.lg, w, r, err) - return - } - rolesCollections.Roles = append(rolesCollections.Roles, role) - } - err = json.NewEncoder(w).Encode(rolesCollections) - - if err != nil { - sh.lg.Warn( - "failed to encode base roles", - zap.String("url", r.URL.String()), - zap.Error(err), - ) - writeError(sh.lg, w, r, err) - return - } -} - -func (sh *authHandler) handleRoles(w http.ResponseWriter, r *http.Request) { - subpath := path.Clean(r.URL.Path[len(authPrefix):]) - // Split "/roles/rolename/command". - // First item is an empty string, second is "roles" - pieces := strings.Split(subpath, "/") - if len(pieces) == 2 { - sh.baseRoles(w, r) - return - } - if len(pieces) != 3 { - writeError(sh.lg, w, r, httptypes.NewHTTPError(http.StatusBadRequest, "Invalid path")) - return - } - sh.forRole(w, r, pieces[2]) -} - -func (sh *authHandler) forRole(w http.ResponseWriter, r *http.Request, role string) { - if !allowMethod(w, r.Method, "GET", "PUT", "DELETE") { - return - } - if !hasRootAccess(sh.lg, sh.sec, r, sh.clientCertAuthEnabled) { - writeNoAuth(sh.lg, w, r) - return - } - w.Header().Set("X-Etcd-Cluster-ID", sh.cluster.ID().String()) - w.Header().Set("Content-Type", "application/json") - - switch r.Method { - case "GET": - data, err := sh.sec.GetRole(role) - if err != nil { - writeError(sh.lg, w, r, err) - return - } - err = json.NewEncoder(w).Encode(data) - if err != nil { - sh.lg.Warn( - "failed to encode a role", - zap.String("url", r.URL.String()), - zap.Error(err), - ) - return - } - return - - case "PUT": - var in v2auth.Role - err := json.NewDecoder(r.Body).Decode(&in) - if err != nil { - writeError(sh.lg, w, r, httptypes.NewHTTPError(http.StatusBadRequest, "Invalid JSON in request body.")) - return - } - if in.Role != role { - writeError(sh.lg, w, r, httptypes.NewHTTPError(http.StatusBadRequest, "Role JSON name does not match the name in the URL")) - return - } - - var out v2auth.Role - - // create - if in.Grant.IsEmpty() && in.Revoke.IsEmpty() { - err = sh.sec.CreateRole(in) - if err != nil { - writeError(sh.lg, w, r, err) - return - } - w.WriteHeader(http.StatusCreated) - out = in - } else { - if !in.Permissions.IsEmpty() { - writeError(sh.lg, w, r, httptypes.NewHTTPError(http.StatusBadRequest, "Role JSON contains both permissions and grant/revoke")) - return - } - out, err = sh.sec.UpdateRole(in) - if err != nil { - writeError(sh.lg, w, r, err) - return - } - w.WriteHeader(http.StatusOK) - } - - err = json.NewEncoder(w).Encode(out) - if err != nil { - sh.lg.Warn( - "failed to encode a role", - zap.String("url", r.URL.String()), - zap.Error(err), - ) - return - } - return - - case "DELETE": - err := sh.sec.DeleteRole(role) - if err != nil { - writeError(sh.lg, w, r, err) - return - } - } -} - -type userWithRoles struct { - User string `json:"user"` - Roles []v2auth.Role `json:"roles,omitempty"` -} - -type usersCollections struct { - Users []userWithRoles `json:"users"` -} - -func (sh *authHandler) baseUsers(w http.ResponseWriter, r *http.Request) { - if !allowMethod(w, r.Method, "GET") { - return - } - if !hasRootAccess(sh.lg, sh.sec, r, sh.clientCertAuthEnabled) { - writeNoAuth(sh.lg, w, r) - return - } - w.Header().Set("X-Etcd-Cluster-ID", sh.cluster.ID().String()) - w.Header().Set("Content-Type", "application/json") - - users, err := sh.sec.AllUsers() - if err != nil { - writeError(sh.lg, w, r, err) - return - } - if users == nil { - users = make([]string, 0) - } - - err = r.ParseForm() - if err != nil { - writeError(sh.lg, w, r, err) - return - } - - ucs := usersCollections{} - for _, userName := range users { - var user v2auth.User - user, err = sh.sec.GetUser(userName) - if err != nil { - writeError(sh.lg, w, r, err) - return - } - - uwr := userWithRoles{User: user.User} - for _, roleName := range user.Roles { - var role v2auth.Role - role, err = sh.sec.GetRole(roleName) - if err != nil { - continue - } - uwr.Roles = append(uwr.Roles, role) - } - - ucs.Users = append(ucs.Users, uwr) - } - err = json.NewEncoder(w).Encode(ucs) - - if err != nil { - sh.lg.Warn( - "failed to encode users", - zap.String("url", r.URL.String()), - zap.Error(err), - ) - writeError(sh.lg, w, r, err) - return - } -} - -func (sh *authHandler) handleUsers(w http.ResponseWriter, r *http.Request) { - subpath := path.Clean(r.URL.Path[len(authPrefix):]) - // Split "/users/username". - // First item is an empty string, second is "users" - pieces := strings.Split(subpath, "/") - if len(pieces) == 2 { - sh.baseUsers(w, r) - return - } - if len(pieces) != 3 { - writeError(sh.lg, w, r, httptypes.NewHTTPError(http.StatusBadRequest, "Invalid path")) - return - } - sh.forUser(w, r, pieces[2]) -} - -func (sh *authHandler) forUser(w http.ResponseWriter, r *http.Request, user string) { - if !allowMethod(w, r.Method, "GET", "PUT", "DELETE") { - return - } - if !hasRootAccess(sh.lg, sh.sec, r, sh.clientCertAuthEnabled) { - writeNoAuth(sh.lg, w, r) - return - } - w.Header().Set("X-Etcd-Cluster-ID", sh.cluster.ID().String()) - w.Header().Set("Content-Type", "application/json") - - switch r.Method { - case "GET": - u, err := sh.sec.GetUser(user) - if err != nil { - writeError(sh.lg, w, r, err) - return - } - - err = r.ParseForm() - if err != nil { - writeError(sh.lg, w, r, err) - return - } - - uwr := userWithRoles{User: u.User} - for _, roleName := range u.Roles { - var role v2auth.Role - role, err = sh.sec.GetRole(roleName) - if err != nil { - writeError(sh.lg, w, r, err) - return - } - uwr.Roles = append(uwr.Roles, role) - } - err = json.NewEncoder(w).Encode(uwr) - - if err != nil { - sh.lg.Warn( - "failed to encode roles", - zap.String("url", r.URL.String()), - zap.Error(err), - ) - return - } - return - - case "PUT": - var u v2auth.User - err := json.NewDecoder(r.Body).Decode(&u) - if err != nil { - writeError(sh.lg, w, r, httptypes.NewHTTPError(http.StatusBadRequest, "Invalid JSON in request body.")) - return - } - if u.User != user { - writeError(sh.lg, w, r, httptypes.NewHTTPError(http.StatusBadRequest, "User JSON name does not match the name in the URL")) - return - } - - var ( - out v2auth.User - created bool - ) - - if len(u.Grant) == 0 && len(u.Revoke) == 0 { - // create or update - if len(u.Roles) != 0 { - out, err = sh.sec.CreateUser(u) - } else { - // if user passes in both password and roles, we are unsure about his/her - // intention. - out, created, err = sh.sec.CreateOrUpdateUser(u) - } - - if err != nil { - writeError(sh.lg, w, r, err) - return - } - } else { - // update case - if len(u.Roles) != 0 { - writeError(sh.lg, w, r, httptypes.NewHTTPError(http.StatusBadRequest, "User JSON contains both roles and grant/revoke")) - return - } - out, err = sh.sec.UpdateUser(u) - if err != nil { - writeError(sh.lg, w, r, err) - return - } - } - - if created { - w.WriteHeader(http.StatusCreated) - } else { - w.WriteHeader(http.StatusOK) - } - - out.Password = "" - - err = json.NewEncoder(w).Encode(out) - if err != nil { - sh.lg.Warn( - "failed to encode a user", - zap.String("url", r.URL.String()), - zap.Error(err), - ) - return - } - return - - case "DELETE": - err := sh.sec.DeleteUser(user) - if err != nil { - writeError(sh.lg, w, r, err) - return - } - } -} - -type enabled struct { - Enabled bool `json:"enabled"` -} - -func (sh *authHandler) enableDisable(w http.ResponseWriter, r *http.Request) { - if !allowMethod(w, r.Method, "GET", "PUT", "DELETE") { - return - } - if !hasWriteRootAccess(sh.lg, sh.sec, r, sh.clientCertAuthEnabled) { - writeNoAuth(sh.lg, w, r) - return - } - w.Header().Set("X-Etcd-Cluster-ID", sh.cluster.ID().String()) - w.Header().Set("Content-Type", "application/json") - isEnabled := sh.sec.AuthEnabled() - switch r.Method { - case "GET": - jsonDict := enabled{isEnabled} - err := json.NewEncoder(w).Encode(jsonDict) - if err != nil { - sh.lg.Warn( - "failed to encode a auth state", - zap.String("url", r.URL.String()), - zap.Error(err), - ) - } - - case "PUT": - err := sh.sec.EnableAuth() - if err != nil { - writeError(sh.lg, w, r, err) - return - } - - case "DELETE": - err := sh.sec.DisableAuth() - if err != nil { - writeError(sh.lg, w, r, err) - return - } - } -} diff --git a/server/etcdserver/api/v2http/client_auth_test.go b/server/etcdserver/api/v2http/client_auth_test.go deleted file mode 100644 index 9a5dd2c88c5b..000000000000 --- a/server/etcdserver/api/v2http/client_auth_test.go +++ /dev/null @@ -1,913 +0,0 @@ -// Copyright 2015 The etcd Authors -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -package v2http - -import ( - "crypto/tls" - "crypto/x509" - "encoding/json" - "encoding/pem" - "errors" - "fmt" - "net/http" - "net/http/httptest" - "net/url" - "os" - "path" - "sort" - "strings" - "testing" - - "go.etcd.io/etcd/server/v3/etcdserver/api" - "go.etcd.io/etcd/server/v3/etcdserver/api/v2auth" - - "go.uber.org/zap" -) - -const goodPassword = "good" - -func mustJSONRequest(t *testing.T, method string, p string, body string) *http.Request { - req, err := http.NewRequest(method, path.Join(authPrefix, p), strings.NewReader(body)) - if err != nil { - t.Fatalf("Error making JSON request: %s %s %s\n", method, p, body) - } - req.Header.Set("Content-Type", "application/json") - return req -} - -type mockAuthStore struct { - users map[string]*v2auth.User - roles map[string]*v2auth.Role - err error - enabled bool -} - -func (s *mockAuthStore) AllUsers() ([]string, error) { - var us []string - for u := range s.users { - us = append(us, u) - } - sort.Strings(us) - return us, s.err -} -func (s *mockAuthStore) GetUser(name string) (v2auth.User, error) { - u, ok := s.users[name] - if !ok { - return v2auth.User{}, s.err - } - return *u, s.err -} -func (s *mockAuthStore) CreateOrUpdateUser(user v2auth.User) (out v2auth.User, created bool, err error) { - if s.users == nil { - out, err = s.CreateUser(user) - return out, true, err - } - out, err = s.UpdateUser(user) - return out, false, err -} -func (s *mockAuthStore) CreateUser(user v2auth.User) (v2auth.User, error) { return user, s.err } -func (s *mockAuthStore) DeleteUser(name string) error { return s.err } -func (s *mockAuthStore) UpdateUser(user v2auth.User) (v2auth.User, error) { - return *s.users[user.User], s.err -} -func (s *mockAuthStore) AllRoles() ([]string, error) { - return []string{"awesome", "guest", "root"}, s.err -} -func (s *mockAuthStore) GetRole(name string) (v2auth.Role, error) { - r, ok := s.roles[name] - if ok { - return *r, s.err - } - return v2auth.Role{}, fmt.Errorf("%q does not exist (%v)", name, s.err) -} -func (s *mockAuthStore) CreateRole(role v2auth.Role) error { return s.err } -func (s *mockAuthStore) DeleteRole(name string) error { return s.err } -func (s *mockAuthStore) UpdateRole(role v2auth.Role) (v2auth.Role, error) { - return *s.roles[role.Role], s.err -} -func (s *mockAuthStore) AuthEnabled() bool { return s.enabled } -func (s *mockAuthStore) EnableAuth() error { return s.err } -func (s *mockAuthStore) DisableAuth() error { return s.err } - -func (s *mockAuthStore) CheckPassword(user v2auth.User, password string) bool { - return user.Password == password -} - -func (s *mockAuthStore) HashPassword(password string) (string, error) { - return password, nil -} - -func TestAuthFlow(t *testing.T) { - api.EnableCapability(api.AuthCapability) - var testCases = []struct { - req *http.Request - store mockAuthStore - - wcode int - wbody string - }{ - { - req: mustJSONRequest(t, "PUT", "users/alice", `{{{{{{{`), - store: mockAuthStore{}, - wcode: http.StatusBadRequest, - wbody: `{"message":"Invalid JSON in request body."}`, - }, - { - req: mustJSONRequest(t, "PUT", "users/alice", `{"user": "alice", "password": "goodpassword"}`), - store: mockAuthStore{enabled: true}, - wcode: http.StatusUnauthorized, - wbody: `{"message":"Insufficient credentials"}`, - }, - // Users - { - req: mustJSONRequest(t, "GET", "users", ""), - store: mockAuthStore{ - users: map[string]*v2auth.User{ - "alice": { - User: "alice", - Roles: []string{"alicerole", "guest"}, - Password: "wheeee", - }, - "bob": { - User: "bob", - Roles: []string{"guest"}, - Password: "wheeee", - }, - "root": { - User: "root", - Roles: []string{"root"}, - Password: "wheeee", - }, - }, - roles: map[string]*v2auth.Role{ - "alicerole": { - Role: "alicerole", - }, - "guest": { - Role: "guest", - }, - "root": { - Role: "root", - }, - }, - }, - wcode: http.StatusOK, - wbody: `{"users":[` + - `{"user":"alice","roles":[` + - `{"role":"alicerole","permissions":{"kv":{"read":null,"write":null}}},` + - `{"role":"guest","permissions":{"kv":{"read":null,"write":null}}}` + - `]},` + - `{"user":"bob","roles":[{"role":"guest","permissions":{"kv":{"read":null,"write":null}}}]},` + - `{"user":"root","roles":[{"role":"root","permissions":{"kv":{"read":null,"write":null}}}]}]}`, - }, - { - req: mustJSONRequest(t, "GET", "users/alice", ""), - store: mockAuthStore{ - users: map[string]*v2auth.User{ - "alice": { - User: "alice", - Roles: []string{"alicerole"}, - Password: "wheeee", - }, - }, - roles: map[string]*v2auth.Role{ - "alicerole": { - Role: "alicerole", - }, - }, - }, - wcode: http.StatusOK, - wbody: `{"user":"alice","roles":[{"role":"alicerole","permissions":{"kv":{"read":null,"write":null}}}]}`, - }, - { - req: mustJSONRequest(t, "PUT", "users/alice", `{"user": "alice", "password": "goodpassword"}`), - store: mockAuthStore{}, - wcode: http.StatusCreated, - wbody: `{"user":"alice","roles":null}`, - }, - { - req: mustJSONRequest(t, "DELETE", "users/alice", ``), - store: mockAuthStore{}, - wcode: http.StatusOK, - wbody: ``, - }, - { - req: mustJSONRequest(t, "PUT", "users/alice", `{"user": "alice", "password": "goodpassword"}`), - store: mockAuthStore{ - users: map[string]*v2auth.User{ - "alice": { - User: "alice", - Roles: []string{"alicerole", "guest"}, - Password: "wheeee", - }, - }, - }, - wcode: http.StatusOK, - wbody: `{"user":"alice","roles":["alicerole","guest"]}`, - }, - { - req: mustJSONRequest(t, "PUT", "users/alice", `{"user": "alice", "grant": ["alicerole"]}`), - store: mockAuthStore{ - users: map[string]*v2auth.User{ - "alice": { - User: "alice", - Roles: []string{"alicerole", "guest"}, - Password: "wheeee", - }, - }, - }, - wcode: http.StatusOK, - wbody: `{"user":"alice","roles":["alicerole","guest"]}`, - }, - { - req: mustJSONRequest(t, "GET", "users/alice", ``), - store: mockAuthStore{ - users: map[string]*v2auth.User{}, - err: v2auth.Error{Status: http.StatusNotFound, Errmsg: "auth: User alice doesn't exist."}, - }, - wcode: http.StatusNotFound, - wbody: `{"message":"auth: User alice doesn't exist."}`, - }, - { - req: mustJSONRequest(t, "GET", "roles/manager", ""), - store: mockAuthStore{ - roles: map[string]*v2auth.Role{ - "manager": { - Role: "manager", - }, - }, - }, - wcode: http.StatusOK, - wbody: `{"role":"manager","permissions":{"kv":{"read":null,"write":null}}}`, - }, - { - req: mustJSONRequest(t, "DELETE", "roles/manager", ``), - store: mockAuthStore{}, - wcode: http.StatusOK, - wbody: ``, - }, - { - req: mustJSONRequest(t, "PUT", "roles/manager", `{"role":"manager","permissions":{"kv":{"read":[],"write":[]}}}`), - store: mockAuthStore{}, - wcode: http.StatusCreated, - wbody: `{"role":"manager","permissions":{"kv":{"read":[],"write":[]}}}`, - }, - { - req: mustJSONRequest(t, "PUT", "roles/manager", `{"role":"manager","revoke":{"kv":{"read":["foo"],"write":[]}}}`), - store: mockAuthStore{ - roles: map[string]*v2auth.Role{ - "manager": { - Role: "manager", - }, - }, - }, - wcode: http.StatusOK, - wbody: `{"role":"manager","permissions":{"kv":{"read":null,"write":null}}}`, - }, - { - req: mustJSONRequest(t, "GET", "roles", ""), - store: mockAuthStore{ - roles: map[string]*v2auth.Role{ - "awesome": { - Role: "awesome", - }, - "guest": { - Role: "guest", - }, - "root": { - Role: "root", - }, - }, - }, - wcode: http.StatusOK, - wbody: `{"roles":[{"role":"awesome","permissions":{"kv":{"read":null,"write":null}}},` + - `{"role":"guest","permissions":{"kv":{"read":null,"write":null}}},` + - `{"role":"root","permissions":{"kv":{"read":null,"write":null}}}]}`, - }, - { - req: mustJSONRequest(t, "GET", "enable", ""), - store: mockAuthStore{ - enabled: true, - }, - wcode: http.StatusOK, - wbody: `{"enabled":true}`, - }, - { - req: mustJSONRequest(t, "PUT", "enable", ""), - store: mockAuthStore{ - enabled: false, - }, - wcode: http.StatusOK, - wbody: ``, - }, - { - req: (func() *http.Request { - req := mustJSONRequest(t, "DELETE", "enable", "") - req.SetBasicAuth("root", "good") - return req - })(), - store: mockAuthStore{ - enabled: true, - users: map[string]*v2auth.User{ - "root": { - User: "root", - Password: goodPassword, - Roles: []string{"root"}, - }, - }, - roles: map[string]*v2auth.Role{ - "root": { - Role: "root", - }, - }, - }, - wcode: http.StatusOK, - wbody: ``, - }, - { - req: (func() *http.Request { - req := mustJSONRequest(t, "DELETE", "enable", "") - req.SetBasicAuth("root", "bad") - return req - })(), - store: mockAuthStore{ - enabled: true, - users: map[string]*v2auth.User{ - "root": { - User: "root", - Password: goodPassword, - Roles: []string{"root"}, - }, - }, - roles: map[string]*v2auth.Role{ - "root": { - Role: "guest", - }, - }, - }, - wcode: http.StatusUnauthorized, - wbody: `{"message":"Insufficient credentials"}`, - }, - } - - for i, tt := range testCases { - mux := http.NewServeMux() - h := &authHandler{ - lg: zap.NewExample(), - sec: &tt.store, - cluster: &fakeCluster{id: 1}, - } - handleAuth(mux, h) - rw := httptest.NewRecorder() - mux.ServeHTTP(rw, tt.req) - if rw.Code != tt.wcode { - t.Errorf("#%d: got code=%d, want %d", i, rw.Code, tt.wcode) - } - g := rw.Body.String() - g = strings.TrimSpace(g) - if g != tt.wbody { - t.Errorf("#%d: got body=%s, want %s", i, g, tt.wbody) - } - } -} - -func TestGetUserGrantedWithNonexistingRole(t *testing.T) { - sh := &authHandler{ - sec: &mockAuthStore{ - users: map[string]*v2auth.User{ - "root": { - User: "root", - Roles: []string{"root", "foo"}, - }, - }, - roles: map[string]*v2auth.Role{ - "root": { - Role: "root", - }, - }, - }, - cluster: &fakeCluster{id: 1}, - } - srv := httptest.NewServer(http.HandlerFunc(sh.baseUsers)) - defer srv.Close() - - req, err := http.NewRequest("GET", "", nil) - if err != nil { - t.Fatal(err) - } - req.URL, err = url.Parse(srv.URL) - if err != nil { - t.Fatal(err) - } - req.Header.Set("Content-Type", "application/json") - - cli := http.DefaultClient - resp, err := cli.Do(req) - if err != nil { - t.Fatal(err) - } - defer resp.Body.Close() - - var uc usersCollections - if err := json.NewDecoder(resp.Body).Decode(&uc); err != nil { - t.Fatal(err) - } - if len(uc.Users) != 1 { - t.Fatalf("expected 1 user, got %+v", uc.Users) - } - if uc.Users[0].User != "root" { - t.Fatalf("expected 'root', got %q", uc.Users[0].User) - } - if len(uc.Users[0].Roles) != 1 { - t.Fatalf("expected 1 role, got %+v", uc.Users[0].Roles) - } - if uc.Users[0].Roles[0].Role != "root" { - t.Fatalf("expected 'root', got %q", uc.Users[0].Roles[0].Role) - } -} - -func mustAuthRequest(username, password string) *http.Request { - req, err := http.NewRequest(http.MethodGet, "path", strings.NewReader("")) - if err != nil { - panic("Cannot make auth request: " + err.Error()) - } - req.SetBasicAuth(username, password) - return req -} - -func unauthedRequest() *http.Request { - req, err := http.NewRequest(http.MethodGet, "path", strings.NewReader("")) - if err != nil { - panic("Cannot make request: " + err.Error()) - } - return req -} - -func tlsAuthedRequest(req *http.Request, certname string) *http.Request { - bytes, err := os.ReadFile(fmt.Sprintf("testdata/%s.pem", certname)) - if err != nil { - panic(err) - } - - block, _ := pem.Decode(bytes) - cert, err := x509.ParseCertificate(block.Bytes) - if err != nil { - panic(err) - } - - req.TLS = &tls.ConnectionState{ - VerifiedChains: [][]*x509.Certificate{{cert}}, - } - return req -} - -func TestPrefixAccess(t *testing.T) { - var table = []struct { - key string - req *http.Request - store *mockAuthStore - hasRoot bool - hasKeyPrefixAccess bool - hasRecursiveAccess bool - }{ - { - key: "/foo", - req: mustAuthRequest("root", "good"), - store: &mockAuthStore{ - users: map[string]*v2auth.User{ - "root": { - User: "root", - Password: goodPassword, - Roles: []string{"root"}, - }, - }, - roles: map[string]*v2auth.Role{ - "root": { - Role: "root", - }, - }, - enabled: true, - }, - hasRoot: true, - hasKeyPrefixAccess: true, - hasRecursiveAccess: true, - }, - { - key: "/foo", - req: mustAuthRequest("user", "good"), - store: &mockAuthStore{ - users: map[string]*v2auth.User{ - "user": { - User: "user", - Password: goodPassword, - Roles: []string{"foorole"}, - }, - }, - roles: map[string]*v2auth.Role{ - "foorole": { - Role: "foorole", - Permissions: v2auth.Permissions{ - KV: v2auth.RWPermission{ - Read: []string{"/foo"}, - Write: []string{"/foo"}, - }, - }, - }, - }, - enabled: true, - }, - hasRoot: false, - hasKeyPrefixAccess: true, - hasRecursiveAccess: false, - }, - { - key: "/foo", - req: mustAuthRequest("user", "good"), - store: &mockAuthStore{ - users: map[string]*v2auth.User{ - "user": { - User: "user", - Password: goodPassword, - Roles: []string{"foorole"}, - }, - }, - roles: map[string]*v2auth.Role{ - "foorole": { - Role: "foorole", - Permissions: v2auth.Permissions{ - KV: v2auth.RWPermission{ - Read: []string{"/foo*"}, - Write: []string{"/foo*"}, - }, - }, - }, - }, - enabled: true, - }, - hasRoot: false, - hasKeyPrefixAccess: true, - hasRecursiveAccess: true, - }, - { - key: "/foo", - req: mustAuthRequest("user", "bad"), - store: &mockAuthStore{ - users: map[string]*v2auth.User{ - "user": { - User: "user", - Password: goodPassword, - Roles: []string{"foorole"}, - }, - }, - roles: map[string]*v2auth.Role{ - "foorole": { - Role: "foorole", - Permissions: v2auth.Permissions{ - KV: v2auth.RWPermission{ - Read: []string{"/foo*"}, - Write: []string{"/foo*"}, - }, - }, - }, - }, - enabled: true, - }, - hasRoot: false, - hasKeyPrefixAccess: false, - hasRecursiveAccess: false, - }, - { - key: "/foo", - req: mustAuthRequest("user", "good"), - store: &mockAuthStore{ - users: map[string]*v2auth.User{}, - err: errors.New("Not the user"), - enabled: true, - }, - hasRoot: false, - hasKeyPrefixAccess: false, - hasRecursiveAccess: false, - }, - { - key: "/foo", - req: mustJSONRequest(t, "GET", "somepath", ""), - store: &mockAuthStore{ - users: map[string]*v2auth.User{ - "user": { - User: "user", - Password: goodPassword, - Roles: []string{"foorole"}, - }, - }, - roles: map[string]*v2auth.Role{ - "guest": { - Role: "guest", - Permissions: v2auth.Permissions{ - KV: v2auth.RWPermission{ - Read: []string{"/foo*"}, - Write: []string{"/foo*"}, - }, - }, - }, - }, - enabled: true, - }, - hasRoot: false, - hasKeyPrefixAccess: true, - hasRecursiveAccess: true, - }, - { - key: "/bar", - req: mustJSONRequest(t, "GET", "somepath", ""), - store: &mockAuthStore{ - users: map[string]*v2auth.User{ - "user": { - User: "user", - Password: goodPassword, - Roles: []string{"foorole"}, - }, - }, - roles: map[string]*v2auth.Role{ - "guest": { - Role: "guest", - Permissions: v2auth.Permissions{ - KV: v2auth.RWPermission{ - Read: []string{"/foo*"}, - Write: []string{"/foo*"}, - }, - }, - }, - }, - enabled: true, - }, - hasRoot: false, - hasKeyPrefixAccess: false, - hasRecursiveAccess: false, - }, - // check access for multiple roles - { - key: "/foo", - req: mustAuthRequest("user", "good"), - store: &mockAuthStore{ - users: map[string]*v2auth.User{ - "user": { - User: "user", - Password: goodPassword, - Roles: []string{"role1", "role2"}, - }, - }, - roles: map[string]*v2auth.Role{ - "role1": { - Role: "role1", - }, - "role2": { - Role: "role2", - Permissions: v2auth.Permissions{ - KV: v2auth.RWPermission{ - Read: []string{"/foo"}, - Write: []string{"/foo"}, - }, - }, - }, - }, - enabled: true, - }, - hasRoot: false, - hasKeyPrefixAccess: true, - hasRecursiveAccess: false, - }, - { - key: "/foo", - req: (func() *http.Request { - req := mustJSONRequest(t, "GET", "somepath", "") - req.Header.Set("Authorization", "malformedencoding") - return req - })(), - store: &mockAuthStore{ - enabled: true, - users: map[string]*v2auth.User{ - "root": { - User: "root", - Password: goodPassword, - Roles: []string{"root"}, - }, - }, - roles: map[string]*v2auth.Role{ - "guest": { - Role: "guest", - Permissions: v2auth.Permissions{ - KV: v2auth.RWPermission{ - Read: []string{"/foo*"}, - Write: []string{"/foo*"}, - }, - }, - }, - }, - }, - hasRoot: false, - hasKeyPrefixAccess: false, - hasRecursiveAccess: false, - }, - { // guest access in non-TLS mode - key: "/foo", - req: (func() *http.Request { - return mustJSONRequest(t, "GET", "somepath", "") - })(), - store: &mockAuthStore{ - enabled: true, - users: map[string]*v2auth.User{ - "root": { - User: "root", - Password: goodPassword, - Roles: []string{"root"}, - }, - }, - roles: map[string]*v2auth.Role{ - "guest": { - Role: "guest", - Permissions: v2auth.Permissions{ - KV: v2auth.RWPermission{ - Read: []string{"/foo*"}, - Write: []string{"/foo*"}, - }, - }, - }, - }, - }, - hasRoot: false, - hasKeyPrefixAccess: true, - hasRecursiveAccess: true, - }, - } - - for i, tt := range table { - if tt.hasRoot != hasRootAccess(zap.NewExample(), tt.store, tt.req, true) { - t.Errorf("#%d: hasRoot doesn't match (expected %v)", i, tt.hasRoot) - } - if tt.hasKeyPrefixAccess != hasKeyPrefixAccess(zap.NewExample(), tt.store, tt.req, tt.key, false, true) { - t.Errorf("#%d: hasKeyPrefixAccess doesn't match (expected %v)", i, tt.hasRoot) - } - if tt.hasRecursiveAccess != hasKeyPrefixAccess(zap.NewExample(), tt.store, tt.req, tt.key, true, true) { - t.Errorf("#%d: hasRecursiveAccess doesn't match (expected %v)", i, tt.hasRoot) - } - } -} - -func TestUserFromClientCertificate(t *testing.T) { - witherror := &mockAuthStore{ - users: map[string]*v2auth.User{ - "user": { - User: "user", - Roles: []string{"root"}, - Password: "password", - }, - "basicauth": { - User: "basicauth", - Roles: []string{"root"}, - Password: "password", - }, - }, - roles: map[string]*v2auth.Role{ - "root": { - Role: "root", - }, - }, - err: errors.New(""), - } - - noerror := &mockAuthStore{ - users: map[string]*v2auth.User{ - "user": { - User: "user", - Roles: []string{"root"}, - Password: "password", - }, - "basicauth": { - User: "basicauth", - Roles: []string{"root"}, - Password: "password", - }, - }, - roles: map[string]*v2auth.Role{ - "root": { - Role: "root", - }, - }, - } - - var table = []struct { - req *http.Request - userExists bool - store v2auth.Store - username string - }{ - { - // non tls request - req: unauthedRequest(), - userExists: false, - store: witherror, - }, - { - // cert with cn of existing user - req: tlsAuthedRequest(unauthedRequest(), "user"), - userExists: true, - username: "user", - store: noerror, - }, - { - // cert with cn of non-existing user - req: tlsAuthedRequest(unauthedRequest(), "otheruser"), - userExists: false, - store: witherror, - }, - } - - for i, tt := range table { - user := userFromClientCertificate(zap.NewExample(), tt.store, tt.req) - userExists := user != nil - - if tt.userExists != userExists { - t.Errorf("#%d: userFromClientCertificate doesn't match (expected %v)", i, tt.userExists) - } - if user != nil && (tt.username != user.User) { - t.Errorf("#%d: userFromClientCertificate username doesn't match (expected %s, got %s)", i, tt.username, user.User) - } - } -} - -func TestUserFromBasicAuth(t *testing.T) { - sec := &mockAuthStore{ - users: map[string]*v2auth.User{ - "user": { - User: "user", - Roles: []string{"root"}, - Password: "password", - }, - }, - roles: map[string]*v2auth.Role{ - "root": { - Role: "root", - }, - }, - } - - var table = []struct { - username string - req *http.Request - userExists bool - }{ - { - // valid user, valid pass - username: "user", - req: mustAuthRequest("user", "password"), - userExists: true, - }, - { - // valid user, bad pass - username: "user", - req: mustAuthRequest("user", "badpass"), - userExists: false, - }, - { - // valid user, no pass - username: "user", - req: mustAuthRequest("user", ""), - userExists: false, - }, - { - // missing user - username: "missing", - req: mustAuthRequest("missing", "badpass"), - userExists: false, - }, - { - // no basic auth - req: unauthedRequest(), - userExists: false, - }, - } - - for i, tt := range table { - user := userFromBasicAuth(zap.NewExample(), sec, tt.req) - userExists := user != nil - - if tt.userExists != userExists { - t.Errorf("#%d: userFromBasicAuth doesn't match (expected %v)", i, tt.userExists) - } - if user != nil && (tt.username != user.User) { - t.Errorf("#%d: userFromBasicAuth username doesn't match (expected %s, got %s)", i, tt.username, user.User) - } - } -} diff --git a/server/etcdserver/api/v2http/client_test.go b/server/etcdserver/api/v2http/client_test.go deleted file mode 100644 index 49a5da007180..000000000000 --- a/server/etcdserver/api/v2http/client_test.go +++ /dev/null @@ -1,2080 +0,0 @@ -// Copyright 2015 The etcd Authors -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -package v2http - -import ( - "bytes" - "context" - "encoding/json" - "errors" - "io" - "net/http" - "net/http/httptest" - "net/url" - "path" - "reflect" - "strings" - "testing" - "time" - - "go.etcd.io/etcd/api/v3/etcdserverpb" - "go.etcd.io/etcd/client/pkg/v3/testutil" - "go.etcd.io/etcd/client/pkg/v3/types" - "go.etcd.io/etcd/raft/v3/raftpb" - "go.etcd.io/etcd/server/v3/etcdserver" - "go.etcd.io/etcd/server/v3/etcdserver/api" - "go.etcd.io/etcd/server/v3/etcdserver/api/membership" - "go.etcd.io/etcd/server/v3/etcdserver/api/v2error" - "go.etcd.io/etcd/server/v3/etcdserver/api/v2http/httptypes" - "go.etcd.io/etcd/server/v3/etcdserver/api/v2store" - - "github.com/coreos/go-semver/semver" - "github.com/jonboulle/clockwork" - "go.uber.org/zap" -) - -func mustMarshalEvent(t *testing.T, ev *v2store.Event) string { - b := new(bytes.Buffer) - if err := json.NewEncoder(b).Encode(ev); err != nil { - t.Fatalf("error marshalling event %#v: %v", ev, err) - } - return b.String() -} - -// mustNewForm takes a set of Values and constructs a PUT *http.Request, -// with a URL constructed from appending the given path to the standard keysPrefix -func mustNewForm(t *testing.T, p string, vals url.Values) *http.Request { - u := testutil.MustNewURL(t, path.Join(keysPrefix, p)) - req, err := http.NewRequest("PUT", u.String(), strings.NewReader(vals.Encode())) - req.Header.Set("Content-Type", "application/x-www-form-urlencoded") - if err != nil { - t.Fatalf("error creating new request: %v", err) - } - return req -} - -// mustNewPostForm takes a set of Values and constructs a POST *http.Request, -// with a URL constructed from appending the given path to the standard keysPrefix -func mustNewPostForm(t *testing.T, p string, vals url.Values) *http.Request { - u := testutil.MustNewURL(t, path.Join(keysPrefix, p)) - req, err := http.NewRequest("POST", u.String(), strings.NewReader(vals.Encode())) - req.Header.Set("Content-Type", "application/x-www-form-urlencoded") - if err != nil { - t.Fatalf("error creating new request: %v", err) - } - return req -} - -// mustNewRequest takes a path, appends it to the standard keysPrefix, and constructs -// a GET *http.Request referencing the resulting URL -func mustNewRequest(t *testing.T, p string) *http.Request { - return mustNewMethodRequest(t, "GET", p) -} - -func mustNewMethodRequest(t *testing.T, m, p string) *http.Request { - return &http.Request{ - Method: m, - URL: testutil.MustNewURL(t, path.Join(keysPrefix, p)), - } -} - -type fakeServer struct { - dummyRaftTimer - dummyStats -} - -func (s *fakeServer) Leader() types.ID { return types.ID(1) } -func (s *fakeServer) Alarms() []*etcdserverpb.AlarmMember { return nil } -func (s *fakeServer) LeaderChangedNotify() <-chan struct{} { return nil } -func (s *fakeServer) Cluster() api.Cluster { return nil } -func (s *fakeServer) ClusterVersion() *semver.Version { return nil } -func (s *fakeServer) RaftHandler() http.Handler { return nil } -func (s *fakeServer) Do(ctx context.Context, r etcdserverpb.Request) (rr etcdserver.Response, err error) { - return -} -func (s *fakeServer) ClientCertAuthEnabled() bool { return false } - -type serverRecorder struct { - fakeServer - actions []action -} - -func (s *serverRecorder) Do(_ context.Context, r etcdserverpb.Request) (etcdserver.Response, error) { - s.actions = append(s.actions, action{name: "Do", params: []interface{}{r}}) - return etcdserver.Response{}, nil -} -func (s *serverRecorder) Process(_ context.Context, m raftpb.Message) error { - s.actions = append(s.actions, action{name: "Process", params: []interface{}{m}}) - return nil -} -func (s *serverRecorder) AddMember(_ context.Context, m membership.Member) ([]*membership.Member, error) { - s.actions = append(s.actions, action{name: "AddMember", params: []interface{}{m}}) - return nil, nil -} -func (s *serverRecorder) RemoveMember(_ context.Context, id uint64) ([]*membership.Member, error) { - s.actions = append(s.actions, action{name: "RemoveMember", params: []interface{}{id}}) - return nil, nil -} - -func (s *serverRecorder) UpdateMember(_ context.Context, m membership.Member) ([]*membership.Member, error) { - s.actions = append(s.actions, action{name: "UpdateMember", params: []interface{}{m}}) - return nil, nil -} - -func (s *serverRecorder) PromoteMember(_ context.Context, id uint64) ([]*membership.Member, error) { - s.actions = append(s.actions, action{name: "PromoteMember", params: []interface{}{id}}) - return nil, nil -} - -type action struct { - name string - params []interface{} -} - -// flushingRecorder provides a channel to allow users to block until the Recorder is Flushed() -type flushingRecorder struct { - *httptest.ResponseRecorder - ch chan struct{} -} - -func (fr *flushingRecorder) Flush() { - fr.ResponseRecorder.Flush() - fr.ch <- struct{}{} -} - -// resServer implements the etcd.Server interface for testing. -// It returns the given response from any Do calls, and nil error -type resServer struct { - fakeServer - res etcdserver.Response -} - -func (rs *resServer) Do(_ context.Context, _ etcdserverpb.Request) (etcdserver.Response, error) { - return rs.res, nil -} -func (rs *resServer) Process(_ context.Context, _ raftpb.Message) error { return nil } -func (rs *resServer) AddMember(_ context.Context, _ membership.Member) ([]*membership.Member, error) { - return nil, nil -} -func (rs *resServer) RemoveMember(_ context.Context, _ uint64) ([]*membership.Member, error) { - return nil, nil -} -func (rs *resServer) UpdateMember(_ context.Context, _ membership.Member) ([]*membership.Member, error) { - return nil, nil -} -func (rs *resServer) PromoteMember(_ context.Context, _ uint64) ([]*membership.Member, error) { - return nil, nil -} - -func boolp(b bool) *bool { return &b } - -type dummyRaftTimer struct{} - -func (drt dummyRaftTimer) Index() uint64 { return uint64(100) } -func (drt dummyRaftTimer) Term() uint64 { return uint64(5) } - -type dummyWatcher struct { - echan chan *v2store.Event - sidx uint64 -} - -func (w *dummyWatcher) EventChan() chan *v2store.Event { - return w.echan -} -func (w *dummyWatcher) StartIndex() uint64 { return w.sidx } -func (w *dummyWatcher) Remove() {} - -func TestBadRefreshRequest(t *testing.T) { - tests := []struct { - in *http.Request - wcode int - }{ - { - mustNewRequest(t, "foo?refresh=true&value=test"), - v2error.EcodeRefreshValue, - }, - { - mustNewRequest(t, "foo?refresh=true&value=10"), - v2error.EcodeRefreshValue, - }, - { - mustNewRequest(t, "foo?refresh=true"), - v2error.EcodeRefreshTTLRequired, - }, - { - mustNewRequest(t, "foo?refresh=true&ttl="), - v2error.EcodeRefreshTTLRequired, - }, - } - for i, tt := range tests { - got, _, err := parseKeyRequest(tt.in, clockwork.NewFakeClock()) - if err == nil { - t.Errorf("#%d: unexpected nil error!", i) - continue - } - ee, ok := err.(*v2error.Error) - if !ok { - t.Errorf("#%d: err is not etcd.Error!", i) - continue - } - if ee.ErrorCode != tt.wcode { - t.Errorf("#%d: code=%d, want %v", i, ee.ErrorCode, tt.wcode) - t.Logf("cause: %#v", ee.Cause) - } - if !reflect.DeepEqual(got, etcdserverpb.Request{}) { - t.Errorf("#%d: unexpected non-empty Request: %#v", i, got) - } - } -} - -func TestBadParseRequest(t *testing.T) { - tests := []struct { - in *http.Request - wcode int - }{ - { - // parseForm failure - &http.Request{ - Body: nil, - Method: "PUT", - }, - v2error.EcodeInvalidForm, - }, - { - // bad key prefix - &http.Request{ - URL: testutil.MustNewURL(t, "/badprefix/"), - }, - v2error.EcodeInvalidForm, - }, - // bad values for prevIndex, waitIndex, ttl - { - mustNewForm(t, "foo", url.Values{"prevIndex": []string{"garbage"}}), - v2error.EcodeIndexNaN, - }, - { - mustNewForm(t, "foo", url.Values{"prevIndex": []string{"1.5"}}), - v2error.EcodeIndexNaN, - }, - { - mustNewForm(t, "foo", url.Values{"prevIndex": []string{"-1"}}), - v2error.EcodeIndexNaN, - }, - { - mustNewForm(t, "foo", url.Values{"waitIndex": []string{"garbage"}}), - v2error.EcodeIndexNaN, - }, - { - mustNewForm(t, "foo", url.Values{"waitIndex": []string{"??"}}), - v2error.EcodeIndexNaN, - }, - { - mustNewForm(t, "foo", url.Values{"ttl": []string{"-1"}}), - v2error.EcodeTTLNaN, - }, - // bad values for recursive, sorted, wait, prevExist, dir, stream - { - mustNewForm(t, "foo", url.Values{"recursive": []string{"hahaha"}}), - v2error.EcodeInvalidField, - }, - { - mustNewForm(t, "foo", url.Values{"recursive": []string{"1234"}}), - v2error.EcodeInvalidField, - }, - { - mustNewForm(t, "foo", url.Values{"recursive": []string{"?"}}), - v2error.EcodeInvalidField, - }, - { - mustNewForm(t, "foo", url.Values{"sorted": []string{"?"}}), - v2error.EcodeInvalidField, - }, - { - mustNewForm(t, "foo", url.Values{"sorted": []string{"x"}}), - v2error.EcodeInvalidField, - }, - { - mustNewForm(t, "foo", url.Values{"wait": []string{"?!"}}), - v2error.EcodeInvalidField, - }, - { - mustNewForm(t, "foo", url.Values{"wait": []string{"yes"}}), - v2error.EcodeInvalidField, - }, - { - mustNewForm(t, "foo", url.Values{"prevExist": []string{"yes"}}), - v2error.EcodeInvalidField, - }, - { - mustNewForm(t, "foo", url.Values{"prevExist": []string{"#2"}}), - v2error.EcodeInvalidField, - }, - { - mustNewForm(t, "foo", url.Values{"dir": []string{"no"}}), - v2error.EcodeInvalidField, - }, - { - mustNewForm(t, "foo", url.Values{"dir": []string{"file"}}), - v2error.EcodeInvalidField, - }, - { - mustNewForm(t, "foo", url.Values{"quorum": []string{"no"}}), - v2error.EcodeInvalidField, - }, - { - mustNewForm(t, "foo", url.Values{"quorum": []string{"file"}}), - v2error.EcodeInvalidField, - }, - { - mustNewForm(t, "foo", url.Values{"stream": []string{"zzz"}}), - v2error.EcodeInvalidField, - }, - { - mustNewForm(t, "foo", url.Values{"stream": []string{"something"}}), - v2error.EcodeInvalidField, - }, - // prevValue cannot be empty - { - mustNewForm(t, "foo", url.Values{"prevValue": []string{""}}), - v2error.EcodePrevValueRequired, - }, - // wait is only valid with GET requests - { - mustNewMethodRequest(t, "HEAD", "foo?wait=true"), - v2error.EcodeInvalidField, - }, - // query values are considered - { - mustNewRequest(t, "foo?prevExist=wrong"), - v2error.EcodeInvalidField, - }, - { - mustNewRequest(t, "foo?ttl=wrong"), - v2error.EcodeTTLNaN, - }, - // but body takes precedence if both are specified - { - mustNewForm( - t, - "foo?ttl=12", - url.Values{"ttl": []string{"garbage"}}, - ), - v2error.EcodeTTLNaN, - }, - { - mustNewForm( - t, - "foo?prevExist=false", - url.Values{"prevExist": []string{"yes"}}, - ), - v2error.EcodeInvalidField, - }, - } - for i, tt := range tests { - got, _, err := parseKeyRequest(tt.in, clockwork.NewFakeClock()) - if err == nil { - t.Errorf("#%d: unexpected nil error!", i) - continue - } - ee, ok := err.(*v2error.Error) - if !ok { - t.Errorf("#%d: err is not etcd.Error!", i) - continue - } - if ee.ErrorCode != tt.wcode { - t.Errorf("#%d: code=%d, want %v", i, ee.ErrorCode, tt.wcode) - t.Logf("cause: %#v", ee.Cause) - } - if !reflect.DeepEqual(got, etcdserverpb.Request{}) { - t.Errorf("#%d: unexpected non-empty Request: %#v", i, got) - } - } -} - -func TestGoodParseRequest(t *testing.T) { - fc := clockwork.NewFakeClock() - fc.Advance(1111) - tests := []struct { - in *http.Request - w etcdserverpb.Request - noValue bool - }{ - { - // good prefix, all other values default - mustNewRequest(t, "foo"), - etcdserverpb.Request{ - Method: "GET", - Path: path.Join(etcdserver.StoreKeysPrefix, "/foo"), - }, - false, - }, - { - // value specified - mustNewForm( - t, - "foo", - url.Values{"value": []string{"some_value"}}, - ), - etcdserverpb.Request{ - Method: "PUT", - Val: "some_value", - Path: path.Join(etcdserver.StoreKeysPrefix, "/foo"), - }, - false, - }, - { - // prevIndex specified - mustNewForm( - t, - "foo", - url.Values{"prevIndex": []string{"98765"}}, - ), - etcdserverpb.Request{ - Method: "PUT", - PrevIndex: 98765, - Path: path.Join(etcdserver.StoreKeysPrefix, "/foo"), - }, - false, - }, - { - // recursive specified - mustNewForm( - t, - "foo", - url.Values{"recursive": []string{"true"}}, - ), - etcdserverpb.Request{ - Method: "PUT", - Recursive: true, - Path: path.Join(etcdserver.StoreKeysPrefix, "/foo"), - }, - false, - }, - { - // sorted specified - mustNewForm( - t, - "foo", - url.Values{"sorted": []string{"true"}}, - ), - etcdserverpb.Request{ - Method: "PUT", - Sorted: true, - Path: path.Join(etcdserver.StoreKeysPrefix, "/foo"), - }, - false, - }, - { - // quorum specified - mustNewForm( - t, - "foo", - url.Values{"quorum": []string{"true"}}, - ), - etcdserverpb.Request{ - Method: "PUT", - Quorum: true, - Path: path.Join(etcdserver.StoreKeysPrefix, "/foo"), - }, - false, - }, - { - // wait specified - mustNewRequest(t, "foo?wait=true"), - etcdserverpb.Request{ - Method: "GET", - Wait: true, - Path: path.Join(etcdserver.StoreKeysPrefix, "/foo"), - }, - false, - }, - { - // empty TTL specified - mustNewRequest(t, "foo?ttl="), - etcdserverpb.Request{ - Method: "GET", - Path: path.Join(etcdserver.StoreKeysPrefix, "/foo"), - Expiration: 0, - }, - false, - }, - { - // non-empty TTL specified - mustNewRequest(t, "foo?ttl=5678"), - etcdserverpb.Request{ - Method: "GET", - Path: path.Join(etcdserver.StoreKeysPrefix, "/foo"), - Expiration: fc.Now().Add(5678 * time.Second).UnixNano(), - }, - false, - }, - { - // zero TTL specified - mustNewRequest(t, "foo?ttl=0"), - etcdserverpb.Request{ - Method: "GET", - Path: path.Join(etcdserver.StoreKeysPrefix, "/foo"), - Expiration: fc.Now().UnixNano(), - }, - false, - }, - { - // dir specified - mustNewRequest(t, "foo?dir=true"), - etcdserverpb.Request{ - Method: "GET", - Dir: true, - Path: path.Join(etcdserver.StoreKeysPrefix, "/foo"), - }, - false, - }, - { - // dir specified negatively - mustNewRequest(t, "foo?dir=false"), - etcdserverpb.Request{ - Method: "GET", - Dir: false, - Path: path.Join(etcdserver.StoreKeysPrefix, "/foo"), - }, - false, - }, - { - // prevExist should be non-null if specified - mustNewForm( - t, - "foo", - url.Values{"prevExist": []string{"true"}}, - ), - etcdserverpb.Request{ - Method: "PUT", - PrevExist: boolp(true), - Path: path.Join(etcdserver.StoreKeysPrefix, "/foo"), - }, - false, - }, - { - // prevExist should be non-null if specified - mustNewForm( - t, - "foo", - url.Values{"prevExist": []string{"false"}}, - ), - etcdserverpb.Request{ - Method: "PUT", - PrevExist: boolp(false), - Path: path.Join(etcdserver.StoreKeysPrefix, "/foo"), - }, - false, - }, - // mix various fields - { - mustNewForm( - t, - "foo", - url.Values{ - "value": []string{"some value"}, - "prevExist": []string{"true"}, - "prevValue": []string{"previous value"}, - }, - ), - etcdserverpb.Request{ - Method: "PUT", - PrevExist: boolp(true), - PrevValue: "previous value", - Val: "some value", - Path: path.Join(etcdserver.StoreKeysPrefix, "/foo"), - }, - false, - }, - // query parameters should be used if given - { - mustNewForm( - t, - "foo?prevValue=woof", - url.Values{}, - ), - etcdserverpb.Request{ - Method: "PUT", - PrevValue: "woof", - Path: path.Join(etcdserver.StoreKeysPrefix, "/foo"), - }, - false, - }, - // but form values should take precedence over query parameters - { - mustNewForm( - t, - "foo?prevValue=woof", - url.Values{ - "prevValue": []string{"miaow"}, - }, - ), - etcdserverpb.Request{ - Method: "PUT", - PrevValue: "miaow", - Path: path.Join(etcdserver.StoreKeysPrefix, "/foo"), - }, - false, - }, - { - // noValueOnSuccess specified - mustNewForm( - t, - "foo", - url.Values{"noValueOnSuccess": []string{"true"}}, - ), - etcdserverpb.Request{ - Method: "PUT", - Path: path.Join(etcdserver.StoreKeysPrefix, "/foo"), - }, - true, - }, - } - - for i, tt := range tests { - got, noValueOnSuccess, err := parseKeyRequest(tt.in, fc) - if err != nil { - t.Errorf("#%d: err = %v, want %v", i, err, nil) - } - - if noValueOnSuccess != tt.noValue { - t.Errorf("#%d: noValue=%t, want %t", i, noValueOnSuccess, tt.noValue) - } - - if !reflect.DeepEqual(got, tt.w) { - t.Errorf("#%d: request=%#v, want %#v", i, got, tt.w) - } - } -} - -func TestServeMembers(t *testing.T) { - memb1 := membership.Member{ID: 12, Attributes: membership.Attributes{ClientURLs: []string{"http://localhost:8080"}}} - memb2 := membership.Member{ID: 13, Attributes: membership.Attributes{ClientURLs: []string{"http://localhost:8081"}}} - cluster := &fakeCluster{ - id: 1, - members: map[uint64]*membership.Member{1: &memb1, 2: &memb2}, - } - h := &membersHandler{ - lg: zap.NewExample(), - server: &serverRecorder{}, - clock: clockwork.NewFakeClock(), - cluster: cluster, - } - - wmc := string(`{"members":[{"id":"c","name":"","peerURLs":[],"clientURLs":["http://localhost:8080"]},{"id":"d","name":"","peerURLs":[],"clientURLs":["http://localhost:8081"]}]}`) - - tests := []struct { - path string - wcode int - wct string - wbody string - }{ - {membersPrefix, http.StatusOK, "application/json", wmc + "\n"}, - {membersPrefix + "/", http.StatusOK, "application/json", wmc + "\n"}, - {path.Join(membersPrefix, "100"), http.StatusNotFound, "application/json", `{"message":"Not found"}`}, - {path.Join(membersPrefix, "foobar"), http.StatusNotFound, "application/json", `{"message":"Not found"}`}, - } - - for i, tt := range tests { - req, err := http.NewRequest("GET", testutil.MustNewURL(t, tt.path).String(), nil) - if err != nil { - t.Fatal(err) - } - rw := httptest.NewRecorder() - h.ServeHTTP(rw, req) - - if rw.Code != tt.wcode { - t.Errorf("#%d: code=%d, want %d", i, rw.Code, tt.wcode) - } - if gct := rw.Header().Get("Content-Type"); gct != tt.wct { - t.Errorf("#%d: content-type = %s, want %s", i, gct, tt.wct) - } - gcid := rw.Header().Get("X-Etcd-Cluster-ID") - wcid := cluster.ID().String() - if gcid != wcid { - t.Errorf("#%d: cid = %s, want %s", i, gcid, wcid) - } - if rw.Body.String() != tt.wbody { - t.Errorf("#%d: body = %q, want %q", i, rw.Body.String(), tt.wbody) - } - } -} - -// TODO: consolidate **ALL** fake server implementations and add no leader test case. -func TestServeLeader(t *testing.T) { - memb1 := membership.Member{ID: 1, Attributes: membership.Attributes{ClientURLs: []string{"http://localhost:8080"}}} - memb2 := membership.Member{ID: 2, Attributes: membership.Attributes{ClientURLs: []string{"http://localhost:8081"}}} - cluster := &fakeCluster{ - id: 1, - members: map[uint64]*membership.Member{1: &memb1, 2: &memb2}, - } - h := &membersHandler{ - lg: zap.NewExample(), - server: &serverRecorder{}, - clock: clockwork.NewFakeClock(), - cluster: cluster, - } - - wmc := string(`{"id":"1","name":"","peerURLs":[],"clientURLs":["http://localhost:8080"]}`) - - tests := []struct { - path string - wcode int - wct string - wbody string - }{ - {membersPrefix + "leader", http.StatusOK, "application/json", wmc + "\n"}, - // TODO: add no leader case - } - - for i, tt := range tests { - req, err := http.NewRequest("GET", testutil.MustNewURL(t, tt.path).String(), nil) - if err != nil { - t.Fatal(err) - } - rw := httptest.NewRecorder() - h.ServeHTTP(rw, req) - - if rw.Code != tt.wcode { - t.Errorf("#%d: code=%d, want %d", i, rw.Code, tt.wcode) - } - if gct := rw.Header().Get("Content-Type"); gct != tt.wct { - t.Errorf("#%d: content-type = %s, want %s", i, gct, tt.wct) - } - gcid := rw.Header().Get("X-Etcd-Cluster-ID") - wcid := cluster.ID().String() - if gcid != wcid { - t.Errorf("#%d: cid = %s, want %s", i, gcid, wcid) - } - if rw.Body.String() != tt.wbody { - t.Errorf("#%d: body = %q, want %q", i, rw.Body.String(), tt.wbody) - } - } -} - -func TestServeMembersCreate(t *testing.T) { - u := testutil.MustNewURL(t, membersPrefix) - b := []byte(`{"peerURLs":["http://127.0.0.1:1"]}`) - req, err := http.NewRequest("POST", u.String(), bytes.NewReader(b)) - if err != nil { - t.Fatal(err) - } - req.Header.Set("Content-Type", "application/json") - s := &serverRecorder{} - h := &membersHandler{ - lg: zap.NewExample(), - server: s, - clock: clockwork.NewFakeClock(), - cluster: &fakeCluster{id: 1}, - } - rw := httptest.NewRecorder() - - h.ServeHTTP(rw, req) - - wcode := http.StatusCreated - if rw.Code != wcode { - t.Errorf("code=%d, want %d", rw.Code, wcode) - } - - wct := "application/json" - if gct := rw.Header().Get("Content-Type"); gct != wct { - t.Errorf("content-type = %s, want %s", gct, wct) - } - gcid := rw.Header().Get("X-Etcd-Cluster-ID") - wcid := h.cluster.ID().String() - if gcid != wcid { - t.Errorf("cid = %s, want %s", gcid, wcid) - } - - wb := `{"id":"c29b431f04be0bc7","name":"","peerURLs":["http://127.0.0.1:1"],"clientURLs":[]}` + "\n" - g := rw.Body.String() - if g != wb { - t.Errorf("got body=%q, want %q", g, wb) - } - - wm := membership.Member{ - ID: 14022875665250782151, - RaftAttributes: membership.RaftAttributes{ - PeerURLs: []string{"http://127.0.0.1:1"}, - }, - } - - wactions := []action{{name: "AddMember", params: []interface{}{wm}}} - if !reflect.DeepEqual(s.actions, wactions) { - t.Errorf("actions = %+v, want %+v", s.actions, wactions) - } -} - -func TestServeMembersDelete(t *testing.T) { - req := &http.Request{ - Method: "DELETE", - URL: testutil.MustNewURL(t, path.Join(membersPrefix, "BEEF")), - } - s := &serverRecorder{} - h := &membersHandler{ - lg: zap.NewExample(), - server: s, - cluster: &fakeCluster{id: 1}, - } - rw := httptest.NewRecorder() - - h.ServeHTTP(rw, req) - - wcode := http.StatusNoContent - if rw.Code != wcode { - t.Errorf("code=%d, want %d", rw.Code, wcode) - } - gcid := rw.Header().Get("X-Etcd-Cluster-ID") - wcid := h.cluster.ID().String() - if gcid != wcid { - t.Errorf("cid = %s, want %s", gcid, wcid) - } - g := rw.Body.String() - if g != "" { - t.Errorf("got body=%q, want %q", g, "") - } - wactions := []action{{name: "RemoveMember", params: []interface{}{uint64(0xBEEF)}}} - if !reflect.DeepEqual(s.actions, wactions) { - t.Errorf("actions = %+v, want %+v", s.actions, wactions) - } -} - -func TestServeMembersUpdate(t *testing.T) { - u := testutil.MustNewURL(t, path.Join(membersPrefix, "1")) - b := []byte(`{"peerURLs":["http://127.0.0.1:1"]}`) - req, err := http.NewRequest("PUT", u.String(), bytes.NewReader(b)) - if err != nil { - t.Fatal(err) - } - req.Header.Set("Content-Type", "application/json") - s := &serverRecorder{} - h := &membersHandler{ - lg: zap.NewExample(), - server: s, - clock: clockwork.NewFakeClock(), - cluster: &fakeCluster{id: 1}, - } - rw := httptest.NewRecorder() - - h.ServeHTTP(rw, req) - - wcode := http.StatusNoContent - if rw.Code != wcode { - t.Errorf("code=%d, want %d", rw.Code, wcode) - } - - gcid := rw.Header().Get("X-Etcd-Cluster-ID") - wcid := h.cluster.ID().String() - if gcid != wcid { - t.Errorf("cid = %s, want %s", gcid, wcid) - } - - wm := membership.Member{ - ID: 1, - RaftAttributes: membership.RaftAttributes{ - PeerURLs: []string{"http://127.0.0.1:1"}, - }, - } - - wactions := []action{{name: "UpdateMember", params: []interface{}{wm}}} - if !reflect.DeepEqual(s.actions, wactions) { - t.Errorf("actions = %+v, want %+v", s.actions, wactions) - } -} - -func TestServeMembersFail(t *testing.T) { - tests := []struct { - req *http.Request - server etcdserver.ServerV2 - - wcode int - }{ - { - // bad method - &http.Request{ - Method: "CONNECT", - }, - &resServer{}, - - http.StatusMethodNotAllowed, - }, - { - // bad method - &http.Request{ - Method: "TRACE", - }, - &resServer{}, - - http.StatusMethodNotAllowed, - }, - { - // parse body error - &http.Request{ - URL: testutil.MustNewURL(t, membersPrefix), - Method: "POST", - Body: io.NopCloser(strings.NewReader("bad json")), - Header: map[string][]string{"Content-Type": {"application/json"}}, - }, - &resServer{}, - - http.StatusBadRequest, - }, - { - // bad content type - &http.Request{ - URL: testutil.MustNewURL(t, membersPrefix), - Method: "POST", - Body: io.NopCloser(strings.NewReader(`{"PeerURLs": ["http://127.0.0.1:1"]}`)), - Header: map[string][]string{"Content-Type": {"application/bad"}}, - }, - &errServer{}, - - http.StatusUnsupportedMediaType, - }, - { - // bad url - &http.Request{ - URL: testutil.MustNewURL(t, membersPrefix), - Method: "POST", - Body: io.NopCloser(strings.NewReader(`{"PeerURLs": ["http://a"]}`)), - Header: map[string][]string{"Content-Type": {"application/json"}}, - }, - &errServer{}, - - http.StatusBadRequest, - }, - { - // etcdserver.AddMember error - &http.Request{ - URL: testutil.MustNewURL(t, membersPrefix), - Method: "POST", - Body: io.NopCloser(strings.NewReader(`{"PeerURLs": ["http://127.0.0.1:1"]}`)), - Header: map[string][]string{"Content-Type": {"application/json"}}, - }, - &errServer{ - err: errors.New("Error while adding a member"), - }, - - http.StatusInternalServerError, - }, - { - // etcdserver.AddMember error - &http.Request{ - URL: testutil.MustNewURL(t, membersPrefix), - Method: "POST", - Body: io.NopCloser(strings.NewReader(`{"PeerURLs": ["http://127.0.0.1:1"]}`)), - Header: map[string][]string{"Content-Type": {"application/json"}}, - }, - &errServer{ - err: membership.ErrIDExists, - }, - - http.StatusConflict, - }, - { - // etcdserver.AddMember error - &http.Request{ - URL: testutil.MustNewURL(t, membersPrefix), - Method: "POST", - Body: io.NopCloser(strings.NewReader(`{"PeerURLs": ["http://127.0.0.1:1"]}`)), - Header: map[string][]string{"Content-Type": {"application/json"}}, - }, - &errServer{ - err: membership.ErrPeerURLexists, - }, - - http.StatusConflict, - }, - { - // etcdserver.RemoveMember error with arbitrary server error - &http.Request{ - URL: testutil.MustNewURL(t, path.Join(membersPrefix, "1")), - Method: "DELETE", - }, - &errServer{ - err: errors.New("Error while removing member"), - }, - - http.StatusInternalServerError, - }, - { - // etcdserver.RemoveMember error with previously removed ID - &http.Request{ - URL: testutil.MustNewURL(t, path.Join(membersPrefix, "0")), - Method: "DELETE", - }, - &errServer{ - err: membership.ErrIDRemoved, - }, - - http.StatusGone, - }, - { - // etcdserver.RemoveMember error with nonexistent ID - &http.Request{ - URL: testutil.MustNewURL(t, path.Join(membersPrefix, "0")), - Method: "DELETE", - }, - &errServer{ - err: membership.ErrIDNotFound, - }, - - http.StatusNotFound, - }, - { - // etcdserver.RemoveMember error with badly formed ID - &http.Request{ - URL: testutil.MustNewURL(t, path.Join(membersPrefix, "bad_id")), - Method: "DELETE", - }, - nil, - - http.StatusNotFound, - }, - { - // etcdserver.RemoveMember with no ID - &http.Request{ - URL: testutil.MustNewURL(t, membersPrefix), - Method: "DELETE", - }, - nil, - - http.StatusMethodNotAllowed, - }, - { - // parse body error - &http.Request{ - URL: testutil.MustNewURL(t, path.Join(membersPrefix, "0")), - Method: "PUT", - Body: io.NopCloser(strings.NewReader("bad json")), - Header: map[string][]string{"Content-Type": {"application/json"}}, - }, - &resServer{}, - - http.StatusBadRequest, - }, - { - // bad content type - &http.Request{ - URL: testutil.MustNewURL(t, path.Join(membersPrefix, "0")), - Method: "PUT", - Body: io.NopCloser(strings.NewReader(`{"PeerURLs": ["http://127.0.0.1:1"]}`)), - Header: map[string][]string{"Content-Type": {"application/bad"}}, - }, - &errServer{}, - - http.StatusUnsupportedMediaType, - }, - { - // bad url - &http.Request{ - URL: testutil.MustNewURL(t, path.Join(membersPrefix, "0")), - Method: "PUT", - Body: io.NopCloser(strings.NewReader(`{"PeerURLs": ["http://a"]}`)), - Header: map[string][]string{"Content-Type": {"application/json"}}, - }, - &errServer{}, - - http.StatusBadRequest, - }, - { - // etcdserver.UpdateMember error - &http.Request{ - URL: testutil.MustNewURL(t, path.Join(membersPrefix, "0")), - Method: "PUT", - Body: io.NopCloser(strings.NewReader(`{"PeerURLs": ["http://127.0.0.1:1"]}`)), - Header: map[string][]string{"Content-Type": {"application/json"}}, - }, - &errServer{ - err: errors.New("blah"), - }, - - http.StatusInternalServerError, - }, - { - // etcdserver.UpdateMember error - &http.Request{ - URL: testutil.MustNewURL(t, path.Join(membersPrefix, "0")), - Method: "PUT", - Body: io.NopCloser(strings.NewReader(`{"PeerURLs": ["http://127.0.0.1:1"]}`)), - Header: map[string][]string{"Content-Type": {"application/json"}}, - }, - &errServer{ - err: membership.ErrPeerURLexists, - }, - - http.StatusConflict, - }, - { - // etcdserver.UpdateMember error - &http.Request{ - URL: testutil.MustNewURL(t, path.Join(membersPrefix, "0")), - Method: "PUT", - Body: io.NopCloser(strings.NewReader(`{"PeerURLs": ["http://127.0.0.1:1"]}`)), - Header: map[string][]string{"Content-Type": {"application/json"}}, - }, - &errServer{ - err: membership.ErrIDNotFound, - }, - - http.StatusNotFound, - }, - { - // etcdserver.UpdateMember error with badly formed ID - &http.Request{ - URL: testutil.MustNewURL(t, path.Join(membersPrefix, "bad_id")), - Method: "PUT", - }, - nil, - - http.StatusNotFound, - }, - { - // etcdserver.UpdateMember with no ID - &http.Request{ - URL: testutil.MustNewURL(t, membersPrefix), - Method: "PUT", - }, - nil, - - http.StatusMethodNotAllowed, - }, - } - for i, tt := range tests { - h := &membersHandler{ - lg: zap.NewExample(), - server: tt.server, - cluster: &fakeCluster{id: 1}, - clock: clockwork.NewFakeClock(), - } - rw := httptest.NewRecorder() - h.ServeHTTP(rw, tt.req) - if rw.Code != tt.wcode { - t.Errorf("#%d: code=%d, want %d", i, rw.Code, tt.wcode) - } - if rw.Code != http.StatusMethodNotAllowed { - gcid := rw.Header().Get("X-Etcd-Cluster-ID") - wcid := h.cluster.ID().String() - if gcid != wcid { - t.Errorf("#%d: cid = %s, want %s", i, gcid, wcid) - } - } - } -} - -func TestWriteEvent(t *testing.T) { - // nil event should not panic - rec := httptest.NewRecorder() - writeKeyEvent(rec, etcdserver.Response{}, false) - h := rec.Header() - if len(h) > 0 { - t.Fatalf("unexpected non-empty headers: %#v", h) - } - b := rec.Body.String() - if len(b) > 0 { - t.Fatalf("unexpected non-empty body: %q", b) - } - - tests := []struct { - ev *v2store.Event - noValue bool - idx string - // TODO(jonboulle): check body as well as just status code - code int - err error - }{ - // standard case, standard 200 response - { - &v2store.Event{ - Action: v2store.Get, - Node: &v2store.NodeExtern{}, - PrevNode: &v2store.NodeExtern{}, - }, - false, - "0", - http.StatusOK, - nil, - }, - // check new nodes return StatusCreated - { - &v2store.Event{ - Action: v2store.Create, - Node: &v2store.NodeExtern{}, - PrevNode: &v2store.NodeExtern{}, - }, - false, - "0", - http.StatusCreated, - nil, - }, - } - - for i, tt := range tests { - rw := httptest.NewRecorder() - resp := etcdserver.Response{Event: tt.ev, Term: 5, Index: 100} - writeKeyEvent(rw, resp, tt.noValue) - if gct := rw.Header().Get("Content-Type"); gct != "application/json" { - t.Errorf("case %d: bad Content-Type: got %q, want application/json", i, gct) - } - if gri := rw.Header().Get("X-Raft-Index"); gri != "100" { - t.Errorf("case %d: bad X-Raft-Index header: got %s, want %s", i, gri, "100") - } - if grt := rw.Header().Get("X-Raft-Term"); grt != "5" { - t.Errorf("case %d: bad X-Raft-Term header: got %s, want %s", i, grt, "5") - } - if gei := rw.Header().Get("X-Etcd-Index"); gei != tt.idx { - t.Errorf("case %d: bad X-Etcd-Index header: got %s, want %s", i, gei, tt.idx) - } - if rw.Code != tt.code { - t.Errorf("case %d: bad response code: got %d, want %v", i, rw.Code, tt.code) - } - - } -} - -func TestV2DMachinesEndpoint(t *testing.T) { - tests := []struct { - method string - wcode int - }{ - {"GET", http.StatusOK}, - {"HEAD", http.StatusOK}, - {"POST", http.StatusMethodNotAllowed}, - } - - m := &machinesHandler{cluster: &fakeCluster{}} - s := httptest.NewServer(m) - defer s.Close() - - for _, tt := range tests { - req, err := http.NewRequest(tt.method, s.URL+machinesPrefix, nil) - if err != nil { - t.Fatal(err) - } - resp, err := http.DefaultClient.Do(req) - if err != nil { - t.Fatal(err) - } - - if resp.StatusCode != tt.wcode { - t.Errorf("StatusCode = %d, expected %d", resp.StatusCode, tt.wcode) - } - } -} - -func TestServeMachines(t *testing.T) { - cluster := &fakeCluster{ - clientURLs: []string{"http://localhost:8080", "http://localhost:8081", "http://localhost:8082"}, - } - writer := httptest.NewRecorder() - req, err := http.NewRequest("GET", "", nil) - if err != nil { - t.Fatal(err) - } - h := &machinesHandler{cluster: cluster} - h.ServeHTTP(writer, req) - w := "http://localhost:8080, http://localhost:8081, http://localhost:8082" - if g := writer.Body.String(); g != w { - t.Errorf("body = %s, want %s", g, w) - } - if writer.Code != http.StatusOK { - t.Errorf("code = %d, want %d", writer.Code, http.StatusOK) - } -} - -func TestGetID(t *testing.T) { - tests := []struct { - path string - - wok bool - wid types.ID - wcode int - }{ - { - "123", - true, 0x123, http.StatusOK, - }, - { - "bad_id", - false, 0, http.StatusNotFound, - }, - { - "", - false, 0, http.StatusMethodNotAllowed, - }, - } - - for i, tt := range tests { - w := httptest.NewRecorder() - id, ok := getID(zap.NewExample(), tt.path, w) - if id != tt.wid { - t.Errorf("#%d: id = %d, want %d", i, id, tt.wid) - } - if ok != tt.wok { - t.Errorf("#%d: ok = %t, want %t", i, ok, tt.wok) - } - if w.Code != tt.wcode { - t.Errorf("#%d code = %d, want %d", i, w.Code, tt.wcode) - } - } -} - -type dummyStats struct { - data []byte -} - -func (ds *dummyStats) SelfStats() []byte { return ds.data } -func (ds *dummyStats) LeaderStats() []byte { return ds.data } -func (ds *dummyStats) StoreStats() []byte { return ds.data } -func (ds *dummyStats) UpdateRecvApp(_ types.ID, _ int64) {} - -func TestServeSelfStats(t *testing.T) { - wb := []byte("some statistics") - w := string(wb) - sh := &statsHandler{ - lg: zap.NewExample(), - stats: &dummyStats{data: wb}, - } - rw := httptest.NewRecorder() - sh.serveSelf(rw, &http.Request{Method: "GET"}) - if rw.Code != http.StatusOK { - t.Errorf("code = %d, want %d", rw.Code, http.StatusOK) - } - wct := "application/json" - if gct := rw.Header().Get("Content-Type"); gct != wct { - t.Errorf("Content-Type = %q, want %q", gct, wct) - } - if g := rw.Body.String(); g != w { - t.Errorf("body = %s, want %s", g, w) - } -} - -func TestSelfServeStatsBad(t *testing.T) { - for _, m := range []string{"PUT", "POST", "DELETE"} { - sh := &statsHandler{lg: zap.NewExample()} - rw := httptest.NewRecorder() - sh.serveSelf( - rw, - &http.Request{ - Method: m, - }, - ) - if rw.Code != http.StatusMethodNotAllowed { - t.Errorf("method %s: code=%d, want %d", m, rw.Code, http.StatusMethodNotAllowed) - } - } -} - -func TestLeaderServeStatsBad(t *testing.T) { - for _, m := range []string{"PUT", "POST", "DELETE"} { - sh := &statsHandler{lg: zap.NewExample()} - rw := httptest.NewRecorder() - sh.serveLeader( - rw, - &http.Request{ - Method: m, - }, - ) - if rw.Code != http.StatusMethodNotAllowed { - t.Errorf("method %s: code=%d, want %d", m, rw.Code, http.StatusMethodNotAllowed) - } - } -} - -func TestServeLeaderStats(t *testing.T) { - wb := []byte("some statistics") - w := string(wb) - sh := &statsHandler{ - lg: zap.NewExample(), - stats: &dummyStats{data: wb}, - } - rw := httptest.NewRecorder() - sh.serveLeader(rw, &http.Request{Method: "GET"}) - if rw.Code != http.StatusOK { - t.Errorf("code = %d, want %d", rw.Code, http.StatusOK) - } - wct := "application/json" - if gct := rw.Header().Get("Content-Type"); gct != wct { - t.Errorf("Content-Type = %q, want %q", gct, wct) - } - if g := rw.Body.String(); g != w { - t.Errorf("body = %s, want %s", g, w) - } -} - -func TestServeStoreStats(t *testing.T) { - wb := []byte("some statistics") - w := string(wb) - sh := &statsHandler{ - lg: zap.NewExample(), - stats: &dummyStats{data: wb}, - } - rw := httptest.NewRecorder() - sh.serveStore(rw, &http.Request{Method: "GET"}) - if rw.Code != http.StatusOK { - t.Errorf("code = %d, want %d", rw.Code, http.StatusOK) - } - wct := "application/json" - if gct := rw.Header().Get("Content-Type"); gct != wct { - t.Errorf("Content-Type = %q, want %q", gct, wct) - } - if g := rw.Body.String(); g != w { - t.Errorf("body = %s, want %s", g, w) - } - -} - -func TestBadServeKeys(t *testing.T) { - testBadCases := []struct { - req *http.Request - server etcdserver.ServerV2 - - wcode int - wbody string - }{ - { - // bad method - &http.Request{ - Method: "CONNECT", - }, - &resServer{}, - - http.StatusMethodNotAllowed, - "Method Not Allowed", - }, - { - // bad method - &http.Request{ - Method: "TRACE", - }, - &resServer{}, - - http.StatusMethodNotAllowed, - "Method Not Allowed", - }, - { - // parseRequest error - &http.Request{ - Body: nil, - Method: "PUT", - }, - &resServer{}, - - http.StatusBadRequest, - `{"errorCode":210,"message":"Invalid POST form","cause":"missing form body","index":0}`, - }, - { - // etcdserver.Server error - mustNewRequest(t, "foo"), - &errServer{ - err: errors.New("Internal Server Error"), - }, - - http.StatusInternalServerError, - `{"errorCode":300,"message":"Raft Internal Error","cause":"Internal Server Error","index":0}`, - }, - { - // etcdserver.Server etcd error - mustNewRequest(t, "foo"), - &errServer{ - err: v2error.NewError(v2error.EcodeKeyNotFound, "/1/pant", 0), - }, - - http.StatusNotFound, - `{"errorCode":100,"message":"Key not found","cause":"/pant","index":0}`, - }, - { - // non-event/watcher response from etcdserver.Server - mustNewRequest(t, "foo"), - &resServer{ - res: etcdserver.Response{}, - }, - - http.StatusInternalServerError, - `{"errorCode":300,"message":"Raft Internal Error","cause":"received response with no Event/Watcher","index":0}`, - }, - } - for i, tt := range testBadCases { - h := &keysHandler{ - lg: zap.NewExample(), - timeout: 0, // context times out immediately - server: tt.server, - cluster: &fakeCluster{id: 1}, - } - rw := httptest.NewRecorder() - h.ServeHTTP(rw, tt.req) - if rw.Code != tt.wcode { - t.Errorf("#%d: got code=%d, want %d", i, rw.Code, tt.wcode) - } - if rw.Code != http.StatusMethodNotAllowed { - gcid := rw.Header().Get("X-Etcd-Cluster-ID") - wcid := h.cluster.ID().String() - if gcid != wcid { - t.Errorf("#%d: cid = %s, want %s", i, gcid, wcid) - } - } - if g := strings.TrimSuffix(rw.Body.String(), "\n"); g != tt.wbody { - t.Errorf("#%d: body = %s, want %s", i, g, tt.wbody) - } - } -} - -func TestServeKeysGood(t *testing.T) { - tests := []struct { - req *http.Request - wcode int - }{ - { - mustNewMethodRequest(t, "HEAD", "foo"), - http.StatusOK, - }, - { - mustNewMethodRequest(t, "GET", "foo"), - http.StatusOK, - }, - { - mustNewForm(t, "foo", url.Values{"value": []string{"bar"}}), - http.StatusOK, - }, - { - mustNewMethodRequest(t, "DELETE", "foo"), - http.StatusOK, - }, - { - mustNewPostForm(t, "foo", url.Values{"value": []string{"bar"}}), - http.StatusOK, - }, - } - server := &resServer{ - res: etcdserver.Response{ - Event: &v2store.Event{ - Action: v2store.Get, - Node: &v2store.NodeExtern{}, - }, - }, - } - for i, tt := range tests { - h := &keysHandler{ - lg: zap.NewExample(), - timeout: time.Hour, - server: server, - cluster: &fakeCluster{id: 1}, - } - rw := httptest.NewRecorder() - h.ServeHTTP(rw, tt.req) - if rw.Code != tt.wcode { - t.Errorf("#%d: got code=%d, want %d", i, rw.Code, tt.wcode) - } - } -} - -func TestServeKeysEvent(t *testing.T) { - tests := []struct { - req *http.Request - rsp etcdserver.Response - wcode int - event *v2store.Event - }{ - { - mustNewRequest(t, "foo"), - etcdserver.Response{ - Event: &v2store.Event{ - Action: v2store.Get, - Node: &v2store.NodeExtern{}, - }, - }, - http.StatusOK, - &v2store.Event{ - Action: v2store.Get, - Node: &v2store.NodeExtern{}, - }, - }, - { - mustNewForm( - t, - "foo", - url.Values{"noValueOnSuccess": []string{"true"}}, - ), - etcdserver.Response{ - Event: &v2store.Event{ - Action: v2store.CompareAndSwap, - Node: &v2store.NodeExtern{}, - }, - }, - http.StatusOK, - &v2store.Event{ - Action: v2store.CompareAndSwap, - Node: nil, - }, - }, - } - - server := &resServer{} - h := &keysHandler{ - lg: zap.NewExample(), - timeout: time.Hour, - server: server, - cluster: &fakeCluster{id: 1}, - } - - for _, tt := range tests { - server.res = tt.rsp - rw := httptest.NewRecorder() - h.ServeHTTP(rw, tt.req) - - wbody := mustMarshalEvent( - t, - tt.event, - ) - - if rw.Code != tt.wcode { - t.Errorf("got code=%d, want %d", rw.Code, tt.wcode) - } - gcid := rw.Header().Get("X-Etcd-Cluster-ID") - wcid := h.cluster.ID().String() - if gcid != wcid { - t.Errorf("cid = %s, want %s", gcid, wcid) - } - g := rw.Body.String() - if g != wbody { - t.Errorf("got body=%#v, want %#v", g, wbody) - } - } -} - -func TestServeKeysWatch(t *testing.T) { - req := mustNewRequest(t, "/foo/bar") - ec := make(chan *v2store.Event) - dw := &dummyWatcher{ - echan: ec, - } - server := &resServer{ - res: etcdserver.Response{ - Watcher: dw, - }, - } - h := &keysHandler{ - lg: zap.NewExample(), - timeout: time.Hour, - server: server, - cluster: &fakeCluster{id: 1}, - } - go func() { - ec <- &v2store.Event{ - Action: v2store.Get, - Node: &v2store.NodeExtern{}, - } - }() - rw := httptest.NewRecorder() - - h.ServeHTTP(rw, req) - - wcode := http.StatusOK - wbody := mustMarshalEvent( - t, - &v2store.Event{ - Action: v2store.Get, - Node: &v2store.NodeExtern{}, - }, - ) - - if rw.Code != wcode { - t.Errorf("got code=%d, want %d", rw.Code, wcode) - } - gcid := rw.Header().Get("X-Etcd-Cluster-ID") - wcid := h.cluster.ID().String() - if gcid != wcid { - t.Errorf("cid = %s, want %s", gcid, wcid) - } - g := rw.Body.String() - if g != wbody { - t.Errorf("got body=%#v, want %#v", g, wbody) - } -} - -type recordingCloseNotifier struct { - *httptest.ResponseRecorder - cn chan bool -} - -func (rcn *recordingCloseNotifier) CloseNotify() <-chan bool { - return rcn.cn -} - -func TestHandleWatch(t *testing.T) { - defaultRwRr := func() (http.ResponseWriter, *httptest.ResponseRecorder) { - r := httptest.NewRecorder() - return r, r - } - noopEv := func(chan *v2store.Event) {} - - tests := []struct { - getCtx func() context.Context - getRwRr func() (http.ResponseWriter, *httptest.ResponseRecorder) - doToChan func(chan *v2store.Event) - - wbody string - }{ - { - // Normal case: one event - context.Background, - defaultRwRr, - func(ch chan *v2store.Event) { - ch <- &v2store.Event{ - Action: v2store.Get, - Node: &v2store.NodeExtern{}, - } - }, - - mustMarshalEvent( - t, - &v2store.Event{ - Action: v2store.Get, - Node: &v2store.NodeExtern{}, - }, - ), - }, - { - // Channel is closed, no event - context.Background, - defaultRwRr, - func(ch chan *v2store.Event) { - close(ch) - }, - - "", - }, - { - // Simulate a timed-out context - func() context.Context { - ctx, cancel := context.WithCancel(context.Background()) - cancel() - return ctx - }, - defaultRwRr, - noopEv, - - "", - }, - { - // Close-notifying request - context.Background, - func() (http.ResponseWriter, *httptest.ResponseRecorder) { - rw := &recordingCloseNotifier{ - ResponseRecorder: httptest.NewRecorder(), - cn: make(chan bool, 1), - } - rw.cn <- true - return rw, rw.ResponseRecorder - }, - noopEv, - - "", - }, - } - - for i, tt := range tests { - rw, rr := tt.getRwRr() - wa := &dummyWatcher{ - echan: make(chan *v2store.Event, 1), - sidx: 10, - } - tt.doToChan(wa.echan) - - resp := etcdserver.Response{Term: 5, Index: 100, Watcher: wa} - handleKeyWatch(tt.getCtx(), zap.NewExample(), rw, resp, false) - - wcode := http.StatusOK - wct := "application/json" - wei := "10" - wri := "100" - wrt := "5" - - if rr.Code != wcode { - t.Errorf("#%d: got code=%d, want %d", i, rr.Code, wcode) - } - h := rr.Header() - if ct := h.Get("Content-Type"); ct != wct { - t.Errorf("#%d: Content-Type=%q, want %q", i, ct, wct) - } - if ei := h.Get("X-Etcd-Index"); ei != wei { - t.Errorf("#%d: X-Etcd-Index=%q, want %q", i, ei, wei) - } - if ri := h.Get("X-Raft-Index"); ri != wri { - t.Errorf("#%d: X-Raft-Index=%q, want %q", i, ri, wri) - } - if rt := h.Get("X-Raft-Term"); rt != wrt { - t.Errorf("#%d: X-Raft-Term=%q, want %q", i, rt, wrt) - } - g := rr.Body.String() - if g != tt.wbody { - t.Errorf("#%d: got body=%#v, want %#v", i, g, tt.wbody) - } - } -} - -func TestHandleWatchStreaming(t *testing.T) { - rw := &flushingRecorder{ - httptest.NewRecorder(), - make(chan struct{}, 1), - } - wa := &dummyWatcher{ - echan: make(chan *v2store.Event), - } - - // Launch the streaming handler in the background with a cancellable context - ctx, cancel := context.WithCancel(context.Background()) - done := make(chan struct{}) - go func() { - resp := etcdserver.Response{Watcher: wa} - handleKeyWatch(ctx, zap.NewExample(), rw, resp, true) - close(done) - }() - - // Expect one Flush for the headers etc. - select { - case <-rw.ch: - case <-time.After(time.Second): - t.Fatalf("timed out waiting for flush") - } - - // Expect headers but no body - wcode := http.StatusOK - wct := "application/json" - wbody := "" - - if rw.Code != wcode { - t.Errorf("got code=%d, want %d", rw.Code, wcode) - } - h := rw.Header() - if ct := h.Get("Content-Type"); ct != wct { - t.Errorf("Content-Type=%q, want %q", ct, wct) - } - g := rw.Body.String() - if g != wbody { - t.Errorf("got body=%#v, want %#v", g, wbody) - } - - // Now send the first event - select { - case wa.echan <- &v2store.Event{ - Action: v2store.Get, - Node: &v2store.NodeExtern{}, - }: - case <-time.After(time.Second): - t.Fatal("timed out waiting for send") - } - - // Wait for it to be flushed... - select { - case <-rw.ch: - case <-time.After(time.Second): - t.Fatalf("timed out waiting for flush") - } - - // And check the body is as expected - wbody = mustMarshalEvent( - t, - &v2store.Event{ - Action: v2store.Get, - Node: &v2store.NodeExtern{}, - }, - ) - g = rw.Body.String() - if g != wbody { - t.Errorf("got body=%#v, want %#v", g, wbody) - } - - // Rinse and repeat - select { - case wa.echan <- &v2store.Event{ - Action: v2store.Get, - Node: &v2store.NodeExtern{}, - }: - case <-time.After(time.Second): - t.Fatal("timed out waiting for send") - } - - select { - case <-rw.ch: - case <-time.After(time.Second): - t.Fatalf("timed out waiting for flush") - } - - // This time, we expect to see both events - wbody = wbody + wbody - g = rw.Body.String() - if g != wbody { - t.Errorf("got body=%#v, want %#v", g, wbody) - } - - // Finally, time out the connection and ensure the serving goroutine returns - cancel() - - select { - case <-done: - case <-time.After(time.Second): - t.Fatalf("timed out waiting for done") - } -} - -func TestTrimEventPrefix(t *testing.T) { - pre := "/abc" - tests := []struct { - ev *v2store.Event - wev *v2store.Event - }{ - { - nil, - nil, - }, - { - &v2store.Event{}, - &v2store.Event{}, - }, - { - &v2store.Event{Node: &v2store.NodeExtern{Key: "/abc/def"}}, - &v2store.Event{Node: &v2store.NodeExtern{Key: "/def"}}, - }, - { - &v2store.Event{PrevNode: &v2store.NodeExtern{Key: "/abc/ghi"}}, - &v2store.Event{PrevNode: &v2store.NodeExtern{Key: "/ghi"}}, - }, - { - &v2store.Event{ - Node: &v2store.NodeExtern{Key: "/abc/def"}, - PrevNode: &v2store.NodeExtern{Key: "/abc/ghi"}, - }, - &v2store.Event{ - Node: &v2store.NodeExtern{Key: "/def"}, - PrevNode: &v2store.NodeExtern{Key: "/ghi"}, - }, - }, - } - for i, tt := range tests { - ev := trimEventPrefix(tt.ev, pre) - if !reflect.DeepEqual(ev, tt.wev) { - t.Errorf("#%d: event = %+v, want %+v", i, ev, tt.wev) - } - } -} - -func TestTrimNodeExternPrefix(t *testing.T) { - pre := "/abc" - tests := []struct { - n *v2store.NodeExtern - wn *v2store.NodeExtern - }{ - { - nil, - nil, - }, - { - &v2store.NodeExtern{Key: "/abc/def"}, - &v2store.NodeExtern{Key: "/def"}, - }, - { - &v2store.NodeExtern{ - Key: "/abc/def", - Nodes: []*v2store.NodeExtern{ - {Key: "/abc/def/1"}, - {Key: "/abc/def/2"}, - }, - }, - &v2store.NodeExtern{ - Key: "/def", - Nodes: []*v2store.NodeExtern{ - {Key: "/def/1"}, - {Key: "/def/2"}, - }, - }, - }, - } - for i, tt := range tests { - trimNodeExternPrefix(tt.n, pre) - if !reflect.DeepEqual(tt.n, tt.wn) { - t.Errorf("#%d: node = %+v, want %+v", i, tt.n, tt.wn) - } - } -} - -func TestTrimPrefix(t *testing.T) { - tests := []struct { - in string - prefix string - w string - }{ - {"/v2/members", "/v2/members", ""}, - {"/v2/members/", "/v2/members", ""}, - {"/v2/members/foo", "/v2/members", "foo"}, - } - for i, tt := range tests { - if g := trimPrefix(tt.in, tt.prefix); g != tt.w { - t.Errorf("#%d: trimPrefix = %q, want %q", i, g, tt.w) - } - } -} - -func TestNewMemberCollection(t *testing.T) { - fixture := []*membership.Member{ - { - ID: 12, - Attributes: membership.Attributes{ClientURLs: []string{"http://localhost:8080", "http://localhost:8081"}}, - RaftAttributes: membership.RaftAttributes{PeerURLs: []string{"http://localhost:8082", "http://localhost:8083"}}, - }, - { - ID: 13, - Attributes: membership.Attributes{ClientURLs: []string{"http://localhost:9090", "http://localhost:9091"}}, - RaftAttributes: membership.RaftAttributes{PeerURLs: []string{"http://localhost:9092", "http://localhost:9093"}}, - }, - } - got := newMemberCollection(fixture) - - want := httptypes.MemberCollection([]httptypes.Member{ - { - ID: "c", - ClientURLs: []string{"http://localhost:8080", "http://localhost:8081"}, - PeerURLs: []string{"http://localhost:8082", "http://localhost:8083"}, - }, - { - ID: "d", - ClientURLs: []string{"http://localhost:9090", "http://localhost:9091"}, - PeerURLs: []string{"http://localhost:9092", "http://localhost:9093"}, - }, - }) - - if !reflect.DeepEqual(&want, got) { - t.Fatalf("newMemberCollection failure: want=%#v, got=%#v", &want, got) - } -} - -func TestNewMember(t *testing.T) { - fixture := &membership.Member{ - ID: 12, - Attributes: membership.Attributes{ClientURLs: []string{"http://localhost:8080", "http://localhost:8081"}}, - RaftAttributes: membership.RaftAttributes{PeerURLs: []string{"http://localhost:8082", "http://localhost:8083"}}, - } - got := newMember(fixture) - - want := httptypes.Member{ - ID: "c", - ClientURLs: []string{"http://localhost:8080", "http://localhost:8081"}, - PeerURLs: []string{"http://localhost:8082", "http://localhost:8083"}, - } - - if !reflect.DeepEqual(want, got) { - t.Fatalf("newMember failure: want=%#v, got=%#v", want, got) - } -} diff --git a/server/etcdserver/api/v2http/doc.go b/server/etcdserver/api/v2http/doc.go deleted file mode 100644 index 475c4b1f95a3..000000000000 --- a/server/etcdserver/api/v2http/doc.go +++ /dev/null @@ -1,16 +0,0 @@ -// Copyright 2015 The etcd Authors -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -// Package v2http provides etcd client and server implementations. -package v2http diff --git a/server/etcdserver/api/v2http/http.go b/server/etcdserver/api/v2http/http.go deleted file mode 100644 index 88138b80a8a9..000000000000 --- a/server/etcdserver/api/v2http/http.go +++ /dev/null @@ -1,82 +0,0 @@ -// Copyright 2015 The etcd Authors -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -package v2http - -import ( - "math" - "net/http" - "strings" - "time" - - "go.etcd.io/etcd/server/v3/etcdserver/api/etcdhttp" - "go.etcd.io/etcd/server/v3/etcdserver/api/v2auth" - "go.etcd.io/etcd/server/v3/etcdserver/api/v2http/httptypes" - - "go.uber.org/zap" -) - -const ( - // time to wait for a Watch request - defaultWatchTimeout = time.Duration(math.MaxInt64) -) - -func writeError(lg *zap.Logger, w http.ResponseWriter, r *http.Request, err error) { - if err == nil { - return - } - if e, ok := err.(v2auth.Error); ok { - herr := httptypes.NewHTTPError(e.HTTPStatus(), e.Error()) - if et := herr.WriteTo(w); et != nil { - if lg != nil { - lg.Debug( - "failed to write v2 HTTP error", - zap.String("remote-addr", r.RemoteAddr), - zap.String("v2auth-error", e.Error()), - zap.Error(et), - ) - } - } - return - } - etcdhttp.WriteError(lg, w, r, err) -} - -// allowMethod verifies that the given method is one of the allowed methods, -// and if not, it writes an error to w. A boolean is returned indicating -// whether or not the method is allowed. -func allowMethod(w http.ResponseWriter, m string, ms ...string) bool { - for _, meth := range ms { - if m == meth { - return true - } - } - w.Header().Set("Allow", strings.Join(ms, ",")) - http.Error(w, "Method Not Allowed", http.StatusMethodNotAllowed) - return false -} - -func requestLogger(lg *zap.Logger, handler http.Handler) http.Handler { - return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { - if lg != nil { - lg.Debug( - "handling HTTP request", - zap.String("method", r.Method), - zap.String("request-uri", r.RequestURI), - zap.String("remote-addr", r.RemoteAddr), - ) - } - handler.ServeHTTP(w, r) - }) -} diff --git a/server/etcdserver/api/v2http/http_test.go b/server/etcdserver/api/v2http/http_test.go deleted file mode 100644 index 2fcd6b26b94b..000000000000 --- a/server/etcdserver/api/v2http/http_test.go +++ /dev/null @@ -1,192 +0,0 @@ -// Copyright 2015 The etcd Authors -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -package v2http - -import ( - "context" - "errors" - "net/http" - "net/http/httptest" - "sort" - "testing" - - "go.etcd.io/etcd/api/v3/etcdserverpb" - "go.etcd.io/etcd/client/pkg/v3/types" - "go.etcd.io/etcd/raft/v3/raftpb" - "go.etcd.io/etcd/server/v3/etcdserver" - "go.etcd.io/etcd/server/v3/etcdserver/api/membership" - "go.etcd.io/etcd/server/v3/etcdserver/api/v2error" - - "github.com/coreos/go-semver/semver" - "go.uber.org/zap" -) - -type fakeCluster struct { - id uint64 - clientURLs []string - members map[uint64]*membership.Member -} - -func (c *fakeCluster) ID() types.ID { return types.ID(c.id) } -func (c *fakeCluster) ClientURLs() []string { return c.clientURLs } -func (c *fakeCluster) Members() []*membership.Member { - var ms membership.MembersByID - for _, m := range c.members { - ms = append(ms, m) - } - sort.Sort(ms) - return []*membership.Member(ms) -} -func (c *fakeCluster) Member(id types.ID) *membership.Member { return c.members[uint64(id)] } -func (c *fakeCluster) Version() *semver.Version { return nil } - -// errServer implements the etcd.Server interface for testing. -// It returns the given error from any Do/Process/AddMember/RemoveMember calls. -type errServer struct { - err error - fakeServer -} - -func (fs *errServer) Do(ctx context.Context, r etcdserverpb.Request) (etcdserver.Response, error) { - return etcdserver.Response{}, fs.err -} -func (fs *errServer) Process(ctx context.Context, m raftpb.Message) error { - return fs.err -} -func (fs *errServer) AddMember(ctx context.Context, m membership.Member) ([]*membership.Member, error) { - return nil, fs.err -} -func (fs *errServer) RemoveMember(ctx context.Context, id uint64) ([]*membership.Member, error) { - return nil, fs.err -} -func (fs *errServer) UpdateMember(ctx context.Context, m membership.Member) ([]*membership.Member, error) { - return nil, fs.err -} -func (fs *errServer) PromoteMember(ctx context.Context, id uint64) ([]*membership.Member, error) { - return nil, fs.err -} - -func TestWriteError(t *testing.T) { - // nil error should not panic - rec := httptest.NewRecorder() - r := new(http.Request) - writeError(zap.NewExample(), rec, r, nil) - h := rec.Header() - if len(h) > 0 { - t.Fatalf("unexpected non-empty headers: %#v", h) - } - b := rec.Body.String() - if len(b) > 0 { - t.Fatalf("unexpected non-empty body: %q", b) - } - - tests := []struct { - err error - wcode int - wi string - }{ - { - v2error.NewError(v2error.EcodeKeyNotFound, "/foo/bar", 123), - http.StatusNotFound, - "123", - }, - { - v2error.NewError(v2error.EcodeTestFailed, "/foo/bar", 456), - http.StatusPreconditionFailed, - "456", - }, - { - err: errors.New("something went wrong"), - wcode: http.StatusInternalServerError, - }, - } - - for i, tt := range tests { - rw := httptest.NewRecorder() - writeError(zap.NewExample(), rw, r, tt.err) - if code := rw.Code; code != tt.wcode { - t.Errorf("#%d: code=%d, want %d", i, code, tt.wcode) - } - if idx := rw.Header().Get("X-Etcd-Index"); idx != tt.wi { - t.Errorf("#%d: X-Etcd-Index=%q, want %q", i, idx, tt.wi) - } - } -} - -func TestAllowMethod(t *testing.T) { - tests := []struct { - m string - ms []string - w bool - wh string - }{ - // Accepted methods - { - m: "GET", - ms: []string{"GET", "POST", "PUT"}, - w: true, - }, - { - m: "POST", - ms: []string{"POST"}, - w: true, - }, - // Made-up methods no good - { - m: "FAKE", - ms: []string{"GET", "POST", "PUT"}, - w: false, - wh: "GET,POST,PUT", - }, - // Empty methods no good - { - m: "", - ms: []string{"GET", "POST"}, - w: false, - wh: "GET,POST", - }, - // Empty accepted methods no good - { - m: "GET", - ms: []string{""}, - w: false, - wh: "", - }, - // No methods accepted - { - m: "GET", - ms: []string{}, - w: false, - wh: "", - }, - } - - for i, tt := range tests { - rw := httptest.NewRecorder() - g := allowMethod(rw, tt.m, tt.ms...) - if g != tt.w { - t.Errorf("#%d: got allowMethod()=%t, want %t", i, g, tt.w) - } - if !tt.w { - if rw.Code != http.StatusMethodNotAllowed { - t.Errorf("#%d: code=%d, want %d", i, rw.Code, http.StatusMethodNotAllowed) - } - gh := rw.Header().Get("Allow") - if gh != tt.wh { - t.Errorf("#%d: Allow header=%q, want %q", i, gh, tt.wh) - } - } - } -} diff --git a/server/etcdserver/api/v2http/httptypes/member.go b/server/etcdserver/api/v2http/httptypes/member.go deleted file mode 100644 index a5467be91ee2..000000000000 --- a/server/etcdserver/api/v2http/httptypes/member.go +++ /dev/null @@ -1,69 +0,0 @@ -// Copyright 2015 The etcd Authors -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -// Package httptypes defines how etcd's HTTP API entities are serialized to and -// deserialized from JSON. -package httptypes - -import ( - "encoding/json" - - "go.etcd.io/etcd/client/pkg/v3/types" -) - -type Member struct { - ID string `json:"id"` - Name string `json:"name"` - PeerURLs []string `json:"peerURLs"` - ClientURLs []string `json:"clientURLs"` -} - -type MemberCreateRequest struct { - PeerURLs types.URLs -} - -type MemberUpdateRequest struct { - MemberCreateRequest -} - -func (m *MemberCreateRequest) UnmarshalJSON(data []byte) error { - s := struct { - PeerURLs []string `json:"peerURLs"` - }{} - - err := json.Unmarshal(data, &s) - if err != nil { - return err - } - - urls, err := types.NewURLs(s.PeerURLs) - if err != nil { - return err - } - - m.PeerURLs = urls - return nil -} - -type MemberCollection []Member - -func (c *MemberCollection) MarshalJSON() ([]byte, error) { - d := struct { - Members []Member `json:"members"` - }{ - Members: []Member(*c), - } - - return json.Marshal(d) -} diff --git a/server/etcdserver/api/v2http/httptypes/member_test.go b/server/etcdserver/api/v2http/httptypes/member_test.go deleted file mode 100644 index 6b8056abdc10..000000000000 --- a/server/etcdserver/api/v2http/httptypes/member_test.go +++ /dev/null @@ -1,135 +0,0 @@ -// Copyright 2015 The etcd Authors -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -package httptypes - -import ( - "encoding/json" - "net/url" - "reflect" - "testing" - - "go.etcd.io/etcd/client/pkg/v3/types" -) - -func TestMemberUnmarshal(t *testing.T) { - tests := []struct { - body []byte - wantMember Member - wantError bool - }{ - // no URLs, just check ID & Name - { - body: []byte(`{"id": "c", "name": "dungarees"}`), - wantMember: Member{ID: "c", Name: "dungarees", PeerURLs: nil, ClientURLs: nil}, - }, - - // both client and peer URLs - { - body: []byte(`{"peerURLs": ["http://127.0.0.1:2379"], "clientURLs": ["http://127.0.0.1:2379"]}`), - wantMember: Member{ - PeerURLs: []string{ - "http://127.0.0.1:2379", - }, - ClientURLs: []string{ - "http://127.0.0.1:2379", - }, - }, - }, - - // multiple peer URLs - { - body: []byte(`{"peerURLs": ["http://127.0.0.1:2379", "https://example.com"]}`), - wantMember: Member{ - PeerURLs: []string{ - "http://127.0.0.1:2379", - "https://example.com", - }, - ClientURLs: nil, - }, - }, - - // multiple client URLs - { - body: []byte(`{"clientURLs": ["http://127.0.0.1:2379", "https://example.com"]}`), - wantMember: Member{ - PeerURLs: nil, - ClientURLs: []string{ - "http://127.0.0.1:2379", - "https://example.com", - }, - }, - }, - - // invalid JSON - { - body: []byte(`{"peerU`), - wantError: true, - }, - } - - for i, tt := range tests { - got := Member{} - err := json.Unmarshal(tt.body, &got) - if tt.wantError != (err != nil) { - t.Errorf("#%d: want error %t, got %v", i, tt.wantError, err) - continue - } - - if !reflect.DeepEqual(tt.wantMember, got) { - t.Errorf("#%d: incorrect output: want=%#v, got=%#v", i, tt.wantMember, got) - } - } -} - -func TestMemberCreateRequestUnmarshal(t *testing.T) { - body := []byte(`{"peerURLs": ["http://127.0.0.1:8081", "https://127.0.0.1:8080"]}`) - want := MemberCreateRequest{ - PeerURLs: types.URLs([]url.URL{ - {Scheme: "http", Host: "127.0.0.1:8081"}, - {Scheme: "https", Host: "127.0.0.1:8080"}, - }), - } - - var req MemberCreateRequest - if err := json.Unmarshal(body, &req); err != nil { - t.Fatalf("Unmarshal returned unexpected err=%v", err) - } - - if !reflect.DeepEqual(want, req) { - t.Fatalf("Failed to unmarshal MemberCreateRequest: want=%#v, got=%#v", want, req) - } -} - -func TestMemberCreateRequestUnmarshalFail(t *testing.T) { - tests := [][]byte{ - // invalid JSON - []byte(``), - []byte(`{`), - - // spot-check validation done in types.NewURLs - []byte(`{"peerURLs": "foo"}`), - []byte(`{"peerURLs": ["."]}`), - []byte(`{"peerURLs": []}`), - []byte(`{"peerURLs": ["http://127.0.0.1:2379/foo"]}`), - []byte(`{"peerURLs": ["http://127.0.0.1"]}`), - } - - for i, tt := range tests { - var req MemberCreateRequest - if err := json.Unmarshal(tt, &req); err == nil { - t.Errorf("#%d: expected err, got nil", i) - } - } -} diff --git a/server/etcdserver/api/v2http/metrics.go b/server/etcdserver/api/v2http/metrics.go deleted file mode 100644 index bdbd8c71c1ba..000000000000 --- a/server/etcdserver/api/v2http/metrics.go +++ /dev/null @@ -1,98 +0,0 @@ -// Copyright 2015 The etcd Authors -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -package v2http - -import ( - "net/http" - "strconv" - "time" - - "go.etcd.io/etcd/api/v3/etcdserverpb" - "go.etcd.io/etcd/server/v3/etcdserver/api/v2error" - "go.etcd.io/etcd/server/v3/etcdserver/api/v2http/httptypes" - - "github.com/prometheus/client_golang/prometheus" -) - -var ( - incomingEvents = prometheus.NewCounterVec( - prometheus.CounterOpts{ - Namespace: "etcd", - Subsystem: "http", - Name: "received_total", - Help: "Counter of requests received into the system (successfully parsed and authd).", - }, []string{"method"}) - - failedEvents = prometheus.NewCounterVec( - prometheus.CounterOpts{ - Namespace: "etcd", - Subsystem: "http", - Name: "failed_total", - Help: "Counter of handle failures of requests (non-watches), by method (GET/PUT etc.) and code (400, 500 etc.).", - }, []string{"method", "code"}) - - successfulEventsHandlingSec = prometheus.NewHistogramVec( - prometheus.HistogramOpts{ - Namespace: "etcd", - Subsystem: "http", - Name: "successful_duration_seconds", - Help: "Bucketed histogram of processing time (s) of successfully handled requests (non-watches), by method (GET/PUT etc.).", - - // lowest bucket start of upper bound 0.0005 sec (0.5 ms) with factor 2 - // highest bucket start of 0.0005 sec * 2^12 == 2.048 sec - Buckets: prometheus.ExponentialBuckets(0.0005, 2, 13), - }, []string{"method"}) -) - -func init() { - prometheus.MustRegister(incomingEvents) - prometheus.MustRegister(failedEvents) - prometheus.MustRegister(successfulEventsHandlingSec) -} - -func reportRequestReceived(request etcdserverpb.Request) { - incomingEvents.WithLabelValues(methodFromRequest(request)).Inc() -} - -func reportRequestCompleted(request etcdserverpb.Request, startTime time.Time) { - method := methodFromRequest(request) - successfulEventsHandlingSec.WithLabelValues(method).Observe(time.Since(startTime).Seconds()) -} - -func reportRequestFailed(request etcdserverpb.Request, err error) { - method := methodFromRequest(request) - failedEvents.WithLabelValues(method, strconv.Itoa(codeFromError(err))).Inc() -} - -func methodFromRequest(request etcdserverpb.Request) string { - if request.Method == "GET" && request.Quorum { - return "QGET" - } - return request.Method -} - -func codeFromError(err error) int { - if err == nil { - return http.StatusInternalServerError - } - switch e := err.(type) { - case *v2error.Error: - return e.StatusCode() - case *httptypes.HTTPError: - return e.Code - default: - return http.StatusInternalServerError - } -} diff --git a/server/etcdserver/api/v2http/testdata/ca.pem b/server/etcdserver/api/v2http/testdata/ca.pem deleted file mode 100644 index 60cbee3bb4bd..000000000000 --- a/server/etcdserver/api/v2http/testdata/ca.pem +++ /dev/null @@ -1,19 +0,0 @@ ------BEGIN CERTIFICATE----- -MIIDEjCCAfqgAwIBAgIIYpX+8HgWGfkwDQYJKoZIhvcNAQELBQAwFTETMBEGA1UE -AxMKZXRjZCB0ZXN0czAeFw0xNTExMjQwMzA1MDBaFw0yMDExMjIwMzA1MDBaMBUx -EzARBgNVBAMTCmV0Y2QgdGVzdHMwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEK -AoIBAQDa9PkwEwiBD8mB+VIKz5r5gRHnNF4Icj6T6R/RsdatecQe6vU0EU4FXtKZ -drWnCGlATyrQooqHpb+rDc7CUt3mXrIxrNkcGTMaesF7P0GWxVkyOGSjJMxGBv3e -bAZknBe4eLMi68L1aT/uYmxcp/B3L2mfdFtc1Gd6mYJpNm1PgilRyIrO0mY5ysIX -4WHCa3yudAv8HrFbQcw7l7OyKA6uSWg6h07lE3d5jw5YOly+hz0iaRtzhb4tJrYD -Lm1tehb0nnoLuW6yYblRSoyBVDT50MFVlyvW40Po5WkOXw/wnsnyxWRR4yqU23wq -quQU0HXJEBLFnT+KbLOQ0EAE35vXAgMBAAGjZjBkMA4GA1UdDwEB/wQEAwIBBjAS -BgNVHRMBAf8ECDAGAQH/AgECMB0GA1UdDgQWBBSbUCGB95ochDrbEZlzGGYuA7xu -xjAfBgNVHSMEGDAWgBSbUCGB95ochDrbEZlzGGYuA7xuxjANBgkqhkiG9w0BAQsF -AAOCAQEAardO/SGCu7Snz3YRBUinzpZEUFTFend+FJtBkxBXCao1RvTXg8PBMkza -LUsaR4mLsGoXLIbNCoIinvVG0QULYCZe11N3l1L0G2g5uhEM4MfJ2rwrMD0o17i+ -nwNRRE3tfKAlWhYQg+4ye36kQVxASPniHjdQgjKYUFTNXdyG6DzuAclaVte9iVw6 -cWl61fB2CZya3+uMtih8t/Kgl2KbMO2PvNByfnDjKmW+v58qHbXyoJZqnpvDn14+ -p2Ox+AvvxYiEiUIvFdWy101QB7NJMCtdwq6oG6OvIOgXzLgitTFSq4kfWDfupQjW -iFoQ+vWmYhK5ld0nBaiz+JmHuemK7A== ------END CERTIFICATE----- diff --git a/server/etcdserver/api/v2http/testdata/otheruser.pem b/server/etcdserver/api/v2http/testdata/otheruser.pem deleted file mode 100644 index d0c74eb9f8d3..000000000000 --- a/server/etcdserver/api/v2http/testdata/otheruser.pem +++ /dev/null @@ -1,20 +0,0 @@ ------BEGIN CERTIFICATE----- -MIIDOTCCAiGgAwIBAgIINYpsso1f3SswDQYJKoZIhvcNAQELBQAwFTETMBEGA1UE -AxMKZXRjZCB0ZXN0czAeFw0xNTExMjQwMzA4MDBaFw0xNjExMjMwMzA4MDBaMBQx -EjAQBgNVBAMTCW90aGVydXNlcjCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoC -ggEBAPOAUa5GblwIjHTEnox2c/Am9jV1TMvzBuVXxnp2UnNHMNwstAooFrEs/Z+d -ft5AOsooP6zVuM3eBQa4i9huJbVNDfPU2H94yA89jYfJYUgo7C838V6NjGsCCptQ -WzkKPNlDbT9xA/7XpIUJ2WltuYDRrjWq8pXQONqTjcg5n4l0JO8xdHJHRUkFQ76F -1npXeLndgGaP11lqzpYlglEGi5URhzAT1xxQ0hLSe8WNmiCxxkq++C8Gx4sPg9mX -M94aoJDzZSnoaqDxckbP/7Q0ZKe/fVdCFkd5+jqT4Mt7hwmz9jTCHcVnAz4EKI+t -rbWgbCfMK6013GotXz7InStVe+MCAwEAAaOBjTCBijAOBgNVHQ8BAf8EBAMCBaAw -HQYDVR0lBBYwFAYIKwYBBQUHAwEGCCsGAQUFBwMCMAwGA1UdEwEB/wQCMAAwHQYD -VR0OBBYEFFwMmf+pnaejmri6y1T+lfU+MBq/MB8GA1UdIwQYMBaAFJtQIYH3mhyE -OtsRmXMYZi4DvG7GMAsGA1UdEQQEMAKCADANBgkqhkiG9w0BAQsFAAOCAQEACOn6 -mec29MTMGPt/EPOmSyhvTKSwH+5YWjCbyUFeoB8puxrJlIphK4mvT+sXp2wzno89 -FVCliO/rJurdErKvyOjlK1QrVGPYIt7Wz9ssAfvlwCyBM8PqgEG8dJN9aAkf2h4r -Ye+hBh1y6Nnataf7lxe9mqAOvD/7wVIgzjCnMD1q5QSY2Mln3HwVQXtbZFbY363Z -X9Fk3PUpjJSX9jbEz9kIlT8AJAdxl6GB8Z9B8PrA8qf4Bhk15ICRHxb67EhDrGWV -8q7ArU2XBqs/+GWpUIMoGKNZv+K+/SksZK1KnzaUvApUCJzt+ac+p8HOgMdvDRgr -GfVVJqcZgyEmeczy0A== ------END CERTIFICATE----- diff --git a/server/etcdserver/api/v2http/testdata/user.pem b/server/etcdserver/api/v2http/testdata/user.pem deleted file mode 100644 index 0fc2108651b6..000000000000 --- a/server/etcdserver/api/v2http/testdata/user.pem +++ /dev/null @@ -1,20 +0,0 @@ ------BEGIN CERTIFICATE----- -MIIDNDCCAhygAwIBAgIIcQ0DAfgevocwDQYJKoZIhvcNAQELBQAwFTETMBEGA1UE -AxMKZXRjZCB0ZXN0czAeFw0xNTExMjQwMzA4MDBaFw0xNjExMjMwMzA4MDBaMA8x -DTALBgNVBAMTBHVzZXIwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQD0 -+3Lm1SmUJJLufaFTYz+e5qyQEshNRyeAhXIeZ1aw+yBjslXGZQ3/uGOwnOnGqUeA -Nidc9ty4NsK6RVppHlezUrBnpl4hws8vHWFKZpU2R6kKL8EYLmg+iVqEBj7XqfAp -8bJqqZI3KOqLXpRH55mA69KP7VEK9ngTVR/tERSrUPT8jcjwbvhSOqD8Qk07BUDR -6RpDr94Mnaf+fMGG36Sh7iUl+i4Oh6FFar+7+b0+5Bhs2/6uVsK4A1Z3jqqfSQH8 -q8Wf5h9Ka4aqGSw4ia5G3Uw7Jsl2aDgpJ7uwJo1k8SclbMYnYdhZuo+U+esY/Fai -YdbjG+AroZ+y9TB8bMlHAgMBAAGjgY0wgYowDgYDVR0PAQH/BAQDAgWgMB0GA1Ud -JQQWMBQGCCsGAQUFBwMBBggrBgEFBQcDAjAMBgNVHRMBAf8EAjAAMB0GA1UdDgQW -BBRuTt0lJIVKYaz76aSxl/MQOLRwfDAfBgNVHSMEGDAWgBSbUCGB95ochDrbEZlz -GGYuA7xuxjALBgNVHREEBDACggAwDQYJKoZIhvcNAQELBQADggEBABLRWZm+Lgjs -c5qDXbgOJW2pR630syY8ixR9c6HvzPVJim8mFioMX+xrlbOC6BmOUlOb9j83bTKn -aOg/0xlpxNbd8QYzgRxZmHZLULPdiNeeRvIzsrzrH88+inrmZhRXRVcHjdO6CG6t -hCdDdRiNU6GkF7dPna0xNcEOKe2wUfzd1ZtKOqzi1w+fKjSeMplZomeWgP4WRvkh -JJ/0ujlMMckgyTxRh8EEaJ35OnpXX7EdipoWhOMmiUnlPqye2icC8Y+CMdZsrod6 -nkoEQnXDCLf/Iv0qj7B9iKbxn7t3QDVxY4UILUReDuD8yrGULlGOl//aY/T3pkZ6 -R5trduZhI3o= ------END CERTIFICATE----- diff --git a/server/etcdserver/api/v2stats/stats.go b/server/etcdserver/api/v2stats/stats.go deleted file mode 100644 index cbf60215a241..000000000000 --- a/server/etcdserver/api/v2stats/stats.go +++ /dev/null @@ -1,26 +0,0 @@ -// Copyright 2015 The etcd Authors -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -// Package v2stats defines a standard interface for etcd cluster statistics. -package v2stats - -type Stats interface { - // SelfStats returns the struct representing statistics of this server - SelfStats() []byte - // LeaderStats returns the statistics of all followers in the cluster - // if this server is leader. Otherwise, nil is returned. - LeaderStats() []byte - // StoreStats returns statistics of the store backing this EtcdServer - StoreStats() []byte -} diff --git a/server/etcdserver/server.go b/server/etcdserver/server.go index 1828cfd2cfa4..d3a7981bcc2c 100644 --- a/server/etcdserver/server.go +++ b/server/etcdserver/server.go @@ -142,7 +142,6 @@ type ServerV2 interface { // Do takes a V2 request and attempts to fulfill it, returning a Response. Do(ctx context.Context, r pb.Request) (Response, error) - stats.Stats ClientCertAuthEnabled() bool } @@ -1224,18 +1223,6 @@ func (s *EtcdServer) StopNotify() <-chan struct{} { return s.done } // when the server is being stopped. func (s *EtcdServer) StoppingNotify() <-chan struct{} { return s.stopping } -func (s *EtcdServer) SelfStats() []byte { return s.stats.JSON() } - -func (s *EtcdServer) LeaderStats() []byte { - lead := s.getLead() - if lead != uint64(s.id) { - return nil - } - return s.lstats.JSON() -} - -func (s *EtcdServer) StoreStats() []byte { return s.v2store.JsonStats() } - func (s *EtcdServer) checkMembershipOperationPermission(ctx context.Context) error { if s.authStore == nil { // In the context of ordinary etcd process, s.authStore will never be nil. diff --git a/tests/e2e/discovery_test.go b/tests/e2e/discovery_test.go index 6f6a5e1506c5..8ace067d5c2f 100644 --- a/tests/e2e/discovery_test.go +++ b/tests/e2e/discovery_test.go @@ -17,11 +17,16 @@ package e2e import ( "context" "fmt" + "net/http" "strings" "testing" + "time" "go.etcd.io/etcd/client/pkg/v3/fileutil" + "go.etcd.io/etcd/client/pkg/v3/testutil" + "go.etcd.io/etcd/client/pkg/v3/transport" "go.etcd.io/etcd/client/v2" + "go.etcd.io/etcd/server/v3/etcdserver/api/rafthttp" "go.etcd.io/etcd/tests/v3/framework/e2e" "go.etcd.io/etcd/tests/v3/framework/integration" ) @@ -49,7 +54,7 @@ func testClusterUsingDiscovery(t *testing.T, size int, peerTLS bool) { } defer dc.Close() - dcc := integration.MustNewHTTPClient(t, dc.EndpointsV2(), nil) + dcc := MustNewHTTPClient(t, dc.EndpointsV2(), nil) dkapi := client.NewKeysAPI(dcc) ctx, cancel := context.WithTimeout(context.Background(), integration.RequestTimeout) if _, err := dkapi.Create(ctx, "/_config/size", fmt.Sprintf("%d", size)); err != nil { @@ -76,3 +81,25 @@ func testClusterUsingDiscovery(t *testing.T, size int, peerTLS bool) { t.Fatal(err) } } + +func MustNewHTTPClient(t testutil.TB, eps []string, tls *transport.TLSInfo) client.Client { + cfgtls := transport.TLSInfo{} + if tls != nil { + cfgtls = *tls + } + cfg := client.Config{Transport: mustNewTransport(t, cfgtls), Endpoints: eps} + c, err := client.New(cfg) + if err != nil { + t.Fatal(err) + } + return c +} + +func mustNewTransport(t testutil.TB, tlsInfo transport.TLSInfo) *http.Transport { + // tick in integration test is short, so 1s dial timeout could play well. + tr, err := transport.NewTimeoutTransport(tlsInfo, time.Second, rafthttp.ConnReadTimeout, rafthttp.ConnWriteTimeout) + if err != nil { + t.Fatal(err) + } + return tr +} diff --git a/tests/framework/integration/cluster.go b/tests/framework/integration/cluster.go index c5687a48616e..a32e634719c7 100644 --- a/tests/framework/integration/cluster.go +++ b/tests/framework/integration/cluster.go @@ -38,7 +38,6 @@ import ( "go.etcd.io/etcd/client/pkg/v3/tlsutil" "go.etcd.io/etcd/client/pkg/v3/transport" "go.etcd.io/etcd/client/pkg/v3/types" - "go.etcd.io/etcd/client/v2" "go.etcd.io/etcd/client/v3" "go.etcd.io/etcd/pkg/v3/grpc_testing" "go.etcd.io/etcd/raft/v3" @@ -1305,28 +1304,6 @@ func (m *Member) ReadyNotify() <-chan struct{} { return m.Server.ReadyNotify() } -func MustNewHTTPClient(t testutil.TB, eps []string, tls *transport.TLSInfo) client.Client { - cfgtls := transport.TLSInfo{} - if tls != nil { - cfgtls = *tls - } - cfg := client.Config{Transport: mustNewTransport(t, cfgtls), Endpoints: eps} - c, err := client.New(cfg) - if err != nil { - t.Fatal(err) - } - return c -} - -func mustNewTransport(t testutil.TB, tlsInfo transport.TLSInfo) *http.Transport { - // tick in integration test is short, so 1s dial timeout could play well. - tr, err := transport.NewTimeoutTransport(tlsInfo, time.Second, rafthttp.ConnReadTimeout, rafthttp.ConnWriteTimeout) - if err != nil { - t.Fatal(err) - } - return tr -} - type SortableMemberSliceByPeerURLs []*pb.Member func (p SortableMemberSliceByPeerURLs) Len() int { return len(p) } From d108a241d0a6392735259204bf45a667a2424ab9 Mon Sep 17 00:00:00 2001 From: bjyangxuanjia Date: Wed, 26 Jan 2022 15:03:44 +0800 Subject: [PATCH 092/258] fix panic when restart after removeMember fix panic when restart after removeMember fix panic when restart after removeMember --- server/etcdserver/api/rafthttp/transport.go | 34 ++++++++++++--------- 1 file changed, 20 insertions(+), 14 deletions(-) diff --git a/server/etcdserver/api/rafthttp/transport.go b/server/etcdserver/api/rafthttp/transport.go index 940e8473bc15..fa3011cb39ac 100644 --- a/server/etcdserver/api/rafthttp/transport.go +++ b/server/etcdserver/api/rafthttp/transport.go @@ -339,24 +339,30 @@ func (t *Transport) RemoveAllPeers() { // the caller of this function must have the peers mutex. func (t *Transport) removePeer(id types.ID) { - if peer, ok := t.peers[id]; ok { + // etcd may remove a member again on startup due to WAL files replaying. + peer, ok := t.peers[id] + if ok { peer.stop() - } else { - if t.Logger != nil { - t.Logger.Panic("unexpected removal of unknown remote peer", zap.String("remote-peer-id", id.String())) - } + delete(t.peers, id) + delete(t.LeaderStats.Followers, id.String()) + t.pipelineProber.Remove(id.String()) + t.streamProber.Remove(id.String()) } - delete(t.peers, id) - delete(t.LeaderStats.Followers, id.String()) - t.pipelineProber.Remove(id.String()) - t.streamProber.Remove(id.String()) if t.Logger != nil { - t.Logger.Info( - "removed remote peer", - zap.String("local-member-id", t.ID.String()), - zap.String("removed-remote-peer-id", id.String()), - ) + if ok { + t.Logger.Info( + "removed remote peer", + zap.String("local-member-id", t.ID.String()), + zap.String("removed-remote-peer-id", id.String()), + ) + } else { + t.Logger.Warn( + "skipped removing already removed peer", + zap.String("local-member-id", t.ID.String()), + zap.String("removed-remote-peer-id", id.String()), + ) + } } } From db5b3a9a6d5ce4938d184f51bb72119fff1a1f3a Mon Sep 17 00:00:00 2001 From: Marek Siarkowicz Date: Wed, 26 Jan 2022 11:46:20 +0100 Subject: [PATCH 093/258] Move changelogs to subdirectory --- CHANGELOG-2.3.md => CHANGELOG/CHANGELOG-2.3.md | 0 CHANGELOG-3.0.md => CHANGELOG/CHANGELOG-3.0.md | 0 CHANGELOG-3.1.md => CHANGELOG/CHANGELOG-3.1.md | 2 +- CHANGELOG-3.2.md => CHANGELOG/CHANGELOG-3.2.md | 2 +- CHANGELOG-3.3.md => CHANGELOG/CHANGELOG-3.3.md | 2 +- CHANGELOG-3.4.md => CHANGELOG/CHANGELOG-3.4.md | 2 +- CHANGELOG-3.5.md => CHANGELOG/CHANGELOG-3.5.md | 2 +- CHANGELOG-3.6.md => CHANGELOG/CHANGELOG-3.6.md | 2 +- CHANGELOG-4.0.md => CHANGELOG/CHANGELOG-4.0.md | 2 +- 9 files changed, 7 insertions(+), 7 deletions(-) rename CHANGELOG-2.3.md => CHANGELOG/CHANGELOG-2.3.md (100%) rename CHANGELOG-3.0.md => CHANGELOG/CHANGELOG-3.0.md (100%) rename CHANGELOG-3.1.md => CHANGELOG/CHANGELOG-3.1.md (99%) rename CHANGELOG-3.2.md => CHANGELOG/CHANGELOG-3.2.md (99%) rename CHANGELOG-3.3.md => CHANGELOG/CHANGELOG-3.3.md (99%) rename CHANGELOG-3.4.md => CHANGELOG/CHANGELOG-3.4.md (99%) rename CHANGELOG-3.5.md => CHANGELOG/CHANGELOG-3.5.md (99%) rename CHANGELOG-3.6.md => CHANGELOG/CHANGELOG-3.6.md (97%) rename CHANGELOG-4.0.md => CHANGELOG/CHANGELOG-4.0.md (97%) diff --git a/CHANGELOG-2.3.md b/CHANGELOG/CHANGELOG-2.3.md similarity index 100% rename from CHANGELOG-2.3.md rename to CHANGELOG/CHANGELOG-2.3.md diff --git a/CHANGELOG-3.0.md b/CHANGELOG/CHANGELOG-3.0.md similarity index 100% rename from CHANGELOG-3.0.md rename to CHANGELOG/CHANGELOG-3.0.md diff --git a/CHANGELOG-3.1.md b/CHANGELOG/CHANGELOG-3.1.md similarity index 99% rename from CHANGELOG-3.1.md rename to CHANGELOG/CHANGELOG-3.1.md index 18765392ace9..b6706b712315 100644 --- a/CHANGELOG-3.1.md +++ b/CHANGELOG/CHANGELOG-3.1.md @@ -1,6 +1,6 @@ -Previous change logs can be found at [CHANGELOG-3.0](https://github.com/etcd-io/etcd/blob/main/CHANGELOG-3.0.md). +Previous change logs can be found at [CHANGELOG-3.0](https://github.com/etcd-io/etcd/blob/main/CHANGELOG/CHANGELOG-3.0.md). The minimum recommended etcd versions to run in **production** are 3.1.11+, 3.2.26+, and 3.3.11+. diff --git a/CHANGELOG-3.2.md b/CHANGELOG/CHANGELOG-3.2.md similarity index 99% rename from CHANGELOG-3.2.md rename to CHANGELOG/CHANGELOG-3.2.md index b6b2d2a39cbb..e4283f36a0fc 100644 --- a/CHANGELOG-3.2.md +++ b/CHANGELOG/CHANGELOG-3.2.md @@ -1,6 +1,6 @@ -Previous change logs can be found at [CHANGELOG-3.1](https://github.com/etcd-io/etcd/blob/main/CHANGELOG-3.1.md). +Previous change logs can be found at [CHANGELOG-3.1](https://github.com/etcd-io/etcd/blob/main/CHANGELOG/CHANGELOG-3.1.md). The minimum recommended etcd versions to run in **production** are 3.2.28+, 3.3.18+, and 3.4.2+. diff --git a/CHANGELOG-3.3.md b/CHANGELOG/CHANGELOG-3.3.md similarity index 99% rename from CHANGELOG-3.3.md rename to CHANGELOG/CHANGELOG-3.3.md index 65246e5dd081..75d56cefbec8 100644 --- a/CHANGELOG-3.3.md +++ b/CHANGELOG/CHANGELOG-3.3.md @@ -1,6 +1,6 @@ -Previous change logs can be found at [CHANGELOG-3.2](https://github.com/etcd-io/etcd/blob/main/CHANGELOG-3.2.md). +Previous change logs can be found at [CHANGELOG-3.2](https://github.com/etcd-io/etcd/blob/main/CHANGELOG/CHANGELOG-3.2.md). The minimum recommended etcd versions to run in **production** are 3.3.18+, 3.4.2+, and 3.5.1+. Refer to the [versioning policy](https://etcd.io/docs/v3.3/op-guide/versioning/) for more details. diff --git a/CHANGELOG-3.4.md b/CHANGELOG/CHANGELOG-3.4.md similarity index 99% rename from CHANGELOG-3.4.md rename to CHANGELOG/CHANGELOG-3.4.md index 50aecd966140..3cb69054469f 100644 --- a/CHANGELOG-3.4.md +++ b/CHANGELOG/CHANGELOG-3.4.md @@ -1,6 +1,6 @@ -Previous change logs can be found at [CHANGELOG-3.3](https://github.com/etcd-io/etcd/blob/main/CHANGELOG-3.3.md). +Previous change logs can be found at [CHANGELOG-3.3](https://github.com/etcd-io/etcd/blob/main/CHANGELOG/CHANGELOG-3.3.md). The minimum recommended etcd versions to run in **production** are 3.3.18+, 3.4.2+, and 3.5.1+. Refer to the [versioning policy](https://etcd.io/docs/v3.4/op-guide/versioning/) for more details. diff --git a/CHANGELOG-3.5.md b/CHANGELOG/CHANGELOG-3.5.md similarity index 99% rename from CHANGELOG-3.5.md rename to CHANGELOG/CHANGELOG-3.5.md index 6699fe17034f..d7acc70b3a6e 100644 --- a/CHANGELOG-3.5.md +++ b/CHANGELOG/CHANGELOG-3.5.md @@ -1,6 +1,6 @@ -Previous change logs can be found at [CHANGELOG-3.4](https://github.com/etcd-io/etcd/blob/main/CHANGELOG-3.4.md). +Previous change logs can be found at [CHANGELOG-3.4](https://github.com/etcd-io/etcd/blob/main/CHANGELOG/CHANGELOG-3.4.md). The minimum recommended etcd versions to run in **production** are 3.3.18+, 3.4.2+, and 3.5.1+. Refer to the [versioning policy](https://etcd.io/docs/v3.5/op-guide/versioning/) for more details. diff --git a/CHANGELOG-3.6.md b/CHANGELOG/CHANGELOG-3.6.md similarity index 97% rename from CHANGELOG-3.6.md rename to CHANGELOG/CHANGELOG-3.6.md index 8d0591cfd6ca..75c6fc8f0e43 100644 --- a/CHANGELOG-3.6.md +++ b/CHANGELOG/CHANGELOG-3.6.md @@ -1,6 +1,6 @@ -Previous change logs can be found at [CHANGELOG-3.5](https://github.com/etcd-io/etcd/blob/main/CHANGELOG-3.5.md). +Previous change logs can be found at [CHANGELOG-3.5](https://github.com/etcd-io/etcd/blob/main/CHANGELOG/CHANGELOG-3.5.md).
diff --git a/CHANGELOG-4.0.md b/CHANGELOG/CHANGELOG-4.0.md similarity index 97% rename from CHANGELOG-4.0.md rename to CHANGELOG/CHANGELOG-4.0.md index 6b15f723719a..c63d724bdaf6 100644 --- a/CHANGELOG-4.0.md +++ b/CHANGELOG/CHANGELOG-4.0.md @@ -1,6 +1,6 @@ -Previous change logs can be found at [CHANGELOG-3.x](https://github.com/etcd-io/etcd/blob/main/CHANGELOG-3.x.md). +Previous change logs can be found at [CHANGELOG-3.x](https://github.com/etcd-io/etcd/blob/main/CHANGELOG/CHANGELOG-3.x.md). The minimum recommended etcd versions to run in **production** are 3.2.28+, 3.3.18+, and 3.4.2+. From e65b64ad3684505ac3eb45aedd0e046768d20440 Mon Sep 17 00:00:00 2001 From: Marek Siarkowicz Date: Wed, 26 Jan 2022 11:48:52 +0100 Subject: [PATCH 094/258] Remove .travis.yaml --- .travis.yml | 51 --------------------------------------------------- 1 file changed, 51 deletions(-) delete mode 100644 .travis.yml diff --git a/.travis.yml b/.travis.yml deleted file mode 100644 index 9f4d26bfb721..000000000000 --- a/.travis.yml +++ /dev/null @@ -1,51 +0,0 @@ -language: go -go_import_path: go.etcd.io/etcd/v3 - -sudo: required - -services: docker - -go: - - "1.17.6" - - tip - -notifications: - on_success: never - on_failure: never - -env: - matrix: - - TARGET=linux-amd64-coverage - - TARGET=linux-amd64-fmt-unit-go-tip-2-cpu - -matrix: - fast_finish: true - allow_failures: - - go: "1.17.6" - env: TARGET=linux-amd64-coverage - - go: tip - env: TARGET=linux-amd64-fmt-unit-go-tip-2-cpu - exclude: - - go: tip - env: TARGET=linux-amd64-coverage - - go: "1.17.6" - env: TARGET=linux-amd64-fmt-unit-go-tip-2-cpu - -before_install: - - if [[ $TRAVIS_GO_VERSION == 1.* ]]; then docker pull gcr.io/etcd-development/etcd-test:go${TRAVIS_GO_VERSION}; fi - -install: - - date - -script: - - date - - echo "TRAVIS_GO_VERSION=${TRAVIS_GO_VERSION}" - - > - case "${TARGET}" in - linux-amd64-coverage) - sudo HOST_TMP_DIR=/tmp TEST_OPTS="VERBOSE='1'" make docker-test-coverage - ;; - linux-amd64-fmt-unit-go-tip-2-cpu) - GOARCH=amd64 PASSES='fmt unit' CPU='2' RACE='false' ./test.sh -p=2 - ;; - esac From 178bfc5a5ad20a6d505e7a2a8cbf50d452269611 Mon Sep 17 00:00:00 2001 From: Marek Siarkowicz Date: Wed, 26 Jan 2022 12:00:27 +0100 Subject: [PATCH 095/258] Remove unused .words file --- .words | 116 --------------------------------------------------------- 1 file changed, 116 deletions(-) delete mode 100644 .words diff --git a/.words b/.words deleted file mode 100644 index da36ba44ba5a..000000000000 --- a/.words +++ /dev/null @@ -1,116 +0,0 @@ -accessors -addrConns -args -atomics -backoff -BackoffFunc -BackoffLinearWithJitter -Balancer -BidiStreams -blackhole -blackholed -CallOptions -cancelable -cancelation -ccBalancerWrapper -clientURLs -clusterName -cluster_proxy -consistentIndex -ConsistentIndexGetter -DefaultMaxRequestBytes -defragment -defragmenting -deleter -dev -/dev/null -dev/null -DNS -errClientDisconnected -ErrCodeEnhanceYourCalm -ErrConnClosing -ErrRequestTooLarge -ErrTimeout -etcd -FIXME -github -GoAway -goroutine -goroutines -gRPC -grpcAddr -hasleader -healthcheck -hostname -iff -inflight -InfoLevel -jitter -jitter -jitter -keepalive -Keepalive -KeepAlive -keepalives -keyspace -lexically -lexicographically -linearizable -linearization -linearized -liveness -localhost -__lostleader -MaxRequestBytes -MiB -middleware -mutators -mutex -nils -nondeterministically -nop -OutputWALDir -parsedTarget -passthrough -PermitWithoutStream -prefetching -prometheus -protobuf -racey -rafthttp -rebalanced -reconnection -repin -ResourceExhausted -retriable -retriable -rpc -RPC -RPCs -saveWALAndSnap -serializable -ServerStreams -SHA -SRV -statusError -subConn -subconns -SubConns -teardown -TestBalancerDoNotBlockOnClose -todo -too_many_pings -transactional -transferee -transientFailure -unbuffered -uncontended -unfreed -unlisting -unprefixed -WatchProgressNotifyInterval -WAL -WithBackoff -WithDialer -WithMax -WithRequireLeader From 2d336a11c8c7bfe7399faaebd0c4e9ff2e189b3c Mon Sep 17 00:00:00 2001 From: Marek Siarkowicz Date: Wed, 26 Jan 2022 15:24:15 +0100 Subject: [PATCH 096/258] Remove badge for disabled test suite --- README.md | 1 - 1 file changed, 1 deletion(-) diff --git a/README.md b/README.md index 27c8555bd1db..1f0e2503954b 100644 --- a/README.md +++ b/README.md @@ -5,7 +5,6 @@ [![Tests](https://github.com/etcd-io/etcd/actions/workflows/tests.yaml/badge.svg)](https://github.com/etcd-io/etcd/actions/workflows/tests.yaml) [![asset-transparency](https://github.com/etcd-io/etcd/actions/workflows/asset-transparency.yaml/badge.svg)](https://github.com/etcd-io/etcd/actions/workflows/asset-transparency.yaml) [![codeql-analysis](https://github.com/etcd-io/etcd/actions/workflows/codeql-analysis.yml/badge.svg)](https://github.com/etcd-io/etcd/actions/workflows/codeql-analysis.yml) -[![self-hosted-linux-arm64-graviton2-tests](https://github.com/etcd-io/etcd/actions/workflows/self-hosted-linux-arm64-graviton2-tests.yml/badge.svg)](https://github.com/etcd-io/etcd/actions/workflows/self-hosted-linux-arm64-graviton2-tests.yml) [![Docs](https://img.shields.io/badge/docs-latest-green.svg)](https://etcd.io/docs) [![Godoc](http://img.shields.io/badge/go-documentation-blue.svg?style=flat-square)](https://godoc.org/github.com/etcd-io/etcd) [![Releases](https://img.shields.io/github/release/etcd-io/etcd/all.svg?style=flat-square)](https://github.com/etcd-io/etcd/releases) From 6d808e5d7d1ba97a39f74129a72973bc2aaf7cf4 Mon Sep 17 00:00:00 2001 From: Marek Siarkowicz Date: Tue, 19 Oct 2021 18:00:48 +0200 Subject: [PATCH 097/258] *: Add static validation to etcd_version proto annotation --- .../apispec/swagger/rpc.swagger.json | 2 +- .../apispec/swagger/v3election.swagger.json | 2 +- .../apispec/swagger/v3lock.swagger.json | 2 +- api/etcdserverpb/rpc.pb.go | 552 +++++++++--------- go.mod | 4 +- scripts/etcd_version_annotations.txt | 543 +++++++++++++++++ scripts/update_proto_annotations.sh | 9 + scripts/verify_proto_annotations.sh | 18 + server/storage/wal/version.go | 27 +- server/storage/wal/version_test.go | 3 +- test.sh | 5 + tools/mod/libs.go | 1 + tools/mod/tools.go | 3 +- tools/proto-annotations/main.go | 215 +++++++ 14 files changed, 1093 insertions(+), 293 deletions(-) create mode 100644 scripts/etcd_version_annotations.txt create mode 100755 scripts/update_proto_annotations.sh create mode 100755 scripts/verify_proto_annotations.sh create mode 100644 tools/proto-annotations/main.go diff --git a/Documentation/dev-guide/apispec/swagger/rpc.swagger.json b/Documentation/dev-guide/apispec/swagger/rpc.swagger.json index 51b5e44db75d..07e4b33f52f9 100644 --- a/Documentation/dev-guide/apispec/swagger/rpc.swagger.json +++ b/Documentation/dev-guide/apispec/swagger/rpc.swagger.json @@ -2671,7 +2671,7 @@ "format": "uint64" }, "revision": { - "description": "revision is the key-value store revision when the request was applied.\nFor watch progress responses, the header.revision indicates progress. All future events\nrecieved in this stream are guaranteed to have a higher revision number than the\nheader.revision number.", + "description": "revision is the key-value store revision when the request was applied.\nFor watch progress responses, the header.revision indicates progress. All future events\nreceived in this stream are guaranteed to have a higher revision number than the\nheader.revision number.", "type": "string", "format": "int64" } diff --git a/Documentation/dev-guide/apispec/swagger/v3election.swagger.json b/Documentation/dev-guide/apispec/swagger/v3election.swagger.json index 3121774607e6..8322e0312226 100644 --- a/Documentation/dev-guide/apispec/swagger/v3election.swagger.json +++ b/Documentation/dev-guide/apispec/swagger/v3election.swagger.json @@ -203,7 +203,7 @@ "revision": { "type": "string", "format": "int64", - "description": "revision is the key-value store revision when the request was applied.\nFor watch progress responses, the header.revision indicates progress. All future events\nrecieved in this stream are guaranteed to have a higher revision number than the\nheader.revision number." + "description": "revision is the key-value store revision when the request was applied.\nFor watch progress responses, the header.revision indicates progress. All future events\nreceived in this stream are guaranteed to have a higher revision number than the\nheader.revision number." }, "raft_term": { "type": "string", diff --git a/Documentation/dev-guide/apispec/swagger/v3lock.swagger.json b/Documentation/dev-guide/apispec/swagger/v3lock.swagger.json index 20fe37715032..aac2bf3ec692 100644 --- a/Documentation/dev-guide/apispec/swagger/v3lock.swagger.json +++ b/Documentation/dev-guide/apispec/swagger/v3lock.swagger.json @@ -95,7 +95,7 @@ "revision": { "type": "string", "format": "int64", - "description": "revision is the key-value store revision when the request was applied.\nFor watch progress responses, the header.revision indicates progress. All future events\nrecieved in this stream are guaranteed to have a higher revision number than the\nheader.revision number." + "description": "revision is the key-value store revision when the request was applied.\nFor watch progress responses, the header.revision indicates progress. All future events\nreceived in this stream are guaranteed to have a higher revision number than the\nheader.revision number." }, "raft_term": { "type": "string", diff --git a/api/etcdserverpb/rpc.pb.go b/api/etcdserverpb/rpc.pb.go index 0e22aed72327..46a8889d1220 100644 --- a/api/etcdserverpb/rpc.pb.go +++ b/api/etcdserverpb/rpc.pb.go @@ -6166,282 +6166,282 @@ func init() { func init() { proto.RegisterFile("rpc.proto", fileDescriptor_77a6da22d6a3feb1) } var fileDescriptor_77a6da22d6a3feb1 = []byte{ - // 4394 bytes of a gzipped FileDescriptorProto - 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xc4, 0x3c, 0x4d, 0x6f, 0x24, 0x49, - 0x56, 0xce, 0xfa, 0x74, 0xbd, 0x2a, 0x97, 0xcb, 0xd1, 0xee, 0x9e, 0xea, 0x9a, 0x6e, 0xb7, 0x27, - 0x7b, 0x7a, 0xc6, 0xe3, 0x99, 0xb1, 0xbb, 0x6d, 0xf7, 0x0e, 0x34, 0x9a, 0x61, 0xab, 0xed, 0x9a, - 0xb6, 0x69, 0xb7, 0xed, 0x4d, 0x57, 0xf7, 0xec, 0x0c, 0xd2, 0x9a, 0x74, 0x55, 0xb4, 0x9d, 0xeb, - 0xaa, 0xcc, 0xda, 0xcc, 0x2c, 0xb7, 0xbd, 0x1c, 0x76, 0x59, 0x58, 0x56, 0x0b, 0xd2, 0x4a, 0x2c, - 0x12, 0x5a, 0x21, 0xb8, 0x20, 0x24, 0x38, 0x00, 0x82, 0x03, 0x07, 0xc4, 0x81, 0x03, 0x1c, 0xe0, - 0x80, 0x84, 0xc4, 0x1f, 0x80, 0x61, 0x4f, 0xfc, 0x05, 0x24, 0xb4, 0x8a, 0xaf, 0x8c, 0xc8, 0xcc, - 0x28, 0xdb, 0xb3, 0xf6, 0x68, 0x2f, 0xd3, 0x95, 0x11, 0xef, 0x2b, 0xde, 0x8b, 0xf7, 0x5e, 0xc4, - 0x7b, 0xe1, 0x81, 0x92, 0x3f, 0xe8, 0x2c, 0x0c, 0x7c, 0x2f, 0xf4, 0x50, 0x05, 0x87, 0x9d, 0x6e, - 0x80, 0xfd, 0x63, 0xec, 0x0f, 0xf6, 0x1b, 0xd3, 0x07, 0xde, 0x81, 0x47, 0x27, 0x16, 0xc9, 0x2f, - 0x06, 0xd3, 0xa8, 0x13, 0x98, 0x45, 0x7b, 0xe0, 0x2c, 0xf6, 0x8f, 0x3b, 0x9d, 0xc1, 0xfe, 0xe2, - 0xd1, 0x31, 0x9f, 0x69, 0x44, 0x33, 0xf6, 0x30, 0x3c, 0x1c, 0xec, 0xd3, 0x7f, 0xf8, 0xdc, 0x6c, - 0x34, 0x77, 0x8c, 0xfd, 0xc0, 0xf1, 0xdc, 0xc1, 0xbe, 0xf8, 0xc5, 0x21, 0x6e, 0x1d, 0x78, 0xde, - 0x41, 0x0f, 0x33, 0x7c, 0xd7, 0xf5, 0x42, 0x3b, 0x74, 0x3c, 0x37, 0x60, 0xb3, 0xe6, 0x8f, 0x0c, - 0xa8, 0x5a, 0x38, 0x18, 0x78, 0x6e, 0x80, 0xd7, 0xb1, 0xdd, 0xc5, 0x3e, 0xba, 0x0d, 0xd0, 0xe9, - 0x0d, 0x83, 0x10, 0xfb, 0x7b, 0x4e, 0xb7, 0x6e, 0xcc, 0x1a, 0x73, 0x39, 0xab, 0xc4, 0x47, 0x36, - 0xba, 0xe8, 0x75, 0x28, 0xf5, 0x71, 0x7f, 0x9f, 0xcd, 0x66, 0xe8, 0xec, 0x38, 0x1b, 0xd8, 0xe8, - 0xa2, 0x06, 0x8c, 0xfb, 0xf8, 0xd8, 0x21, 0xec, 0xeb, 0xd9, 0x59, 0x63, 0x2e, 0x6b, 0x45, 0xdf, - 0x04, 0xd1, 0xb7, 0x5f, 0x86, 0x7b, 0x21, 0xf6, 0xfb, 0xf5, 0x1c, 0x43, 0x24, 0x03, 0x6d, 0xec, - 0xf7, 0x1f, 0x15, 0xbf, 0xf7, 0xf7, 0xf5, 0xec, 0xf2, 0xc2, 0x7d, 0xf3, 0x9f, 0xf3, 0x50, 0xb1, - 0x6c, 0xf7, 0x00, 0x5b, 0xf8, 0x5b, 0x43, 0x1c, 0x84, 0xa8, 0x06, 0xd9, 0x23, 0x7c, 0x4a, 0xe5, - 0xa8, 0x58, 0xe4, 0x27, 0x23, 0xe4, 0x1e, 0xe0, 0x3d, 0xec, 0x32, 0x09, 0x2a, 0x84, 0x90, 0x7b, - 0x80, 0x5b, 0x6e, 0x17, 0x4d, 0x43, 0xbe, 0xe7, 0xf4, 0x9d, 0x90, 0xb3, 0x67, 0x1f, 0x31, 0xb9, - 0x72, 0x09, 0xb9, 0x56, 0x01, 0x02, 0xcf, 0x0f, 0xf7, 0x3c, 0xbf, 0x8b, 0xfd, 0x7a, 0x7e, 0xd6, - 0x98, 0xab, 0x2e, 0xbd, 0xb9, 0xa0, 0x5a, 0x6c, 0x41, 0x15, 0x68, 0x61, 0xd7, 0xf3, 0xc3, 0x6d, - 0x02, 0x6b, 0x95, 0x02, 0xf1, 0x13, 0x7d, 0x0c, 0x65, 0x4a, 0x24, 0xb4, 0xfd, 0x03, 0x1c, 0xd6, - 0x0b, 0x94, 0xca, 0xbd, 0x73, 0xa8, 0xb4, 0x29, 0xb0, 0x45, 0xd9, 0xb3, 0xdf, 0xc8, 0x84, 0x4a, - 0x80, 0x7d, 0xc7, 0xee, 0x39, 0xdf, 0xb6, 0xf7, 0x7b, 0xb8, 0x5e, 0x9c, 0x35, 0xe6, 0xc6, 0xad, - 0xd8, 0x18, 0x59, 0xff, 0x11, 0x3e, 0x0d, 0xf6, 0x3c, 0xb7, 0x77, 0x5a, 0x1f, 0xa7, 0x00, 0xe3, - 0x64, 0x60, 0xdb, 0xed, 0x9d, 0x52, 0xeb, 0x79, 0x43, 0x37, 0x64, 0xb3, 0x25, 0x3a, 0x5b, 0xa2, - 0x23, 0x74, 0xfa, 0x01, 0xd4, 0xfa, 0x8e, 0xbb, 0xd7, 0xf7, 0xba, 0x7b, 0x91, 0x42, 0x80, 0x28, - 0xe4, 0x71, 0xf1, 0xf7, 0xa8, 0x05, 0x1e, 0x58, 0xd5, 0xbe, 0xe3, 0x3e, 0xf3, 0xba, 0x96, 0xd0, - 0x0f, 0x41, 0xb1, 0x4f, 0xe2, 0x28, 0xe5, 0x24, 0x8a, 0x7d, 0xa2, 0xa2, 0x7c, 0x00, 0xd7, 0x08, - 0x97, 0x8e, 0x8f, 0xed, 0x10, 0x4b, 0xac, 0x4a, 0x1c, 0x6b, 0xaa, 0xef, 0xb8, 0xab, 0x14, 0x24, - 0x86, 0x68, 0x9f, 0xa4, 0x10, 0x27, 0x92, 0x88, 0xf6, 0x49, 0x1c, 0xd1, 0xfc, 0x00, 0x4a, 0x91, - 0x5d, 0xd0, 0x38, 0xe4, 0xb6, 0xb6, 0xb7, 0x5a, 0xb5, 0x31, 0x04, 0x50, 0x68, 0xee, 0xae, 0xb6, - 0xb6, 0xd6, 0x6a, 0x06, 0x2a, 0x43, 0x71, 0xad, 0xc5, 0x3e, 0x32, 0x8d, 0xe2, 0x8f, 0xf9, 0x7e, - 0x7b, 0x0a, 0x20, 0x4d, 0x81, 0x8a, 0x90, 0x7d, 0xda, 0xfa, 0xb4, 0x36, 0x46, 0x80, 0x5f, 0xb4, - 0xac, 0xdd, 0x8d, 0xed, 0xad, 0x9a, 0x41, 0xa8, 0xac, 0x5a, 0xad, 0x66, 0xbb, 0x55, 0xcb, 0x10, - 0x88, 0x67, 0xdb, 0x6b, 0xb5, 0x2c, 0x2a, 0x41, 0xfe, 0x45, 0x73, 0xf3, 0x79, 0xab, 0x96, 0x8b, - 0x88, 0xc9, 0x5d, 0xfc, 0x27, 0x06, 0x4c, 0x70, 0x73, 0x33, 0xdf, 0x42, 0x2b, 0x50, 0x38, 0xa4, - 0xfe, 0x45, 0x77, 0x72, 0x79, 0xe9, 0x56, 0x62, 0x6f, 0xc4, 0x7c, 0xd0, 0xe2, 0xb0, 0xc8, 0x84, - 0xec, 0xd1, 0x71, 0x50, 0xcf, 0xcc, 0x66, 0xe7, 0xca, 0x4b, 0xb5, 0x05, 0x16, 0x19, 0x16, 0x9e, - 0xe2, 0xd3, 0x17, 0x76, 0x6f, 0x88, 0x2d, 0x32, 0x89, 0x10, 0xe4, 0xfa, 0x9e, 0x8f, 0xe9, 0x86, - 0x1f, 0xb7, 0xe8, 0x6f, 0xe2, 0x05, 0xd4, 0xe6, 0x7c, 0xb3, 0xb3, 0x0f, 0x29, 0xde, 0xbf, 0x1b, - 0x00, 0x3b, 0xc3, 0x70, 0xb4, 0x8b, 0x4d, 0x43, 0xfe, 0x98, 0x70, 0xe0, 0xee, 0xc5, 0x3e, 0xa8, - 0x6f, 0x61, 0x3b, 0xc0, 0x91, 0x6f, 0x91, 0x0f, 0x34, 0x0b, 0xc5, 0x81, 0x8f, 0x8f, 0xf7, 0x8e, - 0x8e, 0x29, 0xb7, 0x71, 0x69, 0xa7, 0x02, 0x19, 0x7f, 0x7a, 0x8c, 0xe6, 0xa1, 0xe2, 0x1c, 0xb8, - 0x9e, 0x8f, 0xf7, 0x18, 0xd1, 0xbc, 0x0a, 0xb6, 0x64, 0x95, 0xd9, 0x24, 0x5d, 0x92, 0x02, 0xcb, - 0x58, 0x15, 0xb4, 0xb0, 0x9b, 0x64, 0x4e, 0xae, 0xe7, 0xbb, 0x06, 0x94, 0xe9, 0x7a, 0x2e, 0xa5, - 0xec, 0x25, 0xb9, 0x90, 0x0c, 0x45, 0x4b, 0x29, 0x3c, 0xb5, 0x34, 0x29, 0x82, 0x0b, 0x68, 0x0d, - 0xf7, 0x70, 0x88, 0x2f, 0x13, 0xbc, 0x14, 0x55, 0x66, 0xb5, 0xaa, 0x94, 0xfc, 0xfe, 0xdc, 0x80, - 0x6b, 0x31, 0x86, 0x97, 0x5a, 0x7a, 0x1d, 0x8a, 0x5d, 0x4a, 0x8c, 0xc9, 0x94, 0xb5, 0xc4, 0x27, - 0x5a, 0x81, 0x71, 0x2e, 0x52, 0x50, 0xcf, 0xea, 0xb7, 0xa1, 0x94, 0xb2, 0xc8, 0xa4, 0x0c, 0xa4, - 0x98, 0xff, 0x98, 0x81, 0x12, 0x57, 0xc6, 0xf6, 0x00, 0x35, 0x61, 0xc2, 0x67, 0x1f, 0x7b, 0x74, - 0xcd, 0x5c, 0xc6, 0xc6, 0xe8, 0x38, 0xb9, 0x3e, 0x66, 0x55, 0x38, 0x0a, 0x1d, 0x46, 0xbf, 0x02, - 0x65, 0x41, 0x62, 0x30, 0x0c, 0xb9, 0xa1, 0xea, 0x71, 0x02, 0x72, 0x6b, 0xaf, 0x8f, 0x59, 0xc0, - 0xc1, 0x77, 0x86, 0x21, 0x6a, 0xc3, 0xb4, 0x40, 0x66, 0xeb, 0xe3, 0x62, 0x64, 0x29, 0x95, 0xd9, - 0x38, 0x95, 0xb4, 0x39, 0xd7, 0xc7, 0x2c, 0xc4, 0xf1, 0x95, 0x49, 0xb4, 0x26, 0x45, 0x0a, 0x4f, - 0x58, 0x7e, 0x49, 0x89, 0xd4, 0x3e, 0x71, 0x39, 0x11, 0xa1, 0xad, 0x65, 0x45, 0xb6, 0xf6, 0x89, - 0x1b, 0xa9, 0xec, 0x71, 0x09, 0x8a, 0x7c, 0xd8, 0xfc, 0xb7, 0x0c, 0x80, 0xb0, 0xd8, 0xf6, 0x00, - 0xad, 0x41, 0xd5, 0xe7, 0x5f, 0x31, 0xfd, 0xbd, 0xae, 0xd5, 0x1f, 0x37, 0xf4, 0x98, 0x35, 0x21, - 0x90, 0x98, 0xb8, 0x1f, 0x41, 0x25, 0xa2, 0x22, 0x55, 0x78, 0x53, 0xa3, 0xc2, 0x88, 0x42, 0x59, - 0x20, 0x10, 0x25, 0x7e, 0x02, 0xd7, 0x23, 0x7c, 0x8d, 0x16, 0xdf, 0x38, 0x43, 0x8b, 0x11, 0xc1, - 0x6b, 0x82, 0x82, 0xaa, 0xc7, 0x27, 0x8a, 0x60, 0x52, 0x91, 0x37, 0x35, 0x8a, 0x64, 0x40, 0xaa, - 0x26, 0x23, 0x09, 0x63, 0xaa, 0x04, 0x92, 0xf6, 0xd9, 0xb8, 0xf9, 0x97, 0x39, 0x28, 0xae, 0x7a, - 0xfd, 0x81, 0xed, 0x93, 0x4d, 0x54, 0xf0, 0x71, 0x30, 0xec, 0x85, 0x54, 0x81, 0xd5, 0xa5, 0xbb, - 0x71, 0x1e, 0x1c, 0x4c, 0xfc, 0x6b, 0x51, 0x50, 0x8b, 0xa3, 0x10, 0x64, 0x9e, 0xe5, 0x33, 0x17, - 0x40, 0xe6, 0x39, 0x9e, 0xa3, 0x88, 0x80, 0x90, 0x95, 0x01, 0xa1, 0x01, 0x45, 0x7e, 0x60, 0x63, - 0xc1, 0x7a, 0x7d, 0xcc, 0x12, 0x03, 0xe8, 0x1d, 0x98, 0x4c, 0xa6, 0xc2, 0x3c, 0x87, 0xa9, 0x76, - 0xe2, 0x99, 0xf3, 0x2e, 0x54, 0x62, 0x19, 0xba, 0xc0, 0xe1, 0xca, 0x7d, 0x25, 0x2f, 0xdf, 0x10, - 0x61, 0x9d, 0x1c, 0x2b, 0x2a, 0xeb, 0x63, 0x22, 0xb0, 0xdf, 0x11, 0x81, 0x7d, 0x5c, 0x4d, 0xb4, - 0x44, 0xaf, 0x3c, 0xc6, 0xbf, 0xa9, 0x46, 0xad, 0xaf, 0x12, 0xe4, 0x08, 0x48, 0x86, 0x2f, 0xd3, - 0x82, 0x89, 0x98, 0xca, 0x48, 0x8e, 0x6c, 0x7d, 0xed, 0x79, 0x73, 0x93, 0x25, 0xd4, 0x27, 0x34, - 0x87, 0x5a, 0x35, 0x83, 0x24, 0xe8, 0xcd, 0xd6, 0xee, 0x6e, 0x2d, 0x83, 0x6e, 0x40, 0x69, 0x6b, - 0xbb, 0xbd, 0xc7, 0xa0, 0xb2, 0x8d, 0xe2, 0x1f, 0xb3, 0x48, 0x22, 0xf3, 0xf3, 0xa7, 0x11, 0x4d, - 0x9e, 0xa2, 0x95, 0xcc, 0x3c, 0xa6, 0x64, 0x66, 0x43, 0x64, 0xe6, 0x8c, 0xcc, 0xcc, 0x59, 0x84, - 0x20, 0xbf, 0xd9, 0x6a, 0xee, 0xd2, 0x24, 0xcd, 0x48, 0x2f, 0xa7, 0xb3, 0xf5, 0xe3, 0x2a, 0x54, - 0x98, 0x79, 0xf6, 0x86, 0x2e, 0x39, 0x4c, 0xfc, 0x95, 0x01, 0x20, 0x1d, 0x16, 0x2d, 0x42, 0xb1, - 0xc3, 0x44, 0xa8, 0x1b, 0x34, 0x02, 0x5e, 0xd7, 0x5a, 0xdc, 0x12, 0x50, 0xe8, 0x01, 0x14, 0x83, - 0x61, 0xa7, 0x83, 0x03, 0x91, 0xb9, 0x5f, 0x4b, 0x06, 0x61, 0x1e, 0x10, 0x2d, 0x01, 0x47, 0x50, - 0x5e, 0xda, 0x4e, 0x6f, 0x48, 0xf3, 0xf8, 0xd9, 0x28, 0x1c, 0x4e, 0xc6, 0xd8, 0x3f, 0x33, 0xa0, - 0xac, 0xb8, 0xc5, 0xcf, 0x99, 0x02, 0x6e, 0x41, 0x89, 0x0a, 0x83, 0xbb, 0x3c, 0x09, 0x8c, 0x5b, - 0x72, 0x00, 0x7d, 0x05, 0x4a, 0xc2, 0x93, 0x44, 0x1e, 0xa8, 0xeb, 0xc9, 0x6e, 0x0f, 0x2c, 0x09, - 0x2a, 0x85, 0x6c, 0xc3, 0x14, 0xd5, 0x53, 0x87, 0xdc, 0x3e, 0x84, 0x66, 0xd5, 0x63, 0xb9, 0x91, - 0x38, 0x96, 0x37, 0x60, 0x7c, 0x70, 0x78, 0x1a, 0x38, 0x1d, 0xbb, 0xc7, 0xc5, 0x89, 0xbe, 0x25, - 0xd5, 0x5d, 0x40, 0x2a, 0xd5, 0xcb, 0x28, 0x40, 0x12, 0xbd, 0x01, 0xe5, 0x75, 0x3b, 0x38, 0xe4, - 0x42, 0xca, 0xf1, 0x15, 0x98, 0x20, 0xe3, 0x4f, 0x5f, 0x5c, 0x40, 0x7c, 0x81, 0xb5, 0x4c, 0x6f, - 0x58, 0x02, 0xed, 0x52, 0x06, 0x42, 0x90, 0x3b, 0xb4, 0x83, 0x43, 0xaa, 0x8c, 0x09, 0x8b, 0xfe, - 0x46, 0xef, 0x40, 0xad, 0xc3, 0xd6, 0xbf, 0x97, 0xb8, 0x77, 0x4d, 0xf2, 0x71, 0x2b, 0x25, 0x90, - 0x0d, 0x15, 0xb6, 0xbc, 0xab, 0x96, 0x46, 0x6a, 0xaa, 0x01, 0x93, 0xbb, 0xae, 0x3d, 0x08, 0x0e, - 0xbd, 0x30, 0xa1, 0xc5, 0x65, 0xf3, 0xef, 0x0c, 0xa8, 0xc9, 0xc9, 0x4b, 0xc9, 0xf0, 0x36, 0x4c, - 0xfa, 0xb8, 0x6f, 0x3b, 0xae, 0xe3, 0x1e, 0xec, 0xed, 0x9f, 0x86, 0x38, 0xe0, 0x17, 0xd2, 0x6a, - 0x34, 0xfc, 0x98, 0x8c, 0x12, 0x61, 0xf7, 0x7b, 0xde, 0x3e, 0x0f, 0xbb, 0xf4, 0x37, 0x7a, 0x23, - 0x1e, 0x77, 0x4b, 0x22, 0xa0, 0x7d, 0x25, 0x0a, 0xbf, 0x52, 0xe6, 0x9f, 0x64, 0xa0, 0xf2, 0x89, - 0x1d, 0x76, 0xc4, 0x9e, 0x40, 0x1b, 0x50, 0x8d, 0x02, 0x33, 0x1d, 0xe1, 0x72, 0x27, 0x8e, 0x10, - 0x14, 0x47, 0xdc, 0x54, 0xc4, 0x11, 0x62, 0xa2, 0xa3, 0x0e, 0x50, 0x52, 0xb6, 0xdb, 0xc1, 0xbd, - 0x88, 0x54, 0x66, 0x34, 0x29, 0x0a, 0xa8, 0x92, 0x52, 0x07, 0xd0, 0xd7, 0xa1, 0x36, 0xf0, 0xbd, - 0x03, 0x1f, 0x07, 0x41, 0x44, 0x8c, 0x25, 0x65, 0x53, 0x43, 0x6c, 0x87, 0x83, 0x26, 0xce, 0x25, - 0x2b, 0xeb, 0x63, 0xd6, 0xe4, 0x20, 0x3e, 0x27, 0x43, 0xe5, 0xa4, 0x3c, 0xc1, 0xb1, 0x58, 0xf9, - 0x83, 0x2c, 0xa0, 0xf4, 0x32, 0xbf, 0xe8, 0xc1, 0xf7, 0x1e, 0x54, 0x83, 0xd0, 0xf6, 0x53, 0xbb, - 0x78, 0x82, 0x8e, 0x46, 0xf9, 0xeb, 0x6d, 0x88, 0x24, 0xdb, 0x73, 0xbd, 0xd0, 0x79, 0x79, 0xca, - 0xae, 0x1c, 0x56, 0x55, 0x0c, 0x6f, 0xd1, 0x51, 0xb4, 0x05, 0xc5, 0x97, 0x4e, 0x2f, 0xc4, 0x7e, - 0x50, 0xcf, 0xcf, 0x66, 0xe7, 0xaa, 0x4b, 0xef, 0x9e, 0x67, 0x98, 0x85, 0x8f, 0x29, 0x7c, 0xfb, - 0x74, 0xa0, 0x9e, 0x67, 0x39, 0x11, 0xf5, 0x60, 0x5e, 0xd0, 0xdf, 0x71, 0x4c, 0x18, 0x7f, 0x45, - 0x88, 0xee, 0x39, 0x5d, 0x9a, 0x5d, 0xa3, 0x2c, 0xba, 0x62, 0x15, 0xe9, 0xc4, 0x46, 0x17, 0xdd, - 0x85, 0xf1, 0x97, 0xbe, 0x7d, 0xd0, 0xc7, 0x6e, 0xc8, 0xee, 0xed, 0x12, 0x26, 0x9a, 0x30, 0x17, - 0x00, 0xa4, 0x28, 0x24, 0x97, 0x6d, 0x6d, 0xef, 0x3c, 0x6f, 0xd7, 0xc6, 0x50, 0x05, 0xc6, 0xb7, - 0xb6, 0xd7, 0x5a, 0x9b, 0x2d, 0x92, 0xed, 0x44, 0x16, 0x7b, 0x20, 0x9d, 0xae, 0x29, 0x0c, 0x11, - 0xdb, 0x13, 0xaa, 0x5c, 0x46, 0xfc, 0x1a, 0x2d, 0xe4, 0x12, 0x24, 0x1e, 0x98, 0x77, 0x60, 0x5a, - 0xb7, 0x35, 0x04, 0xc0, 0x8a, 0xf9, 0x2f, 0x19, 0x98, 0xe0, 0x8e, 0x70, 0x29, 0xcf, 0xbd, 0xa9, - 0x48, 0xc5, 0x2f, 0x1c, 0x42, 0x49, 0x75, 0x28, 0x32, 0x07, 0xe9, 0xf2, 0x1b, 0xad, 0xf8, 0x24, - 0xe1, 0x96, 0xed, 0x77, 0xdc, 0xe5, 0x66, 0x8f, 0xbe, 0xb5, 0x81, 0x30, 0xaf, 0x0d, 0x84, 0xe8, - 0x3d, 0x98, 0x88, 0x1c, 0xce, 0x0e, 0xf8, 0x51, 0xa9, 0x24, 0x4d, 0x51, 0x11, 0x4e, 0x45, 0x26, - 0x63, 0x36, 0x2b, 0x8e, 0xb0, 0x19, 0xba, 0x07, 0x05, 0x7c, 0x8c, 0xdd, 0x30, 0xa8, 0x97, 0x69, - 0x6a, 0x9c, 0x10, 0x57, 0xa4, 0x16, 0x19, 0xb5, 0xf8, 0xa4, 0x34, 0xd5, 0x47, 0x30, 0x45, 0x6f, - 0xb0, 0x4f, 0x7c, 0xdb, 0x55, 0x6f, 0xe1, 0xed, 0xf6, 0x26, 0x4f, 0x24, 0xe4, 0x27, 0xaa, 0x42, - 0x66, 0x63, 0x8d, 0xeb, 0x27, 0xb3, 0xb1, 0x26, 0xf1, 0x7f, 0xdf, 0x00, 0xa4, 0x12, 0xb8, 0x94, - 0x2d, 0x12, 0x5c, 0x84, 0x1c, 0x59, 0x29, 0xc7, 0x34, 0xe4, 0xb1, 0xef, 0x7b, 0x3e, 0x0b, 0x94, - 0x16, 0xfb, 0x90, 0xd2, 0xbc, 0xcf, 0x85, 0xb1, 0xf0, 0xb1, 0x77, 0x14, 0x45, 0x00, 0x46, 0xd6, - 0x48, 0x0b, 0xdf, 0x86, 0x6b, 0x31, 0xf0, 0xab, 0x49, 0xda, 0xdb, 0x30, 0x49, 0xa9, 0xae, 0x1e, - 0xe2, 0xce, 0xd1, 0xc0, 0x73, 0xdc, 0x94, 0x04, 0xe8, 0x2e, 0x89, 0x5d, 0x22, 0x5d, 0x90, 0x25, - 0xb2, 0x35, 0x57, 0xa2, 0xc1, 0x76, 0x7b, 0x53, 0x6e, 0xf5, 0x7d, 0xb8, 0x91, 0x20, 0x28, 0x56, - 0xf6, 0xab, 0x50, 0xee, 0x44, 0x83, 0x01, 0x3f, 0x13, 0xde, 0x8e, 0x8b, 0x9b, 0x44, 0x55, 0x31, - 0x24, 0x8f, 0xaf, 0xc3, 0x6b, 0x29, 0x1e, 0x57, 0xa1, 0x8e, 0x15, 0xf3, 0x3e, 0x5c, 0xa7, 0x94, - 0x9f, 0x62, 0x3c, 0x68, 0xf6, 0x9c, 0xe3, 0xf3, 0xcd, 0x72, 0xca, 0xd7, 0xab, 0x60, 0x7c, 0xb9, - 0xdb, 0x4a, 0xb2, 0x6e, 0x71, 0xd6, 0x6d, 0xa7, 0x8f, 0xdb, 0xde, 0xe6, 0x68, 0x69, 0x49, 0x22, - 0x3f, 0xc2, 0xa7, 0x01, 0x3f, 0x10, 0xd2, 0xdf, 0x32, 0x7a, 0xfd, 0x8d, 0xc1, 0xd5, 0xa9, 0xd2, - 0xf9, 0x92, 0x5d, 0x63, 0x06, 0xe0, 0x80, 0xf8, 0x20, 0xee, 0x92, 0x09, 0x56, 0x6d, 0x53, 0x46, - 0x22, 0x81, 0x49, 0x16, 0xaa, 0x24, 0x05, 0xbe, 0xcd, 0x1d, 0x87, 0xfe, 0x27, 0x48, 0x9d, 0x94, - 0xde, 0x82, 0x32, 0x9d, 0xd9, 0x0d, 0xed, 0x70, 0x18, 0x8c, 0xb2, 0xdc, 0xb2, 0xf9, 0x03, 0x83, - 0x7b, 0x94, 0xa0, 0x73, 0xa9, 0x35, 0x3f, 0x80, 0x02, 0xbd, 0xf3, 0x89, 0xbb, 0xcb, 0x4d, 0xcd, - 0xc6, 0x66, 0x12, 0x59, 0x1c, 0x50, 0x39, 0x27, 0x19, 0x50, 0x78, 0x46, 0x7b, 0x01, 0x8a, 0xb4, - 0x39, 0x61, 0x39, 0xd7, 0xee, 0xb3, 0x82, 0x62, 0xc9, 0xa2, 0xbf, 0xe9, 0x11, 0x1f, 0x63, 0xff, - 0xb9, 0xb5, 0xc9, 0xee, 0x14, 0x25, 0x2b, 0xfa, 0x26, 0x8a, 0xed, 0xf4, 0x1c, 0xec, 0x86, 0x74, - 0x36, 0x47, 0x67, 0x95, 0x11, 0x74, 0x0f, 0x4a, 0x4e, 0xb0, 0x89, 0x6d, 0xdf, 0xe5, 0x45, 0x7b, - 0x25, 0x30, 0xcb, 0x19, 0xb9, 0xc7, 0xbe, 0x01, 0x35, 0x26, 0x59, 0xb3, 0xdb, 0x55, 0xce, 0xef, - 0x11, 0x7f, 0x23, 0xc1, 0x3f, 0x46, 0x3f, 0x73, 0x3e, 0xfd, 0xbf, 0x35, 0x60, 0x4a, 0x61, 0x70, - 0x29, 0x13, 0xbc, 0x07, 0x05, 0xd6, 0x51, 0xe1, 0x47, 0xc1, 0xe9, 0x38, 0x16, 0x63, 0x63, 0x71, - 0x18, 0xb4, 0x00, 0x45, 0xf6, 0x4b, 0x5c, 0xcc, 0xf4, 0xe0, 0x02, 0x48, 0x8a, 0xbc, 0x00, 0xd7, - 0xf8, 0x1c, 0xee, 0x7b, 0x3a, 0x9f, 0xcb, 0xc5, 0x23, 0xc4, 0xf7, 0x0d, 0x98, 0x8e, 0x23, 0x5c, - 0x6a, 0x95, 0x8a, 0xdc, 0x99, 0x2f, 0x24, 0xf7, 0xaf, 0x09, 0xb9, 0x9f, 0x0f, 0xba, 0xca, 0x91, - 0x33, 0xb9, 0xe3, 0x54, 0xeb, 0x66, 0xe2, 0xd6, 0x95, 0xb4, 0x7e, 0x14, 0xad, 0x49, 0x10, 0xbb, - 0xd4, 0x9a, 0x3e, 0xb8, 0xd0, 0x9a, 0x94, 0x23, 0x58, 0x6a, 0x71, 0x1b, 0x62, 0x1b, 0x6d, 0x3a, - 0x41, 0x94, 0x71, 0xde, 0x85, 0x4a, 0xcf, 0x71, 0xb1, 0xed, 0xf3, 0xae, 0x90, 0xa1, 0xee, 0xc7, - 0x87, 0x56, 0x6c, 0x52, 0x92, 0xfa, 0x6d, 0x03, 0x90, 0x4a, 0xeb, 0x17, 0x63, 0xad, 0x45, 0xa1, - 0xe0, 0x1d, 0xdf, 0xeb, 0x7b, 0xe1, 0x79, 0xdb, 0x6c, 0xc5, 0xfc, 0x5d, 0x03, 0xae, 0x27, 0x30, - 0x7e, 0x11, 0x92, 0xaf, 0x98, 0xb7, 0x60, 0x6a, 0x0d, 0x8b, 0x33, 0x5e, 0xaa, 0x1a, 0xb0, 0x0b, - 0x48, 0x9d, 0xbd, 0x9a, 0x53, 0xcc, 0x2f, 0xc1, 0xd4, 0x33, 0xef, 0x98, 0x04, 0x72, 0x32, 0x2d, - 0xc3, 0x14, 0x2b, 0x4f, 0x45, 0xfa, 0x8a, 0xbe, 0x65, 0xe8, 0xdd, 0x05, 0xa4, 0x62, 0x5e, 0x85, - 0x38, 0xcb, 0xe6, 0x7f, 0x1b, 0x50, 0x69, 0xf6, 0x6c, 0xbf, 0x2f, 0x44, 0xf9, 0x08, 0x0a, 0xac, - 0xd6, 0xc2, 0x0b, 0xa7, 0x6f, 0xc5, 0xe9, 0xa9, 0xb0, 0xec, 0xa3, 0xc9, 0x2a, 0x33, 0x1c, 0x8b, - 0x2c, 0x85, 0xf7, 0x8a, 0xd7, 0x12, 0xbd, 0xe3, 0x35, 0xf4, 0x3e, 0xe4, 0x6d, 0x82, 0x42, 0xd3, - 0x6b, 0x35, 0x59, 0x00, 0xa3, 0xd4, 0xc8, 0x95, 0xc8, 0x62, 0x50, 0xe6, 0x87, 0x50, 0x56, 0x38, - 0xa0, 0x22, 0x64, 0x9f, 0xb4, 0xf8, 0x35, 0xa9, 0xb9, 0xda, 0xde, 0x78, 0xc1, 0x8a, 0x82, 0x55, - 0x80, 0xb5, 0x56, 0xf4, 0x9d, 0x49, 0x15, 0xff, 0x96, 0x4d, 0x9b, 0xd3, 0xe1, 0x79, 0x4b, 0x95, - 0xd0, 0x18, 0x25, 0x61, 0xe6, 0x22, 0x12, 0x4a, 0xab, 0xfe, 0x96, 0x01, 0x13, 0x5c, 0x35, 0x97, - 0x4d, 0xcd, 0x94, 0xf2, 0x88, 0xd4, 0xac, 0x2c, 0xc3, 0xe2, 0x80, 0x52, 0x86, 0x7f, 0x32, 0xa0, - 0xb6, 0xe6, 0xbd, 0x72, 0x0f, 0x7c, 0xbb, 0x1b, 0xf9, 0xe0, 0xc7, 0x09, 0x73, 0x2e, 0x24, 0x6a, - 0xf7, 0x09, 0x78, 0x39, 0x90, 0x30, 0x6b, 0x5d, 0xd6, 0x52, 0x58, 0x7e, 0x17, 0x9f, 0xe6, 0x57, - 0x61, 0x32, 0x81, 0x44, 0x0c, 0xf4, 0xa2, 0xb9, 0xb9, 0xb1, 0x46, 0x0c, 0x42, 0x2b, 0xb8, 0xad, - 0xad, 0xe6, 0xe3, 0xcd, 0x16, 0xef, 0xb3, 0x36, 0xb7, 0x56, 0x5b, 0x9b, 0xd2, 0x50, 0x0f, 0xc5, - 0x0a, 0x1e, 0x9a, 0x3d, 0x98, 0x52, 0x04, 0xba, 0x6c, 0xbb, 0x4b, 0x2f, 0xaf, 0xe4, 0x56, 0x87, - 0x09, 0x7e, 0xca, 0x49, 0x3a, 0xfe, 0xff, 0x65, 0xa0, 0x2a, 0xa6, 0xbe, 0x1c, 0x29, 0xd0, 0x0d, - 0x28, 0x74, 0xf7, 0x77, 0x9d, 0x6f, 0x8b, 0x4e, 0x2b, 0xff, 0x22, 0xe3, 0x3d, 0xc6, 0x87, 0xbd, - 0x9f, 0xe0, 0x5f, 0xe8, 0x16, 0x7b, 0x5a, 0xb1, 0xe1, 0x76, 0xf1, 0x09, 0x3d, 0x0c, 0xe5, 0x2c, - 0x39, 0x40, 0xcb, 0x94, 0xfc, 0x9d, 0x05, 0xbd, 0xeb, 0x2a, 0xef, 0x2e, 0xd0, 0x32, 0xd4, 0xc8, - 0xef, 0xe6, 0x60, 0xd0, 0x73, 0x70, 0x97, 0x11, 0x20, 0xd7, 0xdc, 0x9c, 0x3c, 0xed, 0xa4, 0x00, - 0xd0, 0x1d, 0x28, 0xd0, 0x2b, 0x60, 0x50, 0x1f, 0x27, 0x79, 0x55, 0x82, 0xf2, 0x61, 0xf4, 0x0e, - 0x94, 0x99, 0xc4, 0x1b, 0xee, 0xf3, 0x00, 0xd3, 0x57, 0x08, 0x4a, 0x3d, 0x44, 0x9d, 0x8b, 0x9f, - 0xb3, 0xe0, 0xfc, 0x73, 0xd6, 0x2d, 0x98, 0x6a, 0x0e, 0xc3, 0xc3, 0x96, 0x4b, 0x72, 0x5d, 0xca, - 0x36, 0xb7, 0x01, 0x91, 0xd9, 0x35, 0x27, 0xd0, 0x4e, 0x73, 0x64, 0xad, 0x61, 0x1f, 0x9a, 0x5b, - 0x70, 0x8d, 0xcc, 0x62, 0x37, 0x74, 0x3a, 0xca, 0xb9, 0x42, 0x9c, 0x5c, 0x8d, 0xc4, 0xc9, 0xd5, - 0x0e, 0x82, 0x57, 0x9e, 0xdf, 0xe5, 0xb6, 0x8b, 0xbe, 0x25, 0xb7, 0x7f, 0x30, 0x98, 0x34, 0xcf, - 0x83, 0xd8, 0xa9, 0xf3, 0x0b, 0xd2, 0x43, 0xbf, 0x0c, 0x45, 0x6f, 0x40, 0xdf, 0xec, 0xf0, 0x62, - 0xde, 0x8d, 0x05, 0xf6, 0x0e, 0x68, 0x81, 0x13, 0xde, 0x66, 0xb3, 0x4a, 0xc1, 0x89, 0xc3, 0xa3, - 0x45, 0xa8, 0x1e, 0xda, 0xc1, 0x21, 0xee, 0xee, 0x08, 0xe2, 0xb1, 0x52, 0xe7, 0x43, 0x2b, 0x31, - 0x2d, 0x65, 0x7f, 0x20, 0x45, 0x7f, 0x82, 0xc3, 0x33, 0x44, 0x57, 0xcb, 0xe3, 0xd7, 0x05, 0x0a, - 0xef, 0xea, 0x5d, 0x04, 0xeb, 0x87, 0x06, 0xdc, 0x16, 0x68, 0xab, 0x87, 0xb6, 0x7b, 0x80, 0x85, - 0x30, 0x3f, 0xaf, 0xbe, 0xd2, 0x8b, 0xce, 0x5e, 0x70, 0xd1, 0x4f, 0xa1, 0x1e, 0x2d, 0x9a, 0x16, - 0x56, 0xbc, 0x9e, 0xba, 0x88, 0x61, 0xc0, 0x1d, 0xbc, 0x64, 0xd1, 0xdf, 0x64, 0xcc, 0xf7, 0x7a, - 0xd1, 0x9d, 0x86, 0xfc, 0x96, 0xc4, 0x36, 0xe1, 0xa6, 0x20, 0xc6, 0x2b, 0x1d, 0x71, 0x6a, 0xa9, - 0x35, 0x9d, 0x49, 0x8d, 0xdb, 0x83, 0xd0, 0x38, 0x7b, 0x2b, 0x69, 0x51, 0xe2, 0x26, 0xa4, 0x5c, - 0x0c, 0x1d, 0x97, 0x19, 0xe6, 0x01, 0x44, 0x66, 0xe5, 0xf8, 0x99, 0x9a, 0x27, 0x24, 0xb5, 0xf3, - 0x7c, 0x0b, 0x90, 0xf9, 0xd4, 0x16, 0x18, 0xcd, 0x15, 0xc3, 0x4c, 0x24, 0x28, 0x51, 0xfb, 0x0e, - 0xf6, 0xfb, 0x4e, 0x10, 0x28, 0x7d, 0x22, 0x9d, 0xba, 0xde, 0x82, 0xdc, 0x00, 0xf3, 0x5c, 0x5c, - 0x5e, 0x42, 0xc2, 0x27, 0x14, 0x64, 0x3a, 0x2f, 0xd9, 0xf4, 0xe1, 0x8e, 0x60, 0xc3, 0x0c, 0xa2, - 0xe5, 0x93, 0x14, 0x53, 0x54, 0xb2, 0x33, 0x23, 0x2a, 0xd9, 0xd9, 0x78, 0x25, 0x3b, 0x76, 0x3e, - 0x54, 0x03, 0xd5, 0xd5, 0x9c, 0x0f, 0xdb, 0xcc, 0x00, 0x51, 0x7c, 0xbb, 0x1a, 0xaa, 0x7f, 0xc0, - 0x03, 0xd5, 0x55, 0x65, 0x35, 0x4c, 0xd7, 0x2c, 0xba, 0x88, 0xe2, 0x13, 0x99, 0x50, 0x21, 0x46, - 0xb2, 0xd4, 0x12, 0x7f, 0xce, 0x8a, 0x8d, 0xc9, 0x60, 0x7c, 0x04, 0xd3, 0xf1, 0x60, 0x7c, 0x29, - 0xa1, 0xa6, 0x21, 0x1f, 0x7a, 0x47, 0x58, 0x24, 0x5a, 0xf6, 0x91, 0x52, 0x6b, 0x14, 0xa8, 0xaf, - 0x46, 0xad, 0xdf, 0x94, 0x54, 0xa9, 0x03, 0x5e, 0x76, 0x05, 0x64, 0x3b, 0x8a, 0xab, 0x2c, 0xfb, - 0x90, 0xbc, 0x3e, 0x81, 0x1b, 0xc9, 0xe0, 0x7b, 0x35, 0x8b, 0xd8, 0x63, 0xce, 0xa9, 0x0b, 0xcf, - 0x57, 0xc3, 0xe0, 0x33, 0x19, 0x27, 0x95, 0xa0, 0x7b, 0x35, 0xb4, 0x7f, 0x1d, 0x1a, 0xba, 0x18, - 0x7c, 0xa5, 0xbe, 0x18, 0x85, 0xe4, 0xab, 0xa1, 0xfa, 0x7d, 0x43, 0x92, 0x55, 0x77, 0xcd, 0x87, - 0x5f, 0x84, 0xac, 0xc8, 0x75, 0xf7, 0xa3, 0xed, 0xb3, 0x18, 0x45, 0xcb, 0xac, 0x3e, 0x5a, 0x4a, - 0x14, 0x0a, 0x28, 0xfc, 0x4f, 0x86, 0xfa, 0x2f, 0x73, 0xf7, 0x72, 0x66, 0x32, 0xef, 0x5c, 0x96, - 0x19, 0x49, 0xcf, 0x11, 0x33, 0xfa, 0x91, 0x72, 0x15, 0x35, 0x49, 0x5d, 0x8d, 0xe9, 0x7e, 0x43, - 0x26, 0x98, 0x54, 0x1e, 0xbb, 0x1a, 0x0e, 0x36, 0xcc, 0x8e, 0x4e, 0x61, 0x57, 0xc2, 0x62, 0xbe, - 0x09, 0xa5, 0xe8, 0x22, 0xab, 0x3c, 0xa4, 0x2d, 0x43, 0x71, 0x6b, 0x7b, 0x77, 0xa7, 0xb9, 0x4a, - 0xee, 0x69, 0xd3, 0x50, 0x5c, 0xdd, 0xb6, 0xac, 0xe7, 0x3b, 0x6d, 0x72, 0x51, 0x4b, 0xbc, 0xab, - 0x59, 0x5e, 0xfa, 0x69, 0x16, 0x32, 0x4f, 0x5f, 0xa0, 0x4f, 0x21, 0xcf, 0xde, 0x75, 0x9d, 0xf1, - 0xbc, 0xaf, 0x71, 0xd6, 0xd3, 0x35, 0xf3, 0xb5, 0xef, 0xfd, 0xe7, 0x4f, 0xff, 0x30, 0x33, 0x65, - 0x56, 0x16, 0x8f, 0x97, 0x17, 0x8f, 0x8e, 0x17, 0x69, 0x92, 0x7d, 0x64, 0xcc, 0xa3, 0xaf, 0x41, - 0x76, 0x67, 0x18, 0xa2, 0x91, 0xcf, 0xfe, 0x1a, 0xa3, 0x5f, 0xb3, 0x99, 0xd7, 0x29, 0xd1, 0x49, - 0x13, 0x38, 0xd1, 0xc1, 0x30, 0x24, 0x24, 0xbf, 0x05, 0x65, 0xf5, 0x2d, 0xda, 0xb9, 0x6f, 0x01, - 0x1b, 0xe7, 0xbf, 0x73, 0x33, 0x6f, 0x53, 0x56, 0xaf, 0x99, 0x88, 0xb3, 0x62, 0xaf, 0xe5, 0xd4, - 0x55, 0xb4, 0x4f, 0x5c, 0x34, 0xf2, 0xa5, 0x60, 0x63, 0xf4, 0xd3, 0xb7, 0xd4, 0x2a, 0xc2, 0x13, - 0x97, 0x90, 0xfc, 0x26, 0x7f, 0xe3, 0xd6, 0x09, 0xd1, 0x1d, 0xcd, 0x23, 0x25, 0xf5, 0xf1, 0x4d, - 0x63, 0x76, 0x34, 0x00, 0x67, 0x72, 0x8b, 0x32, 0xb9, 0x61, 0x4e, 0x71, 0x26, 0x9d, 0x08, 0xe4, - 0x91, 0x31, 0xbf, 0xd4, 0x81, 0x3c, 0x6d, 0x05, 0xa3, 0xcf, 0xc4, 0x8f, 0x86, 0xa6, 0xc9, 0x3e, - 0xc2, 0xd0, 0xb1, 0x26, 0xb2, 0x39, 0x4d, 0x19, 0x55, 0xcd, 0x12, 0x61, 0x44, 0x1b, 0xc1, 0x8f, - 0x8c, 0xf9, 0x39, 0xe3, 0xbe, 0xb1, 0xf4, 0xd7, 0x79, 0xc8, 0xd3, 0x96, 0x03, 0x3a, 0x02, 0x90, - 0x2d, 0xcf, 0xe4, 0xea, 0x52, 0xdd, 0xd4, 0xe4, 0xea, 0xd2, 0xdd, 0x52, 0xb3, 0x41, 0x99, 0x4e, - 0x9b, 0x93, 0x84, 0x29, 0xed, 0x64, 0x2c, 0xd2, 0xc6, 0x0d, 0xd1, 0xe3, 0x0f, 0x0d, 0xde, 0x7b, - 0x61, 0x6e, 0x86, 0x74, 0xd4, 0x62, 0xed, 0xce, 0xe4, 0x76, 0xd0, 0x74, 0x38, 0xcd, 0x87, 0x94, - 0xe1, 0xa2, 0x59, 0x93, 0x0c, 0x7d, 0x0a, 0xf1, 0xc8, 0x98, 0xff, 0xac, 0x6e, 0x5e, 0xe3, 0x5a, - 0x4e, 0xcc, 0xa0, 0xef, 0x40, 0x35, 0xde, 0x98, 0x43, 0x77, 0x35, 0xbc, 0x92, 0x8d, 0xbe, 0xc6, - 0x9b, 0x67, 0x03, 0x71, 0x99, 0x66, 0xa8, 0x4c, 0x9c, 0x39, 0xe3, 0x7c, 0x84, 0xf1, 0xc0, 0x26, - 0x40, 0xdc, 0x06, 0xe8, 0x4f, 0x0d, 0xde, 0x5b, 0x95, 0x7d, 0x35, 0xa4, 0xa3, 0x9e, 0x6a, 0xdf, - 0x35, 0xee, 0x9d, 0x03, 0xc5, 0x85, 0xf8, 0x90, 0x0a, 0xf1, 0x81, 0x39, 0x2d, 0x85, 0x08, 0x9d, - 0x3e, 0x0e, 0x3d, 0x2e, 0xc5, 0x67, 0xb7, 0xcc, 0xd7, 0x62, 0xca, 0x89, 0xcd, 0x4a, 0x63, 0xb1, - 0xfe, 0x97, 0xd6, 0x58, 0xb1, 0x16, 0x9b, 0xd6, 0x58, 0xf1, 0xe6, 0x99, 0xce, 0x58, 0xbc, 0xdb, - 0xa5, 0x31, 0x56, 0x34, 0xb3, 0xf4, 0xbf, 0x39, 0x28, 0xae, 0xb2, 0xbf, 0x95, 0x41, 0x1e, 0x94, - 0xa2, 0x8e, 0x10, 0x9a, 0xd1, 0x15, 0x9d, 0xe5, 0x55, 0xae, 0x71, 0x67, 0xe4, 0x3c, 0x17, 0xe8, - 0x0d, 0x2a, 0xd0, 0xeb, 0xe6, 0x0d, 0xc2, 0x99, 0xff, 0x39, 0xce, 0x22, 0x2b, 0x4d, 0x2e, 0xda, - 0xdd, 0x2e, 0x51, 0xc4, 0x6f, 0x42, 0x45, 0xed, 0xcf, 0xa0, 0x37, 0xb4, 0x85, 0x6e, 0xb5, 0xd9, - 0xd3, 0x30, 0xcf, 0x02, 0xe1, 0x9c, 0xdf, 0xa4, 0x9c, 0x67, 0xcc, 0x9b, 0x1a, 0xce, 0x3e, 0x05, - 0x8d, 0x31, 0x67, 0x8d, 0x14, 0x3d, 0xf3, 0x58, 0xc7, 0x46, 0xcf, 0x3c, 0xde, 0x87, 0x39, 0x93, - 0xf9, 0x90, 0x82, 0x12, 0xe6, 0x01, 0x80, 0xec, 0x74, 0x20, 0xad, 0x2e, 0x95, 0x0b, 0x6b, 0x32, - 0x38, 0xa4, 0x9b, 0x24, 0xa6, 0x49, 0xd9, 0xf2, 0x7d, 0x97, 0x60, 0xdb, 0x73, 0x82, 0x90, 0x39, - 0xe6, 0x44, 0xac, 0x4f, 0x81, 0xb4, 0xeb, 0x89, 0xb7, 0x3d, 0x1a, 0x77, 0xcf, 0x84, 0xe1, 0xdc, - 0xef, 0x51, 0xee, 0x77, 0xcc, 0x86, 0x86, 0xfb, 0x80, 0xc1, 0x92, 0xcd, 0xf6, 0xff, 0x05, 0x28, - 0x3f, 0xb3, 0x1d, 0x37, 0xc4, 0xae, 0xed, 0x76, 0x30, 0xda, 0x87, 0x3c, 0xcd, 0xdd, 0xc9, 0x40, - 0xac, 0x96, 0xe5, 0x93, 0x81, 0x38, 0x56, 0x97, 0x36, 0x67, 0x29, 0xe3, 0x86, 0x79, 0x9d, 0x30, - 0xee, 0x4b, 0xd2, 0x8b, 0xac, 0xa2, 0x6d, 0xcc, 0xa3, 0x97, 0x50, 0xe0, 0xfd, 0xe8, 0x04, 0xa1, - 0x58, 0x51, 0xad, 0x71, 0x4b, 0x3f, 0xa9, 0xdb, 0xcb, 0x2a, 0x9b, 0x80, 0xc2, 0x11, 0x3e, 0xc7, - 0x00, 0xb2, 0xbd, 0x92, 0xb4, 0x68, 0xaa, 0x2d, 0xd3, 0x98, 0x1d, 0x0d, 0xa0, 0xd3, 0xa9, 0xca, - 0xb3, 0x1b, 0xc1, 0x12, 0xbe, 0xdf, 0x80, 0xdc, 0xba, 0x1d, 0x1c, 0xa2, 0x44, 0xee, 0x55, 0x1e, - 0x84, 0x36, 0x1a, 0xba, 0x29, 0xce, 0xe5, 0x0e, 0xe5, 0x72, 0x93, 0x85, 0x32, 0x95, 0x0b, 0x7d, - 0x20, 0x69, 0xcc, 0xa3, 0x2e, 0x14, 0xd8, 0x6b, 0xd0, 0xa4, 0xfe, 0x62, 0x4f, 0x4b, 0x93, 0xfa, - 0x8b, 0x3f, 0x20, 0x3d, 0x9f, 0xcb, 0x00, 0xc6, 0xc5, 0x1b, 0x4b, 0x94, 0x78, 0x99, 0x92, 0x78, - 0x98, 0xd9, 0x98, 0x19, 0x35, 0xcd, 0x79, 0xdd, 0xa5, 0xbc, 0x6e, 0x9b, 0xf5, 0x94, 0xad, 0x38, - 0xe4, 0x23, 0x63, 0xfe, 0xbe, 0x81, 0xbe, 0x03, 0x20, 0xfb, 0x4f, 0x29, 0x0f, 0x4c, 0xf6, 0xb4, - 0x52, 0x1e, 0x98, 0x6a, 0x5d, 0x99, 0x0b, 0x94, 0xef, 0x9c, 0x79, 0x37, 0xc9, 0x37, 0xf4, 0x6d, - 0x37, 0x78, 0x89, 0xfd, 0xf7, 0x59, 0xf1, 0x3b, 0x38, 0x74, 0x06, 0x64, 0xc9, 0x3e, 0x94, 0xa2, - 0xf6, 0x40, 0x32, 0xda, 0x26, 0x1b, 0x19, 0xc9, 0x68, 0x9b, 0xea, 0x2b, 0xc4, 0xc3, 0x4e, 0x6c, - 0xb7, 0x08, 0x50, 0xe2, 0x80, 0x7f, 0x51, 0x83, 0x1c, 0x39, 0x90, 0x93, 0xc3, 0x89, 0x2c, 0xf6, - 0x24, 0x57, 0x9f, 0xaa, 0x57, 0x27, 0x57, 0x9f, 0xae, 0x13, 0xc5, 0x0f, 0x27, 0xe4, 0xb2, 0xb6, - 0xc8, 0xaa, 0x28, 0x64, 0xa5, 0x1e, 0x94, 0x95, 0x22, 0x10, 0xd2, 0x10, 0x8b, 0xd7, 0xbf, 0x93, - 0xe9, 0x4e, 0x53, 0x41, 0x32, 0x5f, 0xa7, 0xfc, 0xae, 0xb3, 0x74, 0x47, 0xf9, 0x75, 0x19, 0x04, - 0x61, 0xc8, 0x57, 0xc7, 0xfd, 0x5e, 0xb3, 0xba, 0xb8, 0xef, 0xcf, 0x8e, 0x06, 0x18, 0xb9, 0x3a, - 0xe9, 0xf8, 0xaf, 0xa0, 0xa2, 0x16, 0x7e, 0x90, 0x46, 0xf8, 0x44, 0x85, 0x3e, 0x99, 0x47, 0x74, - 0x75, 0xa3, 0x78, 0x64, 0xa3, 0x2c, 0x6d, 0x05, 0x8c, 0x30, 0xee, 0x41, 0x91, 0x17, 0x80, 0x74, - 0x2a, 0x8d, 0x17, 0xf1, 0x75, 0x2a, 0x4d, 0x54, 0x8f, 0xe2, 0xa7, 0x67, 0xca, 0x91, 0x5c, 0x44, - 0x45, 0xae, 0xe6, 0xdc, 0x9e, 0xe0, 0x70, 0x14, 0x37, 0x59, 0xb4, 0x1d, 0xc5, 0x4d, 0xa9, 0x0f, - 0x8c, 0xe2, 0x76, 0x80, 0x43, 0x1e, 0x0f, 0xc4, 0xe5, 0x1a, 0x8d, 0x20, 0xa6, 0xe6, 0x47, 0xf3, - 0x2c, 0x10, 0xdd, 0xe5, 0x46, 0x32, 0x14, 0xc9, 0xf1, 0x04, 0x40, 0x16, 0xa3, 0x92, 0x27, 0x56, - 0x6d, 0x9f, 0x20, 0x79, 0x62, 0xd5, 0xd7, 0xb3, 0xe2, 0xb1, 0x4f, 0xf2, 0x65, 0x77, 0x2b, 0xc2, - 0xf9, 0xc7, 0x06, 0xa0, 0x74, 0xb9, 0x0a, 0xbd, 0xab, 0xa7, 0xae, 0xed, 0x39, 0x34, 0xde, 0xbb, - 0x18, 0xb0, 0x2e, 0x9d, 0x49, 0x91, 0x3a, 0x14, 0x7a, 0xf0, 0x8a, 0x08, 0xf5, 0x5d, 0x03, 0x26, - 0x62, 0x25, 0x2e, 0xf4, 0xd6, 0x08, 0x9b, 0x26, 0x1a, 0x0f, 0x8d, 0xb7, 0xcf, 0x85, 0xd3, 0x1d, - 0xe5, 0x95, 0x1d, 0x20, 0xee, 0x34, 0xbf, 0x63, 0x40, 0x35, 0x5e, 0x09, 0x43, 0x23, 0x68, 0xa7, - 0xfa, 0x15, 0x8d, 0xb9, 0xf3, 0x01, 0xcf, 0x36, 0x8f, 0xbc, 0xce, 0xf4, 0xa0, 0xc8, 0x4b, 0x66, - 0xba, 0x8d, 0x1f, 0x6f, 0x70, 0xe8, 0x36, 0x7e, 0xa2, 0xde, 0xa6, 0xd9, 0xf8, 0xbe, 0xd7, 0xc3, - 0x8a, 0x9b, 0xf1, 0x4a, 0xda, 0x28, 0x6e, 0x67, 0xbb, 0x59, 0xa2, 0x0c, 0x37, 0x8a, 0x9b, 0x74, - 0x33, 0x51, 0x30, 0x43, 0x23, 0x88, 0x9d, 0xe3, 0x66, 0xc9, 0x7a, 0x9b, 0xc6, 0xcd, 0x28, 0x43, - 0xc5, 0xcd, 0x64, 0x21, 0x4b, 0xe7, 0x66, 0xa9, 0x5e, 0x8c, 0xce, 0xcd, 0xd2, 0xb5, 0x30, 0x8d, - 0x1d, 0x29, 0xdf, 0x98, 0x9b, 0x5d, 0xd3, 0x94, 0xba, 0xd0, 0x7b, 0x23, 0x94, 0xa8, 0xed, 0xec, - 0x34, 0xde, 0xbf, 0x20, 0xf4, 0xc8, 0x3d, 0xce, 0xd4, 0x2f, 0xf6, 0xf8, 0x1f, 0x19, 0x30, 0xad, - 0xab, 0x8e, 0xa1, 0x11, 0x7c, 0x46, 0x34, 0x82, 0x1a, 0x0b, 0x17, 0x05, 0x3f, 0x5b, 0x5b, 0xd1, - 0xae, 0x7f, 0x5c, 0xfb, 0xd7, 0xcf, 0x67, 0x8c, 0xff, 0xf8, 0x7c, 0xc6, 0xf8, 0xaf, 0xcf, 0x67, - 0x8c, 0x9f, 0xfc, 0xcf, 0xcc, 0xd8, 0x7e, 0x81, 0xfe, 0x0f, 0x18, 0x96, 0x7f, 0x16, 0x00, 0x00, - 0xff, 0xff, 0xe6, 0x88, 0xc4, 0x9e, 0x27, 0x42, 0x00, 0x00, + // 4393 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xc4, 0x5c, 0x4f, 0x6f, 0x24, 0x49, + 0x56, 0x77, 0xd6, 0x5f, 0xd7, 0xab, 0x72, 0xb9, 0x1c, 0xed, 0xee, 0xa9, 0xae, 0xe9, 0x76, 0x7b, + 0xb2, 0xa7, 0x67, 0x3c, 0x9e, 0x19, 0xbb, 0xdb, 0x76, 0xef, 0x40, 0xa3, 0x19, 0xb6, 0xda, 0xae, + 0x69, 0x9b, 0x76, 0xdb, 0xde, 0x74, 0x75, 0xcf, 0xce, 0x20, 0xad, 0x49, 0x57, 0x45, 0xdb, 0xb9, + 0xae, 0xca, 0xac, 0xcd, 0xcc, 0x72, 0xdb, 0xcb, 0x61, 0x97, 0x85, 0x65, 0xb5, 0x20, 0xad, 0xc4, + 0x22, 0xa1, 0x15, 0x82, 0x0b, 0x42, 0x82, 0x03, 0x20, 0x38, 0x70, 0x40, 0x1c, 0x38, 0xc0, 0x01, + 0x0e, 0x48, 0x48, 0x7c, 0x01, 0x18, 0xf6, 0xc4, 0x57, 0x40, 0x42, 0xab, 0xf8, 0x97, 0x11, 0x99, + 0x19, 0x65, 0x7b, 0xd6, 0x1e, 0xed, 0x65, 0xba, 0x32, 0xe2, 0xc5, 0xfb, 0xbd, 0x78, 0x2f, 0xe2, + 0xbd, 0x88, 0xf7, 0xc2, 0x03, 0x25, 0x7f, 0xd0, 0x59, 0x18, 0xf8, 0x5e, 0xe8, 0xa1, 0x0a, 0x0e, + 0x3b, 0xdd, 0x00, 0xfb, 0xc7, 0xd8, 0x1f, 0xec, 0x37, 0xa6, 0x0f, 0xbc, 0x03, 0x8f, 0x76, 0x2c, + 0x92, 0x5f, 0x8c, 0xa6, 0x51, 0x27, 0x34, 0x8b, 0xf6, 0xc0, 0x59, 0xec, 0x1f, 0x77, 0x3a, 0x83, + 0xfd, 0xc5, 0xa3, 0x63, 0xde, 0xd3, 0x88, 0x7a, 0xec, 0x61, 0x78, 0x38, 0xd8, 0xa7, 0xff, 0xf0, + 0xbe, 0xd9, 0xa8, 0xef, 0x18, 0xfb, 0x81, 0xe3, 0xb9, 0x83, 0x7d, 0xf1, 0x8b, 0x53, 0xdc, 0x3a, + 0xf0, 0xbc, 0x83, 0x1e, 0x66, 0xe3, 0x5d, 0xd7, 0x0b, 0xed, 0xd0, 0xf1, 0xdc, 0x80, 0xf5, 0x9a, + 0x3f, 0x32, 0xa0, 0x6a, 0xe1, 0x60, 0xe0, 0xb9, 0x01, 0x5e, 0xc7, 0x76, 0x17, 0xfb, 0xe8, 0x36, + 0x40, 0xa7, 0x37, 0x0c, 0x42, 0xec, 0xef, 0x39, 0xdd, 0xba, 0x31, 0x6b, 0xcc, 0xe5, 0xac, 0x12, + 0x6f, 0xd9, 0xe8, 0xa2, 0xd7, 0xa1, 0xd4, 0xc7, 0xfd, 0x7d, 0xd6, 0x9b, 0xa1, 0xbd, 0xe3, 0xac, + 0x61, 0xa3, 0x8b, 0x1a, 0x30, 0xee, 0xe3, 0x63, 0x87, 0xc0, 0xd7, 0xb3, 0xb3, 0xc6, 0x5c, 0xd6, + 0x8a, 0xbe, 0xc9, 0x40, 0xdf, 0x7e, 0x19, 0xee, 0x85, 0xd8, 0xef, 0xd7, 0x73, 0x6c, 0x20, 0x69, + 0x68, 0x63, 0xbf, 0xff, 0xa8, 0xf8, 0xbd, 0xbf, 0xaf, 0x67, 0x97, 0x17, 0xee, 0x9b, 0xff, 0x9c, + 0x87, 0x8a, 0x65, 0xbb, 0x07, 0xd8, 0xc2, 0xdf, 0x1a, 0xe2, 0x20, 0x44, 0x35, 0xc8, 0x1e, 0xe1, + 0x53, 0x2a, 0x47, 0xc5, 0x22, 0x3f, 0x19, 0x23, 0xf7, 0x00, 0xef, 0x61, 0x97, 0x49, 0x50, 0x21, + 0x8c, 0xdc, 0x03, 0xdc, 0x72, 0xbb, 0x68, 0x1a, 0xf2, 0x3d, 0xa7, 0xef, 0x84, 0x1c, 0x9e, 0x7d, + 0xc4, 0xe4, 0xca, 0x25, 0xe4, 0x5a, 0x05, 0x08, 0x3c, 0x3f, 0xdc, 0xf3, 0xfc, 0x2e, 0xf6, 0xeb, + 0xf9, 0x59, 0x63, 0xae, 0xba, 0xf4, 0xe6, 0x82, 0x6a, 0xb1, 0x05, 0x55, 0xa0, 0x85, 0x5d, 0xcf, + 0x0f, 0xb7, 0x09, 0xad, 0x55, 0x0a, 0xc4, 0x4f, 0xf4, 0x31, 0x94, 0x29, 0x93, 0xd0, 0xf6, 0x0f, + 0x70, 0x58, 0x2f, 0x50, 0x2e, 0xf7, 0xce, 0xe1, 0xd2, 0xa6, 0xc4, 0x16, 0x85, 0x67, 0xbf, 0x91, + 0x09, 0x95, 0x00, 0xfb, 0x8e, 0xdd, 0x73, 0xbe, 0x6d, 0xef, 0xf7, 0x70, 0xbd, 0x38, 0x6b, 0xcc, + 0x8d, 0x5b, 0xb1, 0x36, 0x32, 0xff, 0x23, 0x7c, 0x1a, 0xec, 0x79, 0x6e, 0xef, 0xb4, 0x3e, 0x4e, + 0x09, 0xc6, 0x49, 0xc3, 0xb6, 0xdb, 0x3b, 0xa5, 0xd6, 0xf3, 0x86, 0x6e, 0xc8, 0x7a, 0x4b, 0xb4, + 0xb7, 0x44, 0x5b, 0x68, 0xf7, 0x03, 0xa8, 0xf5, 0x1d, 0x77, 0xaf, 0xef, 0x75, 0xf7, 0x22, 0x85, + 0x00, 0x51, 0xc8, 0xe3, 0xe2, 0xef, 0x51, 0x0b, 0x3c, 0xb0, 0xaa, 0x7d, 0xc7, 0x7d, 0xe6, 0x75, + 0x2d, 0xa1, 0x1f, 0x32, 0xc4, 0x3e, 0x89, 0x0f, 0x29, 0x27, 0x87, 0xd8, 0x27, 0xea, 0x90, 0x0f, + 0xe0, 0x1a, 0x41, 0xe9, 0xf8, 0xd8, 0x0e, 0xb1, 0x1c, 0x55, 0x89, 0x8f, 0x9a, 0xea, 0x3b, 0xee, + 0x2a, 0x25, 0x89, 0x0d, 0xb4, 0x4f, 0x52, 0x03, 0x27, 0x92, 0x03, 0xed, 0x93, 0xf8, 0x40, 0xf3, + 0x03, 0x28, 0x45, 0x76, 0x41, 0xe3, 0x90, 0xdb, 0xda, 0xde, 0x6a, 0xd5, 0xc6, 0x10, 0x40, 0xa1, + 0xb9, 0xbb, 0xda, 0xda, 0x5a, 0xab, 0x19, 0xa8, 0x0c, 0xc5, 0xb5, 0x16, 0xfb, 0xc8, 0x34, 0x8a, + 0x3f, 0xe6, 0xeb, 0xed, 0x29, 0x80, 0x34, 0x05, 0x2a, 0x42, 0xf6, 0x69, 0xeb, 0xd3, 0xda, 0x18, + 0x21, 0x7e, 0xd1, 0xb2, 0x76, 0x37, 0xb6, 0xb7, 0x6a, 0x06, 0xe1, 0xb2, 0x6a, 0xb5, 0x9a, 0xed, + 0x56, 0x2d, 0x43, 0x28, 0x9e, 0x6d, 0xaf, 0xd5, 0xb2, 0xa8, 0x04, 0xf9, 0x17, 0xcd, 0xcd, 0xe7, + 0xad, 0x5a, 0x2e, 0x62, 0x26, 0x57, 0xf1, 0x9f, 0x18, 0x30, 0xc1, 0xcd, 0xcd, 0xf6, 0x16, 0x5a, + 0x81, 0xc2, 0x21, 0xdd, 0x5f, 0x74, 0x25, 0x97, 0x97, 0x6e, 0x25, 0xd6, 0x46, 0x6c, 0x0f, 0x5a, + 0x9c, 0x16, 0x99, 0x90, 0x3d, 0x3a, 0x0e, 0xea, 0x99, 0xd9, 0xec, 0x5c, 0x79, 0xa9, 0xb6, 0xc0, + 0x3c, 0xc3, 0xc2, 0x53, 0x7c, 0xfa, 0xc2, 0xee, 0x0d, 0xb1, 0x45, 0x3a, 0x11, 0x82, 0x5c, 0xdf, + 0xf3, 0x31, 0x5d, 0xf0, 0xe3, 0x16, 0xfd, 0x4d, 0x76, 0x01, 0xb5, 0x39, 0x5f, 0xec, 0xec, 0x43, + 0x8a, 0xf7, 0xef, 0x06, 0xc0, 0xce, 0x30, 0x1c, 0xbd, 0xc5, 0xa6, 0x21, 0x7f, 0x4c, 0x10, 0xf8, + 0xf6, 0x62, 0x1f, 0x74, 0x6f, 0x61, 0x3b, 0xc0, 0xd1, 0xde, 0x22, 0x1f, 0x68, 0x16, 0x8a, 0x03, + 0x1f, 0x1f, 0xef, 0x1d, 0x1d, 0x53, 0xb4, 0x71, 0x69, 0xa7, 0x02, 0x69, 0x7f, 0x7a, 0x8c, 0xe6, + 0xa1, 0xe2, 0x1c, 0xb8, 0x9e, 0x8f, 0xf7, 0x18, 0xd3, 0xbc, 0x4a, 0xb6, 0x64, 0x95, 0x59, 0x27, + 0x9d, 0x92, 0x42, 0xcb, 0xa0, 0x0a, 0x5a, 0xda, 0x4d, 0xd2, 0x27, 0xe7, 0xf3, 0x5d, 0x03, 0xca, + 0x74, 0x3e, 0x97, 0x52, 0xf6, 0x92, 0x9c, 0x48, 0x86, 0x0e, 0x4b, 0x29, 0x3c, 0x35, 0x35, 0x29, + 0x82, 0x0b, 0x68, 0x0d, 0xf7, 0x70, 0x88, 0x2f, 0xe3, 0xbc, 0x14, 0x55, 0x66, 0xb5, 0xaa, 0x94, + 0x78, 0x7f, 0x6e, 0xc0, 0xb5, 0x18, 0xe0, 0xa5, 0xa6, 0x5e, 0x87, 0x62, 0x97, 0x32, 0x63, 0x32, + 0x65, 0x2d, 0xf1, 0x89, 0x56, 0x60, 0x9c, 0x8b, 0x14, 0xd4, 0xb3, 0xfa, 0x65, 0x28, 0xa5, 0x2c, + 0x32, 0x29, 0x03, 0x29, 0xe6, 0x3f, 0x66, 0xa0, 0xc4, 0x95, 0xb1, 0x3d, 0x40, 0x4d, 0x98, 0xf0, + 0xd9, 0xc7, 0x1e, 0x9d, 0x33, 0x97, 0xb1, 0x31, 0xda, 0x4f, 0xae, 0x8f, 0x59, 0x15, 0x3e, 0x84, + 0x36, 0xa3, 0x5f, 0x81, 0xb2, 0x60, 0x31, 0x18, 0x86, 0xdc, 0x50, 0xf5, 0x38, 0x03, 0xb9, 0xb4, + 0xd7, 0xc7, 0x2c, 0xe0, 0xe4, 0x3b, 0xc3, 0x10, 0xb5, 0x61, 0x5a, 0x0c, 0x66, 0xf3, 0xe3, 0x62, + 0x64, 0x29, 0x97, 0xd9, 0x38, 0x97, 0xb4, 0x39, 0xd7, 0xc7, 0x2c, 0xc4, 0xc7, 0x2b, 0x9d, 0x68, + 0x4d, 0x8a, 0x14, 0x9e, 0xb0, 0xf8, 0x92, 0x12, 0xa9, 0x7d, 0xe2, 0x72, 0x26, 0x42, 0x5b, 0xcb, + 0x8a, 0x6c, 0xed, 0x13, 0x37, 0x52, 0xd9, 0xe3, 0x12, 0x14, 0x79, 0xb3, 0xf9, 0x6f, 0x19, 0x00, + 0x61, 0xb1, 0xed, 0x01, 0x5a, 0x83, 0xaa, 0xcf, 0xbf, 0x62, 0xfa, 0x7b, 0x5d, 0xab, 0x3f, 0x6e, + 0xe8, 0x31, 0x6b, 0x42, 0x0c, 0x62, 0xe2, 0x7e, 0x04, 0x95, 0x88, 0x8b, 0x54, 0xe1, 0x4d, 0x8d, + 0x0a, 0x23, 0x0e, 0x65, 0x31, 0x80, 0x28, 0xf1, 0x13, 0xb8, 0x1e, 0x8d, 0xd7, 0x68, 0xf1, 0x8d, + 0x33, 0xb4, 0x18, 0x31, 0xbc, 0x26, 0x38, 0xa8, 0x7a, 0x7c, 0xa2, 0x08, 0x26, 0x15, 0x79, 0x53, + 0xa3, 0x48, 0x46, 0xa4, 0x6a, 0x32, 0x92, 0x30, 0xa6, 0x4a, 0x20, 0x61, 0x9f, 0xb5, 0x9b, 0x7f, + 0x99, 0x83, 0xe2, 0xaa, 0xd7, 0x1f, 0xd8, 0x3e, 0x59, 0x44, 0x05, 0x1f, 0x07, 0xc3, 0x5e, 0x48, + 0x15, 0x58, 0x5d, 0xba, 0x1b, 0xc7, 0xe0, 0x64, 0xe2, 0x5f, 0x8b, 0x92, 0x5a, 0x7c, 0x08, 0x19, + 0xcc, 0xa3, 0x7c, 0xe6, 0x02, 0x83, 0x79, 0x8c, 0xe7, 0x43, 0x84, 0x43, 0xc8, 0x4a, 0x87, 0xd0, + 0x80, 0x22, 0x3f, 0xb0, 0x31, 0x67, 0xbd, 0x3e, 0x66, 0x89, 0x06, 0xf4, 0x0e, 0x4c, 0x26, 0x43, + 0x61, 0x9e, 0xd3, 0x54, 0x3b, 0xf1, 0xc8, 0x79, 0x17, 0x2a, 0xb1, 0x08, 0x5d, 0xe0, 0x74, 0xe5, + 0xbe, 0x12, 0x97, 0x6f, 0x08, 0xb7, 0x4e, 0x8e, 0x15, 0x95, 0xf5, 0x31, 0xe1, 0xd8, 0xef, 0x08, + 0xc7, 0x3e, 0xae, 0x06, 0x5a, 0xa2, 0x57, 0xee, 0xe3, 0xdf, 0x54, 0xbd, 0xd6, 0x57, 0xc9, 0xe0, + 0x88, 0x48, 0xba, 0x2f, 0xd3, 0x82, 0x89, 0x98, 0xca, 0x48, 0x8c, 0x6c, 0x7d, 0xed, 0x79, 0x73, + 0x93, 0x05, 0xd4, 0x27, 0x34, 0x86, 0x5a, 0x35, 0x83, 0x04, 0xe8, 0xcd, 0xd6, 0xee, 0x6e, 0x2d, + 0x83, 0x6e, 0x40, 0x69, 0x6b, 0xbb, 0xbd, 0xc7, 0xa8, 0xb2, 0x8d, 0xe2, 0x1f, 0x33, 0x4f, 0x22, + 0xe3, 0xf3, 0xa7, 0x11, 0x4f, 0x1e, 0xa2, 0x95, 0xc8, 0x3c, 0xa6, 0x44, 0x66, 0x43, 0x44, 0xe6, + 0x8c, 0x8c, 0xcc, 0x59, 0x84, 0x20, 0xbf, 0xd9, 0x6a, 0xee, 0xd2, 0x20, 0xcd, 0x58, 0x2f, 0xa7, + 0xa3, 0xf5, 0xe3, 0x2a, 0x54, 0x98, 0x79, 0xf6, 0x86, 0x2e, 0x39, 0x4c, 0xfc, 0x95, 0x01, 0x20, + 0x37, 0x2c, 0x5a, 0x84, 0x62, 0x87, 0x89, 0x50, 0x37, 0xa8, 0x07, 0xbc, 0xae, 0xb5, 0xb8, 0x25, + 0xa8, 0xd0, 0x03, 0x28, 0x06, 0xc3, 0x4e, 0x07, 0x07, 0x22, 0x72, 0xbf, 0x96, 0x74, 0xc2, 0xdc, + 0x21, 0x5a, 0x82, 0x8e, 0x0c, 0x79, 0x69, 0x3b, 0xbd, 0x21, 0x8d, 0xe3, 0x67, 0x0f, 0xe1, 0x74, + 0xd2, 0xc7, 0xfe, 0x99, 0x01, 0x65, 0x65, 0x5b, 0xfc, 0x9c, 0x21, 0xe0, 0x16, 0x94, 0xa8, 0x30, + 0xb8, 0xcb, 0x83, 0xc0, 0xb8, 0x25, 0x1b, 0xd0, 0x57, 0xa0, 0x24, 0x76, 0x92, 0x88, 0x03, 0x75, + 0x3d, 0xdb, 0xed, 0x81, 0x25, 0x49, 0xa5, 0x90, 0x6d, 0x98, 0xa2, 0x7a, 0xea, 0x90, 0xdb, 0x87, + 0xd0, 0xac, 0x7a, 0x2c, 0x37, 0x12, 0xc7, 0xf2, 0x06, 0x8c, 0x0f, 0x0e, 0x4f, 0x03, 0xa7, 0x63, + 0xf7, 0xb8, 0x38, 0xd1, 0xb7, 0xe4, 0xba, 0x0b, 0x48, 0xe5, 0x7a, 0x19, 0x05, 0x48, 0xa6, 0x37, + 0xa0, 0xbc, 0x6e, 0x07, 0x87, 0x5c, 0x48, 0xd9, 0xbe, 0x02, 0x13, 0xa4, 0xfd, 0xe9, 0x8b, 0x0b, + 0x88, 0x2f, 0x46, 0x2d, 0xd3, 0x1b, 0x96, 0x18, 0x76, 0x29, 0x03, 0x21, 0xc8, 0x1d, 0xda, 0xc1, + 0x21, 0x55, 0xc6, 0x84, 0x45, 0x7f, 0xa3, 0x77, 0xa0, 0xd6, 0x61, 0xf3, 0xdf, 0x4b, 0xdc, 0xbb, + 0x26, 0x79, 0xbb, 0x95, 0x12, 0xc8, 0x86, 0x0a, 0x9b, 0xde, 0x55, 0x4b, 0x23, 0x35, 0xd5, 0x80, + 0xc9, 0x5d, 0xd7, 0x1e, 0x04, 0x87, 0x5e, 0x98, 0xd0, 0xe2, 0xb2, 0xf9, 0x77, 0x06, 0xd4, 0x64, + 0xe7, 0xa5, 0x64, 0x78, 0x1b, 0x26, 0x7d, 0xdc, 0xb7, 0x1d, 0xd7, 0x71, 0x0f, 0xf6, 0xf6, 0x4f, + 0x43, 0x1c, 0xf0, 0x0b, 0x69, 0x35, 0x6a, 0x7e, 0x4c, 0x5a, 0x89, 0xb0, 0xfb, 0x3d, 0x6f, 0x9f, + 0xbb, 0x5d, 0xfa, 0x1b, 0xbd, 0x11, 0xf7, 0xbb, 0x25, 0xe1, 0xd0, 0xbe, 0x12, 0xb9, 0x5f, 0x29, + 0xf3, 0x4f, 0x32, 0x50, 0xf9, 0xc4, 0x0e, 0x3b, 0x62, 0x4d, 0xa0, 0x0d, 0xa8, 0x46, 0x8e, 0x99, + 0xb6, 0x70, 0xb9, 0x13, 0x47, 0x08, 0x3a, 0x46, 0xdc, 0x54, 0xc4, 0x11, 0x62, 0xa2, 0xa3, 0x36, + 0x50, 0x56, 0xb6, 0xdb, 0xc1, 0xbd, 0x88, 0x55, 0x66, 0x34, 0x2b, 0x4a, 0xa8, 0xb2, 0x52, 0x1b, + 0xd0, 0xd7, 0xa1, 0x36, 0xf0, 0xbd, 0x03, 0x1f, 0x07, 0x41, 0xc4, 0x8c, 0x05, 0x65, 0x53, 0xc3, + 0x6c, 0x87, 0x93, 0x26, 0xce, 0x25, 0x2b, 0xeb, 0x63, 0xd6, 0xe4, 0x20, 0xde, 0x27, 0x5d, 0xe5, + 0xa4, 0x3c, 0xc1, 0x31, 0x5f, 0xf9, 0x83, 0x2c, 0xa0, 0xf4, 0x34, 0xbf, 0xe8, 0xc1, 0xf7, 0x1e, + 0x54, 0x83, 0xd0, 0xf6, 0x53, 0xab, 0x78, 0x82, 0xb6, 0x46, 0xf1, 0xeb, 0x6d, 0x88, 0x24, 0xdb, + 0x73, 0xbd, 0xd0, 0x79, 0x79, 0xca, 0xae, 0x1c, 0x56, 0x55, 0x34, 0x6f, 0xd1, 0x56, 0xb4, 0x05, + 0xc5, 0x97, 0x4e, 0x2f, 0xc4, 0x7e, 0x50, 0xcf, 0xcf, 0x66, 0xe7, 0xaa, 0x4b, 0xef, 0x9e, 0x67, + 0x98, 0x85, 0x8f, 0x29, 0x7d, 0xfb, 0x74, 0xa0, 0x9e, 0x67, 0x39, 0x13, 0xf5, 0x60, 0x5e, 0xd0, + 0xdf, 0x71, 0x4c, 0x18, 0x7f, 0x45, 0x98, 0xee, 0x39, 0x5d, 0x1a, 0x5d, 0xa3, 0x28, 0xba, 0x62, + 0x15, 0x69, 0xc7, 0x46, 0x17, 0xdd, 0x85, 0xf1, 0x97, 0xbe, 0x7d, 0xd0, 0xc7, 0x6e, 0xc8, 0xee, + 0xed, 0x92, 0x26, 0xea, 0x30, 0x17, 0x00, 0xa4, 0x28, 0x24, 0x96, 0x6d, 0x6d, 0xef, 0x3c, 0x6f, + 0xd7, 0xc6, 0x50, 0x05, 0xc6, 0xb7, 0xb6, 0xd7, 0x5a, 0x9b, 0x2d, 0x12, 0xed, 0x44, 0x14, 0x7b, + 0x20, 0x37, 0x5d, 0x53, 0x18, 0x22, 0xb6, 0x26, 0x54, 0xb9, 0x8c, 0xf8, 0x35, 0x5a, 0xc8, 0x25, + 0x58, 0x3c, 0x30, 0xef, 0xc0, 0xb4, 0x6e, 0x69, 0x08, 0x82, 0x15, 0xf3, 0x5f, 0x32, 0x30, 0xc1, + 0x37, 0xc2, 0xa5, 0x76, 0xee, 0x4d, 0x45, 0x2a, 0x7e, 0xe1, 0x10, 0x4a, 0xaa, 0x43, 0x91, 0x6d, + 0x90, 0x2e, 0xbf, 0xd1, 0x8a, 0x4f, 0xe2, 0x6e, 0xd9, 0x7a, 0xc7, 0x5d, 0x6e, 0xf6, 0xe8, 0x5b, + 0xeb, 0x08, 0xf3, 0x5a, 0x47, 0x88, 0xde, 0x83, 0x89, 0x68, 0xc3, 0xd9, 0x01, 0x3f, 0x2a, 0x95, + 0xa4, 0x29, 0x2a, 0x62, 0x53, 0x91, 0xce, 0x98, 0xcd, 0x8a, 0x23, 0x6c, 0x86, 0xee, 0x41, 0x01, + 0x1f, 0x63, 0x37, 0x0c, 0xea, 0x65, 0x1a, 0x1a, 0x27, 0xc4, 0x15, 0xa9, 0x45, 0x5a, 0x2d, 0xde, + 0x29, 0x4d, 0xf5, 0x11, 0x4c, 0xd1, 0x1b, 0xec, 0x13, 0xdf, 0x76, 0xd5, 0x5b, 0x78, 0xbb, 0xbd, + 0xc9, 0x03, 0x09, 0xf9, 0x89, 0xaa, 0x90, 0xd9, 0x58, 0xe3, 0xfa, 0xc9, 0x6c, 0xac, 0xc9, 0xf1, + 0xbf, 0x6f, 0x00, 0x52, 0x19, 0x5c, 0xca, 0x16, 0x09, 0x14, 0x21, 0x47, 0x56, 0xca, 0x31, 0x0d, + 0x79, 0xec, 0xfb, 0x9e, 0xcf, 0x1c, 0xa5, 0xc5, 0x3e, 0xa4, 0x34, 0xef, 0x73, 0x61, 0x2c, 0x7c, + 0xec, 0x1d, 0x45, 0x1e, 0x80, 0xb1, 0x35, 0xd2, 0xc2, 0xb7, 0xe1, 0x5a, 0x8c, 0xfc, 0x6a, 0x82, + 0xf6, 0x36, 0x4c, 0x52, 0xae, 0xab, 0x87, 0xb8, 0x73, 0x34, 0xf0, 0x1c, 0x37, 0x25, 0x01, 0xba, + 0x4b, 0x7c, 0x97, 0x08, 0x17, 0x64, 0x8a, 0x6c, 0xce, 0x95, 0xa8, 0xb1, 0xdd, 0xde, 0x94, 0x4b, + 0x7d, 0x1f, 0x6e, 0x24, 0x18, 0x8a, 0x99, 0xfd, 0x2a, 0x94, 0x3b, 0x51, 0x63, 0xc0, 0xcf, 0x84, + 0xb7, 0xe3, 0xe2, 0x26, 0x87, 0xaa, 0x23, 0x24, 0xc6, 0xd7, 0xe1, 0xb5, 0x14, 0xc6, 0x55, 0xa8, + 0x63, 0xc5, 0xbc, 0x0f, 0xd7, 0x29, 0xe7, 0xa7, 0x18, 0x0f, 0x9a, 0x3d, 0xe7, 0xf8, 0x7c, 0xb3, + 0x9c, 0xf2, 0xf9, 0x2a, 0x23, 0xbe, 0xdc, 0x65, 0x25, 0xa1, 0x5b, 0x1c, 0xba, 0xed, 0xf4, 0x71, + 0xdb, 0xdb, 0x1c, 0x2d, 0x2d, 0x09, 0xe4, 0x47, 0xf8, 0x34, 0xe0, 0x07, 0x42, 0xfa, 0x5b, 0x7a, + 0xaf, 0xbf, 0x31, 0xb8, 0x3a, 0x55, 0x3e, 0x5f, 0xf2, 0xd6, 0x98, 0x01, 0x38, 0x20, 0x7b, 0x10, + 0x77, 0x49, 0x07, 0xcb, 0xb6, 0x29, 0x2d, 0x91, 0xc0, 0x24, 0x0a, 0x55, 0x92, 0x02, 0xdf, 0xe6, + 0x1b, 0x87, 0xfe, 0x27, 0x48, 0x9d, 0x94, 0xde, 0x82, 0x32, 0xed, 0xd9, 0x0d, 0xed, 0x70, 0x18, + 0x8c, 0xb2, 0xdc, 0xb2, 0xf9, 0x03, 0x83, 0xef, 0x28, 0xc1, 0xe7, 0x52, 0x73, 0x7e, 0x00, 0x05, + 0x7a, 0xe7, 0x13, 0x77, 0x97, 0x9b, 0x9a, 0x85, 0xcd, 0x24, 0xb2, 0x38, 0xa1, 0x72, 0x4e, 0x32, + 0xa0, 0xf0, 0x8c, 0xd6, 0x02, 0x14, 0x69, 0x73, 0xc2, 0x72, 0xae, 0xdd, 0x67, 0x09, 0xc5, 0x92, + 0x45, 0x7f, 0xd3, 0x23, 0x3e, 0xc6, 0xfe, 0x73, 0x6b, 0x93, 0xdd, 0x29, 0x4a, 0x56, 0xf4, 0x4d, + 0x14, 0xdb, 0xe9, 0x39, 0xd8, 0x0d, 0x69, 0x6f, 0x8e, 0xf6, 0x2a, 0x2d, 0xe8, 0x1e, 0x94, 0x9c, + 0x60, 0x13, 0xdb, 0xbe, 0xcb, 0x93, 0xf6, 0x8a, 0x63, 0x96, 0x3d, 0x72, 0x8d, 0x7d, 0x03, 0x6a, + 0x4c, 0xb2, 0x66, 0xb7, 0xab, 0x9c, 0xdf, 0x23, 0x7c, 0x23, 0x81, 0x1f, 0xe3, 0x9f, 0x39, 0x9f, + 0xff, 0xdf, 0x1a, 0x30, 0xa5, 0x00, 0x5c, 0xca, 0x04, 0xef, 0x41, 0x81, 0x55, 0x54, 0xf8, 0x51, + 0x70, 0x3a, 0x3e, 0x8a, 0xc1, 0x58, 0x9c, 0x06, 0x2d, 0x40, 0x91, 0xfd, 0x12, 0x17, 0x33, 0x3d, + 0xb9, 0x20, 0x92, 0x22, 0x2f, 0xc0, 0x35, 0xde, 0x87, 0xfb, 0x9e, 0x6e, 0xcf, 0xe5, 0xe2, 0x1e, + 0xe2, 0xfb, 0x06, 0x4c, 0xc7, 0x07, 0x5c, 0x6a, 0x96, 0x8a, 0xdc, 0x99, 0x2f, 0x24, 0xf7, 0xaf, + 0x09, 0xb9, 0x9f, 0x0f, 0xba, 0xca, 0x91, 0x33, 0xb9, 0xe2, 0x54, 0xeb, 0x66, 0xe2, 0xd6, 0x95, + 0xbc, 0x7e, 0x14, 0xcd, 0x49, 0x30, 0xbb, 0xd4, 0x9c, 0x3e, 0xb8, 0xd0, 0x9c, 0x94, 0x23, 0x58, + 0x6a, 0x72, 0x1b, 0x62, 0x19, 0x6d, 0x3a, 0x41, 0x14, 0x71, 0xde, 0x85, 0x4a, 0xcf, 0x71, 0xb1, + 0xed, 0xf3, 0xaa, 0x90, 0xa1, 0xae, 0xc7, 0x87, 0x56, 0xac, 0x53, 0xb2, 0xfa, 0x6d, 0x03, 0x90, + 0xca, 0xeb, 0x17, 0x63, 0xad, 0x45, 0xa1, 0xe0, 0x1d, 0xdf, 0xeb, 0x7b, 0xe1, 0x79, 0xcb, 0x6c, + 0xc5, 0xfc, 0x5d, 0x03, 0xae, 0x27, 0x46, 0xfc, 0x22, 0x24, 0x5f, 0x31, 0x6f, 0xc1, 0xd4, 0x1a, + 0x16, 0x67, 0xbc, 0x54, 0x36, 0x60, 0x17, 0x90, 0xda, 0x7b, 0x35, 0xa7, 0x98, 0x5f, 0x82, 0xa9, + 0x67, 0xde, 0x31, 0x71, 0xe4, 0xa4, 0x5b, 0xba, 0x29, 0x96, 0x9e, 0x8a, 0xf4, 0x15, 0x7d, 0x4b, + 0xd7, 0xbb, 0x0b, 0x48, 0x1d, 0x79, 0x15, 0xe2, 0x2c, 0x9b, 0xff, 0x6d, 0x40, 0xa5, 0xd9, 0xb3, + 0xfd, 0xbe, 0x10, 0xe5, 0x23, 0x28, 0xb0, 0x5c, 0x0b, 0x4f, 0x9c, 0xbe, 0x15, 0xe7, 0xa7, 0xd2, + 0xb2, 0x8f, 0x26, 0xcb, 0xcc, 0xf0, 0x51, 0x64, 0x2a, 0xbc, 0x56, 0xbc, 0x96, 0xa8, 0x1d, 0xaf, + 0xa1, 0xf7, 0x21, 0x6f, 0x93, 0x21, 0x34, 0xbc, 0x56, 0x93, 0x09, 0x30, 0xca, 0x8d, 0x5c, 0x89, + 0x2c, 0x46, 0x65, 0x7e, 0x08, 0x65, 0x05, 0x01, 0x15, 0x21, 0xfb, 0xa4, 0xc5, 0xaf, 0x49, 0xcd, + 0xd5, 0xf6, 0xc6, 0x0b, 0x96, 0x14, 0xac, 0x02, 0xac, 0xb5, 0xa2, 0xef, 0x8c, 0xa6, 0x54, 0x67, + 0x73, 0x3e, 0x3c, 0x6e, 0xa9, 0x12, 0x1a, 0xa3, 0x24, 0xcc, 0x5c, 0x44, 0x42, 0x09, 0xf1, 0x5b, + 0x06, 0x4c, 0x70, 0xd5, 0x5c, 0x36, 0x34, 0x53, 0xce, 0x23, 0x42, 0xb3, 0x32, 0x0d, 0x8b, 0x13, + 0x4a, 0x19, 0xfe, 0xc9, 0x80, 0xda, 0x9a, 0xf7, 0xca, 0x3d, 0xf0, 0xed, 0x6e, 0xb4, 0x07, 0x3f, + 0x4e, 0x98, 0x73, 0x21, 0x91, 0xbb, 0x4f, 0xd0, 0xcb, 0x86, 0x84, 0x59, 0xeb, 0x32, 0x97, 0xc2, + 0xe2, 0xbb, 0xf8, 0x34, 0xbf, 0x0a, 0x93, 0x89, 0x41, 0xc4, 0x40, 0x2f, 0x9a, 0x9b, 0x1b, 0x6b, + 0xc4, 0x20, 0x34, 0x83, 0xdb, 0xda, 0x6a, 0x3e, 0xde, 0x6c, 0xf1, 0x3a, 0x6b, 0x73, 0x6b, 0xb5, + 0xb5, 0x29, 0x0d, 0xf5, 0x50, 0xcc, 0xe0, 0xa1, 0xd9, 0x83, 0x29, 0x45, 0xa0, 0xcb, 0x96, 0xbb, + 0xf4, 0xf2, 0x4a, 0xb4, 0x3a, 0x4c, 0xf0, 0x53, 0x4e, 0x72, 0xe3, 0xff, 0x5f, 0x06, 0xaa, 0xa2, + 0xeb, 0xcb, 0x91, 0x02, 0xdd, 0x80, 0x42, 0x77, 0x7f, 0xd7, 0xf9, 0xb6, 0xa8, 0xb4, 0xf2, 0x2f, + 0xd2, 0xde, 0x63, 0x38, 0xec, 0xfd, 0x04, 0xff, 0x42, 0xb7, 0xd8, 0xd3, 0x8a, 0x0d, 0xb7, 0x8b, + 0x4f, 0xe8, 0x61, 0x28, 0x67, 0xc9, 0x06, 0x9a, 0xa6, 0xe4, 0xef, 0x2c, 0xe8, 0x5d, 0x57, 0x79, + 0x77, 0x81, 0x96, 0xa1, 0x46, 0x7e, 0x37, 0x07, 0x83, 0x9e, 0x83, 0xbb, 0x8c, 0x01, 0xb9, 0xe6, + 0xe6, 0xe4, 0x69, 0x27, 0x45, 0x80, 0xee, 0x40, 0x81, 0x5e, 0x01, 0x83, 0xfa, 0x38, 0x89, 0xab, + 0x92, 0x94, 0x37, 0xa3, 0x77, 0xa0, 0xcc, 0x24, 0xde, 0x70, 0x9f, 0x07, 0x98, 0xbe, 0x42, 0x50, + 0xf2, 0x21, 0x6a, 0x5f, 0xfc, 0x9c, 0x05, 0xe7, 0x9f, 0xb3, 0x6e, 0xc1, 0x54, 0x73, 0x18, 0x1e, + 0xb6, 0x5c, 0x12, 0xeb, 0x52, 0xb6, 0xb9, 0x0d, 0x88, 0xf4, 0xae, 0x39, 0x81, 0xb6, 0x9b, 0x0f, + 0xd6, 0x1a, 0xf6, 0xa1, 0xb9, 0x05, 0xd7, 0x48, 0x2f, 0x76, 0x43, 0xa7, 0xa3, 0x9c, 0x2b, 0xc4, + 0xc9, 0xd5, 0x48, 0x9c, 0x5c, 0xed, 0x20, 0x78, 0xe5, 0xf9, 0x5d, 0x6e, 0xbb, 0xe8, 0x5b, 0xa2, + 0xfd, 0x83, 0xc1, 0xa4, 0x79, 0x1e, 0xc4, 0x4e, 0x9d, 0x5f, 0x90, 0x1f, 0xfa, 0x65, 0x28, 0x7a, + 0x03, 0xfa, 0x66, 0x87, 0x27, 0xf3, 0x6e, 0x2c, 0xb0, 0x77, 0x40, 0x0b, 0x9c, 0xf1, 0x36, 0xeb, + 0x55, 0x12, 0x4e, 0x9c, 0x1e, 0x2d, 0x42, 0xf5, 0xd0, 0x0e, 0x0e, 0x71, 0x77, 0x47, 0x30, 0x8f, + 0xa5, 0x3a, 0x1f, 0x5a, 0x89, 0x6e, 0x29, 0xfb, 0x03, 0x29, 0xfa, 0x13, 0x1c, 0x9e, 0x21, 0xba, + 0x9a, 0x1e, 0xbf, 0x2e, 0x86, 0xf0, 0xaa, 0xde, 0x45, 0x46, 0xfd, 0xd0, 0x80, 0xdb, 0x62, 0xd8, + 0xea, 0xa1, 0xed, 0x1e, 0x60, 0x21, 0xcc, 0xcf, 0xab, 0xaf, 0xf4, 0xa4, 0xb3, 0x17, 0x9c, 0xf4, + 0x53, 0xa8, 0x47, 0x93, 0xa6, 0x89, 0x15, 0xaf, 0xa7, 0x4e, 0x62, 0x18, 0xf0, 0x0d, 0x5e, 0xb2, + 0xe8, 0x6f, 0xd2, 0xe6, 0x7b, 0xbd, 0xe8, 0x4e, 0x43, 0x7e, 0x4b, 0x66, 0x9b, 0x70, 0x53, 0x30, + 0xe3, 0x99, 0x8e, 0x38, 0xb7, 0xd4, 0x9c, 0xce, 0xe4, 0xc6, 0xed, 0x41, 0x78, 0x9c, 0xbd, 0x94, + 0xb4, 0x43, 0xe2, 0x26, 0xa4, 0x28, 0x86, 0x0e, 0x65, 0x86, 0xed, 0x00, 0x22, 0xb3, 0x72, 0xfc, + 0x4c, 0xf5, 0x13, 0x96, 0xda, 0x7e, 0xbe, 0x04, 0x48, 0x7f, 0x6a, 0x09, 0x8c, 0x46, 0xc5, 0x30, + 0x13, 0x09, 0x4a, 0xd4, 0xbe, 0x83, 0xfd, 0xbe, 0x13, 0x04, 0x4a, 0x9d, 0x48, 0xa7, 0xae, 0xb7, + 0x20, 0x37, 0xc0, 0x3c, 0x16, 0x97, 0x97, 0x90, 0xd8, 0x13, 0xca, 0x60, 0xda, 0x2f, 0x61, 0xfa, + 0x70, 0x47, 0xc0, 0x30, 0x83, 0x68, 0x71, 0x92, 0x62, 0x8a, 0x4c, 0x76, 0x66, 0x44, 0x26, 0x3b, + 0x1b, 0xcf, 0x64, 0xc7, 0xce, 0x87, 0xaa, 0xa3, 0xba, 0x9a, 0xf3, 0x61, 0x9b, 0x19, 0x20, 0xf2, + 0x6f, 0x57, 0xc3, 0xf5, 0x0f, 0xb8, 0xa3, 0xba, 0xaa, 0xa8, 0x86, 0xe9, 0x9c, 0x45, 0x15, 0x51, + 0x7c, 0x22, 0x13, 0x2a, 0xc4, 0x48, 0x96, 0x9a, 0xe2, 0xcf, 0x59, 0xb1, 0x36, 0xe9, 0x8c, 0x8f, + 0x60, 0x3a, 0xee, 0x8c, 0x2f, 0x25, 0xd4, 0x34, 0xe4, 0x43, 0xef, 0x08, 0x8b, 0x40, 0xcb, 0x3e, + 0x52, 0x6a, 0x8d, 0x1c, 0xf5, 0xd5, 0xa8, 0xf5, 0x9b, 0x92, 0x2b, 0xdd, 0x80, 0x97, 0x9d, 0x01, + 0x59, 0x8e, 0xe2, 0x2a, 0xcb, 0x3e, 0x24, 0xd6, 0x27, 0x70, 0x23, 0xe9, 0x7c, 0xaf, 0x66, 0x12, + 0x7b, 0x6c, 0x73, 0xea, 0xdc, 0xf3, 0xd5, 0x00, 0x7c, 0x26, 0xfd, 0xa4, 0xe2, 0x74, 0xaf, 0x86, + 0xf7, 0xaf, 0x43, 0x43, 0xe7, 0x83, 0xaf, 0x74, 0x2f, 0x46, 0x2e, 0xf9, 0x6a, 0xb8, 0x7e, 0xdf, + 0x90, 0x6c, 0xd5, 0x55, 0xf3, 0xe1, 0x17, 0x61, 0x2b, 0x62, 0xdd, 0xfd, 0x68, 0xf9, 0x2c, 0x46, + 0xde, 0x32, 0xab, 0xf7, 0x96, 0x72, 0x08, 0x25, 0x14, 0xfb, 0x4f, 0xba, 0xfa, 0x2f, 0x73, 0xf5, + 0x72, 0x30, 0x19, 0x77, 0x2e, 0x0b, 0x46, 0xc2, 0x73, 0x04, 0x46, 0x3f, 0x52, 0x5b, 0x45, 0x0d, + 0x52, 0x57, 0x63, 0xba, 0xdf, 0x90, 0x01, 0x26, 0x15, 0xc7, 0xae, 0x06, 0xc1, 0x86, 0xd9, 0xd1, + 0x21, 0xec, 0x4a, 0x20, 0xe6, 0x9b, 0x50, 0x8a, 0x2e, 0xb2, 0xca, 0x43, 0xda, 0x32, 0x14, 0xb7, + 0xb6, 0x77, 0x77, 0x9a, 0xab, 0xe4, 0x9e, 0x36, 0x0d, 0xc5, 0xd5, 0x6d, 0xcb, 0x7a, 0xbe, 0xd3, + 0x26, 0x17, 0xb5, 0xe4, 0xbb, 0x9a, 0xa5, 0x9f, 0x66, 0x21, 0xf3, 0xf4, 0x05, 0xfa, 0x14, 0xf2, + 0xec, 0x5d, 0xd7, 0x19, 0xcf, 0xfb, 0x1a, 0x67, 0x3d, 0x5d, 0x33, 0x5f, 0xfb, 0xde, 0x7f, 0xfe, + 0xf4, 0x0f, 0x33, 0x53, 0x66, 0x65, 0xf1, 0x78, 0x79, 0xf1, 0xe8, 0x78, 0x91, 0x06, 0xd9, 0x47, + 0xc6, 0x3c, 0xfa, 0x1a, 0x64, 0x77, 0x86, 0x21, 0x1a, 0xf9, 0xec, 0xaf, 0x31, 0xfa, 0x35, 0x9b, + 0x79, 0x9d, 0x32, 0x9d, 0x34, 0x81, 0x33, 0x1d, 0x0c, 0x43, 0xc2, 0xf2, 0x5b, 0x50, 0x56, 0xdf, + 0xa2, 0x9d, 0xfb, 0x16, 0xb0, 0x71, 0xfe, 0x3b, 0x37, 0xf3, 0x36, 0x85, 0x7a, 0xcd, 0x44, 0x1c, + 0x8a, 0xbd, 0x96, 0x53, 0x67, 0xd1, 0x3e, 0x71, 0xd1, 0xc8, 0x97, 0x82, 0x8d, 0xd1, 0x4f, 0xdf, + 0x52, 0xb3, 0x08, 0x4f, 0x5c, 0xc2, 0xf2, 0x9b, 0xfc, 0x8d, 0x5b, 0x27, 0x44, 0x77, 0x34, 0x8f, + 0x94, 0xd4, 0xc7, 0x37, 0x8d, 0xd9, 0xd1, 0x04, 0x1c, 0xe4, 0x16, 0x05, 0xb9, 0x61, 0x4e, 0x71, + 0x90, 0x4e, 0x44, 0xf2, 0xc8, 0x98, 0x5f, 0xea, 0x40, 0x9e, 0x96, 0x82, 0xd1, 0x67, 0xe2, 0x47, + 0x43, 0x53, 0x64, 0x1f, 0x61, 0xe8, 0x58, 0x11, 0xd9, 0x9c, 0xa6, 0x40, 0x55, 0xb3, 0x44, 0x80, + 0x68, 0x21, 0xf8, 0x91, 0x31, 0x3f, 0x67, 0xdc, 0x37, 0x96, 0xfe, 0x3a, 0x0f, 0x79, 0x5a, 0x72, + 0x40, 0x47, 0x00, 0xb2, 0xe4, 0x99, 0x9c, 0x5d, 0xaa, 0x9a, 0x9a, 0x9c, 0x5d, 0xba, 0x5a, 0x6a, + 0x36, 0x28, 0xe8, 0xb4, 0x39, 0x49, 0x40, 0x69, 0x25, 0x63, 0x91, 0x16, 0x6e, 0x88, 0x1e, 0x7f, + 0x68, 0xf0, 0xda, 0x0b, 0xdb, 0x66, 0x48, 0xc7, 0x2d, 0x56, 0xee, 0x4c, 0x2e, 0x07, 0x4d, 0x85, + 0xd3, 0x7c, 0x48, 0x01, 0x17, 0xcd, 0x9a, 0x04, 0xf4, 0x29, 0xc5, 0x23, 0x63, 0xfe, 0xb3, 0xba, + 0x79, 0x8d, 0x6b, 0x39, 0xd1, 0x83, 0xbe, 0x03, 0xd5, 0x78, 0x61, 0x0e, 0xdd, 0xd5, 0x60, 0x25, + 0x0b, 0x7d, 0x8d, 0x37, 0xcf, 0x26, 0xe2, 0x32, 0xcd, 0x50, 0x99, 0x38, 0x38, 0x43, 0x3e, 0xc2, + 0x78, 0x60, 0x13, 0x22, 0x6e, 0x03, 0xf4, 0xa7, 0x06, 0xaf, 0xad, 0xca, 0xba, 0x1a, 0xd2, 0x71, + 0x4f, 0x95, 0xef, 0x1a, 0xf7, 0xce, 0xa1, 0xe2, 0x42, 0x7c, 0x48, 0x85, 0xf8, 0xc0, 0x9c, 0x96, + 0x42, 0x84, 0x4e, 0x1f, 0x87, 0x1e, 0x97, 0xe2, 0xb3, 0x5b, 0xe6, 0x6b, 0x31, 0xe5, 0xc4, 0x7a, + 0xa5, 0xb1, 0x58, 0xfd, 0x4b, 0x6b, 0xac, 0x58, 0x89, 0x4d, 0x6b, 0xac, 0x78, 0xf1, 0x4c, 0x67, + 0x2c, 0x5e, 0xed, 0xd2, 0x18, 0x2b, 0xea, 0x59, 0xfa, 0xdf, 0x1c, 0x14, 0x57, 0xd9, 0xdf, 0xca, + 0x20, 0x0f, 0x4a, 0x51, 0x45, 0x08, 0xcd, 0xe8, 0x92, 0xce, 0xf2, 0x2a, 0xd7, 0xb8, 0x33, 0xb2, + 0x9f, 0x0b, 0xf4, 0x06, 0x15, 0xe8, 0x75, 0xf3, 0x06, 0x41, 0xe6, 0x7f, 0x8e, 0xb3, 0xc8, 0x52, + 0x93, 0x8b, 0x76, 0xb7, 0x4b, 0x14, 0xf1, 0x9b, 0x50, 0x51, 0xeb, 0x33, 0xe8, 0x0d, 0x6d, 0xa2, + 0x5b, 0x2d, 0xf6, 0x34, 0xcc, 0xb3, 0x48, 0x38, 0xf2, 0x9b, 0x14, 0x79, 0xc6, 0xbc, 0xa9, 0x41, + 0xf6, 0x29, 0x69, 0x0c, 0x9c, 0x15, 0x52, 0xf4, 0xe0, 0xb1, 0x8a, 0x8d, 0x1e, 0x3c, 0x5e, 0x87, + 0x39, 0x13, 0x7c, 0x48, 0x49, 0x09, 0x78, 0x00, 0x20, 0x2b, 0x1d, 0x48, 0xab, 0x4b, 0xe5, 0xc2, + 0x9a, 0x74, 0x0e, 0xe9, 0x22, 0x89, 0x69, 0x52, 0x58, 0xbe, 0xee, 0x12, 0xb0, 0x3d, 0x27, 0x08, + 0xd9, 0xc6, 0x9c, 0x88, 0xd5, 0x29, 0x90, 0x76, 0x3e, 0xf1, 0xb2, 0x47, 0xe3, 0xee, 0x99, 0x34, + 0x1c, 0xfd, 0x1e, 0x45, 0xbf, 0x63, 0x36, 0x34, 0xe8, 0x03, 0x46, 0x4b, 0x16, 0xdb, 0xff, 0x17, + 0xa0, 0xfc, 0xcc, 0x76, 0xdc, 0x10, 0xbb, 0xb6, 0xdb, 0xc1, 0x68, 0x1f, 0xf2, 0x34, 0x76, 0x27, + 0x1d, 0xb1, 0x9a, 0x96, 0x4f, 0x3a, 0xe2, 0x58, 0x5e, 0xda, 0x9c, 0xa5, 0xc0, 0x0d, 0xf3, 0x3a, + 0x01, 0xee, 0x4b, 0xd6, 0x8b, 0x2c, 0xa3, 0x6d, 0xcc, 0xa3, 0x97, 0x50, 0xe0, 0xf5, 0xe8, 0x04, + 0xa3, 0x58, 0x52, 0xad, 0x71, 0x4b, 0xdf, 0xa9, 0x5b, 0xcb, 0x2a, 0x4c, 0x40, 0xe9, 0x08, 0xce, + 0x31, 0x80, 0x2c, 0xaf, 0x24, 0x2d, 0x9a, 0x2a, 0xcb, 0x34, 0x66, 0x47, 0x13, 0xe8, 0x74, 0xaa, + 0x62, 0x76, 0x23, 0x5a, 0x82, 0xfb, 0x0d, 0xc8, 0xad, 0xdb, 0xc1, 0x21, 0x4a, 0xc4, 0x5e, 0xe5, + 0x41, 0x68, 0xa3, 0xa1, 0xeb, 0xe2, 0x28, 0x77, 0x28, 0xca, 0x4d, 0xe6, 0xca, 0x54, 0x14, 0xfa, + 0x40, 0xd2, 0x98, 0x47, 0x5d, 0x28, 0xb0, 0xd7, 0xa0, 0x49, 0xfd, 0xc5, 0x9e, 0x96, 0x26, 0xf5, + 0x17, 0x7f, 0x40, 0x7a, 0x3e, 0xca, 0x00, 0xc6, 0xc5, 0x1b, 0x4b, 0x94, 0x78, 0x99, 0x92, 0x78, + 0x98, 0xd9, 0x98, 0x19, 0xd5, 0xcd, 0xb1, 0xee, 0x52, 0xac, 0xdb, 0x66, 0x3d, 0x65, 0x2b, 0x4e, + 0xf9, 0xc8, 0x98, 0xbf, 0x6f, 0xa0, 0xef, 0x00, 0xc8, 0xfa, 0x53, 0x6a, 0x07, 0x26, 0x6b, 0x5a, + 0xa9, 0x1d, 0x98, 0x2a, 0x5d, 0x99, 0x0b, 0x14, 0x77, 0xce, 0xbc, 0x9b, 0xc4, 0x0d, 0x7d, 0xdb, + 0x0d, 0x5e, 0x62, 0xff, 0x7d, 0x96, 0xfc, 0x0e, 0x0e, 0x9d, 0x01, 0x99, 0xb2, 0x0f, 0xa5, 0xa8, + 0x3c, 0x90, 0xf4, 0xb6, 0xc9, 0x42, 0x46, 0xd2, 0xdb, 0xa6, 0xea, 0x0a, 0x71, 0xb7, 0x13, 0x5b, + 0x2d, 0x82, 0x94, 0x6c, 0xc0, 0xbf, 0xa8, 0x41, 0x8e, 0x1c, 0xc8, 0xc9, 0xe1, 0x44, 0x26, 0x7b, + 0x92, 0xb3, 0x4f, 0xe5, 0xab, 0x93, 0xb3, 0x4f, 0xe7, 0x89, 0xe2, 0x87, 0x13, 0x72, 0x59, 0x5b, + 0x64, 0x59, 0x14, 0x32, 0x53, 0x0f, 0xca, 0x4a, 0x12, 0x08, 0x69, 0x98, 0xc5, 0xf3, 0xdf, 0xc9, + 0x70, 0xa7, 0xc9, 0x20, 0x99, 0xaf, 0x53, 0xbc, 0xeb, 0x2c, 0xdc, 0x51, 0xbc, 0x2e, 0xa3, 0x20, + 0x80, 0x7c, 0x76, 0x7c, 0xdf, 0x6b, 0x66, 0x17, 0xdf, 0xfb, 0xb3, 0xa3, 0x09, 0x46, 0xce, 0x4e, + 0x6e, 0xfc, 0x57, 0x50, 0x51, 0x13, 0x3f, 0x48, 0x23, 0x7c, 0x22, 0x43, 0x9f, 0x8c, 0x23, 0xba, + 0xbc, 0x51, 0xdc, 0xb3, 0x51, 0x48, 0x5b, 0x21, 0x23, 0xc0, 0x3d, 0x28, 0xf2, 0x04, 0x90, 0x4e, + 0xa5, 0xf1, 0x24, 0xbe, 0x4e, 0xa5, 0x89, 0xec, 0x51, 0xfc, 0xf4, 0x4c, 0x11, 0xc9, 0x45, 0x54, + 0xc4, 0x6a, 0x8e, 0xf6, 0x04, 0x87, 0xa3, 0xd0, 0x64, 0xd2, 0x76, 0x14, 0x9a, 0x92, 0x1f, 0x18, + 0x85, 0x76, 0x80, 0x43, 0xee, 0x0f, 0xc4, 0xe5, 0x1a, 0x8d, 0x60, 0xa6, 0xc6, 0x47, 0xf3, 0x2c, + 0x12, 0xdd, 0xe5, 0x46, 0x02, 0x8a, 0xe0, 0x78, 0x02, 0x20, 0x93, 0x51, 0xc9, 0x13, 0xab, 0xb6, + 0x4e, 0x90, 0x3c, 0xb1, 0xea, 0xf3, 0x59, 0x71, 0xdf, 0x27, 0x71, 0xd9, 0xdd, 0x8a, 0x20, 0xff, + 0xd8, 0x00, 0x94, 0x4e, 0x57, 0xa1, 0x77, 0xf5, 0xdc, 0xb5, 0x35, 0x87, 0xc6, 0x7b, 0x17, 0x23, + 0xd6, 0x85, 0x33, 0x29, 0x52, 0x87, 0x52, 0x0f, 0x5e, 0x11, 0xa1, 0xbe, 0x6b, 0xc0, 0x44, 0x2c, + 0xc5, 0x85, 0xde, 0x1a, 0x61, 0xd3, 0x44, 0xe1, 0xa1, 0xf1, 0xf6, 0xb9, 0x74, 0xba, 0xa3, 0xbc, + 0xb2, 0x02, 0xc4, 0x9d, 0xe6, 0x77, 0x0c, 0xa8, 0xc6, 0x33, 0x61, 0x68, 0x04, 0xef, 0x54, 0xbd, + 0xa2, 0x31, 0x77, 0x3e, 0xe1, 0xd9, 0xe6, 0x91, 0xd7, 0x99, 0x1e, 0x14, 0x79, 0xca, 0x4c, 0xb7, + 0xf0, 0xe3, 0x05, 0x0e, 0xdd, 0xc2, 0x4f, 0xe4, 0xdb, 0x34, 0x0b, 0xdf, 0xf7, 0x7a, 0x58, 0xd9, + 0x66, 0x3c, 0x93, 0x36, 0x0a, 0xed, 0xec, 0x6d, 0x96, 0x48, 0xc3, 0x8d, 0x42, 0x93, 0xdb, 0x4c, + 0x24, 0xcc, 0xd0, 0x08, 0x66, 0xe7, 0x6c, 0xb3, 0x64, 0xbe, 0x4d, 0xb3, 0xcd, 0x28, 0xa0, 0xb2, + 0xcd, 0x64, 0x22, 0x4b, 0xb7, 0xcd, 0x52, 0xb5, 0x18, 0xdd, 0x36, 0x4b, 0xe7, 0xc2, 0x34, 0x76, + 0xa4, 0xb8, 0xb1, 0x6d, 0x76, 0x4d, 0x93, 0xea, 0x42, 0xef, 0x8d, 0x50, 0xa2, 0xb6, 0xb2, 0xd3, + 0x78, 0xff, 0x82, 0xd4, 0x23, 0xd7, 0x38, 0x53, 0xbf, 0x58, 0xe3, 0x7f, 0x64, 0xc0, 0xb4, 0x2e, + 0x3b, 0x86, 0x46, 0xe0, 0x8c, 0x28, 0x04, 0x35, 0x16, 0x2e, 0x4a, 0x7e, 0xb6, 0xb6, 0xa2, 0x55, + 0xff, 0xb8, 0xf6, 0xaf, 0x9f, 0xcf, 0x18, 0xff, 0xf1, 0xf9, 0x8c, 0xf1, 0x5f, 0x9f, 0xcf, 0x18, + 0x3f, 0xf9, 0x9f, 0x99, 0xb1, 0xfd, 0x02, 0xfd, 0x1f, 0x30, 0x2c, 0xff, 0x2c, 0x00, 0x00, 0xff, + 0xff, 0x0d, 0x96, 0x9e, 0x56, 0x27, 0x42, 0x00, 0x00, } // Reference imports to suppress errors if they are not otherwise used. diff --git a/go.mod b/go.mod index 4e2211060443..7deb3a5c670d 100644 --- a/go.mod +++ b/go.mod @@ -17,6 +17,7 @@ replace ( require ( github.com/bgentry/speakeasy v0.1.0 + github.com/coreos/go-semver v0.3.0 github.com/dustin/go-humanize v1.0.0 github.com/spf13/cobra v1.2.1 go.etcd.io/bbolt v1.3.6 @@ -33,6 +34,7 @@ require ( go.uber.org/zap v1.17.0 golang.org/x/time v0.0.0-20210220033141-f8bda1e9f3ba google.golang.org/grpc v1.41.0 + google.golang.org/protobuf v1.27.1 gopkg.in/cheggaaa/pb.v1 v1.0.28 ) @@ -40,7 +42,6 @@ require ( github.com/beorn7/perks v1.0.1 // indirect github.com/cenkalti/backoff/v4 v4.1.1 // indirect github.com/cespare/xxhash/v2 v2.1.1 // indirect - github.com/coreos/go-semver v0.3.0 // indirect github.com/coreos/go-systemd/v22 v22.3.2 // indirect github.com/davecgh/go-spew v1.1.1 // indirect github.com/gogo/protobuf v1.3.2 // indirect @@ -82,7 +83,6 @@ require ( golang.org/x/sys v0.0.0-20211123173158-ef496fb156ab // indirect golang.org/x/text v0.3.7 // indirect google.golang.org/genproto v0.0.0-20211118181313-81c1377c94b1 // indirect - google.golang.org/protobuf v1.27.1 // indirect gopkg.in/natefinch/lumberjack.v2 v2.0.0 // indirect gopkg.in/yaml.v2 v2.4.0 // indirect gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b // indirect diff --git a/scripts/etcd_version_annotations.txt b/scripts/etcd_version_annotations.txt new file mode 100644 index 000000000000..155e9c47d4a8 --- /dev/null +++ b/scripts/etcd_version_annotations.txt @@ -0,0 +1,543 @@ +authpb.Permission: "" +authpb.Permission.READ: "" +authpb.Permission.READWRITE: "" +authpb.Permission.Type: "" +authpb.Permission.WRITE: "" +authpb.Permission.key: "" +authpb.Permission.permType: "" +authpb.Permission.range_end: "" +authpb.Role: "" +authpb.Role.keyPermission: "" +authpb.Role.name: "" +authpb.User: "" +authpb.User.name: "" +authpb.User.options: "" +authpb.User.password: "" +authpb.User.roles: "" +authpb.UserAddOptions: "" +authpb.UserAddOptions.no_password: "" +etcdserverpb.AlarmMember: "3.0" +etcdserverpb.AlarmMember.alarm: "" +etcdserverpb.AlarmMember.memberID: "" +etcdserverpb.AlarmRequest: "3.0" +etcdserverpb.AlarmRequest.ACTIVATE: "" +etcdserverpb.AlarmRequest.AlarmAction: "3.0" +etcdserverpb.AlarmRequest.DEACTIVATE: "" +etcdserverpb.AlarmRequest.GET: "" +etcdserverpb.AlarmRequest.action: "" +etcdserverpb.AlarmRequest.alarm: "" +etcdserverpb.AlarmRequest.memberID: "" +etcdserverpb.AlarmResponse: "3.0" +etcdserverpb.AlarmResponse.alarms: "" +etcdserverpb.AlarmResponse.header: "" +etcdserverpb.AlarmType: "3.0" +etcdserverpb.AuthDisableRequest: "3.0" +etcdserverpb.AuthDisableResponse: "3.0" +etcdserverpb.AuthDisableResponse.header: "" +etcdserverpb.AuthEnableRequest: "3.0" +etcdserverpb.AuthEnableResponse: "3.0" +etcdserverpb.AuthEnableResponse.header: "" +etcdserverpb.AuthRoleAddRequest: "3.0" +etcdserverpb.AuthRoleAddRequest.name: "" +etcdserverpb.AuthRoleAddResponse: "3.0" +etcdserverpb.AuthRoleAddResponse.header: "" +etcdserverpb.AuthRoleDeleteRequest: "3.0" +etcdserverpb.AuthRoleDeleteRequest.role: "" +etcdserverpb.AuthRoleDeleteResponse: "3.0" +etcdserverpb.AuthRoleDeleteResponse.header: "" +etcdserverpb.AuthRoleGetRequest: "3.0" +etcdserverpb.AuthRoleGetRequest.role: "" +etcdserverpb.AuthRoleGetResponse: "" +etcdserverpb.AuthRoleGetResponse.header: "3.0" +etcdserverpb.AuthRoleGetResponse.perm: "3.0" +etcdserverpb.AuthRoleGrantPermissionRequest: "3.0" +etcdserverpb.AuthRoleGrantPermissionRequest.name: "" +etcdserverpb.AuthRoleGrantPermissionRequest.perm: "" +etcdserverpb.AuthRoleGrantPermissionResponse: "3.0" +etcdserverpb.AuthRoleGrantPermissionResponse.header: "" +etcdserverpb.AuthRoleListRequest: "3.0" +etcdserverpb.AuthRoleListResponse: "3.0" +etcdserverpb.AuthRoleListResponse.header: "" +etcdserverpb.AuthRoleListResponse.roles: "" +etcdserverpb.AuthRoleRevokePermissionRequest: "3.0" +etcdserverpb.AuthRoleRevokePermissionRequest.key: "" +etcdserverpb.AuthRoleRevokePermissionRequest.range_end: "" +etcdserverpb.AuthRoleRevokePermissionRequest.role: "" +etcdserverpb.AuthRoleRevokePermissionResponse: "3.0" +etcdserverpb.AuthRoleRevokePermissionResponse.header: "" +etcdserverpb.AuthStatusRequest: "3.5" +etcdserverpb.AuthStatusResponse: "3.5" +etcdserverpb.AuthStatusResponse.authRevision: "" +etcdserverpb.AuthStatusResponse.enabled: "" +etcdserverpb.AuthStatusResponse.header: "" +etcdserverpb.AuthUserAddRequest: "3.0" +etcdserverpb.AuthUserAddRequest.hashedPassword: "3.5" +etcdserverpb.AuthUserAddRequest.name: "" +etcdserverpb.AuthUserAddRequest.options: "3.4" +etcdserverpb.AuthUserAddRequest.password: "" +etcdserverpb.AuthUserAddResponse: "3.0" +etcdserverpb.AuthUserAddResponse.header: "" +etcdserverpb.AuthUserChangePasswordRequest: "3.0" +etcdserverpb.AuthUserChangePasswordRequest.hashedPassword: "3.5" +etcdserverpb.AuthUserChangePasswordRequest.name: "" +etcdserverpb.AuthUserChangePasswordRequest.password: "" +etcdserverpb.AuthUserChangePasswordResponse: "3.0" +etcdserverpb.AuthUserChangePasswordResponse.header: "" +etcdserverpb.AuthUserDeleteRequest: "3.0" +etcdserverpb.AuthUserDeleteRequest.name: "" +etcdserverpb.AuthUserDeleteResponse: "3.0" +etcdserverpb.AuthUserDeleteResponse.header: "" +etcdserverpb.AuthUserGetRequest: "3.0" +etcdserverpb.AuthUserGetRequest.name: "" +etcdserverpb.AuthUserGetResponse: "3.0" +etcdserverpb.AuthUserGetResponse.header: "" +etcdserverpb.AuthUserGetResponse.roles: "" +etcdserverpb.AuthUserGrantRoleRequest: "3.0" +etcdserverpb.AuthUserGrantRoleRequest.role: "" +etcdserverpb.AuthUserGrantRoleRequest.user: "" +etcdserverpb.AuthUserGrantRoleResponse: "3.0" +etcdserverpb.AuthUserGrantRoleResponse.header: "" +etcdserverpb.AuthUserListRequest: "3.0" +etcdserverpb.AuthUserListResponse: "3.0" +etcdserverpb.AuthUserListResponse.header: "" +etcdserverpb.AuthUserListResponse.users: "" +etcdserverpb.AuthUserRevokeRoleRequest: "3.0" +etcdserverpb.AuthUserRevokeRoleRequest.name: "" +etcdserverpb.AuthUserRevokeRoleRequest.role: "" +etcdserverpb.AuthUserRevokeRoleResponse: "3.0" +etcdserverpb.AuthUserRevokeRoleResponse.header: "" +etcdserverpb.AuthenticateRequest: "3.0" +etcdserverpb.AuthenticateRequest.name: "" +etcdserverpb.AuthenticateRequest.password: "" +etcdserverpb.AuthenticateResponse: "3.0" +etcdserverpb.AuthenticateResponse.header: "" +etcdserverpb.AuthenticateResponse.token: "" +etcdserverpb.CORRUPT: "3.3" +etcdserverpb.CompactionRequest: "3.0" +etcdserverpb.CompactionRequest.physical: "" +etcdserverpb.CompactionRequest.revision: "" +etcdserverpb.CompactionResponse: "3.0" +etcdserverpb.CompactionResponse.header: "" +etcdserverpb.Compare: "3.0" +etcdserverpb.Compare.CREATE: "" +etcdserverpb.Compare.CompareResult: "3.0" +etcdserverpb.Compare.CompareTarget: "3.0" +etcdserverpb.Compare.EQUAL: "" +etcdserverpb.Compare.GREATER: "" +etcdserverpb.Compare.LEASE: "3.3" +etcdserverpb.Compare.LESS: "" +etcdserverpb.Compare.MOD: "" +etcdserverpb.Compare.NOT_EQUAL: "3.1" +etcdserverpb.Compare.VALUE: "" +etcdserverpb.Compare.VERSION: "" +etcdserverpb.Compare.create_revision: "" +etcdserverpb.Compare.key: "" +etcdserverpb.Compare.lease: "3.3" +etcdserverpb.Compare.mod_revision: "" +etcdserverpb.Compare.range_end: "3.3" +etcdserverpb.Compare.result: "" +etcdserverpb.Compare.target: "" +etcdserverpb.Compare.value: "" +etcdserverpb.Compare.version: "" +etcdserverpb.DefragmentRequest: "3.0" +etcdserverpb.DefragmentResponse: "3.0" +etcdserverpb.DefragmentResponse.header: "" +etcdserverpb.DeleteRangeRequest: "3.0" +etcdserverpb.DeleteRangeRequest.key: "" +etcdserverpb.DeleteRangeRequest.prev_kv: "3.1" +etcdserverpb.DeleteRangeRequest.range_end: "" +etcdserverpb.DeleteRangeResponse: "3.0" +etcdserverpb.DeleteRangeResponse.deleted: "" +etcdserverpb.DeleteRangeResponse.header: "" +etcdserverpb.DeleteRangeResponse.prev_kvs: "3.1" +etcdserverpb.DowngradeRequest: "3.5" +etcdserverpb.DowngradeRequest.CANCEL: "" +etcdserverpb.DowngradeRequest.DowngradeAction: "3.5" +etcdserverpb.DowngradeRequest.ENABLE: "" +etcdserverpb.DowngradeRequest.VALIDATE: "" +etcdserverpb.DowngradeRequest.action: "" +etcdserverpb.DowngradeRequest.version: "" +etcdserverpb.DowngradeResponse: "3.5" +etcdserverpb.DowngradeResponse.header: "" +etcdserverpb.DowngradeResponse.version: "" +etcdserverpb.EmptyResponse: "" +etcdserverpb.HashKVRequest: "3.3" +etcdserverpb.HashKVRequest.revision: "" +etcdserverpb.HashKVResponse: "3.3" +etcdserverpb.HashKVResponse.compact_revision: "" +etcdserverpb.HashKVResponse.hash: "" +etcdserverpb.HashKVResponse.header: "" +etcdserverpb.HashRequest: "3.0" +etcdserverpb.HashResponse: "3.0" +etcdserverpb.HashResponse.hash: "" +etcdserverpb.HashResponse.header: "" +etcdserverpb.InternalAuthenticateRequest: "3.0" +etcdserverpb.InternalAuthenticateRequest.name: "" +etcdserverpb.InternalAuthenticateRequest.password: "" +etcdserverpb.InternalAuthenticateRequest.simple_token: "" +etcdserverpb.InternalRaftRequest: "3.0" +etcdserverpb.InternalRaftRequest.ID: "" +etcdserverpb.InternalRaftRequest.alarm: "" +etcdserverpb.InternalRaftRequest.auth_disable: "" +etcdserverpb.InternalRaftRequest.auth_enable: "" +etcdserverpb.InternalRaftRequest.auth_role_add: "" +etcdserverpb.InternalRaftRequest.auth_role_delete: "" +etcdserverpb.InternalRaftRequest.auth_role_get: "" +etcdserverpb.InternalRaftRequest.auth_role_grant_permission: "" +etcdserverpb.InternalRaftRequest.auth_role_list: "" +etcdserverpb.InternalRaftRequest.auth_role_revoke_permission: "" +etcdserverpb.InternalRaftRequest.auth_status: "3.5" +etcdserverpb.InternalRaftRequest.auth_user_add: "" +etcdserverpb.InternalRaftRequest.auth_user_change_password: "" +etcdserverpb.InternalRaftRequest.auth_user_delete: "" +etcdserverpb.InternalRaftRequest.auth_user_get: "" +etcdserverpb.InternalRaftRequest.auth_user_grant_role: "" +etcdserverpb.InternalRaftRequest.auth_user_list: "" +etcdserverpb.InternalRaftRequest.auth_user_revoke_role: "" +etcdserverpb.InternalRaftRequest.authenticate: "" +etcdserverpb.InternalRaftRequest.cluster_member_attr_set: "3.5" +etcdserverpb.InternalRaftRequest.cluster_version_set: "3.5" +etcdserverpb.InternalRaftRequest.compaction: "" +etcdserverpb.InternalRaftRequest.delete_range: "" +etcdserverpb.InternalRaftRequest.downgrade_info_set: "3.5" +etcdserverpb.InternalRaftRequest.header: "" +etcdserverpb.InternalRaftRequest.lease_checkpoint: "3.4" +etcdserverpb.InternalRaftRequest.lease_grant: "" +etcdserverpb.InternalRaftRequest.lease_revoke: "" +etcdserverpb.InternalRaftRequest.put: "" +etcdserverpb.InternalRaftRequest.range: "" +etcdserverpb.InternalRaftRequest.txn: "" +etcdserverpb.InternalRaftRequest.v2: "" +etcdserverpb.LeaseCheckpoint: "3.4" +etcdserverpb.LeaseCheckpoint.ID: "" +etcdserverpb.LeaseCheckpoint.remaining_TTL: "" +etcdserverpb.LeaseCheckpointRequest: "3.4" +etcdserverpb.LeaseCheckpointRequest.checkpoints: "" +etcdserverpb.LeaseCheckpointResponse: "3.4" +etcdserverpb.LeaseCheckpointResponse.header: "" +etcdserverpb.LeaseGrantRequest: "3.0" +etcdserverpb.LeaseGrantRequest.ID: "" +etcdserverpb.LeaseGrantRequest.TTL: "" +etcdserverpb.LeaseGrantResponse: "3.0" +etcdserverpb.LeaseGrantResponse.ID: "" +etcdserverpb.LeaseGrantResponse.TTL: "" +etcdserverpb.LeaseGrantResponse.error: "" +etcdserverpb.LeaseGrantResponse.header: "" +etcdserverpb.LeaseKeepAliveRequest: "3.0" +etcdserverpb.LeaseKeepAliveRequest.ID: "" +etcdserverpb.LeaseKeepAliveResponse: "3.0" +etcdserverpb.LeaseKeepAliveResponse.ID: "" +etcdserverpb.LeaseKeepAliveResponse.TTL: "" +etcdserverpb.LeaseKeepAliveResponse.header: "" +etcdserverpb.LeaseLeasesRequest: "3.3" +etcdserverpb.LeaseLeasesResponse: "3.3" +etcdserverpb.LeaseLeasesResponse.header: "" +etcdserverpb.LeaseLeasesResponse.leases: "" +etcdserverpb.LeaseRevokeRequest: "3.0" +etcdserverpb.LeaseRevokeRequest.ID: "" +etcdserverpb.LeaseRevokeResponse: "3.0" +etcdserverpb.LeaseRevokeResponse.header: "" +etcdserverpb.LeaseStatus: "3.3" +etcdserverpb.LeaseStatus.ID: "" +etcdserverpb.LeaseTimeToLiveRequest: "3.1" +etcdserverpb.LeaseTimeToLiveRequest.ID: "" +etcdserverpb.LeaseTimeToLiveRequest.keys: "" +etcdserverpb.LeaseTimeToLiveResponse: "3.1" +etcdserverpb.LeaseTimeToLiveResponse.ID: "" +etcdserverpb.LeaseTimeToLiveResponse.TTL: "" +etcdserverpb.LeaseTimeToLiveResponse.grantedTTL: "" +etcdserverpb.LeaseTimeToLiveResponse.header: "" +etcdserverpb.LeaseTimeToLiveResponse.keys: "" +etcdserverpb.Member: "3.0" +etcdserverpb.Member.ID: "" +etcdserverpb.Member.clientURLs: "" +etcdserverpb.Member.isLearner: "3.4" +etcdserverpb.Member.name: "" +etcdserverpb.Member.peerURLs: "" +etcdserverpb.MemberAddRequest: "3.0" +etcdserverpb.MemberAddRequest.isLearner: "3.4" +etcdserverpb.MemberAddRequest.peerURLs: "" +etcdserverpb.MemberAddResponse: "3.0" +etcdserverpb.MemberAddResponse.header: "" +etcdserverpb.MemberAddResponse.member: "" +etcdserverpb.MemberAddResponse.members: "" +etcdserverpb.MemberListRequest: "3.0" +etcdserverpb.MemberListRequest.linearizable: "3.5" +etcdserverpb.MemberListResponse: "3.0" +etcdserverpb.MemberListResponse.header: "" +etcdserverpb.MemberListResponse.members: "" +etcdserverpb.MemberPromoteRequest: "3.4" +etcdserverpb.MemberPromoteRequest.ID: "" +etcdserverpb.MemberPromoteResponse: "3.4" +etcdserverpb.MemberPromoteResponse.header: "" +etcdserverpb.MemberPromoteResponse.members: "" +etcdserverpb.MemberRemoveRequest: "3.0" +etcdserverpb.MemberRemoveRequest.ID: "" +etcdserverpb.MemberRemoveResponse: "3.0" +etcdserverpb.MemberRemoveResponse.header: "" +etcdserverpb.MemberRemoveResponse.members: "" +etcdserverpb.MemberUpdateRequest: "3.0" +etcdserverpb.MemberUpdateRequest.ID: "" +etcdserverpb.MemberUpdateRequest.peerURLs: "" +etcdserverpb.MemberUpdateResponse: "3.0" +etcdserverpb.MemberUpdateResponse.header: "" +etcdserverpb.MemberUpdateResponse.members: "3.1" +etcdserverpb.Metadata: "" +etcdserverpb.Metadata.ClusterID: "" +etcdserverpb.Metadata.NodeID: "" +etcdserverpb.MoveLeaderRequest: "3.3" +etcdserverpb.MoveLeaderRequest.targetID: "" +etcdserverpb.MoveLeaderResponse: "3.3" +etcdserverpb.MoveLeaderResponse.header: "" +etcdserverpb.NONE: "" +etcdserverpb.NOSPACE: "" +etcdserverpb.PutRequest: "3.0" +etcdserverpb.PutRequest.ignore_lease: "3.2" +etcdserverpb.PutRequest.ignore_value: "3.2" +etcdserverpb.PutRequest.key: "" +etcdserverpb.PutRequest.lease: "" +etcdserverpb.PutRequest.prev_kv: "3.1" +etcdserverpb.PutRequest.value: "" +etcdserverpb.PutResponse: "3.0" +etcdserverpb.PutResponse.header: "" +etcdserverpb.PutResponse.prev_kv: "3.1" +etcdserverpb.RangeRequest: "3.0" +etcdserverpb.RangeRequest.ASCEND: "" +etcdserverpb.RangeRequest.CREATE: "" +etcdserverpb.RangeRequest.DESCEND: "" +etcdserverpb.RangeRequest.KEY: "" +etcdserverpb.RangeRequest.MOD: "" +etcdserverpb.RangeRequest.NONE: "" +etcdserverpb.RangeRequest.SortOrder: "3.0" +etcdserverpb.RangeRequest.SortTarget: "3.0" +etcdserverpb.RangeRequest.VALUE: "" +etcdserverpb.RangeRequest.VERSION: "" +etcdserverpb.RangeRequest.count_only: "" +etcdserverpb.RangeRequest.key: "" +etcdserverpb.RangeRequest.keys_only: "" +etcdserverpb.RangeRequest.limit: "" +etcdserverpb.RangeRequest.max_create_revision: "3.1" +etcdserverpb.RangeRequest.max_mod_revision: "3.1" +etcdserverpb.RangeRequest.min_create_revision: "3.1" +etcdserverpb.RangeRequest.min_mod_revision: "3.1" +etcdserverpb.RangeRequest.range_end: "" +etcdserverpb.RangeRequest.revision: "" +etcdserverpb.RangeRequest.serializable: "" +etcdserverpb.RangeRequest.sort_order: "" +etcdserverpb.RangeRequest.sort_target: "" +etcdserverpb.RangeResponse: "3.0" +etcdserverpb.RangeResponse.count: "" +etcdserverpb.RangeResponse.header: "" +etcdserverpb.RangeResponse.kvs: "" +etcdserverpb.RangeResponse.more: "" +etcdserverpb.Request: "" +etcdserverpb.Request.Dir: "" +etcdserverpb.Request.Expiration: "" +etcdserverpb.Request.ID: "" +etcdserverpb.Request.Method: "" +etcdserverpb.Request.Path: "" +etcdserverpb.Request.PrevExist: "" +etcdserverpb.Request.PrevIndex: "" +etcdserverpb.Request.PrevValue: "" +etcdserverpb.Request.Quorum: "" +etcdserverpb.Request.Recursive: "" +etcdserverpb.Request.Refresh: "" +etcdserverpb.Request.Since: "" +etcdserverpb.Request.Sorted: "" +etcdserverpb.Request.Stream: "" +etcdserverpb.Request.Time: "" +etcdserverpb.Request.Val: "" +etcdserverpb.Request.Wait: "" +etcdserverpb.RequestHeader: "3.0" +etcdserverpb.RequestHeader.ID: "" +etcdserverpb.RequestHeader.auth_revision: "3.1" +etcdserverpb.RequestHeader.username: "" +etcdserverpb.RequestOp: "3.0" +etcdserverpb.RequestOp.request_delete_range: "" +etcdserverpb.RequestOp.request_put: "" +etcdserverpb.RequestOp.request_range: "" +etcdserverpb.RequestOp.request_txn: "3.3" +etcdserverpb.ResponseHeader: "3.0" +etcdserverpb.ResponseHeader.cluster_id: "" +etcdserverpb.ResponseHeader.member_id: "" +etcdserverpb.ResponseHeader.raft_term: "" +etcdserverpb.ResponseHeader.revision: "" +etcdserverpb.ResponseOp: "3.0" +etcdserverpb.ResponseOp.response_delete_range: "" +etcdserverpb.ResponseOp.response_put: "" +etcdserverpb.ResponseOp.response_range: "" +etcdserverpb.ResponseOp.response_txn: "3.3" +etcdserverpb.SnapshotRequest: "3.3" +etcdserverpb.SnapshotResponse: "3.3" +etcdserverpb.SnapshotResponse.blob: "" +etcdserverpb.SnapshotResponse.header: "" +etcdserverpb.SnapshotResponse.remaining_bytes: "" +etcdserverpb.SnapshotResponse.version: "3.6" +etcdserverpb.StatusRequest: "3.0" +etcdserverpb.StatusResponse: "3.0" +etcdserverpb.StatusResponse.dbSize: "" +etcdserverpb.StatusResponse.dbSizeInUse: "3.4" +etcdserverpb.StatusResponse.errors: "3.4" +etcdserverpb.StatusResponse.header: "" +etcdserverpb.StatusResponse.isLearner: "3.4" +etcdserverpb.StatusResponse.leader: "" +etcdserverpb.StatusResponse.raftAppliedIndex: "3.4" +etcdserverpb.StatusResponse.raftIndex: "" +etcdserverpb.StatusResponse.raftTerm: "" +etcdserverpb.StatusResponse.version: "" +etcdserverpb.TxnRequest: "3.0" +etcdserverpb.TxnRequest.compare: "" +etcdserverpb.TxnRequest.failure: "" +etcdserverpb.TxnRequest.success: "" +etcdserverpb.TxnResponse: "3.0" +etcdserverpb.TxnResponse.header: "" +etcdserverpb.TxnResponse.responses: "" +etcdserverpb.TxnResponse.succeeded: "" +etcdserverpb.WatchCancelRequest: "3.1" +etcdserverpb.WatchCancelRequest.watch_id: "3.1" +etcdserverpb.WatchCreateRequest: "3.0" +etcdserverpb.WatchCreateRequest.FilterType: "3.1" +etcdserverpb.WatchCreateRequest.NODELETE: "" +etcdserverpb.WatchCreateRequest.NOPUT: "" +etcdserverpb.WatchCreateRequest.filters: "3.1" +etcdserverpb.WatchCreateRequest.fragment: "3.4" +etcdserverpb.WatchCreateRequest.key: "" +etcdserverpb.WatchCreateRequest.prev_kv: "3.1" +etcdserverpb.WatchCreateRequest.progress_notify: "" +etcdserverpb.WatchCreateRequest.range_end: "" +etcdserverpb.WatchCreateRequest.start_revision: "" +etcdserverpb.WatchCreateRequest.watch_id: "3.4" +etcdserverpb.WatchProgressRequest: "3.4" +etcdserverpb.WatchRequest: "3.0" +etcdserverpb.WatchRequest.cancel_request: "" +etcdserverpb.WatchRequest.create_request: "" +etcdserverpb.WatchRequest.progress_request: "3.4" +etcdserverpb.WatchResponse: "3.0" +etcdserverpb.WatchResponse.cancel_reason: "3.4" +etcdserverpb.WatchResponse.canceled: "" +etcdserverpb.WatchResponse.compact_revision: "" +etcdserverpb.WatchResponse.created: "" +etcdserverpb.WatchResponse.events: "" +etcdserverpb.WatchResponse.fragment: "3.4" +etcdserverpb.WatchResponse.header: "" +etcdserverpb.WatchResponse.watch_id: "" +membershippb.Attributes: "3.5" +membershippb.Attributes.client_urls: "" +membershippb.Attributes.name: "" +membershippb.ClusterMemberAttrSetRequest: "3.5" +membershippb.ClusterMemberAttrSetRequest.member_ID: "" +membershippb.ClusterMemberAttrSetRequest.member_attributes: "" +membershippb.ClusterVersionSetRequest: "3.5" +membershippb.ClusterVersionSetRequest.ver: "" +membershippb.DowngradeInfoSetRequest: "3.5" +membershippb.DowngradeInfoSetRequest.enabled: "" +membershippb.DowngradeInfoSetRequest.ver: "" +membershippb.Member: "3.5" +membershippb.Member.ID: "" +membershippb.Member.member_attributes: "" +membershippb.Member.raft_attributes: "" +membershippb.RaftAttributes: "3.5" +membershippb.RaftAttributes.is_learner: "" +membershippb.RaftAttributes.peer_urls: "" +mvccpb.Event: "" +mvccpb.Event.DELETE: "" +mvccpb.Event.EventType: "" +mvccpb.Event.PUT: "" +mvccpb.Event.kv: "" +mvccpb.Event.prev_kv: "" +mvccpb.Event.type: "" +mvccpb.KeyValue: "" +mvccpb.KeyValue.create_revision: "" +mvccpb.KeyValue.key: "" +mvccpb.KeyValue.lease: "" +mvccpb.KeyValue.mod_revision: "" +mvccpb.KeyValue.value: "" +mvccpb.KeyValue.version: "" +raftpb.ConfChange: "3.0" +raftpb.ConfChange.context: "" +raftpb.ConfChange.id: "" +raftpb.ConfChange.node_id: "" +raftpb.ConfChange.type: "" +raftpb.ConfChangeAddLearnerNode: "" +raftpb.ConfChangeAddNode: "" +raftpb.ConfChangeRemoveNode: "" +raftpb.ConfChangeSingle: "" +raftpb.ConfChangeSingle.node_id: "" +raftpb.ConfChangeSingle.type: "" +raftpb.ConfChangeTransition: "3.4" +raftpb.ConfChangeTransitionAuto: "" +raftpb.ConfChangeTransitionJointExplicit: "" +raftpb.ConfChangeTransitionJointImplicit: "" +raftpb.ConfChangeType: "" +raftpb.ConfChangeUpdateNode: "" +raftpb.ConfChangeV2: "3.4" +raftpb.ConfChangeV2.changes: "" +raftpb.ConfChangeV2.context: "" +raftpb.ConfChangeV2.transition: "" +raftpb.ConfState: "" +raftpb.ConfState.auto_leave: "" +raftpb.ConfState.learners: "" +raftpb.ConfState.learners_next: "" +raftpb.ConfState.voters: "" +raftpb.ConfState.voters_outgoing: "" +raftpb.Entry: "3.0" +raftpb.Entry.Data: "" +raftpb.Entry.Index: "" +raftpb.Entry.Term: "" +raftpb.Entry.Type: "" +raftpb.EntryConfChange: "" +raftpb.EntryConfChangeV2: "3.4" +raftpb.EntryNormal: "" +raftpb.EntryType: "3.0" +raftpb.HardState: "" +raftpb.HardState.commit: "" +raftpb.HardState.term: "" +raftpb.HardState.vote: "" +raftpb.Message: "" +raftpb.Message.commit: "" +raftpb.Message.context: "" +raftpb.Message.entries: "" +raftpb.Message.from: "" +raftpb.Message.index: "" +raftpb.Message.logTerm: "" +raftpb.Message.reject: "" +raftpb.Message.rejectHint: "" +raftpb.Message.snapshot: "" +raftpb.Message.term: "" +raftpb.Message.to: "" +raftpb.Message.type: "" +raftpb.MessageType: "" +raftpb.MsgApp: "" +raftpb.MsgAppResp: "" +raftpb.MsgBeat: "" +raftpb.MsgCheckQuorum: "" +raftpb.MsgHeartbeat: "" +raftpb.MsgHeartbeatResp: "" +raftpb.MsgHup: "" +raftpb.MsgPreVote: "" +raftpb.MsgPreVoteResp: "" +raftpb.MsgProp: "" +raftpb.MsgReadIndex: "" +raftpb.MsgReadIndexResp: "" +raftpb.MsgSnap: "" +raftpb.MsgSnapStatus: "" +raftpb.MsgTimeoutNow: "" +raftpb.MsgTransferLeader: "" +raftpb.MsgUnreachable: "" +raftpb.MsgVote: "" +raftpb.MsgVoteResp: "" +raftpb.Snapshot: "" +raftpb.Snapshot.data: "" +raftpb.Snapshot.metadata: "" +raftpb.SnapshotMetadata: "" +raftpb.SnapshotMetadata.conf_state: "" +raftpb.SnapshotMetadata.index: "" +raftpb.SnapshotMetadata.term: "" +walpb.Record: "" +walpb.Record.crc: "" +walpb.Record.data: "" +walpb.Record.type: "" +walpb.Snapshot: "" +walpb.Snapshot.conf_state: "" +walpb.Snapshot.index: "" +walpb.Snapshot.term: "" diff --git a/scripts/update_proto_annotations.sh b/scripts/update_proto_annotations.sh new file mode 100755 index 000000000000..0d18304e1fa3 --- /dev/null +++ b/scripts/update_proto_annotations.sh @@ -0,0 +1,9 @@ +#!/usr/bin/env bash + +set -o errexit +set -o nounset +set -o pipefail + +tmpfile=$(mktemp) +go run ./tools/proto-annotations/main.go --annotation etcd_version > "${tmpfile}" +mv "${tmpfile}" ./scripts/etcd_version_annotations.txt diff --git a/scripts/verify_proto_annotations.sh b/scripts/verify_proto_annotations.sh new file mode 100755 index 000000000000..79f481fe5173 --- /dev/null +++ b/scripts/verify_proto_annotations.sh @@ -0,0 +1,18 @@ +#!/usr/bin/env bash + +set -o errexit +set -o nounset +set -o pipefail + +tmpfile=$(mktemp) +go run ./tools/proto-annotations/main.go --annotation=etcd_version > "${tmpfile}" +if diff -u ./scripts/etcd_version_annotations.txt "${tmpfile}"; then + echo "PASSED proto-annotations verification!" + exit 0 +fi +echo "Failed proto-annotations-verification!" >&2 +echo "If you are adding new proto fields/messages that will be included in raft log:" >&2 +echo "* Please add etcd_version annotation in *.proto file with next etcd version" >&2 +echo "* Run ./scripts/getproto.sh" >&2 +echo "* Run ./scripts/update_proto_annotations.sh" >&2 +exit 1 diff --git a/server/storage/wal/version.go b/server/storage/wal/version.go index 6a4903b98539..906ca2198f64 100644 --- a/server/storage/wal/version.go +++ b/server/storage/wal/version.go @@ -106,7 +106,8 @@ func etcdVersionFromMessage(m protoreflect.Message) *semver.Version { md := m.Descriptor() opts := md.Options().(*descriptorpb.MessageOptions) if opts != nil { - maxVer = maxVersion(maxVer, etcdVersionFromOptionsString(opts.String())) + ver, _ := EtcdVersionFromOptionsString(opts.String()) + maxVer = maxVersion(maxVer, ver) } m.Range(func(field protoreflect.FieldDescriptor, value protoreflect.Value) bool { @@ -127,12 +128,14 @@ func etcdVersionFromEnum(enum protoreflect.EnumDescriptor, value protoreflect.En var maxVer *semver.Version enumOpts := enum.Options().(*descriptorpb.EnumOptions) if enumOpts != nil { - maxVer = maxVersion(maxVer, etcdVersionFromOptionsString(enumOpts.String())) + ver, _ := EtcdVersionFromOptionsString(enumOpts.String()) + maxVer = maxVersion(maxVer, ver) } valueDesc := enum.Values().Get(int(value)) valueOpts := valueDesc.Options().(*descriptorpb.EnumValueOptions) if valueOpts != nil { - maxVer = maxVersion(maxVer, etcdVersionFromOptionsString(valueOpts.String())) + ver, _ := EtcdVersionFromOptionsString(valueOpts.String()) + maxVer = maxVersion(maxVer, ver) } return maxVer } @@ -149,10 +152,11 @@ func etcdVersionFromField(fd protoreflect.FieldDescriptor) *semver.Version { if opts == nil { return nil } - return etcdVersionFromOptionsString(opts.String()) + ver, _ := EtcdVersionFromOptionsString(opts.String()) + return ver } -func etcdVersionFromOptionsString(opts string) *semver.Version { +func EtcdVersionFromOptionsString(opts string) (*semver.Version, error) { // TODO: Use proto.GetExtention when gogo/protobuf is usable with protoreflect msgs := []string{"[versionpb.etcd_version_msg]:", "[versionpb.etcd_version_field]:", "[versionpb.etcd_version_enum]:", "[versionpb.etcd_version_enum_value]:"} var end, index int @@ -164,16 +168,19 @@ func etcdVersionFromOptionsString(opts string) *semver.Version { } } if index == -1 { - return nil + return nil, nil } var verStr string _, err := fmt.Sscanf(opts[end:], "%q", &verStr) if err != nil { - return nil + return nil, err } - ver, err := semver.NewVersion(verStr + ".0") + if strings.Count(verStr, ".") == 1 { + verStr = verStr + ".0" + } + ver, err := semver.NewVersion(verStr) if err != nil { - panic(err) + return nil, err } - return ver + return ver, nil } diff --git a/server/storage/wal/version_test.go b/server/storage/wal/version_test.go index 52965662cb21..88857cf3e816 100644 --- a/server/storage/wal/version_test.go +++ b/server/storage/wal/version_test.go @@ -237,7 +237,8 @@ func TestEtcdVersionFromFieldOptionsString(t *testing.T) { } for _, tc := range tcs { t.Run(tc.input, func(t *testing.T) { - ver := etcdVersionFromOptionsString(tc.input) + ver, err := EtcdVersionFromOptionsString(tc.input) + assert.NoError(t, err) assert.Equal(t, ver, tc.expect) }) } diff --git a/test.sh b/test.sh index 586fa32923c5..f6851b484005 100755 --- a/test.sh +++ b/test.sh @@ -382,6 +382,7 @@ function fmt_pass { dep \ shellcheck \ shellws \ + proto_annotations \ ; do run_pass "${p}" "${@}" done @@ -668,6 +669,10 @@ function mod_tidy_pass { run_for_modules mod_tidy_for_module } +function proto_annotations_pass { + "${ETCD_ROOT_DIR}/scripts/verify_proto_annotations.sh" +} + ########### MAIN ############################################################### function run_pass { diff --git a/tools/mod/libs.go b/tools/mod/libs.go index 0d05c21853a4..1a1191f93cea 100644 --- a/tools/mod/libs.go +++ b/tools/mod/libs.go @@ -12,6 +12,7 @@ // See the License for the specific language governing permissions and // limitations under the License. +//go:build libs // +build libs // This file implements that pattern: diff --git a/tools/mod/tools.go b/tools/mod/tools.go index 9f6305e98a1d..f8a017173130 100644 --- a/tools/mod/tools.go +++ b/tools/mod/tools.go @@ -12,6 +12,7 @@ // See the License for the specific language governing permissions and // limitations under the License. +//go:build tools // +build tools // This file implements that pattern: @@ -33,9 +34,9 @@ import ( _ "github.com/mdempsky/unconvert" _ "github.com/mgechev/revive" _ "github.com/mikefarah/yq/v3" + _ "go.etcd.io/protodoc" _ "gotest.tools" _ "gotest.tools/gotestsum" - _ "go.etcd.io/protodoc" _ "honnef.co/go/tools/cmd/staticcheck" _ "mvdan.cc/unparam" ) diff --git a/tools/proto-annotations/main.go b/tools/proto-annotations/main.go new file mode 100644 index 000000000000..a5345325a4f0 --- /dev/null +++ b/tools/proto-annotations/main.go @@ -0,0 +1,215 @@ +// Copyright 2021 The etcd Authors +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package main + +import ( + "bytes" + "flag" + "fmt" + "io" + "os" + "sort" + + "github.com/coreos/go-semver/semver" + "go.etcd.io/etcd/server/v3/storage/wal" + "google.golang.org/protobuf/reflect/protoreflect" + "google.golang.org/protobuf/reflect/protoregistry" +) + +const ( + EtcdVersionAnnotation = "etcd_version" +) + +func main() { + annotation := flag.String("annotation", "", "Specify what proto annotation to read. Options: etcd_version") + flag.Parse() + var errs []error + switch *annotation { + case EtcdVersionAnnotation: + errs = handleEtcdVersion() + case "": + fmt.Fprintf(os.Stderr, "Please provide --annotation flag") + os.Exit(1) + default: + fmt.Fprintf(os.Stderr, "Unknown annotation %q. Options: etcd_version", *annotation) + os.Exit(1) + } + if len(errs) != 0 { + for _, err := range errs { + fmt.Fprintln(os.Stderr, err) + } + os.Exit(1) + } + os.Exit(0) +} + +func handleEtcdVersion() (errs []error) { + annotations, err := allEtcdVersionAnnotations() + if err != nil { + errs = append(errs, err) + return errs + } + sort.Slice(annotations, func(i, j int) bool { + return annotations[i].fullName < annotations[j].fullName + }) + output := &bytes.Buffer{} + for _, a := range annotations { + newErrs := a.Validate() + if len(newErrs) == 0 { + err := a.PrintLine(output) + if err != nil { + errs = append(errs, err) + return errs + } + } + errs = append(errs, newErrs...) + } + if len(errs) == 0 { + fmt.Print(output) + } + return errs +} + +func allEtcdVersionAnnotations() (annotations []etcdVersionAnnotation, err error) { + var fileAnnotations []etcdVersionAnnotation + protoregistry.GlobalFiles.RangeFiles(func(file protoreflect.FileDescriptor) bool { + switch string(file.Package()) { + // Skip external packages that are not expected to have etcd version annotation. + case "io.prometheus.client", "grpc.binarylog.v1", "google.protobuf", "google.rpc", "google.api": + return true + } + fileAnnotations, err = fileEtcdVersionAnnotations(file) + if err != nil { + return false + } + annotations = append(annotations, fileAnnotations...) + return true + }) + return annotations, err +} + +func fileEtcdVersionAnnotations(file protoreflect.FileDescriptor) (annotations []etcdVersionAnnotation, err error) { + err = visitFileDescriptor(file, func(path string, ver *semver.Version) error { + a := etcdVersionAnnotation{fullName: path, version: ver} + annotations = append(annotations, a) + return nil + }) + return annotations, err +} + +type Visitor func(path string, ver *semver.Version) error + +func visitFileDescriptor(file protoreflect.FileDescriptor, visitor Visitor) error { + msgs := file.Messages() + for i := 0; i < msgs.Len(); i++ { + err := visitMessageDescriptor(msgs.Get(i), visitor) + if err != nil { + return err + } + } + enums := file.Enums() + for i := 0; i < enums.Len(); i++ { + err := visitEnumDescriptor(enums.Get(i), visitor) + if err != nil { + return err + } + } + return nil +} + +func visitMessageDescriptor(md protoreflect.MessageDescriptor, visitor Visitor) error { + err := VisitDescriptor(md, visitor) + if err != nil { + return err + } + fields := md.Fields() + for i := 0; i < fields.Len(); i++ { + fd := fields.Get(i) + err = VisitDescriptor(fd, visitor) + if err != nil { + return err + } + } + + enums := md.Enums() + for i := 0; i < enums.Len(); i++ { + err := visitEnumDescriptor(enums.Get(i), visitor) + if err != nil { + return err + } + } + return err +} + +func visitEnumDescriptor(enum protoreflect.EnumDescriptor, visitor Visitor) error { + err := VisitDescriptor(enum, visitor) + if err != nil { + return err + } + fields := enum.Values() + for i := 0; i < fields.Len(); i++ { + fd := fields.Get(i) + err = VisitDescriptor(fd, visitor) + if err != nil { + return err + } + } + return err +} + +func VisitDescriptor(md protoreflect.Descriptor, visitor Visitor) error { + s, ok := md.Options().(fmt.Stringer) + if !ok { + return nil + } + ver, err := wal.EtcdVersionFromOptionsString(s.String()) + if err != nil { + return fmt.Errorf("%s: %s", md.FullName(), err) + } + return visitor(string(md.FullName()), ver) +} + +type etcdVersionAnnotation struct { + fullName string + version *semver.Version +} + +func (a etcdVersionAnnotation) Validate() (errs []error) { + if a.version == nil { + return nil + } + if a.version.Major == 0 { + errs = append(errs, fmt.Errorf("%s: etcd_version major version should not be zero", a.fullName)) + } + if a.version.Patch != 0 { + errs = append(errs, fmt.Errorf("%s: etcd_version patch version should be zero", a.fullName)) + } + if a.version.PreRelease != "" { + errs = append(errs, fmt.Errorf("%s: etcd_version should not be prerelease", a.fullName)) + } + if a.version.Metadata != "" { + errs = append(errs, fmt.Errorf("%s: etcd_version should not have metadata", a.fullName)) + } + return errs +} + +func (a etcdVersionAnnotation) PrintLine(out io.Writer) error { + if a.version == nil { + _, err := fmt.Fprintf(out, "%s: \"\"\n", a.fullName) + return err + } + _, err := fmt.Fprintf(out, "%s: \"%d.%d\"\n", a.fullName, a.version.Major, a.version.Minor) + return err +} From d865bb96f18408464e088699f8f98e113bdbb441 Mon Sep 17 00:00:00 2001 From: Marek Siarkowicz Date: Fri, 19 Nov 2021 17:04:02 +0100 Subject: [PATCH 098/258] server: Refactor wal version to use visitor pattern --- server/storage/wal/version.go | 168 +++++++++++++++++++++-------- server/storage/wal/version_test.go | 21 +++- tools/proto-annotations/main.go | 76 +------------ 3 files changed, 143 insertions(+), 122 deletions(-) diff --git a/server/storage/wal/version.go b/server/storage/wal/version.go index 906ca2198f64..0190db98e2cd 100644 --- a/server/storage/wal/version.go +++ b/server/storage/wal/version.go @@ -53,32 +53,63 @@ func (w *walVersion) MinimalEtcdVersion() *semver.Version { func MinimalEtcdVersion(ents []raftpb.Entry) *semver.Version { var maxVer *semver.Version for _, ent := range ents { - maxVer = maxVersion(maxVer, etcdVersionFromEntry(ent)) + err := visitEntry(ent, func(path protoreflect.FullName, ver *semver.Version) error { + maxVer = maxVersion(maxVer, ver) + return nil + }) + if err != nil { + panic(err) + } } return maxVer } -func etcdVersionFromEntry(ent raftpb.Entry) *semver.Version { - msgVer := etcdVersionFromMessage(proto.MessageReflect(&ent)) - dataVer := etcdVersionFromData(ent.Type, ent.Data) - return maxVersion(msgVer, dataVer) +type Visitor func(path protoreflect.FullName, ver *semver.Version) error + +func VisitFileDescriptor(file protoreflect.FileDescriptor, visitor Visitor) error { + msgs := file.Messages() + for i := 0; i < msgs.Len(); i++ { + err := visitMessageDescriptor(msgs.Get(i), visitor) + if err != nil { + return err + } + } + enums := file.Enums() + for i := 0; i < enums.Len(); i++ { + err := visitEnumDescriptor(enums.Get(i), visitor) + if err != nil { + return err + } + } + return nil +} + +func visitEntry(ent raftpb.Entry, visitor Visitor) error { + err := visitMessage(proto.MessageReflect(&ent), visitor) + if err != nil { + return err + } + return visitEntryData(ent.Type, ent.Data, visitor) } -func etcdVersionFromData(entryType raftpb.EntryType, data []byte) *semver.Version { +func visitEntryData(entryType raftpb.EntryType, data []byte, visitor Visitor) error { var msg protoreflect.Message - var ver *semver.Version switch entryType { case raftpb.EntryNormal: var raftReq etcdserverpb.InternalRaftRequest err := pbutil.Unmarshaler(&raftReq).Unmarshal(data) if err != nil { - return nil + return err } msg = proto.MessageReflect(&raftReq) if raftReq.ClusterVersionSet != nil { - ver, err = semver.NewVersion(raftReq.ClusterVersionSet.Ver) + ver, err := semver.NewVersion(raftReq.ClusterVersionSet.Ver) if err != nil { - panic(err) + return err + } + err = visitor(msg.Descriptor().FullName(), ver) + if err != nil { + return err } } case raftpb.EntryConfChange: @@ -98,46 +129,106 @@ func etcdVersionFromData(entryType raftpb.EntryType, data []byte) *semver.Versio default: panic("unhandled") } - return maxVersion(etcdVersionFromMessage(msg), ver) + return visitMessage(msg, visitor) } -func etcdVersionFromMessage(m protoreflect.Message) *semver.Version { - var maxVer *semver.Version - md := m.Descriptor() - opts := md.Options().(*descriptorpb.MessageOptions) - if opts != nil { - ver, _ := EtcdVersionFromOptionsString(opts.String()) - maxVer = maxVersion(maxVer, ver) +func visitMessageDescriptor(md protoreflect.MessageDescriptor, visitor Visitor) error { + err := visitDescriptor(md, visitor) + if err != nil { + return err + } + fields := md.Fields() + for i := 0; i < fields.Len(); i++ { + fd := fields.Get(i) + err = visitDescriptor(fd, visitor) + if err != nil { + return err + } } + enums := md.Enums() + for i := 0; i < enums.Len(); i++ { + err := visitEnumDescriptor(enums.Get(i), visitor) + if err != nil { + return err + } + } + return err +} + +func visitMessage(m protoreflect.Message, visitor Visitor) error { + md := m.Descriptor() + err := visitDescriptor(md, visitor) + if err != nil { + return err + } m.Range(func(field protoreflect.FieldDescriptor, value protoreflect.Value) bool { fd := md.Fields().Get(field.Index()) - maxVer = maxVersion(maxVer, etcdVersionFromField(fd)) + err = visitDescriptor(fd, visitor) + if err != nil { + return false + } + switch m := value.Interface().(type) { case protoreflect.Message: - maxVer = maxVersion(maxVer, etcdVersionFromMessage(m)) + err = visitMessage(m, visitor) case protoreflect.EnumNumber: - maxVer = maxVersion(maxVer, etcdVersionFromEnum(field.Enum(), m)) + err = visitEnumNumber(fd.Enum(), m, visitor) + } + if err != nil { + return false } return true }) - return maxVer + return err } -func etcdVersionFromEnum(enum protoreflect.EnumDescriptor, value protoreflect.EnumNumber) *semver.Version { - var maxVer *semver.Version - enumOpts := enum.Options().(*descriptorpb.EnumOptions) - if enumOpts != nil { - ver, _ := EtcdVersionFromOptionsString(enumOpts.String()) - maxVer = maxVersion(maxVer, ver) +func visitEnumDescriptor(enum protoreflect.EnumDescriptor, visitor Visitor) error { + err := visitDescriptor(enum, visitor) + if err != nil { + return err + } + fields := enum.Values() + for i := 0; i < fields.Len(); i++ { + fd := fields.Get(i) + err = visitDescriptor(fd, visitor) + if err != nil { + return err + } + } + return err +} + +func visitEnumNumber(enum protoreflect.EnumDescriptor, number protoreflect.EnumNumber, visitor Visitor) error { + err := visitDescriptor(enum, visitor) + if err != nil { + return err } - valueDesc := enum.Values().Get(int(value)) - valueOpts := valueDesc.Options().(*descriptorpb.EnumValueOptions) + return visitEnumValue(enum.Values().Get(int(number)), visitor) +} + +func visitEnumValue(enum protoreflect.EnumValueDescriptor, visitor Visitor) error { + valueOpts := enum.Options().(*descriptorpb.EnumValueOptions) if valueOpts != nil { - ver, _ := EtcdVersionFromOptionsString(valueOpts.String()) - maxVer = maxVersion(maxVer, ver) + ver, _ := etcdVersionFromOptionsString(valueOpts.String()) + err := visitor(enum.FullName(), ver) + if err != nil { + return err + } } - return maxVer + return nil +} + +func visitDescriptor(md protoreflect.Descriptor, visitor Visitor) error { + opts, ok := md.Options().(fmt.Stringer) + if !ok { + return nil + } + ver, err := etcdVersionFromOptionsString(opts.String()) + if err != nil { + return fmt.Errorf("%s: %s", md.FullName(), err) + } + return visitor(md.FullName(), ver) } func maxVersion(a *semver.Version, b *semver.Version) *semver.Version { @@ -147,16 +238,7 @@ func maxVersion(a *semver.Version, b *semver.Version) *semver.Version { return b } -func etcdVersionFromField(fd protoreflect.FieldDescriptor) *semver.Version { - opts := fd.Options().(*descriptorpb.FieldOptions) - if opts == nil { - return nil - } - ver, _ := EtcdVersionFromOptionsString(opts.String()) - return ver -} - -func EtcdVersionFromOptionsString(opts string) (*semver.Version, error) { +func etcdVersionFromOptionsString(opts string) (*semver.Version, error) { // TODO: Use proto.GetExtention when gogo/protobuf is usable with protoreflect msgs := []string{"[versionpb.etcd_version_msg]:", "[versionpb.etcd_version_field]:", "[versionpb.etcd_version_enum]:", "[versionpb.etcd_version_enum_value]:"} var end, index int diff --git a/server/storage/wal/version_test.go b/server/storage/wal/version_test.go index 88857cf3e816..ace1ac5e344a 100644 --- a/server/storage/wal/version_test.go +++ b/server/storage/wal/version_test.go @@ -25,6 +25,7 @@ import ( "go.etcd.io/etcd/api/v3/membershippb" "go.etcd.io/etcd/pkg/v3/pbutil" "go.etcd.io/etcd/raft/v3/raftpb" + "google.golang.org/protobuf/reflect/protoreflect" ) var ( @@ -97,8 +98,13 @@ func TestEtcdVersionFromEntry(t *testing.T) { } for _, tc := range tcs { t.Run(tc.name, func(t *testing.T) { - ver := etcdVersionFromEntry(tc.input) - assert.Equal(t, tc.expect, ver) + var maxVer *semver.Version + err := visitEntry(tc.input, func(path protoreflect.FullName, ver *semver.Version) error { + maxVer = maxVersion(maxVer, ver) + return nil + }) + assert.NoError(t, err) + assert.Equal(t, tc.expect, maxVer) }) } } @@ -162,8 +168,13 @@ func TestEtcdVersionFromMessage(t *testing.T) { } for _, tc := range tcs { t.Run(tc.name, func(t *testing.T) { - ver := etcdVersionFromMessage(proto.MessageReflect(tc.input)) - assert.Equal(t, tc.expect, ver) + var maxVer *semver.Version + err := visitMessage(proto.MessageReflect(tc.input), func(path protoreflect.FullName, ver *semver.Version) error { + maxVer = maxVersion(maxVer, ver) + return nil + }) + assert.NoError(t, err) + assert.Equal(t, tc.expect, maxVer) }) } } @@ -237,7 +248,7 @@ func TestEtcdVersionFromFieldOptionsString(t *testing.T) { } for _, tc := range tcs { t.Run(tc.input, func(t *testing.T) { - ver, err := EtcdVersionFromOptionsString(tc.input) + ver, err := etcdVersionFromOptionsString(tc.input) assert.NoError(t, err) assert.Equal(t, ver, tc.expect) }) diff --git a/tools/proto-annotations/main.go b/tools/proto-annotations/main.go index a5345325a4f0..105f829fb2de 100644 --- a/tools/proto-annotations/main.go +++ b/tools/proto-annotations/main.go @@ -101,7 +101,7 @@ func allEtcdVersionAnnotations() (annotations []etcdVersionAnnotation, err error } func fileEtcdVersionAnnotations(file protoreflect.FileDescriptor) (annotations []etcdVersionAnnotation, err error) { - err = visitFileDescriptor(file, func(path string, ver *semver.Version) error { + err = wal.VisitFileDescriptor(file, func(path protoreflect.FullName, ver *semver.Version) error { a := etcdVersionAnnotation{fullName: path, version: ver} annotations = append(annotations, a) return nil @@ -109,80 +109,8 @@ func fileEtcdVersionAnnotations(file protoreflect.FileDescriptor) (annotations [ return annotations, err } -type Visitor func(path string, ver *semver.Version) error - -func visitFileDescriptor(file protoreflect.FileDescriptor, visitor Visitor) error { - msgs := file.Messages() - for i := 0; i < msgs.Len(); i++ { - err := visitMessageDescriptor(msgs.Get(i), visitor) - if err != nil { - return err - } - } - enums := file.Enums() - for i := 0; i < enums.Len(); i++ { - err := visitEnumDescriptor(enums.Get(i), visitor) - if err != nil { - return err - } - } - return nil -} - -func visitMessageDescriptor(md protoreflect.MessageDescriptor, visitor Visitor) error { - err := VisitDescriptor(md, visitor) - if err != nil { - return err - } - fields := md.Fields() - for i := 0; i < fields.Len(); i++ { - fd := fields.Get(i) - err = VisitDescriptor(fd, visitor) - if err != nil { - return err - } - } - - enums := md.Enums() - for i := 0; i < enums.Len(); i++ { - err := visitEnumDescriptor(enums.Get(i), visitor) - if err != nil { - return err - } - } - return err -} - -func visitEnumDescriptor(enum protoreflect.EnumDescriptor, visitor Visitor) error { - err := VisitDescriptor(enum, visitor) - if err != nil { - return err - } - fields := enum.Values() - for i := 0; i < fields.Len(); i++ { - fd := fields.Get(i) - err = VisitDescriptor(fd, visitor) - if err != nil { - return err - } - } - return err -} - -func VisitDescriptor(md protoreflect.Descriptor, visitor Visitor) error { - s, ok := md.Options().(fmt.Stringer) - if !ok { - return nil - } - ver, err := wal.EtcdVersionFromOptionsString(s.String()) - if err != nil { - return fmt.Errorf("%s: %s", md.FullName(), err) - } - return visitor(string(md.FullName()), ver) -} - type etcdVersionAnnotation struct { - fullName string + fullName protoreflect.FullName version *semver.Version } From 4bfcd8425919a94275f95c97fb99a02d6ec40f56 Mon Sep 17 00:00:00 2001 From: Marek Siarkowicz Date: Thu, 2 Dec 2021 15:44:38 +0100 Subject: [PATCH 099/258] server: Handle V2Request when analysis WAL entries --- server/storage/wal/version.go | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/server/storage/wal/version.go b/server/storage/wal/version.go index 0190db98e2cd..8fe6725e8cdd 100644 --- a/server/storage/wal/version.go +++ b/server/storage/wal/version.go @@ -97,9 +97,15 @@ func visitEntryData(entryType raftpb.EntryType, data []byte, visitor Visitor) er switch entryType { case raftpb.EntryNormal: var raftReq etcdserverpb.InternalRaftRequest - err := pbutil.Unmarshaler(&raftReq).Unmarshal(data) - if err != nil { - return err + if err := pbutil.Unmarshaler(&raftReq).Unmarshal(data); err != nil { + // try V2 Request + var r etcdserverpb.Request + if pbutil.Unmarshaler(&r).Unmarshal(data) != nil { + // return original error + return err + } + msg = proto.MessageReflect(&r) + break } msg = proto.MessageReflect(&raftReq) if raftReq.ClusterVersionSet != nil { From 50b09d4f885af5a2d7f936f8cae09bc758299139 Mon Sep 17 00:00:00 2001 From: Marek Siarkowicz Date: Wed, 26 Jan 2022 15:34:59 +0100 Subject: [PATCH 100/258] Re-enable code coverage upload --- .github/workflows/coverage.yaml | 28 +++++++++++++++++++++++++ README.md | 2 +- test.sh | 2 +- tests/framework/e2e/etcd_spawn.go | 24 +++++++++++++++++++++ tests/framework/e2e/etcd_spawn_cov.go | 10 +++------ tests/framework/e2e/etcd_spawn_nocov.go | 25 ---------------------- tests/framework/e2e/util.go | 21 +++++++++++++++++++ 7 files changed, 78 insertions(+), 34 deletions(-) create mode 100644 .github/workflows/coverage.yaml create mode 100644 tests/framework/e2e/etcd_spawn.go diff --git a/.github/workflows/coverage.yaml b/.github/workflows/coverage.yaml new file mode 100644 index 000000000000..0bab51853434 --- /dev/null +++ b/.github/workflows/coverage.yaml @@ -0,0 +1,28 @@ +name: Coverage +on: [push, pull_request] +jobs: + coverage: + runs-on: ubuntu-latest + strategy: + fail-fast: false + matrix: + target: + - linux-amd64-coverage + steps: + - uses: actions/checkout@v2 + - uses: actions/setup-go@v2 + with: + go-version: "1.17.6" + - env: + TARGET: ${{ matrix.target }} + run: | + mkdir "${TARGET}" + case "${TARGET}" in + linux-amd64-coverage) + GOARCH=amd64 ./scripts/codecov_upload.sh + ;; + *) + echo "Failed to find target" + exit 1 + ;; + esac diff --git a/README.md b/README.md index 27c8555bd1db..ee813ed9f41e 100644 --- a/README.md +++ b/README.md @@ -1,7 +1,7 @@ # etcd [![Go Report Card](https://goreportcard.com/badge/github.com/etcd-io/etcd?style=flat-square)](https://goreportcard.com/report/github.com/etcd-io/etcd) -[![Coverage](https://codecov.io/gh/etcd-io/etcd/branch/master/graph/badge.svg)](https://codecov.io/gh/etcd-io/etcd) +[![Coverage](https://codecov.io/gh/etcd-io/etcd/branch/main/graph/badge.svg)](https://codecov.io/gh/etcd-io/etcd) [![Tests](https://github.com/etcd-io/etcd/actions/workflows/tests.yaml/badge.svg)](https://github.com/etcd-io/etcd/actions/workflows/tests.yaml) [![asset-transparency](https://github.com/etcd-io/etcd/actions/workflows/asset-transparency.yaml/badge.svg)](https://github.com/etcd-io/etcd/actions/workflows/asset-transparency.yaml) [![codeql-analysis](https://github.com/etcd-io/etcd/actions/workflows/codeql-analysis.yml/badge.svg)](https://github.com/etcd-io/etcd/actions/workflows/codeql-analysis.yml) diff --git a/test.sh b/test.sh index 586fa32923c5..808e4d902ba9 100755 --- a/test.sh +++ b/test.sh @@ -320,7 +320,7 @@ function cov_pass { -timeout=5m "${gocov_build_flags[@]}" "$@" || failed="$failed integration_v2" # integration_cluster_proxy run_for_module "tests" go_test "./integration/..." "parallel" "pkg_to_coverprofileflag integration_cluster_proxy" \ - -tags cluster_proxy -timeout=5m "${gocov_build_flags[@]}" || failed="$failed integration_cluster_proxy" + -tags cluster_proxy -timeout=30m "${gocov_build_flags[@]}" || failed="$failed integration_cluster_proxy" log_callout "[$(date)] Collecting coverage from e2e tests ..." # We don't pass 'gocov_build_flags' nor 'pkg_to_coverprofileflag' here, diff --git a/tests/framework/e2e/etcd_spawn.go b/tests/framework/e2e/etcd_spawn.go new file mode 100644 index 000000000000..f8d1e472b5c3 --- /dev/null +++ b/tests/framework/e2e/etcd_spawn.go @@ -0,0 +1,24 @@ +// Copyright 2022 The etcd Authors +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package e2e + +import ( + "go.etcd.io/etcd/pkg/v3/expect" + "go.uber.org/zap" +) + +func SpawnCmd(args []string, envVars map[string]string) (*expect.ExpectProcess, error) { + return SpawnCmdWithLogger(zap.NewNop(), args, envVars) +} diff --git a/tests/framework/e2e/etcd_spawn_cov.go b/tests/framework/e2e/etcd_spawn_cov.go index 7c4ff8c0fe23..9f27d9f83bdb 100644 --- a/tests/framework/e2e/etcd_spawn_cov.go +++ b/tests/framework/e2e/etcd_spawn_cov.go @@ -36,13 +36,9 @@ var ( coverDir = integration.MustAbsPath(os.Getenv("COVERDIR")) ) -func SpawnCmd(args []string) (*expect.ExpectProcess, error) { - return SpawnCmdWithLogger(zap.NewNop(), args) -} - -func SpawnCmdWithLogger(lg *zap.Logger, args []string) (*expect.ExpectProcess, error) { +func SpawnCmdWithLogger(lg *zap.Logger, args []string, envVars map[string]string) (*expect.ExpectProcess, error) { cmd := args[0] - env := make([]string, 0) + env := mergeEnvVariables(envVars) switch { case strings.HasSuffix(cmd, "/etcd"): cmd = cmd + "_test" @@ -66,7 +62,7 @@ func SpawnCmdWithLogger(lg *zap.Logger, args []string) (*expect.ExpectProcess, e } // when withFlagByEnv() is used in testCtl(), env variables for ctl is set to os.env. // they must be included in ctl_cov_env. - env = append(env, os.Environ()...) + all_args := append(args[1:], covArgs...) lg.Info("spawning process", zap.Strings("args", all_args), zap.String("working-dir", wd)) ep, err := expect.NewExpectWithEnv(cmd, all_args, env) diff --git a/tests/framework/e2e/etcd_spawn_nocov.go b/tests/framework/e2e/etcd_spawn_nocov.go index a9343ccea2be..6df08539de69 100644 --- a/tests/framework/e2e/etcd_spawn_nocov.go +++ b/tests/framework/e2e/etcd_spawn_nocov.go @@ -18,7 +18,6 @@ package e2e import ( - "fmt" "os" "strings" @@ -28,10 +27,6 @@ import ( const noOutputLineCount = 0 // regular binaries emit no extra lines -func SpawnCmd(args []string, envVars map[string]string) (*expect.ExpectProcess, error) { - return SpawnCmdWithLogger(zap.NewNop(), args, envVars) -} - func SpawnCmdWithLogger(lg *zap.Logger, args []string, envVars map[string]string) (*expect.ExpectProcess, error) { wd, err := os.Getwd() if err != nil { @@ -46,23 +41,3 @@ func SpawnCmdWithLogger(lg *zap.Logger, args []string, envVars map[string]string lg.Info("spawning process", zap.Strings("args", args), zap.String("working-dir", wd), zap.Strings("environment-variables", env)) return expect.NewExpectWithEnv(args[0], args[1:], env) } - -func mergeEnvVariables(envVars map[string]string) []string { - var env []string - // Environment variables are passed as parameter have higher priority - // than os environment variables. - for k, v := range envVars { - env = append(env, fmt.Sprintf("%s=%s", k, v)) - } - - // Now, we can set os environment variables not passed as parameter. - currVars := os.Environ() - for _, v := range currVars { - p := strings.Split(v, "=") - if _, ok := envVars[p[0]]; !ok { - env = append(env, fmt.Sprintf("%s=%s", p[0], p[1])) - } - } - - return env -} diff --git a/tests/framework/e2e/util.go b/tests/framework/e2e/util.go index 5d66ba4cb893..8ea76ee40736 100644 --- a/tests/framework/e2e/util.go +++ b/tests/framework/e2e/util.go @@ -18,6 +18,7 @@ import ( "encoding/json" "fmt" "math/rand" + "os" "strings" "testing" "time" @@ -131,3 +132,23 @@ func ExecuteWithTimeout(t *testing.T, timeout time.Duration, f func()) { case <-donec: } } + +func mergeEnvVariables(envVars map[string]string) []string { + var env []string + // Environment variables are passed as parameter have higher priority + // than os environment variables. + for k, v := range envVars { + env = append(env, fmt.Sprintf("%s=%s", k, v)) + } + + // Now, we can set os environment variables not passed as parameter. + currVars := os.Environ() + for _, v := range currVars { + p := strings.Split(v, "=") + if _, ok := envVars[p[0]]; !ok { + env = append(env, fmt.Sprintf("%s=%s", p[0], p[1])) + } + } + + return env +} From f57e4a207d17de08da593fb0ee4228e028ec4465 Mon Sep 17 00:00:00 2001 From: Sahdev Zala Date: Wed, 26 Jan 2022 18:24:49 -0500 Subject: [PATCH 101/258] Add Marek as a project maintainer Marek is one of the current reviewers. He has consistently performed all the tasks to earn a top-level maintainer role as described in the https://github.com/etcd-io/etcd/blob/main/GOVERNANCE.md#maintainers Per discussion with existing maintainers, I nominate him for the maintainer role. Marek, thank you for your outstanding contributions to the project. --- MAINTAINERS | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/MAINTAINERS b/MAINTAINERS index 1ecc76a4ea74..5e3e50a2bee4 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -13,6 +13,7 @@ Gyuho Lee (@gyuho) pkg:* Hitoshi Mitake (@mitake) pkg:* Jingyi Hu (@jingyih) pkg:* Joe Betz (@jpbetz) pkg:* +Marek Siarkowicz (@serathius) pkg:* Piotr Tabor (@ptabor) pkg:* Sahdev Zala (@spzala) pkg:* Sam Batschelet (@hexfusion) pkg:* @@ -24,6 +25,5 @@ Tobias Grieger (@tbg) pkg:go.etcd.io/etcd/raft # REVIEWERS Lili Cosic (lilic@) pkg:* -Marek Siarkowicz (serathius@) pkg:* Wilson Wang (wilsonwang371@) pkg:* From 1713dc67b5149e74cd28bad7c080c646315d0b06 Mon Sep 17 00:00:00 2001 From: ahrtr Date: Thu, 9 Dec 2021 06:20:34 +0800 Subject: [PATCH 102/258] etcd server shouldn't wait for the ready notification infinitely on startup --- CHANGELOG/CHANGELOG-3.6.md | 1 + server/config/config.go | 4 ++ server/embed/config.go | 23 +++++---- server/embed/etcd.go | 2 + server/embed/serve.go | 11 ++++- server/etcdmain/config.go | 1 + server/etcdmain/help.go | 2 + tests/e2e/ctl_v3_kv_no_quorum_test.go | 71 +++++++++++++++++++++++++++ tests/e2e/ctl_v3_test.go | 38 ++++++++------ tests/framework/e2e/cluster.go | 31 ++++++++---- 10 files changed, 148 insertions(+), 36 deletions(-) create mode 100644 tests/e2e/ctl_v3_kv_no_quorum_test.go diff --git a/CHANGELOG/CHANGELOG-3.6.md b/CHANGELOG/CHANGELOG-3.6.md index 75c6fc8f0e43..443633bb5767 100644 --- a/CHANGELOG/CHANGELOG-3.6.md +++ b/CHANGELOG/CHANGELOG-3.6.md @@ -35,6 +35,7 @@ See [code changes](https://github.com/etcd-io/etcd/compare/v3.5.0...v3.6.0). - Add [`etcd --experimental-max-learners`](https://github.com/etcd-io/etcd/pull/13377) flag to allow configuration of learner max membership. - Add [`etcd --experimental-enable-lease-checkpoint-persist`](https://github.com/etcd-io/etcd/pull/13508) flag to handle upgrade from v3.5.2 clusters with this feature enabled. - Add [`etcdctl make-mirror --rev`](https://github.com/etcd-io/etcd/pull/13519) flag to support incremental mirror. +- Add [`etcd --experimental-wait-cluster-ready-timeout`](https://github.com/etcd-io/etcd/pull/13525) flag to wait for cluster to be ready before serving client requests. - Fix [non mutating requests pass through quotaKVServer when NOSPACE](https://github.com/etcd-io/etcd/pull/13435) - Fix [exclude the same alarm type activated by multiple peers](https://github.com/etcd-io/etcd/pull/13467). - Fix [Provide a better liveness probe for when etcd runs as a Kubernetes pod](https://github.com/etcd-io/etcd/pull/13399) diff --git a/server/config/config.go b/server/config/config.go index 43ecab7ecd5f..15cb526f469c 100644 --- a/server/config/config.go +++ b/server/config/config.go @@ -80,6 +80,10 @@ type ServerConfig struct { TickMs uint ElectionTicks int + // WaitClusterReadyTimeout is the maximum time to wait for the + // cluster to be ready on startup before serving client requests. + WaitClusterReadyTimeout time.Duration + // InitialElectionTickAdvance is true, then local member fast-forwards // election ticks to speed up "initial" leader election trigger. This // benefits the case of larger election ticks. For instance, cross diff --git a/server/embed/config.go b/server/embed/config.go index 46d9df0add6a..c63a9f971285 100644 --- a/server/embed/config.go +++ b/server/embed/config.go @@ -60,6 +60,7 @@ const ( DefaultGRPCKeepAliveInterval = 2 * time.Hour DefaultGRPCKeepAliveTimeout = 20 * time.Second DefaultDowngradeCheckTime = 5 * time.Second + DefaultWaitClusterReadyTimeout = 5 * time.Second DefaultListenPeerURLs = "http://localhost:2380" DefaultListenClientURLs = "http://localhost:2379" @@ -212,14 +213,15 @@ type Config struct { // Note that cipher suites are prioritized in the given order. CipherSuites []string `json:"cipher-suites"` - ClusterState string `json:"initial-cluster-state"` - DNSCluster string `json:"discovery-srv"` - DNSClusterServiceName string `json:"discovery-srv-name"` - Dproxy string `json:"discovery-proxy"` - Durl string `json:"discovery"` - InitialCluster string `json:"initial-cluster"` - InitialClusterToken string `json:"initial-cluster-token"` - StrictReconfigCheck bool `json:"strict-reconfig-check"` + ClusterState string `json:"initial-cluster-state"` + DNSCluster string `json:"discovery-srv"` + DNSClusterServiceName string `json:"discovery-srv-name"` + Dproxy string `json:"discovery-proxy"` + Durl string `json:"discovery"` + InitialCluster string `json:"initial-cluster"` + InitialClusterToken string `json:"initial-cluster-token"` + StrictReconfigCheck bool `json:"strict-reconfig-check"` + ExperimentalWaitClusterReadyTimeout time.Duration `json:"wait-cluster-ready-timeout"` // AutoCompactionMode is either 'periodic' or 'revision'. AutoCompactionMode string `json:"auto-compaction-mode"` @@ -471,8 +473,9 @@ func NewConfig() *Config { APUrls: []url.URL{*apurl}, ACUrls: []url.URL{*acurl}, - ClusterState: ClusterStateFlagNew, - InitialClusterToken: "etcd-cluster", + ClusterState: ClusterStateFlagNew, + InitialClusterToken: "etcd-cluster", + ExperimentalWaitClusterReadyTimeout: DefaultWaitClusterReadyTimeout, StrictReconfigCheck: DefaultStrictReconfigCheck, Metrics: "basic", diff --git a/server/embed/etcd.go b/server/embed/etcd.go index 70484277016f..825c56869ad0 100644 --- a/server/embed/etcd.go +++ b/server/embed/etcd.go @@ -181,6 +181,7 @@ func StartEtcd(inCfg *Config) (e *Etcd, err error) { PeerTLSInfo: cfg.PeerTLSInfo, TickMs: cfg.TickMs, ElectionTicks: cfg.ElectionTicks(), + WaitClusterReadyTimeout: cfg.ExperimentalWaitClusterReadyTimeout, InitialElectionTickAdvance: cfg.InitialElectionTickAdvance, AutoCompactionRetention: autoCompactionRetention, AutoCompactionMode: cfg.AutoCompactionMode, @@ -321,6 +322,7 @@ func print(lg *zap.Logger, ec Config, sc config.ServerConfig, memberInitialized zap.Bool("force-new-cluster", sc.ForceNewCluster), zap.String("heartbeat-interval", fmt.Sprintf("%v", time.Duration(sc.TickMs)*time.Millisecond)), zap.String("election-timeout", fmt.Sprintf("%v", time.Duration(sc.ElectionTicks*int(sc.TickMs))*time.Millisecond)), + zap.String("wait-cluster-ready-timeout", sc.WaitClusterReadyTimeout.String()), zap.Bool("initial-election-tick-advance", sc.InitialElectionTickAdvance), zap.Uint64("snapshot-count", sc.SnapshotCount), zap.Uint64("snapshot-catchup-entries", sc.SnapshotCatchUpEntries), diff --git a/server/embed/serve.go b/server/embed/serve.go index 455abd43d36f..bce15a339d8a 100644 --- a/server/embed/serve.go +++ b/server/embed/serve.go @@ -23,6 +23,7 @@ import ( "net" "net/http" "strings" + "time" etcdservergw "go.etcd.io/etcd/api/v3/etcdserverpb/gw" "go.etcd.io/etcd/client/pkg/v3/transport" @@ -93,7 +94,15 @@ func (sctx *serveCtx) serve( errHandler func(error), gopts ...grpc.ServerOption) (err error) { logger := defaultLog.New(io.Discard, "etcdhttp", 0) - <-s.ReadyNotify() + + // When the quorum isn't satisfied, then etcd server will be blocked + // on <-s.ReadyNotify(). Set a timeout here so that the etcd server + // can continue to serve serializable read request. + select { + case <-time.After(s.Cfg.WaitClusterReadyTimeout): + sctx.lg.Warn("timed out waiting for the ready notification") + case <-s.ReadyNotify(): + } sctx.lg.Info("ready to serve client requests") diff --git a/server/etcdmain/config.go b/server/etcdmain/config.go index 4257f1ba081b..efb9368a14a5 100644 --- a/server/etcdmain/config.go +++ b/server/etcdmain/config.go @@ -293,6 +293,7 @@ func newConfig() *config { fs.BoolVar(&cfg.ec.ExperimentalTxnModeWriteWithSharedBuffer, "experimental-txn-mode-write-with-shared-buffer", true, "Enable the write transaction to use a shared buffer in its readonly check operations.") fs.UintVar(&cfg.ec.ExperimentalBootstrapDefragThresholdMegabytes, "experimental-bootstrap-defrag-threshold-megabytes", 0, "Enable the defrag during etcd server bootstrap on condition that it will free at least the provided threshold of disk space. Needs to be set to non-zero value to take effect.") fs.IntVar(&cfg.ec.ExperimentalMaxLearners, "experimental-max-learners", membership.DefaultMaxLearners, "Sets the maximum number of learners that can be available in the cluster membership.") + fs.DurationVar(&cfg.ec.ExperimentalWaitClusterReadyTimeout, "experimental-wait-cluster-ready-timeout", cfg.ec.ExperimentalWaitClusterReadyTimeout, "Maximum duration to wait for the cluster to be ready.") // unsafe fs.BoolVar(&cfg.ec.UnsafeNoFsync, "unsafe-no-fsync", false, "Disables fsync, unsafe, will cause data loss.") diff --git a/server/etcdmain/help.go b/server/etcdmain/help.go index b9dea2e3c4e2..fdd62cb094d6 100644 --- a/server/etcdmain/help.go +++ b/server/etcdmain/help.go @@ -250,6 +250,8 @@ Experimental feature: Set time duration after which a warning is generated if a unary request takes more than this duration. --experimental-max-learners '1' Set the max number of learner members allowed in the cluster membership. + --experimental-wait-cluster-ready-timeout '5s' + Set the maximum time duration to wait for the cluster to be ready. Unsafe feature: --force-new-cluster 'false' diff --git a/tests/e2e/ctl_v3_kv_no_quorum_test.go b/tests/e2e/ctl_v3_kv_no_quorum_test.go new file mode 100644 index 000000000000..942a6e4a9290 --- /dev/null +++ b/tests/e2e/ctl_v3_kv_no_quorum_test.go @@ -0,0 +1,71 @@ +// Copyright 2021 The etcd Authors +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +// When the quorum isn't satisfied, then each etcd member isn't able to +// publish/register server information(i.e., clientURL) into the cluster. +// Accordingly, the v2 proxy can't get any member's clientURL, so this +// case will fail for sure in this case. +// +// todo(ahrtr): When v2 proxy is removed, then we can remove the go build +// lines below. +//go:build !cluster_proxy +// +build !cluster_proxy + +package e2e + +import ( + "testing" + + "go.etcd.io/etcd/tests/v3/framework/e2e" +) + +func TestSerializableReadWithoutQuorum(t *testing.T) { + // Initialize a cluster with 3 members + epc, err := e2e.InitEtcdProcessCluster(t, e2e.NewConfigAutoTLS()) + if err != nil { + t.Fatalf("Failed to initilize the etcd cluster: %v", err) + } + + // Remove two members, so that only one etcd will get started + epc.Procs = epc.Procs[:1] + + // Start the etcd cluster with only one member + if err := epc.Start(); err != nil { + t.Fatalf("Failed to start the etcd cluster: %v", err) + } + + // construct the ctl context + cx := getDefaultCtlCtx(t) + cx.epc = epc + + // run serializable test and wait for result + runCtlTest(t, serializableReadTest, nil, cx) + + // run linearizable test and wait for result + runCtlTest(t, linearizableReadTest, nil, cx) +} + +func serializableReadTest(cx ctlCtx) { + cx.quorum = false + if err := ctlV3Get(cx, []string{"key1"}, []kv{}...); err != nil { + cx.t.Errorf("serializableReadTest failed: %v", err) + } +} + +func linearizableReadTest(cx ctlCtx) { + cx.quorum = true + if err := ctlV3Get(cx, []string{"key1"}, []kv{}...); err == nil { + cx.t.Error("linearizableReadTest is expected to fail, but it succeeded") + } +} diff --git a/tests/e2e/ctl_v3_test.go b/tests/e2e/ctl_v3_test.go index 05c75b8165b3..fc544603d5d3 100644 --- a/tests/e2e/ctl_v3_test.go +++ b/tests/e2e/ctl_v3_test.go @@ -213,14 +213,18 @@ func testCtl(t *testing.T, testFunc func(ctlCtx), opts ...ctlOption) { testCtlWithOffline(t, testFunc, nil, opts...) } -func testCtlWithOffline(t *testing.T, testFunc func(ctlCtx), testOfflineFunc func(ctlCtx), opts ...ctlOption) { - e2e.BeforeTest(t) - - ret := ctlCtx{ +func getDefaultCtlCtx(t *testing.T) ctlCtx { + return ctlCtx{ t: t, cfg: *e2e.NewConfigAutoTLS(), dialTimeout: 7 * time.Second, } +} + +func testCtlWithOffline(t *testing.T, testFunc func(ctlCtx), testOfflineFunc func(ctlCtx), opts ...ctlOption) { + e2e.BeforeTest(t) + + ret := getDefaultCtlCtx(t) ret.applyOpts(opts) if !ret.quorum { @@ -244,15 +248,19 @@ func testCtlWithOffline(t *testing.T, testFunc func(ctlCtx), testOfflineFunc fun ret.epc = epc ret.dataDir = epc.Procs[0].Config().DataDirPath + runCtlTest(t, testFunc, testOfflineFunc, ret) +} + +func runCtlTest(t *testing.T, testFunc func(ctlCtx), testOfflineFunc func(ctlCtx), cx ctlCtx) { defer func() { - if ret.envMap != nil { - for k := range ret.envMap { + if cx.envMap != nil { + for k := range cx.envMap { os.Unsetenv(k) } - ret.envMap = make(map[string]string) + cx.envMap = make(map[string]string) } - if ret.epc != nil { - if errC := ret.epc.Close(); errC != nil { + if cx.epc != nil { + if errC := cx.epc.Close(); errC != nil { t.Fatalf("error closing etcd processes (%v)", errC) } } @@ -261,12 +269,12 @@ func testCtlWithOffline(t *testing.T, testFunc func(ctlCtx), testOfflineFunc fun donec := make(chan struct{}) go func() { defer close(donec) - testFunc(ret) + testFunc(cx) t.Log("---testFunc logic DONE") }() - timeout := 2*ret.dialTimeout + time.Second - if ret.dialTimeout == 0 { + timeout := 2*cx.dialTimeout + time.Second + if cx.dialTimeout == 0 { timeout = 30 * time.Second } select { @@ -276,12 +284,12 @@ func testCtlWithOffline(t *testing.T, testFunc func(ctlCtx), testOfflineFunc fun } t.Log("closing test cluster...") - assert.NoError(t, epc.Close()) - epc = nil + assert.NoError(t, cx.epc.Close()) + cx.epc = nil t.Log("closed test cluster...") if testOfflineFunc != nil { - testOfflineFunc(ret) + testOfflineFunc(cx) } } diff --git a/tests/framework/e2e/cluster.go b/tests/framework/e2e/cluster.go index 4a7c9798bffe..242ebe0d6a7d 100644 --- a/tests/framework/e2e/cluster.go +++ b/tests/framework/e2e/cluster.go @@ -176,6 +176,26 @@ type EtcdProcessClusterConfig struct { // NewEtcdProcessCluster launches a new cluster from etcd processes, returning // a new EtcdProcessCluster once all nodes are ready to accept client requests. func NewEtcdProcessCluster(t testing.TB, cfg *EtcdProcessClusterConfig) (*EtcdProcessCluster, error) { + epc, err := InitEtcdProcessCluster(t, cfg) + if err != nil { + return nil, err + } + + if cfg.RollingStart { + if err := epc.RollingStart(); err != nil { + return nil, fmt.Errorf("Cannot rolling-start: %v", err) + } + } else { + if err := epc.Start(); err != nil { + return nil, fmt.Errorf("Cannot start: %v", err) + } + } + return epc, nil +} + +// InitEtcdProcessCluster initializes a new cluster based on the given config. +// It doesn't start the cluster. +func InitEtcdProcessCluster(t testing.TB, cfg *EtcdProcessClusterConfig) (*EtcdProcessCluster, error) { SkipInShortMode(t) etcdCfgs := cfg.EtcdServerProcessConfigs(t) @@ -190,20 +210,11 @@ func NewEtcdProcessCluster(t testing.TB, cfg *EtcdProcessClusterConfig) (*EtcdPr proc, err := NewEtcdProcess(etcdCfgs[i]) if err != nil { epc.Close() - return nil, fmt.Errorf("Cannot configure: %v", err) + return nil, fmt.Errorf("cannot configure: %v", err) } epc.Procs[i] = proc } - if cfg.RollingStart { - if err := epc.RollingStart(); err != nil { - return nil, fmt.Errorf("Cannot rolling-start: %v", err) - } - } else { - if err := epc.Start(); err != nil { - return nil, fmt.Errorf("Cannot start: %v", err) - } - } return epc, nil } From a879ccf152b222c518bc75f3689057aef0937402 Mon Sep 17 00:00:00 2001 From: ahrtr Date: Tue, 28 Dec 2021 16:54:14 +0800 Subject: [PATCH 103/258] updated servePeers to remvoe the grpc server --- CHANGELOG/CHANGELOG-3.6.md | 1 + server/embed/etcd.go | 14 ++------------ tests/framework/integration/cluster.go | 16 +--------------- 3 files changed, 4 insertions(+), 27 deletions(-) diff --git a/CHANGELOG/CHANGELOG-3.6.md b/CHANGELOG/CHANGELOG-3.6.md index 75c6fc8f0e43..23434ddf01ce 100644 --- a/CHANGELOG/CHANGELOG-3.6.md +++ b/CHANGELOG/CHANGELOG-3.6.md @@ -11,6 +11,7 @@ See [code changes](https://github.com/etcd-io/etcd/compare/v3.5.0...v3.6.0). ### Breaking Changes - `etcd` will no longer start on data dir created by newer versions (for example etcd v3.6 will not run on v3.7+ data dir). To downgrade data dir please check out `etcdutl migrate` command. +- `etcd` doesn't support serving client requests on the peer listen endpoints (--listen-peer-urls). See [pull/13565](https://github.com/etcd-io/etcd/pull/13565). ### etcdctl v3 diff --git a/server/embed/etcd.go b/server/embed/etcd.go index 70484277016f..633e4a6d49de 100644 --- a/server/embed/etcd.go +++ b/server/embed/etcd.go @@ -16,7 +16,6 @@ package embed import ( "context" - "crypto/tls" "fmt" "io" defaultLog "log" @@ -38,7 +37,6 @@ import ( "go.etcd.io/etcd/server/v3/etcdserver" "go.etcd.io/etcd/server/v3/etcdserver/api/etcdhttp" "go.etcd.io/etcd/server/v3/etcdserver/api/rafthttp" - "go.etcd.io/etcd/server/v3/etcdserver/api/v3rpc" "go.etcd.io/etcd/server/v3/storage" "go.etcd.io/etcd/server/v3/verify" @@ -530,20 +528,12 @@ func configurePeerListeners(cfg *Config) (peers []*peerListener, err error) { // configure peer handlers after rafthttp.Transport started func (e *Etcd) servePeers() (err error) { ph := etcdhttp.NewPeerHandler(e.GetLogger(), e.Server) - var peerTLScfg *tls.Config - if !e.cfg.PeerTLSInfo.Empty() { - if peerTLScfg, err = e.cfg.PeerTLSInfo.ServerConfig(); err != nil { - return err - } - } for _, p := range e.Peers { u := p.Listener.Addr().String() - gs := v3rpc.Server(e.Server, peerTLScfg, nil) m := cmux.New(p.Listener) - go gs.Serve(m.Match(cmux.HTTP2())) srv := &http.Server{ - Handler: grpcHandlerFunc(gs, ph), + Handler: ph, ReadTimeout: 5 * time.Minute, ErrorLog: defaultLog.New(io.Discard, "", 0), // do not log user error } @@ -563,7 +553,7 @@ func (e *Etcd) servePeers() (err error) { "stopping serving peer traffic", zap.String("address", u), ) - stopServers(ctx, &servers{secure: peerTLScfg != nil, grpc: gs, http: srv}) + srv.Shutdown(ctx) e.cfg.logger.Info( "stopped serving peer traffic", zap.String("address", u), diff --git a/tests/framework/integration/cluster.go b/tests/framework/integration/cluster.go index f7fc08677f8f..1dc9306ad248 100644 --- a/tests/framework/integration/cluster.go +++ b/tests/framework/integration/cluster.go @@ -545,7 +545,6 @@ type Member struct { GrpcServerOpts []grpc.ServerOption GrpcServer *grpc.Server - GrpcServerPeer *grpc.Server GrpcURL string GrpcBridge *bridge @@ -922,7 +921,6 @@ func (m *Member) Launch() error { } } m.GrpcServer = v3rpc.Server(m.Server, tlscfg, m.GrpcServerRecorder.UnaryInterceptor(), m.GrpcServerOpts...) - m.GrpcServerPeer = v3rpc.Server(m.Server, peerTLScfg, m.GrpcServerRecorder.UnaryInterceptor()) m.ServerClient = v3client.New(m.Server) lockpb.RegisterLockServer(m.GrpcServer, v3lock.NewLockServer(m.ServerClient)) epb.RegisterElectionServer(m.GrpcServer, v3election.NewElectionServer(m.ServerClient)) @@ -934,11 +932,7 @@ func (m *Member) Launch() error { h := (http.Handler)(m.RaftHandler) if m.GrpcListener != nil { h = http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { - if r.ProtoMajor == 2 && strings.Contains(r.Header.Get("Content-Type"), "application/grpc") { - m.GrpcServerPeer.ServeHTTP(w, r) - } else { - m.RaftHandler.ServeHTTP(w, r) - } + m.RaftHandler.ServeHTTP(w, r) }) } @@ -947,11 +941,6 @@ func (m *Member) Launch() error { // don't hang on matcher after closing listener cm.SetReadTimeout(time.Second) - if m.GrpcServer != nil { - grpcl := cm.Match(cmux.HTTP2()) - go m.GrpcServerPeer.Serve(grpcl) - } - // serve http1/http2 rafthttp/grpc ll := cm.Match(cmux.Any()) if peerTLScfg != nil { @@ -1146,9 +1135,6 @@ func (m *Member) Close() { <-ch } m.GrpcServer = nil - m.GrpcServerPeer.GracefulStop() - m.GrpcServerPeer.Stop() - m.GrpcServerPeer = nil } if m.Server != nil { m.Server.HardStop() From 2e74e4d636654b2879bf7fd32a9e14e9c621d725 Mon Sep 17 00:00:00 2001 From: Hitoshi Mitake Date: Sun, 22 Aug 2021 21:48:23 +0900 Subject: [PATCH 104/258] server/auth: avoid logging for JWT token for a case of failed parsing --- server/auth/jwt.go | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/server/auth/jwt.go b/server/auth/jwt.go index dce741f7d0d3..1f3ce57b214f 100644 --- a/server/auth/jwt.go +++ b/server/auth/jwt.go @@ -62,7 +62,6 @@ func (t *tokenJWT) info(ctx context.Context, token string, rev uint64) (*AuthInf if err != nil { t.lg.Warn( "failed to parse a JWT token", - zap.String("token", token), zap.Error(err), ) return nil, false @@ -70,7 +69,7 @@ func (t *tokenJWT) info(ctx context.Context, token string, rev uint64) (*AuthInf claims, ok := parsed.Claims.(jwt.MapClaims) if !parsed.Valid || !ok { - t.lg.Warn("invalid JWT token", zap.String("token", token)) + t.lg.Warn("failed to obtain claims from a JWT token") return nil, false } From 1beae5428ed33e58638407da3d972bdfd16d798f Mon Sep 17 00:00:00 2001 From: Marek Siarkowicz Date: Mon, 24 Jan 2022 14:39:48 +0100 Subject: [PATCH 105/258] Add bug report issue template --- .github/ISSUE_TEMPLATE.md | 2 - .github/ISSUE_TEMPLATE/bug-report.yaml | 92 ++++++++++++++++++++++++++ 2 files changed, 92 insertions(+), 2 deletions(-) delete mode 100644 .github/ISSUE_TEMPLATE.md create mode 100644 .github/ISSUE_TEMPLATE/bug-report.yaml diff --git a/.github/ISSUE_TEMPLATE.md b/.github/ISSUE_TEMPLATE.md deleted file mode 100644 index 3a3c247b5bda..000000000000 --- a/.github/ISSUE_TEMPLATE.md +++ /dev/null @@ -1,2 +0,0 @@ - -Please read https://etcd.io/docs/latest/reporting_bugs/ diff --git a/.github/ISSUE_TEMPLATE/bug-report.yaml b/.github/ISSUE_TEMPLATE/bug-report.yaml new file mode 100644 index 000000000000..088ed4939af0 --- /dev/null +++ b/.github/ISSUE_TEMPLATE/bug-report.yaml @@ -0,0 +1,92 @@ +name: Bug Report +description: Report a bug encountered while operating Etcd +labels: +- area/bug +body: +- type: markdown + attributes: + value: | + Please read https://etcd.io/docs/latest/reporting_bugs/ + If this matter is security related, please disclose it privately via security@etcd.io. + Please fill the form below and provide as much information as possible. + Not doing so may result in your bug not being addressed in a timely manner. + +- type: textarea + id: problem + attributes: + label: What happened? + validations: + required: true + +- type: textarea + id: expected + attributes: + label: What did you expect to happen? + validations: + required: true + +- type: textarea + id: repro + attributes: + label: How can we reproduce it (as minimally and precisely as possible)? + validations: + required: true + +- type: textarea + id: additional + attributes: + label: Anything else we need to know? + +- type: textarea + id: etcdVersion + attributes: + label: Etcd version (please run commands below) + value: | +
+ + ```console + $ etcd --version + # paste output here + + $ etcdctl version + # paste output here + ``` + +
+ validations: + required: true + +- type: textarea + id: config + attributes: + label: Etcd configuration (command line flags or environment variables) + value: | +
+ + # paste your configuration here + +
+ +- type: textarea + id: etcdDebugInformation + attributes: + label: Etcd debug information (please run commands blow, feel free to obfuscate the IP address or FQDN in the output) + value: | +
+ + ```console + $ etcdctl member list -w table + # paste output here + + $ etcdctl --endpoints= endpoint status -w table + # paste output here + ``` + +
+ +- type: textarea + id: logs + attributes: + label: Relevant log output + description: Please copy and paste any relevant log output. This will be automatically formatted into code, so no need for backticks. + render: shell From c836905a1d1416e12e1e7bc8c5189e100e8174bf Mon Sep 17 00:00:00 2001 From: Marek Siarkowicz Date: Tue, 25 Jan 2022 16:19:21 +0100 Subject: [PATCH 106/258] proxy: Fix proxy not passing Linearizable field by using GRPC client --- server/proxy/grpcproxy/cluster.go | 48 ++++--------------------------- 1 file changed, 6 insertions(+), 42 deletions(-) diff --git a/server/proxy/grpcproxy/cluster.go b/server/proxy/grpcproxy/cluster.go index 1f7dccbe74f6..be4e1434016c 100644 --- a/server/proxy/grpcproxy/cluster.go +++ b/server/proxy/grpcproxy/cluster.go @@ -34,7 +34,7 @@ const resolveRetryRate = 1 type clusterProxy struct { lg *zap.Logger - clus clientv3.Cluster + clus pb.ClusterClient ctx context.Context // advertise client URL @@ -67,7 +67,7 @@ func NewClusterProxy(lg *zap.Logger, c *clientv3.Client, advaddr string, prefix cp := &clusterProxy{ lg: lg, - clus: c.Cluster, + clus: pb.NewClusterClient(c.ActiveConnection()), ctx: c.Ctx(), advaddr: advaddr, @@ -123,46 +123,15 @@ func (cp *clusterProxy) monitor(wa endpoints.WatchChannel) { } func (cp *clusterProxy) MemberAdd(ctx context.Context, r *pb.MemberAddRequest) (*pb.MemberAddResponse, error) { - if r.IsLearner { - return cp.memberAddAsLearner(ctx, r.PeerURLs) - } - return cp.memberAdd(ctx, r.PeerURLs) -} - -func (cp *clusterProxy) memberAdd(ctx context.Context, peerURLs []string) (*pb.MemberAddResponse, error) { - mresp, err := cp.clus.MemberAdd(ctx, peerURLs) - if err != nil { - return nil, err - } - resp := (pb.MemberAddResponse)(*mresp) - return &resp, err -} - -func (cp *clusterProxy) memberAddAsLearner(ctx context.Context, peerURLs []string) (*pb.MemberAddResponse, error) { - mresp, err := cp.clus.MemberAddAsLearner(ctx, peerURLs) - if err != nil { - return nil, err - } - resp := (pb.MemberAddResponse)(*mresp) - return &resp, err + return cp.clus.MemberAdd(ctx, r) } func (cp *clusterProxy) MemberRemove(ctx context.Context, r *pb.MemberRemoveRequest) (*pb.MemberRemoveResponse, error) { - mresp, err := cp.clus.MemberRemove(ctx, r.ID) - if err != nil { - return nil, err - } - resp := (pb.MemberRemoveResponse)(*mresp) - return &resp, err + return cp.clus.MemberRemove(ctx, r) } func (cp *clusterProxy) MemberUpdate(ctx context.Context, r *pb.MemberUpdateRequest) (*pb.MemberUpdateResponse, error) { - mresp, err := cp.clus.MemberUpdate(ctx, r.ID, r.PeerURLs) - if err != nil { - return nil, err - } - resp := (pb.MemberUpdateResponse)(*mresp) - return &resp, err + return cp.clus.MemberUpdate(ctx, r) } func (cp *clusterProxy) membersFromUpdates() ([]*pb.Member, error) { @@ -199,12 +168,7 @@ func (cp *clusterProxy) MemberList(ctx context.Context, r *pb.MemberListRequest) hostname, _ := os.Hostname() return &pb.MemberListResponse{Members: []*pb.Member{{Name: hostname, ClientURLs: []string{cp.advaddr}}}}, nil } - mresp, err := cp.clus.MemberList(ctx) - if err != nil { - return nil, err - } - resp := (pb.MemberListResponse)(*mresp) - return &resp, err + return cp.clus.MemberList(ctx, r) } func (cp *clusterProxy) MemberPromote(ctx context.Context, r *pb.MemberPromoteRequest) (*pb.MemberPromoteResponse, error) { From f4187b4460dbc1444fa8ff78601d83078b868c43 Mon Sep 17 00:00:00 2001 From: Marek Siarkowicz Date: Mon, 13 Dec 2021 16:44:17 +0100 Subject: [PATCH 107/258] tools: Improve proto annotation documentation --- server/storage/wal/version.go | 3 + tools/proto-annotations/cmd/etcd_version.go | 117 +++++++++++++++++++ tools/proto-annotations/cmd/root.go | 76 +++++++++++++ tools/proto-annotations/main.go | 120 +------------------- 4 files changed, 199 insertions(+), 117 deletions(-) create mode 100644 tools/proto-annotations/cmd/etcd_version.go create mode 100644 tools/proto-annotations/cmd/root.go diff --git a/server/storage/wal/version.go b/server/storage/wal/version.go index 8fe6725e8cdd..e4c3c250057b 100644 --- a/server/storage/wal/version.go +++ b/server/storage/wal/version.go @@ -66,6 +66,9 @@ func MinimalEtcdVersion(ents []raftpb.Entry) *semver.Version { type Visitor func(path protoreflect.FullName, ver *semver.Version) error +// VisitFileDescriptor calls visitor on each field and enum value with etcd version read from proto definition. +// If field/enum value is not annotated, visitor will be called with nil. +// Upon encountering invalid annotation, will immediately exit with error. func VisitFileDescriptor(file protoreflect.FileDescriptor, visitor Visitor) error { msgs := file.Messages() for i := 0; i < msgs.Len(); i++ { diff --git a/tools/proto-annotations/cmd/etcd_version.go b/tools/proto-annotations/cmd/etcd_version.go new file mode 100644 index 000000000000..9d6f8658a403 --- /dev/null +++ b/tools/proto-annotations/cmd/etcd_version.go @@ -0,0 +1,117 @@ +// Copyright 2021 The etcd Authors +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package cmd + +import ( + "bytes" + "fmt" + "io" + "sort" + + "github.com/coreos/go-semver/semver" + "go.etcd.io/etcd/server/v3/storage/wal" + + "google.golang.org/protobuf/reflect/protoreflect" + "google.golang.org/protobuf/reflect/protoregistry" +) + +// printEtcdVersion writes etcd_version proto annotation to stdout and returns any errors encountered when reading annotation. +func printEtcdVersion() []error { + var errs []error + annotations, err := allEtcdVersionAnnotations() + if err != nil { + errs = append(errs, err) + return errs + } + sort.Slice(annotations, func(i, j int) bool { + return annotations[i].fullName < annotations[j].fullName + }) + output := &bytes.Buffer{} + for _, a := range annotations { + newErrs := a.Validate() + if len(newErrs) == 0 { + err := a.PrintLine(output) + if err != nil { + errs = append(errs, err) + return errs + } + } + errs = append(errs, newErrs...) + } + if len(errs) == 0 { + fmt.Print(output) + } + return errs +} + +func allEtcdVersionAnnotations() (annotations []etcdVersionAnnotation, err error) { + var fileAnnotations []etcdVersionAnnotation + protoregistry.GlobalFiles.RangeFiles(func(file protoreflect.FileDescriptor) bool { + switch string(file.Package()) { + // Skip external packages that are not expected to have etcd version annotation. + case "io.prometheus.client", "grpc.binarylog.v1", "google.protobuf", "google.rpc", "google.api": + return true + } + fileAnnotations, err = fileEtcdVersionAnnotations(file) + if err != nil { + return false + } + annotations = append(annotations, fileAnnotations...) + return true + }) + return annotations, err +} + +func fileEtcdVersionAnnotations(file protoreflect.FileDescriptor) (annotations []etcdVersionAnnotation, err error) { + err = wal.VisitFileDescriptor(file, func(path protoreflect.FullName, ver *semver.Version) error { + a := etcdVersionAnnotation{fullName: path, version: ver} + annotations = append(annotations, a) + return nil + }) + return annotations, err +} + +type etcdVersionAnnotation struct { + fullName protoreflect.FullName + version *semver.Version +} + +func (a etcdVersionAnnotation) Validate() (errs []error) { + if a.version == nil { + return nil + } + if a.version.Major == 0 { + errs = append(errs, fmt.Errorf("%s: etcd_version major version should not be zero", a.fullName)) + } + if a.version.Patch != 0 { + errs = append(errs, fmt.Errorf("%s: etcd_version patch version should be zero", a.fullName)) + } + if a.version.PreRelease != "" { + errs = append(errs, fmt.Errorf("%s: etcd_version should not be prerelease", a.fullName)) + } + if a.version.Metadata != "" { + errs = append(errs, fmt.Errorf("%s: etcd_version should not have metadata", a.fullName)) + } + return errs +} + +func (a etcdVersionAnnotation) PrintLine(out io.Writer) error { + if a.version == nil { + _, err := fmt.Fprintf(out, "%s: \"\"\n", a.fullName) + return err + } + _, err := fmt.Fprintf(out, "%s: \"%d.%d\"\n", a.fullName, a.version.Major, a.version.Minor) + return err +} diff --git a/tools/proto-annotations/cmd/root.go b/tools/proto-annotations/cmd/root.go new file mode 100644 index 000000000000..2b4ff9530a0e --- /dev/null +++ b/tools/proto-annotations/cmd/root.go @@ -0,0 +1,76 @@ +// Copyright 2021 The etcd Authors +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package cmd + +import ( + "fmt" + "os" + + "github.com/spf13/cobra" +) + +const ( + EtcdVersionAnnotation = "etcd_version" +) + +func RootCmd() *cobra.Command { + var annotation string + cmd := &cobra.Command{ + Use: "proto-annotation", + Short: "Proto-annotations prints a dump of annotations used by all protobuf definitions used by Etcd.", + Long: `Tool used to extract values of a specific proto annotation used by protobuf definitions used by Etcd. +Created to ensure that all newly introduced proto definitions have a etcd_version_* annotation, by analysing diffs between generated by this tool. + +Proto annotations is printed to stdout in format: +: "" + + +For example: +''' +etcdserverpb.Member: "3.0" +etcdserverpb.Member.ID: "" +etcdserverpb.Member.clientURLs: "" +etcdserverpb.Member.isLearner: "3.4" +etcdserverpb.Member.name: "" +etcdserverpb.Member.peerURLs: "" +''' + +Any errors in proto will be printed to stderr. +`, + RunE: func(cmd *cobra.Command, args []string) error { + return runProtoAnnotation(annotation) + }, + } + cmd.Flags().StringVar(&annotation, "annotation", "", "Specify what proto annotation to read. Options: etcd_version") + cmd.MarkFlagRequired("annotation") + return cmd +} + +func runProtoAnnotation(annotation string) error { + var errs []error + switch annotation { + case EtcdVersionAnnotation: + errs = printEtcdVersion() + default: + return fmt.Errorf("unknown annotation %q. Options: %q", annotation, EtcdVersionAnnotation) + } + if len(errs) != 0 { + for _, err := range errs { + fmt.Fprintln(os.Stderr, err) + } + return fmt.Errorf("failed reading anotation") + } + return nil +} diff --git a/tools/proto-annotations/main.go b/tools/proto-annotations/main.go index 105f829fb2de..a350ef82b929 100644 --- a/tools/proto-annotations/main.go +++ b/tools/proto-annotations/main.go @@ -15,129 +15,15 @@ package main import ( - "bytes" - "flag" "fmt" - "io" "os" - "sort" - "github.com/coreos/go-semver/semver" - "go.etcd.io/etcd/server/v3/storage/wal" - "google.golang.org/protobuf/reflect/protoreflect" - "google.golang.org/protobuf/reflect/protoregistry" -) - -const ( - EtcdVersionAnnotation = "etcd_version" + "go.etcd.io/etcd/v3/tools/proto-annotations/cmd" ) func main() { - annotation := flag.String("annotation", "", "Specify what proto annotation to read. Options: etcd_version") - flag.Parse() - var errs []error - switch *annotation { - case EtcdVersionAnnotation: - errs = handleEtcdVersion() - case "": - fmt.Fprintf(os.Stderr, "Please provide --annotation flag") + if err := cmd.RootCmd().Execute(); err != nil { + fmt.Fprintln(os.Stderr, err) os.Exit(1) - default: - fmt.Fprintf(os.Stderr, "Unknown annotation %q. Options: etcd_version", *annotation) - os.Exit(1) - } - if len(errs) != 0 { - for _, err := range errs { - fmt.Fprintln(os.Stderr, err) - } - os.Exit(1) - } - os.Exit(0) -} - -func handleEtcdVersion() (errs []error) { - annotations, err := allEtcdVersionAnnotations() - if err != nil { - errs = append(errs, err) - return errs - } - sort.Slice(annotations, func(i, j int) bool { - return annotations[i].fullName < annotations[j].fullName - }) - output := &bytes.Buffer{} - for _, a := range annotations { - newErrs := a.Validate() - if len(newErrs) == 0 { - err := a.PrintLine(output) - if err != nil { - errs = append(errs, err) - return errs - } - } - errs = append(errs, newErrs...) - } - if len(errs) == 0 { - fmt.Print(output) - } - return errs -} - -func allEtcdVersionAnnotations() (annotations []etcdVersionAnnotation, err error) { - var fileAnnotations []etcdVersionAnnotation - protoregistry.GlobalFiles.RangeFiles(func(file protoreflect.FileDescriptor) bool { - switch string(file.Package()) { - // Skip external packages that are not expected to have etcd version annotation. - case "io.prometheus.client", "grpc.binarylog.v1", "google.protobuf", "google.rpc", "google.api": - return true - } - fileAnnotations, err = fileEtcdVersionAnnotations(file) - if err != nil { - return false - } - annotations = append(annotations, fileAnnotations...) - return true - }) - return annotations, err -} - -func fileEtcdVersionAnnotations(file protoreflect.FileDescriptor) (annotations []etcdVersionAnnotation, err error) { - err = wal.VisitFileDescriptor(file, func(path protoreflect.FullName, ver *semver.Version) error { - a := etcdVersionAnnotation{fullName: path, version: ver} - annotations = append(annotations, a) - return nil - }) - return annotations, err -} - -type etcdVersionAnnotation struct { - fullName protoreflect.FullName - version *semver.Version -} - -func (a etcdVersionAnnotation) Validate() (errs []error) { - if a.version == nil { - return nil - } - if a.version.Major == 0 { - errs = append(errs, fmt.Errorf("%s: etcd_version major version should not be zero", a.fullName)) - } - if a.version.Patch != 0 { - errs = append(errs, fmt.Errorf("%s: etcd_version patch version should be zero", a.fullName)) - } - if a.version.PreRelease != "" { - errs = append(errs, fmt.Errorf("%s: etcd_version should not be prerelease", a.fullName)) - } - if a.version.Metadata != "" { - errs = append(errs, fmt.Errorf("%s: etcd_version should not have metadata", a.fullName)) - } - return errs -} - -func (a etcdVersionAnnotation) PrintLine(out io.Writer) error { - if a.version == nil { - _, err := fmt.Fprintf(out, "%s: \"\"\n", a.fullName) - return err } - _, err := fmt.Fprintf(out, "%s: \"%d.%d\"\n", a.fullName, a.version.Major, a.version.Minor) - return err } From 099cffcaa0a570a90ef3abcb7ee22732a752d05f Mon Sep 17 00:00:00 2001 From: Marek Siarkowicz Date: Fri, 28 Jan 2022 12:00:03 +0100 Subject: [PATCH 108/258] tests: Parallelize grpcproxy tests --- .github/workflows/grpcproxy.yaml | 11 ++++++++--- test.sh | 12 +++++++++++- 2 files changed, 19 insertions(+), 4 deletions(-) diff --git a/.github/workflows/grpcproxy.yaml b/.github/workflows/grpcproxy.yaml index 27ec0ab6c216..ef2533351ae8 100644 --- a/.github/workflows/grpcproxy.yaml +++ b/.github/workflows/grpcproxy.yaml @@ -7,7 +7,8 @@ jobs: fail-fast: true matrix: target: - - linux-amd64-grpcproxy + - linux-amd64-grpcproxy-integration + - linux-amd64-grpcproxy-e2e steps: - uses: actions/checkout@v2 - uses: actions/setup-go@v2 @@ -19,8 +20,12 @@ jobs: run: | echo "${TARGET}" case "${TARGET}" in - linux-amd64-grpcproxy) - PASSES='build grpcproxy' CPU='4' COVER='false' RACE='true' ./test.sh 2>&1 | tee test.log + linux-amd64-grpcproxy-integration) + PASSES='build grpcproxy_integration' CPU='4' COVER='false' RACE='true' ./test.sh 2>&1 | tee test.log + ! egrep "(--- FAIL:|FAIL:|DATA RACE|panic: test timed out|appears to have leaked)" -B50 -A10 test.log + ;; + linux-amd64-grpcproxy-e2e) + PASSES='build grpcproxy_e2e' CPU='4' COVER='false' RACE='true' ./test.sh 2>&1 | tee test.log ! egrep "(--- FAIL:|FAIL:|DATA RACE|panic: test timed out|appears to have leaked)" -B50 -A10 test.log ;; *) diff --git a/test.sh b/test.sh index 586fa32923c5..895151f8d1fb 100755 --- a/test.sh +++ b/test.sh @@ -189,7 +189,17 @@ function functional_pass { } function grpcproxy_pass { - run_for_module "tests" go_test "./integration/... ./e2e" "fail_fast" : \ + run_pass "grpcproxy_integration" "${@}" + run_pass "grpcproxy_e2e" "${@}" +} + +function grpcproxy_integration_pass { + run_for_module "tests" go_test "./integration/..." "fail_fast" : \ + -timeout=30m -tags cluster_proxy "${COMMON_TEST_FLAGS[@]}" "$@" +} + +function grpcproxy_e2e_pass { + run_for_module "tests" go_test "./e2e" "fail_fast" : \ -timeout=30m -tags cluster_proxy "${COMMON_TEST_FLAGS[@]}" "$@" } From 3df14fc24ff7c3028c4d43aef87eae5f1824ec00 Mon Sep 17 00:00:00 2001 From: Marek Siarkowicz Date: Fri, 28 Jan 2022 16:08:28 +0100 Subject: [PATCH 109/258] Document proto annotations scripts --- scripts/update_proto_annotations.sh | 3 +++ scripts/verify_proto_annotations.sh | 2 ++ 2 files changed, 5 insertions(+) diff --git a/scripts/update_proto_annotations.sh b/scripts/update_proto_annotations.sh index 0d18304e1fa3..75089e772221 100755 --- a/scripts/update_proto_annotations.sh +++ b/scripts/update_proto_annotations.sh @@ -1,4 +1,7 @@ #!/usr/bin/env bash +# Updates etcd_version_annotations.txt based on state of annotations in proto files. +# Developers can run this script to avoid manually updating etcd_version_annotations.txt. +# Before running this script please ensure that fields/messages that you added are annotated with next etcd version. set -o errexit set -o nounset diff --git a/scripts/verify_proto_annotations.sh b/scripts/verify_proto_annotations.sh index 79f481fe5173..47abbaf1d4c0 100755 --- a/scripts/verify_proto_annotations.sh +++ b/scripts/verify_proto_annotations.sh @@ -1,4 +1,6 @@ #!/usr/bin/env bash +# Verifies proto annotations to ensure all new proto fields and messages are annotated by comparing it with etcd_version_annotations.txt file. +# This scripts is automatically run by CI to prevent pull requests missing adding a proto annotation. set -o errexit set -o nounset From 0c67c5ca49a8128ac63c68e57221058b869e90d7 Mon Sep 17 00:00:00 2001 From: Marek Siarkowicz Date: Fri, 28 Jan 2022 16:12:00 +0100 Subject: [PATCH 110/258] tools: Move external packages constant to top level --- tools/proto-annotations/cmd/etcd_version.go | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) diff --git a/tools/proto-annotations/cmd/etcd_version.go b/tools/proto-annotations/cmd/etcd_version.go index 9d6f8658a403..bd86e5a50767 100644 --- a/tools/proto-annotations/cmd/etcd_version.go +++ b/tools/proto-annotations/cmd/etcd_version.go @@ -27,6 +27,11 @@ import ( "google.golang.org/protobuf/reflect/protoregistry" ) +var ( + // externalPackages that are not expected to have etcd version annotation. + externalPackages = []string{"io.prometheus.client", "grpc.binarylog.v1", "google.protobuf", "google.rpc", "google.api"} +) + // printEtcdVersion writes etcd_version proto annotation to stdout and returns any errors encountered when reading annotation. func printEtcdVersion() []error { var errs []error @@ -59,10 +64,11 @@ func printEtcdVersion() []error { func allEtcdVersionAnnotations() (annotations []etcdVersionAnnotation, err error) { var fileAnnotations []etcdVersionAnnotation protoregistry.GlobalFiles.RangeFiles(func(file protoreflect.FileDescriptor) bool { - switch string(file.Package()) { - // Skip external packages that are not expected to have etcd version annotation. - case "io.prometheus.client", "grpc.binarylog.v1", "google.protobuf", "google.rpc", "google.api": - return true + pkg := string(file.Package()) + for _, externalPkg := range externalPackages { + if pkg == externalPkg { + return true + } } fileAnnotations, err = fileEtcdVersionAnnotations(file) if err != nil { From 95ae9c19f0bc1f2c0567e3eda6570d7b766b9e1e Mon Sep 17 00:00:00 2001 From: richkun Date: Sun, 30 Jan 2022 11:01:45 +0800 Subject: [PATCH 111/258] Show db in use when print endpoint status (#13639) --- CHANGELOG/CHANGELOG-3.6.md | 1 + etcdctl/ctlv3/command/printer.go | 3 ++- etcdctl/ctlv3/command/printer_fields.go | 1 + 3 files changed, 4 insertions(+), 1 deletion(-) diff --git a/CHANGELOG/CHANGELOG-3.6.md b/CHANGELOG/CHANGELOG-3.6.md index 75c6fc8f0e43..97a8213466bc 100644 --- a/CHANGELOG/CHANGELOG-3.6.md +++ b/CHANGELOG/CHANGELOG-3.6.md @@ -15,6 +15,7 @@ See [code changes](https://github.com/etcd-io/etcd/compare/v3.5.0...v3.6.0). ### etcdctl v3 - Add command to generate [shell completion](https://github.com/etcd-io/etcd/pull/13133). +- When print endpoint status, [show db size in use](https://github.com/etcd-io/etcd/pull/13639) ### etcdutl v3 diff --git a/etcdctl/ctlv3/command/printer.go b/etcdctl/ctlv3/command/printer.go index 4cb18f437713..7a4086acbdf6 100644 --- a/etcdctl/ctlv3/command/printer.go +++ b/etcdctl/ctlv3/command/printer.go @@ -201,7 +201,7 @@ func makeEndpointHealthTable(healthList []epHealth) (hdr []string, rows [][]stri } func makeEndpointStatusTable(statusList []epStatus) (hdr []string, rows [][]string) { - hdr = []string{"endpoint", "ID", "version", "db size", "is leader", "is learner", "raft term", + hdr = []string{"endpoint", "ID", "version", "db size", "db size in use", "is leader", "is learner", "raft term", "raft index", "raft applied index", "errors"} for _, status := range statusList { rows = append(rows, []string{ @@ -209,6 +209,7 @@ func makeEndpointStatusTable(statusList []epStatus) (hdr []string, rows [][]stri fmt.Sprintf("%x", status.Resp.Header.MemberId), status.Resp.Version, humanize.Bytes(uint64(status.Resp.DbSize)), + humanize.Bytes(uint64(status.Resp.DbSizeInUse)), fmt.Sprint(status.Resp.Leader == status.Resp.Header.MemberId), fmt.Sprint(status.Resp.IsLearner), fmt.Sprint(status.Resp.RaftTerm), diff --git a/etcdctl/ctlv3/command/printer_fields.go b/etcdctl/ctlv3/command/printer_fields.go index ca4611c735ca..2cb5def1b3c2 100644 --- a/etcdctl/ctlv3/command/printer_fields.go +++ b/etcdctl/ctlv3/command/printer_fields.go @@ -156,6 +156,7 @@ func (p *fieldsPrinter) EndpointStatus(eps []epStatus) { p.hdr(ep.Resp.Header) fmt.Printf("\"Version\" : %q\n", ep.Resp.Version) fmt.Println(`"DBSize" :`, ep.Resp.DbSize) + fmt.Println(`"DBSizeInUse" :`, ep.Resp.DbSizeInUse) fmt.Println(`"Leader" :`, ep.Resp.Leader) fmt.Println(`"IsLearner" :`, ep.Resp.IsLearner) fmt.Println(`"RaftIndex" :`, ep.Resp.RaftIndex) From aa76b32a05c67e7b159fd0158bbdfc9566c1b040 Mon Sep 17 00:00:00 2001 From: Marek Siarkowicz Date: Tue, 1 Feb 2022 15:32:44 +0100 Subject: [PATCH 112/258] release: Post v3.5.2 release updates and fixes --- CHANGELOG/CHANGELOG-3.1.md | 2 +- CHANGELOG/CHANGELOG-3.2.md | 2 +- CHANGELOG/CHANGELOG-3.3.md | 2 +- CHANGELOG/CHANGELOG-3.4.md | 2 +- CHANGELOG/CHANGELOG-3.5.md | 4 ++-- scripts/release | 2 +- 6 files changed, 7 insertions(+), 7 deletions(-) diff --git a/CHANGELOG/CHANGELOG-3.1.md b/CHANGELOG/CHANGELOG-3.1.md index b6706b712315..090104fa3c86 100644 --- a/CHANGELOG/CHANGELOG-3.1.md +++ b/CHANGELOG/CHANGELOG-3.1.md @@ -3,7 +3,7 @@ Previous change logs can be found at [CHANGELOG-3.0](https://github.com/etcd-io/etcd/blob/main/CHANGELOG/CHANGELOG-3.0.md). -The minimum recommended etcd versions to run in **production** are 3.1.11+, 3.2.26+, and 3.3.11+. +The minimum recommended etcd versions to run in **production** are 3.3.18+, 3.4.2+, and 3.5.2+.
diff --git a/CHANGELOG/CHANGELOG-3.2.md b/CHANGELOG/CHANGELOG-3.2.md index e4283f36a0fc..37efc787721a 100644 --- a/CHANGELOG/CHANGELOG-3.2.md +++ b/CHANGELOG/CHANGELOG-3.2.md @@ -3,7 +3,7 @@ Previous change logs can be found at [CHANGELOG-3.1](https://github.com/etcd-io/etcd/blob/main/CHANGELOG/CHANGELOG-3.1.md). -The minimum recommended etcd versions to run in **production** are 3.2.28+, 3.3.18+, and 3.4.2+. +The minimum recommended etcd versions to run in **production** are 3.3.18+, 3.4.2+, and 3.5.2+. ## v3.2.33 (TBD) diff --git a/CHANGELOG/CHANGELOG-3.3.md b/CHANGELOG/CHANGELOG-3.3.md index 75d56cefbec8..6a4ead2ca472 100644 --- a/CHANGELOG/CHANGELOG-3.3.md +++ b/CHANGELOG/CHANGELOG-3.3.md @@ -3,7 +3,7 @@ Previous change logs can be found at [CHANGELOG-3.2](https://github.com/etcd-io/etcd/blob/main/CHANGELOG/CHANGELOG-3.2.md). -The minimum recommended etcd versions to run in **production** are 3.3.18+, 3.4.2+, and 3.5.1+. Refer to the [versioning policy](https://etcd.io/docs/v3.3/op-guide/versioning/) for more details. +The minimum recommended etcd versions to run in **production** are 3.3.18+, 3.4.2+, and 3.5.2+. Refer to the [versioning policy](https://etcd.io/docs/v3.3/op-guide/versioning/) for more details.
diff --git a/CHANGELOG/CHANGELOG-3.4.md b/CHANGELOG/CHANGELOG-3.4.md index 3cb69054469f..4deac1150570 100644 --- a/CHANGELOG/CHANGELOG-3.4.md +++ b/CHANGELOG/CHANGELOG-3.4.md @@ -3,7 +3,7 @@ Previous change logs can be found at [CHANGELOG-3.3](https://github.com/etcd-io/etcd/blob/main/CHANGELOG/CHANGELOG-3.3.md). -The minimum recommended etcd versions to run in **production** are 3.3.18+, 3.4.2+, and 3.5.1+. Refer to the [versioning policy](https://etcd.io/docs/v3.4/op-guide/versioning/) for more details. +The minimum recommended etcd versions to run in **production** are 3.3.18+, 3.4.2+, and 3.5.2+. Refer to the [versioning policy](https://etcd.io/docs/v3.4/op-guide/versioning/) for more details.
diff --git a/CHANGELOG/CHANGELOG-3.5.md b/CHANGELOG/CHANGELOG-3.5.md index d7acc70b3a6e..6ae6c65d7693 100644 --- a/CHANGELOG/CHANGELOG-3.5.md +++ b/CHANGELOG/CHANGELOG-3.5.md @@ -3,11 +3,11 @@ Previous change logs can be found at [CHANGELOG-3.4](https://github.com/etcd-io/etcd/blob/main/CHANGELOG/CHANGELOG-3.4.md). -The minimum recommended etcd versions to run in **production** are 3.3.18+, 3.4.2+, and 3.5.1+. Refer to the [versioning policy](https://etcd.io/docs/v3.5/op-guide/versioning/) for more details. +The minimum recommended etcd versions to run in **production** are 3.3.18+, 3.4.2+, and 3.5.2+. Refer to the [versioning policy](https://etcd.io/docs/v3.5/op-guide/versioning/) for more details.
-## [v3.5.2](https://github.com/etcd-io/etcd/releases/tag/v3.5.2) (TODO) +## [v3.5.2](https://github.com/etcd-io/etcd/releases/tag/v3.5.2) (2022-02-01) See [code changes](https://github.com/etcd-io/etcd/compare/v3.5.1...v3.5.2) and [v3.5 upgrade guide](https://etcd.io/docs/latest/upgrades/upgrade_3_5/) for any breaking changes. diff --git a/scripts/release b/scripts/release index 7c2880813e30..816b34eb9c4e 100755 --- a/scripts/release +++ b/scripts/release @@ -263,7 +263,7 @@ main() { # Check image versions for IMAGE in "quay.io/coreos/etcd:${RELEASE_VERSION}" "gcr.io/etcd-development/etcd:${RELEASE_VERSION}"; do - local image_version=$(dry_run docker run --rm "${IMAGE}" etcd --version | grep "etcd Version" | awk -F: '{print $2}' | tr -d '[:space:]') + local image_version=$(docker run --rm "${IMAGE}" etcd --version | grep "etcd Version" | awk -F: '{print $2}' | tr -d '[:space:]') if [ "${image_version}" != "${VERSION}" ]; then log_error "Check failed: etcd --version output for ${IMAGE} is incorrect: ${image_version}" exit 1 From 43c1631f26676a092d05d5e286eb11d461282846 Mon Sep 17 00:00:00 2001 From: Marek Siarkowicz Date: Tue, 1 Feb 2022 16:39:56 +0100 Subject: [PATCH 113/258] tests: Use cmp.Equal to avoid mutating arguments --- bill-of-materials.json | 9 +++++++++ go.mod | 2 ++ tests/framework/integration/cluster.go | 13 +++---------- tests/go.mod | 2 ++ 4 files changed, 16 insertions(+), 10 deletions(-) diff --git a/bill-of-materials.json b/bill-of-materials.json index 0a66e6c54d9f..82254a5aa7b7 100644 --- a/bill-of-materials.json +++ b/bill-of-materials.json @@ -179,6 +179,15 @@ } ] }, + { + "project": "github.com/google/go-cmp/cmp", + "licenses": [ + { + "type": "BSD 3-clause \"New\" or \"Revised\" License", + "confidence": 0.9663865546218487 + } + ] + }, { "project": "github.com/gorilla/websocket", "licenses": [ diff --git a/go.mod b/go.mod index 4e2211060443..85b246469753 100644 --- a/go.mod +++ b/go.mod @@ -48,6 +48,7 @@ require ( github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da // indirect github.com/golang/protobuf v1.5.2 // indirect github.com/google/btree v1.0.1 // indirect + github.com/google/go-cmp v0.5.6 // indirect github.com/gorilla/websocket v1.4.2 // indirect github.com/grpc-ecosystem/go-grpc-middleware v1.3.0 // indirect github.com/grpc-ecosystem/go-grpc-prometheus v1.2.0 // indirect @@ -81,6 +82,7 @@ require ( golang.org/x/net v0.0.0-20220105145211-5b0dc2dfae98 // indirect golang.org/x/sys v0.0.0-20211123173158-ef496fb156ab // indirect golang.org/x/text v0.3.7 // indirect + golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1 // indirect google.golang.org/genproto v0.0.0-20211118181313-81c1377c94b1 // indirect google.golang.org/protobuf v1.27.1 // indirect gopkg.in/natefinch/lumberjack.v2 v2.0.0 // indirect diff --git a/tests/framework/integration/cluster.go b/tests/framework/integration/cluster.go index a32e634719c7..4600e092d84d 100644 --- a/tests/framework/integration/cluster.go +++ b/tests/framework/integration/cluster.go @@ -58,6 +58,8 @@ import ( "go.uber.org/zap/zapcore" "go.uber.org/zap/zaptest" + "github.com/google/go-cmp/cmp" + "github.com/google/go-cmp/cmp/cmpopts" "github.com/soheilhy/cmux" "go.uber.org/zap" "golang.org/x/crypto/bcrypt" @@ -483,16 +485,7 @@ func (c *Cluster) waitVersion() { func isMembersEqual(membs []*pb.Member, wmembs []*pb.Member) bool { sort.Sort(SortableMemberSliceByPeerURLs(membs)) sort.Sort(SortableMemberSliceByPeerURLs(wmembs)) - for i := range membs { - membs[i].ID = 0 - if membs[i].PeerURLs == nil { - membs[i].PeerURLs = []string{} - } - if membs[i].ClientURLs == nil { - membs[i].ClientURLs = []string{} - } - } - return reflect.DeepEqual(membs, wmembs) + return cmp.Equal(membs, wmembs, cmpopts.IgnoreFields(pb.Member{}, "ID", "PeerURLs", "ClientURLs")) } func newLocalListener(t testutil.TB) net.Listener { diff --git a/tests/go.mod b/tests/go.mod index 9e3cbdb77a2b..2850b0f02f78 100644 --- a/tests/go.mod +++ b/tests/go.mod @@ -19,6 +19,7 @@ require ( github.com/dustin/go-humanize v1.0.0 github.com/gogo/protobuf v1.3.2 github.com/golang/protobuf v1.5.2 + github.com/google/go-cmp v0.5.6 github.com/grpc-ecosystem/go-grpc-middleware v1.3.0 github.com/grpc-ecosystem/go-grpc-prometheus v1.2.0 github.com/grpc-ecosystem/grpc-gateway v1.16.0 @@ -77,6 +78,7 @@ require ( golang.org/x/net v0.0.0-20220105145211-5b0dc2dfae98 // indirect golang.org/x/sys v0.0.0-20211123173158-ef496fb156ab // indirect golang.org/x/text v0.3.7 // indirect + golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1 // indirect google.golang.org/genproto v0.0.0-20211118181313-81c1377c94b1 // indirect google.golang.org/protobuf v1.27.1 // indirect gopkg.in/natefinch/lumberjack.v2 v2.0.0 // indirect From 902dc05014dc304c42eee2d5b65536f9514fb0ae Mon Sep 17 00:00:00 2001 From: Marek Siarkowicz Date: Tue, 1 Feb 2022 16:40:23 +0100 Subject: [PATCH 114/258] tests: Update assertAuthority to explain filtering put method requests --- tests/integration/grpc_test.go | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/tests/integration/grpc_test.go b/tests/integration/grpc_test.go index 6c1e34ae55a4..ca36cb888c79 100644 --- a/tests/integration/grpc_test.go +++ b/tests/integration/grpc_test.go @@ -108,12 +108,13 @@ func TestAuthority(t *testing.T) { kv := setupClient(t, tc.clientURLPattern, clus, tlsConfig) defer kv.Close() + putRequestMethod := "/etcdserverpb.KV/Put" _, err := kv.Put(context.TODO(), "foo", "bar") if err != nil { t.Fatal(err) } - assertAuthority(t, templateAuthority(t, tc.expectAuthorityPattern, clus.Members[0]), clus) + assertAuthority(t, templateAuthority(t, tc.expectAuthorityPattern, clus.Members[0]), clus, putRequestMethod) }) } } @@ -181,12 +182,12 @@ func templateAuthority(t *testing.T, pattern string, m *integration.Member) stri return authority } -func assertAuthority(t *testing.T, expectedAuthority string, clus *integration.Cluster) { +func assertAuthority(t *testing.T, expectedAuthority string, clus *integration.Cluster, filterMethod string) { t.Helper() requestsFound := 0 for _, m := range clus.Members { for _, r := range m.RecordedRequests() { - if r.FullMethod != "/etcdserverpb.KV/Put" { + if filterMethod != "" && r.FullMethod != filterMethod { continue } requestsFound++ From 396efd96080c2e7a111ffd340269b685c5f393f3 Mon Sep 17 00:00:00 2001 From: Marek Siarkowicz Date: Wed, 26 Jan 2022 12:11:10 +0100 Subject: [PATCH 115/258] Cleanup scripts in root directory --- .github/workflows/build.yaml | 18 +++++++-------- .github/workflows/e2e.yaml | 4 ++-- .github/workflows/functional.yaml | 2 +- .github/workflows/grpcproxy.yaml | 4 ++-- .github/workflows/static-analysis.yaml | 2 +- .github/workflows/tests.yaml | 10 ++++---- Makefile | 10 ++++---- build | 6 ----- scripts/{build-binary => build-binary.sh} | 2 +- scripts/{build-docker => build-docker.sh} | 0 scripts/build-release.sh | 2 +- build.bat => scripts/build.bat | 0 build.ps1 => scripts/build.ps1 | 0 build.sh => scripts/build.sh | 0 scripts/codecov_upload.sh | 2 +- scripts/{release => release.sh} | 9 +++++++- test.sh => scripts/test.sh | 28 +++++++++++------------ scripts/test_lib.sh | 4 ++-- test | 6 ----- tests/functional/Dockerfile | 4 ++-- tests/functional/README.md | 4 ++-- tests/functional/cmd/etcd-proxy/main.go | 2 +- tools/local-tester/README.md | 2 +- 23 files changed, 58 insertions(+), 63 deletions(-) delete mode 100755 build rename scripts/{build-binary => build-binary.sh} (98%) rename scripts/{build-docker => build-docker.sh} (100%) rename build.bat => scripts/build.bat (100%) rename build.ps1 => scripts/build.ps1 (100%) rename build.sh => scripts/build.sh (100%) rename scripts/{release => release.sh} (97%) rename test.sh => scripts/test.sh (96%) delete mode 100755 test diff --git a/.github/workflows/build.yaml b/.github/workflows/build.yaml index 6601f89364bd..5d766b513f04 100644 --- a/.github/workflows/build.yaml +++ b/.github/workflows/build.yaml @@ -27,31 +27,31 @@ jobs: echo "${TARGET}" case "${TARGET}" in linux-amd64) - ARCH=amd64 PASSES='build' ./test.sh + ARCH=amd64 PASSES='build' ./scripts/test.sh ;; linux-386) - ARCH=386 PASSES='build' ./test.sh + ARCH=386 PASSES='build' ./scripts/test.sh ;; darwin-amd64) - ARCH=amd64 GOOS=darwin GO_BUILD_FLAGS='-v -mod=readonly' ./build.sh + ARCH=amd64 GOOS=darwin GO_BUILD_FLAGS='-v -mod=readonly' ./scripts/build.sh ;; darwin-arm64) - ARCH=arm64 GOOS=darwin GO_BUILD_FLAGS='-v -mod=readonly' ./build.sh + ARCH=arm64 GOOS=darwin GO_BUILD_FLAGS='-v -mod=readonly' ./scripts/build.sh ;; windows-amd64) - ARCH=amd64 GOOS=windows GO_BUILD_FLAGS='-v -mod=readonly' ./build.sh + ARCH=amd64 GOOS=windows GO_BUILD_FLAGS='-v -mod=readonly' ./scripts/build.sh ;; linux-arm) - ARCH=arm GO_BUILD_FLAGS='-v -mod=readonly' ./build.sh + ARCH=arm GO_BUILD_FLAGS='-v -mod=readonly' ./scripts/build.sh ;; linux-arm64) - ARCH=arm64 GO_BUILD_FLAGS='-v -mod=readonly' ./build.sh + ARCH=arm64 GO_BUILD_FLAGS='-v -mod=readonly' ./scripts/build.sh ;; linux-ppc64le) - ARCH=ppc64le GO_BUILD_FLAGS='-v -mod=readonly' ./build.sh + ARCH=ppc64le GO_BUILD_FLAGS='-v -mod=readonly' ./scripts/build.sh ;; linux-s390x) - ARCH=s390x GO_BUILD_FLAGS='-v -mod=readonly' ./build.sh + ARCH=s390x GO_BUILD_FLAGS='-v -mod=readonly' ./scripts/build.sh ;; *) echo "Failed to find target" diff --git a/.github/workflows/e2e.yaml b/.github/workflows/e2e.yaml index 50e40b10ce76..940002e2c67e 100644 --- a/.github/workflows/e2e.yaml +++ b/.github/workflows/e2e.yaml @@ -21,11 +21,11 @@ jobs: echo "${TARGET}" case "${TARGET}" in linux-amd64-e2e) - PASSES='build release e2e' MANUAL_VER=v3.5.0 CPU='4' EXPECT_DEBUG='true' COVER='false' RACE='true' ./test.sh 2>&1 | tee test.log + PASSES='build release e2e' MANUAL_VER=v3.5.0 CPU='4' EXPECT_DEBUG='true' COVER='false' RACE='true' ./scripts/test.sh 2>&1 | tee test.log ! egrep "(--- FAIL:|FAIL:|DATA RACE|panic: test timed out|appears to have leaked)" -B50 -A10 test.log ;; linux-386-e2e) - GOARCH=386 PASSES='build e2e' CPU='4' EXPECT_DEBUG='true' COVER='false' RACE='true' ./test.sh 2>&1 | tee test.log + GOARCH=386 PASSES='build e2e' CPU='4' EXPECT_DEBUG='true' COVER='false' RACE='true' ./scripts/test.sh 2>&1 | tee test.log ! egrep "(--- FAIL:|FAIL:|DATA RACE|panic: test timed out|appears to have leaked)" -B50 -A10 test.log ;; *) diff --git a/.github/workflows/functional.yaml b/.github/workflows/functional.yaml index 331cf96cded8..3aa9572666de 100644 --- a/.github/workflows/functional.yaml +++ b/.github/workflows/functional.yaml @@ -20,7 +20,7 @@ jobs: echo "${TARGET}" case "${TARGET}" in linux-amd64-functional) - GO_BUILD_FLAGS='-v -mod=readonly' ./build.sh && GOARCH=amd64 PASSES='functional' ./test.sh + GO_BUILD_FLAGS='-v -mod=readonly' ./scripts/build.sh && GOARCH=amd64 PASSES='functional' ./scripts/test.sh ;; *) echo "Failed to find target" diff --git a/.github/workflows/grpcproxy.yaml b/.github/workflows/grpcproxy.yaml index ef2533351ae8..b20d60413607 100644 --- a/.github/workflows/grpcproxy.yaml +++ b/.github/workflows/grpcproxy.yaml @@ -21,11 +21,11 @@ jobs: echo "${TARGET}" case "${TARGET}" in linux-amd64-grpcproxy-integration) - PASSES='build grpcproxy_integration' CPU='4' COVER='false' RACE='true' ./test.sh 2>&1 | tee test.log + PASSES='build grpcproxy_integration' CPU='4' COVER='false' RACE='true' ./scripts/test.sh 2>&1 | tee test.log ! egrep "(--- FAIL:|FAIL:|DATA RACE|panic: test timed out|appears to have leaked)" -B50 -A10 test.log ;; linux-amd64-grpcproxy-e2e) - PASSES='build grpcproxy_e2e' CPU='4' COVER='false' RACE='true' ./test.sh 2>&1 | tee test.log + PASSES='build grpcproxy_e2e' CPU='4' COVER='false' RACE='true' ./scripts/test.sh 2>&1 | tee test.log ! egrep "(--- FAIL:|FAIL:|DATA RACE|panic: test timed out|appears to have leaked)" -B50 -A10 test.log ;; *) diff --git a/.github/workflows/static-analysis.yaml b/.github/workflows/static-analysis.yaml index d6ad2384e8b9..0f87a5d0f3b6 100644 --- a/.github/workflows/static-analysis.yaml +++ b/.github/workflows/static-analysis.yaml @@ -20,7 +20,7 @@ jobs: echo "${TARGET}" case "${TARGET}" in linux-amd64-fmt) - GOARCH=amd64 PASSES='fmt bom dep' ./test.sh + GOARCH=amd64 PASSES='fmt bom dep' ./scripts/test.sh ;; *) echo "Failed to find target" diff --git a/.github/workflows/tests.yaml b/.github/workflows/tests.yaml index d33616327222..2348d0aa7175 100644 --- a/.github/workflows/tests.yaml +++ b/.github/workflows/tests.yaml @@ -25,19 +25,19 @@ jobs: export JUNIT_REPORT_DIR=$(realpath ${TARGET}) case "${TARGET}" in linux-amd64-integration-1-cpu) - GOARCH=amd64 CPU=1 PASSES='integration' RACE='false' ./test.sh + GOARCH=amd64 CPU=1 PASSES='integration' RACE='false' ./scripts/test.sh ;; linux-amd64-integration-2-cpu) - GOARCH=amd64 CPU=2 PASSES='integration' RACE='false' ./test.sh + GOARCH=amd64 CPU=2 PASSES='integration' RACE='false' ./scripts/test.sh ;; linux-amd64-integration-4-cpu) - GOARCH=amd64 CPU=4 PASSES='integration' RACE='false' ./test.sh + GOARCH=amd64 CPU=4 PASSES='integration' RACE='false' ./scripts/test.sh ;; linux-amd64-unit-4-cpu-race) - GOARCH=amd64 PASSES='unit' RACE='true' CPU='4' ./test.sh -p=2 + GOARCH=amd64 PASSES='unit' RACE='true' CPU='4' ./scripts/test.sh -p=2 ;; linux-386-unit-1-cpu) - GOARCH=386 PASSES='unit' RACE='false' CPU='1' ./test.sh -p=4 + GOARCH=386 PASSES='unit' RACE='false' CPU='1' ./scripts/test.sh -p=4 ;; *) echo "Failed to find target" diff --git a/Makefile b/Makefile index 9f213bdb2886..07f183c74b4d 100644 --- a/Makefile +++ b/Makefile @@ -22,7 +22,7 @@ XARGS += rm -r .PHONY: build build: - GO_BUILD_FLAGS="-v" ./build.sh + GO_BUILD_FLAGS="-v" ./scripts/build.sh ./bin/etcd --version ./bin/etcdctl version ./bin/etcdutl version @@ -96,16 +96,16 @@ pull-docker-test: test: $(info TEST_OPTS: $(TEST_OPTS)) $(info log-file: test-$(TEST_SUFFIX).log) - $(TEST_OPTS) ./test.sh 2>&1 | tee test-$(TEST_SUFFIX).log + $(TEST_OPTS) ./scripts/test.sh 2>&1 | tee test-$(TEST_SUFFIX).log ! egrep "(--- FAIL:|FAIL:|DATA RACE|panic: test timed out|appears to have leaked)" -B50 -A10 test-$(TEST_SUFFIX).log test-smoke: $(info log-file: test-$(TEST_SUFFIX).log) - PASSES="fmt build unit" ./test.sh 2<&1 | tee test-$(TEST_SUFFIX).log + PASSES="fmt build unit" ./scripts/test.sh 2<&1 | tee test-$(TEST_SUFFIX).log test-full: $(info log-file: test-$(TEST_SUFFIX).log) - PASSES="fmt build release unit integration functional e2e grpcproxy" ./test.sh 2<&1 | tee test-$(TEST_SUFFIX).log + PASSES="fmt build release unit integration functional e2e grpcproxy" ./scripts/test.sh 2<&1 | tee test-$(TEST_SUFFIX).log ensure-docker-test-image-exists: make push-docker-test || echo "WARNING: Container Image not found in registry, building locally"; make build-docker-test @@ -122,7 +122,7 @@ docker-test: ensure-docker-test-image-exists $(TMP_DIR_MOUNT_FLAG) \ --mount type=bind,source=`pwd`,destination=/go/src/go.etcd.io/etcd \ gcr.io/etcd-development/etcd-test:go$(GO_VERSION) \ - /bin/bash -c "$(TEST_OPTS) ./test.sh 2>&1 | tee test-$(TEST_SUFFIX).log" + /bin/bash -c "$(TEST_OPTS) ./scripts/test.sh 2>&1 | tee test-$(TEST_SUFFIX).log" ! egrep "(--- FAIL:|FAIL:|DATA RACE|panic: test timed out|appears to have leaked)" -B50 -A10 test-$(TEST_SUFFIX).log docker-test-coverage: diff --git a/build b/build deleted file mode 100755 index 60aa15d768d4..000000000000 --- a/build +++ /dev/null @@ -1,6 +0,0 @@ -#!/usr/bin/env bash - -echo -e "\\e[91mDEPRECATED!!! Use build.sh script instead.\\e[0m\\n" -sleep 1 - -source ./build.sh diff --git a/scripts/build-binary b/scripts/build-binary.sh similarity index 98% rename from scripts/build-binary rename to scripts/build-binary.sh index b819a3e57575..ff42270a0f13 100755 --- a/scripts/build-binary +++ b/scripts/build-binary.sh @@ -87,7 +87,7 @@ function main { export GOARCH=${TARGET_ARCH} pushd etcd >/dev/null - GO_LDFLAGS="-s" ./build.sh + GO_LDFLAGS="-s" ./scripts/build.sh popd >/dev/null TARGET="etcd-${VER}-${GOOS}-${GOARCH}" diff --git a/scripts/build-docker b/scripts/build-docker.sh similarity index 100% rename from scripts/build-docker rename to scripts/build-docker.sh diff --git a/scripts/build-release.sh b/scripts/build-release.sh index 149be75f10e1..524af0078a77 100755 --- a/scripts/build-release.sh +++ b/scripts/build-release.sh @@ -22,7 +22,7 @@ ETCD_ROOT=$(dirname "${BASH_SOURCE[0]}")/.. pushd "${ETCD_ROOT}" >/dev/null log_callout "Building etcd binary..." - ./scripts/build-binary "${VERSION}" + ./scripts/build-binary.sh "${VERSION}" for TARGET_ARCH in "amd64" "arm64" "ppc64le" "s390x"; do log_callout "Building ${TARGET_ARCH} docker image..." diff --git a/build.bat b/scripts/build.bat similarity index 100% rename from build.bat rename to scripts/build.bat diff --git a/build.ps1 b/scripts/build.ps1 similarity index 100% rename from build.ps1 rename to scripts/build.ps1 diff --git a/build.sh b/scripts/build.sh similarity index 100% rename from build.sh rename to scripts/build.sh diff --git a/scripts/codecov_upload.sh b/scripts/codecov_upload.sh index f75ad60e0322..8ee1a65afb81 100755 --- a/scripts/codecov_upload.sh +++ b/scripts/codecov_upload.sh @@ -8,7 +8,7 @@ set -o pipefail LOG_FILE=${1:-test-coverage.log} # We collect the coverage -COVERDIR=covdir PASSES='build build_cov cov' ./test.sh 2>&1 | tee "${LOG_FILE}" +COVERDIR=covdir PASSES='build build_cov cov' ./scripts/test.sh 2>&1 | tee "${LOG_FILE}" test_success="$?" # We try to upload whatever we have: diff --git a/scripts/release b/scripts/release.sh similarity index 97% rename from scripts/release rename to scripts/release.sh index 816b34eb9c4e..9fdd5d689608 100755 --- a/scripts/release +++ b/scripts/release.sh @@ -140,7 +140,8 @@ main() { if [[ -n $(git status -s) ]]; then log_callout "Committing mods & api/version/version.go update." run git add api/version/version.go - run git add $(find -name go.mod ! -path './release/*'| xargs) + # shellcheck disable=SC2038,SC2046 + run git add $(find . -name go.mod ! -path './release/*'| xargs) run git diff --staged | cat run git commit -m "version: bump up to ${VERSION}" run git diff --staged | cat @@ -162,6 +163,7 @@ main() { fi # Verify the latest commit has the version tag + # shellcheck disable=SC2155 local tag="$(git describe --exact-match HEAD)" if [ "${tag}" != "${RELEASE_VERSION}" ]; then log_error "Error: Expected HEAD to be tagged with ${RELEASE_VERSION}, but 'git describe --exact-match HEAD' reported: ${tag}" @@ -169,6 +171,7 @@ main() { fi # Verify the version tag is on the right branch + # shellcheck disable=SC2155 local branch=$(git for-each-ref --contains "${RELEASE_VERSION}" --format="%(refname)" 'refs/heads' | cut -d '/' -f 3) if [ "${branch}" != "${BRANCH}" ]; then log_error "Error: Git tag ${RELEASE_VERSION} should be on branch '${BRANCH}' but is on '${branch}'" @@ -198,6 +201,7 @@ main() { # Generate SHA256SUMS log_callout "Generating sha256sums of release artifacts." pushd ./release + # shellcheck disable=SC2010 ls . | grep -E '\.tar.gz$|\.zip$' | xargs shasum -a 256 > ./SHA256SUMS popd if [ -s ./release/SHA256SUMS ]; then @@ -263,6 +267,7 @@ main() { # Check image versions for IMAGE in "quay.io/coreos/etcd:${RELEASE_VERSION}" "gcr.io/etcd-development/etcd:${RELEASE_VERSION}"; do + # shellcheck disable=SC2155 local image_version=$(docker run --rm "${IMAGE}" etcd --version | grep "etcd Version" | awk -F: '{print $2}' | tr -d '[:space:]') if [ "${image_version}" != "${VERSION}" ]; then log_error "Check failed: etcd --version output for ${IMAGE} is incorrect: ${image_version}" @@ -271,9 +276,11 @@ main() { done # Check gsutil binary versions + # shellcheck disable=SC2155 local BINARY_TGZ="etcd-${RELEASE_VERSION}-$(go env GOOS)-amd64.tar.gz" gsutil cp "gs://etcd/${RELEASE_VERSION}/${BINARY_TGZ}" downloads tar -zx -C downloads -f "downloads/${BINARY_TGZ}" + # shellcheck disable=SC2155 local binary_version=$("./downloads/etcd-${RELEASE_VERSION}-$(go env GOOS)-amd64/etcd" --version | grep "etcd Version" | awk -F: '{print $2}' | tr -d '[:space:]') if [ "${binary_version}" != "${VERSION}" ]; then log_error "Check failed: etcd --version output for ${BINARY_TGZ} from gs://etcd/${RELEASE_VERSION} is incorrect: ${binary_version}" diff --git a/test.sh b/scripts/test.sh similarity index 96% rename from test.sh rename to scripts/test.sh index c9c72417135d..c8188546a114 100755 --- a/test.sh +++ b/scripts/test.sh @@ -1,35 +1,35 @@ #!/usr/bin/env bash # # Run all etcd tests -# ./test.sh -# ./test.sh -v +# ./scripts/test.sh +# ./scripts/test.sh -v # # # Run specified test pass # -# $ PASSES=unit ./test.sh -# $ PASSES=integration ./test.sh +# $ PASSES=unit ./scripts/test.sh +# $ PASSES=integration ./scripts/test.sh # # # Run tests for one package # Each pass has different default timeout, if you just run tests in one package or 1 test case then you can set TIMEOUT # flag for different expectation # -# $ PASSES=unit PKG=./wal TIMEOUT=1m ./test.sh -# $ PASSES=integration PKG=./clientv3 TIMEOUT=1m ./test.sh +# $ PASSES=unit PKG=./wal TIMEOUT=1m ./scripts/test.sh +# $ PASSES=integration PKG=./clientv3 TIMEOUT=1m ./scripts/test.sh # # Run specified unit tests in one package # To run all the tests with prefix of "TestNew", set "TESTCASE=TestNew "; # to run only "TestNew", set "TESTCASE="\bTestNew\b"" # -# $ PASSES=unit PKG=./wal TESTCASE=TestNew TIMEOUT=1m ./test.sh -# $ PASSES=unit PKG=./wal TESTCASE="\bTestNew\b" TIMEOUT=1m ./test.sh -# $ PASSES=integration PKG=./client/integration TESTCASE="\bTestV2NoRetryEOF\b" TIMEOUT=1m ./test.sh +# $ PASSES=unit PKG=./wal TESTCASE=TestNew TIMEOUT=1m ./scripts/test.sh +# $ PASSES=unit PKG=./wal TESTCASE="\bTestNew\b" TIMEOUT=1m ./scripts/test.sh +# $ PASSES=integration PKG=./client/integration TESTCASE="\bTestV2NoRetryEOF\b" TIMEOUT=1m ./scripts/test.sh # # # Run code coverage # COVERDIR must either be a absolute path or a relative path to the etcd root -# $ COVERDIR=coverage PASSES="build build_cov cov" ./test.sh +# $ COVERDIR=coverage PASSES="build build_cov cov" ./scripts/test.sh # $ go tool cover -html ./coverage/cover.out set -e @@ -43,7 +43,7 @@ set -o pipefail export GOFLAGS=-mod=readonly source ./scripts/test_lib.sh -source ./build.sh +source ./scripts/build.sh PASSES=${PASSES:-"fmt bom dep build unit"} PKG=${PKG:-} @@ -299,7 +299,7 @@ function cov_pass { fi if [ ! -f "bin/etcd_test" ]; then - log_error "etcd_test binary not found. Call: PASSES='build_cov' ./test.sh" + log_error "etcd_test binary not found. Call: PASSES='build_cov' ./scripts/test.sh" return 255 fi @@ -400,7 +400,7 @@ function fmt_pass { function shellcheck_pass { if tool_exists "shellcheck" "https://github.com/koalaman/shellcheck#installing"; then - generic_checker run shellcheck -fgcc build test scripts/*.sh ./*.sh + generic_checker run shellcheck -fgcc scripts/*.sh fi } @@ -410,7 +410,7 @@ function shellws_pass { local files files=$(find ./ -name '*.sh' -print0 | xargs -0 ) # shellcheck disable=SC2206 - files=( ${files[@]} "./scripts/build-binary" "./scripts/build-docker" "./scripts/release" ) + files=( ${files[@]} "./scripts/build-binary.sh" "./scripts/build-docker.sh" "./scripts/release.sh" ) log_cmd "grep -E -n $'^ *${TAB}' ${files[*]}" # shellcheck disable=SC2086 if grep -E -n $'^ *${TAB}' "${files[@]}" | sed $'s|${TAB}|[\\\\tab]|g'; then diff --git a/scripts/test_lib.sh b/scripts/test_lib.sh index 7c2d0403f4cf..2ca46edebc23 100644 --- a/scripts/test_lib.sh +++ b/scripts/test_lib.sh @@ -71,7 +71,7 @@ function relativePath { local commonPart=$source local result="" - while [[ "${target#$commonPart}" == "${target}" ]]; do + while [[ "${target#"$commonPart"}" == "${target}" ]]; do # no match, means that candidate common part is not correct # go up one level (reduce common part) commonPart="$(dirname "$commonPart")" @@ -90,7 +90,7 @@ function relativePath { # since we now have identified the common part, # compute the non-common part - local forwardPart="${target#$commonPart}" + local forwardPart="${target#"$commonPart"}" # and now stick all parts together if [[ -n $result ]] && [[ -n $forwardPart ]]; then diff --git a/test b/test deleted file mode 100755 index a14782bc3c1d..000000000000 --- a/test +++ /dev/null @@ -1,6 +0,0 @@ -#!/usr/bin/env bash - -echo -e "\\e[91mDEPRECATED!!! Use test.sh script instead.\\e[0m\\n" -sleep 1 - -source ./test.sh diff --git a/tests/functional/Dockerfile b/tests/functional/Dockerfile index c59d4872ceea..74b6e3775671 100644 --- a/tests/functional/Dockerfile +++ b/tests/functional/Dockerfile @@ -26,11 +26,11 @@ ADD ./tests/functional/functional.yaml /functional.yaml RUN go get -v go.etcd.io/gofail \ && pushd ${GOPATH}/src/go.etcd.io/etcd \ - && GO_BUILD_FLAGS="-v" ./build.sh \ + && GO_BUILD_FLAGS="-v" ./scripts/build.sh \ && mkdir -p /bin \ && cp ./bin/etcd /bin/etcd \ && cp ./bin/etcdctl /bin/etcdctl \ - && GO_BUILD_FLAGS="-v" FAILPOINTS=1 ./build.sh \ + && GO_BUILD_FLAGS="-v" FAILPOINTS=1 ./scripts/build.sh \ && cp ./bin/etcd /bin/etcd-failpoints \ && ./tests/functional/build \ && cp ./bin/etcd-agent /bin/etcd-agent \ diff --git a/tests/functional/README.md b/tests/functional/README.md index fe91b86cbefd..50f82c95fbaa 100644 --- a/tests/functional/README.md +++ b/tests/functional/README.md @@ -39,7 +39,7 @@ Proxy layer that simulates various network conditions. Test locally ```bash -$ ./build.sh +$ ./scripts/build.sh $ ./bin/etcd $ make build-functional @@ -201,7 +201,7 @@ $ curl -L http://localhost:2378/blackhole-tx -X DELETE Trigger leader election ```bash -$ ./build.sh +$ ./scripts/build.sh $ make build-functional $ rm -rf /tmp/etcd-proxy-data.s* diff --git a/tests/functional/cmd/etcd-proxy/main.go b/tests/functional/cmd/etcd-proxy/main.go index 3b1705b94355..ff823939686b 100644 --- a/tests/functional/cmd/etcd-proxy/main.go +++ b/tests/functional/cmd/etcd-proxy/main.go @@ -54,7 +54,7 @@ See README.md for more examples. Example: # build etcd -$ ./build.sh +$ ./scripts/build.sh $ ./bin/etcd # build etcd-proxy diff --git a/tools/local-tester/README.md b/tools/local-tester/README.md index 75e3e0aa950c..cbd39e6f31e3 100644 --- a/tools/local-tester/README.md +++ b/tools/local-tester/README.md @@ -11,7 +11,7 @@ local-tester depends on `goreman` to manage its processes and `bash` to run faul local-tester needs `etcd`, `benchmark`, and `bridge` binaries. To build these binaries, run the following from the etcd repository root: ```sh -./build.sh +./scripts/build.sh pushd tools/benchmark/ && go build && popd pushd tools/local-tester/bridge && go build && popd ``` From a1f3c2c7cc795ec0da31e364a258ccc98a7ccc44 Mon Sep 17 00:00:00 2001 From: Marek Siarkowicz Date: Mon, 17 Jan 2022 15:03:17 +0100 Subject: [PATCH 116/258] server: Make --v2-deprecation=write-only the default and remove not-yet option --- server/config/v2_deprecation.go | 4 ++-- server/etcdmain/config.go | 1 - tests/e2e/v2store_deprecation_test.go | 29 ++++++++++++--------------- 3 files changed, 15 insertions(+), 19 deletions(-) diff --git a/server/config/v2_deprecation.go b/server/config/v2_deprecation.go index 828bd9a8f430..862c3bb9343b 100644 --- a/server/config/v2_deprecation.go +++ b/server/config/v2_deprecation.go @@ -17,7 +17,7 @@ package config type V2DeprecationEnum string const ( - // Default in v3.5. Issues a warning if v2store have meaningful content. + // No longer supported in v3.6 V2_DEPR_0_NOT_YET = V2DeprecationEnum("not-yet") // Default in v3.6. Meaningful v2 state is not allowed. // The V2 files are maintained for v3.5 rollback. @@ -28,7 +28,7 @@ const ( // ability to rollback to etcd v3.5. V2_DEPR_2_GONE = V2DeprecationEnum("gone") - V2_DEPR_DEFAULT = V2_DEPR_0_NOT_YET + V2_DEPR_DEFAULT = V2_DEPR_1_WRITE_ONLY ) func (e V2DeprecationEnum) IsAtLeast(v2d V2DeprecationEnum) bool { diff --git a/server/etcdmain/config.go b/server/etcdmain/config.go index 4257f1ba081b..39ae8def3fd0 100644 --- a/server/etcdmain/config.go +++ b/server/etcdmain/config.go @@ -122,7 +122,6 @@ func newConfig() *config { proxyFlagOn, ), v2deprecation: flags.NewSelectiveStringsValue( - string(cconfig.V2_DEPR_0_NOT_YET), string(cconfig.V2_DEPR_1_WRITE_ONLY), string(cconfig.V2_DEPR_1_WRITE_ONLY_DROP), string(cconfig.V2_DEPR_2_GONE)), diff --git a/tests/e2e/v2store_deprecation_test.go b/tests/e2e/v2store_deprecation_test.go index 98442d842d9d..a8afde5aaa9b 100644 --- a/tests/e2e/v2store_deprecation_test.go +++ b/tests/e2e/v2store_deprecation_test.go @@ -44,18 +44,6 @@ func createV2store(t testing.TB, lastReleaseBinary string, dataDirPath string) { } } -func assertVerifyCanStartV2deprecationNotYet(t testing.TB, dataDirPath string) { - t.Log("verify: possible to start etcd with --v2-deprecation=not-yet mode") - - cfg := e2e.ConfigStandalone(e2e.EtcdProcessClusterConfig{DataDirPath: dataDirPath, V2deprecation: "not-yet", KeepDataDir: true}) - epc, err := e2e.NewEtcdProcessCluster(t, cfg) - assert.NoError(t, err) - - defer func() { - assert.NoError(t, epc.Stop()) - }() -} - func assertVerifyCannotStartV2deprecationWriteOnly(t testing.TB, dataDirPath string) { t.Log("Verify its infeasible to start etcd with --v2-deprecation=write-only mode") proc, err := e2e.SpawnCmd([]string{e2e.BinDir + "/etcd", "--v2-deprecation=write-only", "--data-dir=" + dataDirPath}, nil) @@ -65,6 +53,15 @@ func assertVerifyCannotStartV2deprecationWriteOnly(t testing.TB, dataDirPath str assert.NoError(t, err) } +func assertVerifyCannotStartV2deprecationNotYet(t testing.TB, dataDirPath string) { + t.Log("Verify its infeasible to start etcd with --v2-deprecation=not-yet mode") + proc, err := e2e.SpawnCmd([]string{e2e.BinDir + "/etcd", "--v2-deprecation=not-yet", "--data-dir=" + dataDirPath}, nil) + assert.NoError(t, err) + + _, err = proc.Expect(`invalid value "not-yet" for flag -v2-deprecation: invalid value "not-yet"`) + assert.NoError(t, err) +} + func TestV2Deprecation(t *testing.T) { e2e.BeforeTest(t) dataDirPath := t.TempDir() @@ -78,12 +75,12 @@ func TestV2Deprecation(t *testing.T) { createV2store(t, lastReleaseBinary, dataDirPath) }) - t.Run("--v2-deprecation=write-only fails", func(t *testing.T) { - assertVerifyCannotStartV2deprecationWriteOnly(t, dataDirPath) + t.Run("--v2-deprecation=not-yet fails", func(t *testing.T) { + assertVerifyCannotStartV2deprecationNotYet(t, dataDirPath) }) - t.Run("--v2-deprecation=not-yet succeeds", func(t *testing.T) { - assertVerifyCanStartV2deprecationNotYet(t, dataDirPath) + t.Run("--v2-deprecation=write-only fails", func(t *testing.T) { + assertVerifyCannotStartV2deprecationWriteOnly(t, dataDirPath) }) } From 900fc8dd7ea578fbf1944836a04e40e98a11f402 Mon Sep 17 00:00:00 2001 From: ahrtr Date: Sun, 6 Feb 2022 14:23:28 +0800 Subject: [PATCH 117/258] replace gobin with go install The repository github.com/myitcv/gobin has already been archived, and the `go install` command accepts arguments with version suffixs starting from 1.16 (for example, go install example.com/cmd@v1.0.0). So there is no reason to continue to use gobin. --- scripts/test_lib.sh | 22 +++++++++++++--------- tests/Dockerfile | 1 - tools/mod/install_all.sh | 2 +- 3 files changed, 14 insertions(+), 11 deletions(-) diff --git a/scripts/test_lib.sh b/scripts/test_lib.sh index 7c2d0403f4cf..062aeb220f9e 100644 --- a/scripts/test_lib.sh +++ b/scripts/test_lib.sh @@ -353,23 +353,27 @@ function tool_exists { fi } -# Ensure gobin is available, as it runs majority of the tools -if ! command -v "gobin" >/dev/null; then - GOARCH="" run env GO111MODULE=off go get github.com/myitcv/gobin || exit 1 -fi - # tool_get_bin [tool] - returns absolute path to a tool binary (or returns error) function tool_get_bin { - tool_exists "gobin" "GO111MODULE=off go get github.com/myitcv/gobin" || return 2 - local tool="$1" + local pkg_part="$1" if [[ "$tool" == *"@"* ]]; then + pkg_part=$(echo "${tool}" | cut -d'@' -f1) # shellcheck disable=SC2086 - run gobin ${GOBINARGS:-} -p "${tool}" || return 2 + run go install ${GOBINARGS:-} "${tool}" || return 2 else # shellcheck disable=SC2086 - run_for_module ./tools/mod run gobin ${GOBINARGS:-} -p -m --mod=readonly "${tool}" || return 2 + run_for_module ./tools/mod run go install ${GOBINARGS:-} "${tool}" || return 2 fi + + # remove the version suffix, such as removing "/v3" from "go.etcd.io/etcd/v3". + local cmd_base_name + cmd_base_name=$(basename "${pkg_part}") + if [[ ${cmd_base_name} =~ ^v[0-9]*$ ]]; then + pkg_part=$(dirname "${pkg_part}") + fi + + command -v "$(basename "${pkg_part}")" } # tool_pkg_dir [pkg] - returns absolute path to a directory that stores given pkg. diff --git a/tests/Dockerfile b/tests/Dockerfile index f6e5e7447cf0..091398fe3568 100644 --- a/tests/Dockerfile +++ b/tests/Dockerfile @@ -44,7 +44,6 @@ WORKDIR ${GOPATH}/src/go.etcd.io/etcd ADD ./scripts/install-marker.sh /tmp/install-marker.sh -RUN GO111MODULE=off go get github.com/myitcv/gobin RUN /tmp/install-marker.sh amd64 \ && rm -f /tmp/install-marker.sh \ && curl -s https://codecov.io/bash >/codecov \ diff --git a/tools/mod/install_all.sh b/tools/mod/install_all.sh index 7de5fb014731..2f099b5ea702 100755 --- a/tools/mod/install_all.sh +++ b/tools/mod/install_all.sh @@ -1,4 +1,4 @@ #!/usr/bin/env bash cd ./tools/mod || exit 2 -go list --tags tools -f '{{ join .Imports "\n" }}' | xargs gobin -p +go list --tags tools -f '{{ join .Imports "\n" }}' | xargs go install From 72c33d8b05e06db16690e5a6aa51ed7b438268b3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Manuel=20R=C3=BCger?= Date: Sun, 6 Feb 2022 22:32:45 +0100 Subject: [PATCH 118/258] contrib/mixin: Generate rules, fix tests MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * Add Makefile * Make tests runnable * Add generated rule manifest file Signed-off-by: Manuel Rüger --- .github/workflows/contrib.yaml | 11 +++++++++++ .gitignore | 3 ++- contrib/mixin/Makefile | 23 +++++++++++++++++++++++ contrib/mixin/README.md | 8 ++++++-- contrib/mixin/test.yaml | 34 ++++++++++++++++++++++------------ 5 files changed, 64 insertions(+), 15 deletions(-) create mode 100644 .github/workflows/contrib.yaml create mode 100644 contrib/mixin/Makefile diff --git a/.github/workflows/contrib.yaml b/.github/workflows/contrib.yaml new file mode 100644 index 000000000000..612580ce246e --- /dev/null +++ b/.github/workflows/contrib.yaml @@ -0,0 +1,11 @@ +name: Test contrib/mixin +on: [push, pull_request] +jobs: + test: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v2 + - uses: actions/setup-go@v2 + with: + go-version: "1.17.6" + - run: make -C contrib/mixin tools test diff --git a/.gitignore b/.gitignore index dbb48c6e1535..ab1bbe4ceb6b 100644 --- a/.gitignore +++ b/.gitignore @@ -14,6 +14,7 @@ *.test hack/tls-setup/certs .idea +/contrib/mixin/manifests /contrib/raftexample/raftexample /contrib/raftexample/raftexample-* /vendor @@ -22,4 +23,4 @@ hack/tls-setup/certs *.bak .gobincache/ /Documentation/dev-guide/api_reference_v3.md -/Documentation/dev-guide/api_concurrency_reference_v3.md \ No newline at end of file +/Documentation/dev-guide/api_concurrency_reference_v3.md diff --git a/contrib/mixin/Makefile b/contrib/mixin/Makefile new file mode 100644 index 000000000000..843215b00c4f --- /dev/null +++ b/contrib/mixin/Makefile @@ -0,0 +1,23 @@ +.PHONY: tools manifests test clean + +OS := linux +ARCH ?= amd64 +PROMETHEUS_VERSION := 2.33.1 + +tools: + go install github.com/google/go-jsonnet/cmd/jsonnet@latest + go install github.com/brancz/gojsontoyaml@latest + wget -qO- "https://github.com/prometheus/prometheus/releases/download/v${PROMETHEUS_VERSION}/prometheus-${PROMETHEUS_VERSION}.${OS}-${ARCH}.tar.gz" |\ + tar xvz --strip-components=1 -C "$$(go env GOPATH)/bin" prometheus-${PROMETHEUS_VERSION}.${OS}-${ARCH}/promtool + +manifests: manifests/etcd-prometheusRules.yaml + +manifests/etcd-prometheusRules.yaml: + mkdir -p manifests + jsonnet -e '(import "mixin.libsonnet").prometheusAlerts' | gojsontoyaml > manifests/etcd-prometheusRules.yaml + +test: manifests/etcd-prometheusRules.yaml + promtool test rules test.yaml + +clean: + rm -rf manifests/*.yaml diff --git a/contrib/mixin/README.md b/contrib/mixin/README.md index 224066f457d5..2ec70004cda1 100644 --- a/contrib/mixin/README.md +++ b/contrib/mixin/README.md @@ -12,11 +12,15 @@ Instructions for use are the same as the [kubernetes-mixin](https://github.com/k ## Testing alerts -Make sure to have [jsonnet](https://jsonnet.org/) and [gojsontoyaml](https://github.com/brancz/gojsontoyaml) installed. +Make sure to have [jsonnet](https://jsonnet.org/) and [gojsontoyaml](https://github.com/brancz/gojsontoyaml) installed. You can fetch it via + +``` +make tools +``` First compile the mixin to a YAML file, which the promtool will read: ``` -jsonnet -e '(import "mixin.libsonnet").prometheusAlerts' | gojsontoyaml > mixin.yaml +make manifests ``` Then run the unit test: diff --git a/contrib/mixin/test.yaml b/contrib/mixin/test.yaml index 24162bd4d4e7..e8f53f55007c 100644 --- a/contrib/mixin/test.yaml +++ b/contrib/mixin/test.yaml @@ -1,5 +1,5 @@ rule_files: - - mixin.yaml + - manifests/etcd-prometheusRules.yaml evaluation_interval: 1m @@ -86,14 +86,15 @@ tests: exp_annotations: description: 'etcd cluster "etcd": members are down (1).' summary: 'etcd cluster members are down.' + - interval: 1m input_series: - series: 'etcd_server_leader_changes_seen_total{job="etcd",instance="10.10.10.0"}' values: '0 0 2 0 0 1 0 0 0 0 0 0 0 0 0 0' - series: 'etcd_server_leader_changes_seen_total{job="etcd",instance="10.10.10.1"}' - values: '0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0' + values: '0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0' - series: 'etcd_server_leader_changes_seen_total{job="etcd",instance="10.10.10.2"}' - values: '0 0 0 0 0 0 0 0' + values: '0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0' alert_rule_test: - eval_time: 10m alertname: etcdHighNumberOfLeaderChanges @@ -111,25 +112,34 @@ tests: - series: 'etcd_server_leader_changes_seen_total{job="etcd",instance="10.10.10.1"}' values: '0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0' - series: 'etcd_server_leader_changes_seen_total{job="etcd",instance="10.10.10.2"}' - values: '0 0 0 0 0 0 0 0' + values: '0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0' alert_rule_test: - eval_time: 10m alertname: etcdHighNumberOfLeaderChanges exp_alerts: + - interval: 1m input_series: - - series: '((etcd_mvcc_db_total_size_in_bytes/etcd_server_quota_backend_bytes)*100){job="etcd",instance="10.10.10.0"}' - values: '0 10 20 0 0 10 0 0 30 0 0 0 0 0 0 0' - - series: '((etcd_mvcc_db_total_size_in_bytes/etcd_server_quota_backend_bytes)*100){job="etcd",instance="10.10.10.1"}' - values: '0 0 10 0 20 0 0 0 0 0 0 0 0 0 0 0' - - series: '((etcd_mvcc_db_total_size_in_bytes/etcd_server_quota_backend_bytes)*100){job="etcd",instance="10.10.10.2"}' - values: '0 0 0 0 0 0 0 0' + - series: 'etcd_mvcc_db_total_size_in_bytes{job="etcd",instance="10.10.10.0"}' + values: '0 1 2 0 0 1 0 3 0 0 0 0 0 0 0 0' + - series: 'etcd_server_quota_backend_bytes{job="etcd",instance="10.10.10.0"}' + values: '1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1' + - series: 'etcd_mvcc_db_total_size_in_bytes{job="etcd",instance="10.10.10.1"}' + values: '0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0' + - series: 'etcd_server_quota_backend_bytes{job="etcd",instance="10.10.10.1"}' + values: '1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1' + - series: 'etcd_mvcc_db_total_size_in_bytes{job="etcd",instance="10.10.10.2"}' + values: '0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0' + - series: 'etcd_server_quota_backend_bytes{job="etcd",instance="10.10.10.2"}' + values: '1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1' alert_rule_test: - - eval_time: 10m + - eval_time: 11m alertname: etcdExcessiveDatabaseGrowth exp_alerts: - exp_labels: + instance: '10.10.10.0' job: etcd severity: warning exp_annotations: - message: 'etcd cluster "etcd": Observed surge in etcd writes leading to 50% increase in database size over the past four hours, please check as it might be disruptive.' + description: 'etcd cluster "etcd": Observed surge in etcd writes leading to 50% increase in database size over the past four hours on etcd instance 10.10.10.0, please check as it might be disruptive.' + summary: 'etcd cluster database growing very fast.' From 9d83325db80acf5086708a031eb2c0f6248cb630 Mon Sep 17 00:00:00 2001 From: AdamKorcz Date: Thu, 10 Feb 2022 16:31:05 +0000 Subject: [PATCH 119/258] server/auth: fix oss-fuzz issue 44478 --- server/auth/simple_token.go | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/server/auth/simple_token.go b/server/auth/simple_token.go index be706522a535..5f66b56d1616 100644 --- a/server/auth/simple_token.go +++ b/server/auth/simple_token.go @@ -20,6 +20,7 @@ package auth import ( "context" "crypto/rand" + "errors" "fmt" "math/big" "strconv" @@ -212,7 +213,11 @@ func (t *tokenSimple) info(ctx context.Context, token string, revision uint64) ( func (t *tokenSimple) assign(ctx context.Context, username string, rev uint64) (string, error) { // rev isn't used in simple token, it is only used in JWT - index := ctx.Value(AuthenticateParamIndex{}).(uint64) + var index uint64 + var ok bool + if index, ok = ctx.Value(AuthenticateParamIndex{}).(uint64); !ok { + return "", errors.New("failed to assign") + } simpleTokenPrefix := ctx.Value(AuthenticateParamSimpleTokenPrefix{}).(string) token := fmt.Sprintf("%s.%d", simpleTokenPrefix, index) t.assignSimpleTokenToUser(username, token) From 029c354316304bf5c03f5ee0abd2f57d907f7324 Mon Sep 17 00:00:00 2001 From: AdamKorcz Date: Thu, 10 Feb 2022 16:11:09 +0000 Subject: [PATCH 120/258] server/storage/mvcc: fix oss-fuzz issue 44449 --- server/storage/mvcc/index.go | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/server/storage/mvcc/index.go b/server/storage/mvcc/index.go index 13cbc9b8bc2a..be817c5a6d46 100644 --- a/server/storage/mvcc/index.go +++ b/server/storage/mvcc/index.go @@ -257,8 +257,14 @@ func (ti *treeIndex) Equal(bi index) bool { equal := true ti.tree.Ascend(func(item btree.Item) bool { - aki := item.(*keyIndex) - bki := b.tree.Get(item).(*keyIndex) + var aki, bki *keyIndex + var ok bool + if aki, ok = item.(*keyIndex); !ok { + return false + } + if bki, ok = b.tree.Get(item).(*keyIndex); !ok { + return false + } if !aki.equal(bki) { equal = false return false From 01347a8f53802565049064eb077bcca33f60dac1 Mon Sep 17 00:00:00 2001 From: Bogdan Kanivets Date: Wed, 9 Feb 2022 10:46:18 -0800 Subject: [PATCH 121/258] server/storage/backend: restore original bolt db options after defrag Problem: Defrag was implemented before custom bolt options were added. Currently defrag doesn't restore backend options. For example BackendFreelistType will be unset after defrag. Solution: save bolt db options and use them in defrag. --- server/storage/backend/backend.go | 16 ++++++---------- server/storage/backend/backend_test.go | 16 +++++++++++++++- 2 files changed, 21 insertions(+), 11 deletions(-) diff --git a/server/storage/backend/backend.go b/server/storage/backend/backend.go index c75f443a4e32..c558ecacd68a 100644 --- a/server/storage/backend/backend.go +++ b/server/storage/backend/backend.go @@ -99,8 +99,9 @@ type backend struct { // mlock prevents backend database file to be swapped mlock bool - mu sync.RWMutex - db *bolt.DB + mu sync.RWMutex + bopts *bolt.Options + db *bolt.DB batchInterval time.Duration batchLimit int @@ -184,7 +185,8 @@ func newBackend(bcfg BackendConfig) *backend { // In future, may want to make buffering optional for low-concurrency systems // or dynamically swap between buffered/non-buffered depending on workload. b := &backend{ - db: db, + bopts: bopts, + db: db, batchInterval: bcfg.BatchInterval, batchLimit: bcfg.BatchLimit, @@ -510,13 +512,7 @@ func (b *backend) defrag() error { b.lg.Fatal("failed to rename tmp database", zap.Error(err)) } - defragmentedBoltOptions := bolt.Options{} - if boltOpenOptions != nil { - defragmentedBoltOptions = *boltOpenOptions - } - defragmentedBoltOptions.Mlock = b.mlock - - b.db, err = bolt.Open(dbp, 0600, &defragmentedBoltOptions) + b.db, err = bolt.Open(dbp, 0600, b.bopts) if err != nil { b.lg.Fatal("failed to open database", zap.String("path", dbp), zap.Error(err)) } diff --git a/server/storage/backend/backend_test.go b/server/storage/backend/backend_test.go index 389fa73bed15..0b3e4b629ed8 100644 --- a/server/storage/backend/backend_test.go +++ b/server/storage/backend/backend_test.go @@ -122,7 +122,17 @@ func TestBackendBatchIntervalCommit(t *testing.T) { } func TestBackendDefrag(t *testing.T) { - b, _ := betesting.NewDefaultTmpBackend(t) + bcfg := backend.DefaultBackendConfig() + // Make sure we change BackendFreelistType + // The goal is to verify that we restore config option after defrag. + if bcfg.BackendFreelistType == bolt.FreelistMapType { + bcfg.BackendFreelistType = bolt.FreelistArrayType + } else { + bcfg.BackendFreelistType = bolt.FreelistMapType + } + + b, _ := betesting.NewTmpBackendFromCfg(t, bcfg) + defer betesting.Close(t, b) tx := b.BatchTx() @@ -168,6 +178,10 @@ func TestBackendDefrag(t *testing.T) { if nsize >= size { t.Errorf("new size = %v, want < %d", nsize, size) } + db := backend.DbFromBackendForTest(b) + if db.FreelistType != bcfg.BackendFreelistType { + t.Errorf("db FreelistType = [%v], want [%v]", db.FreelistType, bcfg.BackendFreelistType) + } // try put more keys after shrink. tx = b.BatchTx() From b683aa125480073f6d4ffb5eea998bbc0e8c9417 Mon Sep 17 00:00:00 2001 From: sitchenchao Date: Sat, 12 Feb 2022 12:47:16 -0800 Subject: [PATCH 122/258] fix ctl_v3_kv_no_quorum_test.go and coverage failures --- scripts/build.sh | 2 +- scripts/test.sh | 2 +- tests/e2e/ctl_v3_kv_no_quorum_test.go | 54 ++++++++++++++++----------- 3 files changed, 35 insertions(+), 23 deletions(-) diff --git a/scripts/build.sh b/scripts/build.sh index bf41ce958318..e587dc1893f8 100755 --- a/scripts/build.sh +++ b/scripts/build.sh @@ -18,7 +18,7 @@ GO_BUILD_ENV=("CGO_ENABLED=0" "GO_BUILD_FLAGS=${GO_BUILD_FLAGS}" "GOOS=${GOOS}" toggle_failpoints() { mode="$1" if command -v gofail >/dev/null 2>&1; then - run gofail "$mode" server/etcdserver/ server/mvcc/backend/ + run gofail "$mode" server/etcdserver/ server/storage/backend/ elif [[ "$mode" != "disable" ]]; then log_error "FAILPOINTS set but gofail not found" exit 1 diff --git a/scripts/test.sh b/scripts/test.sh index c8188546a114..e8047ccb56ba 100755 --- a/scripts/test.sh +++ b/scripts/test.sh @@ -242,7 +242,7 @@ function split_dir { local num="${2}" local i=0 for f in "${d}/"*; do - local g=$(( "${i}" % "${num}" )) + local g=$(( i % num )) mkdir -p "${d}_${g}" mv "${f}" "${d}_${g}/" (( i++ )) diff --git a/tests/e2e/ctl_v3_kv_no_quorum_test.go b/tests/e2e/ctl_v3_kv_no_quorum_test.go index 942a6e4a9290..dbc599b49765 100644 --- a/tests/e2e/ctl_v3_kv_no_quorum_test.go +++ b/tests/e2e/ctl_v3_kv_no_quorum_test.go @@ -31,29 +31,41 @@ import ( ) func TestSerializableReadWithoutQuorum(t *testing.T) { - // Initialize a cluster with 3 members - epc, err := e2e.InitEtcdProcessCluster(t, e2e.NewConfigAutoTLS()) - if err != nil { - t.Fatalf("Failed to initilize the etcd cluster: %v", err) + tcs := []struct { + name string + testFunc func(cx ctlCtx) + }{ + { + name: "serializableReadTest", + testFunc: serializableReadTest, + }, + { + name: "linearizableReadTest", + testFunc: linearizableReadTest, + }, } + for _, tc := range tcs { + t.Run(tc.name, func(t *testing.T) { + // Initialize a cluster with 3 members + epc, err := e2e.InitEtcdProcessCluster(t, e2e.NewConfigAutoTLS()) + if err != nil { + t.Fatalf("Failed to initilize the etcd cluster: %v", err) + } - // Remove two members, so that only one etcd will get started - epc.Procs = epc.Procs[:1] + // Remove two members, so that only one etcd will get started + epc.Procs = epc.Procs[:1] - // Start the etcd cluster with only one member - if err := epc.Start(); err != nil { - t.Fatalf("Failed to start the etcd cluster: %v", err) - } - - // construct the ctl context - cx := getDefaultCtlCtx(t) - cx.epc = epc + // Start the etcd cluster with only one member + if err := epc.Start(); err != nil { + t.Fatalf("Failed to start the etcd cluster: %v", err) + } - // run serializable test and wait for result - runCtlTest(t, serializableReadTest, nil, cx) - - // run linearizable test and wait for result - runCtlTest(t, linearizableReadTest, nil, cx) + // construct the ctl context + cx := getDefaultCtlCtx(t) + cx.epc = epc + runCtlTest(t, tc.testFunc, nil, cx) + }) + } } func serializableReadTest(cx ctlCtx) { @@ -65,7 +77,7 @@ func serializableReadTest(cx ctlCtx) { func linearizableReadTest(cx ctlCtx) { cx.quorum = true - if err := ctlV3Get(cx, []string{"key1"}, []kv{}...); err == nil { - cx.t.Error("linearizableReadTest is expected to fail, but it succeeded") + if err := ctlV3GetWithErr(cx, []string{"key"}, []string{"retrying of unary invoker failed"}); err != nil { // expect errors + cx.t.Fatalf("ctlV3GetWithErr error (%v)", err) } } From fd79af9ee7e9810acbcd7f31f554d780e89df3b9 Mon Sep 17 00:00:00 2001 From: Chao Chen Date: Wed, 9 Feb 2022 11:54:06 -0800 Subject: [PATCH 123/258] load all leases from backend --- scripts/build.sh | 2 +- server/storage/schema/lease.go | 22 +++-- server/storage/schema/lease_test.go | 106 +++++++++++++++++++++++++ tests/framework/integration/cluster.go | 6 ++ tests/integration/v3_alarm_test.go | 98 +++++++++++++++++++++++ tests/integration/v3_lease_test.go | 86 ++++++++++++++++++++ 6 files changed, 313 insertions(+), 7 deletions(-) create mode 100644 server/storage/schema/lease_test.go diff --git a/scripts/build.sh b/scripts/build.sh index bf41ce958318..e587dc1893f8 100755 --- a/scripts/build.sh +++ b/scripts/build.sh @@ -18,7 +18,7 @@ GO_BUILD_ENV=("CGO_ENABLED=0" "GO_BUILD_FLAGS=${GO_BUILD_FLAGS}" "GOOS=${GOOS}" toggle_failpoints() { mode="$1" if command -v gofail >/dev/null 2>&1; then - run gofail "$mode" server/etcdserver/ server/mvcc/backend/ + run gofail "$mode" server/etcdserver/ server/storage/backend/ elif [[ "$mode" != "disable" ]]; then log_error "FAILPOINTS set but gofail not found" exit 1 diff --git a/server/storage/schema/lease.go b/server/storage/schema/lease.go index 43a0c06e4e19..1d06dfe9d133 100644 --- a/server/storage/schema/lease.go +++ b/server/storage/schema/lease.go @@ -16,7 +16,7 @@ package schema import ( "encoding/binary" - "math" + "fmt" "go.etcd.io/etcd/server/v3/lease/leasepb" "go.etcd.io/etcd/server/v3/storage/backend" @@ -27,15 +27,18 @@ func UnsafeCreateLeaseBucket(tx backend.BatchTx) { } func MustUnsafeGetAllLeases(tx backend.ReadTx) []*leasepb.Lease { - _, vs := tx.UnsafeRange(Lease, leaseIdToBytes(0), leaseIdToBytes(math.MaxInt64), 0) - ls := make([]*leasepb.Lease, 0, len(vs)) - for i := range vs { + ls := make([]*leasepb.Lease, 0) + err := tx.UnsafeForEach(Lease, func(k, v []byte) error { var lpb leasepb.Lease - err := lpb.Unmarshal(vs[i]) + err := lpb.Unmarshal(v) if err != nil { - panic("failed to unmarshal lease proto item") + return fmt.Errorf("failed to Unmarshal lease proto item; lease ID=%016x", bytesToLeaseID(k)) } ls = append(ls, &lpb) + return nil + }) + if err != nil { + panic(err) } return ls } @@ -72,3 +75,10 @@ func leaseIdToBytes(n int64) []byte { binary.BigEndian.PutUint64(bytes, uint64(n)) return bytes } + +func bytesToLeaseID(bytes []byte) int64 { + if len(bytes) != 8 { + panic(fmt.Errorf("lease ID must be 8-byte")) + } + return int64(binary.BigEndian.Uint64(bytes)) +} diff --git a/server/storage/schema/lease_test.go b/server/storage/schema/lease_test.go new file mode 100644 index 000000000000..8ac4f163d853 --- /dev/null +++ b/server/storage/schema/lease_test.go @@ -0,0 +1,106 @@ +// Copyright 2022 The etcd Authors +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package schema + +import ( + "math" + "testing" + "time" + + "github.com/stretchr/testify/assert" + "go.etcd.io/etcd/server/v3/lease/leasepb" + "go.etcd.io/etcd/server/v3/storage/backend" + betesting "go.etcd.io/etcd/server/v3/storage/backend/testing" +) + +func TestLeaseBackend(t *testing.T) { + tcs := []struct { + name string + setup func(tx backend.BatchTx) + want []*leasepb.Lease + }{ + { + name: "Empty by default", + setup: func(tx backend.BatchTx) {}, + want: []*leasepb.Lease{}, + }, + { + name: "Returns data put before", + setup: func(tx backend.BatchTx) { + MustUnsafePutLease(tx, &leasepb.Lease{ + ID: -1, + TTL: 2, + }) + }, + want: []*leasepb.Lease{ + { + ID: -1, + TTL: 2, + }, + }, + }, + { + name: "Skips deleted", + setup: func(tx backend.BatchTx) { + MustUnsafePutLease(tx, &leasepb.Lease{ + ID: -1, + TTL: 2, + }) + MustUnsafePutLease(tx, &leasepb.Lease{ + ID: math.MinInt64, + TTL: 2, + }) + MustUnsafePutLease(tx, &leasepb.Lease{ + ID: math.MaxInt64, + TTL: 3, + }) + UnsafeDeleteLease(tx, &leasepb.Lease{ + ID: -1, + TTL: 2, + }) + }, + want: []*leasepb.Lease{ + { + ID: math.MaxInt64, + TTL: 3, + }, + { + ID: math.MinInt64, // bytes bigger than MaxInt64 + TTL: 2, + }, + }, + }, + } + + for _, tc := range tcs { + t.Run(tc.name, func(t *testing.T) { + be, tmpPath := betesting.NewTmpBackend(t, time.Microsecond, 10) + tx := be.BatchTx() + tx.Lock() + UnsafeCreateLeaseBucket(tx) + tc.setup(tx) + tx.Unlock() + + be.ForceCommit() + be.Close() + + be2 := backend.NewDefaultBackend(tmpPath) + defer be2.Close() + leases := MustUnsafeGetAllLeases(be2.ReadTx()) + + assert.Equal(t, tc.want, leases) + }) + } +} diff --git a/tests/framework/integration/cluster.go b/tests/framework/integration/cluster.go index 4600e092d84d..49723b50c139 100644 --- a/tests/framework/integration/cluster.go +++ b/tests/framework/integration/cluster.go @@ -170,6 +170,7 @@ type ClusterConfig struct { WatchProgressNotifyInterval time.Duration ExperimentalMaxLearners int StrictReconfigCheck bool + CorruptCheckTime time.Duration } type Cluster struct { @@ -282,6 +283,7 @@ func (c *Cluster) mustNewMember(t testutil.TB) *Member { WatchProgressNotifyInterval: c.Cfg.WatchProgressNotifyInterval, ExperimentalMaxLearners: c.Cfg.ExperimentalMaxLearners, StrictReconfigCheck: c.Cfg.StrictReconfigCheck, + CorruptCheckTime: c.Cfg.CorruptCheckTime, }) m.DiscoveryURL = c.Cfg.DiscoveryURL return m @@ -571,6 +573,7 @@ type MemberConfig struct { WatchProgressNotifyInterval time.Duration ExperimentalMaxLearners int StrictReconfigCheck bool + CorruptCheckTime time.Duration } // MustNewMember return an inited member with the given name. If peerTLS is @@ -673,6 +676,9 @@ func MustNewMember(t testutil.TB, mcfg MemberConfig) *Member { m.WatchProgressNotifyInterval = mcfg.WatchProgressNotifyInterval m.InitialCorruptCheck = true + if mcfg.CorruptCheckTime > time.Duration(0) { + m.CorruptCheckTime = mcfg.CorruptCheckTime + } m.WarningApplyDuration = embed.DefaultWarningApplyDuration m.WarningUnaryRequestDuration = embed.DefaultWarningUnaryRequestDuration m.ExperimentalMaxLearners = membership.DefaultMaxLearners diff --git a/tests/integration/v3_alarm_test.go b/tests/integration/v3_alarm_test.go index 89dc26abd00b..5b886d12654b 100644 --- a/tests/integration/v3_alarm_test.go +++ b/tests/integration/v3_alarm_test.go @@ -25,8 +25,10 @@ import ( pb "go.etcd.io/etcd/api/v3/etcdserverpb" "go.etcd.io/etcd/api/v3/v3rpc/rpctypes" "go.etcd.io/etcd/pkg/v3/traceutil" + "go.etcd.io/etcd/server/v3/lease/leasepb" "go.etcd.io/etcd/server/v3/storage/backend" "go.etcd.io/etcd/server/v3/storage/mvcc" + "go.etcd.io/etcd/server/v3/storage/schema" "go.etcd.io/etcd/tests/v3/framework/integration" "go.uber.org/zap/zaptest" ) @@ -253,3 +255,99 @@ func TestV3CorruptAlarm(t *testing.T) { } t.Fatalf("expected error %v after %s", rpctypes.ErrCorrupt, 5*time.Second) } + +func TestV3CorruptAlarmWithLeaseCorrupted(t *testing.T) { + integration.BeforeTest(t) + clus := integration.NewCluster(t, &integration.ClusterConfig{ + CorruptCheckTime: time.Second, + Size: 3, + SnapshotCount: 10, + SnapshotCatchUpEntries: 5, + }) + defer clus.Terminate(t) + + ctx, cancel := context.WithCancel(context.Background()) + defer cancel() + + lresp, err := integration.ToGRPC(clus.RandClient()).Lease.LeaseGrant(ctx, &pb.LeaseGrantRequest{ID: 1, TTL: 60}) + if err != nil { + t.Errorf("could not create lease 1 (%v)", err) + } + if lresp.ID != 1 { + t.Errorf("got id %v, wanted id %v", lresp.ID, 1) + } + + putr := &pb.PutRequest{Key: []byte("foo"), Value: []byte("bar"), Lease: lresp.ID} + // Trigger snapshot from the leader to new member + for i := 0; i < 15; i++ { + _, err := integration.ToGRPC(clus.RandClient()).KV.Put(ctx, putr) + if err != nil { + t.Errorf("#%d: couldn't put key (%v)", i, err) + } + } + + if err := clus.RemoveMember(t, clus.Client(1), uint64(clus.Members[2].ID())); err != nil { + t.Fatal(err) + } + clus.WaitMembersForLeader(t, clus.Members) + + clus.AddMember(t) + clus.WaitMembersForLeader(t, clus.Members) + // Wait for new member to catch up + integration.WaitClientV3(t, clus.Members[2].Client) + + // Corrupt member 2 by modifying backend lease bucket offline. + clus.Members[2].Stop(t) + fp := filepath.Join(clus.Members[2].DataDir, "member", "snap", "db") + bcfg := backend.DefaultBackendConfig() + bcfg.Path = fp + bcfg.Logger = zaptest.NewLogger(t) + be := backend.New(bcfg) + + olpb := leasepb.Lease{ID: int64(1), TTL: 60} + tx := be.BatchTx() + schema.UnsafeDeleteLease(tx, &olpb) + lpb := leasepb.Lease{ID: int64(2), TTL: 60} + schema.MustUnsafePutLease(tx, &lpb) + tx.Commit() + + if err := be.Close(); err != nil { + t.Fatal(err) + } + + if err := clus.Members[2].Restart(t); err != nil { + t.Fatal(err) + } + + clus.Members[1].WaitOK(t) + clus.Members[2].WaitOK(t) + + // Revoke lease should remove key except the member with corruption + _, err = integration.ToGRPC(clus.Members[0].Client).Lease.LeaseRevoke(ctx, &pb.LeaseRevokeRequest{ID: lresp.ID}) + if err != nil { + t.Fatal(err) + } + resp0, err0 := clus.Members[1].Client.KV.Get(context.TODO(), "foo") + if err0 != nil { + t.Fatal(err0) + } + resp1, err1 := clus.Members[2].Client.KV.Get(context.TODO(), "foo") + if err1 != nil { + t.Fatal(err1) + } + + if resp0.Header.Revision == resp1.Header.Revision { + t.Fatalf("matching Revision values") + } + + // Wait for CorruptCheckTime + time.Sleep(time.Second) + presp, perr := clus.Client(0).Put(context.TODO(), "abc", "aaa") + if perr != nil { + if !eqErrGRPC(perr, rpctypes.ErrCorrupt) { + t.Fatalf("expected %v, got %+v (%v)", rpctypes.ErrCorrupt, presp, perr) + } else { + return + } + } +} diff --git a/tests/integration/v3_lease_test.go b/tests/integration/v3_lease_test.go index 412dd7899e65..520c983a30ea 100644 --- a/tests/integration/v3_lease_test.go +++ b/tests/integration/v3_lease_test.go @@ -17,6 +17,7 @@ package integration import ( "context" "fmt" + "math" "testing" "time" @@ -142,6 +143,91 @@ func TestV3LeaseGrantByID(t *testing.T) { } } +// TestV3LeaseNegativeID ensures restarted member lessor can recover negative leaseID from backend. +// +// When the negative leaseID is used for lease revoke, all etcd nodes will remove the lease +// and delete associated keys to ensure kv store data consistency +// +// It ensures issue 12535 is fixed by PR 13676 +func TestV3LeaseNegativeID(t *testing.T) { + tcs := []struct { + leaseID int64 + k []byte + v []byte + }{ + { + leaseID: -1, // int64 -1 is 2^64 -1 in uint64 + k: []byte("foo"), + v: []byte("bar"), + }, + { + leaseID: math.MaxInt64, + k: []byte("bar"), + v: []byte("foo"), + }, + { + leaseID: math.MinInt64, + k: []byte("hello"), + v: []byte("world"), + }, + } + for _, tc := range tcs { + t.Run(fmt.Sprintf("test with lease ID %16x", tc.leaseID), func(t *testing.T) { + integration.BeforeTest(t) + clus := integration.NewCluster(t, &integration.ClusterConfig{Size: 3}) + defer clus.Terminate(t) + + ctx, cancel := context.WithCancel(context.Background()) + defer cancel() + cc := clus.RandClient() + lresp, err := integration.ToGRPC(cc).Lease.LeaseGrant(ctx, &pb.LeaseGrantRequest{ID: tc.leaseID, TTL: 300}) + if err != nil { + t.Errorf("could not create lease %d (%v)", tc.leaseID, err) + } + if lresp.ID != tc.leaseID { + t.Errorf("got id %v, wanted id %v", lresp.ID, tc.leaseID) + } + putr := &pb.PutRequest{Key: tc.k, Value: tc.v, Lease: tc.leaseID} + _, err = integration.ToGRPC(cc).KV.Put(ctx, putr) + if err != nil { + t.Errorf("couldn't put key (%v)", err) + } + + // wait for backend Commit + time.Sleep(100 * time.Millisecond) + // restore lessor from db file + clus.Members[2].Stop(t) + if err := clus.Members[2].Restart(t); err != nil { + t.Fatal(err) + } + + // revoke lease should remove key + integration.WaitClientV3(t, clus.Members[2].Client) + _, err = integration.ToGRPC(clus.RandClient()).Lease.LeaseRevoke(ctx, &pb.LeaseRevokeRequest{ID: tc.leaseID}) + if err != nil { + t.Errorf("could not revoke lease %d (%v)", tc.leaseID, err) + } + var revision int64 + for _, m := range clus.Members { + getr := &pb.RangeRequest{Key: tc.k} + getresp, err := integration.ToGRPC(m.Client).KV.Range(ctx, getr) + if err != nil { + t.Fatal(err) + } + if revision == 0 { + revision = getresp.Header.Revision + } + if revision != getresp.Header.Revision { + t.Errorf("expect revision %d, but got %d", revision, getresp.Header.Revision) + } + if len(getresp.Kvs) != 0 { + t.Errorf("lease removed but key remains") + } + } + }) + } +} + // TestV3LeaseExpire ensures a key is deleted once a key expires. func TestV3LeaseExpire(t *testing.T) { integration.BeforeTest(t) From 1675df37de12c236ffaa8db04e7905aaf45de084 Mon Sep 17 00:00:00 2001 From: Chao Chen Date: Sun, 13 Feb 2022 20:35:51 -0800 Subject: [PATCH 124/258] update 3.6 CHANGELOG --- CHANGELOG/CHANGELOG-3.6.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG/CHANGELOG-3.6.md b/CHANGELOG/CHANGELOG-3.6.md index 7b8d95e2fa39..77383eecc9bd 100644 --- a/CHANGELOG/CHANGELOG-3.6.md +++ b/CHANGELOG/CHANGELOG-3.6.md @@ -45,6 +45,7 @@ See [code changes](https://github.com/etcd-io/etcd/compare/v3.5.0...v3.6.0). - Fix [A client can panic etcd by passing invalid utf-8 in the client-api-version header](https://github.com/etcd-io/etcd/pull/13560) - Fix [etcd gateway doesn't format the endpoint of IPv6 address correctly](https://github.com/etcd-io/etcd/pull/13551) - Fix [A client can cause a nil dereference in etcd by passing an invalid SortTarget](https://github.com/etcd-io/etcd/pull/13555) +- Fix [Grant lease with negative ID can possibly cause db out of sync](https://github.com/etcd-io/etcd/pull/13676) ### tools/benchmark From 0df768d2b148610753ddda23fe83e89527ed76a5 Mon Sep 17 00:00:00 2001 From: AdamKorcz Date: Mon, 14 Feb 2022 10:55:57 +0000 Subject: [PATCH 125/258] server/etcdserver: fix oss-fuzz issue 42181 --- server/etcdserver/server.go | 3 +++ 1 file changed, 3 insertions(+) diff --git a/server/etcdserver/server.go b/server/etcdserver/server.go index d3a7981bcc2c..b93158a81093 100644 --- a/server/etcdserver/server.go +++ b/server/etcdserver/server.go @@ -1898,6 +1898,9 @@ func (s *EtcdServer) applyEntryNormal(e *raftpb.Entry) { id := raftReq.ID if id == 0 { + if raftReq.Header == nil { + s.lg.Panic("applyEntryNormal, could not find a header") + } id = raftReq.Header.ID } From 0fcb2a628cbacd7a3a0a3123354c7e7ce04d2be9 Mon Sep 17 00:00:00 2001 From: AdamKorcz Date: Fri, 11 Feb 2022 22:06:25 +0000 Subject: [PATCH 126/258] server/storage/wal: fix oss-fuzz issue 44433 --- server/storage/wal/version.go | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/server/storage/wal/version.go b/server/storage/wal/version.go index e4c3c250057b..07a441f6844c 100644 --- a/server/storage/wal/version.go +++ b/server/storage/wal/version.go @@ -213,7 +213,12 @@ func visitEnumNumber(enum protoreflect.EnumDescriptor, number protoreflect.EnumN if err != nil { return err } - return visitEnumValue(enum.Values().Get(int(number)), visitor) + intNumber := int(number) + fields := enum.Values() + if intNumber >= fields.Len() || intNumber < 0 { + return fmt.Errorf("could not visit EnumNumber [%d]", intNumber) + } + return visitEnumValue(fields.Get(intNumber), visitor) } func visitEnumValue(enum protoreflect.EnumValueDescriptor, visitor Visitor) error { From 3de5e221a8595cfd63e836a25a725d1aeba97dfe Mon Sep 17 00:00:00 2001 From: Marek Siarkowicz Date: Sun, 13 Feb 2022 21:20:44 +0100 Subject: [PATCH 127/258] tests: Fix cluster version and downgrade request timeout Returning nil means that raft.Trigger was not called, causing member to wait infinitly for response for response on raft request. --- server/etcdserver/apply.go | 6 +++--- server/etcdserver/version/version.go | 2 +- tests/e2e/cluster_downgrade_test.go | 13 +++++++------ 3 files changed, 11 insertions(+), 10 deletions(-) diff --git a/server/etcdserver/apply.go b/server/etcdserver/apply.go index ca7930696c28..f91f859f511d 100644 --- a/server/etcdserver/apply.go +++ b/server/etcdserver/apply.go @@ -148,15 +148,15 @@ func (a *applierV3backend) Apply(r *pb.InternalRaftRequest, shouldApplyV3 member case r.ClusterVersionSet != nil: // Implemented in 3.5.x op = "ClusterVersionSet" a.s.applyV3Internal.ClusterVersionSet(r.ClusterVersionSet, shouldApplyV3) - return nil + return ar case r.ClusterMemberAttrSet != nil: op = "ClusterMemberAttrSet" // Implemented in 3.5.x a.s.applyV3Internal.ClusterMemberAttrSet(r.ClusterMemberAttrSet, shouldApplyV3) - return nil + return ar case r.DowngradeInfoSet != nil: op = "DowngradeInfoSet" // Implemented in 3.5.x a.s.applyV3Internal.DowngradeInfoSet(r.DowngradeInfoSet, shouldApplyV3) - return nil + return ar } if !shouldApplyV3 { diff --git a/server/etcdserver/version/version.go b/server/etcdserver/version/version.go index eb9a370c166a..0a2f99a1fafd 100644 --- a/server/etcdserver/version/version.go +++ b/server/etcdserver/version/version.go @@ -64,7 +64,7 @@ func (m *Manager) DowngradeEnable(ctx context.Context, targetVersion *semver.Ver if err != nil { return err } - return m.s.DowngradeEnable(context.Background(), targetVersion) + return m.s.DowngradeEnable(ctx, targetVersion) } // DowngradeCancel cancels ongoing downgrade process. diff --git a/tests/e2e/cluster_downgrade_test.go b/tests/e2e/cluster_downgrade_test.go index 4769c4878ee5..655067ceabd9 100644 --- a/tests/e2e/cluster_downgrade_test.go +++ b/tests/e2e/cluster_downgrade_test.go @@ -46,17 +46,17 @@ func TestDowngradeUpgrade(t *testing.T) { validateVersion(t, epc, version.Versions{Cluster: currentVersionStr, Server: currentVersionStr}) downgradeEnable(t, epc, lastVersion) + expectLog(t, epc, "The server is ready to downgrade") validateVersion(t, epc, version.Versions{Cluster: lastVersionStr, Server: currentVersionStr}) stopEtcd(t, epc) epc = startEtcd(t, lastReleaseBinary, dataDirPath) - validateVersion(t, epc, version.Versions{Cluster: lastVersionStr, Server: lastVersionStr}) expectLog(t, epc, "the cluster has been downgraded") + validateVersion(t, epc, version.Versions{Cluster: lastVersionStr, Server: lastVersionStr}) stopEtcd(t, epc) epc = startEtcd(t, currentEtcdBinary, dataDirPath) - // TODO: Verify cluster version after upgrade when we fix cluster version set timeout - validateVersion(t, epc, version.Versions{Server: currentVersionStr}) + validateVersion(t, epc, version.Versions{Cluster: currentVersionStr, Server: currentVersionStr}) } func startEtcd(t *testing.T, execPath, dataDirPath string) *e2e.EtcdProcessCluster { @@ -100,11 +100,12 @@ func downgradeEnable(t *testing.T, epc *e2e.EtcdProcessCluster, ver semver.Versi } defer c.Close() ctx, cancel := context.WithTimeout(context.Background(), time.Second*5) - // TODO: Fix request always timing out even thou it succeeds - c.Downgrade(ctx, 1, ver.String()) + _, err = c.Downgrade(ctx, 1, ver.String()) + if err != nil { + t.Fatal(err) + } cancel() - expectLog(t, epc, "The server is ready to downgrade") } func stopEtcd(t *testing.T, epc *e2e.EtcdProcessCluster) { From 8c91d60a6f673dae4285d282169eff5d58fa548a Mon Sep 17 00:00:00 2001 From: Marek Siarkowicz Date: Thu, 10 Feb 2022 19:56:29 +0100 Subject: [PATCH 128/258] server: Switch to publishV3 --- server/etcdserver/server.go | 67 +---------------- server/etcdserver/server_test.go | 124 ------------------------------- 2 files changed, 1 insertion(+), 190 deletions(-) diff --git a/server/etcdserver/server.go b/server/etcdserver/server.go index b93158a81093..8d6a430cc378 100644 --- a/server/etcdserver/server.go +++ b/server/etcdserver/server.go @@ -511,9 +511,7 @@ func (s *EtcdServer) adjustTicks() { func (s *EtcdServer) Start() { s.start() s.GoAttach(func() { s.adjustTicks() }) - // TODO: Switch to publishV3 in 3.6. - // Support for cluster_member_set_attr was added in 3.5. - s.GoAttach(func() { s.publish(s.Cfg.ReqTimeout()) }) + s.GoAttach(func() { s.publishV3(s.Cfg.ReqTimeout()) }) s.GoAttach(s.purgeFile) s.GoAttach(func() { monitorFileDescriptor(s.Logger(), s.stopping) }) s.GoAttach(s.monitorClusterVersions) @@ -1698,69 +1696,6 @@ func (s *EtcdServer) publishV3(timeout time.Duration) { } } -// publish registers server information into the cluster. The information -// is the JSON representation of this server's member struct, updated with the -// static clientURLs of the server. -// The function keeps attempting to register until it succeeds, -// or its server is stopped. -// -// Use v2 store to encode member attributes, and apply through Raft -// but does not go through v2 API endpoint, which means cluster can still -// process publish requests through rafthttp -// TODO: Remove in 3.6 (start using publishV3) -func (s *EtcdServer) publish(timeout time.Duration) { - lg := s.Logger() - b, err := json.Marshal(s.attributes) - if err != nil { - lg.Panic("failed to marshal JSON", zap.Error(err)) - return - } - req := pb.Request{ - Method: "PUT", - Path: membership.MemberAttributesStorePath(s.id), - Val: string(b), - } - - for { - ctx, cancel := context.WithTimeout(s.ctx, timeout) - _, err := s.Do(ctx, req) - cancel() - switch err { - case nil: - close(s.readych) - lg.Info( - "published local member to cluster through raft", - zap.String("local-member-id", s.ID().String()), - zap.String("local-member-attributes", fmt.Sprintf("%+v", s.attributes)), - zap.String("request-path", req.Path), - zap.String("cluster-id", s.cluster.ID().String()), - zap.Duration("publish-timeout", timeout), - ) - return - - case ErrStopped: - lg.Warn( - "stopped publish because server is stopped", - zap.String("local-member-id", s.ID().String()), - zap.String("local-member-attributes", fmt.Sprintf("%+v", s.attributes)), - zap.Duration("publish-timeout", timeout), - zap.Error(err), - ) - return - - default: - lg.Warn( - "failed to publish local member to cluster through raft", - zap.String("local-member-id", s.ID().String()), - zap.String("local-member-attributes", fmt.Sprintf("%+v", s.attributes)), - zap.String("request-path", req.Path), - zap.Duration("publish-timeout", timeout), - zap.Error(err), - ) - } - } -} - func (s *EtcdServer) sendMergedSnap(merged snap.Message) { atomic.AddInt64(&s.inflightSnapshots, 1) diff --git a/server/etcdserver/server_test.go b/server/etcdserver/server_test.go index 32d368d8fc63..29b238cd023b 100644 --- a/server/etcdserver/server_test.go +++ b/server/etcdserver/server_test.go @@ -1473,130 +1473,6 @@ func TestUpdateMember(t *testing.T) { // TODO: test server could stop itself when being removed -func TestPublish(t *testing.T) { - lg := zaptest.NewLogger(t) - n := newNodeRecorder() - ch := make(chan interface{}, 1) - // simulate that request has gone through consensus - ch <- Response{} - w := wait.NewWithResponse(ch) - ctx, cancel := context.WithCancel(context.Background()) - srv := &EtcdServer{ - lgMu: new(sync.RWMutex), - lg: lg, - readych: make(chan struct{}), - Cfg: config.ServerConfig{Logger: lg, TickMs: 1, SnapshotCatchUpEntries: DefaultSnapshotCatchUpEntries}, - id: 1, - r: *newRaftNode(raftNodeConfig{lg: lg, Node: n}), - attributes: membership.Attributes{Name: "node1", ClientURLs: []string{"http://a", "http://b"}}, - cluster: &membership.RaftCluster{}, - w: w, - reqIDGen: idutil.NewGenerator(0, time.Time{}), - SyncTicker: &time.Ticker{}, - - ctx: ctx, - cancel: cancel, - } - srv.publish(time.Hour) - - action := n.Action() - if len(action) != 1 { - t.Fatalf("len(action) = %d, want 1", len(action)) - } - if action[0].Name != "Propose" { - t.Fatalf("action = %s, want Propose", action[0].Name) - } - data := action[0].Params[0].([]byte) - var r pb.Request - if err := r.Unmarshal(data); err != nil { - t.Fatalf("unmarshal request error: %v", err) - } - if r.Method != "PUT" { - t.Errorf("method = %s, want PUT", r.Method) - } - wm := membership.Member{ID: 1, Attributes: membership.Attributes{Name: "node1", ClientURLs: []string{"http://a", "http://b"}}} - if wpath := membership.MemberAttributesStorePath(wm.ID); r.Path != wpath { - t.Errorf("path = %s, want %s", r.Path, wpath) - } - var gattr membership.Attributes - if err := json.Unmarshal([]byte(r.Val), &gattr); err != nil { - t.Fatalf("unmarshal val error: %v", err) - } - if !reflect.DeepEqual(gattr, wm.Attributes) { - t.Errorf("member = %v, want %v", gattr, wm.Attributes) - } -} - -// TestPublishStopped tests that publish will be stopped if server is stopped. -func TestPublishStopped(t *testing.T) { - lg := zaptest.NewLogger(t) - ctx, cancel := context.WithCancel(context.Background()) - r := newRaftNode(raftNodeConfig{ - lg: lg, - Node: newNodeNop(), - transport: newNopTransporter(), - }) - srv := &EtcdServer{ - lgMu: new(sync.RWMutex), - lg: lg, - Cfg: config.ServerConfig{Logger: lg, TickMs: 1, SnapshotCatchUpEntries: DefaultSnapshotCatchUpEntries}, - r: *r, - cluster: &membership.RaftCluster{}, - w: mockwait.NewNop(), - done: make(chan struct{}), - stopping: make(chan struct{}), - stop: make(chan struct{}), - reqIDGen: idutil.NewGenerator(0, time.Time{}), - SyncTicker: &time.Ticker{}, - - ctx: ctx, - cancel: cancel, - } - close(srv.stopping) - srv.publish(time.Hour) -} - -// TestPublishRetry tests that publish will keep retry until success. -func TestPublishRetry(t *testing.T) { - lg := zaptest.NewLogger(t) - - ctx, cancel := context.WithCancel(context.Background()) - n := newNodeRecorderStream() - srv := &EtcdServer{ - lgMu: new(sync.RWMutex), - lg: lg, - Cfg: config.ServerConfig{Logger: lg, TickMs: 1, SnapshotCatchUpEntries: DefaultSnapshotCatchUpEntries}, - r: *newRaftNode(raftNodeConfig{lg: lg, Node: n}), - w: mockwait.NewNop(), - stopping: make(chan struct{}), - reqIDGen: idutil.NewGenerator(0, time.Time{}), - SyncTicker: &time.Ticker{}, - ctx: ctx, - cancel: cancel, - } - // expect multiple proposals from retrying - ch := make(chan struct{}) - go func() { - defer close(ch) - if action, err := n.Wait(2); err != nil { - t.Errorf("len(action) = %d, want >= 2 (%v)", len(action), err) - } - close(srv.stopping) - // drain remaining actions, if any, so publish can terminate - for { - select { - case <-ch: - return - default: - n.Action() - } - } - }() - srv.publish(10 * time.Nanosecond) - ch <- struct{}{} - <-ch -} - func TestPublishV3(t *testing.T) { n := newNodeRecorder() ch := make(chan interface{}, 1) From fad82c1b6fd508db0f250691705e45caf8192043 Mon Sep 17 00:00:00 2001 From: AdamKorcz Date: Tue, 15 Feb 2022 15:32:31 +0000 Subject: [PATCH 129/258] server/etcdserver: fix oss-fuzz issue N --- server/etcdserver/apply_v2.go | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/server/etcdserver/apply_v2.go b/server/etcdserver/apply_v2.go index 2f5913f18c68..6b292233e56a 100644 --- a/server/etcdserver/apply_v2.go +++ b/server/etcdserver/apply_v2.go @@ -20,6 +20,7 @@ import ( "path" "strconv" "time" + "unicode/utf8" "github.com/coreos/go-semver/semver" "go.etcd.io/etcd/pkg/v3/pbutil" @@ -123,6 +124,9 @@ func (s *EtcdServer) applyV2Request(r *RequestV2, shouldApplyV3 membership.Shoul alternative: func() string { return fmt.Sprintf("id:%d,method:%s,path:%s", r.ID, r.Method, r.Path) }, } defer func(start time.Time) { + if !utf8.ValidString(r.Method) { + s.lg.Panic("method is not valid utf-8") + } success := resp.Err == nil applySec.WithLabelValues(v2Version, r.Method, strconv.FormatBool(success)).Observe(time.Since(start).Seconds()) warnOfExpensiveRequest(s.Logger(), s.Cfg.WarningApplyDuration, start, stringer, nil, nil) From caeec38c2a09ec8c8e180b03844ee086630d76a7 Mon Sep 17 00:00:00 2001 From: kumakichi Date: Wed, 16 Feb 2022 17:44:46 +0800 Subject: [PATCH 130/258] fix: a little grammar issue --- server/etcdmain/etcd.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/server/etcdmain/etcd.go b/server/etcdmain/etcd.go index 190364e2781b..830ae01cb300 100644 --- a/server/etcdmain/etcd.go +++ b/server/etcdmain/etcd.go @@ -112,7 +112,7 @@ func startEtcdOrProxyV2(args []string) { which := identifyDataDirOrDie(cfg.ec.GetLogger(), cfg.ec.Dir) if which != dirEmpty { lg.Info( - "server has been already initialized", + "server has already been initialized", zap.String("data-dir", cfg.ec.Dir), zap.String("dir-type", string(which)), ) From 5649cf3f1aded900d1b516dcf91a05a8550128d6 Mon Sep 17 00:00:00 2001 From: AdamKorcz Date: Wed, 16 Feb 2022 10:31:08 +0000 Subject: [PATCH 131/258] Log and return instead of panic --- server/etcdserver/apply_v2.go | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/server/etcdserver/apply_v2.go b/server/etcdserver/apply_v2.go index 6b292233e56a..c44e66d97616 100644 --- a/server/etcdserver/apply_v2.go +++ b/server/etcdserver/apply_v2.go @@ -125,7 +125,8 @@ func (s *EtcdServer) applyV2Request(r *RequestV2, shouldApplyV3 membership.Shoul } defer func(start time.Time) { if !utf8.ValidString(r.Method) { - s.lg.Panic("method is not valid utf-8") + s.lg.Info("method is not valid utf-8") + return } success := resp.Err == nil applySec.WithLabelValues(v2Version, r.Method, strconv.FormatBool(success)).Observe(time.Since(start).Seconds()) From 5fc0092c877ad1989a7070e67df2a3e3b73364be Mon Sep 17 00:00:00 2001 From: ahrtr Date: Thu, 17 Feb 2022 07:09:32 +0800 Subject: [PATCH 132/258] trim the suffix dot from the srv.Target for etcd-client DNS lookup --- CHANGELOG/CHANGELOG-3.6.md | 1 + client/pkg/srv/srv.go | 3 ++- client/pkg/srv/srv_test.go | 4 ++-- 3 files changed, 5 insertions(+), 3 deletions(-) diff --git a/CHANGELOG/CHANGELOG-3.6.md b/CHANGELOG/CHANGELOG-3.6.md index 77383eecc9bd..ec5dc301ccf0 100644 --- a/CHANGELOG/CHANGELOG-3.6.md +++ b/CHANGELOG/CHANGELOG-3.6.md @@ -16,6 +16,7 @@ See [code changes](https://github.com/etcd-io/etcd/compare/v3.5.0...v3.6.0). - Add command to generate [shell completion](https://github.com/etcd-io/etcd/pull/13133). - When print endpoint status, [show db size in use](https://github.com/etcd-io/etcd/pull/13639) +- [Trim the suffix dot from the target](https://github.com/etcd-io/etcd/pull/13712) in SRV records returned by DNS lookup. ### etcdutl v3 diff --git a/client/pkg/srv/srv.go b/client/pkg/srv/srv.go index 948c68349091..21c377e352b5 100644 --- a/client/pkg/srv/srv.go +++ b/client/pkg/srv/srv.go @@ -106,9 +106,10 @@ func GetClient(service, domain string, serviceName string) (*SRVClients, error) return err } for _, srv := range addrs { + shortHost := strings.TrimSuffix(srv.Target, ".") urls = append(urls, &url.URL{ Scheme: scheme, - Host: net.JoinHostPort(srv.Target, fmt.Sprintf("%d", srv.Port)), + Host: net.JoinHostPort(shortHost, fmt.Sprintf("%d", srv.Port)), }) } srvs = append(srvs, addrs...) diff --git a/client/pkg/srv/srv_test.go b/client/pkg/srv/srv_test.go index c2ccf9485d91..f5c84421b9d0 100644 --- a/client/pkg/srv/srv_test.go +++ b/client/pkg/srv/srv_test.go @@ -226,8 +226,8 @@ func TestSRVDiscover(t *testing.T) { }, { []*net.SRV{ - {Target: "a.example.com", Port: 2480}, - {Target: "b.example.com", Port: 2480}, + {Target: "a.example.com.", Port: 2480}, + {Target: "b.example.com.", Port: 2480}, {Target: "c.example.com", Port: 2480}, }, []*net.SRV{}, From 6781651e0ba792f42791f39e2e1f20a6eefac5ac Mon Sep 17 00:00:00 2001 From: ahrtr Date: Mon, 21 Feb 2022 07:06:07 +0800 Subject: [PATCH 133/258] update changelog for both 3.5 and 3.6 for the PRs of trimming the suffix dot from the target in SRV record --- CHANGELOG/CHANGELOG-3.5.md | 6 ++++++ CHANGELOG/CHANGELOG-3.6.md | 4 +++- 2 files changed, 9 insertions(+), 1 deletion(-) diff --git a/CHANGELOG/CHANGELOG-3.5.md b/CHANGELOG/CHANGELOG-3.5.md index 6ae6c65d7693..0c7283a56e40 100644 --- a/CHANGELOG/CHANGELOG-3.5.md +++ b/CHANGELOG/CHANGELOG-3.5.md @@ -5,6 +5,12 @@ Previous change logs can be found at [CHANGELOG-3.4](https://github.com/etcd-io/ The minimum recommended etcd versions to run in **production** are 3.3.18+, 3.4.2+, and 3.5.2+. Refer to the [versioning policy](https://etcd.io/docs/v3.5/op-guide/versioning/) for more details. +
+## v3.5.3 (TBD) + +### package `client/pkg/v3` +- [Trim the suffix dot from the target](https://github.com/etcd-io/etcd/pull/13714) in SRV records returned by DNS lookup +
## [v3.5.2](https://github.com/etcd-io/etcd/releases/tag/v3.5.2) (2022-02-01) diff --git a/CHANGELOG/CHANGELOG-3.6.md b/CHANGELOG/CHANGELOG-3.6.md index ec5dc301ccf0..4c285a665fd6 100644 --- a/CHANGELOG/CHANGELOG-3.6.md +++ b/CHANGELOG/CHANGELOG-3.6.md @@ -16,13 +16,15 @@ See [code changes](https://github.com/etcd-io/etcd/compare/v3.5.0...v3.6.0). - Add command to generate [shell completion](https://github.com/etcd-io/etcd/pull/13133). - When print endpoint status, [show db size in use](https://github.com/etcd-io/etcd/pull/13639) -- [Trim the suffix dot from the target](https://github.com/etcd-io/etcd/pull/13712) in SRV records returned by DNS lookup. ### etcdutl v3 - Add command to generate [shell completion](https://github.com/etcd-io/etcd/pull/13142). - Add `migrate` command for downgrading/upgrading etcd data dir files. +### package `client/pkg/v3` +- [Trim the suffix dot from the target](https://github.com/etcd-io/etcd/pull/13712) in SRV records returned by DNS lookup + ### Package `server` - Package `mvcc` was moved to `storage/mvcc` From 8681888012997d46134e7478bd65fcfdda04a6fd Mon Sep 17 00:00:00 2001 From: ahrtr Date: Mon, 21 Feb 2022 14:46:58 +0800 Subject: [PATCH 134/258] fix typo, renamed ErrGPRCNotSupportedForLearner to ErrGRPCNotSupportedForLearner --- api/v3rpc/rpctypes/error.go | 4 ++-- client/v3/retry_interceptor.go | 2 +- server/etcdserver/api/v3rpc/interceptor.go | 4 ++-- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/api/v3rpc/rpctypes/error.go b/api/v3rpc/rpctypes/error.go index a00832c869dd..163e63b22c2e 100644 --- a/api/v3rpc/rpctypes/error.go +++ b/api/v3rpc/rpctypes/error.go @@ -79,7 +79,7 @@ var ( ErrGRPCTimeoutDueToConnectionLost = status.New(codes.Unavailable, "etcdserver: request timed out, possibly due to connection lost").Err() ErrGRPCUnhealthy = status.New(codes.Unavailable, "etcdserver: unhealthy cluster").Err() ErrGRPCCorrupt = status.New(codes.DataLoss, "etcdserver: corrupt cluster").Err() - ErrGPRCNotSupportedForLearner = status.New(codes.FailedPrecondition, "etcdserver: rpc not supported for learner").Err() + ErrGRPCNotSupportedForLearner = status.New(codes.FailedPrecondition, "etcdserver: rpc not supported for learner").Err() ErrGRPCBadLeaderTransferee = status.New(codes.FailedPrecondition, "etcdserver: bad leader transferee").Err() ErrGRPCWrongDowngradeVersionFormat = status.New(codes.InvalidArgument, "etcdserver: wrong downgrade target version format").Err() @@ -147,7 +147,7 @@ var ( ErrorDesc(ErrGRPCTimeoutDueToConnectionLost): ErrGRPCTimeoutDueToConnectionLost, ErrorDesc(ErrGRPCUnhealthy): ErrGRPCUnhealthy, ErrorDesc(ErrGRPCCorrupt): ErrGRPCCorrupt, - ErrorDesc(ErrGPRCNotSupportedForLearner): ErrGPRCNotSupportedForLearner, + ErrorDesc(ErrGRPCNotSupportedForLearner): ErrGRPCNotSupportedForLearner, ErrorDesc(ErrGRPCBadLeaderTransferee): ErrGRPCBadLeaderTransferee, ErrorDesc(ErrGRPCClusterVersionUnavailable): ErrGRPCClusterVersionUnavailable, diff --git a/client/v3/retry_interceptor.go b/client/v3/retry_interceptor.go index 36d24687d1bc..6cd4be047e56 100644 --- a/client/v3/retry_interceptor.go +++ b/client/v3/retry_interceptor.go @@ -324,7 +324,7 @@ func isSafeRetry(c *Client, err error, callOpts *options) bool { // customer provides mix of learners (not yet voters) and voters with an // expectation to pick voter in the next attempt. // TODO: Ideally client should be 'aware' which endpoint represents: leader/voter/learner with high probability. - if errors.Is(err, rpctypes.ErrGPRCNotSupportedForLearner) && len(c.Endpoints()) > 1 { + if errors.Is(err, rpctypes.ErrGRPCNotSupportedForLearner) && len(c.Endpoints()) > 1 { return true } diff --git a/server/etcdserver/api/v3rpc/interceptor.go b/server/etcdserver/api/v3rpc/interceptor.go index 5e2028d1af71..47f75654e216 100644 --- a/server/etcdserver/api/v3rpc/interceptor.go +++ b/server/etcdserver/api/v3rpc/interceptor.go @@ -50,7 +50,7 @@ func newUnaryInterceptor(s *etcdserver.EtcdServer) grpc.UnaryServerInterceptor { } if s.IsMemberExist(s.ID()) && s.IsLearner() && !isRPCSupportedForLearner(req) { - return nil, rpctypes.ErrGPRCNotSupportedForLearner + return nil, rpctypes.ErrGRPCNotSupportedForLearner } md, ok := metadata.FromIncomingContext(ctx) @@ -219,7 +219,7 @@ func newStreamInterceptor(s *etcdserver.EtcdServer) grpc.StreamServerInterceptor } if s.IsMemberExist(s.ID()) && s.IsLearner() && info.FullMethod != snapshotMethod { // learner does not support stream RPC except Snapshot - return rpctypes.ErrGPRCNotSupportedForLearner + return rpctypes.ErrGRPCNotSupportedForLearner } md, ok := metadata.FromIncomingContext(ss.Context()) From a0f26ff4ea991c9d1417f7d10732e52536e36e4e Mon Sep 17 00:00:00 2001 From: Marek Siarkowicz Date: Fri, 11 Feb 2022 15:04:44 +0100 Subject: [PATCH 135/258] server: Snapshot after cluster version downgrade --- server/etcdserver/apply.go | 15 ++++++++++++++- server/etcdserver/server.go | 12 ++++++++++-- tests/e2e/cluster_downgrade_test.go | 13 ------------- 3 files changed, 24 insertions(+), 16 deletions(-) diff --git a/server/etcdserver/apply.go b/server/etcdserver/apply.go index f91f859f511d..7eb53ebcc61d 100644 --- a/server/etcdserver/apply.go +++ b/server/etcdserver/apply.go @@ -936,7 +936,20 @@ func (a *applierV3backend) RoleList(r *pb.AuthRoleListRequest) (*pb.AuthRoleList } func (a *applierV3backend) ClusterVersionSet(r *membershippb.ClusterVersionSetRequest, shouldApplyV3 membership.ShouldApplyV3) { - a.s.cluster.SetVersion(semver.Must(semver.NewVersion(r.Ver)), api.UpdateCapability, shouldApplyV3) + prevVersion := a.s.Cluster().Version() + newVersion := semver.Must(semver.NewVersion(r.Ver)) + a.s.cluster.SetVersion(newVersion, api.UpdateCapability, shouldApplyV3) + // Force snapshot after cluster version downgrade. + if prevVersion != nil && newVersion.LessThan(*prevVersion) { + lg := a.s.Logger() + if lg != nil { + lg.Info("Cluster version downgrade detected, forcing snapshot", + zap.String("prev-cluster-version", prevVersion.String()), + zap.String("new-cluster-version", newVersion.String()), + ) + } + a.s.forceSnapshot = true + } } func (a *applierV3backend) ClusterMemberAttrSet(r *membershippb.ClusterMemberAttrSetRequest, shouldApplyV3 membership.ShouldApplyV3) { diff --git a/server/etcdserver/server.go b/server/etcdserver/server.go index 8d6a430cc378..d10559a4e21d 100644 --- a/server/etcdserver/server.go +++ b/server/etcdserver/server.go @@ -291,6 +291,9 @@ type EtcdServer struct { clusterVersionChanged *notify.Notifier *AccessController + // forceSnapshot can force snapshot be triggered after apply, independent of the snapshotCount. + // Should only be set within apply code path. Used to force snapshot after cluster version downgrade. + forceSnapshot bool } // NewServer creates a new EtcdServer from the supplied configuration. The @@ -1079,10 +1082,9 @@ func (s *EtcdServer) applyEntries(ep *etcdProgress, apply *apply) { } func (s *EtcdServer) triggerSnapshot(ep *etcdProgress) { - if ep.appliedi-ep.snapi <= s.Cfg.SnapshotCount { + if !s.shouldSnapshot(ep) { return } - lg := s.Logger() lg.Info( "triggering snapshot", @@ -1090,12 +1092,18 @@ func (s *EtcdServer) triggerSnapshot(ep *etcdProgress) { zap.Uint64("local-member-applied-index", ep.appliedi), zap.Uint64("local-member-snapshot-index", ep.snapi), zap.Uint64("local-member-snapshot-count", s.Cfg.SnapshotCount), + zap.Bool("snapshot-forced", s.forceSnapshot), ) + s.forceSnapshot = false s.snapshot(ep.appliedi, ep.confState) ep.snapi = ep.appliedi } +func (s *EtcdServer) shouldSnapshot(ep *etcdProgress) bool { + return (s.forceSnapshot && ep.appliedi != ep.snapi) || (ep.appliedi-ep.snapi > s.Cfg.SnapshotCount) +} + func (s *EtcdServer) hasMultipleVotingMembers() bool { return s.cluster != nil && len(s.cluster.VotingMemberIDs()) > 1 } diff --git a/tests/e2e/cluster_downgrade_test.go b/tests/e2e/cluster_downgrade_test.go index 655067ceabd9..5e2eb9ff209a 100644 --- a/tests/e2e/cluster_downgrade_test.go +++ b/tests/e2e/cluster_downgrade_test.go @@ -17,7 +17,6 @@ package e2e import ( "context" "fmt" - "strings" "testing" "time" @@ -66,8 +65,6 @@ func startEtcd(t *testing.T, execPath, dataDirPath string) *e2e.EtcdProcessClust ClusterSize: 1, InitialToken: "new", KeepDataDir: true, - // TODO: REMOVE snapshot override when snapshotting is automated after lowering storage versiont l - SnapshotCount: 5, }) if err != nil { t.Fatalf("could not start etcd process cluster (%v)", err) @@ -77,16 +74,6 @@ func startEtcd(t *testing.T, execPath, dataDirPath string) *e2e.EtcdProcessClust t.Fatalf("error closing etcd processes (%v)", errC) } }) - - prefixArgs := []string{e2e.CtlBinPath, "--endpoints", strings.Join(epc.EndpointsV3(), ",")} - t.Log("Write keys to ensure wal snapshot is created so cluster version set is snapshotted") - e2e.ExecuteWithTimeout(t, 20*time.Second, func() { - for i := 0; i < 10; i++ { - if err := e2e.SpawnWithExpect(append(prefixArgs, "put", fmt.Sprintf("%d", i), "value"), "OK"); err != nil { - t.Fatal(err) - } - } - }) return epc } From ebc86d12c05f11f960e389488681563c38f3ab7a Mon Sep 17 00:00:00 2001 From: ahrtr Date: Sat, 22 Jan 2022 08:35:36 +0800 Subject: [PATCH 136/258] support v3 discovery to bootstrap a new etcd cluster --- CHANGELOG/CHANGELOG-3.6.md | 5 + server/config/config.go | 17 +- server/embed/config.go | 47 +- server/embed/etcd.go | 14 + server/etcdmain/config.go | 15 +- server/etcdmain/etcd.go | 9 +- server/etcdmain/help.go | 26 +- .../etcdserver/api/v3discovery/discovery.go | 580 +++++++++++++ .../api/v3discovery/discovery_test.go | 783 ++++++++++++++++++ server/etcdserver/bootstrap.go | 7 +- tests/e2e/discovery_v3_test.go | 112 +++ tests/framework/e2e/cluster.go | 26 +- tests/framework/integration/cluster.go | 2 + 13 files changed, 1618 insertions(+), 25 deletions(-) create mode 100644 server/etcdserver/api/v3discovery/discovery.go create mode 100644 server/etcdserver/api/v3discovery/discovery_test.go create mode 100644 tests/e2e/discovery_v3_test.go diff --git a/CHANGELOG/CHANGELOG-3.6.md b/CHANGELOG/CHANGELOG-3.6.md index ec5dc301ccf0..798745196c0f 100644 --- a/CHANGELOG/CHANGELOG-3.6.md +++ b/CHANGELOG/CHANGELOG-3.6.md @@ -12,6 +12,10 @@ See [code changes](https://github.com/etcd-io/etcd/compare/v3.5.0...v3.6.0). - `etcd` will no longer start on data dir created by newer versions (for example etcd v3.6 will not run on v3.7+ data dir). To downgrade data dir please check out `etcdutl migrate` command. +### Deprecations + +- Deprecated [V2 discovery](https://etcd.io/docs/v3.5/dev-internal/discovery_protocol/). + ### etcdctl v3 - Add command to generate [shell completion](https://github.com/etcd-io/etcd/pull/13133). @@ -38,6 +42,7 @@ See [code changes](https://github.com/etcd-io/etcd/compare/v3.5.0...v3.6.0). - Add [`etcd --experimental-enable-lease-checkpoint-persist`](https://github.com/etcd-io/etcd/pull/13508) flag to handle upgrade from v3.5.2 clusters with this feature enabled. - Add [`etcdctl make-mirror --rev`](https://github.com/etcd-io/etcd/pull/13519) flag to support incremental mirror. - Add [`etcd --experimental-wait-cluster-ready-timeout`](https://github.com/etcd-io/etcd/pull/13525) flag to wait for cluster to be ready before serving client requests. +- Add [v3 discovery](https://github.com/etcd-io/etcd/pull/13635) to bootstrap a new etcd cluster. - Fix [non mutating requests pass through quotaKVServer when NOSPACE](https://github.com/etcd-io/etcd/pull/13435) - Fix [exclude the same alarm type activated by multiple peers](https://github.com/etcd-io/etcd/pull/13467). - Fix [Provide a better liveness probe for when etcd runs as a Kubernetes pod](https://github.com/etcd-io/etcd/pull/13399) diff --git a/server/config/config.go b/server/config/config.go index 15cb526f469c..8f901444211d 100644 --- a/server/config/config.go +++ b/server/config/config.go @@ -25,6 +25,7 @@ import ( "go.etcd.io/etcd/client/pkg/v3/transport" "go.etcd.io/etcd/client/pkg/v3/types" "go.etcd.io/etcd/pkg/v3/netutil" + "go.etcd.io/etcd/server/v3/etcdserver/api/v3discovery" "go.etcd.io/etcd/server/v3/storage/datadir" "go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc" @@ -34,12 +35,16 @@ import ( // ServerConfig holds the configuration of etcd as taken from the command line or discovery. type ServerConfig struct { - Name string - DiscoveryURL string - DiscoveryProxy string - ClientURLs types.URLs - PeerURLs types.URLs - DataDir string + Name string + + EnableV2Discovery bool + DiscoveryURL string + DiscoveryProxy string + DiscoveryCfg v3discovery.DiscoveryConfig + + ClientURLs types.URLs + PeerURLs types.URLs + DataDir string // DedicatedWALDir config will make the etcd to write the WAL to the WALDir // rather than the dataDir/member/wal. DedicatedWALDir string diff --git a/server/embed/config.go b/server/embed/config.go index c63a9f971285..778d2b1cbc26 100644 --- a/server/embed/config.go +++ b/server/embed/config.go @@ -15,6 +15,7 @@ package embed import ( + "errors" "fmt" "net" "net/http" @@ -36,6 +37,7 @@ import ( "go.etcd.io/etcd/server/v3/etcdserver" "go.etcd.io/etcd/server/v3/etcdserver/api/membership" "go.etcd.io/etcd/server/v3/etcdserver/api/v3compactor" + "go.etcd.io/etcd/server/v3/etcdserver/api/v3discovery" bolt "go.etcd.io/bbolt" "go.uber.org/multierr" @@ -62,6 +64,11 @@ const ( DefaultDowngradeCheckTime = 5 * time.Second DefaultWaitClusterReadyTimeout = 5 * time.Second + DefaultDiscoveryDialTimeout = 2 * time.Second + DefaultDiscoveryRequestTimeOut = 5 * time.Second + DefaultDiscoveryKeepAliveTime = 2 * time.Second + DefaultDiscoveryKeepAliveTimeOut = 6 * time.Second + DefaultListenPeerURLs = "http://localhost:2380" DefaultListenClientURLs = "http://localhost:2379" @@ -88,6 +95,8 @@ const ( // It's enabled by default. DefaultStrictReconfigCheck = true + DefaultEnableV2Discovery = true + // maxElectionMs specifies the maximum value of election timeout. // More details are listed in ../Documentation/tuning.md#time-parameters. maxElectionMs = 50000 @@ -213,11 +222,15 @@ type Config struct { // Note that cipher suites are prioritized in the given order. CipherSuites []string `json:"cipher-suites"` - ClusterState string `json:"initial-cluster-state"` - DNSCluster string `json:"discovery-srv"` - DNSClusterServiceName string `json:"discovery-srv-name"` - Dproxy string `json:"discovery-proxy"` - Durl string `json:"discovery"` + ClusterState string `json:"initial-cluster-state"` + DNSCluster string `json:"discovery-srv"` + DNSClusterServiceName string `json:"discovery-srv-name"` + Dproxy string `json:"discovery-proxy"` + + EnableV2Discovery bool `json:"enable-v2-discovery"` + Durl string `json:"discovery"` + DiscoveryCfg v3discovery.DiscoveryConfig `json:"discovery-config"` + InitialCluster string `json:"initial-cluster"` InitialClusterToken string `json:"initial-cluster-token"` StrictReconfigCheck bool `json:"strict-reconfig-check"` @@ -504,6 +517,14 @@ func NewConfig() *Config { ExperimentalMaxLearners: membership.DefaultMaxLearners, V2Deprecation: config.V2_DEPR_DEFAULT, + + EnableV2Discovery: DefaultEnableV2Discovery, + DiscoveryCfg: v3discovery.DiscoveryConfig{ + DialTimeout: DefaultDiscoveryDialTimeout, + RequestTimeOut: DefaultDiscoveryRequestTimeOut, + KeepAliveTime: DefaultDiscoveryKeepAliveTime, + KeepAliveTimeout: DefaultDiscoveryKeepAliveTimeOut, + }, } cfg.InitialCluster = cfg.InitialClusterFromName(cfg.Name) return cfg @@ -667,6 +688,22 @@ func (cfg *Config) Validate() error { return ErrConflictBootstrapFlags } + // Check if both v2 discovery and v3 discovery flags are passed. + v2discoveryFlagsExist := cfg.Dproxy != "" + v3discoveryFlagsExist := cfg.DiscoveryCfg.CertFile != "" || + cfg.DiscoveryCfg.KeyFile != "" || + cfg.DiscoveryCfg.TrustedCAFile != "" || + cfg.DiscoveryCfg.User != "" || + cfg.DiscoveryCfg.Password != "" + if cfg.EnableV2Discovery && v3discoveryFlagsExist { + return errors.New("v2 discovery is enabled, but some v3 discovery " + + "settings (discovery-cert, discovery-key, discovery-cacert, " + + "discovery-user, discovery-password) are set") + } + if !cfg.EnableV2Discovery && v2discoveryFlagsExist { + return errors.New("v3 discovery is enabled, but --discovery-proxy is set") + } + if cfg.TickMs == 0 { return fmt.Errorf("--heartbeat-interval must be >0 (set to %dms)", cfg.TickMs) } diff --git a/server/embed/etcd.go b/server/embed/etcd.go index 825c56869ad0..46069b63900d 100644 --- a/server/embed/etcd.go +++ b/server/embed/etcd.go @@ -175,8 +175,10 @@ func StartEtcd(inCfg *Config) (e *Etcd, err error) { MaxWALFiles: cfg.MaxWalFiles, InitialPeerURLsMap: urlsmap, InitialClusterToken: token, + EnableV2Discovery: cfg.EnableV2Discovery, DiscoveryURL: cfg.Durl, DiscoveryProxy: cfg.Dproxy, + DiscoveryCfg: cfg.DiscoveryCfg, NewCluster: cfg.IsNewCluster(), PeerTLSInfo: cfg.PeerTLSInfo, TickMs: cfg.TickMs, @@ -345,6 +347,18 @@ func print(lg *zap.Logger, ec Config, sc config.ServerConfig, memberInitialized zap.String("auto-compaction-interval", sc.AutoCompactionRetention.String()), zap.String("discovery-url", sc.DiscoveryURL), zap.String("discovery-proxy", sc.DiscoveryProxy), + + zap.String("discovery-dial-timeout", sc.DiscoveryCfg.DialTimeout.String()), + zap.String("discovery-request-timeout", sc.DiscoveryCfg.RequestTimeOut.String()), + zap.String("discovery-keepalive-time", sc.DiscoveryCfg.KeepAliveTime.String()), + zap.String("discovery-keepalive-timeout", sc.DiscoveryCfg.KeepAliveTimeout.String()), + zap.Bool("discovery-insecure-transport", sc.DiscoveryCfg.InsecureTransport), + zap.Bool("discovery-insecure-skip-tls-verify", sc.DiscoveryCfg.InsecureSkipVerify), + zap.String("discovery-cert", sc.DiscoveryCfg.CertFile), + zap.String("discovery-key", sc.DiscoveryCfg.KeyFile), + zap.String("discovery-cacert", sc.DiscoveryCfg.TrustedCAFile), + zap.String("discovery-user", sc.DiscoveryCfg.User), + zap.String("downgrade-check-interval", sc.DowngradeCheckTime.String()), zap.Int("max-learners", sc.ExperimentalMaxLearners), ) diff --git a/server/etcdmain/config.go b/server/etcdmain/config.go index 00439c9e6d46..b837b9d42550 100644 --- a/server/etcdmain/config.go +++ b/server/etcdmain/config.go @@ -185,10 +185,23 @@ func newConfig() *config { "advertise-client-urls", "List of this member's client URLs to advertise to the public.", ) + fs.BoolVar(&cfg.ec.EnableV2Discovery, "enable-v2-discovery", cfg.ec.EnableV2Discovery, "Enable to bootstrap the cluster using v2 discovery. Will be deprecated in v3.7, and be decommissioned in v3.8.") fs.StringVar(&cfg.ec.Durl, "discovery", cfg.ec.Durl, "Discovery URL used to bootstrap the cluster.") fs.Var(cfg.cf.fallback, "discovery-fallback", fmt.Sprintf("Valid values include %q", cfg.cf.fallback.Valids())) - fs.StringVar(&cfg.ec.Dproxy, "discovery-proxy", cfg.ec.Dproxy, "HTTP proxy to use for traffic to discovery service.") + fs.DurationVar(&cfg.ec.DiscoveryCfg.DialTimeout, "discovery-dial-timeout", cfg.ec.DiscoveryCfg.DialTimeout, "V3 discovery: dial timeout for client connections.") + fs.DurationVar(&cfg.ec.DiscoveryCfg.RequestTimeOut, "discovery-request-timeout", cfg.ec.DiscoveryCfg.RequestTimeOut, "V3 discovery: timeout for discovery requests (excluding dial timeout).") + fs.DurationVar(&cfg.ec.DiscoveryCfg.KeepAliveTime, "discovery-keepalive-time", cfg.ec.DiscoveryCfg.KeepAliveTime, "V3 discovery: keepalive time for client connections.") + fs.DurationVar(&cfg.ec.DiscoveryCfg.KeepAliveTimeout, "discovery-keepalive-timeout", cfg.ec.DiscoveryCfg.KeepAliveTimeout, "V3 discovery: keepalive timeout for client connections.") + fs.BoolVar(&cfg.ec.DiscoveryCfg.InsecureTransport, "discovery-insecure-transport", true, "V3 discovery: disable transport security for client connections.") + fs.BoolVar(&cfg.ec.DiscoveryCfg.InsecureSkipVerify, "discovery-insecure-skip-tls-verify", false, "V3 discovery: skip server certificate verification (CAUTION: this option should be enabled only for testing purposes).") + fs.StringVar(&cfg.ec.DiscoveryCfg.CertFile, "discovery-cert", "", "V3 discovery: identify secure client using this TLS certificate file.") + fs.StringVar(&cfg.ec.DiscoveryCfg.KeyFile, "discovery-key", "", "V3 discovery: identify secure client using this TLS key file.") + fs.StringVar(&cfg.ec.DiscoveryCfg.TrustedCAFile, "discovery-cacert", "", "V3 discovery: verify certificates of TLS-enabled secure servers using this CA bundle.") + fs.StringVar(&cfg.ec.DiscoveryCfg.User, "discovery-user", "", "V3 discovery: username[:password] for authentication (prompt if password is not supplied).") + fs.StringVar(&cfg.ec.DiscoveryCfg.Password, "discovery-password", "", "V3 discovery: password for authentication (if this option is used, --user option shouldn't include password).") + + fs.StringVar(&cfg.ec.Dproxy, "discovery-proxy", cfg.ec.Dproxy, "HTTP proxy to use for traffic to discovery service. Will be deprecated in v3.7, and be decommissioned in v3.8.") fs.StringVar(&cfg.ec.DNSCluster, "discovery-srv", cfg.ec.DNSCluster, "DNS domain used to bootstrap initial cluster.") fs.StringVar(&cfg.ec.DNSClusterServiceName, "discovery-srv-name", cfg.ec.DNSClusterServiceName, "Service name to query when using DNS discovery.") fs.StringVar(&cfg.ec.InitialCluster, "initial-cluster", cfg.ec.InitialCluster, "Initial cluster configuration for bootstrapping.") diff --git a/server/etcdmain/etcd.go b/server/etcdmain/etcd.go index 190364e2781b..5d78e72029e6 100644 --- a/server/etcdmain/etcd.go +++ b/server/etcdmain/etcd.go @@ -17,6 +17,7 @@ package etcdmain import ( "encoding/json" "fmt" + "net/http" "os" "path/filepath" @@ -34,6 +35,7 @@ import ( "go.etcd.io/etcd/server/v3/etcdserver" "go.etcd.io/etcd/server/v3/etcdserver/api/etcdhttp" "go.etcd.io/etcd/server/v3/etcdserver/api/v2discovery" + "go.etcd.io/etcd/server/v3/etcdserver/api/v3discovery" "go.etcd.io/etcd/server/v3/proxy/httpproxy" "go.uber.org/zap" @@ -318,7 +320,12 @@ func startProxy(cfg *config) error { if cfg.ec.Durl != "" { var s string - s, err = v2discovery.GetCluster(lg, cfg.ec.Durl, cfg.ec.Dproxy) + if cfg.ec.EnableV2Discovery { + lg.Warn("V2 discovery is deprecated!") + s, err = v2discovery.GetCluster(lg, cfg.ec.Durl, cfg.ec.Dproxy) + } else { + s, err = v3discovery.GetCluster(lg, cfg.ec.Durl, &cfg.ec.DiscoveryCfg) + } if err != nil { return err } diff --git a/server/etcdmain/help.go b/server/etcdmain/help.go index fdd62cb094d6..84b683b0dc7e 100644 --- a/server/etcdmain/help.go +++ b/server/etcdmain/help.go @@ -104,13 +104,37 @@ Clustering: --advertise-client-urls 'http://localhost:2379' List of this member's client URLs to advertise to the public. The client URLs advertised should be accessible to machines that talk to etcd cluster. etcd client libraries parse these URLs to connect to the cluster. + --enable-v2-discovery 'true' + Enable to bootstrap the cluster using v2 discovery. Will be deprecated in v3.7, and be decommissioned in v3.8. --discovery '' Discovery URL used to bootstrap the cluster. + --discovery-dial-timeout '2s' + V3 discovery: dial timeout for client connections. + --discovery-request-timeout '5s' + V3 discovery: timeout for discovery requests (excluding dial timeout). + --discovery-keepalive-time '2s' + V3 discovery: keepalive time for client connections. + --discovery-keepalive-timeout '6s' + V3 discovery: keepalive timeout for client connections. + --discovery-insecure-transport 'true' + V3 discovery: disable transport security for client connections. + --discovery-insecure-skip-tls-verify 'false' + V3 discovery: skip server certificate verification (CAUTION: this option should be enabled only for testing purposes). + --discovery-cert '' + V3 discovery: identify secure client using this TLS certificate file. + --discovery-key '' + V3 discovery: identify secure client using this TLS key file. + --discovery-cacert '' + V3 discovery: verify certificates of TLS-enabled secure servers using this CA bundle. + --discovery-user '' + V3 discovery: username[:password] for authentication (prompt if password is not supplied). + --discovery-password '' + V3 discovery: password for authentication (if this option is used, --user option shouldn't include password). --discovery-fallback 'proxy' Expected behavior ('exit' or 'proxy') when discovery services fails. "proxy" supports v2 API only. --discovery-proxy '' - HTTP proxy to use for traffic to discovery service. + HTTP proxy to use for traffic to discovery service. Will be deprecated in v3.7, and be decommissioned in v3.8. --discovery-srv '' DNS srv domain used to bootstrap the cluster. --discovery-srv-name '' diff --git a/server/etcdserver/api/v3discovery/discovery.go b/server/etcdserver/api/v3discovery/discovery.go new file mode 100644 index 000000000000..7fcaadf3aeb3 --- /dev/null +++ b/server/etcdserver/api/v3discovery/discovery.go @@ -0,0 +1,580 @@ +// Copyright 2022 The etcd Authors +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +// Package v3discovery provides an implementation of the cluster discovery that +// is used by etcd with v3 client. +package v3discovery + +import ( + "context" + "crypto/tls" + "errors" + + "math" + "net/url" + "path" + "sort" + "strconv" + "strings" + "time" + + "go.etcd.io/etcd/client/pkg/v3/transport" + "go.etcd.io/etcd/client/pkg/v3/types" + "go.etcd.io/etcd/client/v3" + + "github.com/jonboulle/clockwork" + "go.uber.org/zap" +) + +const ( + discoveryPrefix = "/_etcd/registry" +) + +var ( + ErrInvalidURL = errors.New("discovery: invalid peer URL") + ErrBadSizeKey = errors.New("discovery: size key is bad") + ErrSizeNotFound = errors.New("discovery: size key not found") + ErrFullCluster = errors.New("discovery: cluster is full") + ErrTooManyRetries = errors.New("discovery: too many retries") +) + +var ( + // Number of retries discovery will attempt before giving up and error out. + nRetries = uint(math.MaxUint32) + maxExponentialRetries = uint(8) +) + +type DiscoveryConfig struct { + Url string `json:"discovery"` + + DialTimeout time.Duration `json:"discovery-dial-timeout"` + RequestTimeOut time.Duration `json:"discovery-request-timeout"` + KeepAliveTime time.Duration `json:"discovery-keepalive-time"` + KeepAliveTimeout time.Duration `json:"discovery-keepalive-timeout"` + + InsecureTransport bool `json:"discovery-insecure-transport"` + InsecureSkipVerify bool `json:"discovery-insecure-skip-tls-verify"` + CertFile string `json:"discovery-cert"` + KeyFile string `json:"discovery-key"` + TrustedCAFile string `json:"discovery-cacert"` + + User string `json:"discovery-user"` + Password string `json:"discovery-password"` +} + +type memberInfo struct { + // peerRegKey is the key used by the member when registering in the + // discovery service. + // Format: "/_etcd/registry//members/". + peerRegKey string + // peerURLsMap format: "peerName=peerURLs", i.e., "member1=http://127.0.0.1:2380". + peerURLsMap string + // createRev is the member's CreateRevision in the etcd cluster backing + // the discovery service. + createRev int64 +} + +type clusterInfo struct { + clusterToken string + members []memberInfo +} + +// key prefix for each cluster: "/_etcd/registry/". +func geClusterKeyPrefix(cluster string) string { + return path.Join(discoveryPrefix, cluster) +} + +// key format for cluster size: "/_etcd/registry//_config/size". +func geClusterSizeKey(cluster string) string { + return path.Join(geClusterKeyPrefix(cluster), "_config/size") +} + +// key prefix for each member: "/_etcd/registry//members". +func getMemberKeyPrefix(clusterToken string) string { + return path.Join(geClusterKeyPrefix(clusterToken), "members") +} + +// key format for each member: "/_etcd/registry//members/". +func getMemberKey(cluster, memberId string) string { + return path.Join(getMemberKeyPrefix(cluster), memberId) +} + +// GetCluster will connect to the discovery service at the given url and +// retrieve a string describing the cluster +func GetCluster(lg *zap.Logger, dUrl string, cfg *DiscoveryConfig) (cs string, rerr error) { + d, err := newDiscovery(lg, dUrl, cfg, 0) + if err != nil { + return "", err + } + + defer d.close() + defer func() { + if rerr != nil { + d.lg.Error( + "discovery failed to get cluster", + zap.String("cluster", cs), + zap.Error(rerr), + ) + } else { + d.lg.Info( + "discovery got cluster successfully", + zap.String("cluster", cs), + ) + } + }() + + return d.getCluster() +} + +// JoinCluster will connect to the discovery service at the given url, and +// register the server represented by the given id and config to the cluster. +// The parameter `config` is supposed to be in the format "memberName=peerURLs", +// such as "member1=http://127.0.0.1:2380". +// +// The final returned string has the same format as "--initial-cluster", such as +// "infra1=http://127.0.0.1:12380,infra2=http://127.0.0.1:22380,infra3=http://127.0.0.1:32380". +func JoinCluster(lg *zap.Logger, durl string, cfg *DiscoveryConfig, id types.ID, config string) (cs string, rerr error) { + d, err := newDiscovery(lg, durl, cfg, id) + if err != nil { + return "", err + } + + defer d.close() + defer func() { + if rerr != nil { + d.lg.Error( + "discovery failed to join cluster", + zap.String("cluster", cs), + zap.Error(rerr), + ) + } else { + d.lg.Info( + "discovery joined cluster successfully", + zap.String("cluster", cs), + ) + } + }() + + return d.joinCluster(config) +} + +type discovery struct { + lg *zap.Logger + clusterToken string + memberId types.ID + c *clientv3.Client + retries uint + durl string + + cfg *DiscoveryConfig + + clock clockwork.Clock +} + +func newDiscovery(lg *zap.Logger, durl string, dcfg *DiscoveryConfig, id types.ID) (*discovery, error) { + if lg == nil { + lg = zap.NewNop() + } + u, err := url.Parse(durl) + if err != nil { + return nil, err + } + token := u.Path + u.Path = "" + + lg = lg.With(zap.String("discovery-url", durl)) + cfg, err := newClientCfg(dcfg, u.String(), lg) + if err != nil { + return nil, err + } + + c, err := clientv3.New(*cfg) + if err != nil { + return nil, err + } + return &discovery{ + lg: lg, + clusterToken: token, + memberId: id, + c: c, + durl: u.String(), + cfg: dcfg, + clock: clockwork.NewRealClock(), + }, nil +} + +// The following function follows the same logic as etcdctl, refer to +// https://github.com/etcd-io/etcd/blob/f9a8c49c695b098d66a07948666664ea10d01a82/etcdctl/ctlv3/command/global.go#L191-L250 +func newClientCfg(dcfg *DiscoveryConfig, dUrl string, lg *zap.Logger) (*clientv3.Config, error) { + var cfgtls *transport.TLSInfo + + if dcfg.CertFile != "" || dcfg.KeyFile != "" || dcfg.TrustedCAFile != "" { + cfgtls = &transport.TLSInfo{ + CertFile: dcfg.CertFile, + KeyFile: dcfg.KeyFile, + TrustedCAFile: dcfg.TrustedCAFile, + Logger: lg, + } + } + + cfg := &clientv3.Config{ + Endpoints: []string{dUrl}, + DialTimeout: dcfg.DialTimeout, + DialKeepAliveTime: dcfg.KeepAliveTime, + DialKeepAliveTimeout: dcfg.KeepAliveTimeout, + Username: dcfg.User, + Password: dcfg.Password, + } + + if cfgtls != nil { + if clientTLS, err := cfgtls.ClientConfig(); err == nil { + cfg.TLS = clientTLS + } else { + return nil, err + } + } + + // If key/cert is not given but user wants secure connection, we + // should still setup an empty tls configuration for gRPC to setup + // secure connection. + if cfg.TLS == nil && !dcfg.InsecureTransport { + cfg.TLS = &tls.Config{} + } + + // If the user wants to skip TLS verification then we should set + // the InsecureSkipVerify flag in tls configuration. + if cfg.TLS != nil && dcfg.InsecureSkipVerify { + cfg.TLS.InsecureSkipVerify = true + } + + return cfg, nil +} + +func (d *discovery) getCluster() (string, error) { + cls, clusterSize, rev, err := d.checkCluster() + if err != nil { + if err == ErrFullCluster { + return cls.getInitClusterStr(clusterSize) + } + return "", err + } + + for cls.Len() < clusterSize { + d.waitPeers(cls, clusterSize, rev) + } + + return cls.getInitClusterStr(clusterSize) +} + +func (d *discovery) joinCluster(config string) (string, error) { + _, _, _, err := d.checkCluster() + if err != nil { + return "", err + } + + if err := d.registerSelf(config); err != nil { + return "", err + } + + cls, clusterSize, rev, err := d.checkCluster() + if err != nil { + return "", err + } + + for cls.Len() < clusterSize { + d.waitPeers(cls, clusterSize, rev) + } + + return cls.getInitClusterStr(clusterSize) +} + +func (d *discovery) getClusterSize() (int, error) { + configKey := geClusterSizeKey(d.clusterToken) + ctx, cancel := context.WithTimeout(context.Background(), d.cfg.RequestTimeOut) + defer cancel() + + resp, err := d.c.Get(ctx, configKey) + if err != nil { + d.lg.Warn( + "failed to get cluster size from discovery service", + zap.String("clusterSizeKey", configKey), + zap.Error(err), + ) + return 0, err + } + + if len(resp.Kvs) == 0 { + return 0, ErrSizeNotFound + } + + clusterSize, err := strconv.ParseInt(string(resp.Kvs[0].Value), 10, 0) + if err != nil || clusterSize <= 0 { + return 0, ErrBadSizeKey + } + + return int(clusterSize), nil +} + +func (d *discovery) getClusterMembers() (*clusterInfo, int64, error) { + membersKeyPrefix := getMemberKeyPrefix(d.clusterToken) + ctx, cancel := context.WithTimeout(context.Background(), d.cfg.RequestTimeOut) + defer cancel() + + resp, err := d.c.Get(ctx, membersKeyPrefix, clientv3.WithPrefix()) + if err != nil { + d.lg.Warn( + "failed to get cluster members from discovery service", + zap.String("membersKeyPrefix", membersKeyPrefix), + zap.Error(err), + ) + return nil, 0, err + } + + cls := &clusterInfo{clusterToken: d.clusterToken} + for _, kv := range resp.Kvs { + mKey := strings.TrimSpace(string(kv.Key)) + mValue := strings.TrimSpace(string(kv.Value)) + + if err := cls.add(mKey, mValue, kv.CreateRevision); err != nil { + d.lg.Warn( + err.Error(), + zap.String("memberKey", mKey), + zap.String("memberInfo", mValue), + ) + } else { + d.lg.Info( + "found peer from discovery service", + zap.String("memberKey", mKey), + zap.String("memberInfo", mValue), + ) + } + } + + return cls, resp.Header.Revision, nil +} + +func (d *discovery) checkClusterRetry() (*clusterInfo, int, int64, error) { + if d.retries < nRetries { + d.logAndBackoffForRetry("cluster status check") + return d.checkCluster() + } + return nil, 0, 0, ErrTooManyRetries +} + +func (d *discovery) checkCluster() (*clusterInfo, int, int64, error) { + clusterSize, err := d.getClusterSize() + if err != nil { + if err == ErrSizeNotFound || err == ErrBadSizeKey { + return nil, 0, 0, err + } + + return d.checkClusterRetry() + } + + cls, rev, err := d.getClusterMembers() + if err != nil { + return d.checkClusterRetry() + } + d.retries = 0 + + // find self position + memberSelfId := getMemberKey(d.clusterToken, d.memberId.String()) + idx := 0 + for _, m := range cls.members { + if m.peerRegKey == memberSelfId { + break + } + if idx >= clusterSize-1 { + return cls, clusterSize, rev, ErrFullCluster + } + idx++ + } + return cls, clusterSize, rev, nil +} + +func (d *discovery) registerSelfRetry(contents string) error { + if d.retries < nRetries { + d.logAndBackoffForRetry("register member itself") + return d.registerSelf(contents) + } + return ErrTooManyRetries +} + +func (d *discovery) registerSelf(contents string) error { + ctx, cancel := context.WithTimeout(context.Background(), d.cfg.RequestTimeOut) + memberKey := getMemberKey(d.clusterToken, d.memberId.String()) + _, err := d.c.Put(ctx, memberKey, contents) + cancel() + + if err != nil { + d.lg.Warn( + "failed to register members itself to the discovery service", + zap.String("memberKey", memberKey), + zap.Error(err), + ) + return d.registerSelfRetry(contents) + } + d.retries = 0 + + d.lg.Info( + "register member itself successfully", + zap.String("memberKey", memberKey), + zap.String("memberInfo", contents), + ) + + return nil +} + +func (d *discovery) waitPeers(cls *clusterInfo, clusterSize int, rev int64) { + // watch from the next revision + membersKeyPrefix := getMemberKeyPrefix(d.clusterToken) + w := d.c.Watch(context.Background(), membersKeyPrefix, clientv3.WithPrefix(), clientv3.WithRev(rev+1)) + + d.lg.Info( + "waiting for peers from discovery service", + zap.Int("clusterSize", clusterSize), + zap.Int("found-peers", cls.Len()), + ) + + // waiting for peers until all needed peers are returned + for wresp := range w { + for _, ev := range wresp.Events { + mKey := strings.TrimSpace(string(ev.Kv.Key)) + mValue := strings.TrimSpace(string(ev.Kv.Value)) + + if err := cls.add(mKey, mValue, ev.Kv.CreateRevision); err != nil { + d.lg.Warn( + err.Error(), + zap.String("memberKey", mKey), + zap.String("memberInfo", mValue), + ) + } else { + d.lg.Info( + "found peer from discovery service", + zap.String("memberKey", mKey), + zap.String("memberInfo", mValue), + ) + } + } + + if cls.Len() >= clusterSize { + break + } + } + + d.lg.Info( + "found all needed peers from discovery service", + zap.Int("clusterSize", clusterSize), + zap.Int("found-peers", cls.Len()), + ) +} + +func (d *discovery) logAndBackoffForRetry(step string) { + d.retries++ + // logAndBackoffForRetry stops exponential backoff when the retries are + // more than maxExpoentialRetries and is set to a constant backoff afterward. + retries := d.retries + if retries > maxExponentialRetries { + retries = maxExponentialRetries + } + retryTimeInSecond := time.Duration(0x1< clusterSize { + peerURLs = peerURLs[:clusterSize] + } + + us := strings.Join(peerURLs, ",") + _, err := types.NewURLsMap(us) + if err != nil { + return us, ErrInvalidURL + } + + return us, nil +} + +func (cls *clusterInfo) getPeerURLs() []string { + var peerURLs []string + for _, peer := range cls.members { + peerURLs = append(peerURLs, peer.peerURLsMap) + } + return peerURLs +} diff --git a/server/etcdserver/api/v3discovery/discovery_test.go b/server/etcdserver/api/v3discovery/discovery_test.go new file mode 100644 index 000000000000..529bb3984623 --- /dev/null +++ b/server/etcdserver/api/v3discovery/discovery_test.go @@ -0,0 +1,783 @@ +package v3discovery + +import ( + "context" + "errors" + "fmt" + "testing" + + "go.etcd.io/etcd/api/v3/etcdserverpb" + "go.etcd.io/etcd/api/v3/mvccpb" + "go.etcd.io/etcd/client/pkg/v3/types" + "go.etcd.io/etcd/client/v3" + + "github.com/jonboulle/clockwork" + "go.uber.org/zap" +) + +// fakeKVForClusterSize is used to test getClusterSize. +type fakeKVForClusterSize struct { + *fakeBaseKV + clusterSizeStr string +} + +// We only need to overwrite the method `Get`. +func (fkv *fakeKVForClusterSize) Get(ctx context.Context, key string, opts ...clientv3.OpOption) (*clientv3.GetResponse, error) { + if fkv.clusterSizeStr == "" { + // cluster size isn't configured in this case. + return &clientv3.GetResponse{}, nil + } + + return &clientv3.GetResponse{ + Kvs: []*mvccpb.KeyValue{ + { + Value: []byte(fkv.clusterSizeStr), + }, + }, + }, nil +} + +func TestGetClusterSize(t *testing.T) { + cases := []struct { + name string + clusterSizeStr string + expectedErr error + expectedSize int + }{ + { + name: "cluster size not defined", + clusterSizeStr: "", + expectedErr: ErrSizeNotFound, + }, + { + name: "invalid cluster size", + clusterSizeStr: "invalidSize", + expectedErr: ErrBadSizeKey, + }, + { + name: "valid cluster size", + clusterSizeStr: "3", + expectedErr: nil, + expectedSize: 3, + }, + } + + lg, err := zap.NewProduction() + if err != nil { + t.Errorf("Failed to create a logger, error: %v", err) + } + for _, tc := range cases { + t.Run(tc.name, func(t *testing.T) { + d := &discovery{ + lg: lg, + c: &clientv3.Client{ + KV: &fakeKVForClusterSize{ + fakeBaseKV: &fakeBaseKV{}, + clusterSizeStr: tc.clusterSizeStr, + }, + }, + cfg: &DiscoveryConfig{}, + clusterToken: "fakeToken", + } + + if cs, err := d.getClusterSize(); err != tc.expectedErr { + t.Errorf("Unexpected error, expected: %v got: %v", tc.expectedErr, err) + } else { + if err == nil && cs != tc.expectedSize { + t.Errorf("Unexpected cluster size, expected: %d got: %d", tc.expectedSize, cs) + } + } + }) + } +} + +// fakeKVForClusterMembers is used to test getClusterMembers. +type fakeKVForClusterMembers struct { + *fakeBaseKV + members []memberInfo +} + +// We only need to overwrite method `Get`. +func (fkv *fakeKVForClusterMembers) Get(ctx context.Context, key string, opts ...clientv3.OpOption) (*clientv3.GetResponse, error) { + kvs := memberInfoToKeyValues(fkv.members) + + return &clientv3.GetResponse{ + Header: &etcdserverpb.ResponseHeader{ + Revision: 10, + }, + Kvs: kvs, + }, nil +} + +func memberInfoToKeyValues(members []memberInfo) []*mvccpb.KeyValue { + kvs := make([]*mvccpb.KeyValue, 0) + for _, mi := range members { + kvs = append(kvs, &mvccpb.KeyValue{ + Key: []byte(mi.peerRegKey), + Value: []byte(mi.peerURLsMap), + CreateRevision: mi.createRev, + }) + } + + return kvs +} + +func TestGetClusterMembers(t *testing.T) { + actualMemberInfo := []memberInfo{ + { + peerRegKey: "/_etcd/registry/fakeToken/members/" + types.ID(101).String(), + peerURLsMap: "infra1=http://192.168.0.100:2380", + createRev: 8, + }, + { + // invalid peer registry key + peerRegKey: "/invalidPrefix/fakeToken/members/" + types.ID(102).String(), + peerURLsMap: "infra2=http://192.168.0.102:2380", + createRev: 6, + }, + { + peerRegKey: "/_etcd/registry/fakeToken/members/" + types.ID(102).String(), + peerURLsMap: "infra2=http://192.168.0.102:2380", + createRev: 6, + }, + { + // invalid peer info format + peerRegKey: "/_etcd/registry/fakeToken/members/" + types.ID(102).String(), + peerURLsMap: "http://192.168.0.102:2380", + createRev: 6, + }, + { + peerRegKey: "/_etcd/registry/fakeToken/members/" + types.ID(103).String(), + peerURLsMap: "infra3=http://192.168.0.103:2380", + createRev: 7, + }, + { + // duplicate peer + peerRegKey: "/_etcd/registry/fakeToken/members/" + types.ID(101).String(), + peerURLsMap: "infra1=http://192.168.0.100:2380", + createRev: 2, + }, + } + + // sort by CreateRevision + expectedMemberInfo := []memberInfo{ + { + peerRegKey: "/_etcd/registry/fakeToken/members/" + types.ID(102).String(), + peerURLsMap: "infra2=http://192.168.0.102:2380", + createRev: 6, + }, + { + peerRegKey: "/_etcd/registry/fakeToken/members/" + types.ID(103).String(), + peerURLsMap: "infra3=http://192.168.0.103:2380", + createRev: 7, + }, + { + peerRegKey: "/_etcd/registry/fakeToken/members/" + types.ID(101).String(), + peerURLsMap: "infra1=http://192.168.0.100:2380", + createRev: 8, + }, + } + + lg, err := zap.NewProduction() + if err != nil { + t.Errorf("Failed to create a logger, error: %v", err) + } + + d := &discovery{ + lg: lg, + c: &clientv3.Client{ + KV: &fakeKVForClusterMembers{ + fakeBaseKV: &fakeBaseKV{}, + members: actualMemberInfo, + }, + }, + cfg: &DiscoveryConfig{}, + clusterToken: "fakeToken", + } + + clsInfo, _, err := d.getClusterMembers() + if err != nil { + t.Errorf("Failed to get cluster members, error: %v", err) + } + + if clsInfo.Len() != len(expectedMemberInfo) { + t.Errorf("unexpected member count, expected: %d, got: %d", len(expectedMemberInfo), clsInfo.Len()) + } + + for i, m := range clsInfo.members { + if m != expectedMemberInfo[i] { + t.Errorf("unexpected member[%d], expected: %v, got: %v", i, expectedMemberInfo[i], m) + } + } +} + +// fakeKVForCheckCluster is used to test checkCluster. +type fakeKVForCheckCluster struct { + *fakeBaseKV + t *testing.T + token string + clusterSizeStr string + members []memberInfo + getSizeRetries int + getMembersRetries int +} + +// We only need to overwrite method `Get`. +func (fkv *fakeKVForCheckCluster) Get(ctx context.Context, key string, opts ...clientv3.OpOption) (*clientv3.GetResponse, error) { + clusterSizeKey := fmt.Sprintf("/_etcd/registry/%s/_config/size", fkv.token) + clusterMembersKey := fmt.Sprintf("/_etcd/registry/%s/members", fkv.token) + + if key == clusterSizeKey { + if fkv.getSizeRetries > 0 { + fkv.getSizeRetries-- + // discovery client should retry on error. + return nil, errors.New("get cluster size failed") + } + return &clientv3.GetResponse{ + Kvs: []*mvccpb.KeyValue{ + { + Value: []byte(fkv.clusterSizeStr), + }, + }, + }, nil + + } else if key == clusterMembersKey { + if fkv.getMembersRetries > 0 { + fkv.getMembersRetries-- + // discovery client should retry on error. + return nil, errors.New("get cluster members failed") + } + kvs := memberInfoToKeyValues(fkv.members) + + return &clientv3.GetResponse{ + Header: &etcdserverpb.ResponseHeader{ + Revision: 10, + }, + Kvs: kvs, + }, nil + } else { + fkv.t.Errorf("unexpected key: %s", key) + return nil, fmt.Errorf("unexpected key: %s", key) + } +} + +func TestCheckCluster(t *testing.T) { + actualMemberInfo := []memberInfo{ + { + peerRegKey: "/_etcd/registry/fakeToken/members/" + types.ID(101).String(), + peerURLsMap: "infra1=http://192.168.0.100:2380", + createRev: 8, + }, + { + // invalid peer registry key + peerRegKey: "/invalidPrefix/fakeToken/members/" + types.ID(102).String(), + peerURLsMap: "infra2=http://192.168.0.102:2380", + createRev: 6, + }, + { + peerRegKey: "/_etcd/registry/fakeToken/members/" + types.ID(102).String(), + peerURLsMap: "infra2=http://192.168.0.102:2380", + createRev: 6, + }, + { + // invalid peer info format + peerRegKey: "/_etcd/registry/fakeToken/members/" + types.ID(102).String(), + peerURLsMap: "http://192.168.0.102:2380", + createRev: 6, + }, + { + peerRegKey: "/_etcd/registry/fakeToken/members/" + types.ID(103).String(), + peerURLsMap: "infra3=http://192.168.0.103:2380", + createRev: 7, + }, + { + // duplicate peer + peerRegKey: "/_etcd/registry/fakeToken/members/" + types.ID(101).String(), + peerURLsMap: "infra1=http://192.168.0.100:2380", + createRev: 2, + }, + } + + // sort by CreateRevision + expectedMemberInfo := []memberInfo{ + { + peerRegKey: "/_etcd/registry/fakeToken/members/" + types.ID(102).String(), + peerURLsMap: "infra2=http://192.168.0.102:2380", + createRev: 6, + }, + { + peerRegKey: "/_etcd/registry/fakeToken/members/" + types.ID(103).String(), + peerURLsMap: "infra3=http://192.168.0.103:2380", + createRev: 7, + }, + { + peerRegKey: "/_etcd/registry/fakeToken/members/" + types.ID(101).String(), + peerURLsMap: "infra1=http://192.168.0.100:2380", + createRev: 8, + }, + } + + cases := []struct { + name string + memberId types.ID + getSizeRetries int + getMembersRetries int + expectedError error + }{ + { + name: "no retries", + memberId: 101, + getSizeRetries: 0, + getMembersRetries: 0, + expectedError: nil, + }, + { + name: "2 retries for getClusterSize", + memberId: 102, + getSizeRetries: 2, + getMembersRetries: 0, + expectedError: nil, + }, + { + name: "2 retries for getClusterMembers", + memberId: 103, + getSizeRetries: 0, + getMembersRetries: 2, + expectedError: nil, + }, + { + name: "error due to cluster full", + memberId: 104, + getSizeRetries: 0, + getMembersRetries: 0, + expectedError: ErrFullCluster, + }, + } + + for _, tc := range cases { + t.Run(tc.name, func(t *testing.T) { + lg, err := zap.NewProduction() + if err != nil { + t.Errorf("Failed to create a logger, error: %v", err) + } + + fkv := &fakeKVForCheckCluster{ + fakeBaseKV: &fakeBaseKV{}, + t: t, + token: "fakeToken", + clusterSizeStr: "3", + members: actualMemberInfo, + getSizeRetries: tc.getSizeRetries, + getMembersRetries: tc.getMembersRetries, + } + + d := &discovery{ + lg: lg, + c: &clientv3.Client{ + KV: fkv, + }, + cfg: &DiscoveryConfig{}, + clusterToken: "fakeToken", + memberId: tc.memberId, + clock: clockwork.NewRealClock(), + } + + clsInfo, _, _, err := d.checkCluster() + if err != tc.expectedError { + t.Errorf("Unexpected error, expected: %v, got: %v", tc.expectedError, err) + } + + if err == nil { + if fkv.getSizeRetries != 0 || fkv.getMembersRetries != 0 { + t.Errorf("Discovery client did not retry checking cluster on error, remaining etries: (%d, %d)", fkv.getSizeRetries, fkv.getMembersRetries) + } + + if clsInfo.Len() != len(expectedMemberInfo) { + t.Errorf("Unexpected member count, expected: %d, got: %d", len(expectedMemberInfo), clsInfo.Len()) + } + + for mIdx, m := range clsInfo.members { + if m != expectedMemberInfo[mIdx] { + t.Errorf("Unexpected member[%d], expected: %v, got: %v", mIdx, expectedMemberInfo[mIdx], m) + } + } + } + }) + } +} + +// fakeKVForRegisterSelf is used to test registerSelf. +type fakeKVForRegisterSelf struct { + *fakeBaseKV + t *testing.T + expectedRegKey string + expectedRegValue string + retries int +} + +// We only need to overwrite method `Put`. +func (fkv *fakeKVForRegisterSelf) Put(ctx context.Context, key string, val string, opts ...clientv3.OpOption) (*clientv3.PutResponse, error) { + if key != fkv.expectedRegKey { + fkv.t.Errorf("unexpected register key, expected: %s, got: %s", fkv.expectedRegKey, key) + } + + if val != fkv.expectedRegValue { + fkv.t.Errorf("unexpected register value, expected: %s, got: %s", fkv.expectedRegValue, val) + } + + if fkv.retries > 0 { + fkv.retries-- + // discovery client should retry on error. + return nil, errors.New("register self failed") + } + + return nil, nil +} + +func TestRegisterSelf(t *testing.T) { + cases := []struct { + name string + token string + memberId types.ID + expectedRegKey string + expectedRegValue string + retries int // when retries > 0, then return an error on Put request. + }{ + { + name: "no retry with token1", + token: "token1", + memberId: 101, + expectedRegKey: "/_etcd/registry/token1/members/" + types.ID(101).String(), + expectedRegValue: "infra=http://127.0.0.1:2380", + retries: 0, + }, + { + name: "no retry with token2", + token: "token2", + memberId: 102, + expectedRegKey: "/_etcd/registry/token2/members/" + types.ID(102).String(), + expectedRegValue: "infra=http://127.0.0.1:2380", + retries: 0, + }, + { + name: "2 retries", + token: "token3", + memberId: 103, + expectedRegKey: "/_etcd/registry/token3/members/" + types.ID(103).String(), + expectedRegValue: "infra=http://127.0.0.1:2380", + retries: 2, + }, + } + + lg, err := zap.NewProduction() + if err != nil { + t.Errorf("Failed to create a logger, error: %v", err) + } + + for _, tc := range cases { + t.Run(tc.name, func(t *testing.T) { + fkv := &fakeKVForRegisterSelf{ + fakeBaseKV: &fakeBaseKV{}, + t: t, + expectedRegKey: tc.expectedRegKey, + expectedRegValue: tc.expectedRegValue, + retries: tc.retries, + } + + d := &discovery{ + lg: lg, + clusterToken: tc.token, + memberId: tc.memberId, + cfg: &DiscoveryConfig{}, + c: &clientv3.Client{ + KV: fkv, + }, + clock: clockwork.NewRealClock(), + } + + if err := d.registerSelf(tc.expectedRegValue); err != nil { + t.Errorf("Error occuring on register member self: %v", err) + } + + if fkv.retries != 0 { + t.Errorf("Discovery client did not retry registering itself on error, remaining retries: %d", fkv.retries) + } + }) + } +} + +// fakeWatcherForWaitPeers is used to test waitPeers. +type fakeWatcherForWaitPeers struct { + *fakeBaseWatcher + t *testing.T + token string + members []memberInfo +} + +// We only need to overwrite method `Watch`. +func (fw *fakeWatcherForWaitPeers) Watch(ctx context.Context, key string, opts ...clientv3.OpOption) clientv3.WatchChan { + expectedWatchKey := fmt.Sprintf("/_etcd/registry/%s/members", fw.token) + if key != expectedWatchKey { + fw.t.Errorf("unexpected watch key, expected: %s, got: %s", expectedWatchKey, key) + } + + ch := make(chan clientv3.WatchResponse, 1) + go func() { + for _, mi := range fw.members { + ch <- clientv3.WatchResponse{ + Events: []*clientv3.Event{ + { + Kv: &mvccpb.KeyValue{ + Key: []byte(mi.peerRegKey), + Value: []byte(mi.peerURLsMap), + CreateRevision: mi.createRev, + }, + }, + }, + } + } + close(ch) + }() + return ch +} + +func TestWaitPeers(t *testing.T) { + actualMemberInfo := []memberInfo{ + { + peerRegKey: "/_etcd/registry/fakeToken/members/" + types.ID(101).String(), + peerURLsMap: "infra1=http://192.168.0.100:2380", + createRev: 8, + }, + { + // invalid peer registry key + peerRegKey: "/invalidPrefix/fakeToken/members/" + types.ID(102).String(), + peerURLsMap: "infra2=http://192.168.0.102:2380", + createRev: 6, + }, + { + peerRegKey: "/_etcd/registry/fakeToken/members/" + types.ID(102).String(), + peerURLsMap: "infra2=http://192.168.0.102:2380", + createRev: 6, + }, + { + // invalid peer info format + peerRegKey: "/_etcd/registry/fakeToken/members/" + types.ID(102).String(), + peerURLsMap: "http://192.168.0.102:2380", + createRev: 6, + }, + { + peerRegKey: "/_etcd/registry/fakeToken/members/" + types.ID(103).String(), + peerURLsMap: "infra3=http://192.168.0.103:2380", + createRev: 7, + }, + { + // duplicate peer + peerRegKey: "/_etcd/registry/fakeToken/members/" + types.ID(101).String(), + peerURLsMap: "infra1=http://192.168.0.100:2380", + createRev: 2, + }, + } + + // sort by CreateRevision + expectedMemberInfo := []memberInfo{ + { + peerRegKey: "/_etcd/registry/fakeToken/members/" + types.ID(102).String(), + peerURLsMap: "infra2=http://192.168.0.102:2380", + createRev: 6, + }, + { + peerRegKey: "/_etcd/registry/fakeToken/members/" + types.ID(103).String(), + peerURLsMap: "infra3=http://192.168.0.103:2380", + createRev: 7, + }, + { + peerRegKey: "/_etcd/registry/fakeToken/members/" + types.ID(101).String(), + peerURLsMap: "infra1=http://192.168.0.100:2380", + createRev: 8, + }, + } + + lg, err := zap.NewProduction() + if err != nil { + t.Errorf("Failed to create a logger, error: %v", err) + } + + d := &discovery{ + lg: lg, + c: &clientv3.Client{ + KV: &fakeBaseKV{}, + Watcher: &fakeWatcherForWaitPeers{ + fakeBaseWatcher: &fakeBaseWatcher{}, + t: t, + token: "fakeToken", + members: actualMemberInfo, + }, + }, + cfg: &DiscoveryConfig{}, + clusterToken: "fakeToken", + } + + cls := clusterInfo{ + clusterToken: "fakeToken", + } + + d.waitPeers(&cls, 3, 0) + + if cls.Len() != len(expectedMemberInfo) { + t.Errorf("unexpected member number returned by watch, expected: %d, got: %d", len(expectedMemberInfo), cls.Len()) + } + + for i, m := range cls.members { + if m != expectedMemberInfo[i] { + t.Errorf("unexpected member[%d] returned by watch, expected: %v, got: %v", i, expectedMemberInfo[i], m) + } + } +} + +func TestGetInitClusterStr(t *testing.T) { + cases := []struct { + name string + members []memberInfo + clusterSize int + expectedResult string + expectedError error + }{ + { + name: "1 member", + members: []memberInfo{ + { + peerURLsMap: "infra2=http://192.168.0.102:2380", + }, + }, + clusterSize: 1, + expectedResult: "infra2=http://192.168.0.102:2380", + expectedError: nil, + }, + { + name: "2 members", + members: []memberInfo{ + { + peerURLsMap: "infra2=http://192.168.0.102:2380", + }, + { + peerURLsMap: "infra3=http://192.168.0.103:2380", + }, + }, + clusterSize: 2, + expectedResult: "infra2=http://192.168.0.102:2380,infra3=http://192.168.0.103:2380", + expectedError: nil, + }, + { + name: "3 members", + members: []memberInfo{ + { + peerURLsMap: "infra2=http://192.168.0.102:2380", + }, + { + peerURLsMap: "infra3=http://192.168.0.103:2380", + }, + { + peerURLsMap: "infra1=http://192.168.0.100:2380", + }, + }, + clusterSize: 3, + expectedResult: "infra2=http://192.168.0.102:2380,infra3=http://192.168.0.103:2380,infra1=http://192.168.0.100:2380", + expectedError: nil, + }, + { + name: "should ignore redundant member", + members: []memberInfo{ + { + peerURLsMap: "infra2=http://192.168.0.102:2380", + }, + { + peerURLsMap: "infra3=http://192.168.0.103:2380", + }, + { + peerURLsMap: "infra1=http://192.168.0.100:2380", + }, + { + peerURLsMap: "infra4=http://192.168.0.104:2380", + }, + }, + clusterSize: 3, + expectedResult: "infra2=http://192.168.0.102:2380,infra3=http://192.168.0.103:2380,infra1=http://192.168.0.100:2380", + expectedError: nil, + }, + { + name: "invalid_peer_url", + members: []memberInfo{ + { + peerURLsMap: "infra2=http://192.168.0.102:2380", + }, + { + peerURLsMap: "infra3=http://192.168.0.103", //not host:port + }, + }, + clusterSize: 2, + expectedResult: "infra2=http://192.168.0.102:2380,infra3=http://192.168.0.103:2380", + expectedError: ErrInvalidURL, + }, + } + + for _, tc := range cases { + t.Run(tc.name, func(t *testing.T) { + clsInfo := &clusterInfo{ + members: tc.members, + } + + retStr, err := clsInfo.getInitClusterStr(tc.clusterSize) + if err != tc.expectedError { + t.Errorf("Unexpected error, expected: %v, got: %v", tc.expectedError, err) + } + + if err == nil { + if retStr != tc.expectedResult { + t.Errorf("Unexpected result, expected: %s, got: %s", tc.expectedResult, retStr) + } + } + }) + } +} + +// fakeBaseKV is the base struct implementing the interface `clientv3.KV`. +type fakeBaseKV struct{} + +func (fkv *fakeBaseKV) Put(ctx context.Context, key string, val string, opts ...clientv3.OpOption) (*clientv3.PutResponse, error) { + return nil, nil +} + +func (fkv *fakeBaseKV) Get(ctx context.Context, key string, opts ...clientv3.OpOption) (*clientv3.GetResponse, error) { + return nil, nil +} + +func (fkv *fakeBaseKV) Delete(ctx context.Context, key string, opts ...clientv3.OpOption) (*clientv3.DeleteResponse, error) { + return nil, nil +} + +func (fkv *fakeBaseKV) Compact(ctx context.Context, rev int64, opts ...clientv3.CompactOption) (*clientv3.CompactResponse, error) { + return nil, nil +} + +func (fkv *fakeBaseKV) Do(ctx context.Context, op clientv3.Op) (clientv3.OpResponse, error) { + return clientv3.OpResponse{}, nil +} + +func (fkv *fakeBaseKV) Txn(ctx context.Context) clientv3.Txn { + return nil +} + +// fakeBaseWatcher is the base struct implementing the interface `clientv3.Watcher`. +type fakeBaseWatcher struct{} + +func (fw *fakeBaseWatcher) Watch(ctx context.Context, key string, opts ...clientv3.OpOption) clientv3.WatchChan { + return nil +} + +func (fw *fakeBaseWatcher) RequestProgress(ctx context.Context) error { + return nil +} + +func (fw *fakeBaseWatcher) Close() error { + return nil +} diff --git a/server/etcdserver/bootstrap.go b/server/etcdserver/bootstrap.go index 0c1297afee50..76b888ec3e76 100644 --- a/server/etcdserver/bootstrap.go +++ b/server/etcdserver/bootstrap.go @@ -40,6 +40,7 @@ import ( "go.etcd.io/etcd/server/v3/etcdserver/api/snap" "go.etcd.io/etcd/server/v3/etcdserver/api/v2discovery" "go.etcd.io/etcd/server/v3/etcdserver/api/v2store" + "go.etcd.io/etcd/server/v3/etcdserver/api/v3discovery" "go.etcd.io/etcd/server/v3/etcdserver/cindex" serverstorage "go.etcd.io/etcd/server/v3/storage" "go.etcd.io/etcd/server/v3/storage/backend" @@ -328,7 +329,11 @@ func bootstrapNewClusterNoWAL(cfg config.ServerConfig, prt http.RoundTripper) (* } if cfg.ShouldDiscover() { var str string - str, err = v2discovery.JoinCluster(cfg.Logger, cfg.DiscoveryURL, cfg.DiscoveryProxy, m.ID, cfg.InitialPeerURLsMap.String()) + if cfg.EnableV2Discovery { + str, err = v2discovery.JoinCluster(cfg.Logger, cfg.DiscoveryURL, cfg.DiscoveryProxy, m.ID, cfg.InitialPeerURLsMap.String()) + } else { + str, err = v3discovery.JoinCluster(cfg.Logger, cfg.DiscoveryURL, &cfg.DiscoveryCfg, m.ID, cfg.InitialPeerURLsMap.String()) + } if err != nil { return nil, &DiscoveryError{Op: "join", Err: err} } diff --git a/tests/e2e/discovery_v3_test.go b/tests/e2e/discovery_v3_test.go new file mode 100644 index 000000000000..efc50656340f --- /dev/null +++ b/tests/e2e/discovery_v3_test.go @@ -0,0 +1,112 @@ +// Copyright 2022 The etcd Authors +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package e2e + +import ( + "fmt" + "strconv" + "strings" + "testing" + + "go.etcd.io/etcd/tests/v3/framework/e2e" +) + +func TestClusterOf1UsingV3Discovery(t *testing.T) { + testClusterUsingV3Discovery(t, 1, e2e.ClientNonTLS, false) +} +func TestClusterOf3UsingV3Discovery(t *testing.T) { + testClusterUsingV3Discovery(t, 3, e2e.ClientTLS, true) +} +func TestTLSClusterOf3UsingV3Discovery(t *testing.T) { + testClusterUsingV3Discovery(t, 5, e2e.ClientTLS, false) +} + +func testClusterUsingV3Discovery(t *testing.T, clusterSize int, clientTlsType e2e.ClientConnType, isClientAutoTls bool) { + e2e.BeforeTest(t) + + // step 1: start the discovery service + ds, err := e2e.NewEtcdProcessCluster(t, &e2e.EtcdProcessClusterConfig{ + InitialToken: "new", + BasePort: 2000, + ClusterSize: 1, + ClientTLS: clientTlsType, + IsClientAutoTLS: isClientAutoTls, + }) + if err != nil { + t.Fatalf("could not start discovery etcd cluster (%v)", err) + } + defer ds.Close() + + // step 2: configure the cluster size + clusterToken := "8A591FAB-1D72-41FA-BDF2-A27162FDA1E0" + configSizeKey := fmt.Sprintf("/_etcd/registry/%s/_config/size", clusterToken) + configSizeValStr := strconv.Itoa(clusterSize) + if err := ctlV3Put(ctlCtx{epc: ds}, configSizeKey, configSizeValStr, ""); err != nil { + t.Errorf("failed to configure cluster size to discovery serivce, error: %v", err) + } + + // step 3: start the etcd cluster + epc, err := bootstrapEtcdClusterUsingV3Discovery(t, ds.EndpointsV3()[0], clusterToken, clusterSize, clientTlsType, isClientAutoTls) + if err != nil { + t.Fatalf("could not start etcd process cluster (%v)", err) + } + defer epc.Close() + + // step 4: sanity test on the etcd cluster + etcdctl := []string{e2e.CtlBinPath, "--endpoints", strings.Join(epc.EndpointsV3(), ",")} + if err := e2e.SpawnWithExpect(append(etcdctl, "put", "key", "value"), "OK"); err != nil { + t.Fatal(err) + } + if err := e2e.SpawnWithExpect(append(etcdctl, "get", "key"), "value"); err != nil { + t.Fatal(err) + } +} + +func bootstrapEtcdClusterUsingV3Discovery(t *testing.T, durl string, clusterToken string, clusterSize int, clientTlsType e2e.ClientConnType, isClientAutoTls bool) (*e2e.EtcdProcessCluster, error) { + // cluster configuration + cfg := &e2e.EtcdProcessClusterConfig{ + BasePort: 3000, + ClusterSize: clusterSize, + IsPeerTLS: true, + IsPeerAutoTLS: true, + Discovery: fmt.Sprintf("%s/%s", durl, clusterToken), + } + + // initialize the cluster + epc, err := e2e.InitEtcdProcessCluster(t, cfg) + if err != nil { + return epc, err + } + + // populate discovery related security configuration + for _, ep := range epc.Procs { + epCfg := ep.Config() + epCfg.Args = append(epCfg.Args, "--enable-v2-discovery=false") + + if clientTlsType == e2e.ClientTLS { + if isClientAutoTls { + epCfg.Args = append(epCfg.Args, "--discovery-insecure-transport=false") + epCfg.Args = append(epCfg.Args, "--discovery-insecure-skip-tls-verify=true") + } else { + epCfg.Args = append(epCfg.Args, "--discovery-cacert="+e2e.CaPath) + epCfg.Args = append(epCfg.Args, "--discovery-cert="+e2e.CertPath) + epCfg.Args = append(epCfg.Args, "--discovery-key="+e2e.PrivateKeyPath) + } + } + } + + // start the cluster + return e2e.StartEtcdProcessCluster(epc, cfg) +} diff --git a/tests/framework/e2e/cluster.go b/tests/framework/e2e/cluster.go index 242ebe0d6a7d..e1de1951047f 100644 --- a/tests/framework/e2e/cluster.go +++ b/tests/framework/e2e/cluster.go @@ -181,16 +181,7 @@ func NewEtcdProcessCluster(t testing.TB, cfg *EtcdProcessClusterConfig) (*EtcdPr return nil, err } - if cfg.RollingStart { - if err := epc.RollingStart(); err != nil { - return nil, fmt.Errorf("Cannot rolling-start: %v", err) - } - } else { - if err := epc.Start(); err != nil { - return nil, fmt.Errorf("Cannot start: %v", err) - } - } - return epc, nil + return StartEtcdProcessCluster(epc, cfg) } // InitEtcdProcessCluster initializes a new cluster based on the given config. @@ -218,6 +209,21 @@ func InitEtcdProcessCluster(t testing.TB, cfg *EtcdProcessClusterConfig) (*EtcdP return epc, nil } +// StartEtcdProcessCluster launches a new cluster from etcd processes. +func StartEtcdProcessCluster(epc *EtcdProcessCluster, cfg *EtcdProcessClusterConfig) (*EtcdProcessCluster, error) { + if cfg.RollingStart { + if err := epc.RollingStart(); err != nil { + return nil, fmt.Errorf("cannot rolling-start: %v", err) + } + } else { + if err := epc.Start(); err != nil { + return nil, fmt.Errorf("cannot start: %v", err) + } + } + + return epc, nil +} + func (cfg *EtcdProcessClusterConfig) ClientScheme() string { if cfg.ClientTLS == ClientTLS { return "https" diff --git a/tests/framework/integration/cluster.go b/tests/framework/integration/cluster.go index 49723b50c139..c1aa0f275089 100644 --- a/tests/framework/integration/cluster.go +++ b/tests/framework/integration/cluster.go @@ -588,6 +588,8 @@ func MustNewMember(t testutil.TB, mcfg MemberConfig) *Member { peerScheme := SchemeFromTLSInfo(mcfg.PeerTLS) clientScheme := SchemeFromTLSInfo(mcfg.ClientTLS) + m.EnableV2Discovery = embed.DefaultEnableV2Discovery + pln := newLocalListener(t) m.PeerListeners = []net.Listener{pln} m.PeerURLs, err = types.NewURLs([]string{peerScheme + "://" + pln.Addr().String()}) From 8e71ebf0711268663f82a1c3f3c1c6e5bc230b97 Mon Sep 17 00:00:00 2001 From: "leoyang.yl" Date: Sat, 18 Sep 2021 17:08:37 +0800 Subject: [PATCH 137/258] Add downgrade commands --- etcdctl/README.md | 41 +++++++ etcdctl/ctlv3/command/downgrade_command.go | 135 +++++++++++++++++++++ etcdctl/ctlv3/command/printer.go | 10 ++ etcdctl/ctlv3/command/printer_simple.go | 10 ++ etcdctl/ctlv3/ctl.go | 1 + 5 files changed, 197 insertions(+) create mode 100644 etcdctl/ctlv3/command/downgrade_command.go diff --git a/etcdctl/README.md b/etcdctl/README.md index 8dc9d2a13d79..4ef3b62b8aea 100644 --- a/etcdctl/README.md +++ b/etcdctl/README.md @@ -1083,6 +1083,47 @@ echo ${transferee_id} # Leadership transferred from 45ddc0e800e20b93 to c89feb932daef420 ``` +### DOWNGRADE \ + +Downgrade provides commands to downgrade cluster version + +### DOWNGRADE VALIDATE \ + +DOWNGRADE VALIDATE validate downgrade capability before starting downgrade + +#### Example + +```bash +./etcdctl downgrade validate 3.5.0 +Downgrade validate success, cluster version 3.6.0 + +./etcdctl downgrade validate 3.4.0 +Error: etcdserver: invalid downgrade target version + +``` + +### DOWNGRADE ENABLE \ + +DOWNGRADE ENABLE starts a downgrade action to cluster + +#### Example + +```bash +./etcdctl downgrade enable 3.5.0 +Downgrade enable success, cluster version 3.6.0 +``` + +### DOWNGRADE CANCEL \ + +DOWNGRADE CANCEL cancels the ongoing downgrade action to cluster + +#### Example + +```bash +./etcdctl downgrade cancel +Downgrade cancel success, cluster version 3.6.0 +``` + ## Concurrency commands ### LOCK [options] \ [command arg1 arg2 ...] diff --git a/etcdctl/ctlv3/command/downgrade_command.go b/etcdctl/ctlv3/command/downgrade_command.go new file mode 100644 index 000000000000..55e95859c784 --- /dev/null +++ b/etcdctl/ctlv3/command/downgrade_command.go @@ -0,0 +1,135 @@ +// Copyright 2016 The etcd Authors +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package command + +import ( + "errors" + "github.com/spf13/cobra" + pb "go.etcd.io/etcd/api/v3/etcdserverpb" + "go.etcd.io/etcd/pkg/v3/cobrautl" +) + +// NewDowngradeCommand returns the cobra command for "downgrade". +func NewDowngradeCommand() *cobra.Command { + dc := &cobra.Command{ + Use: "downgrade ", + Short: "Downgrade related commands", + } + + dc.AddCommand(NewDowngradeValidateCommand()) + dc.AddCommand(NewDowngradeEnableCommand()) + dc.AddCommand(NewDowngradeCancelCommand()) + + return dc +} + +// NewDowngradeValidateCommand returns the cobra command for "downgrade validate". +func NewDowngradeValidateCommand() *cobra.Command { + cc := &cobra.Command{ + Use: "validate ", + Short: "Validate downgrade capability before starting downgrade", + + Run: downgradeValidateCommandFunc, + } + return cc +} + +// NewDowngradeEnableCommand returns the cobra command for "downgrade enable". +func NewDowngradeEnableCommand() *cobra.Command { + cc := &cobra.Command{ + Use: "enable ", + Short: "Start a downgrade action to cluster", + + Run: downgradeEnableCommandFunc, + } + return cc +} + +// NewDowngradeCancelCommand returns the cobra command for "downgrade cancel". +func NewDowngradeCancelCommand() *cobra.Command { + cc := &cobra.Command{ + Use: "cancel", + Short: "Cancel the ongoing downgrade action to cluster", + + Run: downgradeCancelCommandFunc, + } + return cc +} + +// downgradeValidateCommandFunc executes the "downgrade validate" command. +func downgradeValidateCommandFunc(cmd *cobra.Command, args []string) { + if len(args) < 1 { + cobrautl.ExitWithError(cobrautl.ExitBadArgs, errors.New("TARGET_VERSION not provided")) + } + if len(args) > 1 { + cobrautl.ExitWithError(cobrautl.ExitBadArgs, errors.New("too many arguments")) + } + targetVersion := args[0] + + if len(targetVersion) == 0 { + cobrautl.ExitWithError(cobrautl.ExitBadArgs, errors.New("member peer urls not provided")) + } + + ctx, cancel := commandCtx(cmd) + cli := mustClientFromCmd(cmd) + + resp, err := cli.Downgrade(ctx, int32(pb.DowngradeRequest_VALIDATE), targetVersion) + cancel() + if err != nil { + cobrautl.ExitWithError(cobrautl.ExitError, err) + } + + display.DowngradeValidate(*resp) +} + +// downgradeEnableCommandFunc executes the "downgrade enable" command. +func downgradeEnableCommandFunc(cmd *cobra.Command, args []string) { + if len(args) < 1 { + cobrautl.ExitWithError(cobrautl.ExitBadArgs, errors.New("TARGET_VERSION not provided")) + } + if len(args) > 1 { + cobrautl.ExitWithError(cobrautl.ExitBadArgs, errors.New("too many arguments")) + } + targetVersion := args[0] + + if len(targetVersion) == 0 { + cobrautl.ExitWithError(cobrautl.ExitBadArgs, errors.New("member peer urls not provided")) + } + + ctx, cancel := commandCtx(cmd) + cli := mustClientFromCmd(cmd) + + resp, err := cli.Downgrade(ctx, int32(pb.DowngradeRequest_ENABLE), targetVersion) + cancel() + if err != nil { + cobrautl.ExitWithError(cobrautl.ExitError, err) + } + + display.DowngradeEnable(*resp) +} + +// downgradeCancelCommandFunc executes the "downgrade cancel" command. +func downgradeCancelCommandFunc(cmd *cobra.Command, args []string) { + ctx, cancel := commandCtx(cmd) + cli := mustClientFromCmd(cmd) + + resp, err := cli.Downgrade(ctx, int32(pb.DowngradeRequest_CANCEL), "") + cancel() + if err != nil { + cobrautl.ExitWithError(cobrautl.ExitError, err) + } + + display.DowngradeCancel(*resp) +} diff --git a/etcdctl/ctlv3/command/printer.go b/etcdctl/ctlv3/command/printer.go index 7a4086acbdf6..287f88984cb6 100644 --- a/etcdctl/ctlv3/command/printer.go +++ b/etcdctl/ctlv3/command/printer.go @@ -50,6 +50,10 @@ type printer interface { EndpointHashKV([]epHashKV) MoveLeader(leader, target uint64, r v3.MoveLeaderResponse) + DowngradeValidate(r v3.DowngradeResponse) + DowngradeEnable(r v3.DowngradeResponse) + DowngradeCancel(r v3.DowngradeResponse) + Alarm(v3.AlarmResponse) RoleAdd(role string, r v3.AuthRoleAddResponse) @@ -118,6 +122,9 @@ func (p *printerRPC) Alarm(r v3.AlarmResponse) { p.p((*pb.AlarmRespons func (p *printerRPC) MoveLeader(leader, target uint64, r v3.MoveLeaderResponse) { p.p((*pb.MoveLeaderResponse)(&r)) } +func (p *printerRPC) DowngradeValidate(r v3.DowngradeResponse) { p.p((*pb.DowngradeResponse)(&r)) } +func (p *printerRPC) DowngradeEnable(r v3.DowngradeResponse) { p.p((*pb.DowngradeResponse)(&r)) } +func (p *printerRPC) DowngradeCancel(r v3.DowngradeResponse) { p.p((*pb.DowngradeResponse)(&r)) } func (p *printerRPC) RoleAdd(_ string, r v3.AuthRoleAddResponse) { p.p((*pb.AuthRoleAddResponse)(&r)) } func (p *printerRPC) RoleGet(_ string, r v3.AuthRoleGetResponse) { p.p((*pb.AuthRoleGetResponse)(&r)) } func (p *printerRPC) RoleDelete(_ string, r v3.AuthRoleDeleteResponse) { @@ -163,6 +170,9 @@ func (p *printerUnsupported) EndpointStatus([]epStatus) { p.p(nil) } func (p *printerUnsupported) EndpointHashKV([]epHashKV) { p.p(nil) } func (p *printerUnsupported) MoveLeader(leader, target uint64, r v3.MoveLeaderResponse) { p.p(nil) } +func (p *printerUnsupported) DowngradeValidate(r v3.DowngradeResponse) { p.p(nil) } +func (p *printerUnsupported) DowngradeEnable(r v3.DowngradeResponse) { p.p(nil) } +func (p *printerUnsupported) DowngradeCancel(r v3.DowngradeResponse) { p.p(nil) } func makeMemberListTable(r v3.MemberListResponse) (hdr []string, rows [][]string) { hdr = []string{"ID", "Status", "Name", "Peer Addrs", "Client Addrs", "Is Learner"} diff --git a/etcdctl/ctlv3/command/printer_simple.go b/etcdctl/ctlv3/command/printer_simple.go index 14028c614457..1970a49a4bc5 100644 --- a/etcdctl/ctlv3/command/printer_simple.go +++ b/etcdctl/ctlv3/command/printer_simple.go @@ -176,6 +176,16 @@ func (s *simplePrinter) MoveLeader(leader, target uint64, r v3.MoveLeaderRespons fmt.Printf("Leadership transferred from %s to %s\n", types.ID(leader), types.ID(target)) } +func (s *simplePrinter) DowngradeValidate(r v3.DowngradeResponse) { + fmt.Printf("Downgrade validate success, cluster version %s", r.Version) +} +func (s *simplePrinter) DowngradeEnable(r v3.DowngradeResponse) { + fmt.Printf("Downgrade enable success, cluster version %s", r.Version) +} +func (s *simplePrinter) DowngradeCancel(r v3.DowngradeResponse) { + fmt.Printf("Downgrade cancel success, cluster version %s", r.Version) +} + func (s *simplePrinter) RoleAdd(role string, r v3.AuthRoleAddResponse) { fmt.Printf("Role %s created\n", role) } diff --git a/etcdctl/ctlv3/ctl.go b/etcdctl/ctlv3/ctl.go index 8de7a77689df..bfe8f8674ab8 100644 --- a/etcdctl/ctlv3/ctl.go +++ b/etcdctl/ctlv3/ctl.go @@ -97,6 +97,7 @@ func init() { command.NewRoleCommand(), command.NewCheckCommand(), command.NewCompletionCommand(), + command.NewDowngradeCommand(), ) } From 2db4d355548049a82d1e42e9ad0786ffba7003a3 Mon Sep 17 00:00:00 2001 From: Marek Siarkowicz Date: Fri, 11 Feb 2022 15:33:50 +0100 Subject: [PATCH 138/258] tests: Move etcdctl to e2e framework --- tests/e2e/ctl_v3_grpc_test.go | 47 +----------------------- tests/framework/e2e/etcdctl.go | 65 ++++++++++++++++++++++++++++++++++ 2 files changed, 66 insertions(+), 46 deletions(-) create mode 100644 tests/framework/e2e/etcdctl.go diff --git a/tests/e2e/ctl_v3_grpc_test.go b/tests/e2e/ctl_v3_grpc_test.go index 39211e7dcbcf..d3cc101a629a 100644 --- a/tests/e2e/ctl_v3_grpc_test.go +++ b/tests/e2e/ctl_v3_grpc_test.go @@ -98,7 +98,7 @@ func TestAuthority(t *testing.T) { defer epc.Close() endpoints := templateEndpoints(t, tc.clientURLPattern, epc) - client := clusterEtcdctlV3(cfg, endpoints) + client := e2e.NewEtcdctl(cfg, endpoints) err = client.Put("foo", "bar") if err != nil { t.Fatal(err) @@ -152,48 +152,3 @@ func firstMatch(t *testing.T, expectLine string, logs ...e2e.LogsExpect) string } return <-match } - -type etcdctlV3 struct { - cfg *e2e.EtcdProcessClusterConfig - endpoints []string -} - -func clusterEtcdctlV3(cfg *e2e.EtcdProcessClusterConfig, endpoints []string) *etcdctlV3 { - return &etcdctlV3{ - cfg: cfg, - endpoints: endpoints, - } -} - -func (ctl *etcdctlV3) Put(key, value string) error { - return ctl.runCmd("put", key, value) -} - -func (ctl *etcdctlV3) runCmd(args ...string) error { - cmdArgs := []string{e2e.CtlBinPath + "3"} - for k, v := range ctl.flags() { - cmdArgs = append(cmdArgs, fmt.Sprintf("--%s=%s", k, v)) - } - cmdArgs = append(cmdArgs, args...) - return e2e.SpawnWithExpect(cmdArgs, "OK") -} - -func (ctl *etcdctlV3) flags() map[string]string { - fmap := make(map[string]string) - if ctl.cfg.ClientTLS == e2e.ClientTLS { - if ctl.cfg.IsClientAutoTLS { - fmap["insecure-transport"] = "false" - fmap["insecure-skip-tls-verify"] = "true" - } else if ctl.cfg.IsClientCRL { - fmap["cacert"] = e2e.CaPath - fmap["cert"] = e2e.RevokedCertPath - fmap["key"] = e2e.RevokedPrivateKeyPath - } else { - fmap["cacert"] = e2e.CaPath - fmap["cert"] = e2e.CertPath - fmap["key"] = e2e.PrivateKeyPath - } - } - fmap["endpoints"] = strings.Join(ctl.endpoints, ",") - return fmap -} diff --git a/tests/framework/e2e/etcdctl.go b/tests/framework/e2e/etcdctl.go new file mode 100644 index 000000000000..fb24e635ce19 --- /dev/null +++ b/tests/framework/e2e/etcdctl.go @@ -0,0 +1,65 @@ +// Copyright 2022 The etcd Authors +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package e2e + +import ( + "fmt" + "strings" +) + +type etcdctlV3 struct { + cfg *EtcdProcessClusterConfig + endpoints []string +} + +func NewEtcdctl(cfg *EtcdProcessClusterConfig, endpoints []string) *etcdctlV3 { + return &etcdctlV3{ + cfg: cfg, + endpoints: endpoints, + } +} + +func (ctl *etcdctlV3) Put(key, value string) error { + return ctl.runCmd("put", key, value) +} + +func (ctl *etcdctlV3) runCmd(args ...string) error { + cmdArgs := []string{CtlBinPath + "3"} + for k, v := range ctl.flags() { + cmdArgs = append(cmdArgs, fmt.Sprintf("--%s=%s", k, v)) + } + cmdArgs = append(cmdArgs, args...) + return SpawnWithExpect(cmdArgs, "OK") +} + +func (ctl *etcdctlV3) flags() map[string]string { + fmap := make(map[string]string) + if ctl.cfg.ClientTLS == ClientTLS { + if ctl.cfg.IsClientAutoTLS { + fmap["insecure-transport"] = "false" + fmap["insecure-skip-tls-verify"] = "true" + } else if ctl.cfg.IsClientCRL { + fmap["cacert"] = CaPath + fmap["cert"] = RevokedCertPath + fmap["key"] = RevokedPrivateKeyPath + } else { + fmap["cacert"] = CaPath + fmap["cert"] = CertPath + fmap["key"] = PrivateKeyPath + } + } + fmap["endpoints"] = strings.Join(ctl.endpoints, ",") + return fmap +} From 2a7766c8cd6d711e16952f8ce26c17a0ea5f3536 Mon Sep 17 00:00:00 2001 From: Marek Siarkowicz Date: Fri, 11 Feb 2022 15:39:32 +0100 Subject: [PATCH 139/258] tests: Switch downgradetests to use etcdctl --- tests/e2e/cluster_downgrade_test.go | 21 ++++++--------------- tests/framework/e2e/etcdctl.go | 11 +++++++---- 2 files changed, 13 insertions(+), 19 deletions(-) diff --git a/tests/e2e/cluster_downgrade_test.go b/tests/e2e/cluster_downgrade_test.go index 5e2eb9ff209a..93a54884b54b 100644 --- a/tests/e2e/cluster_downgrade_test.go +++ b/tests/e2e/cluster_downgrade_test.go @@ -15,7 +15,6 @@ package e2e import ( - "context" "fmt" "testing" "time" @@ -23,7 +22,6 @@ import ( "github.com/coreos/go-semver/semver" "go.etcd.io/etcd/api/v3/version" "go.etcd.io/etcd/client/pkg/v3/fileutil" - clientv3 "go.etcd.io/etcd/client/v3" "go.etcd.io/etcd/tests/v3/framework/e2e" ) @@ -79,20 +77,13 @@ func startEtcd(t *testing.T, execPath, dataDirPath string) *e2e.EtcdProcessClust func downgradeEnable(t *testing.T, epc *e2e.EtcdProcessCluster, ver semver.Version) { t.Log("etcdctl downgrade...") - c, err := clientv3.New(clientv3.Config{ - Endpoints: epc.EndpointsV3(), + c := e2e.NewEtcdctl(epc.Cfg, epc.EndpointsV3()) + e2e.ExecuteWithTimeout(t, 20*time.Second, func() { + err := c.DowngradeEnable(ver.String()) + if err != nil { + t.Fatal(err) + } }) - if err != nil { - t.Fatal(err) - } - defer c.Close() - ctx, cancel := context.WithTimeout(context.Background(), time.Second*5) - _, err = c.Downgrade(ctx, 1, ver.String()) - if err != nil { - t.Fatal(err) - } - cancel() - } func stopEtcd(t *testing.T, epc *e2e.EtcdProcessCluster) { diff --git a/tests/framework/e2e/etcdctl.go b/tests/framework/e2e/etcdctl.go index fb24e635ce19..86940eee7979 100644 --- a/tests/framework/e2e/etcdctl.go +++ b/tests/framework/e2e/etcdctl.go @@ -32,16 +32,19 @@ func NewEtcdctl(cfg *EtcdProcessClusterConfig, endpoints []string) *etcdctlV3 { } func (ctl *etcdctlV3) Put(key, value string) error { - return ctl.runCmd("put", key, value) + return SpawnWithExpect(ctl.cmdArgs("put", key, value), "OK") } -func (ctl *etcdctlV3) runCmd(args ...string) error { +func (ctl *etcdctlV3) DowngradeEnable(version string) error { + return SpawnWithExpect(ctl.cmdArgs("downgrade", "enable", version), "Downgrade enable success") +} + +func (ctl *etcdctlV3) cmdArgs(args ...string) []string { cmdArgs := []string{CtlBinPath + "3"} for k, v := range ctl.flags() { cmdArgs = append(cmdArgs, fmt.Sprintf("--%s=%s", k, v)) } - cmdArgs = append(cmdArgs, args...) - return SpawnWithExpect(cmdArgs, "OK") + return append(cmdArgs, args...) } func (ctl *etcdctlV3) flags() map[string]string { From 22ee50e00592ae8e0c042c72bc28a02620cc0e91 Mon Sep 17 00:00:00 2001 From: Marek Siarkowicz Date: Mon, 14 Feb 2022 14:42:07 +0100 Subject: [PATCH 140/258] etcdctl: Fix target version not provided message --- etcdctl/ctlv3/command/downgrade_command.go | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/etcdctl/ctlv3/command/downgrade_command.go b/etcdctl/ctlv3/command/downgrade_command.go index 55e95859c784..039c70a55dbd 100644 --- a/etcdctl/ctlv3/command/downgrade_command.go +++ b/etcdctl/ctlv3/command/downgrade_command.go @@ -16,6 +16,7 @@ package command import ( "errors" + "github.com/spf13/cobra" pb "go.etcd.io/etcd/api/v3/etcdserverpb" "go.etcd.io/etcd/pkg/v3/cobrautl" @@ -79,7 +80,7 @@ func downgradeValidateCommandFunc(cmd *cobra.Command, args []string) { targetVersion := args[0] if len(targetVersion) == 0 { - cobrautl.ExitWithError(cobrautl.ExitBadArgs, errors.New("member peer urls not provided")) + cobrautl.ExitWithError(cobrautl.ExitBadArgs, errors.New("target version not provided")) } ctx, cancel := commandCtx(cmd) @@ -105,7 +106,7 @@ func downgradeEnableCommandFunc(cmd *cobra.Command, args []string) { targetVersion := args[0] if len(targetVersion) == 0 { - cobrautl.ExitWithError(cobrautl.ExitBadArgs, errors.New("member peer urls not provided")) + cobrautl.ExitWithError(cobrautl.ExitBadArgs, errors.New("target version not provided")) } ctx, cancel := commandCtx(cmd) From d0c1c3a1fddb39469701b1d3076221b9e8189686 Mon Sep 17 00:00:00 2001 From: Marek Siarkowicz Date: Mon, 14 Feb 2022 14:51:58 +0100 Subject: [PATCH 141/258] client: Alias downgrade action enum --- client/v3/maintenance.go | 24 +++++++++++++--------- etcdctl/ctlv3/command/downgrade_command.go | 8 ++++---- 2 files changed, 18 insertions(+), 14 deletions(-) diff --git a/client/v3/maintenance.go b/client/v3/maintenance.go index 59fdcfd9fd59..25ff135ff088 100644 --- a/client/v3/maintenance.go +++ b/client/v3/maintenance.go @@ -33,6 +33,14 @@ type ( HashKVResponse pb.HashKVResponse MoveLeaderResponse pb.MoveLeaderResponse DowngradeResponse pb.DowngradeResponse + + DowngradeAction pb.DowngradeRequest_DowngradeAction +) + +const ( + DowngradeValidate = DowngradeAction(pb.DowngradeRequest_VALIDATE) + DowngradeEnable = DowngradeAction(pb.DowngradeRequest_ENABLE) + DowngradeCancel = DowngradeAction(pb.DowngradeRequest_CANCEL) ) type Maintenance interface { @@ -76,12 +84,8 @@ type Maintenance interface { // Downgrade requests downgrades, verifies feasibility or cancels downgrade // on the cluster version. - // action is one of the following: - // VALIDATE = 0; - // ENABLE = 1; - // CANCEL = 2; // Supported since etcd 3.5. - Downgrade(ctx context.Context, action int32, version string) (*DowngradeResponse, error) + Downgrade(ctx context.Context, action DowngradeAction, version string) (*DowngradeResponse, error) } // SnapshotResponse is aggregated response from the snapshot stream. @@ -337,14 +341,14 @@ func (m *maintenance) MoveLeader(ctx context.Context, transfereeID uint64) (*Mov return (*MoveLeaderResponse)(resp), toErr(ctx, err) } -func (m *maintenance) Downgrade(ctx context.Context, action int32, version string) (*DowngradeResponse, error) { - actionType := pb.DowngradeRequest_VALIDATE +func (m *maintenance) Downgrade(ctx context.Context, action DowngradeAction, version string) (*DowngradeResponse, error) { + var actionType pb.DowngradeRequest_DowngradeAction switch action { - case 0: + case DowngradeValidate: actionType = pb.DowngradeRequest_VALIDATE - case 1: + case DowngradeEnable: actionType = pb.DowngradeRequest_ENABLE - case 2: + case DowngradeCancel: actionType = pb.DowngradeRequest_CANCEL default: return nil, errors.New("etcdclient: unknown downgrade action") diff --git a/etcdctl/ctlv3/command/downgrade_command.go b/etcdctl/ctlv3/command/downgrade_command.go index 039c70a55dbd..bccae16c339d 100644 --- a/etcdctl/ctlv3/command/downgrade_command.go +++ b/etcdctl/ctlv3/command/downgrade_command.go @@ -18,7 +18,7 @@ import ( "errors" "github.com/spf13/cobra" - pb "go.etcd.io/etcd/api/v3/etcdserverpb" + clientv3 "go.etcd.io/etcd/client/v3" "go.etcd.io/etcd/pkg/v3/cobrautl" ) @@ -86,7 +86,7 @@ func downgradeValidateCommandFunc(cmd *cobra.Command, args []string) { ctx, cancel := commandCtx(cmd) cli := mustClientFromCmd(cmd) - resp, err := cli.Downgrade(ctx, int32(pb.DowngradeRequest_VALIDATE), targetVersion) + resp, err := cli.Downgrade(ctx, clientv3.DowngradeValidate, targetVersion) cancel() if err != nil { cobrautl.ExitWithError(cobrautl.ExitError, err) @@ -112,7 +112,7 @@ func downgradeEnableCommandFunc(cmd *cobra.Command, args []string) { ctx, cancel := commandCtx(cmd) cli := mustClientFromCmd(cmd) - resp, err := cli.Downgrade(ctx, int32(pb.DowngradeRequest_ENABLE), targetVersion) + resp, err := cli.Downgrade(ctx, clientv3.DowngradeEnable, targetVersion) cancel() if err != nil { cobrautl.ExitWithError(cobrautl.ExitError, err) @@ -126,7 +126,7 @@ func downgradeCancelCommandFunc(cmd *cobra.Command, args []string) { ctx, cancel := commandCtx(cmd) cli := mustClientFromCmd(cmd) - resp, err := cli.Downgrade(ctx, int32(pb.DowngradeRequest_CANCEL), "") + resp, err := cli.Downgrade(ctx, clientv3.DowngradeCancel, "") cancel() if err != nil { cobrautl.ExitWithError(cobrautl.ExitError, err) From 16d70051375efeaae94d96f725061401abe0ddc0 Mon Sep 17 00:00:00 2001 From: Marek Siarkowicz Date: Mon, 21 Feb 2022 17:54:33 +0100 Subject: [PATCH 142/258] etcdctl: Add dot at the end of sentences --- etcdctl/README.md | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/etcdctl/README.md b/etcdctl/README.md index 4ef3b62b8aea..cff009f18a68 100644 --- a/etcdctl/README.md +++ b/etcdctl/README.md @@ -1085,11 +1085,11 @@ echo ${transferee_id} ### DOWNGRADE \ -Downgrade provides commands to downgrade cluster version +Downgrade provides commands to downgrade cluster version. ### DOWNGRADE VALIDATE \ -DOWNGRADE VALIDATE validate downgrade capability before starting downgrade +DOWNGRADE VALIDATE validate downgrade capability before starting downgrade. #### Example @@ -1104,7 +1104,7 @@ Error: etcdserver: invalid downgrade target version ### DOWNGRADE ENABLE \ -DOWNGRADE ENABLE starts a downgrade action to cluster +DOWNGRADE ENABLE starts a downgrade action to cluster. #### Example @@ -1115,7 +1115,7 @@ Downgrade enable success, cluster version 3.6.0 ### DOWNGRADE CANCEL \ -DOWNGRADE CANCEL cancels the ongoing downgrade action to cluster +DOWNGRADE CANCEL cancels the ongoing downgrade action to cluster. #### Example From 5d3847577fbd3fa56b48cfe3c29915e8970f62a5 Mon Sep 17 00:00:00 2001 From: ahrtr Date: Fri, 18 Feb 2022 06:47:59 +0800 Subject: [PATCH 143/258] always print the raft_term in decimal even flag --hex is provided --- CHANGELOG/CHANGELOG-3.6.md | 1 + etcdctl/ctlv3/command/printer_json.go | 2 +- tests/e2e/ctl_v3_member_test.go | 11 ++++++++--- 3 files changed, 10 insertions(+), 4 deletions(-) diff --git a/CHANGELOG/CHANGELOG-3.6.md b/CHANGELOG/CHANGELOG-3.6.md index 6d091dd73ba9..154b5244d1d9 100644 --- a/CHANGELOG/CHANGELOG-3.6.md +++ b/CHANGELOG/CHANGELOG-3.6.md @@ -20,6 +20,7 @@ See [code changes](https://github.com/etcd-io/etcd/compare/v3.5.0...v3.6.0). - Add command to generate [shell completion](https://github.com/etcd-io/etcd/pull/13133). - When print endpoint status, [show db size in use](https://github.com/etcd-io/etcd/pull/13639) +- [Always print the raft_term in decimal](https://github.com/etcd-io/etcd/pull/13711) when displaying member list in json. ### etcdutl v3 diff --git a/etcdctl/ctlv3/command/printer_json.go b/etcdctl/ctlv3/command/printer_json.go index ca90a4a311c5..4c75c85a8c7d 100644 --- a/etcdctl/ctlv3/command/printer_json.go +++ b/etcdctl/ctlv3/command/printer_json.go @@ -67,7 +67,7 @@ func printMemberListWithHexJSON(r clientv3.MemberListResponse) { b = strconv.AppendUint(nil, r.Header.MemberId, 16) buffer.Write(b) buffer.WriteString("\",\"raft_term\":") - b = strconv.AppendUint(nil, r.Header.RaftTerm, 16) + b = strconv.AppendUint(nil, r.Header.RaftTerm, 10) buffer.Write(b) buffer.WriteByte('}') for i := 0; i < len(r.Members); i++ { diff --git a/tests/e2e/ctl_v3_member_test.go b/tests/e2e/ctl_v3_member_test.go index fe111424d223..657b0eaf5ed8 100644 --- a/tests/e2e/ctl_v3_member_test.go +++ b/tests/e2e/ctl_v3_member_test.go @@ -160,15 +160,20 @@ func memberListWithHexTest(cx ctlCtx) { if num == 0 { cx.t.Fatal("member number is 0") } + + if resp.Header.RaftTerm != hexResp.Header.RaftTerm { + cx.t.Fatalf("Unexpected raft_term, expected %d, got %d", resp.Header.RaftTerm, hexResp.Header.RaftTerm) + } + for i := 0; i < num; i++ { if resp.Members[i].Name != hexResp.Members[i].Name { - cx.t.Fatalf("member name,expected %v,got %v", resp.Members[i].Name, hexResp.Members[i].Name) + cx.t.Fatalf("Unexpected member name,expected %v, got %v", resp.Members[i].Name, hexResp.Members[i].Name) } if !reflect.DeepEqual(resp.Members[i].PeerURLs, hexResp.Members[i].PeerURLs) { - cx.t.Fatalf("member peerURLs,expected %v,got %v", resp.Members[i].PeerURLs, hexResp.Members[i].PeerURLs) + cx.t.Fatalf("Unexpected member peerURLs, expected %v, got %v", resp.Members[i].PeerURLs, hexResp.Members[i].PeerURLs) } if !reflect.DeepEqual(resp.Members[i].ClientURLs, hexResp.Members[i].ClientURLs) { - cx.t.Fatalf("member clientURLS,expected %v,got %v", resp.Members[i].ClientURLs, hexResp.Members[i].ClientURLs) + cx.t.Fatalf("Unexpected member clientURLS, expected %v, got %v", resp.Members[i].ClientURLs, hexResp.Members[i].ClientURLs) } } } From 13e20cce5e410d699f7c902c48ccad560d2d1dcb Mon Sep 17 00:00:00 2001 From: ahrtr Date: Tue, 22 Feb 2022 07:55:16 +0800 Subject: [PATCH 144/258] update 3.5 changelog to cover the PR of improving health check --- CHANGELOG/CHANGELOG-3.5.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/CHANGELOG/CHANGELOG-3.5.md b/CHANGELOG/CHANGELOG-3.5.md index 0c7283a56e40..dc6ce5d0ef90 100644 --- a/CHANGELOG/CHANGELOG-3.5.md +++ b/CHANGELOG/CHANGELOG-3.5.md @@ -6,8 +6,12 @@ Previous change logs can be found at [CHANGELOG-3.4](https://github.com/etcd-io/ The minimum recommended etcd versions to run in **production** are 3.3.18+, 3.4.2+, and 3.5.2+. Refer to the [versioning policy](https://etcd.io/docs/v3.5/op-guide/versioning/) for more details.
+ ## v3.5.3 (TBD) +### etcd server +- Fix [Provide a better liveness probe for when etcd runs as a Kubernetes pod](https://github.com/etcd-io/etcd/pull/13706) + ### package `client/pkg/v3` - [Trim the suffix dot from the target](https://github.com/etcd-io/etcd/pull/13714) in SRV records returned by DNS lookup From c1c2f1233d0c540a567ec78e43e4424feecd533c Mon Sep 17 00:00:00 2001 From: Marek Siarkowicz Date: Tue, 22 Feb 2022 16:29:35 +0100 Subject: [PATCH 145/258] etcdctl: Documment downgrade commands --- etcdctl/README.md | 24 +++++++++++++++++++++++- 1 file changed, 23 insertions(+), 1 deletion(-) diff --git a/etcdctl/README.md b/etcdctl/README.md index cff009f18a68..fa92089b3c3b 100644 --- a/etcdctl/README.md +++ b/etcdctl/README.md @@ -1085,7 +1085,29 @@ echo ${transferee_id} ### DOWNGRADE \ -Downgrade provides commands to downgrade cluster version. +NOTICE: Downgrades is an experimental feature in v3.6 and is not recommended for production clusters. + +Downgrade provides commands to downgrade cluster. +Normally etcd members cannot be downgraded due to cluster version mechanism. + +After initial bootstrap, cluster members agree on the cluster version. Every 5 seconds, leader checks versions of all members and picks lowers minor version. +New members will refuse joining cluster with cluster version newer than theirs, thus preventing cluster from downgrading. +Downgrade commands allow cluster administrator to force cluster version to be lowered to previous minor version, thus allowing to downgrade the cluster. + +Downgrade should be is executed in stages: +1. Verify that cluster is ready be downgraded by running `etcdctl downgrade validate ` +2. Start the downgrade process by running `etcdctl downgrade enable ` +3. For each cluster member: + 1. Ensure that member is ready for downgrade by confirming that it wrote `The server is ready to downgrade` log. + 2. Replace member binary with one with older version. + 3. Confirm that member has correctly started and joined the cluster. +4. Ensure that downgrade process has succeeded by checking leader log for `the cluster has been downgraded` + +Downgrade can be canceled by running `etcdctl downgrade cancel` command. + +In case of downgrade being canceled, cluster version will return to its normal behavior (pick the lowest member minor version). +If no members were downgraded, cluster version will return to original value. +If at least one member was downgraded, cluster version will stay at the `` until downgraded members are upgraded back. ### DOWNGRADE VALIDATE \ From 42faf9fe06d2d1867a56274278ea84f323074cb8 Mon Sep 17 00:00:00 2001 From: Marek Siarkowicz Date: Tue, 22 Feb 2022 16:30:08 +0100 Subject: [PATCH 146/258] etcdctl: Use minor versions for downgrade --- etcdctl/README.md | 12 ++++++------ etcdctl/ctlv3/command/printer_simple.go | 6 +++--- server/etcdserver/v3_server.go | 7 ++++--- 3 files changed, 13 insertions(+), 12 deletions(-) diff --git a/etcdctl/README.md b/etcdctl/README.md index fa92089b3c3b..66dfc619f3a1 100644 --- a/etcdctl/README.md +++ b/etcdctl/README.md @@ -1116,10 +1116,10 @@ DOWNGRADE VALIDATE validate downgrade capability before starting downgrade. #### Example ```bash -./etcdctl downgrade validate 3.5.0 -Downgrade validate success, cluster version 3.6.0 +./etcdctl downgrade validate 3.5 +Downgrade validate success, cluster version 3.6 -./etcdctl downgrade validate 3.4.0 +./etcdctl downgrade validate 3.4 Error: etcdserver: invalid downgrade target version ``` @@ -1131,8 +1131,8 @@ DOWNGRADE ENABLE starts a downgrade action to cluster. #### Example ```bash -./etcdctl downgrade enable 3.5.0 -Downgrade enable success, cluster version 3.6.0 +./etcdctl downgrade enable 3.5 +Downgrade enable success, cluster version 3.6 ``` ### DOWNGRADE CANCEL \ @@ -1143,7 +1143,7 @@ DOWNGRADE CANCEL cancels the ongoing downgrade action to cluster. ```bash ./etcdctl downgrade cancel -Downgrade cancel success, cluster version 3.6.0 +Downgrade cancel success, cluster version 3.5 ``` ## Concurrency commands diff --git a/etcdctl/ctlv3/command/printer_simple.go b/etcdctl/ctlv3/command/printer_simple.go index 1970a49a4bc5..32f8cac60499 100644 --- a/etcdctl/ctlv3/command/printer_simple.go +++ b/etcdctl/ctlv3/command/printer_simple.go @@ -177,13 +177,13 @@ func (s *simplePrinter) MoveLeader(leader, target uint64, r v3.MoveLeaderRespons } func (s *simplePrinter) DowngradeValidate(r v3.DowngradeResponse) { - fmt.Printf("Downgrade validate success, cluster version %s", r.Version) + fmt.Printf("Downgrade validate success, cluster version %s\n", r.Version) } func (s *simplePrinter) DowngradeEnable(r v3.DowngradeResponse) { - fmt.Printf("Downgrade enable success, cluster version %s", r.Version) + fmt.Printf("Downgrade enable success, cluster version %s\n", r.Version) } func (s *simplePrinter) DowngradeCancel(r v3.DowngradeResponse) { - fmt.Printf("Downgrade cancel success, cluster version %s", r.Version) + fmt.Printf("Downgrade cancel success, cluster version %s\n", r.Version) } func (s *simplePrinter) RoleAdd(role string, r v3.AuthRoleAddResponse) { diff --git a/server/etcdserver/v3_server.go b/server/etcdserver/v3_server.go index 9885fc01c031..3e868bebda98 100644 --- a/server/etcdserver/v3_server.go +++ b/server/etcdserver/v3_server.go @@ -23,6 +23,7 @@ import ( "time" pb "go.etcd.io/etcd/api/v3/etcdserverpb" + "go.etcd.io/etcd/api/v3/version" "go.etcd.io/etcd/pkg/v3/traceutil" "go.etcd.io/etcd/raft/v3" "go.etcd.io/etcd/server/v3/auth" @@ -922,7 +923,7 @@ func (s *EtcdServer) downgradeValidate(ctx context.Context, v string) (*pb.Downg if cv == nil { return nil, ErrClusterVersionUnavailable } - resp.Version = cv.String() + resp.Version = version.Cluster(cv.String()) err = s.Version().DowngradeValidate(ctx, targetVersion) if err != nil { return nil, err @@ -943,7 +944,7 @@ func (s *EtcdServer) downgradeEnable(ctx context.Context, r *pb.DowngradeRequest lg.Warn("reject downgrade request", zap.Error(err)) return nil, err } - resp := pb.DowngradeResponse{Version: s.ClusterVersion().String()} + resp := pb.DowngradeResponse{Version: version.Cluster(s.ClusterVersion().String())} return &resp, nil } @@ -952,6 +953,6 @@ func (s *EtcdServer) downgradeCancel(ctx context.Context) (*pb.DowngradeResponse if err != nil { s.lg.Warn("failed to cancel downgrade", zap.Error(err)) } - resp := pb.DowngradeResponse{Version: s.ClusterVersion().String()} + resp := pb.DowngradeResponse{Version: version.Cluster(s.ClusterVersion().String())} return &resp, nil } From d61e9d967fae13bd0b270070ac028ac7bbed11ca Mon Sep 17 00:00:00 2001 From: Marek Siarkowicz Date: Tue, 22 Feb 2022 18:55:13 +0100 Subject: [PATCH 147/258] Add Benjamin to reviewers --- MAINTAINERS | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/MAINTAINERS b/MAINTAINERS index 5e3e50a2bee4..9ca0c6a0d33f 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -26,4 +26,4 @@ Tobias Grieger (@tbg) pkg:go.etcd.io/etcd/raft # REVIEWERS Lili Cosic (lilic@) pkg:* Wilson Wang (wilsonwang371@) pkg:* - +Benjamin (ahrtr@) pkg:* From c4e5c1401173f006c74b219249ca3f43f9e457ff Mon Sep 17 00:00:00 2001 From: Marek Siarkowicz Date: Wed, 23 Feb 2022 10:36:59 +0100 Subject: [PATCH 148/258] Update Benjamin contact --- MAINTAINERS | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/MAINTAINERS b/MAINTAINERS index 9ca0c6a0d33f..c91a77f403ea 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -26,4 +26,4 @@ Tobias Grieger (@tbg) pkg:go.etcd.io/etcd/raft # REVIEWERS Lili Cosic (lilic@) pkg:* Wilson Wang (wilsonwang371@) pkg:* -Benjamin (ahrtr@) pkg:* +Benjamin Wang (ahrtr@) pkg:* From 744dd077cdf167eb769fc8d1611fd9a46b4c26ba Mon Sep 17 00:00:00 2001 From: Marek Siarkowicz Date: Thu, 17 Feb 2022 22:01:50 +0100 Subject: [PATCH 149/258] tests: Create common framework for e2e and integration tests and migrate TestKVPut test --- scripts/test.sh | 5 +- tests/common/e2e_test.go | 24 ++++++++ tests/common/integration_test.go | 26 +++++++++ tests/common/kv_test.go | 50 +++++++++++++++++ tests/common/main_test.go | 27 +++++++++ tests/e2e/cluster_downgrade_test.go | 7 ++- tests/e2e/ctl_v3_grpc_test.go | 3 +- tests/e2e/ctl_v3_kv_test.go | 2 - tests/framework/default.go | 44 +++++++++++++++ tests/framework/e2e.go | 68 ++++++++++++++++++++++ tests/framework/e2e/etcdctl.go | 39 ++++++++++--- tests/framework/e2e/util.go | 14 ----- tests/framework/framework.go | 21 +++++++ tests/framework/integration.go | 81 +++++++++++++++++++++++++++ tests/framework/interface.go | 38 +++++++++++++ tests/framework/testutils/options.go | 27 +++++++++ tests/framework/testutils/util.go | 37 ++++++++++++ tests/integration/clientv3/kv_test.go | 44 ++++++--------- 18 files changed, 500 insertions(+), 57 deletions(-) create mode 100644 tests/common/e2e_test.go create mode 100644 tests/common/integration_test.go create mode 100644 tests/common/kv_test.go create mode 100644 tests/common/main_test.go create mode 100644 tests/framework/default.go create mode 100644 tests/framework/e2e.go create mode 100644 tests/framework/framework.go create mode 100644 tests/framework/integration.go create mode 100644 tests/framework/interface.go create mode 100644 tests/framework/testutils/options.go create mode 100644 tests/framework/testutils/util.go diff --git a/scripts/test.sh b/scripts/test.sh index e8047ccb56ba..687b32433fe2 100755 --- a/scripts/test.sh +++ b/scripts/test.sh @@ -107,14 +107,15 @@ function integration_extra { } function integration_pass { - local pkgs=${USERPKG:-"./integration/..."} - run_for_module "tests" go_test "${pkgs}" "parallel" : -timeout="${TIMEOUT:-15m}" "${COMMON_TEST_FLAGS[@]}" "${RUN_ARG[@]}" "$@" || return $? + run_for_module "tests" go_test "./integration/..." "parallel" : -timeout="${TIMEOUT:-15m}" "${COMMON_TEST_FLAGS[@]}" "${RUN_ARG[@]}" "$@" || return $? + run_for_module "tests" go_test "./common/..." "parallel" : --tags=integration -timeout="${TIMEOUT:-15m}" "${COMMON_TEST_FLAGS[@]}" "${RUN_ARG[@]}" "$@" || return $? integration_extra "$@" } function e2e_pass { # e2e tests are running pre-build binary. Settings like --race,-cover,-cpu does not have any impact. run_for_module "tests" go_test "./e2e/..." "keep_going" : -timeout="${TIMEOUT:-30m}" "${RUN_ARG[@]}" "$@" + run_for_module "tests" go_test "./common/..." "keep_going" : --tags=e2e -timeout="${TIMEOUT:-30m}" "${RUN_ARG[@]}" "$@" } function integration_e2e_pass { diff --git a/tests/common/e2e_test.go b/tests/common/e2e_test.go new file mode 100644 index 000000000000..e0f29ce399ce --- /dev/null +++ b/tests/common/e2e_test.go @@ -0,0 +1,24 @@ +// Copyright 2022 The etcd Authors +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +//go:build e2e +// +build e2e + +package common + +import "go.etcd.io/etcd/tests/v3/framework" + +func init() { + testFramework = framework.RunE2eTests +} diff --git a/tests/common/integration_test.go b/tests/common/integration_test.go new file mode 100644 index 000000000000..7c7ccc2244ca --- /dev/null +++ b/tests/common/integration_test.go @@ -0,0 +1,26 @@ +// Copyright 2022 The etcd Authors +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +//go:build integration +// +build integration + +package common + +import ( + "go.etcd.io/etcd/tests/v3/framework" +) + +func init() { + testFramework = framework.RunIntegrationTests +} diff --git a/tests/common/kv_test.go b/tests/common/kv_test.go new file mode 100644 index 000000000000..868fa3f3efd7 --- /dev/null +++ b/tests/common/kv_test.go @@ -0,0 +1,50 @@ +// Copyright 2022 The etcd Authors +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package common + +import ( + "testing" + "time" + + "go.etcd.io/etcd/tests/v3/framework/testutils" +) + +func TestKVPut(t *testing.T) { + testFramework.BeforeTest(t) + clus := testFramework.NewCluster(t) + defer clus.Close() + cc := clus.Client() + + testutils.ExecuteWithTimeout(t, 10*time.Second, func() { + key, value := "foo", "bar" + + if err := cc.Put(key, value); err != nil { + t.Fatalf("count not put key %q, err: %s", key, err) + } + resp, err := cc.Get(key, testutils.WithSerializable()) + if err != nil { + t.Fatalf("count not get key %q, err: %s", key, err) + } + if len(resp.Kvs) != 1 { + t.Errorf("Unexpected lenth of response, got %d", len(resp.Kvs)) + } + if string(resp.Kvs[0].Key) != key { + t.Errorf("Unexpected key, want %q, got %q", key, resp.Kvs[0].Key) + } + if string(resp.Kvs[0].Value) != value { + t.Errorf("Unexpected value, want %q, got %q", value, resp.Kvs[0].Value) + } + }) +} diff --git a/tests/common/main_test.go b/tests/common/main_test.go new file mode 100644 index 000000000000..b3987e1b5913 --- /dev/null +++ b/tests/common/main_test.go @@ -0,0 +1,27 @@ +// Copyright 2022 The etcd Authors +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package common + +import ( + "testing" + + "go.etcd.io/etcd/tests/v3/framework" +) + +var testFramework = framework.TestFramework + +func TestMain(m *testing.M) { + testFramework.TestMain(m) +} diff --git a/tests/e2e/cluster_downgrade_test.go b/tests/e2e/cluster_downgrade_test.go index 93a54884b54b..06031ea489f6 100644 --- a/tests/e2e/cluster_downgrade_test.go +++ b/tests/e2e/cluster_downgrade_test.go @@ -23,6 +23,7 @@ import ( "go.etcd.io/etcd/api/v3/version" "go.etcd.io/etcd/client/pkg/v3/fileutil" "go.etcd.io/etcd/tests/v3/framework/e2e" + "go.etcd.io/etcd/tests/v3/framework/testutils" ) func TestDowngradeUpgrade(t *testing.T) { @@ -78,7 +79,7 @@ func startEtcd(t *testing.T, execPath, dataDirPath string) *e2e.EtcdProcessClust func downgradeEnable(t *testing.T, epc *e2e.EtcdProcessCluster, ver semver.Version) { t.Log("etcdctl downgrade...") c := e2e.NewEtcdctl(epc.Cfg, epc.EndpointsV3()) - e2e.ExecuteWithTimeout(t, 20*time.Second, func() { + testutils.ExecuteWithTimeout(t, 20*time.Second, func() { err := c.DowngradeEnable(ver.String()) if err != nil { t.Fatal(err) @@ -96,7 +97,7 @@ func stopEtcd(t *testing.T, epc *e2e.EtcdProcessCluster) { func validateVersion(t *testing.T, epc *e2e.EtcdProcessCluster, expect version.Versions) { t.Log("Validate version") // Two separate calls to expect as it doesn't support multiple matches on the same line - e2e.ExecuteWithTimeout(t, 20*time.Second, func() { + testutils.ExecuteWithTimeout(t, 20*time.Second, func() { if expect.Server != "" { err := e2e.SpawnWithExpects(e2e.CURLPrefixArgs(epc, "GET", e2e.CURLReq{Endpoint: "/version"}), nil, `"etcdserver":"`+expect.Server) if err != nil { @@ -114,7 +115,7 @@ func validateVersion(t *testing.T, epc *e2e.EtcdProcessCluster, expect version.V func expectLog(t *testing.T, epc *e2e.EtcdProcessCluster, expectLog string) { t.Helper() - e2e.ExecuteWithTimeout(t, 30*time.Second, func() { + testutils.ExecuteWithTimeout(t, 30*time.Second, func() { _, err := epc.Procs[0].Logs().Expect(expectLog) if err != nil { t.Fatal(err) diff --git a/tests/e2e/ctl_v3_grpc_test.go b/tests/e2e/ctl_v3_grpc_test.go index d3cc101a629a..8c8be2c698ef 100644 --- a/tests/e2e/ctl_v3_grpc_test.go +++ b/tests/e2e/ctl_v3_grpc_test.go @@ -25,6 +25,7 @@ import ( "github.com/stretchr/testify/assert" "go.etcd.io/etcd/tests/v3/framework/e2e" + "go.etcd.io/etcd/tests/v3/framework/testutils" ) func TestAuthority(t *testing.T) { @@ -104,7 +105,7 @@ func TestAuthority(t *testing.T) { t.Fatal(err) } - e2e.ExecuteWithTimeout(t, 5*time.Second, func() { + testutils.ExecuteWithTimeout(t, 5*time.Second, func() { assertAuthority(t, fmt.Sprintf(tc.expectAuthorityPattern, 20000), epc) }) }) diff --git a/tests/e2e/ctl_v3_kv_test.go b/tests/e2e/ctl_v3_kv_test.go index 69f639be7040..d74434ab2a0a 100644 --- a/tests/e2e/ctl_v3_kv_test.go +++ b/tests/e2e/ctl_v3_kv_test.go @@ -18,12 +18,10 @@ import ( "fmt" "strings" "testing" - "time" "go.etcd.io/etcd/tests/v3/framework/e2e" ) -func TestCtlV3Put(t *testing.T) { testCtl(t, putTest, withDialTimeout(7*time.Second)) } func TestCtlV3PutNoTLS(t *testing.T) { testCtl(t, putTest, withCfg(*e2e.NewConfigNoTLS())) } func TestCtlV3PutClientTLS(t *testing.T) { testCtl(t, putTest, withCfg(*e2e.NewConfigClientTLS())) } func TestCtlV3PutClientAutoTLS(t *testing.T) { diff --git a/tests/framework/default.go b/tests/framework/default.go new file mode 100644 index 000000000000..d34dc64622cc --- /dev/null +++ b/tests/framework/default.go @@ -0,0 +1,44 @@ +// Copyright 2022 The etcd Authors +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package framework + +import ( + "flag" + "fmt" + "os" + "testing" + + "go.etcd.io/etcd/client/pkg/v3/testutil" +) + +type noFrameworkSelected struct{} + +var _ testFramework = (*noFrameworkSelected)(nil) + +func (e noFrameworkSelected) TestMain(m *testing.M) { + flag.Parse() + if !testing.Short() { + fmt.Println(`No test mode selected, please selected either e2e mode with "--tags e2e" or integration mode with "--tags integration"`) + os.Exit(1) + } +} + +func (e noFrameworkSelected) BeforeTest(t testing.TB) { + testutil.SkipTestIfShortMode(t, "Cannot create clusters in --short tests") +} + +func (e noFrameworkSelected) NewCluster(t testing.TB) Cluster { + return nil +} diff --git a/tests/framework/e2e.go b/tests/framework/e2e.go new file mode 100644 index 000000000000..7dfc4b611106 --- /dev/null +++ b/tests/framework/e2e.go @@ -0,0 +1,68 @@ +// Copyright 2022 The etcd Authors +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package framework + +import ( + "os" + "testing" + + "go.etcd.io/etcd/client/pkg/v3/testutil" + clientv3 "go.etcd.io/etcd/client/v3" + "go.etcd.io/etcd/tests/v3/framework/e2e" + "go.etcd.io/etcd/tests/v3/framework/testutils" +) + +type e2eFramework struct{} + +func (e e2eFramework) TestMain(m *testing.M) { + e2e.InitFlags() + v := m.Run() + if v == 0 && testutil.CheckLeakedGoroutine() { + os.Exit(1) + } + os.Exit(v) +} + +func (e e2eFramework) BeforeTest(t testing.TB) { + e2e.BeforeTest(t) +} + +func (e e2eFramework) NewCluster(t testing.TB) Cluster { + epc, err := e2e.NewEtcdProcessCluster(t, e2e.ConfigStandalone(*e2e.NewConfigAutoTLS())) + if err != nil { + t.Fatalf("could not start etcd integrationCluster: %s", err) + } + return &e2eCluster{*epc} +} + +type e2eCluster struct { + e2e.EtcdProcessCluster +} + +func (c *e2eCluster) Client() Client { + return e2eClient{e2e.NewEtcdctl(c.Cfg, c.EndpointsV3())} +} + +type e2eClient struct { + *e2e.EtcdctlV3 +} + +func (c e2eClient) Get(key string, opts ...testutils.GetOption) (*clientv3.GetResponse, error) { + o := testutils.GetOptions{} + for _, opt := range opts { + opt(&o) + } + return c.EtcdctlV3.Get(key, o.Serializable) +} diff --git a/tests/framework/e2e/etcdctl.go b/tests/framework/e2e/etcdctl.go index 86940eee7979..68e1e438e4ae 100644 --- a/tests/framework/e2e/etcdctl.go +++ b/tests/framework/e2e/etcdctl.go @@ -15,31 +15,52 @@ package e2e import ( + "encoding/json" "fmt" "strings" + + clientv3 "go.etcd.io/etcd/client/v3" ) -type etcdctlV3 struct { +type EtcdctlV3 struct { cfg *EtcdProcessClusterConfig endpoints []string } -func NewEtcdctl(cfg *EtcdProcessClusterConfig, endpoints []string) *etcdctlV3 { - return &etcdctlV3{ +func NewEtcdctl(cfg *EtcdProcessClusterConfig, endpoints []string) *EtcdctlV3 { + return &EtcdctlV3{ cfg: cfg, endpoints: endpoints, } } -func (ctl *etcdctlV3) Put(key, value string) error { - return SpawnWithExpect(ctl.cmdArgs("put", key, value), "OK") +func (ctl *EtcdctlV3) DowngradeEnable(version string) error { + return SpawnWithExpect(ctl.cmdArgs("downgrade", "enable", version), "Downgrade enable success") } -func (ctl *etcdctlV3) DowngradeEnable(version string) error { - return SpawnWithExpect(ctl.cmdArgs("downgrade", "enable", version), "Downgrade enable success") +func (ctl *EtcdctlV3) Get(key string, serializable bool) (*clientv3.GetResponse, error) { + args := ctl.cmdArgs() + if serializable { + args = append(args, "--consistency", "s") + } + cmd, err := SpawnCmd(append(args, "get", key, "-w", "json"), nil) + if err != nil { + return nil, err + } + line, err := cmd.Expect("kvs") + if err != nil { + return nil, err + } + var resp clientv3.GetResponse + err = json.Unmarshal([]byte(line), &resp) + return &resp, err +} + +func (ctl *EtcdctlV3) Put(key, value string) error { + return SpawnWithExpect(ctl.cmdArgs("put", key, value), "OK") } -func (ctl *etcdctlV3) cmdArgs(args ...string) []string { +func (ctl *EtcdctlV3) cmdArgs(args ...string) []string { cmdArgs := []string{CtlBinPath + "3"} for k, v := range ctl.flags() { cmdArgs = append(cmdArgs, fmt.Sprintf("--%s=%s", k, v)) @@ -47,7 +68,7 @@ func (ctl *etcdctlV3) cmdArgs(args ...string) []string { return append(cmdArgs, args...) } -func (ctl *etcdctlV3) flags() map[string]string { +func (ctl *EtcdctlV3) flags() map[string]string { fmap := make(map[string]string) if ctl.cfg.ClientTLS == ClientTLS { if ctl.cfg.IsClientAutoTLS { diff --git a/tests/framework/e2e/util.go b/tests/framework/e2e/util.go index 8ea76ee40736..7d997e08a92e 100644 --- a/tests/framework/e2e/util.go +++ b/tests/framework/e2e/util.go @@ -119,20 +119,6 @@ func SkipInShortMode(t testing.TB) { testutil.SkipTestIfShortMode(t, "e2e tests are not running in --short mode") } -func ExecuteWithTimeout(t *testing.T, timeout time.Duration, f func()) { - donec := make(chan struct{}) - go func() { - defer close(donec) - f() - }() - - select { - case <-time.After(timeout): - testutil.FatalStack(t, fmt.Sprintf("test timed out after %v", timeout)) - case <-donec: - } -} - func mergeEnvVariables(envVars map[string]string) []string { var env []string // Environment variables are passed as parameter have higher priority diff --git a/tests/framework/framework.go b/tests/framework/framework.go new file mode 100644 index 000000000000..d07968e738e7 --- /dev/null +++ b/tests/framework/framework.go @@ -0,0 +1,21 @@ +// Copyright 2022 The etcd Authors +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package framework + +var ( + TestFramework testFramework = noFrameworkSelected{} + RunE2eTests testFramework = e2eFramework{} + RunIntegrationTests testFramework = integrationFramework{} +) diff --git a/tests/framework/integration.go b/tests/framework/integration.go new file mode 100644 index 000000000000..46eb83d83168 --- /dev/null +++ b/tests/framework/integration.go @@ -0,0 +1,81 @@ +// Copyright 2022 The etcd Authors +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package framework + +import ( + "context" + "testing" + + "go.etcd.io/etcd/client/pkg/v3/testutil" + clientv3 "go.etcd.io/etcd/client/v3" + "go.etcd.io/etcd/tests/v3/framework/integration" + "go.etcd.io/etcd/tests/v3/framework/testutils" +) + +type integrationFramework struct{} + +func (e integrationFramework) TestMain(m *testing.M) { + testutil.MustTestMainWithLeakDetection(m) +} + +func (e integrationFramework) BeforeTest(t testing.TB) { + integration.BeforeTest(t) +} + +func (e integrationFramework) NewCluster(t testing.TB) Cluster { + return &integrationCluster{ + Cluster: integration.NewCluster(t, &integration.ClusterConfig{Size: 1}), + t: t, + } +} + +type integrationCluster struct { + *integration.Cluster + t testing.TB +} + +func (c *integrationCluster) Close() error { + c.Terminate(c.t) + return nil +} + +func (c *integrationCluster) Client() Client { + cc, err := c.ClusterClient() + if err != nil { + c.t.Fatal(err) + } + return &integrationClient{cc} +} + +type integrationClient struct { + *clientv3.Client +} + +func (c integrationClient) Get(key string, opts ...testutils.GetOption) (*clientv3.GetResponse, error) { + o := testutils.GetOptions{} + for _, opt := range opts { + opt(&o) + } + clientOpts := []clientv3.OpOption{} + if o.Serializable { + clientOpts = append(clientOpts, clientv3.WithSerializable()) + } + return c.Client.Get(context.Background(), key, clientOpts...) +} + +func (c integrationClient) Put(key, value string) error { + _, err := c.Client.Put(context.Background(), key, value) + return err +} diff --git a/tests/framework/interface.go b/tests/framework/interface.go new file mode 100644 index 000000000000..273ed453224a --- /dev/null +++ b/tests/framework/interface.go @@ -0,0 +1,38 @@ +// Copyright 2022 The etcd Authors +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package framework + +import ( + "testing" + + clientv3 "go.etcd.io/etcd/client/v3" + "go.etcd.io/etcd/tests/v3/framework/testutils" +) + +type testFramework interface { + TestMain(m *testing.M) + BeforeTest(testing.TB) + NewCluster(testing.TB) Cluster +} + +type Cluster interface { + Close() error + Client() Client +} + +type Client interface { + Put(key, value string) error + Get(key string, opts ...testutils.GetOption) (*clientv3.GetResponse, error) +} diff --git a/tests/framework/testutils/options.go b/tests/framework/testutils/options.go new file mode 100644 index 000000000000..49cfb8d093c0 --- /dev/null +++ b/tests/framework/testutils/options.go @@ -0,0 +1,27 @@ +// Copyright 2022 The etcd Authors +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package testutils + +type GetOptions struct { + Serializable bool +} + +type GetOption func(*GetOptions) + +func WithSerializable() GetOption { + return func(options *GetOptions) { + options.Serializable = true + } +} diff --git a/tests/framework/testutils/util.go b/tests/framework/testutils/util.go new file mode 100644 index 000000000000..2c6564afd316 --- /dev/null +++ b/tests/framework/testutils/util.go @@ -0,0 +1,37 @@ +// Copyright 2022 The etcd Authors +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package testutils + +import ( + "fmt" + "testing" + "time" + + "go.etcd.io/etcd/client/pkg/v3/testutil" +) + +func ExecuteWithTimeout(t *testing.T, timeout time.Duration, f func()) { + donec := make(chan struct{}) + go func() { + defer close(donec) + f() + }() + + select { + case <-time.After(timeout): + testutil.FatalStack(t, fmt.Sprintf("test timed out after %v", timeout)) + case <-donec: + } +} diff --git a/tests/integration/clientv3/kv_test.go b/tests/integration/clientv3/kv_test.go index 27c7d9329ae9..fe0b5a2c45d6 100644 --- a/tests/integration/clientv3/kv_test.go +++ b/tests/integration/clientv3/kv_test.go @@ -71,7 +71,7 @@ func TestKVPutError(t *testing.T) { } } -func TestKVPut(t *testing.T) { +func TestKVPutWithLease(t *testing.T) { integration2.BeforeTest(t) clus := integration2.NewCluster(t, &integration2.ClusterConfig{Size: 3}) @@ -82,36 +82,28 @@ func TestKVPut(t *testing.T) { kv := clus.RandClient() ctx := context.TODO() - resp, err := lapi.Grant(context.Background(), 10) + lease, err := lapi.Grant(context.Background(), 10) if err != nil { t.Fatalf("failed to create lease %v", err) } - tests := []struct { - key, val string - leaseID clientv3.LeaseID - }{ - {"foo", "bar", clientv3.NoLease}, - {"hello", "world", resp.ID}, + key := "hello" + val := "world" + if _, err := kv.Put(ctx, key, val, clientv3.WithLease(lease.ID)); err != nil { + t.Fatalf("couldn't put %q (%v)", key, err) } - - for i, tt := range tests { - if _, err := kv.Put(ctx, tt.key, tt.val, clientv3.WithLease(tt.leaseID)); err != nil { - t.Fatalf("#%d: couldn't put %q (%v)", i, tt.key, err) - } - resp, err := kv.Get(ctx, tt.key) - if err != nil { - t.Fatalf("#%d: couldn't get key (%v)", i, err) - } - if len(resp.Kvs) != 1 { - t.Fatalf("#%d: expected 1 key, got %d", i, len(resp.Kvs)) - } - if !bytes.Equal([]byte(tt.val), resp.Kvs[0].Value) { - t.Errorf("#%d: val = %s, want %s", i, tt.val, resp.Kvs[0].Value) - } - if tt.leaseID != clientv3.LeaseID(resp.Kvs[0].Lease) { - t.Errorf("#%d: val = %d, want %d", i, tt.leaseID, resp.Kvs[0].Lease) - } + resp, err := kv.Get(ctx, key) + if err != nil { + t.Fatalf("couldn't get key (%v)", err) + } + if len(resp.Kvs) != 1 { + t.Fatalf("expected 1 key, got %d", len(resp.Kvs)) + } + if !bytes.Equal([]byte(val), resp.Kvs[0].Value) { + t.Errorf("val = %s, want %s", val, resp.Kvs[0].Value) + } + if lease.ID != clientv3.LeaseID(resp.Kvs[0].Lease) { + t.Errorf("val = %d, want %d", lease.ID, resp.Kvs[0].Lease) } } From def122871c5f78d2c3482d91260c887bdb8fe737 Mon Sep 17 00:00:00 2001 From: Marek Siarkowicz Date: Wed, 23 Feb 2022 16:17:01 +0100 Subject: [PATCH 150/258] tests: Use GetOptions to configure serializble get --- tests/framework/e2e.go | 2 +- tests/framework/e2e/etcdctl.go | 5 +++-- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/tests/framework/e2e.go b/tests/framework/e2e.go index 7dfc4b611106..4593506abfe6 100644 --- a/tests/framework/e2e.go +++ b/tests/framework/e2e.go @@ -64,5 +64,5 @@ func (c e2eClient) Get(key string, opts ...testutils.GetOption) (*clientv3.GetRe for _, opt := range opts { opt(&o) } - return c.EtcdctlV3.Get(key, o.Serializable) + return c.EtcdctlV3.Get(key, o) } diff --git a/tests/framework/e2e/etcdctl.go b/tests/framework/e2e/etcdctl.go index 68e1e438e4ae..b0a53afd1304 100644 --- a/tests/framework/e2e/etcdctl.go +++ b/tests/framework/e2e/etcdctl.go @@ -20,6 +20,7 @@ import ( "strings" clientv3 "go.etcd.io/etcd/client/v3" + "go.etcd.io/etcd/tests/v3/framework/testutils" ) type EtcdctlV3 struct { @@ -38,9 +39,9 @@ func (ctl *EtcdctlV3) DowngradeEnable(version string) error { return SpawnWithExpect(ctl.cmdArgs("downgrade", "enable", version), "Downgrade enable success") } -func (ctl *EtcdctlV3) Get(key string, serializable bool) (*clientv3.GetResponse, error) { +func (ctl *EtcdctlV3) Get(key string, o testutils.GetOptions) (*clientv3.GetResponse, error) { args := ctl.cmdArgs() - if serializable { + if o.Serializable { args = append(args, "--consistency", "s") } cmd, err := SpawnCmd(append(args, "get", key, "-w", "json"), nil) From 2f36e0c62b98bbe98b411f973c414ec65d62eeb7 Mon Sep 17 00:00:00 2001 From: ahrtr Date: Wed, 23 Feb 2022 09:21:55 +0800 Subject: [PATCH 151/258] Change discovery url to endpoints Currently the discovery url is just one endpoint. But actually it should be the same as the etcdctl, which means that it should be a list of endpoints. When one endpoint is down, the clientv3 can fail over to the next endpoint automatically. --- server/config/config.go | 11 +++-- server/embed/config.go | 45 ++++++++++------- server/embed/etcd.go | 4 +- server/etcdmain/config.go | 14 ++++-- server/etcdmain/etcd.go | 27 +++++----- server/etcdmain/help.go | 8 +-- .../etcdserver/api/v3discovery/discovery.go | 36 ++++++-------- server/etcdserver/bootstrap.go | 6 ++- tests/e2e/discovery_v3_test.go | 49 ++++++++++++------- tests/framework/e2e/cluster.go | 15 +++++- tests/framework/integration/cluster.go | 2 - 11 files changed, 127 insertions(+), 90 deletions(-) diff --git a/server/config/config.go b/server/config/config.go index 8f901444211d..75d7df6c4a68 100644 --- a/server/config/config.go +++ b/server/config/config.go @@ -37,10 +37,9 @@ import ( type ServerConfig struct { Name string - EnableV2Discovery bool - DiscoveryURL string - DiscoveryProxy string - DiscoveryCfg v3discovery.DiscoveryConfig + DiscoveryURL string + DiscoveryProxy string + DiscoveryCfg v3discovery.DiscoveryConfig ClientURLs types.URLs PeerURLs types.URLs @@ -309,7 +308,9 @@ func (c *ServerConfig) WALDir() string { func (c *ServerConfig) SnapDir() string { return filepath.Join(c.MemberDir(), "snap") } -func (c *ServerConfig) ShouldDiscover() bool { return c.DiscoveryURL != "" } +func (c *ServerConfig) ShouldDiscover() bool { + return c.DiscoveryURL != "" || len(c.DiscoveryCfg.Endpoints) > 0 +} // ReqTimeout returns timeout for request to finish. func (c *ServerConfig) ReqTimeout() time.Duration { diff --git a/server/embed/config.go b/server/embed/config.go index 778d2b1cbc26..e6f9e3a32344 100644 --- a/server/embed/config.go +++ b/server/embed/config.go @@ -95,8 +95,6 @@ const ( // It's enabled by default. DefaultStrictReconfigCheck = true - DefaultEnableV2Discovery = true - // maxElectionMs specifies the maximum value of election timeout. // More details are listed in ../Documentation/tuning.md#time-parameters. maxElectionMs = 50000 @@ -106,7 +104,7 @@ const ( var ( ErrConflictBootstrapFlags = fmt.Errorf("multiple discovery or bootstrap flags are set. " + - "Choose one of \"initial-cluster\", \"discovery\" or \"discovery-srv\"") + "Choose one of \"initial-cluster\", \"discovery\", \"discovery-endpoints\" or \"discovery-srv\"") ErrUnsetAdvertiseClientURLsFlag = fmt.Errorf("--advertise-client-urls is required when --listen-client-urls is set explicitly") ErrLogRotationInvalidLogOutput = fmt.Errorf("--log-outputs requires a single file path when --log-rotate-config-json is defined") @@ -227,9 +225,8 @@ type Config struct { DNSClusterServiceName string `json:"discovery-srv-name"` Dproxy string `json:"discovery-proxy"` - EnableV2Discovery bool `json:"enable-v2-discovery"` - Durl string `json:"discovery"` - DiscoveryCfg v3discovery.DiscoveryConfig `json:"discovery-config"` + Durl string `json:"discovery"` + DiscoveryCfg v3discovery.DiscoveryConfig `json:"discovery-config"` InitialCluster string `json:"initial-cluster"` InitialClusterToken string `json:"initial-cluster-token"` @@ -518,7 +515,6 @@ func NewConfig() *Config { V2Deprecation: config.V2_DEPR_DEFAULT, - EnableV2Discovery: DefaultEnableV2Discovery, DiscoveryCfg: v3discovery.DiscoveryConfig{ DialTimeout: DefaultDiscoveryDialTimeout, RequestTimeOut: DefaultDiscoveryRequestTimeOut, @@ -606,8 +602,8 @@ func (cfg *configYAML) configFromFile(path string) error { cfg.HostWhitelist = uv.Values } - // If a discovery flag is set, clear default initial cluster set by InitialClusterFromName - if (cfg.Durl != "" || cfg.DNSCluster != "") && cfg.InitialCluster == defaultInitialCluster { + // If a discovery or discovery-endpoints flag is set, clear default initial cluster set by InitialClusterFromName + if (cfg.Durl != "" || cfg.DNSCluster != "" || len(cfg.DiscoveryCfg.Endpoints) > 0) && cfg.InitialCluster == defaultInitialCluster { cfg.InitialCluster = "" } if cfg.ClusterState == "" { @@ -674,7 +670,7 @@ func (cfg *Config) Validate() error { } // Check if conflicting flags are passed. nSet := 0 - for _, v := range []bool{cfg.Durl != "", cfg.InitialCluster != "", cfg.DNSCluster != ""} { + for _, v := range []bool{cfg.Durl != "", cfg.InitialCluster != "", cfg.DNSCluster != "", len(cfg.DiscoveryCfg.Endpoints) > 0} { if v { nSet++ } @@ -690,18 +686,24 @@ func (cfg *Config) Validate() error { // Check if both v2 discovery and v3 discovery flags are passed. v2discoveryFlagsExist := cfg.Dproxy != "" - v3discoveryFlagsExist := cfg.DiscoveryCfg.CertFile != "" || + v3discoveryFlagsExist := len(cfg.DiscoveryCfg.Endpoints) > 0 || + cfg.DiscoveryCfg.Token != "" || + cfg.DiscoveryCfg.CertFile != "" || cfg.DiscoveryCfg.KeyFile != "" || cfg.DiscoveryCfg.TrustedCAFile != "" || cfg.DiscoveryCfg.User != "" || cfg.DiscoveryCfg.Password != "" - if cfg.EnableV2Discovery && v3discoveryFlagsExist { - return errors.New("v2 discovery is enabled, but some v3 discovery " + - "settings (discovery-cert, discovery-key, discovery-cacert, " + - "discovery-user, discovery-password) are set") + + if v2discoveryFlagsExist && v3discoveryFlagsExist { + return errors.New("both v2 discovery settings (discovery, discovery-proxy) " + + "and v3 discovery settings (discovery-token, discovery-endpoints, discovery-cert, " + + "discovery-key, discovery-cacert, discovery-user, discovery-password) are set") } - if !cfg.EnableV2Discovery && v2discoveryFlagsExist { - return errors.New("v3 discovery is enabled, but --discovery-proxy is set") + + // If one of `discovery-token` and `discovery-endpoints` is provided, + // then the other one must be provided as well. + if (cfg.DiscoveryCfg.Token != "") != (len(cfg.DiscoveryCfg.Endpoints) > 0) { + return errors.New("both --discovery-token and --discovery-endpoints must be set") } if cfg.TickMs == 0 { @@ -753,11 +755,18 @@ func (cfg *Config) PeerURLsMapAndToken(which string) (urlsmap types.URLsMap, tok switch { case cfg.Durl != "": urlsmap = types.URLsMap{} - // If using discovery, generate a temporary cluster based on + // If using v2 discovery, generate a temporary cluster based on // self's advertised peer URLs urlsmap[cfg.Name] = cfg.APUrls token = cfg.Durl + case len(cfg.DiscoveryCfg.Endpoints) > 0: + urlsmap = types.URLsMap{} + // If using v3 discovery, generate a temporary cluster based on + // self's advertised peer URLs + urlsmap[cfg.Name] = cfg.APUrls + token = cfg.DiscoveryCfg.Token + case cfg.DNSCluster != "": clusterStrs, cerr := cfg.GetDNSClusterNames() lg := cfg.logger diff --git a/server/embed/etcd.go b/server/embed/etcd.go index 46069b63900d..c43adca6be12 100644 --- a/server/embed/etcd.go +++ b/server/embed/etcd.go @@ -26,6 +26,7 @@ import ( "runtime" "sort" "strconv" + "strings" "sync" "time" @@ -175,7 +176,6 @@ func StartEtcd(inCfg *Config) (e *Etcd, err error) { MaxWALFiles: cfg.MaxWalFiles, InitialPeerURLsMap: urlsmap, InitialClusterToken: token, - EnableV2Discovery: cfg.EnableV2Discovery, DiscoveryURL: cfg.Durl, DiscoveryProxy: cfg.Dproxy, DiscoveryCfg: cfg.DiscoveryCfg, @@ -348,6 +348,8 @@ func print(lg *zap.Logger, ec Config, sc config.ServerConfig, memberInitialized zap.String("discovery-url", sc.DiscoveryURL), zap.String("discovery-proxy", sc.DiscoveryProxy), + zap.String("discovery-token", sc.DiscoveryCfg.Token), + zap.String("discovery-endpoints", strings.Join(sc.DiscoveryCfg.Endpoints, ",")), zap.String("discovery-dial-timeout", sc.DiscoveryCfg.DialTimeout.String()), zap.String("discovery-request-timeout", sc.DiscoveryCfg.RequestTimeOut.String()), zap.String("discovery-keepalive-time", sc.DiscoveryCfg.KeepAliveTime.String()), diff --git a/server/etcdmain/config.go b/server/etcdmain/config.go index b837b9d42550..dc78e1d532b9 100644 --- a/server/etcdmain/config.go +++ b/server/etcdmain/config.go @@ -185,10 +185,16 @@ func newConfig() *config { "advertise-client-urls", "List of this member's client URLs to advertise to the public.", ) - fs.BoolVar(&cfg.ec.EnableV2Discovery, "enable-v2-discovery", cfg.ec.EnableV2Discovery, "Enable to bootstrap the cluster using v2 discovery. Will be deprecated in v3.7, and be decommissioned in v3.8.") - fs.StringVar(&cfg.ec.Durl, "discovery", cfg.ec.Durl, "Discovery URL used to bootstrap the cluster.") + + fs.StringVar(&cfg.ec.Durl, "discovery", cfg.ec.Durl, "Discovery URL used to bootstrap the cluster for v2 discovery. Will be deprecated in v3.7, and be decommissioned in v3.8.") fs.Var(cfg.cf.fallback, "discovery-fallback", fmt.Sprintf("Valid values include %q", cfg.cf.fallback.Valids())) + fs.Var( + flags.NewUniqueStringsValue(""), + "discovery-endpoints", + "V3 discovery: List of gRPC endpoints of the discovery service.", + ) + fs.StringVar(&cfg.ec.DiscoveryCfg.Token, "discovery-token", "", "V3 discovery: discovery token for the etcd cluster to be bootstrapped.") fs.DurationVar(&cfg.ec.DiscoveryCfg.DialTimeout, "discovery-dial-timeout", cfg.ec.DiscoveryCfg.DialTimeout, "V3 discovery: dial timeout for client connections.") fs.DurationVar(&cfg.ec.DiscoveryCfg.RequestTimeOut, "discovery-request-timeout", cfg.ec.DiscoveryCfg.RequestTimeOut, "V3 discovery: timeout for discovery requests (excluding dial timeout).") fs.DurationVar(&cfg.ec.DiscoveryCfg.KeepAliveTime, "discovery-keepalive-time", cfg.ec.DiscoveryCfg.KeepAliveTime, "V3 discovery: keepalive time for client connections.") @@ -408,6 +414,8 @@ func (cfg *config) configFromCmdLine() error { cfg.ec.ACUrls = flags.UniqueURLsFromFlag(cfg.cf.flagSet, "advertise-client-urls") cfg.ec.ListenMetricsUrls = flags.UniqueURLsFromFlag(cfg.cf.flagSet, "listen-metrics-urls") + cfg.ec.DiscoveryCfg.Endpoints = flags.UniqueStringsFromFlag(cfg.cf.flagSet, "discovery-endpoints") + cfg.ec.CORS = flags.UniqueURLsMapFromFlag(cfg.cf.flagSet, "cors") cfg.ec.HostWhitelist = flags.UniqueStringsMapFromFlag(cfg.cf.flagSet, "host-whitelist") @@ -428,7 +436,7 @@ func (cfg *config) configFromCmdLine() error { } // disable default initial-cluster if discovery is set - if (cfg.ec.Durl != "" || cfg.ec.DNSCluster != "" || cfg.ec.DNSClusterServiceName != "") && !flags.IsSet(cfg.cf.flagSet, "initial-cluster") { + if (cfg.ec.Durl != "" || cfg.ec.DNSCluster != "" || cfg.ec.DNSClusterServiceName != "" || len(cfg.ec.DiscoveryCfg.Endpoints) > 0) && !flags.IsSet(cfg.cf.flagSet, "initial-cluster") { cfg.ec.InitialCluster = "" } diff --git a/server/etcdmain/etcd.go b/server/etcdmain/etcd.go index 5d78e72029e6..5ab2680d7a6f 100644 --- a/server/etcdmain/etcd.go +++ b/server/etcdmain/etcd.go @@ -196,8 +196,8 @@ func startEtcdOrProxyV2(args []string) { if types.URLs(cfg.ec.APUrls).String() == embed.DefaultInitialAdvertisePeerURLs { lg.Warn("forgot to set --initial-advertise-peer-urls?") } - if cfg.ec.InitialCluster == cfg.ec.InitialClusterFromName(cfg.ec.Name) && len(cfg.ec.Durl) == 0 { - lg.Warn("--discovery flag is not set") + if cfg.ec.InitialCluster == cfg.ec.InitialClusterFromName(cfg.ec.Name) && len(cfg.ec.Durl) == 0 && len(cfg.ec.DiscoveryCfg.Endpoints) == 0 { + lg.Warn("V2 discovery settings (i.e., --discovery) or v3 discovery settings (i.e., --discovery-token, --discovery-endpoints) are not set") } os.Exit(1) } @@ -287,7 +287,7 @@ func startProxy(cfg *config) error { b, err := os.ReadFile(clusterfile) switch { case err == nil: - if cfg.ec.Durl != "" { + if cfg.ec.Durl != "" || len(cfg.ec.DiscoveryCfg.Endpoints) > 0 { lg.Warn( "discovery token ignored since the proxy has already been initialized; valid cluster file found", zap.String("cluster-file", clusterfile), @@ -318,21 +318,22 @@ func startProxy(cfg *config) error { return fmt.Errorf("error setting up initial cluster: %v", err) } + var s string if cfg.ec.Durl != "" { - var s string - if cfg.ec.EnableV2Discovery { - lg.Warn("V2 discovery is deprecated!") - s, err = v2discovery.GetCluster(lg, cfg.ec.Durl, cfg.ec.Dproxy) - } else { - s, err = v3discovery.GetCluster(lg, cfg.ec.Durl, &cfg.ec.DiscoveryCfg) - } - if err != nil { - return err - } + lg.Warn("V2 discovery is deprecated!") + s, err = v2discovery.GetCluster(lg, cfg.ec.Durl, cfg.ec.Dproxy) + } else if len(cfg.ec.DiscoveryCfg.Endpoints) > 0 { + s, err = v3discovery.GetCluster(lg, &cfg.ec.DiscoveryCfg) + } + if err != nil { + return err + } + if s != "" { if urlsmap, err = types.NewURLsMap(s); err != nil { return err } } + peerURLs = urlsmap.URLs() lg.Info("proxy using peer URLS", zap.Strings("peer-urls", peerURLs)) diff --git a/server/etcdmain/help.go b/server/etcdmain/help.go index 84b683b0dc7e..6600a4a421a8 100644 --- a/server/etcdmain/help.go +++ b/server/etcdmain/help.go @@ -104,10 +104,12 @@ Clustering: --advertise-client-urls 'http://localhost:2379' List of this member's client URLs to advertise to the public. The client URLs advertised should be accessible to machines that talk to etcd cluster. etcd client libraries parse these URLs to connect to the cluster. - --enable-v2-discovery 'true' - Enable to bootstrap the cluster using v2 discovery. Will be deprecated in v3.7, and be decommissioned in v3.8. --discovery '' - Discovery URL used to bootstrap the cluster. + Discovery URL used to bootstrap the cluster for v2 discovery. Will be deprecated in v3.7, and be decommissioned in v3.8. + --discovery-token '' + V3 discovery: discovery token for the etcd cluster to be bootstrapped. + --discovery-endpoints '' + V3 discovery: List of gRPC endpoints of the discovery service. --discovery-dial-timeout '2s' V3 discovery: dial timeout for client connections. --discovery-request-timeout '5s' diff --git a/server/etcdserver/api/v3discovery/discovery.go b/server/etcdserver/api/v3discovery/discovery.go index 7fcaadf3aeb3..cb91d6ed7c9f 100644 --- a/server/etcdserver/api/v3discovery/discovery.go +++ b/server/etcdserver/api/v3discovery/discovery.go @@ -22,7 +22,6 @@ import ( "errors" "math" - "net/url" "path" "sort" "strconv" @@ -56,7 +55,8 @@ var ( ) type DiscoveryConfig struct { - Url string `json:"discovery"` + Token string `json:"discovery-token"` + Endpoints []string `json:"discovery-endpoints"` DialTimeout time.Duration `json:"discovery-dial-timeout"` RequestTimeOut time.Duration `json:"discovery-request-timeout"` @@ -110,10 +110,10 @@ func getMemberKey(cluster, memberId string) string { return path.Join(getMemberKeyPrefix(cluster), memberId) } -// GetCluster will connect to the discovery service at the given url and +// GetCluster will connect to the discovery service at the given endpoints and // retrieve a string describing the cluster -func GetCluster(lg *zap.Logger, dUrl string, cfg *DiscoveryConfig) (cs string, rerr error) { - d, err := newDiscovery(lg, dUrl, cfg, 0) +func GetCluster(lg *zap.Logger, cfg *DiscoveryConfig) (cs string, rerr error) { + d, err := newDiscovery(lg, cfg, 0) if err != nil { return "", err } @@ -137,15 +137,15 @@ func GetCluster(lg *zap.Logger, dUrl string, cfg *DiscoveryConfig) (cs string, r return d.getCluster() } -// JoinCluster will connect to the discovery service at the given url, and +// JoinCluster will connect to the discovery service at the endpoints, and // register the server represented by the given id and config to the cluster. // The parameter `config` is supposed to be in the format "memberName=peerURLs", // such as "member1=http://127.0.0.1:2380". // // The final returned string has the same format as "--initial-cluster", such as // "infra1=http://127.0.0.1:12380,infra2=http://127.0.0.1:22380,infra3=http://127.0.0.1:32380". -func JoinCluster(lg *zap.Logger, durl string, cfg *DiscoveryConfig, id types.ID, config string) (cs string, rerr error) { - d, err := newDiscovery(lg, durl, cfg, id) +func JoinCluster(lg *zap.Logger, cfg *DiscoveryConfig, id types.ID, config string) (cs string, rerr error) { + d, err := newDiscovery(lg, cfg, id) if err != nil { return "", err } @@ -175,26 +175,19 @@ type discovery struct { memberId types.ID c *clientv3.Client retries uint - durl string cfg *DiscoveryConfig clock clockwork.Clock } -func newDiscovery(lg *zap.Logger, durl string, dcfg *DiscoveryConfig, id types.ID) (*discovery, error) { +func newDiscovery(lg *zap.Logger, dcfg *DiscoveryConfig, id types.ID) (*discovery, error) { if lg == nil { lg = zap.NewNop() } - u, err := url.Parse(durl) - if err != nil { - return nil, err - } - token := u.Path - u.Path = "" - lg = lg.With(zap.String("discovery-url", durl)) - cfg, err := newClientCfg(dcfg, u.String(), lg) + lg = lg.With(zap.String("discovery-token", dcfg.Token), zap.String("discovery-endpoints", strings.Join(dcfg.Endpoints, ","))) + cfg, err := newClientCfg(dcfg, lg) if err != nil { return nil, err } @@ -205,10 +198,9 @@ func newDiscovery(lg *zap.Logger, durl string, dcfg *DiscoveryConfig, id types.I } return &discovery{ lg: lg, - clusterToken: token, + clusterToken: dcfg.Token, memberId: id, c: c, - durl: u.String(), cfg: dcfg, clock: clockwork.NewRealClock(), }, nil @@ -216,7 +208,7 @@ func newDiscovery(lg *zap.Logger, durl string, dcfg *DiscoveryConfig, id types.I // The following function follows the same logic as etcdctl, refer to // https://github.com/etcd-io/etcd/blob/f9a8c49c695b098d66a07948666664ea10d01a82/etcdctl/ctlv3/command/global.go#L191-L250 -func newClientCfg(dcfg *DiscoveryConfig, dUrl string, lg *zap.Logger) (*clientv3.Config, error) { +func newClientCfg(dcfg *DiscoveryConfig, lg *zap.Logger) (*clientv3.Config, error) { var cfgtls *transport.TLSInfo if dcfg.CertFile != "" || dcfg.KeyFile != "" || dcfg.TrustedCAFile != "" { @@ -229,7 +221,7 @@ func newClientCfg(dcfg *DiscoveryConfig, dUrl string, lg *zap.Logger) (*clientv3 } cfg := &clientv3.Config{ - Endpoints: []string{dUrl}, + Endpoints: dcfg.Endpoints, DialTimeout: dcfg.DialTimeout, DialKeepAliveTime: dcfg.KeepAliveTime, DialKeepAliveTimeout: dcfg.KeepAliveTimeout, diff --git a/server/etcdserver/bootstrap.go b/server/etcdserver/bootstrap.go index 76b888ec3e76..e0b747f1d48b 100644 --- a/server/etcdserver/bootstrap.go +++ b/server/etcdserver/bootstrap.go @@ -329,10 +329,12 @@ func bootstrapNewClusterNoWAL(cfg config.ServerConfig, prt http.RoundTripper) (* } if cfg.ShouldDiscover() { var str string - if cfg.EnableV2Discovery { + if cfg.DiscoveryURL != "" { + cfg.Logger.Warn("V2 discovery is deprecated!") str, err = v2discovery.JoinCluster(cfg.Logger, cfg.DiscoveryURL, cfg.DiscoveryProxy, m.ID, cfg.InitialPeerURLsMap.String()) } else { - str, err = v3discovery.JoinCluster(cfg.Logger, cfg.DiscoveryURL, &cfg.DiscoveryCfg, m.ID, cfg.InitialPeerURLsMap.String()) + cfg.Logger.Info("Bootstrapping cluster using v3 discovery.") + str, err = v3discovery.JoinCluster(cfg.Logger, &cfg.DiscoveryCfg, m.ID, cfg.InitialPeerURLsMap.String()) } if err != nil { return nil, &DiscoveryError{Op: "join", Err: err} diff --git a/tests/e2e/discovery_v3_test.go b/tests/e2e/discovery_v3_test.go index efc50656340f..45c87e5a96ea 100644 --- a/tests/e2e/discovery_v3_test.go +++ b/tests/e2e/discovery_v3_test.go @@ -23,24 +23,34 @@ import ( "go.etcd.io/etcd/tests/v3/framework/e2e" ) -func TestClusterOf1UsingV3Discovery(t *testing.T) { - testClusterUsingV3Discovery(t, 1, e2e.ClientNonTLS, false) +func TestClusterOf1UsingV3Discovery_1endpoint(t *testing.T) { + testClusterUsingV3Discovery(t, 1, 1, e2e.ClientNonTLS, false) } -func TestClusterOf3UsingV3Discovery(t *testing.T) { - testClusterUsingV3Discovery(t, 3, e2e.ClientTLS, true) +func TestClusterOf3UsingV3Discovery_1endpoint(t *testing.T) { + testClusterUsingV3Discovery(t, 1, 3, e2e.ClientTLS, true) } -func TestTLSClusterOf3UsingV3Discovery(t *testing.T) { - testClusterUsingV3Discovery(t, 5, e2e.ClientTLS, false) +func TestTLSClusterOf5UsingV3Discovery_1endpoint(t *testing.T) { + testClusterUsingV3Discovery(t, 1, 5, e2e.ClientTLS, false) } -func testClusterUsingV3Discovery(t *testing.T, clusterSize int, clientTlsType e2e.ClientConnType, isClientAutoTls bool) { +func TestClusterOf1UsingV3Discovery_3endpoints(t *testing.T) { + testClusterUsingV3Discovery(t, 3, 1, e2e.ClientNonTLS, false) +} +func TestClusterOf3UsingV3Discovery_3endpoints(t *testing.T) { + testClusterUsingV3Discovery(t, 3, 3, e2e.ClientTLS, true) +} +func TestTLSClusterOf5UsingV3Discovery_3endpoints(t *testing.T) { + testClusterUsingV3Discovery(t, 3, 5, e2e.ClientTLS, false) +} + +func testClusterUsingV3Discovery(t *testing.T, discoveryClusterSize, targetClusterSize int, clientTlsType e2e.ClientConnType, isClientAutoTls bool) { e2e.BeforeTest(t) // step 1: start the discovery service ds, err := e2e.NewEtcdProcessCluster(t, &e2e.EtcdProcessClusterConfig{ InitialToken: "new", BasePort: 2000, - ClusterSize: 1, + ClusterSize: discoveryClusterSize, ClientTLS: clientTlsType, IsClientAutoTLS: isClientAutoTls, }) @@ -50,15 +60,15 @@ func testClusterUsingV3Discovery(t *testing.T, clusterSize int, clientTlsType e2 defer ds.Close() // step 2: configure the cluster size - clusterToken := "8A591FAB-1D72-41FA-BDF2-A27162FDA1E0" - configSizeKey := fmt.Sprintf("/_etcd/registry/%s/_config/size", clusterToken) - configSizeValStr := strconv.Itoa(clusterSize) + discoveryToken := "8A591FAB-1D72-41FA-BDF2-A27162FDA1E0" + configSizeKey := fmt.Sprintf("/_etcd/registry/%s/_config/size", discoveryToken) + configSizeValStr := strconv.Itoa(targetClusterSize) if err := ctlV3Put(ctlCtx{epc: ds}, configSizeKey, configSizeValStr, ""); err != nil { t.Errorf("failed to configure cluster size to discovery serivce, error: %v", err) } // step 3: start the etcd cluster - epc, err := bootstrapEtcdClusterUsingV3Discovery(t, ds.EndpointsV3()[0], clusterToken, clusterSize, clientTlsType, isClientAutoTls) + epc, err := bootstrapEtcdClusterUsingV3Discovery(t, ds.EndpointsV3(), discoveryToken, targetClusterSize, clientTlsType, isClientAutoTls) if err != nil { t.Fatalf("could not start etcd process cluster (%v)", err) } @@ -74,26 +84,27 @@ func testClusterUsingV3Discovery(t *testing.T, clusterSize int, clientTlsType e2 } } -func bootstrapEtcdClusterUsingV3Discovery(t *testing.T, durl string, clusterToken string, clusterSize int, clientTlsType e2e.ClientConnType, isClientAutoTls bool) (*e2e.EtcdProcessCluster, error) { +func bootstrapEtcdClusterUsingV3Discovery(t *testing.T, discoveryEndpoints []string, discoveryToken string, clusterSize int, clientTlsType e2e.ClientConnType, isClientAutoTls bool) (*e2e.EtcdProcessCluster, error) { // cluster configuration cfg := &e2e.EtcdProcessClusterConfig{ - BasePort: 3000, - ClusterSize: clusterSize, - IsPeerTLS: true, - IsPeerAutoTLS: true, - Discovery: fmt.Sprintf("%s/%s", durl, clusterToken), + BasePort: 3000, + ClusterSize: clusterSize, + IsPeerTLS: true, + IsPeerAutoTLS: true, + DiscoveryToken: discoveryToken, + DiscoveryEndpoints: discoveryEndpoints, } // initialize the cluster epc, err := e2e.InitEtcdProcessCluster(t, cfg) if err != nil { + t.Fatalf("could not initialize etcd cluster (%v)", err) return epc, err } // populate discovery related security configuration for _, ep := range epc.Procs { epCfg := ep.Config() - epCfg.Args = append(epCfg.Args, "--enable-v2-discovery=false") if clientTlsType == e2e.ClientTLS { if isClientAutoTls { diff --git a/tests/framework/e2e/cluster.go b/tests/framework/e2e/cluster.go index e1de1951047f..64be2f39caa5 100644 --- a/tests/framework/e2e/cluster.go +++ b/tests/framework/e2e/cluster.go @@ -170,7 +170,11 @@ type EtcdProcessClusterConfig struct { V2deprecation string RollingStart bool - Discovery string + + Discovery string // v2 discovery + + DiscoveryEndpoints []string // v3 discovery + DiscoveryToken string } // NewEtcdProcessCluster launches a new cluster from etcd processes, returning @@ -348,7 +352,7 @@ func (cfg *EtcdProcessClusterConfig) EtcdServerProcessConfigs(tb testing.TB) []* } } - if cfg.Discovery == "" { + if cfg.Discovery == "" && len(cfg.DiscoveryEndpoints) == 0 { for i := range etcdCfgs { initialClusterArgs := []string{"--initial-cluster", strings.Join(initialCluster, ",")} etcdCfgs[i].InitialCluster = strings.Join(initialCluster, ",") @@ -356,6 +360,13 @@ func (cfg *EtcdProcessClusterConfig) EtcdServerProcessConfigs(tb testing.TB) []* } } + if len(cfg.DiscoveryEndpoints) > 0 { + for i := range etcdCfgs { + etcdCfgs[i].Args = append(etcdCfgs[i].Args, fmt.Sprintf("--discovery-token=%s", cfg.DiscoveryToken)) + etcdCfgs[i].Args = append(etcdCfgs[i].Args, fmt.Sprintf("--discovery-endpoints=%s", strings.Join(cfg.DiscoveryEndpoints, ","))) + } + } + return etcdCfgs } diff --git a/tests/framework/integration/cluster.go b/tests/framework/integration/cluster.go index c1aa0f275089..49723b50c139 100644 --- a/tests/framework/integration/cluster.go +++ b/tests/framework/integration/cluster.go @@ -588,8 +588,6 @@ func MustNewMember(t testutil.TB, mcfg MemberConfig) *Member { peerScheme := SchemeFromTLSInfo(mcfg.PeerTLS) clientScheme := SchemeFromTLSInfo(mcfg.ClientTLS) - m.EnableV2Discovery = embed.DefaultEnableV2Discovery - pln := newLocalListener(t) m.PeerListeners = []net.Listener{pln} m.PeerURLs, err = types.NewURLs([]string{peerScheme + "://" + pln.Addr().String()}) From 6f03dc7416f4a353ab8a1e6e714c0b591fb8920a Mon Sep 17 00:00:00 2001 From: ahrtr Date: Tue, 22 Feb 2022 17:13:45 +0800 Subject: [PATCH 152/258] update 3.5 changelog to cover the PR of always printing raft_term in decimal when displaying member list in json --- CHANGELOG/CHANGELOG-3.5.md | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/CHANGELOG/CHANGELOG-3.5.md b/CHANGELOG/CHANGELOG-3.5.md index dc6ce5d0ef90..526e86147c0a 100644 --- a/CHANGELOG/CHANGELOG-3.5.md +++ b/CHANGELOG/CHANGELOG-3.5.md @@ -13,8 +13,13 @@ The minimum recommended etcd versions to run in **production** are 3.3.18+, 3.4. - Fix [Provide a better liveness probe for when etcd runs as a Kubernetes pod](https://github.com/etcd-io/etcd/pull/13706) ### package `client/pkg/v3` + - [Trim the suffix dot from the target](https://github.com/etcd-io/etcd/pull/13714) in SRV records returned by DNS lookup +### etcdctl v3 + +- [Always print the raft_term in decimal](https://github.com/etcd-io/etcd/pull/13727) when displaying member list in json. +
## [v3.5.2](https://github.com/etcd-io/etcd/releases/tag/v3.5.2) (2022-02-01) From 65be41dd6e35b425971f866970d2c3806da8bcf6 Mon Sep 17 00:00:00 2001 From: Marek Siarkowicz Date: Wed, 23 Feb 2022 16:41:21 +0100 Subject: [PATCH 153/258] tests: Rename framework to runner and document the runners --- tests/common/e2e_test.go | 2 +- tests/common/integration_test.go | 2 +- tests/common/kv_test.go | 4 ++-- tests/common/main_test.go | 4 ++-- tests/framework/e2e.go | 8 ++++---- tests/framework/framework.go | 9 ++++++--- tests/framework/integration.go | 8 ++++---- tests/framework/interface.go | 2 +- tests/framework/{default.go => unit.go} | 12 ++++++------ 9 files changed, 27 insertions(+), 24 deletions(-) rename tests/framework/{default.go => unit.go} (79%) diff --git a/tests/common/e2e_test.go b/tests/common/e2e_test.go index e0f29ce399ce..1debbafaa00f 100644 --- a/tests/common/e2e_test.go +++ b/tests/common/e2e_test.go @@ -20,5 +20,5 @@ package common import "go.etcd.io/etcd/tests/v3/framework" func init() { - testFramework = framework.RunE2eTests + testRunner = framework.E2eTestRunner } diff --git a/tests/common/integration_test.go b/tests/common/integration_test.go index 7c7ccc2244ca..a2588a9cce5e 100644 --- a/tests/common/integration_test.go +++ b/tests/common/integration_test.go @@ -22,5 +22,5 @@ import ( ) func init() { - testFramework = framework.RunIntegrationTests + testRunner = framework.IntegrationTestRunner } diff --git a/tests/common/kv_test.go b/tests/common/kv_test.go index 868fa3f3efd7..b6a37fe5009b 100644 --- a/tests/common/kv_test.go +++ b/tests/common/kv_test.go @@ -22,8 +22,8 @@ import ( ) func TestKVPut(t *testing.T) { - testFramework.BeforeTest(t) - clus := testFramework.NewCluster(t) + testRunner.BeforeTest(t) + clus := testRunner.NewCluster(t) defer clus.Close() cc := clus.Client() diff --git a/tests/common/main_test.go b/tests/common/main_test.go index b3987e1b5913..73dbae69d47d 100644 --- a/tests/common/main_test.go +++ b/tests/common/main_test.go @@ -20,8 +20,8 @@ import ( "go.etcd.io/etcd/tests/v3/framework" ) -var testFramework = framework.TestFramework +var testRunner = framework.UnitTestRunner func TestMain(m *testing.M) { - testFramework.TestMain(m) + testRunner.TestMain(m) } diff --git a/tests/framework/e2e.go b/tests/framework/e2e.go index 4593506abfe6..094628a3761a 100644 --- a/tests/framework/e2e.go +++ b/tests/framework/e2e.go @@ -24,9 +24,9 @@ import ( "go.etcd.io/etcd/tests/v3/framework/testutils" ) -type e2eFramework struct{} +type e2eRunner struct{} -func (e e2eFramework) TestMain(m *testing.M) { +func (e e2eRunner) TestMain(m *testing.M) { e2e.InitFlags() v := m.Run() if v == 0 && testutil.CheckLeakedGoroutine() { @@ -35,11 +35,11 @@ func (e e2eFramework) TestMain(m *testing.M) { os.Exit(v) } -func (e e2eFramework) BeforeTest(t testing.TB) { +func (e e2eRunner) BeforeTest(t testing.TB) { e2e.BeforeTest(t) } -func (e e2eFramework) NewCluster(t testing.TB) Cluster { +func (e e2eRunner) NewCluster(t testing.TB) Cluster { epc, err := e2e.NewEtcdProcessCluster(t, e2e.ConfigStandalone(*e2e.NewConfigAutoTLS())) if err != nil { t.Fatalf("could not start etcd integrationCluster: %s", err) diff --git a/tests/framework/framework.go b/tests/framework/framework.go index d07968e738e7..5f41ba6f56ed 100644 --- a/tests/framework/framework.go +++ b/tests/framework/framework.go @@ -15,7 +15,10 @@ package framework var ( - TestFramework testFramework = noFrameworkSelected{} - RunE2eTests testFramework = e2eFramework{} - RunIntegrationTests testFramework = integrationFramework{} + // UnitTestRunner only runs in `--short` mode, will fail otherwise. Attempts in cluster creation will result in tests being skipped. + UnitTestRunner testRunner = unitRunner{} + // E2eTestRunner runs etcd and etcdctl binaries in a separate process. + E2eTestRunner = e2eRunner{} + // IntegrationTestRunner runs etcdserver.EtcdServer in separate goroutine and uses client libraries to communicate. + IntegrationTestRunner = integrationRunner{} ) diff --git a/tests/framework/integration.go b/tests/framework/integration.go index 46eb83d83168..b37111aa4248 100644 --- a/tests/framework/integration.go +++ b/tests/framework/integration.go @@ -24,17 +24,17 @@ import ( "go.etcd.io/etcd/tests/v3/framework/testutils" ) -type integrationFramework struct{} +type integrationRunner struct{} -func (e integrationFramework) TestMain(m *testing.M) { +func (e integrationRunner) TestMain(m *testing.M) { testutil.MustTestMainWithLeakDetection(m) } -func (e integrationFramework) BeforeTest(t testing.TB) { +func (e integrationRunner) BeforeTest(t testing.TB) { integration.BeforeTest(t) } -func (e integrationFramework) NewCluster(t testing.TB) Cluster { +func (e integrationRunner) NewCluster(t testing.TB) Cluster { return &integrationCluster{ Cluster: integration.NewCluster(t, &integration.ClusterConfig{Size: 1}), t: t, diff --git a/tests/framework/interface.go b/tests/framework/interface.go index 273ed453224a..9eb9e34c28e5 100644 --- a/tests/framework/interface.go +++ b/tests/framework/interface.go @@ -21,7 +21,7 @@ import ( "go.etcd.io/etcd/tests/v3/framework/testutils" ) -type testFramework interface { +type testRunner interface { TestMain(m *testing.M) BeforeTest(testing.TB) NewCluster(testing.TB) Cluster diff --git a/tests/framework/default.go b/tests/framework/unit.go similarity index 79% rename from tests/framework/default.go rename to tests/framework/unit.go index d34dc64622cc..231e0f7df496 100644 --- a/tests/framework/default.go +++ b/tests/framework/unit.go @@ -23,11 +23,11 @@ import ( "go.etcd.io/etcd/client/pkg/v3/testutil" ) -type noFrameworkSelected struct{} +type unitRunner struct{} -var _ testFramework = (*noFrameworkSelected)(nil) +var _ testRunner = (*unitRunner)(nil) -func (e noFrameworkSelected) TestMain(m *testing.M) { +func (e unitRunner) TestMain(m *testing.M) { flag.Parse() if !testing.Short() { fmt.Println(`No test mode selected, please selected either e2e mode with "--tags e2e" or integration mode with "--tags integration"`) @@ -35,10 +35,10 @@ func (e noFrameworkSelected) TestMain(m *testing.M) { } } -func (e noFrameworkSelected) BeforeTest(t testing.TB) { - testutil.SkipTestIfShortMode(t, "Cannot create clusters in --short tests") +func (e unitRunner) BeforeTest(t testing.TB) { } -func (e noFrameworkSelected) NewCluster(t testing.TB) Cluster { +func (e unitRunner) NewCluster(t testing.TB) Cluster { + testutil.SkipTestIfShortMode(t, "Cannot create clusters in --short tests") return nil } From 9b6681fffdaee59b74cc70fd67bd46e78e8ad43b Mon Sep 17 00:00:00 2001 From: ahrtr Date: Mon, 21 Feb 2022 13:11:39 +0800 Subject: [PATCH 154/258] add failover test cases --- tests/framework/integration/cluster.go | 8 ++ tests/integration/v3_failover_test.go | 173 +++++++++++++++++++++++++ tests/integration/v3_kv_test.go | 14 ++ 3 files changed, 195 insertions(+) create mode 100644 tests/integration/v3_failover_test.go diff --git a/tests/framework/integration/cluster.go b/tests/framework/integration/cluster.go index 49723b50c139..3b5be315f3cd 100644 --- a/tests/framework/integration/cluster.go +++ b/tests/framework/integration/cluster.go @@ -1372,6 +1372,14 @@ func (c *Cluster) Client(i int) *clientv3.Client { return c.Members[i].Client } +func (c *Cluster) Endpoints() []string { + var endpoints []string + for _, m := range c.Members { + endpoints = append(endpoints, m.GrpcURL) + } + return endpoints +} + func (c *Cluster) ClusterClient() (client *clientv3.Client, err error) { if c.clusterClient == nil { endpoints := []string{} diff --git a/tests/integration/v3_failover_test.go b/tests/integration/v3_failover_test.go new file mode 100644 index 000000000000..8fa8dfa16cce --- /dev/null +++ b/tests/integration/v3_failover_test.go @@ -0,0 +1,173 @@ +// Copyright 2022 The etcd Authors +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package integration + +import ( + "bytes" + "context" + "crypto/tls" + "go.etcd.io/etcd/api/v3/v3rpc/rpctypes" + clientv3test "go.etcd.io/etcd/tests/v3/integration/clientv3" + "testing" + "time" + + "go.etcd.io/etcd/client/v3" + integration2 "go.etcd.io/etcd/tests/v3/framework/integration" + "google.golang.org/grpc" +) + +func TestFailover(t *testing.T) { + cases := []struct { + name string + testFunc func(*testing.T, *tls.Config, *integration2.Cluster) (*clientv3.Client, error) + }{ + { + name: "create client before the first server down", + testFunc: createClientBeforeServerDown, + }, + { + name: "create client after the first server down", + testFunc: createClientAfterServerDown, + }, + } + + for _, tc := range cases { + t.Run(tc.name, func(t *testing.T) { + t.Logf("Starting test [%s]", tc.name) + integration2.BeforeTest(t) + + // Launch an etcd cluster with 3 members + t.Logf("Launching an etcd cluster with 3 members [%s]", tc.name) + clus := integration2.NewCluster(t, &integration2.ClusterConfig{Size: 3, ClientTLS: &integration2.TestTLSInfo}) + defer clus.Terminate(t) + + cc, err := integration2.TestTLSInfo.ClientConfig() + if err != nil { + t.Fatal(err) + } + // Create an etcd client before or after first server down + t.Logf("Creating an etcd client [%s]", tc.name) + cli, err := tc.testFunc(t, cc, clus) + if err != nil { + t.Fatalf("Failed to create client: %v", err) + } + defer cli.Close() + + // Sanity test + t.Logf("Running sanity test [%s]", tc.name) + key, val := "key1", "val1" + putWithRetries(t, cli, key, val, 10) + getWithRetries(t, cli, key, val, 10) + + t.Logf("Test done [%s]", tc.name) + }) + } +} + +func createClientBeforeServerDown(t *testing.T, cc *tls.Config, clus *integration2.Cluster) (*clientv3.Client, error) { + cli, err := createClient(t, cc, clus) + if err != nil { + return nil, err + } + clus.Members[0].Close() + return cli, nil +} + +func createClientAfterServerDown(t *testing.T, cc *tls.Config, clus *integration2.Cluster) (*clientv3.Client, error) { + clus.Members[0].Close() + return createClient(t, cc, clus) +} + +func createClient(t *testing.T, cc *tls.Config, clus *integration2.Cluster) (*clientv3.Client, error) { + cli, err := integration2.NewClient(t, clientv3.Config{ + Endpoints: clus.Endpoints(), + DialTimeout: 5 * time.Second, + DialOptions: []grpc.DialOption{grpc.WithBlock()}, + TLS: cc, + }) + if err != nil { + return nil, err + } + + return cli, nil +} + +func putWithRetries(t *testing.T, cli *clientv3.Client, key, val string, retryCount int) { + for retryCount > 0 { + // put data test + err := func() error { + t.Log("Sanity test, putting data") + ctx, cancel := context.WithTimeout(context.Background(), 2*time.Second) + defer cancel() + + if _, putErr := cli.Put(ctx, key, val); putErr != nil { + t.Logf("Failed to put data (%v)", putErr) + return putErr + } + return nil + }() + + if err != nil { + retryCount-- + if shouldRetry(err) { + continue + } else { + t.Fatal(err) + } + } + break + } +} + +func getWithRetries(t *testing.T, cli *clientv3.Client, key, val string, retryCount int) { + for retryCount > 0 { + // get data test + err := func() error { + t.Log("Sanity test, getting data") + ctx, cancel := context.WithTimeout(context.Background(), 2*time.Second) + defer cancel() + resp, getErr := cli.Get(ctx, key) + if getErr != nil { + t.Logf("Failed to get key (%v)", getErr) + return getErr + } + if len(resp.Kvs) != 1 { + t.Fatalf("Expected 1 key, got %d", len(resp.Kvs)) + } + if !bytes.Equal([]byte(val), resp.Kvs[0].Value) { + t.Fatalf("Unexpected value, expected: %s, got: %s", val, string(resp.Kvs[0].Value)) + } + return nil + }() + + if err != nil { + retryCount-- + if shouldRetry(err) { + continue + } else { + t.Fatal(err) + } + } + break + } +} + +func shouldRetry(err error) bool { + if clientv3test.IsClientTimeout(err) || clientv3test.IsServerCtxTimeout(err) || + err == rpctypes.ErrTimeout || err == rpctypes.ErrTimeoutDueToLeaderFail { + return true + } + return false +} diff --git a/tests/integration/v3_kv_test.go b/tests/integration/v3_kv_test.go index 01a4570f51ef..d47cc75a20d1 100644 --- a/tests/integration/v3_kv_test.go +++ b/tests/integration/v3_kv_test.go @@ -1,3 +1,17 @@ +// Copyright 2022 The etcd Authors +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + package integration import ( From 778c95fdf4546d880e1dd280f49874b3686ab7be Mon Sep 17 00:00:00 2001 From: Marek Siarkowicz Date: Fri, 25 Feb 2022 13:30:34 +0100 Subject: [PATCH 155/258] scripts: Fix release scripts --- scripts/build-release.sh | 2 +- scripts/release.sh | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/scripts/build-release.sh b/scripts/build-release.sh index 524af0078a77..e90fb3e138f8 100755 --- a/scripts/build-release.sh +++ b/scripts/build-release.sh @@ -26,6 +26,6 @@ pushd "${ETCD_ROOT}" >/dev/null for TARGET_ARCH in "amd64" "arm64" "ppc64le" "s390x"; do log_callout "Building ${TARGET_ARCH} docker image..." - GOOS=linux GOARCH=${TARGET_ARCH} BINARYDIR=release/etcd-${VERSION}-linux-${TARGET_ARCH} BUILDDIR=release ./scripts/build-docker "${VERSION}" + GOOS=linux GOARCH=${TARGET_ARCH} BINARYDIR=release/etcd-${VERSION}-linux-${TARGET_ARCH} BUILDDIR=release ./scripts/build-docker.sh "${VERSION}" done popd >/dev/null diff --git a/scripts/release.sh b/scripts/release.sh index 9fdd5d689608..ec41510ce0c8 100755 --- a/scripts/release.sh +++ b/scripts/release.sh @@ -102,7 +102,7 @@ main() { # Check go version. local go_version current_go_version - go_version="go$(run_go_tool "github.com/mikefarah/yq/v3" read .travis.yml "go[0]")" + go_version="go$(run_go_tool "github.com/mikefarah/yq/v3" read .github/workflows/build.yaml "jobs.build.steps[1].with.go-version")" current_go_version=$(go version | awk '{ print $3 }') if [[ "${current_go_version}" != "${go_version}" ]]; then log_error "Current go version is ${current_go_version}, but etcd ${RELEASE_VERSION} requires ${go_version} (see .travis.yml)." @@ -129,7 +129,7 @@ main() { log_callout "Building etcd and checking --version output" - run ./build.sh + run ./scripts/build.sh local etcd_version etcd_version=$(bin/etcd --version | grep "etcd Version" | awk '{ print $3 }') if [[ "${etcd_version}" != "${VERSION}" ]]; then From 0ecd4de923aa69b13e90d14e2115f2c5e50a99f0 Mon Sep 17 00:00:00 2001 From: kkkkun Date: Mon, 28 Feb 2022 16:22:40 +0800 Subject: [PATCH 156/258] delete duplicate metrics rangeCounterDebug --- server/storage/mvcc/metrics.go | 8 -------- 1 file changed, 8 deletions(-) diff --git a/server/storage/mvcc/metrics.go b/server/storage/mvcc/metrics.go index f28d114e2bc9..c7ece518e478 100644 --- a/server/storage/mvcc/metrics.go +++ b/server/storage/mvcc/metrics.go @@ -28,13 +28,6 @@ var ( Name: "range_total", Help: "Total number of ranges seen by this member.", }) - rangeCounterDebug = prometheus.NewCounter( - prometheus.CounterOpts{ - Namespace: "etcd_debugging", - Subsystem: "mvcc", - Name: "range_total", - Help: "Total number of ranges seen by this member.", - }) putCounter = prometheus.NewCounter( prometheus.CounterOpts{ @@ -280,7 +273,6 @@ var ( func init() { prometheus.MustRegister(rangeCounter) - prometheus.MustRegister(rangeCounterDebug) prometheus.MustRegister(putCounter) prometheus.MustRegister(deleteCounter) prometheus.MustRegister(txnCounter) From fb559105006337157635673f216c2f1392050f83 Mon Sep 17 00:00:00 2001 From: Marek Siarkowicz Date: Mon, 28 Feb 2022 13:20:27 +0100 Subject: [PATCH 157/258] version: bump up to 3.6.0-alpha.0 --- api/version/version.go | 2 +- client/v2/go.mod | 4 ++-- client/v3/go.mod | 4 ++-- etcdctl/go.mod | 16 ++++++++-------- etcdutl/go.mod | 14 +++++++------- go.mod | 20 ++++++++++---------- pkg/go.mod | 2 +- raft/go.mod | 4 ++-- server/go.mod | 12 ++++++------ tests/go.mod | 16 ++++++++-------- 10 files changed, 47 insertions(+), 47 deletions(-) diff --git a/api/version/version.go b/api/version/version.go index 6921aee53ad0..07cffa09dfa8 100644 --- a/api/version/version.go +++ b/api/version/version.go @@ -26,7 +26,7 @@ import ( var ( // MinClusterVersion is the min cluster version this etcd binary is compatible with. MinClusterVersion = "3.0.0" - Version = "3.6.0-pre" + Version = "3.6.0-alpha.0" APIVersion = "unknown" // Git SHA Value will be set during build diff --git a/client/v2/go.mod b/client/v2/go.mod index a473f45acfb9..a67bac661702 100644 --- a/client/v2/go.mod +++ b/client/v2/go.mod @@ -3,8 +3,8 @@ module go.etcd.io/etcd/client/v2 go 1.17 require ( - go.etcd.io/etcd/api/v3 v3.5.0 - go.etcd.io/etcd/client/pkg/v3 v3.5.0 + go.etcd.io/etcd/api/v3 v3.6.0-alpha.0 + go.etcd.io/etcd/client/pkg/v3 v3.6.0-alpha.0 sigs.k8s.io/json v0.0.0-20211020170558-c049b76a60c6 ) diff --git a/client/v3/go.mod b/client/v3/go.mod index fee83ab74edf..18ada51125b7 100644 --- a/client/v3/go.mod +++ b/client/v3/go.mod @@ -6,8 +6,8 @@ require ( github.com/dustin/go-humanize v1.0.0 github.com/grpc-ecosystem/go-grpc-prometheus v1.2.0 github.com/prometheus/client_golang v1.11.0 - go.etcd.io/etcd/api/v3 v3.5.0 - go.etcd.io/etcd/client/pkg/v3 v3.5.0 + go.etcd.io/etcd/api/v3 v3.6.0-alpha.0 + go.etcd.io/etcd/client/pkg/v3 v3.6.0-alpha.0 go.uber.org/zap v1.17.0 google.golang.org/grpc v1.41.0 sigs.k8s.io/yaml v1.2.0 diff --git a/etcdctl/go.mod b/etcdctl/go.mod index 07e60105f980..d6b770a4d614 100644 --- a/etcdctl/go.mod +++ b/etcdctl/go.mod @@ -9,12 +9,12 @@ require ( github.com/spf13/cobra v1.2.1 github.com/spf13/pflag v1.0.5 github.com/urfave/cli v1.22.4 - go.etcd.io/etcd/api/v3 v3.5.0 - go.etcd.io/etcd/client/pkg/v3 v3.5.0 - go.etcd.io/etcd/client/v2 v2.305.0 - go.etcd.io/etcd/client/v3 v3.5.0 - go.etcd.io/etcd/etcdutl/v3 v3.5.0 - go.etcd.io/etcd/pkg/v3 v3.5.0 + go.etcd.io/etcd/api/v3 v3.6.0-alpha.0 + go.etcd.io/etcd/client/pkg/v3 v3.6.0-alpha.0 + go.etcd.io/etcd/client/v2 v2.306.0-alpha.0 + go.etcd.io/etcd/client/v3 v3.6.0-alpha.0 + go.etcd.io/etcd/etcdutl/v3 v3.6.0-alpha.0 + go.etcd.io/etcd/pkg/v3 v3.6.0-alpha.0 go.uber.org/zap v1.17.0 golang.org/x/time v0.0.0-20210220033141-f8bda1e9f3ba google.golang.org/grpc v1.41.0 @@ -43,8 +43,8 @@ require ( github.com/shurcooL/sanitized_anchor_name v1.0.0 // indirect github.com/xiang90/probing v0.0.0-20190116061207-43a291ad63a2 // indirect go.etcd.io/bbolt v1.3.6 // indirect - go.etcd.io/etcd/raft/v3 v3.5.0 // indirect - go.etcd.io/etcd/server/v3 v3.5.0 // indirect + go.etcd.io/etcd/raft/v3 v3.6.0-alpha.0 // indirect + go.etcd.io/etcd/server/v3 v3.6.0-alpha.0 // indirect go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.26.1 // indirect go.opentelemetry.io/otel v1.2.0 // indirect go.opentelemetry.io/otel/trace v1.2.0 // indirect diff --git a/etcdutl/go.mod b/etcdutl/go.mod index 7f4c660fb384..719335f1a32f 100644 --- a/etcdutl/go.mod +++ b/etcdutl/go.mod @@ -26,12 +26,12 @@ require ( github.com/olekukonko/tablewriter v0.0.5 github.com/spf13/cobra v1.2.1 go.etcd.io/bbolt v1.3.6 - go.etcd.io/etcd/api/v3 v3.5.0 - go.etcd.io/etcd/client/pkg/v3 v3.5.0 - go.etcd.io/etcd/client/v3 v3.5.0 - go.etcd.io/etcd/pkg/v3 v3.5.0 - go.etcd.io/etcd/raft/v3 v3.5.0 - go.etcd.io/etcd/server/v3 v3.5.0 + go.etcd.io/etcd/api/v3 v3.6.0-alpha.0 + go.etcd.io/etcd/client/pkg/v3 v3.6.0-alpha.0 + go.etcd.io/etcd/client/v3 v3.6.0-alpha.0 + go.etcd.io/etcd/pkg/v3 v3.6.0-alpha.0 + go.etcd.io/etcd/raft/v3 v3.6.0-alpha.0 + go.etcd.io/etcd/server/v3 v3.6.0-alpha.0 go.uber.org/zap v1.17.0 ) @@ -53,7 +53,7 @@ require ( github.com/prometheus/procfs v0.6.0 // indirect github.com/spf13/pflag v1.0.5 // indirect github.com/xiang90/probing v0.0.0-20190116061207-43a291ad63a2 // indirect - go.etcd.io/etcd/client/v2 v2.305.0 // indirect + go.etcd.io/etcd/client/v2 v2.306.0-alpha.0 // indirect go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.26.1 // indirect go.opentelemetry.io/otel v1.2.0 // indirect go.opentelemetry.io/otel/trace v1.2.0 // indirect diff --git a/go.mod b/go.mod index 0cbdbda3c223..618e1446cf41 100644 --- a/go.mod +++ b/go.mod @@ -21,16 +21,16 @@ require ( github.com/dustin/go-humanize v1.0.0 github.com/spf13/cobra v1.2.1 go.etcd.io/bbolt v1.3.6 - go.etcd.io/etcd/api/v3 v3.5.0 - go.etcd.io/etcd/client/pkg/v3 v3.5.0 - go.etcd.io/etcd/client/v2 v2.305.0 - go.etcd.io/etcd/client/v3 v3.5.0 - go.etcd.io/etcd/etcdctl/v3 v3.0.0-00010101000000-000000000000 - go.etcd.io/etcd/etcdutl/v3 v3.5.0 - go.etcd.io/etcd/pkg/v3 v3.5.0 - go.etcd.io/etcd/raft/v3 v3.5.0 - go.etcd.io/etcd/server/v3 v3.5.0 - go.etcd.io/etcd/tests/v3 v3.0.0-00010101000000-000000000000 + go.etcd.io/etcd/api/v3 v3.6.0-alpha.0 + go.etcd.io/etcd/client/pkg/v3 v3.6.0-alpha.0 + go.etcd.io/etcd/client/v2 v2.306.0-alpha.0 + go.etcd.io/etcd/client/v3 v3.6.0-alpha.0 + go.etcd.io/etcd/etcdctl/v3 v3.6.0-alpha.0 + go.etcd.io/etcd/etcdutl/v3 v3.6.0-alpha.0 + go.etcd.io/etcd/pkg/v3 v3.6.0-alpha.0 + go.etcd.io/etcd/raft/v3 v3.6.0-alpha.0 + go.etcd.io/etcd/server/v3 v3.6.0-alpha.0 + go.etcd.io/etcd/tests/v3 v3.6.0-alpha.0 go.uber.org/zap v1.17.0 golang.org/x/time v0.0.0-20210220033141-f8bda1e9f3ba google.golang.org/grpc v1.41.0 diff --git a/pkg/go.mod b/pkg/go.mod index 37d0306b0782..f6f240f04e01 100644 --- a/pkg/go.mod +++ b/pkg/go.mod @@ -9,7 +9,7 @@ require ( github.com/spf13/cobra v1.2.1 github.com/spf13/pflag v1.0.5 github.com/stretchr/testify v1.7.0 - go.etcd.io/etcd/client/pkg/v3 v3.5.0 + go.etcd.io/etcd/client/pkg/v3 v3.6.0-alpha.0 go.uber.org/zap v1.17.0 google.golang.org/grpc v1.41.0 ) diff --git a/raft/go.mod b/raft/go.mod index 10fb463ac37c..95caf2fa9d27 100644 --- a/raft/go.mod +++ b/raft/go.mod @@ -8,8 +8,8 @@ require ( github.com/gogo/protobuf v1.3.2 github.com/golang/protobuf v1.5.2 github.com/pkg/errors v0.9.1 // indirect - go.etcd.io/etcd/api/v3 v3.5.0 - go.etcd.io/etcd/client/pkg/v3 v3.5.0 + go.etcd.io/etcd/api/v3 v3.6.0-alpha.0 + go.etcd.io/etcd/client/pkg/v3 v3.6.0-alpha.0 ) require ( diff --git a/server/go.mod b/server/go.mod index f5b73302cf79..b64ee751d7ff 100644 --- a/server/go.mod +++ b/server/go.mod @@ -23,12 +23,12 @@ require ( github.com/tmc/grpc-websocket-proxy v0.0.0-20201229170055-e5319fda7802 github.com/xiang90/probing v0.0.0-20190116061207-43a291ad63a2 go.etcd.io/bbolt v1.3.6 - go.etcd.io/etcd/api/v3 v3.5.0 - go.etcd.io/etcd/client/pkg/v3 v3.5.0 - go.etcd.io/etcd/client/v2 v2.305.0 - go.etcd.io/etcd/client/v3 v3.5.0 - go.etcd.io/etcd/pkg/v3 v3.5.0 - go.etcd.io/etcd/raft/v3 v3.5.0 + go.etcd.io/etcd/api/v3 v3.6.0-alpha.0 + go.etcd.io/etcd/client/pkg/v3 v3.6.0-alpha.0 + go.etcd.io/etcd/client/v2 v2.306.0-alpha.0 + go.etcd.io/etcd/client/v3 v3.6.0-alpha.0 + go.etcd.io/etcd/pkg/v3 v3.6.0-alpha.0 + go.etcd.io/etcd/raft/v3 v3.6.0-alpha.0 go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.26.1 go.opentelemetry.io/otel v1.2.0 go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.1.0 diff --git a/tests/go.mod b/tests/go.mod index 2850b0f02f78..f2871f5004cb 100644 --- a/tests/go.mod +++ b/tests/go.mod @@ -29,14 +29,14 @@ require ( github.com/spf13/pflag v1.0.5 github.com/stretchr/testify v1.7.0 go.etcd.io/bbolt v1.3.6 - go.etcd.io/etcd/api/v3 v3.5.0 - go.etcd.io/etcd/client/pkg/v3 v3.5.0 - go.etcd.io/etcd/client/v2 v2.305.0 - go.etcd.io/etcd/client/v3 v3.5.0 - go.etcd.io/etcd/etcdutl/v3 v3.5.0 - go.etcd.io/etcd/pkg/v3 v3.5.0 - go.etcd.io/etcd/raft/v3 v3.5.0 - go.etcd.io/etcd/server/v3 v3.5.0 + go.etcd.io/etcd/api/v3 v3.6.0-alpha.0 + go.etcd.io/etcd/client/pkg/v3 v3.6.0-alpha.0 + go.etcd.io/etcd/client/v2 v2.306.0-alpha.0 + go.etcd.io/etcd/client/v3 v3.6.0-alpha.0 + go.etcd.io/etcd/etcdutl/v3 v3.6.0-alpha.0 + go.etcd.io/etcd/pkg/v3 v3.6.0-alpha.0 + go.etcd.io/etcd/raft/v3 v3.6.0-alpha.0 + go.etcd.io/etcd/server/v3 v3.6.0-alpha.0 go.uber.org/zap v1.17.0 golang.org/x/crypto v0.0.0-20210513164829-c07d793c2f9a golang.org/x/sync v0.0.0-20210220032951-036812b2e83c From 59f7764772f1663b4d2e4e3399f4687ab2e09cf7 Mon Sep 17 00:00:00 2001 From: kkkkun Date: Tue, 1 Mar 2022 11:11:09 +0800 Subject: [PATCH 158/258] add timeout for http client --- server/etcdserver/adapters.go | 2 +- server/etcdserver/bootstrap.go | 2 +- server/etcdserver/cluster_util.go | 20 +++++++++++--------- 3 files changed, 13 insertions(+), 11 deletions(-) diff --git a/server/etcdserver/adapters.go b/server/etcdserver/adapters.go index bc4b68645483..110abd7e9519 100644 --- a/server/etcdserver/adapters.go +++ b/server/etcdserver/adapters.go @@ -68,7 +68,7 @@ func (s *serverVersionAdapter) GetDowngradeInfo() *serverversion.DowngradeInfo { } func (s *serverVersionAdapter) GetMembersVersions() map[string]*version.Versions { - return getMembersVersions(s.lg, s.cluster, s.id, s.peerRt) + return getMembersVersions(s.lg, s.cluster, s.id, s.peerRt, s.Cfg.ReqTimeout()) } func (s *serverVersionAdapter) GetStorageVersion() *semver.Version { diff --git a/server/etcdserver/bootstrap.go b/server/etcdserver/bootstrap.go index e0b747f1d48b..857e7afa6ad9 100644 --- a/server/etcdserver/bootstrap.go +++ b/server/etcdserver/bootstrap.go @@ -298,7 +298,7 @@ func bootstrapExistingClusterNoWAL(cfg config.ServerConfig, prt http.RoundTrippe if err := membership.ValidateClusterAndAssignIDs(cfg.Logger, cl, existingCluster); err != nil { return nil, fmt.Errorf("error validating peerURLs %s: %v", existingCluster, err) } - if !isCompatibleWithCluster(cfg.Logger, cl, cl.MemberByName(cfg.Name).ID, prt) { + if !isCompatibleWithCluster(cfg.Logger, cl, cl.MemberByName(cfg.Name).ID, prt, cfg.ReqTimeout()) { return nil, fmt.Errorf("incompatible with current running cluster") } scaleUpLearners := false diff --git a/server/etcdserver/cluster_util.go b/server/etcdserver/cluster_util.go index 2f22568bce0f..d4feaf9a22aa 100644 --- a/server/etcdserver/cluster_util.go +++ b/server/etcdserver/cluster_util.go @@ -138,7 +138,7 @@ func getRemotePeerURLs(cl *membership.RaftCluster, local string) []string { // The key of the returned map is the member's ID. The value of the returned map // is the semver versions string, including server and cluster. // If it fails to get the version of a member, the key will be nil. -func getMembersVersions(lg *zap.Logger, cl *membership.RaftCluster, local types.ID, rt http.RoundTripper) map[string]*version.Versions { +func getMembersVersions(lg *zap.Logger, cl *membership.RaftCluster, local types.ID, rt http.RoundTripper, timeout time.Duration) map[string]*version.Versions { members := cl.Members() vers := make(map[string]*version.Versions) for _, m := range members { @@ -150,7 +150,7 @@ func getMembersVersions(lg *zap.Logger, cl *membership.RaftCluster, local types. vers[m.ID.String()] = &version.Versions{Server: version.Version, Cluster: cv} continue } - ver, err := getVersion(lg, m, rt) + ver, err := getVersion(lg, m, rt, timeout) if err != nil { lg.Warn("failed to get version", zap.String("remote-member-id", m.ID.String()), zap.Error(err)) vers[m.ID.String()] = nil @@ -183,9 +183,9 @@ func allowedVersionRange(downgradeEnabled bool) (minV *semver.Version, maxV *sem // cluster version in the range of [MinV, MaxV] and no known members has a cluster version // out of the range. // We set this rule since when the local member joins, another member might be offline. -func isCompatibleWithCluster(lg *zap.Logger, cl *membership.RaftCluster, local types.ID, rt http.RoundTripper) bool { - vers := getMembersVersions(lg, cl, local, rt) - minV, maxV := allowedVersionRange(getDowngradeEnabledFromRemotePeers(lg, cl, local, rt)) +func isCompatibleWithCluster(lg *zap.Logger, cl *membership.RaftCluster, local types.ID, rt http.RoundTripper, timeout time.Duration) bool { + vers := getMembersVersions(lg, cl, local, rt, timeout) + minV, maxV := allowedVersionRange(getDowngradeEnabledFromRemotePeers(lg, cl, local, rt, timeout)) return isCompatibleWithVers(lg, vers, local, minV, maxV) } @@ -234,9 +234,10 @@ func isCompatibleWithVers(lg *zap.Logger, vers map[string]*version.Versions, loc // getVersion returns the Versions of the given member via its // peerURLs. Returns the last error if it fails to get the version. -func getVersion(lg *zap.Logger, m *membership.Member, rt http.RoundTripper) (*version.Versions, error) { +func getVersion(lg *zap.Logger, m *membership.Member, rt http.RoundTripper, timeout time.Duration) (*version.Versions, error) { cc := &http.Client{ Transport: rt, + Timeout: timeout, } var ( err error @@ -331,14 +332,14 @@ func promoteMemberHTTP(ctx context.Context, url string, id uint64, peerRt http.R } // getDowngradeEnabledFromRemotePeers will get the downgrade enabled status of the cluster. -func getDowngradeEnabledFromRemotePeers(lg *zap.Logger, cl *membership.RaftCluster, local types.ID, rt http.RoundTripper) bool { +func getDowngradeEnabledFromRemotePeers(lg *zap.Logger, cl *membership.RaftCluster, local types.ID, rt http.RoundTripper, timeout time.Duration) bool { members := cl.Members() for _, m := range members { if m.ID == local { continue } - enable, err := getDowngradeEnabled(lg, m, rt) + enable, err := getDowngradeEnabled(lg, m, rt, timeout) if err != nil { lg.Warn("failed to get downgrade enabled status", zap.String("remote-member-id", m.ID.String()), zap.Error(err)) } else { @@ -352,9 +353,10 @@ func getDowngradeEnabledFromRemotePeers(lg *zap.Logger, cl *membership.RaftClust // getDowngradeEnabled returns the downgrade enabled status of the given member // via its peerURLs. Returns the last error if it fails to get it. -func getDowngradeEnabled(lg *zap.Logger, m *membership.Member, rt http.RoundTripper) (bool, error) { +func getDowngradeEnabled(lg *zap.Logger, m *membership.Member, rt http.RoundTripper, timeout time.Duration) (bool, error) { cc := &http.Client{ Transport: rt, + Timeout: timeout, } var ( err error From f7ee30cc416f325e690f3939ee07ab098b6fcddf Mon Sep 17 00:00:00 2001 From: Marek Siarkowicz Date: Thu, 24 Feb 2022 13:13:18 +0100 Subject: [PATCH 159/258] tests: Implement remaining GetOptions fields --- tests/common/kv_test.go | 2 +- tests/framework/e2e.go | 10 ------ tests/framework/e2e/etcdctl.go | 53 ++++++++++++++++++++++++++-- tests/framework/integration.go | 27 +++++++++++--- tests/framework/interface.go | 2 +- tests/framework/testutils/options.go | 18 +++++----- 6 files changed, 85 insertions(+), 27 deletions(-) diff --git a/tests/common/kv_test.go b/tests/common/kv_test.go index b6a37fe5009b..54bda9915d71 100644 --- a/tests/common/kv_test.go +++ b/tests/common/kv_test.go @@ -33,7 +33,7 @@ func TestKVPut(t *testing.T) { if err := cc.Put(key, value); err != nil { t.Fatalf("count not put key %q, err: %s", key, err) } - resp, err := cc.Get(key, testutils.WithSerializable()) + resp, err := cc.Get(key, testutils.GetOptions{Serializable: true}) if err != nil { t.Fatalf("count not get key %q, err: %s", key, err) } diff --git a/tests/framework/e2e.go b/tests/framework/e2e.go index 094628a3761a..7b7769ec9a1c 100644 --- a/tests/framework/e2e.go +++ b/tests/framework/e2e.go @@ -19,9 +19,7 @@ import ( "testing" "go.etcd.io/etcd/client/pkg/v3/testutil" - clientv3 "go.etcd.io/etcd/client/v3" "go.etcd.io/etcd/tests/v3/framework/e2e" - "go.etcd.io/etcd/tests/v3/framework/testutils" ) type e2eRunner struct{} @@ -58,11 +56,3 @@ func (c *e2eCluster) Client() Client { type e2eClient struct { *e2e.EtcdctlV3 } - -func (c e2eClient) Get(key string, opts ...testutils.GetOption) (*clientv3.GetResponse, error) { - o := testutils.GetOptions{} - for _, opt := range opts { - opt(&o) - } - return c.EtcdctlV3.Get(key, o) -} diff --git a/tests/framework/e2e/etcdctl.go b/tests/framework/e2e/etcdctl.go index b0a53afd1304..90dd4856de4b 100644 --- a/tests/framework/e2e/etcdctl.go +++ b/tests/framework/e2e/etcdctl.go @@ -44,15 +44,64 @@ func (ctl *EtcdctlV3) Get(key string, o testutils.GetOptions) (*clientv3.GetResp if o.Serializable { args = append(args, "--consistency", "s") } - cmd, err := SpawnCmd(append(args, "get", key, "-w", "json"), nil) + args = append(args, "get", key, "-w", "json") + if o.End != "" { + args = append(args, o.End) + } + if o.Revision != 0 { + args = append(args, fmt.Sprintf("--rev=%d", o.Revision)) + } + if o.Prefix { + args = append(args, "--prefix") + } + if o.Limit != 0 { + args = append(args, fmt.Sprintf("--limit=%d", o.Limit)) + } + if o.FromKey { + args = append(args, "--from-key") + } + if o.CountOnly { + args = append(args, "-w", "fields", "--count-only") + } else { + args = append(args, "-w", "json") + } + switch o.SortBy { + case clientv3.SortByCreateRevision: + args = append(args, "--sort-by=CREATE") + case clientv3.SortByModRevision: + args = append(args, "--sort-by=MODIFY") + case clientv3.SortByValue: + args = append(args, "--sort-by=VALUE") + case clientv3.SortByVersion: + args = append(args, "--sort-by=VERSION") + case clientv3.SortByKey: + // nothing + default: + return nil, fmt.Errorf("bad sort target %v", o.SortBy) + } + switch o.Order { + case clientv3.SortAscend: + args = append(args, "--order=ASCEND") + case clientv3.SortDescend: + args = append(args, "--order=DESCEND") + case clientv3.SortNone: + // nothing + default: + return nil, fmt.Errorf("bad sort order %v", o.Order) + } + cmd, err := SpawnCmd(args, nil) if err != nil { return nil, err } + var resp clientv3.GetResponse + if o.CountOnly { + _, err := cmd.Expect("Count") + return &resp, err + } line, err := cmd.Expect("kvs") if err != nil { return nil, err } - var resp clientv3.GetResponse err = json.Unmarshal([]byte(line), &resp) return &resp, err } diff --git a/tests/framework/integration.go b/tests/framework/integration.go index b37111aa4248..c628d7080378 100644 --- a/tests/framework/integration.go +++ b/tests/framework/integration.go @@ -63,15 +63,32 @@ type integrationClient struct { *clientv3.Client } -func (c integrationClient) Get(key string, opts ...testutils.GetOption) (*clientv3.GetResponse, error) { - o := testutils.GetOptions{} - for _, opt := range opts { - opt(&o) - } +func (c integrationClient) Get(key string, o testutils.GetOptions) (*clientv3.GetResponse, error) { clientOpts := []clientv3.OpOption{} + if o.Revision != 0 { + clientOpts = append(clientOpts, clientv3.WithRev(int64(o.Revision))) + } + if o.End != "" { + clientOpts = append(clientOpts, clientv3.WithRange(o.End)) + } if o.Serializable { clientOpts = append(clientOpts, clientv3.WithSerializable()) } + if o.Prefix { + clientOpts = append(clientOpts, clientv3.WithPrefix()) + } + if o.Limit != 0 { + clientOpts = append(clientOpts, clientv3.WithLimit(int64(o.Limit))) + } + if o.FromKey { + clientOpts = append(clientOpts, clientv3.WithFromKey()) + } + if o.CountOnly { + clientOpts = append(clientOpts, clientv3.WithCountOnly()) + } + if o.SortBy != clientv3.SortByKey || o.Order != clientv3.SortNone { + clientOpts = append(clientOpts, clientv3.WithSort(o.SortBy, o.Order)) + } return c.Client.Get(context.Background(), key, clientOpts...) } diff --git a/tests/framework/interface.go b/tests/framework/interface.go index 9eb9e34c28e5..b430106c663e 100644 --- a/tests/framework/interface.go +++ b/tests/framework/interface.go @@ -34,5 +34,5 @@ type Cluster interface { type Client interface { Put(key, value string) error - Get(key string, opts ...testutils.GetOption) (*clientv3.GetResponse, error) + Get(key string, opts testutils.GetOptions) (*clientv3.GetResponse, error) } diff --git a/tests/framework/testutils/options.go b/tests/framework/testutils/options.go index 49cfb8d093c0..0ec7e56de2b9 100644 --- a/tests/framework/testutils/options.go +++ b/tests/framework/testutils/options.go @@ -14,14 +14,16 @@ package testutils +import clientv3 "go.etcd.io/etcd/client/v3" + type GetOptions struct { + Revision int + End string + CountOnly bool Serializable bool -} - -type GetOption func(*GetOptions) - -func WithSerializable() GetOption { - return func(options *GetOptions) { - options.Serializable = true - } + Prefix bool + FromKey bool + Limit int + Order clientv3.SortOrder + SortBy clientv3.SortTarget } From 1c8adcd830c8006e23e21732601bd8e45783b48b Mon Sep 17 00:00:00 2001 From: Marek Siarkowicz Date: Fri, 18 Feb 2022 12:46:59 +0100 Subject: [PATCH 160/258] tests: Handle simple TLS configuration for cluster in common framework --- tests/common/kv_test.go | 5 ++- .../options.go => config/client.go} | 2 +- tests/framework/config/cluster.go | 29 ++++++++++++++ tests/framework/e2e.go | 34 +++++++++++++++- tests/framework/e2e/etcdctl.go | 4 +- tests/framework/integration.go | 39 +++++++++++++++++-- tests/framework/interface.go | 6 +-- tests/framework/unit.go | 3 +- 8 files changed, 107 insertions(+), 15 deletions(-) rename tests/framework/{testutils/options.go => config/client.go} (97%) create mode 100644 tests/framework/config/cluster.go diff --git a/tests/common/kv_test.go b/tests/common/kv_test.go index 54bda9915d71..e2b6efc70748 100644 --- a/tests/common/kv_test.go +++ b/tests/common/kv_test.go @@ -18,12 +18,13 @@ import ( "testing" "time" + "go.etcd.io/etcd/tests/v3/framework/config" "go.etcd.io/etcd/tests/v3/framework/testutils" ) func TestKVPut(t *testing.T) { testRunner.BeforeTest(t) - clus := testRunner.NewCluster(t) + clus := testRunner.NewCluster(t, config.ClusterConfig{ClusterSize: 1, PeerTLS: config.AutoTLS}) defer clus.Close() cc := clus.Client() @@ -33,7 +34,7 @@ func TestKVPut(t *testing.T) { if err := cc.Put(key, value); err != nil { t.Fatalf("count not put key %q, err: %s", key, err) } - resp, err := cc.Get(key, testutils.GetOptions{Serializable: true}) + resp, err := cc.Get(key, config.GetOptions{Serializable: true}) if err != nil { t.Fatalf("count not get key %q, err: %s", key, err) } diff --git a/tests/framework/testutils/options.go b/tests/framework/config/client.go similarity index 97% rename from tests/framework/testutils/options.go rename to tests/framework/config/client.go index 0ec7e56de2b9..47c7ba13864c 100644 --- a/tests/framework/testutils/options.go +++ b/tests/framework/config/client.go @@ -12,7 +12,7 @@ // See the License for the specific language governing permissions and // limitations under the License. -package testutils +package config import clientv3 "go.etcd.io/etcd/client/v3" diff --git a/tests/framework/config/cluster.go b/tests/framework/config/cluster.go new file mode 100644 index 000000000000..c9deab294ebe --- /dev/null +++ b/tests/framework/config/cluster.go @@ -0,0 +1,29 @@ +// Copyright 2022 The etcd Authors +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package config + +type TLSConfig string + +const ( + NoTLS TLSConfig = "" + AutoTLS TLSConfig = "auto-tls" + ManualTLS TLSConfig = "manual-tls" +) + +type ClusterConfig struct { + ClusterSize int + PeerTLS TLSConfig + ClientTLS TLSConfig +} diff --git a/tests/framework/e2e.go b/tests/framework/e2e.go index 7b7769ec9a1c..d0e799163e6f 100644 --- a/tests/framework/e2e.go +++ b/tests/framework/e2e.go @@ -19,6 +19,7 @@ import ( "testing" "go.etcd.io/etcd/client/pkg/v3/testutil" + "go.etcd.io/etcd/tests/v3/framework/config" "go.etcd.io/etcd/tests/v3/framework/e2e" ) @@ -37,8 +38,37 @@ func (e e2eRunner) BeforeTest(t testing.TB) { e2e.BeforeTest(t) } -func (e e2eRunner) NewCluster(t testing.TB) Cluster { - epc, err := e2e.NewEtcdProcessCluster(t, e2e.ConfigStandalone(*e2e.NewConfigAutoTLS())) +func (e e2eRunner) NewCluster(t testing.TB, cfg config.ClusterConfig) Cluster { + e2eConfig := e2e.EtcdProcessClusterConfig{ + InitialToken: "new", + ClusterSize: cfg.ClusterSize, + } + switch cfg.ClientTLS { + case config.NoTLS: + e2eConfig.ClientTLS = e2e.ClientNonTLS + case config.AutoTLS: + e2eConfig.IsClientAutoTLS = true + e2eConfig.ClientTLS = e2e.ClientTLS + case config.ManualTLS: + e2eConfig.IsClientAutoTLS = false + e2eConfig.ClientTLS = e2e.ClientTLS + default: + t.Fatalf("ClientTLS config %q not supported", cfg.ClientTLS) + } + switch cfg.PeerTLS { + case config.NoTLS: + e2eConfig.IsPeerTLS = false + e2eConfig.IsPeerAutoTLS = false + case config.AutoTLS: + e2eConfig.IsPeerTLS = true + e2eConfig.IsPeerAutoTLS = true + case config.ManualTLS: + e2eConfig.IsPeerTLS = true + e2eConfig.IsPeerAutoTLS = false + default: + t.Fatalf("PeerTLS config %q not supported", cfg.PeerTLS) + } + epc, err := e2e.NewEtcdProcessCluster(t, &e2eConfig) if err != nil { t.Fatalf("could not start etcd integrationCluster: %s", err) } diff --git a/tests/framework/e2e/etcdctl.go b/tests/framework/e2e/etcdctl.go index 90dd4856de4b..5d79bbfbba5f 100644 --- a/tests/framework/e2e/etcdctl.go +++ b/tests/framework/e2e/etcdctl.go @@ -20,7 +20,7 @@ import ( "strings" clientv3 "go.etcd.io/etcd/client/v3" - "go.etcd.io/etcd/tests/v3/framework/testutils" + "go.etcd.io/etcd/tests/v3/framework/config" ) type EtcdctlV3 struct { @@ -39,7 +39,7 @@ func (ctl *EtcdctlV3) DowngradeEnable(version string) error { return SpawnWithExpect(ctl.cmdArgs("downgrade", "enable", version), "Downgrade enable success") } -func (ctl *EtcdctlV3) Get(key string, o testutils.GetOptions) (*clientv3.GetResponse, error) { +func (ctl *EtcdctlV3) Get(key string, o config.GetOptions) (*clientv3.GetResponse, error) { args := ctl.cmdArgs() if o.Serializable { args = append(args, "--consistency", "s") diff --git a/tests/framework/integration.go b/tests/framework/integration.go index c628d7080378..d484fe580462 100644 --- a/tests/framework/integration.go +++ b/tests/framework/integration.go @@ -16,12 +16,15 @@ package framework import ( "context" + "fmt" "testing" "go.etcd.io/etcd/client/pkg/v3/testutil" + "go.etcd.io/etcd/client/pkg/v3/transport" clientv3 "go.etcd.io/etcd/client/v3" + "go.etcd.io/etcd/tests/v3/framework/config" "go.etcd.io/etcd/tests/v3/framework/integration" - "go.etcd.io/etcd/tests/v3/framework/testutils" + "go.uber.org/zap" ) type integrationRunner struct{} @@ -34,13 +37,41 @@ func (e integrationRunner) BeforeTest(t testing.TB) { integration.BeforeTest(t) } -func (e integrationRunner) NewCluster(t testing.TB) Cluster { +func (e integrationRunner) NewCluster(t testing.TB, cfg config.ClusterConfig) Cluster { + var err error + var integrationCfg integration.ClusterConfig + integrationCfg.Size = cfg.ClusterSize + integrationCfg.ClientTLS, err = tlsInfo(t, cfg.ClientTLS) + if err != nil { + t.Fatalf("ClientTLS: %s", err) + } + integrationCfg.PeerTLS, err = tlsInfo(t, cfg.PeerTLS) + if err != nil { + t.Fatalf("PeerTLS: %s", err) + } return &integrationCluster{ - Cluster: integration.NewCluster(t, &integration.ClusterConfig{Size: 1}), + Cluster: integration.NewCluster(t, &integrationCfg), t: t, } } +func tlsInfo(t testing.TB, cfg config.TLSConfig) (*transport.TLSInfo, error) { + switch cfg { + case config.NoTLS: + return nil, nil + case config.AutoTLS: + tls, err := transport.SelfCert(zap.NewNop(), t.TempDir(), []string{"localhost"}, 1) + if err != nil { + return nil, fmt.Errorf("failed to generate cert: %s", err) + } + return &tls, nil + case config.ManualTLS: + return &integration.TestTLSInfo, nil + default: + return nil, fmt.Errorf("config %q not supported", cfg) + } +} + type integrationCluster struct { *integration.Cluster t testing.TB @@ -63,7 +94,7 @@ type integrationClient struct { *clientv3.Client } -func (c integrationClient) Get(key string, o testutils.GetOptions) (*clientv3.GetResponse, error) { +func (c integrationClient) Get(key string, o config.GetOptions) (*clientv3.GetResponse, error) { clientOpts := []clientv3.OpOption{} if o.Revision != 0 { clientOpts = append(clientOpts, clientv3.WithRev(int64(o.Revision))) diff --git a/tests/framework/interface.go b/tests/framework/interface.go index b430106c663e..fb57b92ec267 100644 --- a/tests/framework/interface.go +++ b/tests/framework/interface.go @@ -18,13 +18,13 @@ import ( "testing" clientv3 "go.etcd.io/etcd/client/v3" - "go.etcd.io/etcd/tests/v3/framework/testutils" + "go.etcd.io/etcd/tests/v3/framework/config" ) type testRunner interface { TestMain(m *testing.M) BeforeTest(testing.TB) - NewCluster(testing.TB) Cluster + NewCluster(testing.TB, config.ClusterConfig) Cluster } type Cluster interface { @@ -34,5 +34,5 @@ type Cluster interface { type Client interface { Put(key, value string) error - Get(key string, opts testutils.GetOptions) (*clientv3.GetResponse, error) + Get(key string, opts config.GetOptions) (*clientv3.GetResponse, error) } diff --git a/tests/framework/unit.go b/tests/framework/unit.go index 231e0f7df496..45b10ff4164a 100644 --- a/tests/framework/unit.go +++ b/tests/framework/unit.go @@ -21,6 +21,7 @@ import ( "testing" "go.etcd.io/etcd/client/pkg/v3/testutil" + "go.etcd.io/etcd/tests/v3/framework/config" ) type unitRunner struct{} @@ -38,7 +39,7 @@ func (e unitRunner) TestMain(m *testing.M) { func (e unitRunner) BeforeTest(t testing.TB) { } -func (e unitRunner) NewCluster(t testing.TB) Cluster { +func (e unitRunner) NewCluster(t testing.TB, cfg config.ClusterConfig) Cluster { testutil.SkipTestIfShortMode(t, "Cannot create clusters in --short tests") return nil } From 58c38089193cfb2a89d2a1154ffbe10724a39e6c Mon Sep 17 00:00:00 2001 From: Marek Siarkowicz Date: Fri, 18 Feb 2022 12:48:56 +0100 Subject: [PATCH 161/258] tests: Handle multiple cluster configurations --- tests/common/kv_test.go | 57 +++++++++++++++++++++++++---------------- 1 file changed, 35 insertions(+), 22 deletions(-) diff --git a/tests/common/kv_test.go b/tests/common/kv_test.go index e2b6efc70748..c8ef1d0230be 100644 --- a/tests/common/kv_test.go +++ b/tests/common/kv_test.go @@ -24,28 +24,41 @@ import ( func TestKVPut(t *testing.T) { testRunner.BeforeTest(t) - clus := testRunner.NewCluster(t, config.ClusterConfig{ClusterSize: 1, PeerTLS: config.AutoTLS}) - defer clus.Close() - cc := clus.Client() + tcs := []struct { + name string + config config.ClusterConfig + }{ + { + name: "PeerAutoTLS", + config: config.ClusterConfig{ClusterSize: 1, PeerTLS: config.AutoTLS}, + }, + } + for _, tc := range tcs { + t.Run(tc.name, func(t *testing.T) { + clus := testRunner.NewCluster(t, tc.config) + defer clus.Close() + cc := clus.Client() - testutils.ExecuteWithTimeout(t, 10*time.Second, func() { - key, value := "foo", "bar" + testutils.ExecuteWithTimeout(t, 10*time.Second, func() { + key, value := "foo", "bar" - if err := cc.Put(key, value); err != nil { - t.Fatalf("count not put key %q, err: %s", key, err) - } - resp, err := cc.Get(key, config.GetOptions{Serializable: true}) - if err != nil { - t.Fatalf("count not get key %q, err: %s", key, err) - } - if len(resp.Kvs) != 1 { - t.Errorf("Unexpected lenth of response, got %d", len(resp.Kvs)) - } - if string(resp.Kvs[0].Key) != key { - t.Errorf("Unexpected key, want %q, got %q", key, resp.Kvs[0].Key) - } - if string(resp.Kvs[0].Value) != value { - t.Errorf("Unexpected value, want %q, got %q", value, resp.Kvs[0].Value) - } - }) + if err := cc.Put(key, value); err != nil { + t.Fatalf("count not put key %q, err: %s", key, err) + } + resp, err := cc.Get(key, config.GetOptions{Serializable: true}) + if err != nil { + t.Fatalf("count not get key %q, err: %s", key, err) + } + if len(resp.Kvs) != 1 { + t.Errorf("Unexpected lenth of response, got %d", len(resp.Kvs)) + } + if string(resp.Kvs[0].Key) != key { + t.Errorf("Unexpected key, want %q, got %q", key, resp.Kvs[0].Key) + } + if string(resp.Kvs[0].Value) != value { + t.Errorf("Unexpected value, want %q, got %q", value, resp.Kvs[0].Value) + } + }) + }) + } } From 81ef11ffb81395295acc2e8d7b7e86ca379c5271 Mon Sep 17 00:00:00 2001 From: Marek Siarkowicz Date: Fri, 18 Feb 2022 13:06:48 +0100 Subject: [PATCH 162/258] tests: Test different TLS configuration with TestKVPut --- tests/common/kv_test.go | 16 ++++++++++++++++ tests/e2e/ctl_v3_kv_test.go | 6 ------ tests/framework/integration/cluster.go | 15 ++++++++++++--- 3 files changed, 28 insertions(+), 9 deletions(-) diff --git a/tests/common/kv_test.go b/tests/common/kv_test.go index c8ef1d0230be..0e2af0956848 100644 --- a/tests/common/kv_test.go +++ b/tests/common/kv_test.go @@ -28,10 +28,26 @@ func TestKVPut(t *testing.T) { name string config config.ClusterConfig }{ + { + name: "NoTLS", + config: config.ClusterConfig{ClusterSize: 1}, + }, + { + name: "PeerTLS", + config: config.ClusterConfig{ClusterSize: 1, PeerTLS: config.ManualTLS}, + }, { name: "PeerAutoTLS", config: config.ClusterConfig{ClusterSize: 1, PeerTLS: config.AutoTLS}, }, + { + name: "ClientTLS", + config: config.ClusterConfig{ClusterSize: 1, ClientTLS: config.ManualTLS}, + }, + { + name: "ClientAutoTLS", + config: config.ClusterConfig{ClusterSize: 1, ClientTLS: config.AutoTLS}, + }, } for _, tc := range tcs { t.Run(tc.name, func(t *testing.T) { diff --git a/tests/e2e/ctl_v3_kv_test.go b/tests/e2e/ctl_v3_kv_test.go index d74434ab2a0a..4c094d856b61 100644 --- a/tests/e2e/ctl_v3_kv_test.go +++ b/tests/e2e/ctl_v3_kv_test.go @@ -22,12 +22,6 @@ import ( "go.etcd.io/etcd/tests/v3/framework/e2e" ) -func TestCtlV3PutNoTLS(t *testing.T) { testCtl(t, putTest, withCfg(*e2e.NewConfigNoTLS())) } -func TestCtlV3PutClientTLS(t *testing.T) { testCtl(t, putTest, withCfg(*e2e.NewConfigClientTLS())) } -func TestCtlV3PutClientAutoTLS(t *testing.T) { - testCtl(t, putTest, withCfg(*e2e.NewConfigClientAutoTLS())) -} -func TestCtlV3PutPeerTLS(t *testing.T) { testCtl(t, putTest, withCfg(*e2e.NewConfigPeerTLS())) } func TestCtlV3PutTimeout(t *testing.T) { testCtl(t, putTest, withDialTimeout(0)) } func TestCtlV3PutClientTLSFlagByEnv(t *testing.T) { testCtl(t, putTest, withCfg(*e2e.NewConfigClientTLS()), withFlagByEnv()) diff --git a/tests/framework/integration/cluster.go b/tests/framework/integration/cluster.go index 3b5be315f3cd..e5a6778d15c2 100644 --- a/tests/framework/integration/cluster.go +++ b/tests/framework/integration/cluster.go @@ -1387,9 +1387,18 @@ func (c *Cluster) ClusterClient() (client *clientv3.Client, err error) { endpoints = append(endpoints, m.GrpcURL) } cfg := clientv3.Config{ - Endpoints: endpoints, - DialTimeout: 5 * time.Second, - DialOptions: []grpc.DialOption{grpc.WithBlock()}, + Endpoints: endpoints, + DialTimeout: 5 * time.Second, + DialOptions: []grpc.DialOption{grpc.WithBlock()}, + MaxCallSendMsgSize: c.Cfg.ClientMaxCallSendMsgSize, + MaxCallRecvMsgSize: c.Cfg.ClientMaxCallRecvMsgSize, + } + if c.Cfg.ClientTLS != nil { + tls, err := c.Cfg.ClientTLS.ClientConfig() + if err != nil { + return nil, err + } + cfg.TLS = tls } c.clusterClient, err = newClientV3(cfg) if err != nil { From 74d77dbaaabb86946549dee756225850a72011bf Mon Sep 17 00:00:00 2001 From: Marek Siarkowicz Date: Fri, 18 Feb 2022 14:23:51 +0100 Subject: [PATCH 163/258] tests: Migrate TestKVGet e2e test to common test framework --- tests/common/kv_test.go | 75 +++++++++++++++++++ tests/e2e/ctl_v3_kv_test.go | 7 -- .../testutils/{util.go => execute.go} | 0 tests/framework/testutils/kvs.go | 28 +++++++ 4 files changed, 103 insertions(+), 7 deletions(-) rename tests/framework/testutils/{util.go => execute.go} (100%) create mode 100644 tests/framework/testutils/kvs.go diff --git a/tests/common/kv_test.go b/tests/common/kv_test.go index 0e2af0956848..a2c16f89fc19 100644 --- a/tests/common/kv_test.go +++ b/tests/common/kv_test.go @@ -18,6 +18,8 @@ import ( "testing" "time" + "github.com/stretchr/testify/assert" + clientv3 "go.etcd.io/etcd/client/v3" "go.etcd.io/etcd/tests/v3/framework/config" "go.etcd.io/etcd/tests/v3/framework/testutils" ) @@ -78,3 +80,76 @@ func TestKVPut(t *testing.T) { }) } } + +func TestKVGet(t *testing.T) { + testRunner.BeforeTest(t) + tcs := []struct { + name string + config config.ClusterConfig + }{ + { + name: "NoTLS", + config: config.ClusterConfig{ClusterSize: 1}, + }, + { + name: "PeerTLS", + config: config.ClusterConfig{ClusterSize: 1, PeerTLS: config.ManualTLS}, + }, + { + name: "PeerAutoTLS", + config: config.ClusterConfig{ClusterSize: 1, PeerTLS: config.AutoTLS}, + }, + { + name: "ClientTLS", + config: config.ClusterConfig{ClusterSize: 1, ClientTLS: config.ManualTLS}, + }, + { + name: "ClientAutoTLS", + config: config.ClusterConfig{ClusterSize: 1, ClientTLS: config.AutoTLS}, + }, + } + for _, tc := range tcs { + t.Run(tc.name, func(t *testing.T) { + clus := testRunner.NewCluster(t, tc.config) + defer clus.Close() + cc := clus.Client() + + testutils.ExecuteWithTimeout(t, 10*time.Second, func() { + var ( + kvs = []testutils.KeyValue{{"key1", "val1"}, {"key2", "val2"}, {"key3", "val3"}} + revkvs = []testutils.KeyValue{{"key3", "val3"}, {"key2", "val2"}, {"key1", "val1"}} + ) + for i := range kvs { + if err := cc.Put(kvs[i].Key, kvs[i].Value); err != nil { + t.Fatalf("count not put key %q, err: %s", kvs[i].Key, err) + } + } + tests := []struct { + key string + options config.GetOptions + + wkv []testutils.KeyValue + }{ + {key: "key1", wkv: []testutils.KeyValue{{"key1", "val1"}}}, + {key: "", options: config.GetOptions{Prefix: true}, wkv: kvs}, + {key: "", options: config.GetOptions{FromKey: true}, wkv: kvs}, + {key: "key", options: config.GetOptions{Prefix: true}, wkv: kvs}, + {key: "key", options: config.GetOptions{Prefix: true, Limit: 2}, wkv: kvs[:2]}, + {key: "key", options: config.GetOptions{Prefix: true, Order: clientv3.SortAscend, SortBy: clientv3.SortByModRevision}, wkv: kvs}, + {key: "key", options: config.GetOptions{Prefix: true, Order: clientv3.SortAscend, SortBy: clientv3.SortByVersion}, wkv: kvs}, + {key: "key", options: config.GetOptions{Prefix: true, Order: clientv3.SortNone, SortBy: clientv3.SortByCreateRevision}, wkv: kvs}, + {key: "key", options: config.GetOptions{Prefix: true, Order: clientv3.SortDescend, SortBy: clientv3.SortByCreateRevision}, wkv: revkvs}, + {key: "key", options: config.GetOptions{Prefix: true, Order: clientv3.SortDescend, SortBy: clientv3.SortByKey}, wkv: revkvs}, + } + for _, tt := range tests { + resp, err := cc.Get(tt.key, tt.options) + if err != nil { + t.Fatalf("count not get key %q, err: %s", tt.key[0], err) + } + kvs := testutils.FromGetResponse(resp) + assert.Equal(t, tt.wkv, kvs) + } + }) + }) + } +} diff --git a/tests/e2e/ctl_v3_kv_test.go b/tests/e2e/ctl_v3_kv_test.go index 4c094d856b61..4c902cae73ca 100644 --- a/tests/e2e/ctl_v3_kv_test.go +++ b/tests/e2e/ctl_v3_kv_test.go @@ -29,13 +29,6 @@ func TestCtlV3PutClientTLSFlagByEnv(t *testing.T) { func TestCtlV3PutIgnoreValue(t *testing.T) { testCtl(t, putTestIgnoreValue) } func TestCtlV3PutIgnoreLease(t *testing.T) { testCtl(t, putTestIgnoreLease) } -func TestCtlV3Get(t *testing.T) { testCtl(t, getTest) } -func TestCtlV3GetNoTLS(t *testing.T) { testCtl(t, getTest, withCfg(*e2e.NewConfigNoTLS())) } -func TestCtlV3GetClientTLS(t *testing.T) { testCtl(t, getTest, withCfg(*e2e.NewConfigClientTLS())) } -func TestCtlV3GetClientAutoTLS(t *testing.T) { - testCtl(t, getTest, withCfg(*e2e.NewConfigClientAutoTLS())) -} -func TestCtlV3GetPeerTLS(t *testing.T) { testCtl(t, getTest, withCfg(*e2e.NewConfigPeerTLS())) } func TestCtlV3GetTimeout(t *testing.T) { testCtl(t, getTest, withDialTimeout(0)) } func TestCtlV3GetQuorum(t *testing.T) { testCtl(t, getTest, withQuorum()) } diff --git a/tests/framework/testutils/util.go b/tests/framework/testutils/execute.go similarity index 100% rename from tests/framework/testutils/util.go rename to tests/framework/testutils/execute.go diff --git a/tests/framework/testutils/kvs.go b/tests/framework/testutils/kvs.go new file mode 100644 index 000000000000..d61ab6742da1 --- /dev/null +++ b/tests/framework/testutils/kvs.go @@ -0,0 +1,28 @@ +// Copyright 2022 The etcd Authors +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package testutils + +import clientv3 "go.etcd.io/etcd/client/v3" + +type KeyValue struct { + Key, Value string +} + +func FromGetResponse(resp *clientv3.GetResponse) (kvs []KeyValue) { + for _, kv := range resp.Kvs { + kvs = append(kvs, KeyValue{Key: string(kv.Key), Value: string(kv.Value)}) + } + return kvs +} From bd9f366f40ea1da55ee859acf283c5ab84c723f8 Mon Sep 17 00:00:00 2001 From: Marek Siarkowicz Date: Fri, 18 Feb 2022 15:15:35 +0100 Subject: [PATCH 164/258] tests: Migrate TestKVRange integration test to TestKVGet --- tests/common/kv_test.go | 48 +++-- .../testutils/{kvs.go => helpters.go} | 8 +- tests/integration/clientv3/kv_test.go | 168 ------------------ 3 files changed, 31 insertions(+), 193 deletions(-) rename tests/framework/testutils/{kvs.go => helpters.go} (78%) diff --git a/tests/common/kv_test.go b/tests/common/kv_test.go index a2c16f89fc19..2b69d7ba576d 100644 --- a/tests/common/kv_test.go +++ b/tests/common/kv_test.go @@ -116,37 +116,47 @@ func TestKVGet(t *testing.T) { testutils.ExecuteWithTimeout(t, 10*time.Second, func() { var ( - kvs = []testutils.KeyValue{{"key1", "val1"}, {"key2", "val2"}, {"key3", "val3"}} - revkvs = []testutils.KeyValue{{"key3", "val3"}, {"key2", "val2"}, {"key1", "val1"}} + kvs = []string{"a", "b", "c", "c", "c", "foo", "foo/abc", "fop"} + wantKvs = []string{"a", "b", "c", "foo", "foo/abc", "fop"} + kvsByVersion = []string{"a", "b", "foo", "foo/abc", "fop", "c"} + reversedKvs = []string{"fop", "foo/abc", "foo", "c", "b", "a"} ) + for i := range kvs { - if err := cc.Put(kvs[i].Key, kvs[i].Value); err != nil { - t.Fatalf("count not put key %q, err: %s", kvs[i].Key, err) + if err := cc.Put(kvs[i], "bar"); err != nil { + t.Fatalf("count not put key %q, err: %s", kvs[i], err) } } tests := []struct { - key string + begin string + end string options config.GetOptions - wkv []testutils.KeyValue + wkv []string }{ - {key: "key1", wkv: []testutils.KeyValue{{"key1", "val1"}}}, - {key: "", options: config.GetOptions{Prefix: true}, wkv: kvs}, - {key: "", options: config.GetOptions{FromKey: true}, wkv: kvs}, - {key: "key", options: config.GetOptions{Prefix: true}, wkv: kvs}, - {key: "key", options: config.GetOptions{Prefix: true, Limit: 2}, wkv: kvs[:2]}, - {key: "key", options: config.GetOptions{Prefix: true, Order: clientv3.SortAscend, SortBy: clientv3.SortByModRevision}, wkv: kvs}, - {key: "key", options: config.GetOptions{Prefix: true, Order: clientv3.SortAscend, SortBy: clientv3.SortByVersion}, wkv: kvs}, - {key: "key", options: config.GetOptions{Prefix: true, Order: clientv3.SortNone, SortBy: clientv3.SortByCreateRevision}, wkv: kvs}, - {key: "key", options: config.GetOptions{Prefix: true, Order: clientv3.SortDescend, SortBy: clientv3.SortByCreateRevision}, wkv: revkvs}, - {key: "key", options: config.GetOptions{Prefix: true, Order: clientv3.SortDescend, SortBy: clientv3.SortByKey}, wkv: revkvs}, + {begin: "a", wkv: wantKvs[:1]}, + {begin: "a", options: config.GetOptions{Serializable: true}, wkv: wantKvs[:1]}, + {begin: "a", options: config.GetOptions{End: "c"}, wkv: wantKvs[:2]}, + {begin: "", options: config.GetOptions{Prefix: true}, wkv: wantKvs}, + {begin: "", options: config.GetOptions{FromKey: true}, wkv: wantKvs}, + {begin: "a", options: config.GetOptions{End: "x"}, wkv: wantKvs}, + {begin: "", options: config.GetOptions{Prefix: true, Revision: 4}, wkv: kvs[:3]}, + {begin: "a", options: config.GetOptions{CountOnly: true}, wkv: nil}, + {begin: "foo", options: config.GetOptions{Prefix: true}, wkv: []string{"foo", "foo/abc"}}, + {begin: "foo", options: config.GetOptions{FromKey: true}, wkv: []string{"foo", "foo/abc", "fop"}}, + {begin: "", options: config.GetOptions{Prefix: true, Limit: 2}, wkv: wantKvs[:2]}, + {begin: "", options: config.GetOptions{Prefix: true, Order: clientv3.SortAscend, SortBy: clientv3.SortByModRevision}, wkv: wantKvs}, + {begin: "", options: config.GetOptions{Prefix: true, Order: clientv3.SortAscend, SortBy: clientv3.SortByVersion}, wkv: kvsByVersion}, + {begin: "", options: config.GetOptions{Prefix: true, Order: clientv3.SortNone, SortBy: clientv3.SortByCreateRevision}, wkv: wantKvs}, + {begin: "", options: config.GetOptions{Prefix: true, Order: clientv3.SortDescend, SortBy: clientv3.SortByCreateRevision}, wkv: reversedKvs}, + {begin: "", options: config.GetOptions{Prefix: true, Order: clientv3.SortDescend, SortBy: clientv3.SortByKey}, wkv: reversedKvs}, } for _, tt := range tests { - resp, err := cc.Get(tt.key, tt.options) + resp, err := cc.Get(tt.begin, tt.options) if err != nil { - t.Fatalf("count not get key %q, err: %s", tt.key[0], err) + t.Fatalf("count not get key %q, err: %s", tt.begin, err) } - kvs := testutils.FromGetResponse(resp) + kvs := testutils.KeysFromGetResponse(resp) assert.Equal(t, tt.wkv, kvs) } }) diff --git a/tests/framework/testutils/kvs.go b/tests/framework/testutils/helpters.go similarity index 78% rename from tests/framework/testutils/kvs.go rename to tests/framework/testutils/helpters.go index d61ab6742da1..ecc165a86857 100644 --- a/tests/framework/testutils/kvs.go +++ b/tests/framework/testutils/helpters.go @@ -16,13 +16,9 @@ package testutils import clientv3 "go.etcd.io/etcd/client/v3" -type KeyValue struct { - Key, Value string -} - -func FromGetResponse(resp *clientv3.GetResponse) (kvs []KeyValue) { +func KeysFromGetResponse(resp *clientv3.GetResponse) (kvs []string) { for _, kv := range resp.Kvs { - kvs = append(kvs, KeyValue{Key: string(kv.Key), Value: string(kv.Value)}) + kvs = append(kvs, string(kv.Key)) } return kvs } diff --git a/tests/integration/clientv3/kv_test.go b/tests/integration/clientv3/kv_test.go index fe0b5a2c45d6..9d164760cd6c 100644 --- a/tests/integration/clientv3/kv_test.go +++ b/tests/integration/clientv3/kv_test.go @@ -254,180 +254,12 @@ func TestKVRange(t *testing.T) { wantSet []*mvccpb.KeyValue }{ - // range first two - { - "a", "c", - 0, - nil, - - []*mvccpb.KeyValue{ - {Key: []byte("a"), Value: nil, CreateRevision: 2, ModRevision: 2, Version: 1}, - {Key: []byte("b"), Value: nil, CreateRevision: 3, ModRevision: 3, Version: 1}, - }, - }, - // range first two with serializable - { - "a", "c", - 0, - []clientv3.OpOption{clientv3.WithSerializable()}, - - []*mvccpb.KeyValue{ - {Key: []byte("a"), Value: nil, CreateRevision: 2, ModRevision: 2, Version: 1}, - {Key: []byte("b"), Value: nil, CreateRevision: 3, ModRevision: 3, Version: 1}, - }, - }, - // range all with rev - { - "a", "x", - 2, - nil, - - []*mvccpb.KeyValue{ - {Key: []byte("a"), Value: nil, CreateRevision: 2, ModRevision: 2, Version: 1}, - }, - }, - // range all with countOnly - { - "a", "x", - 2, - []clientv3.OpOption{clientv3.WithCountOnly()}, - - nil, - }, - // range all with SortByKey, SortAscend - { - "a", "x", - 0, - []clientv3.OpOption{clientv3.WithSort(clientv3.SortByKey, clientv3.SortAscend)}, - - []*mvccpb.KeyValue{ - {Key: []byte("a"), Value: nil, CreateRevision: 2, ModRevision: 2, Version: 1}, - {Key: []byte("b"), Value: nil, CreateRevision: 3, ModRevision: 3, Version: 1}, - {Key: []byte("c"), Value: nil, CreateRevision: 4, ModRevision: 6, Version: 3}, - {Key: []byte("foo"), Value: nil, CreateRevision: 7, ModRevision: 7, Version: 1}, - {Key: []byte("foo/abc"), Value: nil, CreateRevision: 8, ModRevision: 8, Version: 1}, - {Key: []byte("fop"), Value: nil, CreateRevision: 9, ModRevision: 9, Version: 1}, - }, - }, - // range all with SortByKey, missing sorting order (ASCEND by default) - { - "a", "x", - 0, - []clientv3.OpOption{clientv3.WithSort(clientv3.SortByKey, clientv3.SortNone)}, - - []*mvccpb.KeyValue{ - {Key: []byte("a"), Value: nil, CreateRevision: 2, ModRevision: 2, Version: 1}, - {Key: []byte("b"), Value: nil, CreateRevision: 3, ModRevision: 3, Version: 1}, - {Key: []byte("c"), Value: nil, CreateRevision: 4, ModRevision: 6, Version: 3}, - {Key: []byte("foo"), Value: nil, CreateRevision: 7, ModRevision: 7, Version: 1}, - {Key: []byte("foo/abc"), Value: nil, CreateRevision: 8, ModRevision: 8, Version: 1}, - {Key: []byte("fop"), Value: nil, CreateRevision: 9, ModRevision: 9, Version: 1}, - }, - }, - // range all with SortByCreateRevision, SortDescend - { - "a", "x", - 0, - []clientv3.OpOption{clientv3.WithSort(clientv3.SortByCreateRevision, clientv3.SortDescend)}, - - []*mvccpb.KeyValue{ - {Key: []byte("fop"), Value: nil, CreateRevision: 9, ModRevision: 9, Version: 1}, - {Key: []byte("foo/abc"), Value: nil, CreateRevision: 8, ModRevision: 8, Version: 1}, - {Key: []byte("foo"), Value: nil, CreateRevision: 7, ModRevision: 7, Version: 1}, - {Key: []byte("c"), Value: nil, CreateRevision: 4, ModRevision: 6, Version: 3}, - {Key: []byte("b"), Value: nil, CreateRevision: 3, ModRevision: 3, Version: 1}, - {Key: []byte("a"), Value: nil, CreateRevision: 2, ModRevision: 2, Version: 1}, - }, - }, - // range all with SortByCreateRevision, missing sorting order (ASCEND by default) - { - "a", "x", - 0, - []clientv3.OpOption{clientv3.WithSort(clientv3.SortByCreateRevision, clientv3.SortNone)}, - - []*mvccpb.KeyValue{ - {Key: []byte("a"), Value: nil, CreateRevision: 2, ModRevision: 2, Version: 1}, - {Key: []byte("b"), Value: nil, CreateRevision: 3, ModRevision: 3, Version: 1}, - {Key: []byte("c"), Value: nil, CreateRevision: 4, ModRevision: 6, Version: 3}, - {Key: []byte("foo"), Value: nil, CreateRevision: 7, ModRevision: 7, Version: 1}, - {Key: []byte("foo/abc"), Value: nil, CreateRevision: 8, ModRevision: 8, Version: 1}, - {Key: []byte("fop"), Value: nil, CreateRevision: 9, ModRevision: 9, Version: 1}, - }, - }, - // range all with SortByModRevision, SortDescend - { - "a", "x", - 0, - []clientv3.OpOption{clientv3.WithSort(clientv3.SortByModRevision, clientv3.SortDescend)}, - - []*mvccpb.KeyValue{ - {Key: []byte("fop"), Value: nil, CreateRevision: 9, ModRevision: 9, Version: 1}, - {Key: []byte("foo/abc"), Value: nil, CreateRevision: 8, ModRevision: 8, Version: 1}, - {Key: []byte("foo"), Value: nil, CreateRevision: 7, ModRevision: 7, Version: 1}, - {Key: []byte("c"), Value: nil, CreateRevision: 4, ModRevision: 6, Version: 3}, - {Key: []byte("b"), Value: nil, CreateRevision: 3, ModRevision: 3, Version: 1}, - {Key: []byte("a"), Value: nil, CreateRevision: 2, ModRevision: 2, Version: 1}, - }, - }, - // WithPrefix - { - "foo", "", - 0, - []clientv3.OpOption{clientv3.WithPrefix()}, - - []*mvccpb.KeyValue{ - {Key: []byte("foo"), Value: nil, CreateRevision: 7, ModRevision: 7, Version: 1}, - {Key: []byte("foo/abc"), Value: nil, CreateRevision: 8, ModRevision: 8, Version: 1}, - }, - }, - // WithFromKey - { - "fo", "", - 0, - []clientv3.OpOption{clientv3.WithFromKey()}, - - []*mvccpb.KeyValue{ - {Key: []byte("foo"), Value: nil, CreateRevision: 7, ModRevision: 7, Version: 1}, - {Key: []byte("foo/abc"), Value: nil, CreateRevision: 8, ModRevision: 8, Version: 1}, - {Key: []byte("fop"), Value: nil, CreateRevision: 9, ModRevision: 9, Version: 1}, - }, - }, // fetch entire keyspace using WithFromKey { "\x00", "", 0, []clientv3.OpOption{clientv3.WithFromKey(), clientv3.WithSort(clientv3.SortByKey, clientv3.SortAscend)}, - []*mvccpb.KeyValue{ - {Key: []byte("a"), Value: nil, CreateRevision: 2, ModRevision: 2, Version: 1}, - {Key: []byte("b"), Value: nil, CreateRevision: 3, ModRevision: 3, Version: 1}, - {Key: []byte("c"), Value: nil, CreateRevision: 4, ModRevision: 6, Version: 3}, - {Key: []byte("foo"), Value: nil, CreateRevision: 7, ModRevision: 7, Version: 1}, - {Key: []byte("foo/abc"), Value: nil, CreateRevision: 8, ModRevision: 8, Version: 1}, - {Key: []byte("fop"), Value: nil, CreateRevision: 9, ModRevision: 9, Version: 1}, - }, - }, - // fetch entire keyspace using WithPrefix - { - "", "", - 0, - []clientv3.OpOption{clientv3.WithPrefix(), clientv3.WithSort(clientv3.SortByKey, clientv3.SortAscend)}, - - []*mvccpb.KeyValue{ - {Key: []byte("a"), Value: nil, CreateRevision: 2, ModRevision: 2, Version: 1}, - {Key: []byte("b"), Value: nil, CreateRevision: 3, ModRevision: 3, Version: 1}, - {Key: []byte("c"), Value: nil, CreateRevision: 4, ModRevision: 6, Version: 3}, - {Key: []byte("foo"), Value: nil, CreateRevision: 7, ModRevision: 7, Version: 1}, - {Key: []byte("foo/abc"), Value: nil, CreateRevision: 8, ModRevision: 8, Version: 1}, - {Key: []byte("fop"), Value: nil, CreateRevision: 9, ModRevision: 9, Version: 1}, - }, - }, - // fetch keyspace with empty key using WithFromKey - { - "", "", - 0, - []clientv3.OpOption{clientv3.WithFromKey(), clientv3.WithSort(clientv3.SortByKey, clientv3.SortAscend)}, - []*mvccpb.KeyValue{ {Key: []byte("a"), Value: nil, CreateRevision: 2, ModRevision: 2, Version: 1}, {Key: []byte("b"), Value: nil, CreateRevision: 3, ModRevision: 3, Version: 1}, From 49e9cb5f53df0d8c97ea998b3a13bcbbd0ad0677 Mon Sep 17 00:00:00 2001 From: Marek Siarkowicz Date: Fri, 18 Feb 2022 15:20:55 +0100 Subject: [PATCH 165/258] tests: Test multi member cluster --- tests/common/kv_test.go | 8 ++++---- tests/e2e/ctl_v3_kv_test.go | 1 - 2 files changed, 4 insertions(+), 5 deletions(-) diff --git a/tests/common/kv_test.go b/tests/common/kv_test.go index 2b69d7ba576d..68f3205b3823 100644 --- a/tests/common/kv_test.go +++ b/tests/common/kv_test.go @@ -36,11 +36,11 @@ func TestKVPut(t *testing.T) { }, { name: "PeerTLS", - config: config.ClusterConfig{ClusterSize: 1, PeerTLS: config.ManualTLS}, + config: config.ClusterConfig{ClusterSize: 3, PeerTLS: config.ManualTLS}, }, { name: "PeerAutoTLS", - config: config.ClusterConfig{ClusterSize: 1, PeerTLS: config.AutoTLS}, + config: config.ClusterConfig{ClusterSize: 3, PeerTLS: config.AutoTLS}, }, { name: "ClientTLS", @@ -93,11 +93,11 @@ func TestKVGet(t *testing.T) { }, { name: "PeerTLS", - config: config.ClusterConfig{ClusterSize: 1, PeerTLS: config.ManualTLS}, + config: config.ClusterConfig{ClusterSize: 3, PeerTLS: config.ManualTLS}, }, { name: "PeerAutoTLS", - config: config.ClusterConfig{ClusterSize: 1, PeerTLS: config.AutoTLS}, + config: config.ClusterConfig{ClusterSize: 3, PeerTLS: config.AutoTLS}, }, { name: "ClientTLS", diff --git a/tests/e2e/ctl_v3_kv_test.go b/tests/e2e/ctl_v3_kv_test.go index 4c902cae73ca..ae83ee1272d9 100644 --- a/tests/e2e/ctl_v3_kv_test.go +++ b/tests/e2e/ctl_v3_kv_test.go @@ -30,7 +30,6 @@ func TestCtlV3PutIgnoreValue(t *testing.T) { testCtl(t, putTestIgnoreValue) } func TestCtlV3PutIgnoreLease(t *testing.T) { testCtl(t, putTestIgnoreLease) } func TestCtlV3GetTimeout(t *testing.T) { testCtl(t, getTest, withDialTimeout(0)) } -func TestCtlV3GetQuorum(t *testing.T) { testCtl(t, getTest, withQuorum()) } func TestCtlV3GetFormat(t *testing.T) { testCtl(t, getFormatTest) } func TestCtlV3GetRev(t *testing.T) { testCtl(t, getRevTest) } From 124bc1ebbcebd63ec592a5ea05524fd76ccc35aa Mon Sep 17 00:00:00 2001 From: kkkkun Date: Tue, 1 Mar 2022 18:00:07 +0800 Subject: [PATCH 166/258] mvcc: clean up duplicate metrics name --- server/storage/mvcc/kvstore.go | 3 --- server/storage/mvcc/metrics.go | 4 ---- 2 files changed, 7 deletions(-) diff --git a/server/storage/mvcc/kvstore.go b/server/storage/mvcc/kvstore.go index dbf59239c149..846f83cde18d 100644 --- a/server/storage/mvcc/kvstore.go +++ b/server/storage/mvcc/kvstore.go @@ -500,9 +500,6 @@ func (s *store) setupMetricsReporter() { reportDbTotalSizeInBytesMu.Lock() reportDbTotalSizeInBytes = func() float64 { return float64(b.Size()) } reportDbTotalSizeInBytesMu.Unlock() - reportDbTotalSizeInBytesDebugMu.Lock() - reportDbTotalSizeInBytesDebug = func() float64 { return float64(b.Size()) } - reportDbTotalSizeInBytesDebugMu.Unlock() reportDbTotalSizeInUseInBytesMu.Lock() reportDbTotalSizeInUseInBytes = func() float64 { return float64(b.SizeInUse()) } reportDbTotalSizeInUseInBytesMu.Unlock() diff --git a/server/storage/mvcc/metrics.go b/server/storage/mvcc/metrics.go index c7ece518e478..b75abbcc0893 100644 --- a/server/storage/mvcc/metrics.go +++ b/server/storage/mvcc/metrics.go @@ -169,10 +169,6 @@ var ( reportDbTotalSizeInBytesMu sync.RWMutex reportDbTotalSizeInBytes = func() float64 { return 0 } - // overridden by mvcc initialization - reportDbTotalSizeInBytesDebugMu sync.RWMutex - reportDbTotalSizeInBytesDebug = func() float64 { return 0 } - dbTotalSizeInUse = prometheus.NewGaugeFunc(prometheus.GaugeOpts{ Namespace: "etcd", Subsystem: "mvcc", From a60abee0d46630ac10d0c96eff21daf578625487 Mon Sep 17 00:00:00 2001 From: Marek Siarkowicz Date: Thu, 24 Feb 2022 15:26:32 +0100 Subject: [PATCH 167/258] tests: Migrate kv delete tests to common framework. --- tests/common/kv_test.go | 103 ++++++++++++++++++++++++++ tests/e2e/ctl_v3_kv_test.go | 6 +- tests/framework/config/client.go | 6 ++ tests/framework/e2e/etcdctl.go | 27 ++++++- tests/framework/integration.go | 14 ++++ tests/framework/interface.go | 1 + tests/integration/clientv3/kv_test.go | 53 ------------- 7 files changed, 151 insertions(+), 59 deletions(-) diff --git a/tests/common/kv_test.go b/tests/common/kv_test.go index 68f3205b3823..2a4eccacc913 100644 --- a/tests/common/kv_test.go +++ b/tests/common/kv_test.go @@ -163,3 +163,106 @@ func TestKVGet(t *testing.T) { }) } } + +func TestKVDelete(t *testing.T) { + testRunner.BeforeTest(t) + tcs := []struct { + name string + config config.ClusterConfig + }{ + { + name: "NoTLS", + config: config.ClusterConfig{ClusterSize: 1}, + }, + { + name: "PeerTLS", + config: config.ClusterConfig{ClusterSize: 3, PeerTLS: config.ManualTLS}, + }, + { + name: "PeerAutoTLS", + config: config.ClusterConfig{ClusterSize: 3, PeerTLS: config.AutoTLS}, + }, + { + name: "ClientTLS", + config: config.ClusterConfig{ClusterSize: 1, ClientTLS: config.ManualTLS}, + }, + { + name: "ClientAutoTLS", + config: config.ClusterConfig{ClusterSize: 1, ClientTLS: config.AutoTLS}, + }, + } + for _, tc := range tcs { + t.Run(tc.name, func(t *testing.T) { + clus := testRunner.NewCluster(t, tc.config) + defer clus.Close() + cc := clus.Client() + testutils.ExecuteWithTimeout(t, 10*time.Second, func() { + kvs := []string{"a", "b", "c", "c/abc", "d"} + tests := []struct { + deleteKey string + options config.DeleteOptions + + wantDeleted int + wantKeys []string + }{ + { // delete all keys + deleteKey: "", + options: config.DeleteOptions{Prefix: true}, + wantDeleted: 5, + }, + { // delete all keys + deleteKey: "", + options: config.DeleteOptions{FromKey: true}, + wantDeleted: 5, + }, + { + deleteKey: "a", + options: config.DeleteOptions{End: "c"}, + wantDeleted: 2, + wantKeys: []string{"c", "c/abc", "d"}, + }, + { + deleteKey: "c", + wantDeleted: 1, + wantKeys: []string{"a", "b", "c/abc", "d"}, + }, + { + deleteKey: "c", + options: config.DeleteOptions{Prefix: true}, + wantDeleted: 2, + wantKeys: []string{"a", "b", "d"}, + }, + { + deleteKey: "c", + options: config.DeleteOptions{FromKey: true}, + wantDeleted: 3, + wantKeys: []string{"a", "b"}, + }, + { + deleteKey: "e", + wantDeleted: 0, + wantKeys: kvs, + }, + } + for _, tt := range tests { + for i := range kvs { + if err := cc.Put(kvs[i], "bar"); err != nil { + t.Fatalf("count not put key %q, err: %s", kvs[i], err) + } + } + del, err := cc.Delete(tt.deleteKey, tt.options) + if err != nil { + t.Fatalf("count not get key %q, err: %s", tt.deleteKey, err) + } + assert.Equal(t, tt.wantDeleted, int(del.Deleted)) + get, err := cc.Get("", config.GetOptions{Prefix: true}) + if err != nil { + t.Fatalf("count not get key, err: %s", err) + } + kvs := testutils.KeysFromGetResponse(get) + assert.Equal(t, tt.wantKeys, kvs) + } + }) + }) + } +} diff --git a/tests/e2e/ctl_v3_kv_test.go b/tests/e2e/ctl_v3_kv_test.go index ae83ee1272d9..e23d02612490 100644 --- a/tests/e2e/ctl_v3_kv_test.go +++ b/tests/e2e/ctl_v3_kv_test.go @@ -36,11 +36,7 @@ func TestCtlV3GetRev(t *testing.T) { testCtl(t, getRevTest) } func TestCtlV3GetKeysOnly(t *testing.T) { testCtl(t, getKeysOnlyTest) } func TestCtlV3GetCountOnly(t *testing.T) { testCtl(t, getCountOnlyTest) } -func TestCtlV3Del(t *testing.T) { testCtl(t, delTest) } -func TestCtlV3DelNoTLS(t *testing.T) { testCtl(t, delTest, withCfg(*e2e.NewConfigNoTLS())) } -func TestCtlV3DelClientTLS(t *testing.T) { testCtl(t, delTest, withCfg(*e2e.NewConfigClientTLS())) } -func TestCtlV3DelPeerTLS(t *testing.T) { testCtl(t, delTest, withCfg(*e2e.NewConfigPeerTLS())) } -func TestCtlV3DelTimeout(t *testing.T) { testCtl(t, delTest, withDialTimeout(0)) } +func TestCtlV3DelTimeout(t *testing.T) { testCtl(t, delTest, withDialTimeout(0)) } func TestCtlV3GetRevokedCRL(t *testing.T) { cfg := e2e.EtcdProcessClusterConfig{ diff --git a/tests/framework/config/client.go b/tests/framework/config/client.go index 47c7ba13864c..e4ad1a46cd58 100644 --- a/tests/framework/config/client.go +++ b/tests/framework/config/client.go @@ -27,3 +27,9 @@ type GetOptions struct { Order clientv3.SortOrder SortBy clientv3.SortTarget } + +type DeleteOptions struct { + Prefix bool + FromKey bool + End string +} diff --git a/tests/framework/e2e/etcdctl.go b/tests/framework/e2e/etcdctl.go index 5d79bbfbba5f..3846b79a5bd8 100644 --- a/tests/framework/e2e/etcdctl.go +++ b/tests/framework/e2e/etcdctl.go @@ -98,7 +98,7 @@ func (ctl *EtcdctlV3) Get(key string, o config.GetOptions) (*clientv3.GetRespons _, err := cmd.Expect("Count") return &resp, err } - line, err := cmd.Expect("kvs") + line, err := cmd.Expect("header") if err != nil { return nil, err } @@ -110,6 +110,31 @@ func (ctl *EtcdctlV3) Put(key, value string) error { return SpawnWithExpect(ctl.cmdArgs("put", key, value), "OK") } +func (ctl *EtcdctlV3) Delete(key string, o config.DeleteOptions) (*clientv3.DeleteResponse, error) { + args := ctl.cmdArgs() + args = append(args, "del", key, "-w", "json") + if o.End != "" { + args = append(args, o.End) + } + if o.Prefix { + args = append(args, "--prefix") + } + if o.FromKey { + args = append(args, "--from-key") + } + cmd, err := SpawnCmd(args, nil) + if err != nil { + return nil, err + } + var resp clientv3.DeleteResponse + line, err := cmd.Expect("header") + if err != nil { + return nil, err + } + err = json.Unmarshal([]byte(line), &resp) + return &resp, err +} + func (ctl *EtcdctlV3) cmdArgs(args ...string) []string { cmdArgs := []string{CtlBinPath + "3"} for k, v := range ctl.flags() { diff --git a/tests/framework/integration.go b/tests/framework/integration.go index d484fe580462..baf260f932e0 100644 --- a/tests/framework/integration.go +++ b/tests/framework/integration.go @@ -127,3 +127,17 @@ func (c integrationClient) Put(key, value string) error { _, err := c.Client.Put(context.Background(), key, value) return err } + +func (c integrationClient) Delete(key string, o config.DeleteOptions) (*clientv3.DeleteResponse, error) { + clientOpts := []clientv3.OpOption{} + if o.Prefix { + clientOpts = append(clientOpts, clientv3.WithPrefix()) + } + if o.FromKey { + clientOpts = append(clientOpts, clientv3.WithFromKey()) + } + if o.End != "" { + clientOpts = append(clientOpts, clientv3.WithRange(o.End)) + } + return c.Client.Delete(context.Background(), key, clientOpts...) +} diff --git a/tests/framework/interface.go b/tests/framework/interface.go index fb57b92ec267..4a5225dc176d 100644 --- a/tests/framework/interface.go +++ b/tests/framework/interface.go @@ -35,4 +35,5 @@ type Cluster interface { type Client interface { Put(key, value string) error Get(key string, opts config.GetOptions) (*clientv3.GetResponse, error) + Delete(key string, opts config.DeleteOptions) (*clientv3.DeleteResponse, error) } diff --git a/tests/integration/clientv3/kv_test.go b/tests/integration/clientv3/kv_test.go index 9d164760cd6c..ddb8db99e551 100644 --- a/tests/integration/clientv3/kv_test.go +++ b/tests/integration/clientv3/kv_test.go @@ -358,27 +358,6 @@ func TestKVDeleteRange(t *testing.T) { wkeys []string }{ - // [a, c) - { - key: "a", - opts: []clientv3.OpOption{clientv3.WithRange("c")}, - - wkeys: []string{"c", "c/abc", "d"}, - }, - // >= c - { - key: "c", - opts: []clientv3.OpOption{clientv3.WithFromKey()}, - - wkeys: []string{"a", "b"}, - }, - // c* - { - key: "c", - opts: []clientv3.OpOption{clientv3.WithPrefix()}, - - wkeys: []string{"a", "b", "d"}, - }, // * { key: "\x00", @@ -415,38 +394,6 @@ func TestKVDeleteRange(t *testing.T) { } } -func TestKVDelete(t *testing.T) { - integration2.BeforeTest(t) - - clus := integration2.NewCluster(t, &integration2.ClusterConfig{Size: 3}) - defer clus.Terminate(t) - - kv := clus.RandClient() - ctx := context.TODO() - - presp, err := kv.Put(ctx, "foo", "") - if err != nil { - t.Fatalf("couldn't put 'foo' (%v)", err) - } - if presp.Header.Revision != 2 { - t.Fatalf("presp.Header.Revision got %d, want %d", presp.Header.Revision, 2) - } - resp, err := kv.Delete(ctx, "foo") - if err != nil { - t.Fatalf("couldn't delete key (%v)", err) - } - if resp.Header.Revision != 3 { - t.Fatalf("resp.Header.Revision got %d, want %d", resp.Header.Revision, 3) - } - gresp, err := kv.Get(ctx, "foo") - if err != nil { - t.Fatalf("couldn't get key (%v)", err) - } - if len(gresp.Kvs) > 0 { - t.Fatalf("gresp.Kvs got %+v, want none", gresp.Kvs) - } -} - func TestKVCompactError(t *testing.T) { integration2.BeforeTest(t) From 793218ed2bfadaea235788b7e2cff2975eb34649 Mon Sep 17 00:00:00 2001 From: ahrtr Date: Mon, 7 Mar 2022 09:47:37 +0800 Subject: [PATCH 168/258] update the confstate before sending snapshot When there is a `raftpb.EntryConfChange` after creating the snapshot, then the confState included in the snapshot is out of date. so We need to update the confState before sending a snapshot to a follower. --- contrib/raftexample/raft.go | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/contrib/raftexample/raft.go b/contrib/raftexample/raft.go index 439a08375cd4..49a18f3ea462 100644 --- a/contrib/raftexample/raft.go +++ b/contrib/raftexample/raft.go @@ -456,7 +456,7 @@ func (rc *raftNode) serveChannels() { rc.publishSnapshot(rd.Snapshot) } rc.raftStorage.Append(rd.Entries) - rc.transport.Send(rd.Messages) + rc.transport.Send(rc.processMessages(rd.Messages)) applyDoneC, ok := rc.publishEntries(rc.entriesToApply(rd.CommittedEntries)) if !ok { rc.stop() @@ -476,6 +476,18 @@ func (rc *raftNode) serveChannels() { } } +// When there is a `raftpb.EntryConfChange` after creating the snapshot, +// then the confState included in the snapshot is out of date. so We need +// to update the confState before sending a snapshot to a follower. +func (rc *raftNode) processMessages(ms []raftpb.Message) []raftpb.Message { + for i := 0; i < len(ms); i++ { + if ms[i].Type == raftpb.MsgSnap { + ms[i].Snapshot.Metadata.ConfState = rc.confState + } + } + return ms +} + func (rc *raftNode) serveRaft() { url, err := url.Parse(rc.peers[rc.id-1]) if err != nil { From b7824b794bd35d178bdf872ff72648d64bae7aed Mon Sep 17 00:00:00 2001 From: cuishuang Date: Fri, 4 Mar 2022 16:04:35 +0800 Subject: [PATCH 169/258] fix some typos Signed-off-by: cuishuang fix some typos Signed-off-by: cuishuang --- CHANGELOG/CHANGELOG-3.3.md | 4 ++-- CHANGELOG/CHANGELOG-3.4.md | 2 +- client/pkg/transport/listener.go | 2 +- client/pkg/transport/transport.go | 2 +- pkg/expect/expect.go | 2 +- scripts/build.sh | 2 +- 6 files changed, 7 insertions(+), 7 deletions(-) diff --git a/CHANGELOG/CHANGELOG-3.3.md b/CHANGELOG/CHANGELOG-3.3.md index 6a4ead2ca472..c7043d730a11 100644 --- a/CHANGELOG/CHANGELOG-3.3.md +++ b/CHANGELOG/CHANGELOG-3.3.md @@ -760,7 +760,7 @@ See [code changes](https://github.com/etcd-io/etcd/compare/v3.3.2...v3.3.3) and - For every compaction period or 1-hour, compactor uses the last revision that was fetched before compaction period, to discard historical data. - The retention window of compaction period moves for every given compaction period or hour. - For instance, when hourly writes are 100 and `etcd --auto-compaction-mode=periodic --auto-compaction-retention=24h`, `v3.2.x`, `v3.3.0`, `v3.3.1`, and `v3.3.2` compact revision 2400, 2640, and 2880 for every 2.4-hour, while `v3.3.3` *or later* compacts revision 2400, 2500, 2600 for every 1-hour. - - Futhermore, when `etcd --auto-compaction-mode=periodic --auto-compaction-retention=30m` and writes per minute are about 1000, `v3.3.0`, `v3.3.1`, and `v3.3.2` compact revision 30000, 33000, and 36000, for every 3-minute, while `v3.3.3` *or later* compacts revision 30000, 60000, and 90000, for every 30-minute. + - Furthermore, when `etcd --auto-compaction-mode=periodic --auto-compaction-retention=30m` and writes per minute are about 1000, `v3.3.0`, `v3.3.1`, and `v3.3.2` compact revision 30000, 33000, and 36000, for every 3-minute, while `v3.3.3` *or later* compacts revision 30000, 60000, and 90000, for every 30-minute. ### Metrics, Monitoring @@ -963,7 +963,7 @@ See [security doc](https://etcd.io/docs/latest/op-guide/security/) for more deta - Periodic compactor continues to record latest revisions for every 1/10 of given compaction period (e.g. 1-hour when `etcd --auto-compaction-mode=periodic --auto-compaction-retention=10h`). - For every 1/10 of given compaction period, compactor uses the last revision that was fetched before compaction period, to discard historical data. - The retention window of compaction period moves for every 1/10 of given compaction period. - - For instance, when hourly writes are 100 and `--auto-compaction-retention=10`, v3.1 compacts revision 1000, 2000, and 3000 for every 10-hour, while v3.2.x, v3.3.0, v3.3.1, and v3.3.2 compact revision 1000, 1100, and 1200 for every 1-hour. Futhermore, when writes per minute are 1000, v3.3.0, v3.3.1, and v3.3.2 with `--auto-compaction-mode=periodic --auto-compaction-retention=30m` compact revision 30000, 33000, and 36000, for every 3-minute with more finer granularity. + - For instance, when hourly writes are 100 and `--auto-compaction-retention=10`, v3.1 compacts revision 1000, 2000, and 3000 for every 10-hour, while v3.2.x, v3.3.0, v3.3.1, and v3.3.2 compact revision 1000, 1100, and 1200 for every 1-hour. Furthermore, when writes per minute are 1000, v3.3.0, v3.3.1, and v3.3.2 with `--auto-compaction-mode=periodic --auto-compaction-retention=30m` compact revision 30000, 33000, and 36000, for every 3-minute with more finer granularity. - Whether compaction succeeds or not, this process repeats for every 1/10 of given compaction period. If compaction succeeds, it just removes compacted revision from historical revision records. - Add [`etcd --grpc-keepalive-min-time`, `etcd --grpc-keepalive-interval`, `etcd --grpc-keepalive-timeout`](https://github.com/etcd-io/etcd/pull/8535) flags to configure server-side keepalive policies. - Serve [`/health` endpoint as unhealthy](https://github.com/etcd-io/etcd/pull/8272) when [alarm (e.g. `NOSPACE`) is raised or there's no leader](https://github.com/etcd-io/etcd/issues/8207). diff --git a/CHANGELOG/CHANGELOG-3.4.md b/CHANGELOG/CHANGELOG-3.4.md index 4deac1150570..4b37e233acda 100644 --- a/CHANGELOG/CHANGELOG-3.4.md +++ b/CHANGELOG/CHANGELOG-3.4.md @@ -544,7 +544,7 @@ See [code changes](https://github.com/etcd-io/etcd/compare/v3.3.0...v3.4.0) and - For every compaction period or 1-hour, compactor uses the last revision that was fetched before compaction period, to discard historical data. - The retention window of compaction period moves for every given compaction period or hour. - For instance, when hourly writes are 100 and `etcd --auto-compaction-mode=periodic --auto-compaction-retention=24h`, `v3.2.x`, `v3.3.0`, `v3.3.1`, and `v3.3.2` compact revision 2400, 2640, and 2880 for every 2.4-hour, while `v3.3.3` *or later* compacts revision 2400, 2500, 2600 for every 1-hour. - - Futhermore, when `etcd --auto-compaction-mode=periodic --auto-compaction-retention=30m` and writes per minute are about 1000, `v3.3.0`, `v3.3.1`, and `v3.3.2` compact revision 30000, 33000, and 36000, for every 3-minute, while `v3.3.3` *or later* compacts revision 30000, 60000, and 90000, for every 30-minute. + - Furthermore, when `etcd --auto-compaction-mode=periodic --auto-compaction-retention=30m` and writes per minute are about 1000, `v3.3.0`, `v3.3.1`, and `v3.3.2` compact revision 30000, 33000, and 36000, for every 3-minute, while `v3.3.3` *or later* compacts revision 30000, 60000, and 90000, for every 30-minute. - Improve [lease expire/revoke operation performance](https://github.com/etcd-io/etcd/pull/9418), address [lease scalability issue](https://github.com/etcd-io/etcd/issues/9496). - Make [Lease `Lookup` non-blocking with concurrent `Grant`/`Revoke`](https://github.com/etcd-io/etcd/pull/9229). - Make etcd server return `raft.ErrProposalDropped` on internal Raft proposal drop in [v3 applier](https://github.com/etcd-io/etcd/pull/9549) and [v2 applier](https://github.com/etcd-io/etcd/pull/9558). diff --git a/client/pkg/transport/listener.go b/client/pkg/transport/listener.go index 2a5ec9a02d61..3659491d7c01 100644 --- a/client/pkg/transport/listener.go +++ b/client/pkg/transport/listener.go @@ -43,7 +43,7 @@ func NewListener(addr, scheme string, tlsinfo *TLSInfo) (l net.Listener, err err return newListener(addr, scheme, WithTLSInfo(tlsinfo)) } -// NewListenerWithOpts creates a new listener which accpets listener options. +// NewListenerWithOpts creates a new listener which accepts listener options. func NewListenerWithOpts(addr, scheme string, opts ...ListenerOption) (net.Listener, error) { return newListener(addr, scheme, opts...) } diff --git a/client/pkg/transport/transport.go b/client/pkg/transport/transport.go index 648512772d37..91462dcdb08b 100644 --- a/client/pkg/transport/transport.go +++ b/client/pkg/transport/transport.go @@ -57,7 +57,7 @@ func NewTransport(info TLSInfo, dialtimeoutd time.Duration) (*http.Transport, er TLSClientConfig: cfg, // Cost of reopening connection on sockets is low, and they are mostly used in testing. // Long living unix-transport connections were leading to 'leak' test flakes. - // Alternativly the returned Transport (t) should override CloseIdleConnections to + // Alternatively the returned Transport (t) should override CloseIdleConnections to // forward it to 'tu' as well. IdleConnTimeout: time.Microsecond, } diff --git a/pkg/expect/expect.go b/pkg/expect/expect.go index 12f95f98d9ff..3dcc6e8a2ad3 100644 --- a/pkg/expect/expect.go +++ b/pkg/expect/expect.go @@ -148,7 +148,7 @@ func (ep *ExpectProcess) Signal(sig os.Signal) error { // Close waits for the expect process to exit. // Close currently does not return error if process exited with !=0 status. -// TODO: Close should expose underlying proces failure by default. +// TODO: Close should expose underlying process failure by default. func (ep *ExpectProcess) Close() error { return ep.close(false) } func (ep *ExpectProcess) close(kill bool) error { diff --git a/scripts/build.sh b/scripts/build.sh index e587dc1893f8..f33ab3c40231 100755 --- a/scripts/build.sh +++ b/scripts/build.sh @@ -66,7 +66,7 @@ etcd_build() { "-ldflags=${GO_LDFLAGS[*]}" \ -o="../${out}/etcdctl" . || return 2 ) || return 2 - # Verify whether symbol we overriden exists + # Verify whether symbol we overwrote exists # For cross-compiling we cannot run: ${out}/etcd --version | grep -q "Git SHA: ${GIT_SHA}" # We need symbols to do this check: From 5cf6ba48de350a9d223168ff1ddd3a348ac70526 Mon Sep 17 00:00:00 2001 From: ahrtr Date: Tue, 8 Mar 2022 09:38:23 +0800 Subject: [PATCH 170/258] added a unit test for the method processMessages --- contrib/raftexample/raft_test.go | 129 +++++++++++++++++++++++++++++++ 1 file changed, 129 insertions(+) create mode 100644 contrib/raftexample/raft_test.go diff --git a/contrib/raftexample/raft_test.go b/contrib/raftexample/raft_test.go new file mode 100644 index 000000000000..53d9ad2f7604 --- /dev/null +++ b/contrib/raftexample/raft_test.go @@ -0,0 +1,129 @@ +// Copyright 2022 The etcd Authors +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package main + +import ( + "go.etcd.io/etcd/raft/v3/raftpb" + "reflect" + "testing" +) + +func TestProcessMessages(t *testing.T) { + cases := []struct { + name string + confState raftpb.ConfState + InputMessages []raftpb.Message + ExpectedMessages []raftpb.Message + }{ + { + name: "only one snapshot message", + confState: raftpb.ConfState{ + Voters: []uint64{2, 6, 8, 10}, + }, + InputMessages: []raftpb.Message{ + { + Type: raftpb.MsgSnap, + To: 8, + Snapshot: raftpb.Snapshot{ + Metadata: raftpb.SnapshotMetadata{ + Index: 100, + Term: 3, + ConfState: raftpb.ConfState{ + Voters: []uint64{2, 6, 8}, + AutoLeave: true, + }, + }, + }, + }, + }, + ExpectedMessages: []raftpb.Message{ + { + Type: raftpb.MsgSnap, + To: 8, + Snapshot: raftpb.Snapshot{ + Metadata: raftpb.SnapshotMetadata{ + Index: 100, + Term: 3, + ConfState: raftpb.ConfState{ + Voters: []uint64{2, 6, 8, 10}, + }, + }, + }, + }, + }, + }, + { + name: "one snapshot message and one other message", + confState: raftpb.ConfState{ + Voters: []uint64{2, 7, 8, 12}, + }, + InputMessages: []raftpb.Message{ + { + Type: raftpb.MsgSnap, + To: 8, + Snapshot: raftpb.Snapshot{ + Metadata: raftpb.SnapshotMetadata{ + Index: 100, + Term: 3, + ConfState: raftpb.ConfState{ + Voters: []uint64{2, 6, 8}, + AutoLeave: true, + }, + }, + }, + }, + { + Type: raftpb.MsgApp, + From: 6, + To: 8, + }, + }, + ExpectedMessages: []raftpb.Message{ + { + Type: raftpb.MsgSnap, + To: 8, + Snapshot: raftpb.Snapshot{ + Metadata: raftpb.SnapshotMetadata{ + Index: 100, + Term: 3, + ConfState: raftpb.ConfState{ + Voters: []uint64{2, 7, 8, 12}, + }, + }, + }, + }, + { + Type: raftpb.MsgApp, + From: 6, + To: 8, + }, + }, + }, + } + + for _, tc := range cases { + t.Run(tc.name, func(t *testing.T) { + rn := &raftNode{ + confState: tc.confState, + } + + outputMessages := rn.processMessages(tc.InputMessages) + + if !reflect.DeepEqual(outputMessages, tc.ExpectedMessages) { + t.Fatalf("Unexpected messages, expected: %v, got %v", tc.ExpectedMessages, outputMessages) + } + }) + } +} From b6a2d2d48ac5fcd8d7914537f4fa9f0bc11d27b8 Mon Sep 17 00:00:00 2001 From: Luiz Gustavo Date: Tue, 8 Mar 2022 02:29:20 -0300 Subject: [PATCH 171/258] tools: Add -wal-dir flag on etcd-dump-logs to make it compatible with ETCD_WAL_DIR variable (#13672) --- tools/etcd-dump-logs/README.md | 4 +++- tools/etcd-dump-logs/main.go | 8 +++++++- 2 files changed, 10 insertions(+), 2 deletions(-) diff --git a/tools/etcd-dump-logs/README.md b/tools/etcd-dump-logs/README.md index b6edc3021349..176d8a47dcae 100644 --- a/tools/etcd-dump-logs/README.md +++ b/tools/etcd-dump-logs/README.md @@ -13,7 +13,9 @@ Usage: - data_dir/member/wal/0000000000000000-0000000000000000.wal Flags: - + -wal-dir string + If set, dumps WAL from the informed path, rather than following the + standard 'data_dir/member/wal/' location -entry-type string If set, filters output by entry type. Must be one or more than one of: ConfigChange, Normal, Request, InternalRaftRequest, diff --git a/tools/etcd-dump-logs/main.go b/tools/etcd-dump-logs/main.go index 899f40591d26..cda3dd5b8b78 100644 --- a/tools/etcd-dump-logs/main.go +++ b/tools/etcd-dump-logs/main.go @@ -45,6 +45,7 @@ const ( func main() { snapfile := flag.String("start-snap", "", "The base name of snapshot file to start dumping") + waldir := flag.String("wal-dir", "", "If set, dumps WAL from the informed path, rather than following the standard 'data_dir/member/wal/' location") index := flag.Uint64("start-index", 0, "The index to start dumping") // Default entry types are Normal and ConfigChange entrytype := flag.String("entry-type", defaultEntryTypes, `If set, filters output by entry type. Must be one or more than one of: @@ -103,7 +104,12 @@ and output a hex encoded line of binary for each input line`) fmt.Println("Start dumping log entries from snapshot.") } - w, err := wal.OpenForRead(zap.NewExample(), walDir(dataDir), walsnap) + wd := *waldir + if wd == "" { + wd = walDir(dataDir) + } + + w, err := wal.OpenForRead(zap.NewExample(), wd, walsnap) if err != nil { log.Fatalf("Failed opening WAL: %v", err) } From 8800f0cabb948e4e8e00d277eb9a690c6783bf86 Mon Sep 17 00:00:00 2001 From: kkkkun Date: Tue, 8 Mar 2022 17:04:03 +0800 Subject: [PATCH 172/258] clean up stack log --- etcdutl/snapshot/v3_snapshot.go | 1 - 1 file changed, 1 deletion(-) diff --git a/etcdutl/snapshot/v3_snapshot.go b/etcdutl/snapshot/v3_snapshot.go index cf7b4a6ebfc5..7df6bab33629 100644 --- a/etcdutl/snapshot/v3_snapshot.go +++ b/etcdutl/snapshot/v3_snapshot.go @@ -262,7 +262,6 @@ func (s *v3Manager) Restore(cfg RestoreConfig) error { zap.String("wal-dir", s.walDir), zap.String("data-dir", dataDir), zap.String("snap-dir", s.snapDir), - zap.Stack("stack"), ) if err = s.saveDB(); err != nil { From 1ae5aa52de5bde7afc940fe8a75f58c7b43b9f3e Mon Sep 17 00:00:00 2001 From: ahrtr Date: Wed, 9 Mar 2022 15:12:20 +0800 Subject: [PATCH 173/258] fix some typos related to downgrade --- etcdctl/README.md | 4 ++-- server/etcdserver/version/monitor.go | 4 ++-- server/storage/schema/schema.go | 2 +- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/etcdctl/README.md b/etcdctl/README.md index 66dfc619f3a1..db273ec838d9 100644 --- a/etcdctl/README.md +++ b/etcdctl/README.md @@ -1094,8 +1094,8 @@ After initial bootstrap, cluster members agree on the cluster version. Every 5 s New members will refuse joining cluster with cluster version newer than theirs, thus preventing cluster from downgrading. Downgrade commands allow cluster administrator to force cluster version to be lowered to previous minor version, thus allowing to downgrade the cluster. -Downgrade should be is executed in stages: -1. Verify that cluster is ready be downgraded by running `etcdctl downgrade validate ` +Downgrade should be executed in stages: +1. Verify that cluster is ready to be downgraded by running `etcdctl downgrade validate ` 2. Start the downgrade process by running `etcdctl downgrade enable ` 3. For each cluster member: 1. Ensure that member is ready for downgrade by confirming that it wrote `The server is ready to downgrade` log. diff --git a/server/etcdserver/version/monitor.go b/server/etcdserver/version/monitor.go index 8ac8d8e8d687..2ccc897a0d5a 100644 --- a/server/etcdserver/version/monitor.go +++ b/server/etcdserver/version/monitor.go @@ -101,11 +101,11 @@ func (m *Monitor) UpdateStorageVersionIfNeeded() { if sv == nil || sv.Major != cv.Major || sv.Minor != cv.Minor { if sv != nil { - m.lg.Info("storage version differs from storage version.", zap.String("cluster-version", cv.String()), zap.String("storage-version", sv.String())) + m.lg.Info("cluster version differs from storage version.", zap.String("cluster-version", cv.String()), zap.String("storage-version", sv.String())) } err := m.s.UpdateStorageVersion(semver.Version{Major: cv.Major, Minor: cv.Minor}) if err != nil { - m.lg.Error("failed update storage version", zap.String("cluster-version", cv.String()), zap.Error(err)) + m.lg.Error("failed to update storage version", zap.String("cluster-version", cv.String()), zap.Error(err)) return } d := m.s.GetDowngradeInfo() diff --git a/server/storage/schema/schema.go b/server/storage/schema/schema.go index f3b29c01154a..889b4e8d7152 100644 --- a/server/storage/schema/schema.go +++ b/server/storage/schema/schema.go @@ -73,7 +73,7 @@ func UnsafeMigrate(lg *zap.Logger, tx backend.BatchTx, w WALVersion, target semv } plan, err := newPlan(lg, current, target) if err != nil { - return fmt.Errorf("cannot create migration plan: %w", err) + return fmt.Errorf("cannot create migration plan: %v", err) } if target.LessThan(current) { minVersion := w.MinimalEtcdVersion() From d578a86a5943f48ce6f58d399165bd7b00de5f05 Mon Sep 17 00:00:00 2001 From: ahrtr Date: Thu, 10 Mar 2022 03:26:34 +0800 Subject: [PATCH 174/258] fix some log format typos --- etcdutl/etcdutl/migrate_command.go | 2 +- server/embed/config_logging.go | 4 ++-- server/storage/schema/membership.go | 4 ++-- server/storage/schema/schema.go | 2 +- tests/functional/tester/cluster.go | 2 +- 5 files changed, 7 insertions(+), 7 deletions(-) diff --git a/etcdutl/etcdutl/migrate_command.go b/etcdutl/etcdutl/migrate_command.go index e9bac4f37a5f..c3a02cb4a266 100644 --- a/etcdutl/etcdutl/migrate_command.go +++ b/etcdutl/etcdutl/migrate_command.go @@ -83,7 +83,7 @@ func (o *migrateOptions) Config() (*migrateConfig, error) { } c.targetVersion, err = semver.NewVersion(o.targetVersion + ".0") if err != nil { - return nil, fmt.Errorf("failed to parse target version: %w", err) + return nil, fmt.Errorf("failed to parse target version: %v", err) } if c.targetVersion.LessThan(schema.V3_5) { return nil, fmt.Errorf(`target version %q not supported. Minimal "3.5"`, storageVersionToString(c.targetVersion)) diff --git a/server/embed/config_logging.go b/server/embed/config_logging.go index b019289e6deb..2ebdb5e27b80 100644 --- a/server/embed/config_logging.go +++ b/server/embed/config_logging.go @@ -269,9 +269,9 @@ func setupLogRotation(logOutputs []string, logRotateConfigJSON string) error { var syntaxError *json.SyntaxError switch { case errors.As(err, &syntaxError): - return fmt.Errorf("improperly formatted log rotation config: %w", err) + return fmt.Errorf("improperly formatted log rotation config: %v", err) case errors.As(err, &unmarshalTypeError): - return fmt.Errorf("invalid log rotation config: %w", err) + return fmt.Errorf("invalid log rotation config: %v", err) } } zap.RegisterSink("rotate", func(u *url.URL) (zap.Sink, error) { diff --git a/server/storage/schema/membership.go b/server/storage/schema/membership.go index 0b9cc0e497b9..844b50a85a4f 100644 --- a/server/storage/schema/membership.go +++ b/server/storage/schema/membership.go @@ -102,7 +102,7 @@ func (s *membershipBackend) readMembersFromBackend() (map[types.ID]*membership.M return nil }) if err != nil { - return nil, nil, fmt.Errorf("couldn't read members from backend: %w", err) + return nil, nil, fmt.Errorf("couldn't read members from backend: %v", err) } err = tx.UnsafeForEach(MembersRemoved, func(k, v []byte) error { @@ -111,7 +111,7 @@ func (s *membershipBackend) readMembersFromBackend() (map[types.ID]*membership.M return nil }) if err != nil { - return nil, nil, fmt.Errorf("couldn't read members_removed from backend: %w", err) + return nil, nil, fmt.Errorf("couldn't read members_removed from backend: %v", err) } return members, removed, nil } diff --git a/server/storage/schema/schema.go b/server/storage/schema/schema.go index 889b4e8d7152..850b55d5bd56 100644 --- a/server/storage/schema/schema.go +++ b/server/storage/schema/schema.go @@ -69,7 +69,7 @@ func Migrate(lg *zap.Logger, tx backend.BatchTx, w WALVersion, target semver.Ver func UnsafeMigrate(lg *zap.Logger, tx backend.BatchTx, w WALVersion, target semver.Version) error { current, err := UnsafeDetectSchemaVersion(lg, tx) if err != nil { - return fmt.Errorf("cannot detect storage schema version: %w", err) + return fmt.Errorf("cannot detect storage schema version: %v", err) } plan, err := newPlan(lg, current, target) if err != nil { diff --git a/tests/functional/tester/cluster.go b/tests/functional/tester/cluster.go index 256b61458afc..796ad5574f95 100644 --- a/tests/functional/tester/cluster.go +++ b/tests/functional/tester/cluster.go @@ -88,7 +88,7 @@ func NewCluster(lg *zap.Logger, fpath string) (*Cluster, error) { var err error clus.agentConns[i], err = grpc.Dial(ap.AgentAddr, dialOpts...) if err != nil { - return nil, fmt.Errorf("cannot dial agent %v: %w", ap.AgentAddr, err) + return nil, fmt.Errorf("cannot dial agent %v: %v", ap.AgentAddr, err) } clus.agentClients[i] = rpcpb.NewTransportClient(clus.agentConns[i]) lg.Info("connected", zap.String("agent-address", ap.AgentAddr)) From 3ecd8d23642230c6ca164aed2a945fe89fb9d831 Mon Sep 17 00:00:00 2001 From: ahrtr Date: Thu, 10 Mar 2022 04:25:47 +0800 Subject: [PATCH 175/258] update incorrect migration log message It can be upgrade or downgrade, so we should use word "updated" here. --- server/storage/schema/migration.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/server/storage/schema/migration.go b/server/storage/schema/migration.go index c8c4a701ba6c..47734b4b851a 100644 --- a/server/storage/schema/migration.go +++ b/server/storage/schema/migration.go @@ -60,7 +60,7 @@ func (p migrationPlan) unsafeExecute(lg *zap.Logger, tx backend.BatchTx) (err er if err != nil { return err } - lg.Info("upgraded storage version", zap.String("new-storage-version", s.target.String())) + lg.Info("updated storage version", zap.String("new-storage-version", s.target.String())) } return nil } From 34cd8ae1a2474aaa5c0b879d0ca110267061459a Mon Sep 17 00:00:00 2001 From: kkkkun Date: Thu, 10 Mar 2022 17:01:47 +0800 Subject: [PATCH 176/258] tests: Migrate compact tests to common framework --- tests/common/compact_test.go | 87 +++++++++++++++++++++++++++ tests/framework/config/client.go | 10 ++- tests/framework/e2e/etcdctl.go | 14 +++++ tests/framework/integration.go | 14 +++++ tests/framework/interface.go | 1 + tests/framework/testutils/helpters.go | 15 ++++- 6 files changed, 139 insertions(+), 2 deletions(-) create mode 100644 tests/common/compact_test.go diff --git a/tests/common/compact_test.go b/tests/common/compact_test.go new file mode 100644 index 000000000000..8effa94e1277 --- /dev/null +++ b/tests/common/compact_test.go @@ -0,0 +1,87 @@ +// Copyright 2022 The etcd Authors +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package common + +import ( + "strings" + "testing" + "time" + + "github.com/stretchr/testify/assert" + "go.etcd.io/etcd/tests/v3/framework/config" + "go.etcd.io/etcd/tests/v3/framework/testutils" +) + +func TestCompact(t *testing.T) { + + testRunner.BeforeTest(t) + tcs := []struct { + name string + options config.CompactOption + }{ + { + name: "NoPhysical", + options: config.CompactOption{Physical: false, Timeout: 10 * time.Second}, + }, + { + name: "Physical", + options: config.CompactOption{Physical: true, Timeout: 10 * time.Second}, + }, + } + for _, tc := range tcs { + t.Run(tc.name, func(t *testing.T) { + clus := testRunner.NewCluster(t, config.ClusterConfig{ClusterSize: 3}) + defer clus.Close() + testutils.ExecuteWithTimeout(t, 10*time.Second, func() { + var kvs = []testutils.KV{{Key: "key", Val: "val1"}, {Key: "key", Val: "val2"}, {Key: "key", Val: "val3"}} + for i := range kvs { + if err := clus.Client().Put(kvs[i].Key, kvs[i].Val); err != nil { + t.Fatalf("compactTest #%d: put kv error (%v)", i, err) + } + } + get, err := clus.Client().Get("key", config.GetOptions{Revision: 3}) + if err != nil { + t.Fatalf("compactTest: Get kv by revision error (%v)", err) + } + + getkvs := testutils.KeyValuesFromGetResponse(get) + assert.Equal(t, kvs[1:2], getkvs) + + _, err = clus.Client().Compact(4, tc.options) + if err != nil { + t.Fatalf("compactTest: Compact error (%v)", err) + } + + get, err = clus.Client().Get("key", config.GetOptions{Revision: 3}) + if err != nil { + if !strings.Contains(err.Error(), "required revision has been compacted") { + t.Fatalf("compactTest: Get compact key error (%v)", err) + } + } else { + t.Fatalf("expected '...has been compacted' error, got ") + } + + _, err = clus.Client().Compact(2, tc.options) + if err != nil { + if !strings.Contains(err.Error(), "required revision has been compacted") { + t.Fatal(err) + } + } else { + t.Fatalf("expected '...has been compacted' error, got ") + } + }) + }) + } +} diff --git a/tests/framework/config/client.go b/tests/framework/config/client.go index e4ad1a46cd58..c41565b47186 100644 --- a/tests/framework/config/client.go +++ b/tests/framework/config/client.go @@ -14,7 +14,10 @@ package config -import clientv3 "go.etcd.io/etcd/client/v3" +import ( + clientv3 "go.etcd.io/etcd/client/v3" + "time" +) type GetOptions struct { Revision int @@ -33,3 +36,8 @@ type DeleteOptions struct { FromKey bool End string } + +type CompactOption struct { + Physical bool + Timeout time.Duration +} diff --git a/tests/framework/e2e/etcdctl.go b/tests/framework/e2e/etcdctl.go index 3846b79a5bd8..f807c7fe67d1 100644 --- a/tests/framework/e2e/etcdctl.go +++ b/tests/framework/e2e/etcdctl.go @@ -162,3 +162,17 @@ func (ctl *EtcdctlV3) flags() map[string]string { fmap["endpoints"] = strings.Join(ctl.endpoints, ",") return fmap } + +func (ctl *EtcdctlV3) Compact(rev int64, o config.CompactOption) (*clientv3.CompactResponse, error) { + args := ctl.cmdArgs() + args = append(args, "compact", fmt.Sprint(rev)) + + if o.Timeout != 0 { + args = append(args, fmt.Sprintf("--command-timeout=%s", o.Timeout)) + } + if o.Physical { + args = append(args, "--physical") + } + + return nil, SpawnWithExpect(args, fmt.Sprintf("compacted revision %v", rev)) +} diff --git a/tests/framework/integration.go b/tests/framework/integration.go index baf260f932e0..18aabed5a334 100644 --- a/tests/framework/integration.go +++ b/tests/framework/integration.go @@ -141,3 +141,17 @@ func (c integrationClient) Delete(key string, o config.DeleteOptions) (*clientv3 } return c.Client.Delete(context.Background(), key, clientOpts...) } + +func (c integrationClient) Compact(rev int64, o config.CompactOption) (*clientv3.CompactResponse, error) { + ctx := context.Background() + if o.Timeout != 0 { + var cancel context.CancelFunc + ctx, cancel = context.WithTimeout(ctx, o.Timeout) + defer cancel() + } + clientOpts := []clientv3.CompactOption{} + if o.Physical { + clientOpts = append(clientOpts, clientv3.WithCompactPhysical()) + } + return c.Client.Compact(ctx, rev, clientOpts...) +} diff --git a/tests/framework/interface.go b/tests/framework/interface.go index 4a5225dc176d..5c1ac01145a6 100644 --- a/tests/framework/interface.go +++ b/tests/framework/interface.go @@ -36,4 +36,5 @@ type Client interface { Put(key, value string) error Get(key string, opts config.GetOptions) (*clientv3.GetResponse, error) Delete(key string, opts config.DeleteOptions) (*clientv3.DeleteResponse, error) + Compact(rev int64, opts config.CompactOption) (*clientv3.CompactResponse, error) } diff --git a/tests/framework/testutils/helpters.go b/tests/framework/testutils/helpters.go index ecc165a86857..c508bd274919 100644 --- a/tests/framework/testutils/helpters.go +++ b/tests/framework/testutils/helpters.go @@ -14,7 +14,13 @@ package testutils -import clientv3 "go.etcd.io/etcd/client/v3" +import ( + clientv3 "go.etcd.io/etcd/client/v3" +) + +type KV struct { + Key, Val string +} func KeysFromGetResponse(resp *clientv3.GetResponse) (kvs []string) { for _, kv := range resp.Kvs { @@ -22,3 +28,10 @@ func KeysFromGetResponse(resp *clientv3.GetResponse) (kvs []string) { } return kvs } + +func KeyValuesFromGetResponse(resp *clientv3.GetResponse) (kvs []KV) { + for _, kv := range resp.Kvs { + kvs = append(kvs, KV{Key: string(kv.Key), Val: string(kv.Value)}) + } + return kvs +} From 1bfc88a8d673d62143ef595c650c2bab6f39d5dd Mon Sep 17 00:00:00 2001 From: AdamKorcz Date: Fri, 11 Mar 2022 11:21:56 +0000 Subject: [PATCH 177/258] Add fuzzing audit report --- security/FUZZING_AUDIT_2022.PDF | Bin 0 -> 282738 bytes security/README.md | 1 + 2 files changed, 1 insertion(+) create mode 100644 security/FUZZING_AUDIT_2022.PDF diff --git a/security/FUZZING_AUDIT_2022.PDF b/security/FUZZING_AUDIT_2022.PDF new file mode 100644 index 0000000000000000000000000000000000000000..695ce764ee024bb348df243635668c41c4b5b54d GIT binary patch literal 282738 zcmeFXWmKHawl0bWhhTx=0fI~8F2UX1-CctdG-z-QZUGv1Y24jig1b8eIL-I1v)9^Z z?K95UW86RY-qSz2-%)ecGksQdz4ci^M2wz^ffe!d^wGfvA`=OK#NNmXk(ZZI#nQ#b zl!Qv##L3XiMVG|X#n^>Lg4IEPsDE5E*4IPOhf^H7XO}pRg(( z4yGiG8uCU~rp7Mdd9Fq-e~n1m8k&Qrt6Q45Sdg%Aup%-_m|B`!xR5Y2gQW=D+t@oP zI~W>+=ZcuRSsI%vi3@>e%NjaclQ6w`PzfyB(#2W9)JfRh*1_J+)Xs&36OmEO(#8es zDn>CILl;vKQ)7D*un-wjJ9DrURyIxmKR=1Hi<7CLE#lXoCmGgG6WkbLUgj+B=-X$e zlqupu5+n*LU$C_YXo@IH(g(@2?Up@VmiI&isNj=ktbCG8ia%p~Z@6@e6`kH9)+)H{ zSiD&l(&iD7USc@gd7f@hwLSZi5bhTzKdSqzVx}X?xJoM6aU2CT9 zydd)J+TyHk=XEC0CqhfWl_r1bK&0bk`!yVqMqgX8xw<>-wAbCrwb7&9fmxT5UZg$Wu8=gO>(l0 zyqHm6Kim53X!@5-3rT#eLYZVUbt9zAr9|7WFXr6yQ7yC7kfMA`X%agH4=m;zj>C(l zE4}Yxsgc}kklOIfPt^FPxx7!5vdDjxw#IUdp5z5~579DDiX5CHDr*z~e$ex@%p7SD z5X&_1&FPq1=*08Vp=FWLCQ-jOZwv}-_k&i{Gl5aL@x^o4R^yUbg}+r&#IsU$*RT^{ zlZY6V_e^RWec}wbr*=ClhlZn8REWwitF3I!KbSjb?qr#A$oFE7Ch8HLd#lBcx;hRy zO)ur=*u_`Fw?1rCY^y#$lqSuXISTDL`f`u3sWS_FI>`3C>gEfvQcq+}iSMt=ipjjN ze?~uGVjvtuz!qCM+o7Ai`?ZsKw`zzy`=QQC*W~ucx7Vchn)K(|%$ml#FQW{_QPhl2 z){e-+Y});e+WKd)r_1Xv#;^4KW77&$8B!`r6XJOT*8VKuJfOM?rG~40qK~9WE&39gV96LeFrP-FKykJUPBMeK-h(uE-`t+8FEeX zB1ft?spVNyDtgS(M2ff<)H1&`_Dw6kY6L5KNTU1N(wlvKP`@m(hGf2-i!`+x>%=N- zJ!t;WQLC}-bG&>GL(9OF_qcITHpy+%40T76-1YU8_Yj1@l~;P!6UlL-rFX|5ELKxQ z>wxA&E%RJ?lA<=ef5@W;zXUN>;LwC%oWFRoC*JC;{E6FMAAvIN3`WG`|>ZZqr=Q9 z>|0yoN)O~{sYakLuqhf#)$O=6iR{jv8P zq?>>V3d=icc9cm93Mp^_w2_{Q=eT7aTPo@RbH8b5+gU_ggx$BHGYnqdq5X8<1-E+W|mcHd7saf`fW$Uv;AaU-AL_V|_`myY0Mdb*u7 znxPkP#|`X~unE4oLe1}14Cb34cY>Ko?Pf5dw`DVcgBBoUfP;;p>Hm%-pPRPqT2s@=HrHg;^ zm?~046<2;*#5%)Maah9F?IVgz;QH{h`~z1@%4=x9ycvq|)Pn<>LW)`nBBs8{hoj~- z{|hSKOJ-}___0tg|E^k6o_qGSN1U}hDk z9T&opN~TdVplK371{}(d%L8C28S)SBNnIaIQGE$W;p=wxCOP&zGm?$n6e;o!`S{s) zZXYQ)HU`m|e*T6u*wuA91-g88Eu?7MuujpNV>PnDyMr`}GOa6xhajLKqQ4j_XHutE_Gy+G|ShPZPk=}N|~b>djc^-Gjv(QLrPht6_=#3inx+ZmXXzg zEi@aVj*=&Y0)UyJ(#l*~d3Pc0xjhr*{8peG0hlmY0FVyB-EOebte9@muuVva3MxBA%MBI7Zbdl;->sIG_`mJiq+AsxmlR%qWLAGp)6xhaCn z)rt7X?Yr%T7#s^gRPHKL2?sAsN2Y0;NtiWXbD$7B0Tt~Zx#qRqvHC%#IGH=W6Z!xA&1iY)rXTrYa=*~?4c z_%?2cE{kTlR+kNU{;tC)|2{L4oiSzovX5XKZTXQbwH#pP@Z)ng|C&IR2uib3z&XL} z>*!StGdTq|A{iuBAyGC^$1&47>W-QSE*(R57`ZEc>2(yB#MnrQaG}e$kai?vWfm!W zEE{#Y0z&uVe&POmcBYc4yKjvfbZ#2)+5pim&B*4$Rt5-rWGSkB3pp5E`eu_CS1ZgW z9Mz!*h+F8Xa!o%vjW;^)Y8mDZ75+r1%gEG}!g_{Ad@&>s=^|*s<}K&HEcduFwrg6l z)bMyTTyvV@p_tw9S?(4IzE}`gA}n0i0BXyLm9zQ8pzVg#8dF7j3`?G+s8B`rsHH%% z>@cM$V6*Q?-iN`6`1^iTj@&5-;MOamP8P+$xj`G|67 zj;HVSKfyW+8k&@J^{mLPqfO6%wvxUQynN-i2P<7MM_GF-T}T!A(VpfWtTaG&)r+mK z7_cW(gS8| zas*2*eTcTAX_QZsW1JPQ5H^h#xm-^^BZO&e=eu*EoO_sOwOytqs|*sWI<5{Vj+~gU>$%cv-0xj$ofvpUbwcBBnrI%XG==T2a8{TvHj`%`nEes z{^9|d3b~}2q2r<7$3{k4**RSa`_o0wxO~I2iZ|3|>hH{PFsGqVu=_sxq|Hp+jp&H2 zZSfLbC1F0p5}wr!*=f*<_tgs027g>E+caLvQN6G8WC#?Vmg#TZ5!n%?Of0MJ-hd5G z4YCYX+n67TRMOw6`~c4LdL~wfuU`x)441y>`n=LBF8ujSW*cx}n$Q(_pwQHqbhI`} zriid5Uorr3`bjU$Kcywmt+}}$ zG;VekV40*wW`!jdLKXQCR;lkF{hLlLyPYp9ZZwH+L>1MVi9YXgYWo)(BAGB&p$n$W zGsZN9myuHHCEM@K-ITA~zVUf;RFRQNDc$;VpeWyRJASp`BO!*gc`Bp`S8+YeED^(= zBEb6g^6nl_o@srl0`mxxPg1C8N!^bd+}5AY0+g8*U#Vm;dByJOvN#0RKgKoa2FDrd z?JMUNR`>uv2JL-S=K^-Q3{Y4HQbpcJR`#PB>wPG;EPwYpm1Q+dbV(ChH)BlCKX!Cy z@@-Groa{QO!uWU9c*)18vDT5`iZyqZ-u{n87V;lB+p__XfRh?4)j7E;v+6!UPN{2@q zFRPB3TXN7019Fgv)9Fh6kFHG7r_@@3Yqkr7-COL&ZH;>;oLEzba`nW6_nHafF()7B~Jl91l_(EmndXH~> z-Pz>6sn|vXOO{`q8ED8q3-YaxpNG)s}?=e3lLy}Ejx{) zWCUjP8xxoLI`JKEMs1vLm{g!G@7_PWDKWd*bMDt5gJh|QJ+Vx{2JgiKDJ^1%`$SF zLdtc~ibbS76gfM0TYm?=RrOF}IC8PQQ#=5a`tfQl4?U~<%ycriN&buE7o7^K3vY9C zo4DOhz1=z5<(Dk>7CD6T>jYJFS&r)-=%PC3k>r#MGaRhGP{e>etb7UBYpmnn z{a~ut9`X?1*z}SmVCGW|d_LI>=rSIu?l7vqJT4&@4h?p#DQ)1ff1kcKT11Ym zn$eVuwpfNIilX;}AH*BEr)}zv@!@E9y1A8?{qES4yc<)0>7%oOr+HSK-FD$ZrD5K$ z&ZE@RMM`fiEtE?0d9sf?&&xw4JIO!z)IBv@cB7OALEcWY6xOAd=GhwK$ZOi`Re%-@ z>Wh^5*V+a&#g*Zg+5>IPwBsP^CnY`Ki{lxB%L&rN%j2*)U#B6t8w|xJQnCSQXPH>d zo7(FBms0Nx2K1+$0^IF9@0rDkN*}eG%io7yRFuPdZ7%>ii2v7rIwW48_r4f>dpisJ z$8pa;PR0H@JNloeZ~qS+O^G`hdi?iKquAM**#6ULl&(j%oau|-Y6NYya*_y@iItF) ztPnm+;vYKMKD_EaLTpPFi-+fY-3W`EVvz{yxHK%%Le`L+7@>N)rrYN=FWM+uSj?V z_I0j~tf{liBd>*krDC(`38^I{V? zDx>`4JlAlz&0pr>ks=77)1@9ms&BcBm1kzjj`S^ovA>57nu^=qRwG8d@8ubG@M)_0 zKc<&h1_o=LU$Z7L-ILBH7dz>9TB zPUs<&hjwZw+~Aw?#qN7hNw%!Tk2ok?;SU+m;vNG{1H=5d4%H{#vAA>Rv4FYE_#8LP zOr9&}oS!(NlV)o>Bg@RxPdbAg5Xp+WF*7E~OjS`*%=i?Y`KI{wg-0KrU&;=740h$ zJ1k1~N6bF1ttK`V*~$y#eg1T&4WqUBE@51t`9?v8CoNXzR&)UGhvKNO`VrjBo#_|U z&O>* z0&g1*Q1m+@GRJ3!ypTH_I`hZjx8W^DD+(b)z6%J8XH8k(a5CR&W@jmS&I=|mP|l36 z_yrtf{BK*MsI({tjdln|CMkyFI4{D3Cdl|CPUkt=^4MUx%4>mlGF=>d>okk-p*KC_ z+4WiBE?zOGL;y>88RlbBzi~ycUoIW_c$IwYdV^vTz`O{lgRYl)GH=%X#3!Kg7_bOy zUPAoAIC|;e+w_Ny&nklr=om-ma<)FXB;FJ~d#(7KC(7n?Zh37{%Z57~aB@dz)8%SR z7#K%^Urv4?cCCJCH2z(?1~}2GW1G5g7pFGABhdAZSBVVj@kCQ-5&v>eCZ1H|6+I6% zn&FL8(pk?xt_%~gQo6YeA9k}Wc!J=uNOR7T)|U!@Y7^fUWtjUaxN5K|i>TIRwi>q% zfe({=!im|^(etXPO^)*FpyEWhVT#JbvaVE#!F_ajI^7$+ZMTM_cIeM?MOY`QA!q?KZOPL>~u>RRNm_e!e)JlJHcFXZ+Vp1>bagGnpJxH*&B zrctaNW}9Zd0OB@5zrSb|PB0DU>jL3tPP^52COZ=_YR~OZ@%qlYH23VJ{oHmxBYM!= zwns+G3acdqDEu!XU?{et&q*wKVvU~_-(xMN*~7+%7Sm0I8omEbf<+Ov_JgqiMKsFw z8U_h8lY3{JIz;Nz!Fb`DbMQVVR$qKhVMe3>SE!@V^e3TiZhga8{#Np$6T}qX3SiE! zsuzL*T`E@4M;Sjs!&tq9`&mVbee9msVb$s+(mrmnnldabi2g>kuJFKg!%=qxM8TkU zY%~CPbYoE2u>ie@g@)`l&Oxt>xat~L02FS{mk56pp&pH_T?vHsY`lOBgemLmTvm}j z2CNUUUyGeSX#w+!Gl zfN_@AsCnD^v)G~vm1lP(hEV_@WL$ksy7~)dQI(k~?|n{{_Nfpa_1y3`_k9+GPv0j7 z2IF+|@lzn?goWVASbZ5yX_bJ+P$@FrtYQ|m$zW0p1Vx>#4k3ZBUt%>j_1q`OW0B7Y zIVJCNaxyEG;AJ4ZlQBNeZG01)!qh}nDoeyv!=Sd;u8>9)3KA0} z0TQDd5fb~ZC$YX8PcPDF!iMTFU~3AEO@NPj!4Lw|Fgo&U%r920zULbt`Z}l_$KG@q z1oc57ksV|Hvq?~@3TRU|daxM=jlRH_%0eF+k4s~8KUB7q#S z`b-~=jz`vGn%m7y?yos7sof2a(i@a0@@{*8<~YX?9Kz>}=z+>;1_ir;WMbT$3s5Z; zWb;#&%KH#_l+vn736nR_J*<(O?kgkM4G~1gQS6`#TFi=<4Y~(0fJv1~ zh=?atv-ZLjd5tbA8shR79}+S9hvNl1aA8v*ZY#rGrn(t)p6O}8QCKjRy3K@f^mQPI z1xLZrR1Q`w9-h)rG}u)FqJ}}SI+Tr7Pvw0dJ?sHIQh-r9!Gmrt8Wg%A;rh7>86Am` z@Ml9<%#KrKR(>L^?`nP#@JEg5Ice0-@2M0dG`_(Ar0X^>?7w`oxM}!aiOS=yMkX5A zXik+?84y-_*ck^7qM$=MC*E83ftv56!~?y%q}b_HL2-PAUtQ4CiBaa5AZ0*t&!B7} zZbMj%j!P>V{C?R(O{1&4&d2026EP1KbZ{sLBs-f)?whJl@`c4Fw(t?=CY491>?vTr zPsGS-bl#Woutw%xDbh86!T@f~8dio#Moz@YXnf`nbU`3IN>fl`e@COxk_93_NSNxD4-qH; z*aMG}8iehgt}YoX2PtMjhm%SOJC~#K%j`kD;3T2cFoUJerl@s~?R^RXj6njhbv8ZqBF7%7B}zy3&l_FRSk$;l4a-_M2!n zLCC(zwSaczNz)BjS&4q$Sxu0DJliVPt zErJ5U(>ie{7Xhy{(0xoofyAvzZgcCQVe`0vWyFNA&%ocMQCb$?;Ba#~?`-qaZ=A%Q zybXgw7Oo~BH1d7J9XF7k9A$O# z`u-Kg5Q#3tB+fO19ycfX(Dc4!v$-mjUp5r{Nbhq#RcrG@&2i2}o|puQ*^l+G)_6`L`-A|hK2=f;bd+_g|#K;qG6g>Dg#e(=7qx9mx$Bu;R zMm<(#DUZs8_%AxU zk3qmG_B)L6Xx7kIK5FA>f-Bf2uTYtk73ycsf|xX5QwJ9}2YtIhlI&=odM?8CYD-OF zL{6jA*5{-Hh7s)cUys_4;JU9e18V!5)hom0U9ACZcs>h}W&f6X)aX~r@l>6%_!{r^ z;4h&9{S86S1&g!dx+=PXFmN@Rz`)T`4Vjq2|KnS>1QJ1&v=>ByD*$s;J060cunMd* zbV?XlPIi~G;7vnqRdj)ns57hSIWv_xIgl>U5fcnp3%zrdqCC~doq$-kgvTc1Ku=Xf z2{eF8iG5S>L%8lUz3yB0A$r!}5OA=L$gE_>`%ttn@)J68tSz363`{ImNOVH-7WBgL z>>9Gd1(9NHl?n3IJZd*ihJ=LY{l(ha`_yK9nyC{H*J}hQyE=BC0;Cvv`Fj zVlyI>GMcc1btpaTx6J^wB-kM6B#LQY8Q7GonJ8vlsH2Zrfnz#WCbXX6ICw0QaJ#&# znY_26zw5?HCakZ}O#v`-{Q**av>2Y@y*yeakoc{iG1aU(&h$&3QxHpjy3kFQw5OVb z@O37Efitx5p5dkulahH|j*SV1T|=vt?9;LGz9Z1e2^da&nrD#fOh;y1SRspcqRJgX zHv-+U_8Z?11}FtQzfnsyiF5 zlG`llrn&LeNRy{@x~OA5cb-lG-kj)LFXwFGMUpZ91bK{XmP-X>%kz-nKs!~F9pJkJ0GP zG2_Sg{Wzps)2Z0J5hn7X5Y(pmBTvtUC?DyZG5+hToi6(RhrGMoVi3JmzKQvqt@DqG zEV`A2OQ6KvL`?|e_|B2g{d)O{ucG#1B024~r_U%trWPD9G$Z27)7~}up7}zJd*Q{x z|7KIT!O^Dh_w+F5Qi&Yz(0m-?yQ2@o6QcG+TNW~~i8m}Ez+LHPe_*_x+9Qxd_p_tCd@O=Dd!kI zhh6q$O)oif8t3^m*7SKosLVyg4ncO_SaXr&XzL#~2GnXY8t<_YR*=z(Gdt+t5!f0N zKlh37LDL+y*PvPTa>sVjK4=kg)@o9|R$sp2?{uy|gV2YeM79lsIqC9cj}>yH~8Nz_Lbf zC`lljL{e(q=Qp=o;AUCsJG`UqXR*?C9UtvpslPb1;%^pLj7zese3N~SnF#BmjOPO1 z*T@Nvc#bp!jOL)x|4+~GN2Rq%A8Htox*lJuwX7pFlSOQ`gX?PJqx*TxbTN9fk)}3M zbrZsVXePt24ny4$H*m0MCN-do(Y248OE0{$8VQ zOcp%;BUsK?Mp_+fs{7su^3^|ZRi_7iO5{MC>=&O`m$J?7D; z8K9oT_Oupqp2pov%f3hHSQ8M$UX;$M*6^T*57ecs9Lt=xeU6#aZehj^)Xc|=x+5IF z%lI~632xEHBV=GS6c}TteMTj3G(wXD`O~KH-00TN8ppOHf{* z!rYZ|jpibt%+YiNHP!|B`++#<5>;1Z+u#79=eUe`;wg}t@u7UzOx6eT8_n(Dl>SI@ zeds+TGt>30di*~Rqv0Gqzm{r@%W)jR4Z=+cdWTn6k9hOVtveE0+Y+afl|=+y%sUe1 zRjtkQ-zL=hLX!xLpKJ@$_Fjn)FeHp)0$Ve~%j4MHL7w%*Gf__8M*=9?9ydQHUBVx}O~J>zlnoG5m6R-eHEIiW_n#CF`4g{6jI&b#3S5Ql zeq6dyjbBBuHdpV>-5ke!5bgY^K;4)$lfijl&zLM>;v-!vOGlkwa!kkkY~NN_)2tFp zfi}0qo?ALA`p_@=-7*< zEDO%;y0O|#l%0mHc{j87z10J}aYpi~JB5u$n{dscj4qq@AIB1Bp}9HmIyb`q)zshZ z=)8*~3yX94LRTrj_Z3i*9uT@z2J zCfys~4~{t|4rFs!Jeftp9DGUqn^rVPTF(mhXqD8Ot`{SWl}wL zR1nlL>{n$9aAX_0n6+4T2|x-Qg+-1&)$w-NE^ zvptJwu$(jCbAJ$CsVQ^S<;dA>A}pS&duqQp$?VV@f@|=3nTZPcfhsFD_Q;P6@Xf}2hR*rvt19c1nJ=Twitd=Qd~)~ z^&lxDdS)+xq9aG(MNH~xh^4NxHMlM{GaN*c?r2p~3{)D`IMj_5lZ;YB1E^`onY)QD zUAAiSmV8rFvKN^>wZ+>8rLsA0iS$IJr^>`Vkd1{6+t0#ppn{%V+@T;s?$G)9g zBop{^y^`>-Y5O#^yU|s!ToSe_Z&%Dzg?Fv{lt5{&^qSLI@{%vzOQYm;m|) zmgXGgkMNb~H1dT=yaL z%MV5{V1Q(U{=j) zNSg0+Ui-_>|0#1`_HUWDmsy!A$C4JRvfGIyFfRy1UfwkX>18L$PTl5XfRKtc$@>?AF(TbN&_@%@fg(02Xo z6(PldeYD%<6uPPBp@3?Bc?QCVteHs|OVwekYNI#W=F0N;ZZ!-aqkusnT)ONwp&)Y5; zN@bXuFD`Yb$`M7uJdvioPLvlxd`4}>GF2z5@)A~{#JD$axA3C~F^I%IKw! zK+k8j*Y;HNRl6_c0-?b`QwAK4;P66yPFgMo0Z*ihHZqZ??0xl-8tkh2%U0H8aqdFB zaQ5cb-fg>~{ah);y`1r`HDnH#joW}~ddoP@e|pKG#02Y7g!&O}Wc7qM@aorU+^8hz zDf$s#0;XR6=SulPz4I6XbH?Cu)%;stKz#d$BLYbp#AVa9tI^K5sJGoB%ie)$2@ro9 z2+_pHX%vkAe~16CPyRI_w8OUDGKP5BH7ihxp(AYBz~0G*`8%B;2TnTCX;-Ak8)~3v z%lO#Yj`HvP2{mj=-%{?g|7s6-#YGUbLyOkfP(y73dB2A7P1*@85#>Xl%~;iux&GCa z4Fnftb--&0#P;oP5t;^LL%OFCxmw!bvw67Vj$XB4-{l1pP%g1bDVw(Jt#2LXs9Bmr z@|%Etl$K}k4~G8=5y8MoY_5ufDlzwyKB~H1d~StFyLbJlrY=?@kZ8tSm)h>u4h_tE z?e8=B)*rz-p>E&)`j`b&uhw3!x#mhhU8$Sp&X|Q&ir6CsGx|d#Jvkx#6P%g-U}XS& z_qQklE_qorjQ-AIS@GKnxOzy4Zg()i`-!*WiCKnZ3SVwc_(9IxvQf3m zvays|9CXv%k}g@%DiG&F+VWcZ^Oljn#+go) zVBa};IrJcM44mL zlkuHn`gM^Z7MS`MZ{tLLyyHL;U%r9cS5+5^6HlMoTfs>|w1f@A92`AD@^(RI(jbiJ?IZm!Z1^eQe-e&fNwQX(=ObLEHV_UmT)bCd4QDFzZ9C3zwv>oqjiaUh zR~sXDUaDN7*x4aOS=xL7#&`xaxc{aAs*MeVXZi&kj127G9z6ri(�PeBE)IvPs)B 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

QeY!$l}& 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

j40MPdJ`H2MEVVgD&R`S17me6qo? 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[~SCoha? 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

cb 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 #`rH#KrhinD}@vP^~H9L2*1 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 literal 0 HcmV?d00001 diff --git a/security/README.md b/security/README.md index 073069569893..282a940d3668 100644 --- a/security/README.md +++ b/security/README.md @@ -35,6 +35,7 @@ A public disclosure date is negotiated by the etcd Product Security Committee an ## Security Audit A third party security audit was performed by Trail of Bits, find the full report [here](SECURITY_AUDIT.pdf). +A third party fuzzing audit was performed by Ada Logics, find the full report [here](FUZZING_AUDIT_2022.pdf). ## Private Distributor List From 3dcbbf62d95764cf8a3de00dd12ea29df23f0b7f Mon Sep 17 00:00:00 2001 From: ahrtr Date: Tue, 1 Mar 2022 00:32:20 +0800 Subject: [PATCH 178/258] Move clientconfig into clientv3 so that it can be reused by both etcdctl and v3 discovery --- client/v3/config.go | 25 +++++ etcdctl/ctlv3/command/check.go | 4 +- etcdctl/ctlv3/command/global.go | 106 +++++++----------- etcdctl/ctlv3/command/make_mirror_command.go | 42 +++---- etcdctl/ctlv3/command/move_leader_command.go | 4 +- etcdctl/ctlv3/command/util.go | 14 +-- server/embed/config.go | 24 ++-- server/embed/etcd.go | 14 +-- server/etcdmain/config.go | 16 +-- .../etcdserver/api/v3discovery/discovery.go | 40 +++---- 10 files changed, 141 insertions(+), 148 deletions(-) diff --git a/client/v3/config.go b/client/v3/config.go index 335a288732b5..eaa409f0ff05 100644 --- a/client/v3/config.go +++ b/client/v3/config.go @@ -90,3 +90,28 @@ type Config struct { // TODO: support custom balancer picker } + +type ClientConfig struct { + Endpoints []string `json:"endpoints"` + RequestTimeout time.Duration `json:"request-timeout"` + DialTimeout time.Duration `json:"dial-timeout"` + KeepAliveTime time.Duration `json:"keepalive-time"` + KeepAliveTimeout time.Duration `json:"keepalive-timeout"` + Secure *SecureConfig `json:"secure"` + Auth *AuthConfig `json:"auth"` +} + +type SecureConfig struct { + Cert string `json:"cert"` + Key string `json:"key"` + Cacert string `json:"cacert"` + ServerName string `json:"server-name"` + + InsecureTransport bool `json:"insecure-transport"` + InsecureSkipVerify bool `json:"insecure-skip-tls-verify"` +} + +type AuthConfig struct { + Username string `json:"username"` + Password string `json:"password"` +} diff --git a/etcdctl/ctlv3/command/check.go b/etcdctl/ctlv3/command/check.go index 50d6d3bbd73f..7227b14cdbaa 100644 --- a/etcdctl/ctlv3/command/check.go +++ b/etcdctl/ctlv3/command/check.go @@ -158,7 +158,7 @@ func newCheckPerfCommand(cmd *cobra.Command, args []string) { cc := clientConfigFromCmd(cmd) clients := make([]*v3.Client, cfg.clients) for i := 0; i < cfg.clients; i++ { - clients[i] = cc.mustClient() + clients[i] = mustClient(cc) } ctx, cancel := context.WithTimeout(context.Background(), time.Duration(cfg.duration)*time.Second) @@ -331,7 +331,7 @@ func newCheckDatascaleCommand(cmd *cobra.Command, args []string) { cc := clientConfigFromCmd(cmd) clients := make([]*v3.Client, cfg.clients) for i := 0; i < cfg.clients; i++ { - clients[i] = cc.mustClient() + clients[i] = mustClient(cc) } // get endpoints diff --git a/etcdctl/ctlv3/command/global.go b/etcdctl/ctlv3/command/global.go index 9097419d3e39..e67ea84c91b3 100644 --- a/etcdctl/ctlv3/command/global.go +++ b/etcdctl/ctlv3/command/global.go @@ -60,21 +60,6 @@ type GlobalFlags struct { Debug bool } -type secureCfg struct { - cert string - key string - cacert string - serverName string - - insecureTransport bool - insecureSkipVerify bool -} - -type authCfg struct { - username string - password string -} - type discoveryCfg struct { domain string insecure bool @@ -97,22 +82,13 @@ func initDisplayFromCmd(cmd *cobra.Command) { } } -type clientConfig struct { - endpoints []string - dialTimeout time.Duration - keepAliveTime time.Duration - keepAliveTimeout time.Duration - scfg *secureCfg - acfg *authCfg -} - type discardValue struct{} func (*discardValue) String() string { return "" } func (*discardValue) Set(string) error { return nil } func (*discardValue) Type() string { return "" } -func clientConfigFromCmd(cmd *cobra.Command) *clientConfig { +func clientConfigFromCmd(cmd *cobra.Command) *clientv3.ClientConfig { lg, err := zap.NewProduction() if err != nil { cobrautl.ExitWithError(cobrautl.ExitError, err) @@ -143,18 +119,18 @@ func clientConfigFromCmd(cmd *cobra.Command) *clientConfig { grpclog.SetLoggerV2(grpclog.NewLoggerV2(io.Discard, io.Discard, os.Stderr)) } - cfg := &clientConfig{} - cfg.endpoints, err = endpointsFromCmd(cmd) + cfg := &clientv3.ClientConfig{} + cfg.Endpoints, err = endpointsFromCmd(cmd) if err != nil { cobrautl.ExitWithError(cobrautl.ExitError, err) } - cfg.dialTimeout = dialTimeoutFromCmd(cmd) - cfg.keepAliveTime = keepAliveTimeFromCmd(cmd) - cfg.keepAliveTimeout = keepAliveTimeoutFromCmd(cmd) + cfg.DialTimeout = dialTimeoutFromCmd(cmd) + cfg.KeepAliveTime = keepAliveTimeFromCmd(cmd) + cfg.KeepAliveTimeout = keepAliveTimeoutFromCmd(cmd) - cfg.scfg = secureCfgFromCmd(cmd) - cfg.acfg = authCfgFromCmd(cmd) + cfg.Secure = secureCfgFromCmd(cmd) + cfg.Auth = authCfgFromCmd(cmd) initDisplayFromCmd(cmd) return cfg @@ -162,7 +138,7 @@ func clientConfigFromCmd(cmd *cobra.Command) *clientConfig { func mustClientCfgFromCmd(cmd *cobra.Command) *clientv3.Config { cc := clientConfigFromCmd(cmd) - cfg, err := newClientCfg(cc.endpoints, cc.dialTimeout, cc.keepAliveTime, cc.keepAliveTimeout, cc.scfg, cc.acfg) + cfg, err := newClientCfg(cc.Endpoints, cc.DialTimeout, cc.KeepAliveTime, cc.KeepAliveTimeout, cc.Secure, cc.Auth) if err != nil { cobrautl.ExitWithError(cobrautl.ExitBadArgs, err) } @@ -171,11 +147,11 @@ func mustClientCfgFromCmd(cmd *cobra.Command) *clientv3.Config { func mustClientFromCmd(cmd *cobra.Command) *clientv3.Client { cfg := clientConfigFromCmd(cmd) - return cfg.mustClient() + return mustClient(cfg) } -func (cc *clientConfig) mustClient() *clientv3.Client { - cfg, err := newClientCfg(cc.endpoints, cc.dialTimeout, cc.keepAliveTime, cc.keepAliveTimeout, cc.scfg, cc.acfg) +func mustClient(cc *clientv3.ClientConfig) *clientv3.Client { + cfg, err := newClientCfg(cc.Endpoints, cc.DialTimeout, cc.KeepAliveTime, cc.KeepAliveTimeout, cc.Secure, cc.Auth) if err != nil { cobrautl.ExitWithError(cobrautl.ExitBadArgs, err) } @@ -188,28 +164,28 @@ func (cc *clientConfig) mustClient() *clientv3.Client { return client } -func newClientCfg(endpoints []string, dialTimeout, keepAliveTime, keepAliveTimeout time.Duration, scfg *secureCfg, acfg *authCfg) (*clientv3.Config, error) { +func newClientCfg(endpoints []string, dialTimeout, keepAliveTime, keepAliveTimeout time.Duration, scfg *clientv3.SecureConfig, acfg *clientv3.AuthConfig) (*clientv3.Config, error) { // set tls if any one tls option set var cfgtls *transport.TLSInfo tlsinfo := transport.TLSInfo{} tlsinfo.Logger, _ = zap.NewProduction() - if scfg.cert != "" { - tlsinfo.CertFile = scfg.cert + if scfg.Cert != "" { + tlsinfo.CertFile = scfg.Cert cfgtls = &tlsinfo } - if scfg.key != "" { - tlsinfo.KeyFile = scfg.key + if scfg.Key != "" { + tlsinfo.KeyFile = scfg.Key cfgtls = &tlsinfo } - if scfg.cacert != "" { - tlsinfo.TrustedCAFile = scfg.cacert + if scfg.Cacert != "" { + tlsinfo.TrustedCAFile = scfg.Cacert cfgtls = &tlsinfo } - if scfg.serverName != "" { - tlsinfo.ServerName = scfg.serverName + if scfg.ServerName != "" { + tlsinfo.ServerName = scfg.ServerName cfgtls = &tlsinfo } @@ -231,19 +207,19 @@ func newClientCfg(endpoints []string, dialTimeout, keepAliveTime, keepAliveTimeo // if key/cert is not given but user wants secure connection, we // should still setup an empty tls configuration for gRPC to setup // secure connection. - if cfg.TLS == nil && !scfg.insecureTransport { + if cfg.TLS == nil && !scfg.InsecureTransport { cfg.TLS = &tls.Config{} } // If the user wants to skip TLS verification then we should set // the InsecureSkipVerify flag in tls configuration. - if scfg.insecureSkipVerify && cfg.TLS != nil { + if scfg.InsecureSkipVerify && cfg.TLS != nil { cfg.TLS.InsecureSkipVerify = true } if acfg != nil { - cfg.Username = acfg.username - cfg.Password = acfg.password + cfg.Username = acfg.Username + cfg.Password = acfg.Password } return cfg, nil @@ -284,7 +260,7 @@ func keepAliveTimeoutFromCmd(cmd *cobra.Command) time.Duration { return keepAliveTimeout } -func secureCfgFromCmd(cmd *cobra.Command) *secureCfg { +func secureCfgFromCmd(cmd *cobra.Command) *clientv3.SecureConfig { cert, key, cacert := keyAndCertFromCmd(cmd) insecureTr := insecureTransportFromCmd(cmd) skipVerify := insecureSkipVerifyFromCmd(cmd) @@ -294,14 +270,14 @@ func secureCfgFromCmd(cmd *cobra.Command) *secureCfg { discoveryCfg.domain = "" } - return &secureCfg{ - cert: cert, - key: key, - cacert: cacert, - serverName: discoveryCfg.domain, + return &clientv3.SecureConfig{ + Cert: cert, + Key: key, + Cacert: cacert, + ServerName: discoveryCfg.domain, - insecureTransport: insecureTr, - insecureSkipVerify: skipVerify, + InsecureTransport: insecureTr, + InsecureSkipVerify: skipVerify, } } @@ -344,7 +320,7 @@ func keyAndCertFromCmd(cmd *cobra.Command) (cert, key, cacert string) { return cert, key, cacert } -func authCfgFromCmd(cmd *cobra.Command) *authCfg { +func authCfgFromCmd(cmd *cobra.Command) *clientv3.AuthConfig { userFlag, err := cmd.Flags().GetString("user") if err != nil { cobrautl.ExitWithError(cobrautl.ExitBadArgs, err) @@ -358,23 +334,23 @@ func authCfgFromCmd(cmd *cobra.Command) *authCfg { return nil } - var cfg authCfg + var cfg clientv3.AuthConfig if passwordFlag == "" { splitted := strings.SplitN(userFlag, ":", 2) if len(splitted) < 2 { - cfg.username = userFlag - cfg.password, err = speakeasy.Ask("Password: ") + cfg.Username = userFlag + cfg.Password, err = speakeasy.Ask("Password: ") if err != nil { cobrautl.ExitWithError(cobrautl.ExitError, err) } } else { - cfg.username = splitted[0] - cfg.password = splitted[1] + cfg.Username = splitted[0] + cfg.Password = splitted[1] } } else { - cfg.username = userFlag - cfg.password = passwordFlag + cfg.Username = userFlag + cfg.Password = passwordFlag } return &cfg diff --git a/etcdctl/ctlv3/command/make_mirror_command.go b/etcdctl/ctlv3/command/make_mirror_command.go index 3d8b869d0c87..0604373b3e77 100644 --- a/etcdctl/ctlv3/command/make_mirror_command.go +++ b/etcdctl/ctlv3/command/make_mirror_command.go @@ -69,29 +69,29 @@ func NewMakeMirrorCommand() *cobra.Command { return c } -func authDestCfg() *authCfg { +func authDestCfg() *clientv3.AuthConfig { if mmuser == "" { return nil } - var cfg authCfg + var cfg clientv3.AuthConfig if mmpassword == "" { splitted := strings.SplitN(mmuser, ":", 2) if len(splitted) < 2 { var err error - cfg.username = mmuser - cfg.password, err = speakeasy.Ask("Destination Password: ") + cfg.Username = mmuser + cfg.Password, err = speakeasy.Ask("Destination Password: ") if err != nil { cobrautl.ExitWithError(cobrautl.ExitError, err) } } else { - cfg.username = splitted[0] - cfg.password = splitted[1] + cfg.Username = splitted[0] + cfg.Password = splitted[1] } } else { - cfg.username = mmuser - cfg.password = mmpassword + cfg.Username = mmuser + cfg.Password = mmpassword } return &cfg @@ -105,24 +105,24 @@ func makeMirrorCommandFunc(cmd *cobra.Command, args []string) { dialTimeout := dialTimeoutFromCmd(cmd) keepAliveTime := keepAliveTimeFromCmd(cmd) keepAliveTimeout := keepAliveTimeoutFromCmd(cmd) - sec := &secureCfg{ - cert: mmcert, - key: mmkey, - cacert: mmcacert, - insecureTransport: mminsecureTr, + sec := &clientv3.SecureConfig{ + Cert: mmcert, + Key: mmkey, + Cacert: mmcacert, + InsecureTransport: mminsecureTr, } auth := authDestCfg() - cc := &clientConfig{ - endpoints: []string{args[0]}, - dialTimeout: dialTimeout, - keepAliveTime: keepAliveTime, - keepAliveTimeout: keepAliveTimeout, - scfg: sec, - acfg: auth, + cc := &clientv3.ClientConfig{ + Endpoints: []string{args[0]}, + DialTimeout: dialTimeout, + KeepAliveTime: keepAliveTime, + KeepAliveTimeout: keepAliveTimeout, + Secure: sec, + Auth: auth, } - dc := cc.mustClient() + dc := mustClient(cc) c := mustClientFromCmd(cmd) err := makeMirror(context.TODO(), c, dc) diff --git a/etcdctl/ctlv3/command/move_leader_command.go b/etcdctl/ctlv3/command/move_leader_command.go index 098c897cd7a9..76b1736d5415 100644 --- a/etcdctl/ctlv3/command/move_leader_command.go +++ b/etcdctl/ctlv3/command/move_leader_command.go @@ -54,8 +54,8 @@ func transferLeadershipCommandFunc(cmd *cobra.Command, args []string) { var leaderID uint64 for _, ep := range eps { cfg := clientConfigFromCmd(cmd) - cfg.endpoints = []string{ep} - cli := cfg.mustClient() + cfg.Endpoints = []string{ep} + cli := mustClient(cfg) resp, serr := cli.Status(ctx, ep) if serr != nil { cobrautl.ExitWithError(cobrautl.ExitError, serr) diff --git a/etcdctl/ctlv3/command/util.go b/etcdctl/ctlv3/command/util.go index 27f1e51e9b1f..86f83be36ded 100644 --- a/etcdctl/ctlv3/command/util.go +++ b/etcdctl/ctlv3/command/util.go @@ -27,7 +27,7 @@ import ( "time" pb "go.etcd.io/etcd/api/v3/mvccpb" - v3 "go.etcd.io/etcd/client/v3" + "go.etcd.io/etcd/client/v3" "go.etcd.io/etcd/pkg/v3/cobrautl" "github.com/spf13/cobra" @@ -93,7 +93,7 @@ func isCommandTimeoutFlagSet(cmd *cobra.Command) bool { } // get the process_resident_memory_bytes from /metrics -func endpointMemoryMetrics(host string, scfg *secureCfg) float64 { +func endpointMemoryMetrics(host string, scfg *clientv3.SecureConfig) float64 { residentMemoryKey := "process_resident_memory_bytes" var residentMemoryValue string if !strings.HasPrefix(host, "http://") && !strings.HasPrefix(host, "https://") { @@ -102,14 +102,14 @@ func endpointMemoryMetrics(host string, scfg *secureCfg) float64 { url := host + "/metrics" if strings.HasPrefix(host, "https://") { // load client certificate - cert, err := tls.LoadX509KeyPair(scfg.cert, scfg.key) + cert, err := tls.LoadX509KeyPair(scfg.Cert, scfg.Key) if err != nil { fmt.Println(fmt.Sprintf("client certificate error: %v", err)) return 0.0 } http.DefaultTransport.(*http.Transport).TLSClientConfig = &tls.Config{ Certificates: []tls.Certificate{cert}, - InsecureSkipVerify: scfg.insecureSkipVerify, + InsecureSkipVerify: scfg.InsecureSkipVerify, } } resp, err := http.Get(url) @@ -144,10 +144,10 @@ func endpointMemoryMetrics(host string, scfg *secureCfg) float64 { } // compact keyspace history to a provided revision -func compact(c *v3.Client, rev int64) { +func compact(c *clientv3.Client, rev int64) { fmt.Printf("Compacting with revision %d\n", rev) ctx, cancel := context.WithTimeout(context.Background(), 30*time.Second) - _, err := c.Compact(ctx, rev, v3.WithCompactPhysical()) + _, err := c.Compact(ctx, rev, clientv3.WithCompactPhysical()) cancel() if err != nil { cobrautl.ExitWithError(cobrautl.ExitError, err) @@ -156,7 +156,7 @@ func compact(c *v3.Client, rev int64) { } // defrag a given endpoint -func defrag(c *v3.Client, ep string) { +func defrag(c *clientv3.Client, ep string) { fmt.Printf("Defragmenting %q\n", ep) ctx, cancel := context.WithTimeout(context.Background(), 30*time.Second) _, err := c.Defragment(ctx, ep) diff --git a/server/embed/config.go b/server/embed/config.go index e6f9e3a32344..2c86a29f9421 100644 --- a/server/embed/config.go +++ b/server/embed/config.go @@ -31,6 +31,7 @@ import ( "go.etcd.io/etcd/client/pkg/v3/tlsutil" "go.etcd.io/etcd/client/pkg/v3/transport" "go.etcd.io/etcd/client/pkg/v3/types" + "go.etcd.io/etcd/client/v3" "go.etcd.io/etcd/pkg/v3/flags" "go.etcd.io/etcd/pkg/v3/netutil" "go.etcd.io/etcd/server/v3/config" @@ -516,10 +517,15 @@ func NewConfig() *Config { V2Deprecation: config.V2_DEPR_DEFAULT, DiscoveryCfg: v3discovery.DiscoveryConfig{ - DialTimeout: DefaultDiscoveryDialTimeout, - RequestTimeOut: DefaultDiscoveryRequestTimeOut, - KeepAliveTime: DefaultDiscoveryKeepAliveTime, - KeepAliveTimeout: DefaultDiscoveryKeepAliveTimeOut, + ClientConfig: clientv3.ClientConfig{ + DialTimeout: DefaultDiscoveryDialTimeout, + RequestTimeout: DefaultDiscoveryRequestTimeOut, + KeepAliveTime: DefaultDiscoveryKeepAliveTime, + KeepAliveTimeout: DefaultDiscoveryKeepAliveTimeOut, + + Secure: &clientv3.SecureConfig{}, + Auth: &clientv3.AuthConfig{}, + }, }, } cfg.InitialCluster = cfg.InitialClusterFromName(cfg.Name) @@ -688,11 +694,11 @@ func (cfg *Config) Validate() error { v2discoveryFlagsExist := cfg.Dproxy != "" v3discoveryFlagsExist := len(cfg.DiscoveryCfg.Endpoints) > 0 || cfg.DiscoveryCfg.Token != "" || - cfg.DiscoveryCfg.CertFile != "" || - cfg.DiscoveryCfg.KeyFile != "" || - cfg.DiscoveryCfg.TrustedCAFile != "" || - cfg.DiscoveryCfg.User != "" || - cfg.DiscoveryCfg.Password != "" + cfg.DiscoveryCfg.Secure.Cert != "" || + cfg.DiscoveryCfg.Secure.Key != "" || + cfg.DiscoveryCfg.Secure.Cacert != "" || + cfg.DiscoveryCfg.Auth.Username != "" || + cfg.DiscoveryCfg.Auth.Password != "" if v2discoveryFlagsExist && v3discoveryFlagsExist { return errors.New("both v2 discovery settings (discovery, discovery-proxy) " + diff --git a/server/embed/etcd.go b/server/embed/etcd.go index aa59cc84452b..e955efd925b6 100644 --- a/server/embed/etcd.go +++ b/server/embed/etcd.go @@ -349,15 +349,15 @@ func print(lg *zap.Logger, ec Config, sc config.ServerConfig, memberInitialized zap.String("discovery-token", sc.DiscoveryCfg.Token), zap.String("discovery-endpoints", strings.Join(sc.DiscoveryCfg.Endpoints, ",")), zap.String("discovery-dial-timeout", sc.DiscoveryCfg.DialTimeout.String()), - zap.String("discovery-request-timeout", sc.DiscoveryCfg.RequestTimeOut.String()), + zap.String("discovery-request-timeout", sc.DiscoveryCfg.RequestTimeout.String()), zap.String("discovery-keepalive-time", sc.DiscoveryCfg.KeepAliveTime.String()), zap.String("discovery-keepalive-timeout", sc.DiscoveryCfg.KeepAliveTimeout.String()), - zap.Bool("discovery-insecure-transport", sc.DiscoveryCfg.InsecureTransport), - zap.Bool("discovery-insecure-skip-tls-verify", sc.DiscoveryCfg.InsecureSkipVerify), - zap.String("discovery-cert", sc.DiscoveryCfg.CertFile), - zap.String("discovery-key", sc.DiscoveryCfg.KeyFile), - zap.String("discovery-cacert", sc.DiscoveryCfg.TrustedCAFile), - zap.String("discovery-user", sc.DiscoveryCfg.User), + zap.Bool("discovery-insecure-transport", sc.DiscoveryCfg.Secure.InsecureTransport), + zap.Bool("discovery-insecure-skip-tls-verify", sc.DiscoveryCfg.Secure.InsecureSkipVerify), + zap.String("discovery-cert", sc.DiscoveryCfg.Secure.Cert), + zap.String("discovery-key", sc.DiscoveryCfg.Secure.Key), + zap.String("discovery-cacert", sc.DiscoveryCfg.Secure.Cacert), + zap.String("discovery-user", sc.DiscoveryCfg.Auth.Username), zap.String("downgrade-check-interval", sc.DowngradeCheckTime.String()), zap.Int("max-learners", sc.ExperimentalMaxLearners), diff --git a/server/etcdmain/config.go b/server/etcdmain/config.go index dc78e1d532b9..71a776373e7e 100644 --- a/server/etcdmain/config.go +++ b/server/etcdmain/config.go @@ -196,16 +196,16 @@ func newConfig() *config { ) fs.StringVar(&cfg.ec.DiscoveryCfg.Token, "discovery-token", "", "V3 discovery: discovery token for the etcd cluster to be bootstrapped.") fs.DurationVar(&cfg.ec.DiscoveryCfg.DialTimeout, "discovery-dial-timeout", cfg.ec.DiscoveryCfg.DialTimeout, "V3 discovery: dial timeout for client connections.") - fs.DurationVar(&cfg.ec.DiscoveryCfg.RequestTimeOut, "discovery-request-timeout", cfg.ec.DiscoveryCfg.RequestTimeOut, "V3 discovery: timeout for discovery requests (excluding dial timeout).") + fs.DurationVar(&cfg.ec.DiscoveryCfg.RequestTimeout, "discovery-request-timeout", cfg.ec.DiscoveryCfg.RequestTimeout, "V3 discovery: timeout for discovery requests (excluding dial timeout).") fs.DurationVar(&cfg.ec.DiscoveryCfg.KeepAliveTime, "discovery-keepalive-time", cfg.ec.DiscoveryCfg.KeepAliveTime, "V3 discovery: keepalive time for client connections.") fs.DurationVar(&cfg.ec.DiscoveryCfg.KeepAliveTimeout, "discovery-keepalive-timeout", cfg.ec.DiscoveryCfg.KeepAliveTimeout, "V3 discovery: keepalive timeout for client connections.") - fs.BoolVar(&cfg.ec.DiscoveryCfg.InsecureTransport, "discovery-insecure-transport", true, "V3 discovery: disable transport security for client connections.") - fs.BoolVar(&cfg.ec.DiscoveryCfg.InsecureSkipVerify, "discovery-insecure-skip-tls-verify", false, "V3 discovery: skip server certificate verification (CAUTION: this option should be enabled only for testing purposes).") - fs.StringVar(&cfg.ec.DiscoveryCfg.CertFile, "discovery-cert", "", "V3 discovery: identify secure client using this TLS certificate file.") - fs.StringVar(&cfg.ec.DiscoveryCfg.KeyFile, "discovery-key", "", "V3 discovery: identify secure client using this TLS key file.") - fs.StringVar(&cfg.ec.DiscoveryCfg.TrustedCAFile, "discovery-cacert", "", "V3 discovery: verify certificates of TLS-enabled secure servers using this CA bundle.") - fs.StringVar(&cfg.ec.DiscoveryCfg.User, "discovery-user", "", "V3 discovery: username[:password] for authentication (prompt if password is not supplied).") - fs.StringVar(&cfg.ec.DiscoveryCfg.Password, "discovery-password", "", "V3 discovery: password for authentication (if this option is used, --user option shouldn't include password).") + fs.BoolVar(&cfg.ec.DiscoveryCfg.Secure.InsecureTransport, "discovery-insecure-transport", true, "V3 discovery: disable transport security for client connections.") + fs.BoolVar(&cfg.ec.DiscoveryCfg.Secure.InsecureSkipVerify, "discovery-insecure-skip-tls-verify", false, "V3 discovery: skip server certificate verification (CAUTION: this option should be enabled only for testing purposes).") + fs.StringVar(&cfg.ec.DiscoveryCfg.Secure.Cert, "discovery-cert", "", "V3 discovery: identify secure client using this TLS certificate file.") + fs.StringVar(&cfg.ec.DiscoveryCfg.Secure.Key, "discovery-key", "", "V3 discovery: identify secure client using this TLS key file.") + fs.StringVar(&cfg.ec.DiscoveryCfg.Secure.Cacert, "discovery-cacert", "", "V3 discovery: verify certificates of TLS-enabled secure servers using this CA bundle.") + fs.StringVar(&cfg.ec.DiscoveryCfg.Auth.Username, "discovery-user", "", "V3 discovery: username[:password] for authentication (prompt if password is not supplied).") + fs.StringVar(&cfg.ec.DiscoveryCfg.Auth.Password, "discovery-password", "", "V3 discovery: password for authentication (if this option is used, --user option shouldn't include password).") fs.StringVar(&cfg.ec.Dproxy, "discovery-proxy", cfg.ec.Dproxy, "HTTP proxy to use for traffic to discovery service. Will be deprecated in v3.7, and be decommissioned in v3.8.") fs.StringVar(&cfg.ec.DNSCluster, "discovery-srv", cfg.ec.DNSCluster, "DNS domain used to bootstrap initial cluster.") diff --git a/server/etcdserver/api/v3discovery/discovery.go b/server/etcdserver/api/v3discovery/discovery.go index cb91d6ed7c9f..1a6e1d22638f 100644 --- a/server/etcdserver/api/v3discovery/discovery.go +++ b/server/etcdserver/api/v3discovery/discovery.go @@ -55,22 +55,8 @@ var ( ) type DiscoveryConfig struct { - Token string `json:"discovery-token"` - Endpoints []string `json:"discovery-endpoints"` - - DialTimeout time.Duration `json:"discovery-dial-timeout"` - RequestTimeOut time.Duration `json:"discovery-request-timeout"` - KeepAliveTime time.Duration `json:"discovery-keepalive-time"` - KeepAliveTimeout time.Duration `json:"discovery-keepalive-timeout"` - - InsecureTransport bool `json:"discovery-insecure-transport"` - InsecureSkipVerify bool `json:"discovery-insecure-skip-tls-verify"` - CertFile string `json:"discovery-cert"` - KeyFile string `json:"discovery-key"` - TrustedCAFile string `json:"discovery-cacert"` - - User string `json:"discovery-user"` - Password string `json:"discovery-password"` + clientv3.ClientConfig `json:"client"` + Token string `json:"token"` } type memberInfo struct { @@ -211,11 +197,11 @@ func newDiscovery(lg *zap.Logger, dcfg *DiscoveryConfig, id types.ID) (*discover func newClientCfg(dcfg *DiscoveryConfig, lg *zap.Logger) (*clientv3.Config, error) { var cfgtls *transport.TLSInfo - if dcfg.CertFile != "" || dcfg.KeyFile != "" || dcfg.TrustedCAFile != "" { + if dcfg.Secure.Cert != "" || dcfg.Secure.Key != "" || dcfg.Secure.Cacert != "" { cfgtls = &transport.TLSInfo{ - CertFile: dcfg.CertFile, - KeyFile: dcfg.KeyFile, - TrustedCAFile: dcfg.TrustedCAFile, + CertFile: dcfg.Secure.Cert, + KeyFile: dcfg.Secure.Key, + TrustedCAFile: dcfg.Secure.Cacert, Logger: lg, } } @@ -225,8 +211,8 @@ func newClientCfg(dcfg *DiscoveryConfig, lg *zap.Logger) (*clientv3.Config, erro DialTimeout: dcfg.DialTimeout, DialKeepAliveTime: dcfg.KeepAliveTime, DialKeepAliveTimeout: dcfg.KeepAliveTimeout, - Username: dcfg.User, - Password: dcfg.Password, + Username: dcfg.Auth.Username, + Password: dcfg.Auth.Password, } if cfgtls != nil { @@ -240,13 +226,13 @@ func newClientCfg(dcfg *DiscoveryConfig, lg *zap.Logger) (*clientv3.Config, erro // If key/cert is not given but user wants secure connection, we // should still setup an empty tls configuration for gRPC to setup // secure connection. - if cfg.TLS == nil && !dcfg.InsecureTransport { + if cfg.TLS == nil && !dcfg.Secure.InsecureTransport { cfg.TLS = &tls.Config{} } // If the user wants to skip TLS verification then we should set // the InsecureSkipVerify flag in tls configuration. - if cfg.TLS != nil && dcfg.InsecureSkipVerify { + if cfg.TLS != nil && dcfg.Secure.InsecureSkipVerify { cfg.TLS.InsecureSkipVerify = true } @@ -293,7 +279,7 @@ func (d *discovery) joinCluster(config string) (string, error) { func (d *discovery) getClusterSize() (int, error) { configKey := geClusterSizeKey(d.clusterToken) - ctx, cancel := context.WithTimeout(context.Background(), d.cfg.RequestTimeOut) + ctx, cancel := context.WithTimeout(context.Background(), d.cfg.RequestTimeout) defer cancel() resp, err := d.c.Get(ctx, configKey) @@ -320,7 +306,7 @@ func (d *discovery) getClusterSize() (int, error) { func (d *discovery) getClusterMembers() (*clusterInfo, int64, error) { membersKeyPrefix := getMemberKeyPrefix(d.clusterToken) - ctx, cancel := context.WithTimeout(context.Background(), d.cfg.RequestTimeOut) + ctx, cancel := context.WithTimeout(context.Background(), d.cfg.RequestTimeout) defer cancel() resp, err := d.c.Get(ctx, membersKeyPrefix, clientv3.WithPrefix()) @@ -404,7 +390,7 @@ func (d *discovery) registerSelfRetry(contents string) error { } func (d *discovery) registerSelf(contents string) error { - ctx, cancel := context.WithTimeout(context.Background(), d.cfg.RequestTimeOut) + ctx, cancel := context.WithTimeout(context.Background(), d.cfg.RequestTimeout) memberKey := getMemberKey(d.clusterToken, d.memberId.String()) _, err := d.c.Put(ctx, memberKey, contents) cancel() From 1a3822f2c3eaf81728bed567f2ac89dafa5aa215 Mon Sep 17 00:00:00 2001 From: ahrtr Date: Wed, 2 Mar 2022 07:24:33 +0800 Subject: [PATCH 179/258] Rename ClientConfig to ConfigSpec The ClientConfig is a fully declarive configuration, so it makes more sense to rename it to ConfigSpec. It can also mitigate the confusion between Config and ClientConfig. --- client/v3/config.go | 5 ++++- etcdctl/ctlv3/command/global.go | 6 +++--- etcdctl/ctlv3/command/make_mirror_command.go | 2 +- server/embed/config.go | 2 +- server/etcdserver/api/v3discovery/discovery.go | 14 +++++++------- 5 files changed, 16 insertions(+), 13 deletions(-) diff --git a/client/v3/config.go b/client/v3/config.go index eaa409f0ff05..29726160852a 100644 --- a/client/v3/config.go +++ b/client/v3/config.go @@ -91,7 +91,10 @@ type Config struct { // TODO: support custom balancer picker } -type ClientConfig struct { +// ConfigSpec is the configuration from users, which comes from command-line flags, +// environment variables or config file. It is a fully declarative configuration, +// and can be serialized & deserialized to/from JSON. +type ConfigSpec struct { Endpoints []string `json:"endpoints"` RequestTimeout time.Duration `json:"request-timeout"` DialTimeout time.Duration `json:"dial-timeout"` diff --git a/etcdctl/ctlv3/command/global.go b/etcdctl/ctlv3/command/global.go index e67ea84c91b3..57adae28f00a 100644 --- a/etcdctl/ctlv3/command/global.go +++ b/etcdctl/ctlv3/command/global.go @@ -88,7 +88,7 @@ func (*discardValue) String() string { return "" } func (*discardValue) Set(string) error { return nil } func (*discardValue) Type() string { return "" } -func clientConfigFromCmd(cmd *cobra.Command) *clientv3.ClientConfig { +func clientConfigFromCmd(cmd *cobra.Command) *clientv3.ConfigSpec { lg, err := zap.NewProduction() if err != nil { cobrautl.ExitWithError(cobrautl.ExitError, err) @@ -119,7 +119,7 @@ func clientConfigFromCmd(cmd *cobra.Command) *clientv3.ClientConfig { grpclog.SetLoggerV2(grpclog.NewLoggerV2(io.Discard, io.Discard, os.Stderr)) } - cfg := &clientv3.ClientConfig{} + cfg := &clientv3.ConfigSpec{} cfg.Endpoints, err = endpointsFromCmd(cmd) if err != nil { cobrautl.ExitWithError(cobrautl.ExitError, err) @@ -150,7 +150,7 @@ func mustClientFromCmd(cmd *cobra.Command) *clientv3.Client { return mustClient(cfg) } -func mustClient(cc *clientv3.ClientConfig) *clientv3.Client { +func mustClient(cc *clientv3.ConfigSpec) *clientv3.Client { cfg, err := newClientCfg(cc.Endpoints, cc.DialTimeout, cc.KeepAliveTime, cc.KeepAliveTimeout, cc.Secure, cc.Auth) if err != nil { cobrautl.ExitWithError(cobrautl.ExitBadArgs, err) diff --git a/etcdctl/ctlv3/command/make_mirror_command.go b/etcdctl/ctlv3/command/make_mirror_command.go index 0604373b3e77..e93e108ea1d3 100644 --- a/etcdctl/ctlv3/command/make_mirror_command.go +++ b/etcdctl/ctlv3/command/make_mirror_command.go @@ -114,7 +114,7 @@ func makeMirrorCommandFunc(cmd *cobra.Command, args []string) { auth := authDestCfg() - cc := &clientv3.ClientConfig{ + cc := &clientv3.ConfigSpec{ Endpoints: []string{args[0]}, DialTimeout: dialTimeout, KeepAliveTime: keepAliveTime, diff --git a/server/embed/config.go b/server/embed/config.go index 2c86a29f9421..21218e66e1c0 100644 --- a/server/embed/config.go +++ b/server/embed/config.go @@ -517,7 +517,7 @@ func NewConfig() *Config { V2Deprecation: config.V2_DEPR_DEFAULT, DiscoveryCfg: v3discovery.DiscoveryConfig{ - ClientConfig: clientv3.ClientConfig{ + ConfigSpec: clientv3.ConfigSpec{ DialTimeout: DefaultDiscoveryDialTimeout, RequestTimeout: DefaultDiscoveryRequestTimeOut, KeepAliveTime: DefaultDiscoveryKeepAliveTime, diff --git a/server/etcdserver/api/v3discovery/discovery.go b/server/etcdserver/api/v3discovery/discovery.go index 1a6e1d22638f..1c274cdba17f 100644 --- a/server/etcdserver/api/v3discovery/discovery.go +++ b/server/etcdserver/api/v3discovery/discovery.go @@ -55,8 +55,8 @@ var ( ) type DiscoveryConfig struct { - clientv3.ClientConfig `json:"client"` - Token string `json:"token"` + clientv3.ConfigSpec `json:"client"` + Token string `json:"token"` } type memberInfo struct { @@ -77,18 +77,18 @@ type clusterInfo struct { } // key prefix for each cluster: "/_etcd/registry/". -func geClusterKeyPrefix(cluster string) string { +func getClusterKeyPrefix(cluster string) string { return path.Join(discoveryPrefix, cluster) } // key format for cluster size: "/_etcd/registry//_config/size". -func geClusterSizeKey(cluster string) string { - return path.Join(geClusterKeyPrefix(cluster), "_config/size") +func getClusterSizeKey(cluster string) string { + return path.Join(getClusterKeyPrefix(cluster), "_config/size") } // key prefix for each member: "/_etcd/registry//members". func getMemberKeyPrefix(clusterToken string) string { - return path.Join(geClusterKeyPrefix(clusterToken), "members") + return path.Join(getClusterKeyPrefix(clusterToken), "members") } // key format for each member: "/_etcd/registry//members/". @@ -278,7 +278,7 @@ func (d *discovery) joinCluster(config string) (string, error) { } func (d *discovery) getClusterSize() (int, error) { - configKey := geClusterSizeKey(d.clusterToken) + configKey := getClusterSizeKey(d.clusterToken) ctx, cancel := context.WithTimeout(context.Background(), d.cfg.RequestTimeout) defer cancel() From 8c0e4fe5597520349390b62b3e67135a1c9175c8 Mon Sep 17 00:00:00 2001 From: kkkkun Date: Mon, 14 Mar 2022 11:07:57 +0800 Subject: [PATCH 180/258] delete offline defrag in etcdctl --- etcdctl/README.md | 15 +-------------- etcdctl/ctlv3/command/defrag_command.go | 14 -------------- tests/e2e/ctl_v3_defrag_test.go | 3 --- 3 files changed, 1 insertion(+), 31 deletions(-) diff --git a/etcdctl/README.md b/etcdctl/README.md index db273ec838d9..990a3fdcd18f 100644 --- a/etcdctl/README.md +++ b/etcdctl/README.md @@ -913,7 +913,7 @@ If NOSPACE alarm is present: ### DEFRAG [options] -DEFRAG defragments the backend database file for a set of given endpoints while etcd is running, ~~or directly defragments an etcd data directory while etcd is not running~~. When an etcd member reclaims storage space from deleted and compacted keys, the space is kept in a free list and the database file remains the same size. By defragmenting the database, the etcd member releases this free space back to the file system. +DEFRAG defragments the backend database file for a set of given endpoints while etcd is running. When an etcd member reclaims storage space from deleted and compacted keys, the space is kept in a free list and the database file remains the same size. By defragmenting the database, the etcd member releases this free space back to the file system. **Note: to defragment offline (`--data-dir` flag), use: `etcutl defrag` instead** @@ -921,9 +921,6 @@ DEFRAG defragments the backend database file for a set of given endpoints while **Note that defragmentation request does not get replicated over cluster. That is, the request is only applied to the local node. Specify all members in `--endpoints` flag or `--cluster` flag to automatically find all cluster members.** -#### Options - -- data-dir -- Optional. **Deprecated**. If present, defragments a data directory not in use by etcd. To be removed in v3.6. #### Output @@ -946,16 +943,6 @@ Finished defragmenting etcd member[http://127.0.0.1:22379] Finished defragmenting etcd member[http://127.0.0.1:32379] ``` -To defragment a data directory directly, use the `etcdutl` with `--data-dir` flag -(`etcdctl` will remove this flag in v3.6): - -``` bash -# Defragment while etcd is not running -./etcdutl defrag --data-dir default.etcd -# success (exit status 0) -# Error: cannot open database at default.etcd/member/snap/db -``` - #### Remarks DEFRAG returns a zero exit code only if it succeeded defragmenting all given endpoints. diff --git a/etcdctl/ctlv3/command/defrag_command.go b/etcdctl/ctlv3/command/defrag_command.go index 9b4f29a6aa68..5ebf4483d44d 100644 --- a/etcdctl/ctlv3/command/defrag_command.go +++ b/etcdctl/ctlv3/command/defrag_command.go @@ -20,14 +20,9 @@ import ( "time" "github.com/spf13/cobra" - "go.etcd.io/etcd/etcdutl/v3/etcdutl" "go.etcd.io/etcd/pkg/v3/cobrautl" ) -var ( - defragDataDir string -) - // NewDefragCommand returns the cobra command for "Defrag". func NewDefragCommand() *cobra.Command { cmd := &cobra.Command{ @@ -36,19 +31,10 @@ func NewDefragCommand() *cobra.Command { Run: defragCommandFunc, } cmd.PersistentFlags().BoolVar(&epClusterEndpoints, "cluster", false, "use all endpoints from the cluster member list") - cmd.Flags().StringVar(&defragDataDir, "data-dir", "", "Optional. If present, defragments a data directory not in use by etcd.") - cmd.MarkFlagDirname("data-dir") return cmd } func defragCommandFunc(cmd *cobra.Command, args []string) { - if len(defragDataDir) > 0 { - fmt.Fprintf(os.Stderr, "Use `etcdutl defrag` instead. The --data-dir is going to be decomissioned in v3.6.\n\n") - err := etcdutl.DefragData(defragDataDir) - if err != nil { - cobrautl.ExitWithError(cobrautl.ExitError, err) - } - } failures := 0 c := mustClientFromCmd(cmd) diff --git a/tests/e2e/ctl_v3_defrag_test.go b/tests/e2e/ctl_v3_defrag_test.go index 6abf855f49d1..c47ed3f4cdfc 100644 --- a/tests/e2e/ctl_v3_defrag_test.go +++ b/tests/e2e/ctl_v3_defrag_test.go @@ -22,9 +22,6 @@ import ( func TestCtlV3DefragOnline(t *testing.T) { testCtl(t, defragOnlineTest) } -func TestCtlV3DefragOffline(t *testing.T) { - testCtlWithOffline(t, maintenanceInitKeys, defragOfflineTest) -} func TestCtlV3DefragOfflineEtcdutl(t *testing.T) { testCtlWithOffline(t, maintenanceInitKeys, defragOfflineTest, withEtcdutl()) } From 494a4712488b57d1ea238de6c9a3c2524dccfd7e Mon Sep 17 00:00:00 2001 From: Marek Siarkowicz Date: Mon, 14 Mar 2022 14:07:50 +0100 Subject: [PATCH 181/258] *: Restore release documentation --- RELEASE.md | 159 +++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 159 insertions(+) create mode 100644 RELEASE.md diff --git a/RELEASE.md b/RELEASE.md new file mode 100644 index 000000000000..8085f7c5610b --- /dev/null +++ b/RELEASE.md @@ -0,0 +1,159 @@ +# Release + +The guide talks about how to release a new version of etcd. + +The procedure includes some manual steps for sanity checking, but it can probably be further scripted. Please keep this document up-to-date if making changes to the release process. + +## Release management + +etcd community members are assigned to manage the release each etcd major/minor version as well as manage patches +and to each stable release branch. The managers are responsible for communicating the timelines and status of each +release and for ensuring the stability of the release branch. + +| Releases | Manager | +| -------- | ------- | +| 3.1 patch (post 3.1.0) | Joe Betz [@jpbetz](https://github.com/jpbetz) | +| 3.2 patch (post 3.2.0) | Joe Betz [@jpbetz](https://github.com/jpbetz) | +| 3.3 patch (post 3.3.0) | Gyuho Lee [@gyuho](https://github.com/gyuho) | + +## Prepare release + +Set desired version as environment variable for following steps. Here is an example to release 2.3.0: + +``` +export VERSION=v2.3.0 +export PREV_VERSION=v2.2.5 +``` + +All releases version numbers follow the format of [semantic versioning 2.0.0](http://semver.org/). + +### Major, minor version release, or its pre-release + +- Ensure the relevant milestone on GitHub is complete. All referenced issues should be closed, or moved elsewhere. +- Remove this release from [roadmap](https://github.com/etcd-io/etcd/blob/master/ROADMAP.md), if necessary. +- Ensure the latest upgrade documentation is available. +- Bump [hardcoded MinClusterVerion in the repository](https://github.com/etcd-io/etcd/blob/v3.4.15/version/version.go#L29), if necessary. +- Add feature capability maps for the new version, if necessary. + +### Patch version release + +- To request a backport, devlopers submit cherrypick PRs targeting the release branch. The commits should not include merge commits. The commits should be restricted to bug fixes and security patches. +- The cherrypick PRs should target the appropriate release branch (`base:release--`). `hack/patch/cherrypick.sh` may be used to automatically generate cherrypick PRs. +- The release patch manager reviews the cherrypick PRs. Please discuss carefully what is backported to the patch release. Each patch release should be strictly better than it's predecessor. +- The release patch manager will cherry-pick these commits starting from the oldest one into stable branch. + +## Write release note + +- Write introduction for the new release. For example, what major bug we fix, what new features we introduce or what performance improvement we make. +- Put `[GH XXXX]` at the head of change line to reference Pull Request that introduces the change. Moreover, add a link on it to jump to the Pull Request. +- Find PRs with `release-note` label and explain them in `NEWS` file, as a straightforward summary of changes for end-users. + +## Tag version + +- Bump [hardcoded Version in the repository](https://github.com/etcd-io/etcd/blob/v3.4.15/version/version.go#L30) to the latest version `${VERSION}`. +- Ensure all tests on CI system are passed. +- Manually check etcd is buildable in Linux, Darwin and Windows. +- Manually check upgrade etcd cluster of previous minor version works well. +- Manually check new features work well. +- Add a signed tag through `git tag -s ${VERSION}`. +- Sanity check tag correctness through `git show tags/$VERSION`. +- Push the tag to GitHub through `git push origin tags/$VERSION`. This assumes `origin` corresponds to "https://github.com/etcd-io/etcd\". + +## Build release binaries and images + +- Ensure `docker` is available. + +Run release script in root directory: + +``` +TAG=gcr.io/etcd-development/etcd ./scripts/release.sh ${VERSION} +``` + +It generates all release binaries and images under directory ./release. + +## Sign binaries, images, and source code + +etcd project key must be used to sign the generated binaries and images.`$SUBKEYID` is the key ID of etcd project Yubikey. Connect the key and run `gpg2 --card-status` to get the ID. + +The following commands are used for public release sign: + +``` +cd release +for i in etcd-*{.zip,.tar.gz}; do gpg2 --default-key $SUBKEYID --armor --output ${i}.asc --detach-sign ${i}; done +for i in etcd-*{.zip,.tar.gz}; do gpg2 --verify ${i}.asc ${i}; done + +# sign zipped source code files +wget https://github.com/etcd-io/etcd/archive/${VERSION}.zip +gpg2 --armor --default-key $SUBKEYID --output ${VERSION}.zip.asc --detach-sign ${VERSION}.zip +gpg2 --verify ${VERSION}.zip.asc ${VERSION}.zip + +wget https://github.com/etcd-io/etcd/archive/${VERSION}.tar.gz +gpg2 --armor --default-key $SUBKEYID --output ${VERSION}.tar.gz.asc --detach-sign ${VERSION}.tar.gz +gpg2 --verify ${VERSION}.tar.gz.asc ${VERSION}.tar.gz +``` + +The public key for GPG signing can be found at [CoreOS Application Signing Key](https://coreos.com/security/app-signing-key) + + +## Publish release page in GitHub + +- Set release title as the version name. +- Follow the format of previous release pages. +- Attach the generated binaries and signatures. +- Select whether it is a pre-release. +- Publish the release! + +## Publish docker image in gcr.io + +- Push docker image: + +``` +gcloud docker -- login -u _json_key -p "$(cat /etc/gcp-key-etcd.json)" https://gcr.io + +for TARGET_ARCH in "-arm64" "-ppc64le" "-s390x" ""; do + gcloud docker -- push gcr.io/etcd-development/etcd:${VERSION}${TARGET_ARCH} +done +``` + +- Add `latest` tag to the new image on [gcr.io](https://console.cloud.google.com/gcr/images/etcd-development/GLOBAL/etcd?project=etcd-development&authuser=1) if this is a stable release. + +## Publish docker image in Quay.io + +- Build docker images with quay.io: + +``` +for TARGET_ARCH in "amd64" "arm64" "ppc64le" "s390x"; do + TAG=quay.io/coreos/etcd GOARCH=${TARGET_ARCH} \ + BINARYDIR=release/etcd-${VERSION}-linux-${TARGET_ARCH} \ + BUILDDIR=release \ + ./scripts/build-docker ${VERSION} +done +``` + +- Push docker image: + +``` +docker login quay.io + +for TARGET_ARCH in "-arm64" "-ppc64le" "-s390x" ""; do + docker push quay.io/coreos/etcd:${VERSION}${TARGET_ARCH} +done +``` + +- Add `latest` tag to the new image on [quay.io](https://quay.io/repository/coreos/etcd?tag=latest&tab=tags) if this is a stable release. + +## Announce to the etcd-dev Googlegroup + +- Follow the format of [previous release emails](https://groups.google.com/forum/#!forum/etcd-dev). +- Make sure to include a list of authors that contributed since the previous release - something like the following might be handy: + +``` +git log ...${PREV_VERSION} --pretty=format:"%an" | sort | uniq | tr '\n' ',' | sed -e 's#,#, #g' -e 's#, $##' +``` + +- Send email to etcd-dev@googlegroups.com + +## Post release + +- Create new stable branch through `git push origin ${VERSION_MAJOR}.${VERSION_MINOR}` if this is a major stable release. This assumes `origin` corresponds to "https://github.com/etcd-io/etcd\". +- Bump [hardcoded Version in the repository](https://github.com/etcd-io/etcd/blob/v3.4.15/version/version.go#L30) to the version `${VERSION}+git`. \ No newline at end of file From a1f24e9afc07bd8790cb6368fb2910ef6228e6f4 Mon Sep 17 00:00:00 2001 From: kkkkun Date: Tue, 15 Mar 2022 22:50:56 +0800 Subject: [PATCH 182/258] tests: Migrate endpoint tests to common framework --- tests/common/endpoint_test.go | 58 ++++++++++++++++++ tests/e2e/ctl_v3_auth_test.go | 11 +++- tests/e2e/ctl_v3_endpoint_test.go | 93 ----------------------------- tests/framework/e2e/etcdctl.go | 67 +++++++++++++++++++++ tests/framework/integration.go | 41 +++++++++++++ tests/framework/interface.go | 4 ++ tests/integration/v3_health_test.go | 39 ------------ 7 files changed, 180 insertions(+), 133 deletions(-) create mode 100644 tests/common/endpoint_test.go delete mode 100644 tests/e2e/ctl_v3_endpoint_test.go delete mode 100644 tests/integration/v3_health_test.go diff --git a/tests/common/endpoint_test.go b/tests/common/endpoint_test.go new file mode 100644 index 000000000000..371e85fbbb84 --- /dev/null +++ b/tests/common/endpoint_test.go @@ -0,0 +1,58 @@ +// Copyright 2022 The etcd Authors +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package common + +import ( + "testing" + "time" + + "go.etcd.io/etcd/tests/v3/framework/config" + "go.etcd.io/etcd/tests/v3/framework/testutils" +) + +func TestEndpointStatus(t *testing.T) { + testRunner.BeforeTest(t) + clus := testRunner.NewCluster(t, config.ClusterConfig{ClusterSize: 3}) + defer clus.Close() + testutils.ExecuteWithTimeout(t, 10*time.Second, func() { + _, err := clus.Client().Status() + if err != nil { + t.Fatalf("get endpoint status error: %v", err) + } + }) +} + +func TestEndpointHashKV(t *testing.T) { + testRunner.BeforeTest(t) + clus := testRunner.NewCluster(t, config.ClusterConfig{ClusterSize: 3}) + defer clus.Close() + testutils.ExecuteWithTimeout(t, 10*time.Second, func() { + _, err := clus.Client().HashKV(0) + if err != nil { + t.Fatalf("get endpoint hashkv error: %v", err) + } + }) +} + +func TestEndpointHealth(t *testing.T) { + testRunner.BeforeTest(t) + clus := testRunner.NewCluster(t, config.ClusterConfig{ClusterSize: 3}) + defer clus.Close() + testutils.ExecuteWithTimeout(t, 10*time.Second, func() { + if err := clus.Client().Health(); err != nil { + t.Fatalf("get endpoint health error: %v", err) + } + }) +} diff --git a/tests/e2e/ctl_v3_auth_test.go b/tests/e2e/ctl_v3_auth_test.go index 4d376f64c8c6..fd15a9e617ec 100644 --- a/tests/e2e/ctl_v3_auth_test.go +++ b/tests/e2e/ctl_v3_auth_test.go @@ -22,7 +22,7 @@ import ( "testing" "time" - "go.etcd.io/etcd/client/v3" + clientv3 "go.etcd.io/etcd/client/v3" "go.etcd.io/etcd/tests/v3/framework/e2e" ) @@ -1256,3 +1256,12 @@ func authTestRevisionConsistency(cx ctlCtx) { cx.t.Fatalf("auth revison shouldn't change when restarting etcd, expected: %d, got: %d", oldAuthRevision, newAuthRevision) } } + +func ctlV3EndpointHealth(cx ctlCtx) error { + cmdArgs := append(cx.PrefixArgs(), "endpoint", "health") + lines := make([]string, cx.epc.Cfg.ClusterSize) + for i := range lines { + lines[i] = "is healthy" + } + return e2e.SpawnWithExpects(cmdArgs, cx.envMap, lines...) +} diff --git a/tests/e2e/ctl_v3_endpoint_test.go b/tests/e2e/ctl_v3_endpoint_test.go deleted file mode 100644 index 8e364e8b4b81..000000000000 --- a/tests/e2e/ctl_v3_endpoint_test.go +++ /dev/null @@ -1,93 +0,0 @@ -// Copyright 2016 The etcd Authors -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -package e2e - -import ( - "context" - "fmt" - "net/url" - "testing" - "time" - - "go.etcd.io/etcd/client/v3" - "go.etcd.io/etcd/tests/v3/framework/e2e" -) - -func TestCtlV3EndpointHealth(t *testing.T) { testCtl(t, endpointHealthTest, withQuorum()) } -func TestCtlV3EndpointStatus(t *testing.T) { testCtl(t, endpointStatusTest, withQuorum()) } -func TestCtlV3EndpointHashKV(t *testing.T) { testCtl(t, endpointHashKVTest, withQuorum()) } - -func endpointHealthTest(cx ctlCtx) { - if err := ctlV3EndpointHealth(cx); err != nil { - cx.t.Fatalf("endpointStatusTest ctlV3EndpointHealth error (%v)", err) - } -} - -func ctlV3EndpointHealth(cx ctlCtx) error { - cmdArgs := append(cx.PrefixArgs(), "endpoint", "health") - lines := make([]string, cx.epc.Cfg.ClusterSize) - for i := range lines { - lines[i] = "is healthy" - } - return e2e.SpawnWithExpects(cmdArgs, cx.envMap, lines...) -} - -func endpointStatusTest(cx ctlCtx) { - if err := ctlV3EndpointStatus(cx); err != nil { - cx.t.Fatalf("endpointStatusTest ctlV3EndpointStatus error (%v)", err) - } -} - -func ctlV3EndpointStatus(cx ctlCtx) error { - cmdArgs := append(cx.PrefixArgs(), "endpoint", "status") - var eps []string - for _, ep := range cx.epc.EndpointsV3() { - u, _ := url.Parse(ep) - eps = append(eps, u.Host) - } - return e2e.SpawnWithExpects(cmdArgs, cx.envMap, eps...) -} - -func endpointHashKVTest(cx ctlCtx) { - if err := ctlV3EndpointHashKV(cx); err != nil { - cx.t.Fatalf("endpointHashKVTest ctlV3EndpointHashKV error (%v)", err) - } -} - -func ctlV3EndpointHashKV(cx ctlCtx) error { - eps := cx.epc.EndpointsV3() - - // get latest hash to compare - cli, err := clientv3.New(clientv3.Config{ - Endpoints: eps, - DialTimeout: 3 * time.Second, - }) - if err != nil { - cx.t.Fatal(err) - } - defer cli.Close() - hresp, err := cli.HashKV(context.TODO(), eps[0], 0) - if err != nil { - cx.t.Fatal(err) - } - - cmdArgs := append(cx.PrefixArgs(), "endpoint", "hashkv") - var ss []string - for _, ep := range cx.epc.EndpointsV3() { - u, _ := url.Parse(ep) - ss = append(ss, fmt.Sprintf("%s, %d", u.Host, hresp.Hash)) - } - return e2e.SpawnWithExpects(cmdArgs, cx.envMap, ss...) -} diff --git a/tests/framework/e2e/etcdctl.go b/tests/framework/e2e/etcdctl.go index f807c7fe67d1..18c436748264 100644 --- a/tests/framework/e2e/etcdctl.go +++ b/tests/framework/e2e/etcdctl.go @@ -176,3 +176,70 @@ func (ctl *EtcdctlV3) Compact(rev int64, o config.CompactOption) (*clientv3.Comp return nil, SpawnWithExpect(args, fmt.Sprintf("compacted revision %v", rev)) } + +func (ctl *EtcdctlV3) Status() ([]*clientv3.StatusResponse, error) { + args := ctl.cmdArgs() + args = append(args, "endpoint", "status", "-w", "json") + args = append(args, "--endpoints", strings.Join(ctl.endpoints, ",")) + cmd, err := SpawnCmd(args, nil) + if err != nil { + return nil, err + } + + var epStatus []*struct { + Endpoint string + Status *clientv3.StatusResponse + } + line, err := cmd.Expect("header") + if err != nil { + return nil, err + } + err = json.Unmarshal([]byte(line), &epStatus) + if err != nil { + return nil, err + } + resp := make([]*clientv3.StatusResponse, len(epStatus)) + for _, e := range epStatus { + resp = append(resp, e.Status) + } + return resp, err +} + +func (ctl *EtcdctlV3) HashKV(rev int64) ([]*clientv3.HashKVResponse, error) { + args := ctl.cmdArgs() + args = append(args, "endpoint", "hashkv", "-w", "json") + args = append(args, "--endpoints", strings.Join(ctl.endpoints, ",")) + args = append(args, "--rev", fmt.Sprint(rev)) + cmd, err := SpawnCmd(args, nil) + if err != nil { + return nil, err + } + var epHashKVs []*struct { + Endpoint string + HashKV *clientv3.HashKVResponse + } + line, err := cmd.Expect("header") + if err != nil { + return nil, err + } + err = json.Unmarshal([]byte(line), &epHashKVs) + if err != nil { + return nil, err + } + resp := make([]*clientv3.HashKVResponse, len(epHashKVs)) + for _, e := range epHashKVs { + resp = append(resp, e.HashKV) + } + return resp, err +} + +func (ctl *EtcdctlV3) Health() error { + args := ctl.cmdArgs() + args = append(args, "endpoint", "health") + lines := make([]string, len(ctl.endpoints)) + for i := range lines { + lines[i] = "is healthy" + } + return SpawnWithExpects(args, map[string]string{}, lines...) + +} diff --git a/tests/framework/integration.go b/tests/framework/integration.go index 18aabed5a334..73e15f130ff0 100644 --- a/tests/framework/integration.go +++ b/tests/framework/integration.go @@ -19,9 +19,12 @@ import ( "fmt" "testing" + healthpb "google.golang.org/grpc/health/grpc_health_v1" + "go.etcd.io/etcd/client/pkg/v3/testutil" "go.etcd.io/etcd/client/pkg/v3/transport" clientv3 "go.etcd.io/etcd/client/v3" + "go.etcd.io/etcd/tests/v3/framework/config" "go.etcd.io/etcd/tests/v3/framework/integration" "go.uber.org/zap" @@ -155,3 +158,41 @@ func (c integrationClient) Compact(rev int64, o config.CompactOption) (*clientv3 } return c.Client.Compact(ctx, rev, clientOpts...) } + +func (c integrationClient) Status() ([]*clientv3.StatusResponse, error) { + endpoints := c.Client.Endpoints() + var resp []*clientv3.StatusResponse + for _, ep := range endpoints { + status, err := c.Client.Status(context.Background(), ep) + if err != nil { + return nil, err + } + resp = append(resp, status) + } + return resp, nil +} + +func (c integrationClient) HashKV(rev int64) ([]*clientv3.HashKVResponse, error) { + endpoints := c.Client.Endpoints() + var resp []*clientv3.HashKVResponse + for _, ep := range endpoints { + hashKV, err := c.Client.HashKV(context.Background(), ep, rev) + if err != nil { + return nil, err + } + resp = append(resp, hashKV) + } + return resp, nil +} + +func (c integrationClient) Health() error { + cli := healthpb.NewHealthClient(c.Client.ActiveConnection()) + resp, err := cli.Check(context.TODO(), &healthpb.HealthCheckRequest{}) + if err != nil { + return err + } + if resp.Status != healthpb.HealthCheckResponse_SERVING { + return fmt.Errorf("status expected %s, got %s", healthpb.HealthCheckResponse_SERVING, resp.Status) + } + return nil +} diff --git a/tests/framework/interface.go b/tests/framework/interface.go index 5c1ac01145a6..f6982f321a89 100644 --- a/tests/framework/interface.go +++ b/tests/framework/interface.go @@ -37,4 +37,8 @@ type Client interface { Get(key string, opts config.GetOptions) (*clientv3.GetResponse, error) Delete(key string, opts config.DeleteOptions) (*clientv3.DeleteResponse, error) Compact(rev int64, opts config.CompactOption) (*clientv3.CompactResponse, error) + + Status() ([]*clientv3.StatusResponse, error) + HashKV(rev int64) ([]*clientv3.HashKVResponse, error) + Health() error } diff --git a/tests/integration/v3_health_test.go b/tests/integration/v3_health_test.go deleted file mode 100644 index 98b64c63fe05..000000000000 --- a/tests/integration/v3_health_test.go +++ /dev/null @@ -1,39 +0,0 @@ -// Copyright 2017 The etcd Authors -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -package integration - -import ( - "context" - "testing" - - "go.etcd.io/etcd/tests/v3/framework/integration" - healthpb "google.golang.org/grpc/health/grpc_health_v1" -) - -func TestHealthCheck(t *testing.T) { - integration.BeforeTest(t) - - clus := integration.NewCluster(t, &integration.ClusterConfig{Size: 1}) - defer clus.Terminate(t) - - cli := healthpb.NewHealthClient(clus.RandClient().ActiveConnection()) - resp, err := cli.Check(context.TODO(), &healthpb.HealthCheckRequest{}) - if err != nil { - t.Fatal(err) - } - if resp.Status != healthpb.HealthCheckResponse_SERVING { - t.Fatalf("status expected %s, got %s", healthpb.HealthCheckResponse_SERVING, resp.Status) - } -} From b50239f9a46a11ec6f4d070e305bf7c2b3e49f50 Mon Sep 17 00:00:00 2001 From: Danielle Lancashire Date: Tue, 15 Mar 2022 16:38:59 +0000 Subject: [PATCH 183/258] integration/client/watch: remove duplicate setup This test was being skipped as it has a duplicate call to integration2.BeginTest. This duplicate call registered a second handler for leak detection which failed and skipped the test as the wrapper (runWatchTest) has already started a cluster. --- tests/integration/clientv3/watch_test.go | 2 -- 1 file changed, 2 deletions(-) diff --git a/tests/integration/clientv3/watch_test.go b/tests/integration/clientv3/watch_test.go index 1d472ecc55ca..f464ec9bb964 100644 --- a/tests/integration/clientv3/watch_test.go +++ b/tests/integration/clientv3/watch_test.go @@ -299,8 +299,6 @@ func TestWatchCancelRunning(t *testing.T) { } func testWatchCancelRunning(t *testing.T, wctx *watchctx) { - integration2.BeforeTest(t) - ctx, cancel := context.WithCancel(context.Background()) if wctx.ch = wctx.w.Watch(ctx, "a"); wctx.ch == nil { t.Fatalf("expected non-nil watcher channel") From 3bbbef54c17b54186ea2467317d4e60eeec6e785 Mon Sep 17 00:00:00 2001 From: Danielle Lancashire Date: Tue, 15 Mar 2022 17:42:47 +0000 Subject: [PATCH 184/258] integration/clientv3/exp/recipes: Fix lock test TestMutexTryLock(SingleNode|MultiNode) were being skipped as they had duplicate calls to integration2.BeginTest. These duplicate calls registered a second handler for leak detection which failed and skipped the test as the wrappers had already started a cluster. part of #13698 --- .../integration/clientv3/experimental/recipes/v3_lock_test.go | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/tests/integration/clientv3/experimental/recipes/v3_lock_test.go b/tests/integration/clientv3/experimental/recipes/v3_lock_test.go index ee130679bd02..ab7e7ff9e9cd 100644 --- a/tests/integration/clientv3/experimental/recipes/v3_lock_test.go +++ b/tests/integration/clientv3/experimental/recipes/v3_lock_test.go @@ -21,7 +21,7 @@ import ( "time" "go.etcd.io/etcd/api/v3/mvccpb" - "go.etcd.io/etcd/client/v3" + clientv3 "go.etcd.io/etcd/client/v3" "go.etcd.io/etcd/client/v3/concurrency" recipe "go.etcd.io/etcd/client/v3/experimental/recipes" integration2 "go.etcd.io/etcd/tests/v3/framework/integration" @@ -113,8 +113,6 @@ func TestMutexTryLockMultiNode(t *testing.T) { } func testMutexTryLock(t *testing.T, lockers int, chooseClient func() *clientv3.Client) { - integration2.BeforeTest(t) - lockedC := make(chan *concurrency.Mutex) notlockedC := make(chan *concurrency.Mutex) stopC := make(chan struct{}) From a045e4bbfc26f45e8cc64663a5a82cbc1b1a2fe2 Mon Sep 17 00:00:00 2001 From: Danielle Lancashire Date: Tue, 15 Mar 2022 11:06:57 +0000 Subject: [PATCH 185/258] expect_test: Look up binaries from the path Not all systems include binaries in the same location. On my (NixOS, so albeit a little weird) system these binaries exist in very different locations. This test switches to looking up the paths from the users PATH or skips the test if they do not exist to improve the `make test` experience on such systems. --- pkg/expect/expect_test.go | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/pkg/expect/expect_test.go b/pkg/expect/expect_test.go index c5ed18ec60bf..f091f1377de6 100644 --- a/pkg/expect/expect_test.go +++ b/pkg/expect/expect_test.go @@ -23,7 +23,7 @@ import ( ) func TestExpectFunc(t *testing.T) { - ep, err := NewExpect("/bin/echo", "hello world") + ep, err := NewExpect("echo", "hello world") if err != nil { t.Fatal(err) } @@ -41,7 +41,7 @@ func TestExpectFunc(t *testing.T) { } func TestEcho(t *testing.T) { - ep, err := NewExpect("/bin/echo", "hello world") + ep, err := NewExpect("echo", "hello world") if err != nil { t.Fatal(err) } @@ -62,7 +62,7 @@ func TestEcho(t *testing.T) { } func TestLineCount(t *testing.T) { - ep, err := NewExpect("/usr/bin/printf", "1\n2\n3") + ep, err := NewExpect("printf", "1\n2\n3") if err != nil { t.Fatal(err) } @@ -83,7 +83,7 @@ func TestLineCount(t *testing.T) { } func TestSend(t *testing.T) { - ep, err := NewExpect("/usr/bin/tr", "a", "b") + ep, err := NewExpect("tr", "a", "b") if err != nil { t.Fatal(err) } @@ -99,7 +99,7 @@ func TestSend(t *testing.T) { } func TestSignal(t *testing.T) { - ep, err := NewExpect("/bin/sleep", "100") + ep, err := NewExpect("sleep", "100") if err != nil { t.Fatal(err) } From edce939f6e8b414df4170577ab7a3cd243d8c2e9 Mon Sep 17 00:00:00 2001 From: ahrtr Date: Thu, 10 Mar 2022 14:37:45 +0800 Subject: [PATCH 186/258] add one more field storageVersion into StatusResponse When performing the downgrade operation, users can confirm whether each member is ready to be downgraded using the field 'storageVersion'. If it's equal to the 'target version' in the downgrade command, then it's ready to be downgraded; otherwise, the etcd member is still in progress of processing the db file. --- CHANGELOG/CHANGELOG-3.6.md | 1 + .../apispec/swagger/rpc.swagger.json | 4 + api/etcdserverpb/rpc.pb.go | 607 ++++++++++-------- api/etcdserverpb/rpc.proto | 2 + etcdctl/ctlv3/command/printer.go | 3 +- etcdctl/ctlv3/command/printer_fields.go | 1 + scripts/etcd_version_annotations.txt | 1 + server/etcdserver/adapters.go | 6 +- server/etcdserver/api/v3rpc/maintenance.go | 7 +- server/etcdserver/server.go | 8 +- 10 files changed, 355 insertions(+), 285 deletions(-) diff --git a/CHANGELOG/CHANGELOG-3.6.md b/CHANGELOG/CHANGELOG-3.6.md index 06c5c6d6200b..f33b697bf5a3 100644 --- a/CHANGELOG/CHANGELOG-3.6.md +++ b/CHANGELOG/CHANGELOG-3.6.md @@ -22,6 +22,7 @@ See [code changes](https://github.com/etcd-io/etcd/compare/v3.5.0...v3.6.0). - Add command to generate [shell completion](https://github.com/etcd-io/etcd/pull/13133). - When print endpoint status, [show db size in use](https://github.com/etcd-io/etcd/pull/13639) - [Always print the raft_term in decimal](https://github.com/etcd-io/etcd/pull/13711) when displaying member list in json. +- [Add one more field `storageVersion`](https://github.com/etcd-io/etcd/pull/13773) into the response of command `etcdctl endpoint status`. ### etcdutl v3 diff --git a/Documentation/dev-guide/apispec/swagger/rpc.swagger.json b/Documentation/dev-guide/apispec/swagger/rpc.swagger.json index 07e4b33f52f9..35cc83fbddcb 100644 --- a/Documentation/dev-guide/apispec/swagger/rpc.swagger.json +++ b/Documentation/dev-guide/apispec/swagger/rpc.swagger.json @@ -2771,6 +2771,10 @@ "type": "string", "format": "uint64" }, + "storageVersion": { + "description": "storageVersion is the version of the db file.", + "type": "string" + }, "version": { "description": "version is the cluster protocol version used by the responding member.", "type": "string" diff --git a/api/etcdserverpb/rpc.pb.go b/api/etcdserverpb/rpc.pb.go index 46a8889d1220..52c53f8afcb1 100644 --- a/api/etcdserverpb/rpc.pb.go +++ b/api/etcdserverpb/rpc.pb.go @@ -4235,7 +4235,9 @@ type StatusResponse struct { // dbSizeInUse is the size of the backend database logically in use, in bytes, of the responding member. DbSizeInUse int64 `protobuf:"varint,9,opt,name=dbSizeInUse,proto3" json:"dbSizeInUse,omitempty"` // isLearner indicates if the member is raft learner. - IsLearner bool `protobuf:"varint,10,opt,name=isLearner,proto3" json:"isLearner,omitempty"` + IsLearner bool `protobuf:"varint,10,opt,name=isLearner,proto3" json:"isLearner,omitempty"` + // storageVersion is the version of the db file. + StorageVersion string `protobuf:"bytes,11,opt,name=storageVersion,proto3" json:"storageVersion,omitempty"` XXX_NoUnkeyedLiteral struct{} `json:"-"` XXX_unrecognized []byte `json:"-"` XXX_sizecache int32 `json:"-"` @@ -4344,6 +4346,13 @@ func (m *StatusResponse) GetIsLearner() bool { return false } +func (m *StatusResponse) GetStorageVersion() string { + if m != nil { + return m.StorageVersion + } + return "" +} + type AuthEnableRequest struct { XXX_NoUnkeyedLiteral struct{} `json:"-"` XXX_unrecognized []byte `json:"-"` @@ -6166,282 +6175,283 @@ func init() { func init() { proto.RegisterFile("rpc.proto", fileDescriptor_77a6da22d6a3feb1) } var fileDescriptor_77a6da22d6a3feb1 = []byte{ - // 4393 bytes of a gzipped FileDescriptorProto - 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xc4, 0x5c, 0x4f, 0x6f, 0x24, 0x49, - 0x56, 0x77, 0xd6, 0x5f, 0xd7, 0xab, 0x72, 0xb9, 0x1c, 0xed, 0xee, 0xa9, 0xae, 0xe9, 0x76, 0x7b, - 0xb2, 0xa7, 0x67, 0x3c, 0x9e, 0x19, 0xbb, 0xdb, 0x76, 0xef, 0x40, 0xa3, 0x19, 0xb6, 0xda, 0xae, - 0x69, 0x9b, 0x76, 0xdb, 0xde, 0x74, 0x75, 0xcf, 0xce, 0x20, 0xad, 0x49, 0x57, 0x45, 0xdb, 0xb9, - 0xae, 0xca, 0xac, 0xcd, 0xcc, 0x72, 0xdb, 0xcb, 0x61, 0x97, 0x85, 0x65, 0xb5, 0x20, 0xad, 0xc4, - 0x22, 0xa1, 0x15, 0x82, 0x0b, 0x42, 0x82, 0x03, 0x20, 0x38, 0x70, 0x40, 0x1c, 0x38, 0xc0, 0x01, - 0x0e, 0x48, 0x48, 0x7c, 0x01, 0x18, 0xf6, 0xc4, 0x57, 0x40, 0x42, 0xab, 0xf8, 0x97, 0x11, 0x99, - 0x19, 0x65, 0x7b, 0xd6, 0x1e, 0xed, 0x65, 0xba, 0x32, 0xe2, 0xc5, 0xfb, 0xbd, 0x78, 0x2f, 0xe2, - 0xbd, 0x88, 0xf7, 0xc2, 0x03, 0x25, 0x7f, 0xd0, 0x59, 0x18, 0xf8, 0x5e, 0xe8, 0xa1, 0x0a, 0x0e, - 0x3b, 0xdd, 0x00, 0xfb, 0xc7, 0xd8, 0x1f, 0xec, 0x37, 0xa6, 0x0f, 0xbc, 0x03, 0x8f, 0x76, 0x2c, - 0x92, 0x5f, 0x8c, 0xa6, 0x51, 0x27, 0x34, 0x8b, 0xf6, 0xc0, 0x59, 0xec, 0x1f, 0x77, 0x3a, 0x83, - 0xfd, 0xc5, 0xa3, 0x63, 0xde, 0xd3, 0x88, 0x7a, 0xec, 0x61, 0x78, 0x38, 0xd8, 0xa7, 0xff, 0xf0, - 0xbe, 0xd9, 0xa8, 0xef, 0x18, 0xfb, 0x81, 0xe3, 0xb9, 0x83, 0x7d, 0xf1, 0x8b, 0x53, 0xdc, 0x3a, - 0xf0, 0xbc, 0x83, 0x1e, 0x66, 0xe3, 0x5d, 0xd7, 0x0b, 0xed, 0xd0, 0xf1, 0xdc, 0x80, 0xf5, 0x9a, - 0x3f, 0x32, 0xa0, 0x6a, 0xe1, 0x60, 0xe0, 0xb9, 0x01, 0x5e, 0xc7, 0x76, 0x17, 0xfb, 0xe8, 0x36, - 0x40, 0xa7, 0x37, 0x0c, 0x42, 0xec, 0xef, 0x39, 0xdd, 0xba, 0x31, 0x6b, 0xcc, 0xe5, 0xac, 0x12, - 0x6f, 0xd9, 0xe8, 0xa2, 0xd7, 0xa1, 0xd4, 0xc7, 0xfd, 0x7d, 0xd6, 0x9b, 0xa1, 0xbd, 0xe3, 0xac, - 0x61, 0xa3, 0x8b, 0x1a, 0x30, 0xee, 0xe3, 0x63, 0x87, 0xc0, 0xd7, 0xb3, 0xb3, 0xc6, 0x5c, 0xd6, - 0x8a, 0xbe, 0xc9, 0x40, 0xdf, 0x7e, 0x19, 0xee, 0x85, 0xd8, 0xef, 0xd7, 0x73, 0x6c, 0x20, 0x69, - 0x68, 0x63, 0xbf, 0xff, 0xa8, 0xf8, 0xbd, 0xbf, 0xaf, 0x67, 0x97, 0x17, 0xee, 0x9b, 0xff, 0x9c, - 0x87, 0x8a, 0x65, 0xbb, 0x07, 0xd8, 0xc2, 0xdf, 0x1a, 0xe2, 0x20, 0x44, 0x35, 0xc8, 0x1e, 0xe1, - 0x53, 0x2a, 0x47, 0xc5, 0x22, 0x3f, 0x19, 0x23, 0xf7, 0x00, 0xef, 0x61, 0x97, 0x49, 0x50, 0x21, - 0x8c, 0xdc, 0x03, 0xdc, 0x72, 0xbb, 0x68, 0x1a, 0xf2, 0x3d, 0xa7, 0xef, 0x84, 0x1c, 0x9e, 0x7d, - 0xc4, 0xe4, 0xca, 0x25, 0xe4, 0x5a, 0x05, 0x08, 0x3c, 0x3f, 0xdc, 0xf3, 0xfc, 0x2e, 0xf6, 0xeb, - 0xf9, 0x59, 0x63, 0xae, 0xba, 0xf4, 0xe6, 0x82, 0x6a, 0xb1, 0x05, 0x55, 0xa0, 0x85, 0x5d, 0xcf, - 0x0f, 0xb7, 0x09, 0xad, 0x55, 0x0a, 0xc4, 0x4f, 0xf4, 0x31, 0x94, 0x29, 0x93, 0xd0, 0xf6, 0x0f, - 0x70, 0x58, 0x2f, 0x50, 0x2e, 0xf7, 0xce, 0xe1, 0xd2, 0xa6, 0xc4, 0x16, 0x85, 0x67, 0xbf, 0x91, - 0x09, 0x95, 0x00, 0xfb, 0x8e, 0xdd, 0x73, 0xbe, 0x6d, 0xef, 0xf7, 0x70, 0xbd, 0x38, 0x6b, 0xcc, - 0x8d, 0x5b, 0xb1, 0x36, 0x32, 0xff, 0x23, 0x7c, 0x1a, 0xec, 0x79, 0x6e, 0xef, 0xb4, 0x3e, 0x4e, - 0x09, 0xc6, 0x49, 0xc3, 0xb6, 0xdb, 0x3b, 0xa5, 0xd6, 0xf3, 0x86, 0x6e, 0xc8, 0x7a, 0x4b, 0xb4, - 0xb7, 0x44, 0x5b, 0x68, 0xf7, 0x03, 0xa8, 0xf5, 0x1d, 0x77, 0xaf, 0xef, 0x75, 0xf7, 0x22, 0x85, - 0x00, 0x51, 0xc8, 0xe3, 0xe2, 0xef, 0x51, 0x0b, 0x3c, 0xb0, 0xaa, 0x7d, 0xc7, 0x7d, 0xe6, 0x75, - 0x2d, 0xa1, 0x1f, 0x32, 0xc4, 0x3e, 0x89, 0x0f, 0x29, 0x27, 0x87, 0xd8, 0x27, 0xea, 0x90, 0x0f, - 0xe0, 0x1a, 0x41, 0xe9, 0xf8, 0xd8, 0x0e, 0xb1, 0x1c, 0x55, 0x89, 0x8f, 0x9a, 0xea, 0x3b, 0xee, - 0x2a, 0x25, 0x89, 0x0d, 0xb4, 0x4f, 0x52, 0x03, 0x27, 0x92, 0x03, 0xed, 0x93, 0xf8, 0x40, 0xf3, - 0x03, 0x28, 0x45, 0x76, 0x41, 0xe3, 0x90, 0xdb, 0xda, 0xde, 0x6a, 0xd5, 0xc6, 0x10, 0x40, 0xa1, - 0xb9, 0xbb, 0xda, 0xda, 0x5a, 0xab, 0x19, 0xa8, 0x0c, 0xc5, 0xb5, 0x16, 0xfb, 0xc8, 0x34, 0x8a, - 0x3f, 0xe6, 0xeb, 0xed, 0x29, 0x80, 0x34, 0x05, 0x2a, 0x42, 0xf6, 0x69, 0xeb, 0xd3, 0xda, 0x18, - 0x21, 0x7e, 0xd1, 0xb2, 0x76, 0x37, 0xb6, 0xb7, 0x6a, 0x06, 0xe1, 0xb2, 0x6a, 0xb5, 0x9a, 0xed, - 0x56, 0x2d, 0x43, 0x28, 0x9e, 0x6d, 0xaf, 0xd5, 0xb2, 0xa8, 0x04, 0xf9, 0x17, 0xcd, 0xcd, 0xe7, - 0xad, 0x5a, 0x2e, 0x62, 0x26, 0x57, 0xf1, 0x9f, 0x18, 0x30, 0xc1, 0xcd, 0xcd, 0xf6, 0x16, 0x5a, - 0x81, 0xc2, 0x21, 0xdd, 0x5f, 0x74, 0x25, 0x97, 0x97, 0x6e, 0x25, 0xd6, 0x46, 0x6c, 0x0f, 0x5a, - 0x9c, 0x16, 0x99, 0x90, 0x3d, 0x3a, 0x0e, 0xea, 0x99, 0xd9, 0xec, 0x5c, 0x79, 0xa9, 0xb6, 0xc0, - 0x3c, 0xc3, 0xc2, 0x53, 0x7c, 0xfa, 0xc2, 0xee, 0x0d, 0xb1, 0x45, 0x3a, 0x11, 0x82, 0x5c, 0xdf, - 0xf3, 0x31, 0x5d, 0xf0, 0xe3, 0x16, 0xfd, 0x4d, 0x76, 0x01, 0xb5, 0x39, 0x5f, 0xec, 0xec, 0x43, - 0x8a, 0xf7, 0xef, 0x06, 0xc0, 0xce, 0x30, 0x1c, 0xbd, 0xc5, 0xa6, 0x21, 0x7f, 0x4c, 0x10, 0xf8, - 0xf6, 0x62, 0x1f, 0x74, 0x6f, 0x61, 0x3b, 0xc0, 0xd1, 0xde, 0x22, 0x1f, 0x68, 0x16, 0x8a, 0x03, - 0x1f, 0x1f, 0xef, 0x1d, 0x1d, 0x53, 0xb4, 0x71, 0x69, 0xa7, 0x02, 0x69, 0x7f, 0x7a, 0x8c, 0xe6, - 0xa1, 0xe2, 0x1c, 0xb8, 0x9e, 0x8f, 0xf7, 0x18, 0xd3, 0xbc, 0x4a, 0xb6, 0x64, 0x95, 0x59, 0x27, - 0x9d, 0x92, 0x42, 0xcb, 0xa0, 0x0a, 0x5a, 0xda, 0x4d, 0xd2, 0x27, 0xe7, 0xf3, 0x5d, 0x03, 0xca, - 0x74, 0x3e, 0x97, 0x52, 0xf6, 0x92, 0x9c, 0x48, 0x86, 0x0e, 0x4b, 0x29, 0x3c, 0x35, 0x35, 0x29, - 0x82, 0x0b, 0x68, 0x0d, 0xf7, 0x70, 0x88, 0x2f, 0xe3, 0xbc, 0x14, 0x55, 0x66, 0xb5, 0xaa, 0x94, - 0x78, 0x7f, 0x6e, 0xc0, 0xb5, 0x18, 0xe0, 0xa5, 0xa6, 0x5e, 0x87, 0x62, 0x97, 0x32, 0x63, 0x32, - 0x65, 0x2d, 0xf1, 0x89, 0x56, 0x60, 0x9c, 0x8b, 0x14, 0xd4, 0xb3, 0xfa, 0x65, 0x28, 0xa5, 0x2c, - 0x32, 0x29, 0x03, 0x29, 0xe6, 0x3f, 0x66, 0xa0, 0xc4, 0x95, 0xb1, 0x3d, 0x40, 0x4d, 0x98, 0xf0, - 0xd9, 0xc7, 0x1e, 0x9d, 0x33, 0x97, 0xb1, 0x31, 0xda, 0x4f, 0xae, 0x8f, 0x59, 0x15, 0x3e, 0x84, - 0x36, 0xa3, 0x5f, 0x81, 0xb2, 0x60, 0x31, 0x18, 0x86, 0xdc, 0x50, 0xf5, 0x38, 0x03, 0xb9, 0xb4, - 0xd7, 0xc7, 0x2c, 0xe0, 0xe4, 0x3b, 0xc3, 0x10, 0xb5, 0x61, 0x5a, 0x0c, 0x66, 0xf3, 0xe3, 0x62, - 0x64, 0x29, 0x97, 0xd9, 0x38, 0x97, 0xb4, 0x39, 0xd7, 0xc7, 0x2c, 0xc4, 0xc7, 0x2b, 0x9d, 0x68, - 0x4d, 0x8a, 0x14, 0x9e, 0xb0, 0xf8, 0x92, 0x12, 0xa9, 0x7d, 0xe2, 0x72, 0x26, 0x42, 0x5b, 0xcb, - 0x8a, 0x6c, 0xed, 0x13, 0x37, 0x52, 0xd9, 0xe3, 0x12, 0x14, 0x79, 0xb3, 0xf9, 0x6f, 0x19, 0x00, - 0x61, 0xb1, 0xed, 0x01, 0x5a, 0x83, 0xaa, 0xcf, 0xbf, 0x62, 0xfa, 0x7b, 0x5d, 0xab, 0x3f, 0x6e, - 0xe8, 0x31, 0x6b, 0x42, 0x0c, 0x62, 0xe2, 0x7e, 0x04, 0x95, 0x88, 0x8b, 0x54, 0xe1, 0x4d, 0x8d, - 0x0a, 0x23, 0x0e, 0x65, 0x31, 0x80, 0x28, 0xf1, 0x13, 0xb8, 0x1e, 0x8d, 0xd7, 0x68, 0xf1, 0x8d, - 0x33, 0xb4, 0x18, 0x31, 0xbc, 0x26, 0x38, 0xa8, 0x7a, 0x7c, 0xa2, 0x08, 0x26, 0x15, 0x79, 0x53, - 0xa3, 0x48, 0x46, 0xa4, 0x6a, 0x32, 0x92, 0x30, 0xa6, 0x4a, 0x20, 0x61, 0x9f, 0xb5, 0x9b, 0x7f, - 0x99, 0x83, 0xe2, 0xaa, 0xd7, 0x1f, 0xd8, 0x3e, 0x59, 0x44, 0x05, 0x1f, 0x07, 0xc3, 0x5e, 0x48, - 0x15, 0x58, 0x5d, 0xba, 0x1b, 0xc7, 0xe0, 0x64, 0xe2, 0x5f, 0x8b, 0x92, 0x5a, 0x7c, 0x08, 0x19, - 0xcc, 0xa3, 0x7c, 0xe6, 0x02, 0x83, 0x79, 0x8c, 0xe7, 0x43, 0x84, 0x43, 0xc8, 0x4a, 0x87, 0xd0, - 0x80, 0x22, 0x3f, 0xb0, 0x31, 0x67, 0xbd, 0x3e, 0x66, 0x89, 0x06, 0xf4, 0x0e, 0x4c, 0x26, 0x43, - 0x61, 0x9e, 0xd3, 0x54, 0x3b, 0xf1, 0xc8, 0x79, 0x17, 0x2a, 0xb1, 0x08, 0x5d, 0xe0, 0x74, 0xe5, - 0xbe, 0x12, 0x97, 0x6f, 0x08, 0xb7, 0x4e, 0x8e, 0x15, 0x95, 0xf5, 0x31, 0xe1, 0xd8, 0xef, 0x08, - 0xc7, 0x3e, 0xae, 0x06, 0x5a, 0xa2, 0x57, 0xee, 0xe3, 0xdf, 0x54, 0xbd, 0xd6, 0x57, 0xc9, 0xe0, - 0x88, 0x48, 0xba, 0x2f, 0xd3, 0x82, 0x89, 0x98, 0xca, 0x48, 0x8c, 0x6c, 0x7d, 0xed, 0x79, 0x73, - 0x93, 0x05, 0xd4, 0x27, 0x34, 0x86, 0x5a, 0x35, 0x83, 0x04, 0xe8, 0xcd, 0xd6, 0xee, 0x6e, 0x2d, - 0x83, 0x6e, 0x40, 0x69, 0x6b, 0xbb, 0xbd, 0xc7, 0xa8, 0xb2, 0x8d, 0xe2, 0x1f, 0x33, 0x4f, 0x22, - 0xe3, 0xf3, 0xa7, 0x11, 0x4f, 0x1e, 0xa2, 0x95, 0xc8, 0x3c, 0xa6, 0x44, 0x66, 0x43, 0x44, 0xe6, - 0x8c, 0x8c, 0xcc, 0x59, 0x84, 0x20, 0xbf, 0xd9, 0x6a, 0xee, 0xd2, 0x20, 0xcd, 0x58, 0x2f, 0xa7, - 0xa3, 0xf5, 0xe3, 0x2a, 0x54, 0x98, 0x79, 0xf6, 0x86, 0x2e, 0x39, 0x4c, 0xfc, 0x95, 0x01, 0x20, - 0x37, 0x2c, 0x5a, 0x84, 0x62, 0x87, 0x89, 0x50, 0x37, 0xa8, 0x07, 0xbc, 0xae, 0xb5, 0xb8, 0x25, - 0xa8, 0xd0, 0x03, 0x28, 0x06, 0xc3, 0x4e, 0x07, 0x07, 0x22, 0x72, 0xbf, 0x96, 0x74, 0xc2, 0xdc, - 0x21, 0x5a, 0x82, 0x8e, 0x0c, 0x79, 0x69, 0x3b, 0xbd, 0x21, 0x8d, 0xe3, 0x67, 0x0f, 0xe1, 0x74, - 0xd2, 0xc7, 0xfe, 0x99, 0x01, 0x65, 0x65, 0x5b, 0xfc, 0x9c, 0x21, 0xe0, 0x16, 0x94, 0xa8, 0x30, - 0xb8, 0xcb, 0x83, 0xc0, 0xb8, 0x25, 0x1b, 0xd0, 0x57, 0xa0, 0x24, 0x76, 0x92, 0x88, 0x03, 0x75, - 0x3d, 0xdb, 0xed, 0x81, 0x25, 0x49, 0xa5, 0x90, 0x6d, 0x98, 0xa2, 0x7a, 0xea, 0x90, 0xdb, 0x87, - 0xd0, 0xac, 0x7a, 0x2c, 0x37, 0x12, 0xc7, 0xf2, 0x06, 0x8c, 0x0f, 0x0e, 0x4f, 0x03, 0xa7, 0x63, - 0xf7, 0xb8, 0x38, 0xd1, 0xb7, 0xe4, 0xba, 0x0b, 0x48, 0xe5, 0x7a, 0x19, 0x05, 0x48, 0xa6, 0x37, - 0xa0, 0xbc, 0x6e, 0x07, 0x87, 0x5c, 0x48, 0xd9, 0xbe, 0x02, 0x13, 0xa4, 0xfd, 0xe9, 0x8b, 0x0b, - 0x88, 0x2f, 0x46, 0x2d, 0xd3, 0x1b, 0x96, 0x18, 0x76, 0x29, 0x03, 0x21, 0xc8, 0x1d, 0xda, 0xc1, - 0x21, 0x55, 0xc6, 0x84, 0x45, 0x7f, 0xa3, 0x77, 0xa0, 0xd6, 0x61, 0xf3, 0xdf, 0x4b, 0xdc, 0xbb, - 0x26, 0x79, 0xbb, 0x95, 0x12, 0xc8, 0x86, 0x0a, 0x9b, 0xde, 0x55, 0x4b, 0x23, 0x35, 0xd5, 0x80, - 0xc9, 0x5d, 0xd7, 0x1e, 0x04, 0x87, 0x5e, 0x98, 0xd0, 0xe2, 0xb2, 0xf9, 0x77, 0x06, 0xd4, 0x64, - 0xe7, 0xa5, 0x64, 0x78, 0x1b, 0x26, 0x7d, 0xdc, 0xb7, 0x1d, 0xd7, 0x71, 0x0f, 0xf6, 0xf6, 0x4f, - 0x43, 0x1c, 0xf0, 0x0b, 0x69, 0x35, 0x6a, 0x7e, 0x4c, 0x5a, 0x89, 0xb0, 0xfb, 0x3d, 0x6f, 0x9f, - 0xbb, 0x5d, 0xfa, 0x1b, 0xbd, 0x11, 0xf7, 0xbb, 0x25, 0xe1, 0xd0, 0xbe, 0x12, 0xb9, 0x5f, 0x29, - 0xf3, 0x4f, 0x32, 0x50, 0xf9, 0xc4, 0x0e, 0x3b, 0x62, 0x4d, 0xa0, 0x0d, 0xa8, 0x46, 0x8e, 0x99, - 0xb6, 0x70, 0xb9, 0x13, 0x47, 0x08, 0x3a, 0x46, 0xdc, 0x54, 0xc4, 0x11, 0x62, 0xa2, 0xa3, 0x36, - 0x50, 0x56, 0xb6, 0xdb, 0xc1, 0xbd, 0x88, 0x55, 0x66, 0x34, 0x2b, 0x4a, 0xa8, 0xb2, 0x52, 0x1b, - 0xd0, 0xd7, 0xa1, 0x36, 0xf0, 0xbd, 0x03, 0x1f, 0x07, 0x41, 0xc4, 0x8c, 0x05, 0x65, 0x53, 0xc3, - 0x6c, 0x87, 0x93, 0x26, 0xce, 0x25, 0x2b, 0xeb, 0x63, 0xd6, 0xe4, 0x20, 0xde, 0x27, 0x5d, 0xe5, - 0xa4, 0x3c, 0xc1, 0x31, 0x5f, 0xf9, 0x83, 0x2c, 0xa0, 0xf4, 0x34, 0xbf, 0xe8, 0xc1, 0xf7, 0x1e, - 0x54, 0x83, 0xd0, 0xf6, 0x53, 0xab, 0x78, 0x82, 0xb6, 0x46, 0xf1, 0xeb, 0x6d, 0x88, 0x24, 0xdb, - 0x73, 0xbd, 0xd0, 0x79, 0x79, 0xca, 0xae, 0x1c, 0x56, 0x55, 0x34, 0x6f, 0xd1, 0x56, 0xb4, 0x05, - 0xc5, 0x97, 0x4e, 0x2f, 0xc4, 0x7e, 0x50, 0xcf, 0xcf, 0x66, 0xe7, 0xaa, 0x4b, 0xef, 0x9e, 0x67, - 0x98, 0x85, 0x8f, 0x29, 0x7d, 0xfb, 0x74, 0xa0, 0x9e, 0x67, 0x39, 0x13, 0xf5, 0x60, 0x5e, 0xd0, - 0xdf, 0x71, 0x4c, 0x18, 0x7f, 0x45, 0x98, 0xee, 0x39, 0x5d, 0x1a, 0x5d, 0xa3, 0x28, 0xba, 0x62, - 0x15, 0x69, 0xc7, 0x46, 0x17, 0xdd, 0x85, 0xf1, 0x97, 0xbe, 0x7d, 0xd0, 0xc7, 0x6e, 0xc8, 0xee, - 0xed, 0x92, 0x26, 0xea, 0x30, 0x17, 0x00, 0xa4, 0x28, 0x24, 0x96, 0x6d, 0x6d, 0xef, 0x3c, 0x6f, - 0xd7, 0xc6, 0x50, 0x05, 0xc6, 0xb7, 0xb6, 0xd7, 0x5a, 0x9b, 0x2d, 0x12, 0xed, 0x44, 0x14, 0x7b, - 0x20, 0x37, 0x5d, 0x53, 0x18, 0x22, 0xb6, 0x26, 0x54, 0xb9, 0x8c, 0xf8, 0x35, 0x5a, 0xc8, 0x25, - 0x58, 0x3c, 0x30, 0xef, 0xc0, 0xb4, 0x6e, 0x69, 0x08, 0x82, 0x15, 0xf3, 0x5f, 0x32, 0x30, 0xc1, - 0x37, 0xc2, 0xa5, 0x76, 0xee, 0x4d, 0x45, 0x2a, 0x7e, 0xe1, 0x10, 0x4a, 0xaa, 0x43, 0x91, 0x6d, - 0x90, 0x2e, 0xbf, 0xd1, 0x8a, 0x4f, 0xe2, 0x6e, 0xd9, 0x7a, 0xc7, 0x5d, 0x6e, 0xf6, 0xe8, 0x5b, - 0xeb, 0x08, 0xf3, 0x5a, 0x47, 0x88, 0xde, 0x83, 0x89, 0x68, 0xc3, 0xd9, 0x01, 0x3f, 0x2a, 0x95, - 0xa4, 0x29, 0x2a, 0x62, 0x53, 0x91, 0xce, 0x98, 0xcd, 0x8a, 0x23, 0x6c, 0x86, 0xee, 0x41, 0x01, - 0x1f, 0x63, 0x37, 0x0c, 0xea, 0x65, 0x1a, 0x1a, 0x27, 0xc4, 0x15, 0xa9, 0x45, 0x5a, 0x2d, 0xde, - 0x29, 0x4d, 0xf5, 0x11, 0x4c, 0xd1, 0x1b, 0xec, 0x13, 0xdf, 0x76, 0xd5, 0x5b, 0x78, 0xbb, 0xbd, - 0xc9, 0x03, 0x09, 0xf9, 0x89, 0xaa, 0x90, 0xd9, 0x58, 0xe3, 0xfa, 0xc9, 0x6c, 0xac, 0xc9, 0xf1, - 0xbf, 0x6f, 0x00, 0x52, 0x19, 0x5c, 0xca, 0x16, 0x09, 0x14, 0x21, 0x47, 0x56, 0xca, 0x31, 0x0d, - 0x79, 0xec, 0xfb, 0x9e, 0xcf, 0x1c, 0xa5, 0xc5, 0x3e, 0xa4, 0x34, 0xef, 0x73, 0x61, 0x2c, 0x7c, - 0xec, 0x1d, 0x45, 0x1e, 0x80, 0xb1, 0x35, 0xd2, 0xc2, 0xb7, 0xe1, 0x5a, 0x8c, 0xfc, 0x6a, 0x82, - 0xf6, 0x36, 0x4c, 0x52, 0xae, 0xab, 0x87, 0xb8, 0x73, 0x34, 0xf0, 0x1c, 0x37, 0x25, 0x01, 0xba, - 0x4b, 0x7c, 0x97, 0x08, 0x17, 0x64, 0x8a, 0x6c, 0xce, 0x95, 0xa8, 0xb1, 0xdd, 0xde, 0x94, 0x4b, - 0x7d, 0x1f, 0x6e, 0x24, 0x18, 0x8a, 0x99, 0xfd, 0x2a, 0x94, 0x3b, 0x51, 0x63, 0xc0, 0xcf, 0x84, - 0xb7, 0xe3, 0xe2, 0x26, 0x87, 0xaa, 0x23, 0x24, 0xc6, 0xd7, 0xe1, 0xb5, 0x14, 0xc6, 0x55, 0xa8, - 0x63, 0xc5, 0xbc, 0x0f, 0xd7, 0x29, 0xe7, 0xa7, 0x18, 0x0f, 0x9a, 0x3d, 0xe7, 0xf8, 0x7c, 0xb3, - 0x9c, 0xf2, 0xf9, 0x2a, 0x23, 0xbe, 0xdc, 0x65, 0x25, 0xa1, 0x5b, 0x1c, 0xba, 0xed, 0xf4, 0x71, - 0xdb, 0xdb, 0x1c, 0x2d, 0x2d, 0x09, 0xe4, 0x47, 0xf8, 0x34, 0xe0, 0x07, 0x42, 0xfa, 0x5b, 0x7a, - 0xaf, 0xbf, 0x31, 0xb8, 0x3a, 0x55, 0x3e, 0x5f, 0xf2, 0xd6, 0x98, 0x01, 0x38, 0x20, 0x7b, 0x10, - 0x77, 0x49, 0x07, 0xcb, 0xb6, 0x29, 0x2d, 0x91, 0xc0, 0x24, 0x0a, 0x55, 0x92, 0x02, 0xdf, 0xe6, - 0x1b, 0x87, 0xfe, 0x27, 0x48, 0x9d, 0x94, 0xde, 0x82, 0x32, 0xed, 0xd9, 0x0d, 0xed, 0x70, 0x18, - 0x8c, 0xb2, 0xdc, 0xb2, 0xf9, 0x03, 0x83, 0xef, 0x28, 0xc1, 0xe7, 0x52, 0x73, 0x7e, 0x00, 0x05, - 0x7a, 0xe7, 0x13, 0x77, 0x97, 0x9b, 0x9a, 0x85, 0xcd, 0x24, 0xb2, 0x38, 0xa1, 0x72, 0x4e, 0x32, - 0xa0, 0xf0, 0x8c, 0xd6, 0x02, 0x14, 0x69, 0x73, 0xc2, 0x72, 0xae, 0xdd, 0x67, 0x09, 0xc5, 0x92, - 0x45, 0x7f, 0xd3, 0x23, 0x3e, 0xc6, 0xfe, 0x73, 0x6b, 0x93, 0xdd, 0x29, 0x4a, 0x56, 0xf4, 0x4d, - 0x14, 0xdb, 0xe9, 0x39, 0xd8, 0x0d, 0x69, 0x6f, 0x8e, 0xf6, 0x2a, 0x2d, 0xe8, 0x1e, 0x94, 0x9c, - 0x60, 0x13, 0xdb, 0xbe, 0xcb, 0x93, 0xf6, 0x8a, 0x63, 0x96, 0x3d, 0x72, 0x8d, 0x7d, 0x03, 0x6a, - 0x4c, 0xb2, 0x66, 0xb7, 0xab, 0x9c, 0xdf, 0x23, 0x7c, 0x23, 0x81, 0x1f, 0xe3, 0x9f, 0x39, 0x9f, - 0xff, 0xdf, 0x1a, 0x30, 0xa5, 0x00, 0x5c, 0xca, 0x04, 0xef, 0x41, 0x81, 0x55, 0x54, 0xf8, 0x51, - 0x70, 0x3a, 0x3e, 0x8a, 0xc1, 0x58, 0x9c, 0x06, 0x2d, 0x40, 0x91, 0xfd, 0x12, 0x17, 0x33, 0x3d, - 0xb9, 0x20, 0x92, 0x22, 0x2f, 0xc0, 0x35, 0xde, 0x87, 0xfb, 0x9e, 0x6e, 0xcf, 0xe5, 0xe2, 0x1e, - 0xe2, 0xfb, 0x06, 0x4c, 0xc7, 0x07, 0x5c, 0x6a, 0x96, 0x8a, 0xdc, 0x99, 0x2f, 0x24, 0xf7, 0xaf, - 0x09, 0xb9, 0x9f, 0x0f, 0xba, 0xca, 0x91, 0x33, 0xb9, 0xe2, 0x54, 0xeb, 0x66, 0xe2, 0xd6, 0x95, - 0xbc, 0x7e, 0x14, 0xcd, 0x49, 0x30, 0xbb, 0xd4, 0x9c, 0x3e, 0xb8, 0xd0, 0x9c, 0x94, 0x23, 0x58, - 0x6a, 0x72, 0x1b, 0x62, 0x19, 0x6d, 0x3a, 0x41, 0x14, 0x71, 0xde, 0x85, 0x4a, 0xcf, 0x71, 0xb1, - 0xed, 0xf3, 0xaa, 0x90, 0xa1, 0xae, 0xc7, 0x87, 0x56, 0xac, 0x53, 0xb2, 0xfa, 0x6d, 0x03, 0x90, - 0xca, 0xeb, 0x17, 0x63, 0xad, 0x45, 0xa1, 0xe0, 0x1d, 0xdf, 0xeb, 0x7b, 0xe1, 0x79, 0xcb, 0x6c, - 0xc5, 0xfc, 0x5d, 0x03, 0xae, 0x27, 0x46, 0xfc, 0x22, 0x24, 0x5f, 0x31, 0x6f, 0xc1, 0xd4, 0x1a, - 0x16, 0x67, 0xbc, 0x54, 0x36, 0x60, 0x17, 0x90, 0xda, 0x7b, 0x35, 0xa7, 0x98, 0x5f, 0x82, 0xa9, - 0x67, 0xde, 0x31, 0x71, 0xe4, 0xa4, 0x5b, 0xba, 0x29, 0x96, 0x9e, 0x8a, 0xf4, 0x15, 0x7d, 0x4b, - 0xd7, 0xbb, 0x0b, 0x48, 0x1d, 0x79, 0x15, 0xe2, 0x2c, 0x9b, 0xff, 0x6d, 0x40, 0xa5, 0xd9, 0xb3, - 0xfd, 0xbe, 0x10, 0xe5, 0x23, 0x28, 0xb0, 0x5c, 0x0b, 0x4f, 0x9c, 0xbe, 0x15, 0xe7, 0xa7, 0xd2, - 0xb2, 0x8f, 0x26, 0xcb, 0xcc, 0xf0, 0x51, 0x64, 0x2a, 0xbc, 0x56, 0xbc, 0x96, 0xa8, 0x1d, 0xaf, - 0xa1, 0xf7, 0x21, 0x6f, 0x93, 0x21, 0x34, 0xbc, 0x56, 0x93, 0x09, 0x30, 0xca, 0x8d, 0x5c, 0x89, - 0x2c, 0x46, 0x65, 0x7e, 0x08, 0x65, 0x05, 0x01, 0x15, 0x21, 0xfb, 0xa4, 0xc5, 0xaf, 0x49, 0xcd, - 0xd5, 0xf6, 0xc6, 0x0b, 0x96, 0x14, 0xac, 0x02, 0xac, 0xb5, 0xa2, 0xef, 0x8c, 0xa6, 0x54, 0x67, - 0x73, 0x3e, 0x3c, 0x6e, 0xa9, 0x12, 0x1a, 0xa3, 0x24, 0xcc, 0x5c, 0x44, 0x42, 0x09, 0xf1, 0x5b, - 0x06, 0x4c, 0x70, 0xd5, 0x5c, 0x36, 0x34, 0x53, 0xce, 0x23, 0x42, 0xb3, 0x32, 0x0d, 0x8b, 0x13, - 0x4a, 0x19, 0xfe, 0xc9, 0x80, 0xda, 0x9a, 0xf7, 0xca, 0x3d, 0xf0, 0xed, 0x6e, 0xb4, 0x07, 0x3f, - 0x4e, 0x98, 0x73, 0x21, 0x91, 0xbb, 0x4f, 0xd0, 0xcb, 0x86, 0x84, 0x59, 0xeb, 0x32, 0x97, 0xc2, - 0xe2, 0xbb, 0xf8, 0x34, 0xbf, 0x0a, 0x93, 0x89, 0x41, 0xc4, 0x40, 0x2f, 0x9a, 0x9b, 0x1b, 0x6b, - 0xc4, 0x20, 0x34, 0x83, 0xdb, 0xda, 0x6a, 0x3e, 0xde, 0x6c, 0xf1, 0x3a, 0x6b, 0x73, 0x6b, 0xb5, - 0xb5, 0x29, 0x0d, 0xf5, 0x50, 0xcc, 0xe0, 0xa1, 0xd9, 0x83, 0x29, 0x45, 0xa0, 0xcb, 0x96, 0xbb, - 0xf4, 0xf2, 0x4a, 0xb4, 0x3a, 0x4c, 0xf0, 0x53, 0x4e, 0x72, 0xe3, 0xff, 0x5f, 0x06, 0xaa, 0xa2, - 0xeb, 0xcb, 0x91, 0x02, 0xdd, 0x80, 0x42, 0x77, 0x7f, 0xd7, 0xf9, 0xb6, 0xa8, 0xb4, 0xf2, 0x2f, - 0xd2, 0xde, 0x63, 0x38, 0xec, 0xfd, 0x04, 0xff, 0x42, 0xb7, 0xd8, 0xd3, 0x8a, 0x0d, 0xb7, 0x8b, - 0x4f, 0xe8, 0x61, 0x28, 0x67, 0xc9, 0x06, 0x9a, 0xa6, 0xe4, 0xef, 0x2c, 0xe8, 0x5d, 0x57, 0x79, - 0x77, 0x81, 0x96, 0xa1, 0x46, 0x7e, 0x37, 0x07, 0x83, 0x9e, 0x83, 0xbb, 0x8c, 0x01, 0xb9, 0xe6, - 0xe6, 0xe4, 0x69, 0x27, 0x45, 0x80, 0xee, 0x40, 0x81, 0x5e, 0x01, 0x83, 0xfa, 0x38, 0x89, 0xab, - 0x92, 0x94, 0x37, 0xa3, 0x77, 0xa0, 0xcc, 0x24, 0xde, 0x70, 0x9f, 0x07, 0x98, 0xbe, 0x42, 0x50, - 0xf2, 0x21, 0x6a, 0x5f, 0xfc, 0x9c, 0x05, 0xe7, 0x9f, 0xb3, 0x6e, 0xc1, 0x54, 0x73, 0x18, 0x1e, - 0xb6, 0x5c, 0x12, 0xeb, 0x52, 0xb6, 0xb9, 0x0d, 0x88, 0xf4, 0xae, 0x39, 0x81, 0xb6, 0x9b, 0x0f, - 0xd6, 0x1a, 0xf6, 0xa1, 0xb9, 0x05, 0xd7, 0x48, 0x2f, 0x76, 0x43, 0xa7, 0xa3, 0x9c, 0x2b, 0xc4, - 0xc9, 0xd5, 0x48, 0x9c, 0x5c, 0xed, 0x20, 0x78, 0xe5, 0xf9, 0x5d, 0x6e, 0xbb, 0xe8, 0x5b, 0xa2, - 0xfd, 0x83, 0xc1, 0xa4, 0x79, 0x1e, 0xc4, 0x4e, 0x9d, 0x5f, 0x90, 0x1f, 0xfa, 0x65, 0x28, 0x7a, - 0x03, 0xfa, 0x66, 0x87, 0x27, 0xf3, 0x6e, 0x2c, 0xb0, 0x77, 0x40, 0x0b, 0x9c, 0xf1, 0x36, 0xeb, - 0x55, 0x12, 0x4e, 0x9c, 0x1e, 0x2d, 0x42, 0xf5, 0xd0, 0x0e, 0x0e, 0x71, 0x77, 0x47, 0x30, 0x8f, - 0xa5, 0x3a, 0x1f, 0x5a, 0x89, 0x6e, 0x29, 0xfb, 0x03, 0x29, 0xfa, 0x13, 0x1c, 0x9e, 0x21, 0xba, - 0x9a, 0x1e, 0xbf, 0x2e, 0x86, 0xf0, 0xaa, 0xde, 0x45, 0x46, 0xfd, 0xd0, 0x80, 0xdb, 0x62, 0xd8, - 0xea, 0xa1, 0xed, 0x1e, 0x60, 0x21, 0xcc, 0xcf, 0xab, 0xaf, 0xf4, 0xa4, 0xb3, 0x17, 0x9c, 0xf4, - 0x53, 0xa8, 0x47, 0x93, 0xa6, 0x89, 0x15, 0xaf, 0xa7, 0x4e, 0x62, 0x18, 0xf0, 0x0d, 0x5e, 0xb2, - 0xe8, 0x6f, 0xd2, 0xe6, 0x7b, 0xbd, 0xe8, 0x4e, 0x43, 0x7e, 0x4b, 0x66, 0x9b, 0x70, 0x53, 0x30, - 0xe3, 0x99, 0x8e, 0x38, 0xb7, 0xd4, 0x9c, 0xce, 0xe4, 0xc6, 0xed, 0x41, 0x78, 0x9c, 0xbd, 0x94, - 0xb4, 0x43, 0xe2, 0x26, 0xa4, 0x28, 0x86, 0x0e, 0x65, 0x86, 0xed, 0x00, 0x22, 0xb3, 0x72, 0xfc, - 0x4c, 0xf5, 0x13, 0x96, 0xda, 0x7e, 0xbe, 0x04, 0x48, 0x7f, 0x6a, 0x09, 0x8c, 0x46, 0xc5, 0x30, - 0x13, 0x09, 0x4a, 0xd4, 0xbe, 0x83, 0xfd, 0xbe, 0x13, 0x04, 0x4a, 0x9d, 0x48, 0xa7, 0xae, 0xb7, - 0x20, 0x37, 0xc0, 0x3c, 0x16, 0x97, 0x97, 0x90, 0xd8, 0x13, 0xca, 0x60, 0xda, 0x2f, 0x61, 0xfa, - 0x70, 0x47, 0xc0, 0x30, 0x83, 0x68, 0x71, 0x92, 0x62, 0x8a, 0x4c, 0x76, 0x66, 0x44, 0x26, 0x3b, - 0x1b, 0xcf, 0x64, 0xc7, 0xce, 0x87, 0xaa, 0xa3, 0xba, 0x9a, 0xf3, 0x61, 0x9b, 0x19, 0x20, 0xf2, - 0x6f, 0x57, 0xc3, 0xf5, 0x0f, 0xb8, 0xa3, 0xba, 0xaa, 0xa8, 0x86, 0xe9, 0x9c, 0x45, 0x15, 0x51, - 0x7c, 0x22, 0x13, 0x2a, 0xc4, 0x48, 0x96, 0x9a, 0xe2, 0xcf, 0x59, 0xb1, 0x36, 0xe9, 0x8c, 0x8f, - 0x60, 0x3a, 0xee, 0x8c, 0x2f, 0x25, 0xd4, 0x34, 0xe4, 0x43, 0xef, 0x08, 0x8b, 0x40, 0xcb, 0x3e, - 0x52, 0x6a, 0x8d, 0x1c, 0xf5, 0xd5, 0xa8, 0xf5, 0x9b, 0x92, 0x2b, 0xdd, 0x80, 0x97, 0x9d, 0x01, - 0x59, 0x8e, 0xe2, 0x2a, 0xcb, 0x3e, 0x24, 0xd6, 0x27, 0x70, 0x23, 0xe9, 0x7c, 0xaf, 0x66, 0x12, - 0x7b, 0x6c, 0x73, 0xea, 0xdc, 0xf3, 0xd5, 0x00, 0x7c, 0x26, 0xfd, 0xa4, 0xe2, 0x74, 0xaf, 0x86, - 0xf7, 0xaf, 0x43, 0x43, 0xe7, 0x83, 0xaf, 0x74, 0x2f, 0x46, 0x2e, 0xf9, 0x6a, 0xb8, 0x7e, 0xdf, - 0x90, 0x6c, 0xd5, 0x55, 0xf3, 0xe1, 0x17, 0x61, 0x2b, 0x62, 0xdd, 0xfd, 0x68, 0xf9, 0x2c, 0x46, - 0xde, 0x32, 0xab, 0xf7, 0x96, 0x72, 0x08, 0x25, 0x14, 0xfb, 0x4f, 0xba, 0xfa, 0x2f, 0x73, 0xf5, - 0x72, 0x30, 0x19, 0x77, 0x2e, 0x0b, 0x46, 0xc2, 0x73, 0x04, 0x46, 0x3f, 0x52, 0x5b, 0x45, 0x0d, - 0x52, 0x57, 0x63, 0xba, 0xdf, 0x90, 0x01, 0x26, 0x15, 0xc7, 0xae, 0x06, 0xc1, 0x86, 0xd9, 0xd1, - 0x21, 0xec, 0x4a, 0x20, 0xe6, 0x9b, 0x50, 0x8a, 0x2e, 0xb2, 0xca, 0x43, 0xda, 0x32, 0x14, 0xb7, - 0xb6, 0x77, 0x77, 0x9a, 0xab, 0xe4, 0x9e, 0x36, 0x0d, 0xc5, 0xd5, 0x6d, 0xcb, 0x7a, 0xbe, 0xd3, - 0x26, 0x17, 0xb5, 0xe4, 0xbb, 0x9a, 0xa5, 0x9f, 0x66, 0x21, 0xf3, 0xf4, 0x05, 0xfa, 0x14, 0xf2, - 0xec, 0x5d, 0xd7, 0x19, 0xcf, 0xfb, 0x1a, 0x67, 0x3d, 0x5d, 0x33, 0x5f, 0xfb, 0xde, 0x7f, 0xfe, - 0xf4, 0x0f, 0x33, 0x53, 0x66, 0x65, 0xf1, 0x78, 0x79, 0xf1, 0xe8, 0x78, 0x91, 0x06, 0xd9, 0x47, - 0xc6, 0x3c, 0xfa, 0x1a, 0x64, 0x77, 0x86, 0x21, 0x1a, 0xf9, 0xec, 0xaf, 0x31, 0xfa, 0x35, 0x9b, - 0x79, 0x9d, 0x32, 0x9d, 0x34, 0x81, 0x33, 0x1d, 0x0c, 0x43, 0xc2, 0xf2, 0x5b, 0x50, 0x56, 0xdf, - 0xa2, 0x9d, 0xfb, 0x16, 0xb0, 0x71, 0xfe, 0x3b, 0x37, 0xf3, 0x36, 0x85, 0x7a, 0xcd, 0x44, 0x1c, - 0x8a, 0xbd, 0x96, 0x53, 0x67, 0xd1, 0x3e, 0x71, 0xd1, 0xc8, 0x97, 0x82, 0x8d, 0xd1, 0x4f, 0xdf, - 0x52, 0xb3, 0x08, 0x4f, 0x5c, 0xc2, 0xf2, 0x9b, 0xfc, 0x8d, 0x5b, 0x27, 0x44, 0x77, 0x34, 0x8f, - 0x94, 0xd4, 0xc7, 0x37, 0x8d, 0xd9, 0xd1, 0x04, 0x1c, 0xe4, 0x16, 0x05, 0xb9, 0x61, 0x4e, 0x71, - 0x90, 0x4e, 0x44, 0xf2, 0xc8, 0x98, 0x5f, 0xea, 0x40, 0x9e, 0x96, 0x82, 0xd1, 0x67, 0xe2, 0x47, - 0x43, 0x53, 0x64, 0x1f, 0x61, 0xe8, 0x58, 0x11, 0xd9, 0x9c, 0xa6, 0x40, 0x55, 0xb3, 0x44, 0x80, - 0x68, 0x21, 0xf8, 0x91, 0x31, 0x3f, 0x67, 0xdc, 0x37, 0x96, 0xfe, 0x3a, 0x0f, 0x79, 0x5a, 0x72, - 0x40, 0x47, 0x00, 0xb2, 0xe4, 0x99, 0x9c, 0x5d, 0xaa, 0x9a, 0x9a, 0x9c, 0x5d, 0xba, 0x5a, 0x6a, - 0x36, 0x28, 0xe8, 0xb4, 0x39, 0x49, 0x40, 0x69, 0x25, 0x63, 0x91, 0x16, 0x6e, 0x88, 0x1e, 0x7f, - 0x68, 0xf0, 0xda, 0x0b, 0xdb, 0x66, 0x48, 0xc7, 0x2d, 0x56, 0xee, 0x4c, 0x2e, 0x07, 0x4d, 0x85, - 0xd3, 0x7c, 0x48, 0x01, 0x17, 0xcd, 0x9a, 0x04, 0xf4, 0x29, 0xc5, 0x23, 0x63, 0xfe, 0xb3, 0xba, - 0x79, 0x8d, 0x6b, 0x39, 0xd1, 0x83, 0xbe, 0x03, 0xd5, 0x78, 0x61, 0x0e, 0xdd, 0xd5, 0x60, 0x25, - 0x0b, 0x7d, 0x8d, 0x37, 0xcf, 0x26, 0xe2, 0x32, 0xcd, 0x50, 0x99, 0x38, 0x38, 0x43, 0x3e, 0xc2, - 0x78, 0x60, 0x13, 0x22, 0x6e, 0x03, 0xf4, 0xa7, 0x06, 0xaf, 0xad, 0xca, 0xba, 0x1a, 0xd2, 0x71, - 0x4f, 0x95, 0xef, 0x1a, 0xf7, 0xce, 0xa1, 0xe2, 0x42, 0x7c, 0x48, 0x85, 0xf8, 0xc0, 0x9c, 0x96, - 0x42, 0x84, 0x4e, 0x1f, 0x87, 0x1e, 0x97, 0xe2, 0xb3, 0x5b, 0xe6, 0x6b, 0x31, 0xe5, 0xc4, 0x7a, - 0xa5, 0xb1, 0x58, 0xfd, 0x4b, 0x6b, 0xac, 0x58, 0x89, 0x4d, 0x6b, 0xac, 0x78, 0xf1, 0x4c, 0x67, - 0x2c, 0x5e, 0xed, 0xd2, 0x18, 0x2b, 0xea, 0x59, 0xfa, 0xdf, 0x1c, 0x14, 0x57, 0xd9, 0xdf, 0xca, - 0x20, 0x0f, 0x4a, 0x51, 0x45, 0x08, 0xcd, 0xe8, 0x92, 0xce, 0xf2, 0x2a, 0xd7, 0xb8, 0x33, 0xb2, - 0x9f, 0x0b, 0xf4, 0x06, 0x15, 0xe8, 0x75, 0xf3, 0x06, 0x41, 0xe6, 0x7f, 0x8e, 0xb3, 0xc8, 0x52, - 0x93, 0x8b, 0x76, 0xb7, 0x4b, 0x14, 0xf1, 0x9b, 0x50, 0x51, 0xeb, 0x33, 0xe8, 0x0d, 0x6d, 0xa2, - 0x5b, 0x2d, 0xf6, 0x34, 0xcc, 0xb3, 0x48, 0x38, 0xf2, 0x9b, 0x14, 0x79, 0xc6, 0xbc, 0xa9, 0x41, - 0xf6, 0x29, 0x69, 0x0c, 0x9c, 0x15, 0x52, 0xf4, 0xe0, 0xb1, 0x8a, 0x8d, 0x1e, 0x3c, 0x5e, 0x87, - 0x39, 0x13, 0x7c, 0x48, 0x49, 0x09, 0x78, 0x00, 0x20, 0x2b, 0x1d, 0x48, 0xab, 0x4b, 0xe5, 0xc2, - 0x9a, 0x74, 0x0e, 0xe9, 0x22, 0x89, 0x69, 0x52, 0x58, 0xbe, 0xee, 0x12, 0xb0, 0x3d, 0x27, 0x08, - 0xd9, 0xc6, 0x9c, 0x88, 0xd5, 0x29, 0x90, 0x76, 0x3e, 0xf1, 0xb2, 0x47, 0xe3, 0xee, 0x99, 0x34, - 0x1c, 0xfd, 0x1e, 0x45, 0xbf, 0x63, 0x36, 0x34, 0xe8, 0x03, 0x46, 0x4b, 0x16, 0xdb, 0xff, 0x17, - 0xa0, 0xfc, 0xcc, 0x76, 0xdc, 0x10, 0xbb, 0xb6, 0xdb, 0xc1, 0x68, 0x1f, 0xf2, 0x34, 0x76, 0x27, - 0x1d, 0xb1, 0x9a, 0x96, 0x4f, 0x3a, 0xe2, 0x58, 0x5e, 0xda, 0x9c, 0xa5, 0xc0, 0x0d, 0xf3, 0x3a, - 0x01, 0xee, 0x4b, 0xd6, 0x8b, 0x2c, 0xa3, 0x6d, 0xcc, 0xa3, 0x97, 0x50, 0xe0, 0xf5, 0xe8, 0x04, - 0xa3, 0x58, 0x52, 0xad, 0x71, 0x4b, 0xdf, 0xa9, 0x5b, 0xcb, 0x2a, 0x4c, 0x40, 0xe9, 0x08, 0xce, - 0x31, 0x80, 0x2c, 0xaf, 0x24, 0x2d, 0x9a, 0x2a, 0xcb, 0x34, 0x66, 0x47, 0x13, 0xe8, 0x74, 0xaa, - 0x62, 0x76, 0x23, 0x5a, 0x82, 0xfb, 0x0d, 0xc8, 0xad, 0xdb, 0xc1, 0x21, 0x4a, 0xc4, 0x5e, 0xe5, - 0x41, 0x68, 0xa3, 0xa1, 0xeb, 0xe2, 0x28, 0x77, 0x28, 0xca, 0x4d, 0xe6, 0xca, 0x54, 0x14, 0xfa, - 0x40, 0xd2, 0x98, 0x47, 0x5d, 0x28, 0xb0, 0xd7, 0xa0, 0x49, 0xfd, 0xc5, 0x9e, 0x96, 0x26, 0xf5, - 0x17, 0x7f, 0x40, 0x7a, 0x3e, 0xca, 0x00, 0xc6, 0xc5, 0x1b, 0x4b, 0x94, 0x78, 0x99, 0x92, 0x78, - 0x98, 0xd9, 0x98, 0x19, 0xd5, 0xcd, 0xb1, 0xee, 0x52, 0xac, 0xdb, 0x66, 0x3d, 0x65, 0x2b, 0x4e, - 0xf9, 0xc8, 0x98, 0xbf, 0x6f, 0xa0, 0xef, 0x00, 0xc8, 0xfa, 0x53, 0x6a, 0x07, 0x26, 0x6b, 0x5a, - 0xa9, 0x1d, 0x98, 0x2a, 0x5d, 0x99, 0x0b, 0x14, 0x77, 0xce, 0xbc, 0x9b, 0xc4, 0x0d, 0x7d, 0xdb, - 0x0d, 0x5e, 0x62, 0xff, 0x7d, 0x96, 0xfc, 0x0e, 0x0e, 0x9d, 0x01, 0x99, 0xb2, 0x0f, 0xa5, 0xa8, - 0x3c, 0x90, 0xf4, 0xb6, 0xc9, 0x42, 0x46, 0xd2, 0xdb, 0xa6, 0xea, 0x0a, 0x71, 0xb7, 0x13, 0x5b, - 0x2d, 0x82, 0x94, 0x6c, 0xc0, 0xbf, 0xa8, 0x41, 0x8e, 0x1c, 0xc8, 0xc9, 0xe1, 0x44, 0x26, 0x7b, - 0x92, 0xb3, 0x4f, 0xe5, 0xab, 0x93, 0xb3, 0x4f, 0xe7, 0x89, 0xe2, 0x87, 0x13, 0x72, 0x59, 0x5b, - 0x64, 0x59, 0x14, 0x32, 0x53, 0x0f, 0xca, 0x4a, 0x12, 0x08, 0x69, 0x98, 0xc5, 0xf3, 0xdf, 0xc9, - 0x70, 0xa7, 0xc9, 0x20, 0x99, 0xaf, 0x53, 0xbc, 0xeb, 0x2c, 0xdc, 0x51, 0xbc, 0x2e, 0xa3, 0x20, - 0x80, 0x7c, 0x76, 0x7c, 0xdf, 0x6b, 0x66, 0x17, 0xdf, 0xfb, 0xb3, 0xa3, 0x09, 0x46, 0xce, 0x4e, - 0x6e, 0xfc, 0x57, 0x50, 0x51, 0x13, 0x3f, 0x48, 0x23, 0x7c, 0x22, 0x43, 0x9f, 0x8c, 0x23, 0xba, - 0xbc, 0x51, 0xdc, 0xb3, 0x51, 0x48, 0x5b, 0x21, 0x23, 0xc0, 0x3d, 0x28, 0xf2, 0x04, 0x90, 0x4e, - 0xa5, 0xf1, 0x24, 0xbe, 0x4e, 0xa5, 0x89, 0xec, 0x51, 0xfc, 0xf4, 0x4c, 0x11, 0xc9, 0x45, 0x54, - 0xc4, 0x6a, 0x8e, 0xf6, 0x04, 0x87, 0xa3, 0xd0, 0x64, 0xd2, 0x76, 0x14, 0x9a, 0x92, 0x1f, 0x18, - 0x85, 0x76, 0x80, 0x43, 0xee, 0x0f, 0xc4, 0xe5, 0x1a, 0x8d, 0x60, 0xa6, 0xc6, 0x47, 0xf3, 0x2c, - 0x12, 0xdd, 0xe5, 0x46, 0x02, 0x8a, 0xe0, 0x78, 0x02, 0x20, 0x93, 0x51, 0xc9, 0x13, 0xab, 0xb6, - 0x4e, 0x90, 0x3c, 0xb1, 0xea, 0xf3, 0x59, 0x71, 0xdf, 0x27, 0x71, 0xd9, 0xdd, 0x8a, 0x20, 0xff, - 0xd8, 0x00, 0x94, 0x4e, 0x57, 0xa1, 0x77, 0xf5, 0xdc, 0xb5, 0x35, 0x87, 0xc6, 0x7b, 0x17, 0x23, - 0xd6, 0x85, 0x33, 0x29, 0x52, 0x87, 0x52, 0x0f, 0x5e, 0x11, 0xa1, 0xbe, 0x6b, 0xc0, 0x44, 0x2c, - 0xc5, 0x85, 0xde, 0x1a, 0x61, 0xd3, 0x44, 0xe1, 0xa1, 0xf1, 0xf6, 0xb9, 0x74, 0xba, 0xa3, 0xbc, - 0xb2, 0x02, 0xc4, 0x9d, 0xe6, 0x77, 0x0c, 0xa8, 0xc6, 0x33, 0x61, 0x68, 0x04, 0xef, 0x54, 0xbd, - 0xa2, 0x31, 0x77, 0x3e, 0xe1, 0xd9, 0xe6, 0x91, 0xd7, 0x99, 0x1e, 0x14, 0x79, 0xca, 0x4c, 0xb7, - 0xf0, 0xe3, 0x05, 0x0e, 0xdd, 0xc2, 0x4f, 0xe4, 0xdb, 0x34, 0x0b, 0xdf, 0xf7, 0x7a, 0x58, 0xd9, - 0x66, 0x3c, 0x93, 0x36, 0x0a, 0xed, 0xec, 0x6d, 0x96, 0x48, 0xc3, 0x8d, 0x42, 0x93, 0xdb, 0x4c, - 0x24, 0xcc, 0xd0, 0x08, 0x66, 0xe7, 0x6c, 0xb3, 0x64, 0xbe, 0x4d, 0xb3, 0xcd, 0x28, 0xa0, 0xb2, - 0xcd, 0x64, 0x22, 0x4b, 0xb7, 0xcd, 0x52, 0xb5, 0x18, 0xdd, 0x36, 0x4b, 0xe7, 0xc2, 0x34, 0x76, - 0xa4, 0xb8, 0xb1, 0x6d, 0x76, 0x4d, 0x93, 0xea, 0x42, 0xef, 0x8d, 0x50, 0xa2, 0xb6, 0xb2, 0xd3, - 0x78, 0xff, 0x82, 0xd4, 0x23, 0xd7, 0x38, 0x53, 0xbf, 0x58, 0xe3, 0x7f, 0x64, 0xc0, 0xb4, 0x2e, - 0x3b, 0x86, 0x46, 0xe0, 0x8c, 0x28, 0x04, 0x35, 0x16, 0x2e, 0x4a, 0x7e, 0xb6, 0xb6, 0xa2, 0x55, - 0xff, 0xb8, 0xf6, 0xaf, 0x9f, 0xcf, 0x18, 0xff, 0xf1, 0xf9, 0x8c, 0xf1, 0x5f, 0x9f, 0xcf, 0x18, - 0x3f, 0xf9, 0x9f, 0x99, 0xb1, 0xfd, 0x02, 0xfd, 0x1f, 0x30, 0x2c, 0xff, 0x2c, 0x00, 0x00, 0xff, - 0xff, 0x0d, 0x96, 0x9e, 0x56, 0x27, 0x42, 0x00, 0x00, + // 4411 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xc4, 0x5c, 0x4f, 0x6f, 0x1c, 0xc9, + 0x75, 0x67, 0xcf, 0x5f, 0xce, 0x9b, 0xe1, 0x70, 0x58, 0xa2, 0xb4, 0xa3, 0x59, 0x89, 0xe2, 0xb6, + 0x56, 0xbb, 0x5a, 0xed, 0x2e, 0x29, 0x91, 0x92, 0x37, 0x51, 0xb0, 0x1b, 0x8f, 0xc8, 0x59, 0x89, + 0x11, 0x45, 0xd2, 0xcd, 0x91, 0xd6, 0xbb, 0x01, 0xcc, 0x34, 0x67, 0x4a, 0x64, 0x9b, 0x33, 0xdd, + 0xe3, 0xee, 0x1e, 0x8a, 0x74, 0x0e, 0x76, 0x9c, 0x38, 0x86, 0x13, 0xc0, 0x40, 0x1c, 0x20, 0x30, + 0x82, 0xe4, 0x12, 0x04, 0x48, 0x0e, 0x4e, 0x90, 0x1c, 0x72, 0x08, 0x72, 0xc8, 0x21, 0x39, 0x24, + 0x87, 0x00, 0x01, 0xf2, 0x05, 0x92, 0x8d, 0x4f, 0xf9, 0x10, 0x81, 0x51, 0xff, 0xba, 0xaa, 0xbb, + 0xab, 0x49, 0xae, 0xc9, 0x85, 0x2f, 0xab, 0xe9, 0xaa, 0x57, 0xef, 0xf7, 0xea, 0xbd, 0xaa, 0xf7, + 0xaa, 0xde, 0x2b, 0x2e, 0x54, 0xfc, 0x51, 0x6f, 0x61, 0xe4, 0x7b, 0xa1, 0x87, 0x6a, 0x38, 0xec, + 0xf5, 0x03, 0xec, 0x1f, 0x62, 0x7f, 0xb4, 0xdb, 0x9a, 0xdd, 0xf3, 0xf6, 0x3c, 0xda, 0xb1, 0x48, + 0x7e, 0x31, 0x9a, 0x56, 0x93, 0xd0, 0x2c, 0xda, 0x23, 0x67, 0x71, 0x78, 0xd8, 0xeb, 0x8d, 0x76, + 0x17, 0x0f, 0x0e, 0x79, 0x4f, 0x2b, 0xea, 0xb1, 0xc7, 0xe1, 0xfe, 0x68, 0x97, 0xfe, 0xc3, 0xfb, + 0xe6, 0xa3, 0xbe, 0x43, 0xec, 0x07, 0x8e, 0xe7, 0x8e, 0x76, 0xc5, 0x2f, 0x4e, 0x71, 0x6d, 0xcf, + 0xf3, 0xf6, 0x06, 0x98, 0x8d, 0x77, 0x5d, 0x2f, 0xb4, 0x43, 0xc7, 0x73, 0x03, 0xd6, 0x6b, 0xfe, + 0xc8, 0x80, 0xba, 0x85, 0x83, 0x91, 0xe7, 0x06, 0xf8, 0x09, 0xb6, 0xfb, 0xd8, 0x47, 0xd7, 0x01, + 0x7a, 0x83, 0x71, 0x10, 0x62, 0x7f, 0xc7, 0xe9, 0x37, 0x8d, 0x79, 0xe3, 0x76, 0xc1, 0xaa, 0xf0, + 0x96, 0xb5, 0x3e, 0x7a, 0x1d, 0x2a, 0x43, 0x3c, 0xdc, 0x65, 0xbd, 0x39, 0xda, 0x3b, 0xc9, 0x1a, + 0xd6, 0xfa, 0xa8, 0x05, 0x93, 0x3e, 0x3e, 0x74, 0x08, 0x7c, 0x33, 0x3f, 0x6f, 0xdc, 0xce, 0x5b, + 0xd1, 0x37, 0x19, 0xe8, 0xdb, 0x2f, 0xc3, 0x9d, 0x10, 0xfb, 0xc3, 0x66, 0x81, 0x0d, 0x24, 0x0d, + 0x5d, 0xec, 0x0f, 0x1f, 0x96, 0xbf, 0xf7, 0x0f, 0xcd, 0xfc, 0xf2, 0xc2, 0x5d, 0xf3, 0x5f, 0x8a, + 0x50, 0xb3, 0x6c, 0x77, 0x0f, 0x5b, 0xf8, 0x5b, 0x63, 0x1c, 0x84, 0xa8, 0x01, 0xf9, 0x03, 0x7c, + 0x4c, 0xe5, 0xa8, 0x59, 0xe4, 0x27, 0x63, 0xe4, 0xee, 0xe1, 0x1d, 0xec, 0x32, 0x09, 0x6a, 0x84, + 0x91, 0xbb, 0x87, 0x3b, 0x6e, 0x1f, 0xcd, 0x42, 0x71, 0xe0, 0x0c, 0x9d, 0x90, 0xc3, 0xb3, 0x8f, + 0x98, 0x5c, 0x85, 0x84, 0x5c, 0x2b, 0x00, 0x81, 0xe7, 0x87, 0x3b, 0x9e, 0xdf, 0xc7, 0x7e, 0xb3, + 0x38, 0x6f, 0xdc, 0xae, 0x2f, 0xbd, 0xb9, 0xa0, 0x5a, 0x6c, 0x41, 0x15, 0x68, 0x61, 0xdb, 0xf3, + 0xc3, 0x4d, 0x42, 0x6b, 0x55, 0x02, 0xf1, 0x13, 0x7d, 0x0c, 0x55, 0xca, 0x24, 0xb4, 0xfd, 0x3d, + 0x1c, 0x36, 0x4b, 0x94, 0xcb, 0xad, 0x53, 0xb8, 0x74, 0x29, 0xb1, 0x45, 0xe1, 0xd9, 0x6f, 0x64, + 0x42, 0x2d, 0xc0, 0xbe, 0x63, 0x0f, 0x9c, 0x6f, 0xdb, 0xbb, 0x03, 0xdc, 0x2c, 0xcf, 0x1b, 0xb7, + 0x27, 0xad, 0x58, 0x1b, 0x99, 0xff, 0x01, 0x3e, 0x0e, 0x76, 0x3c, 0x77, 0x70, 0xdc, 0x9c, 0xa4, + 0x04, 0x93, 0xa4, 0x61, 0xd3, 0x1d, 0x1c, 0x53, 0xeb, 0x79, 0x63, 0x37, 0x64, 0xbd, 0x15, 0xda, + 0x5b, 0xa1, 0x2d, 0xb4, 0xfb, 0x1e, 0x34, 0x86, 0x8e, 0xbb, 0x33, 0xf4, 0xfa, 0x3b, 0x91, 0x42, + 0x80, 0x28, 0xe4, 0x51, 0xf9, 0x0f, 0xa8, 0x05, 0xee, 0x59, 0xf5, 0xa1, 0xe3, 0x3e, 0xf3, 0xfa, + 0x96, 0xd0, 0x0f, 0x19, 0x62, 0x1f, 0xc5, 0x87, 0x54, 0x93, 0x43, 0xec, 0x23, 0x75, 0xc8, 0x07, + 0x70, 0x89, 0xa0, 0xf4, 0x7c, 0x6c, 0x87, 0x58, 0x8e, 0xaa, 0xc5, 0x47, 0xcd, 0x0c, 0x1d, 0x77, + 0x85, 0x92, 0xc4, 0x06, 0xda, 0x47, 0xa9, 0x81, 0x53, 0xc9, 0x81, 0xf6, 0x51, 0x7c, 0xa0, 0xf9, + 0x01, 0x54, 0x22, 0xbb, 0xa0, 0x49, 0x28, 0x6c, 0x6c, 0x6e, 0x74, 0x1a, 0x13, 0x08, 0xa0, 0xd4, + 0xde, 0x5e, 0xe9, 0x6c, 0xac, 0x36, 0x0c, 0x54, 0x85, 0xf2, 0x6a, 0x87, 0x7d, 0xe4, 0x5a, 0xe5, + 0x1f, 0xf3, 0xf5, 0xf6, 0x14, 0x40, 0x9a, 0x02, 0x95, 0x21, 0xff, 0xb4, 0xf3, 0x69, 0x63, 0x82, + 0x10, 0xbf, 0xe8, 0x58, 0xdb, 0x6b, 0x9b, 0x1b, 0x0d, 0x83, 0x70, 0x59, 0xb1, 0x3a, 0xed, 0x6e, + 0xa7, 0x91, 0x23, 0x14, 0xcf, 0x36, 0x57, 0x1b, 0x79, 0x54, 0x81, 0xe2, 0x8b, 0xf6, 0xfa, 0xf3, + 0x4e, 0xa3, 0x10, 0x31, 0x93, 0xab, 0xf8, 0xcf, 0x0c, 0x98, 0xe2, 0xe6, 0x66, 0x7b, 0x0b, 0xdd, + 0x87, 0xd2, 0x3e, 0xdd, 0x5f, 0x74, 0x25, 0x57, 0x97, 0xae, 0x25, 0xd6, 0x46, 0x6c, 0x0f, 0x5a, + 0x9c, 0x16, 0x99, 0x90, 0x3f, 0x38, 0x0c, 0x9a, 0xb9, 0xf9, 0xfc, 0xed, 0xea, 0x52, 0x63, 0x81, + 0x79, 0x86, 0x85, 0xa7, 0xf8, 0xf8, 0x85, 0x3d, 0x18, 0x63, 0x8b, 0x74, 0x22, 0x04, 0x85, 0xa1, + 0xe7, 0x63, 0xba, 0xe0, 0x27, 0x2d, 0xfa, 0x9b, 0xec, 0x02, 0x6a, 0x73, 0xbe, 0xd8, 0xd9, 0x87, + 0x14, 0xef, 0x3f, 0x0c, 0x80, 0xad, 0x71, 0x98, 0xbd, 0xc5, 0x66, 0xa1, 0x78, 0x48, 0x10, 0xf8, + 0xf6, 0x62, 0x1f, 0x74, 0x6f, 0x61, 0x3b, 0xc0, 0xd1, 0xde, 0x22, 0x1f, 0x68, 0x1e, 0xca, 0x23, + 0x1f, 0x1f, 0xee, 0x1c, 0x1c, 0x52, 0xb4, 0x49, 0x69, 0xa7, 0x12, 0x69, 0x7f, 0x7a, 0x88, 0xee, + 0x40, 0xcd, 0xd9, 0x73, 0x3d, 0x1f, 0xef, 0x30, 0xa6, 0x45, 0x95, 0x6c, 0xc9, 0xaa, 0xb2, 0x4e, + 0x3a, 0x25, 0x85, 0x96, 0x41, 0x95, 0xb4, 0xb4, 0xeb, 0xa4, 0x4f, 0xce, 0xe7, 0xbb, 0x06, 0x54, + 0xe9, 0x7c, 0xce, 0xa5, 0xec, 0x25, 0x39, 0x91, 0x1c, 0x1d, 0x96, 0x52, 0x78, 0x6a, 0x6a, 0x52, + 0x04, 0x17, 0xd0, 0x2a, 0x1e, 0xe0, 0x10, 0x9f, 0xc7, 0x79, 0x29, 0xaa, 0xcc, 0x6b, 0x55, 0x29, + 0xf1, 0xfe, 0xd2, 0x80, 0x4b, 0x31, 0xc0, 0x73, 0x4d, 0xbd, 0x09, 0xe5, 0x3e, 0x65, 0xc6, 0x64, + 0xca, 0x5b, 0xe2, 0x13, 0xdd, 0x87, 0x49, 0x2e, 0x52, 0xd0, 0xcc, 0xeb, 0x97, 0xa1, 0x94, 0xb2, + 0xcc, 0xa4, 0x0c, 0xa4, 0x98, 0xff, 0x94, 0x83, 0x0a, 0x57, 0xc6, 0xe6, 0x08, 0xb5, 0x61, 0xca, + 0x67, 0x1f, 0x3b, 0x74, 0xce, 0x5c, 0xc6, 0x56, 0xb6, 0x9f, 0x7c, 0x32, 0x61, 0xd5, 0xf8, 0x10, + 0xda, 0x8c, 0x7e, 0x0d, 0xaa, 0x82, 0xc5, 0x68, 0x1c, 0x72, 0x43, 0x35, 0xe3, 0x0c, 0xe4, 0xd2, + 0x7e, 0x32, 0x61, 0x01, 0x27, 0xdf, 0x1a, 0x87, 0xa8, 0x0b, 0xb3, 0x62, 0x30, 0x9b, 0x1f, 0x17, + 0x23, 0x4f, 0xb9, 0xcc, 0xc7, 0xb9, 0xa4, 0xcd, 0xf9, 0x64, 0xc2, 0x42, 0x7c, 0xbc, 0xd2, 0x89, + 0x56, 0xa5, 0x48, 0xe1, 0x11, 0x8b, 0x2f, 0x29, 0x91, 0xba, 0x47, 0x2e, 0x67, 0x22, 0xb4, 0xb5, + 0xac, 0xc8, 0xd6, 0x3d, 0x72, 0x23, 0x95, 0x3d, 0xaa, 0x40, 0x99, 0x37, 0x9b, 0xff, 0x9e, 0x03, + 0x10, 0x16, 0xdb, 0x1c, 0xa1, 0x55, 0xa8, 0xfb, 0xfc, 0x2b, 0xa6, 0xbf, 0xd7, 0xb5, 0xfa, 0xe3, + 0x86, 0x9e, 0xb0, 0xa6, 0xc4, 0x20, 0x26, 0xee, 0x47, 0x50, 0x8b, 0xb8, 0x48, 0x15, 0x5e, 0xd5, + 0xa8, 0x30, 0xe2, 0x50, 0x15, 0x03, 0x88, 0x12, 0x3f, 0x81, 0xcb, 0xd1, 0x78, 0x8d, 0x16, 0xdf, + 0x38, 0x41, 0x8b, 0x11, 0xc3, 0x4b, 0x82, 0x83, 0xaa, 0xc7, 0xc7, 0x8a, 0x60, 0x52, 0x91, 0x57, + 0x35, 0x8a, 0x64, 0x44, 0xaa, 0x26, 0x23, 0x09, 0x63, 0xaa, 0x04, 0x12, 0xf6, 0x59, 0xbb, 0xf9, + 0xd7, 0x05, 0x28, 0xaf, 0x78, 0xc3, 0x91, 0xed, 0x93, 0x45, 0x54, 0xf2, 0x71, 0x30, 0x1e, 0x84, + 0x54, 0x81, 0xf5, 0xa5, 0x9b, 0x71, 0x0c, 0x4e, 0x26, 0xfe, 0xb5, 0x28, 0xa9, 0xc5, 0x87, 0x90, + 0xc1, 0x3c, 0xca, 0xe7, 0xce, 0x30, 0x98, 0xc7, 0x78, 0x3e, 0x44, 0x38, 0x84, 0xbc, 0x74, 0x08, + 0x2d, 0x28, 0xf3, 0x03, 0x1b, 0x73, 0xd6, 0x4f, 0x26, 0x2c, 0xd1, 0x80, 0xde, 0x81, 0xe9, 0x64, + 0x28, 0x2c, 0x72, 0x9a, 0x7a, 0x2f, 0x1e, 0x39, 0x6f, 0x42, 0x2d, 0x16, 0xa1, 0x4b, 0x9c, 0xae, + 0x3a, 0x54, 0xe2, 0xf2, 0x15, 0xe1, 0xd6, 0xc9, 0xb1, 0xa2, 0xf6, 0x64, 0x42, 0x38, 0xf6, 0x1b, + 0xc2, 0xb1, 0x4f, 0xaa, 0x81, 0x96, 0xe8, 0x95, 0xfb, 0xf8, 0x37, 0x55, 0xaf, 0xf5, 0x55, 0x32, + 0x38, 0x22, 0x92, 0xee, 0xcb, 0xb4, 0x60, 0x2a, 0xa6, 0x32, 0x12, 0x23, 0x3b, 0x5f, 0x7b, 0xde, + 0x5e, 0x67, 0x01, 0xf5, 0x31, 0x8d, 0xa1, 0x56, 0xc3, 0x20, 0x01, 0x7a, 0xbd, 0xb3, 0xbd, 0xdd, + 0xc8, 0xa1, 0x2b, 0x50, 0xd9, 0xd8, 0xec, 0xee, 0x30, 0xaa, 0x7c, 0xab, 0xfc, 0xa7, 0xcc, 0x93, + 0xc8, 0xf8, 0xfc, 0x69, 0xc4, 0x93, 0x87, 0x68, 0x25, 0x32, 0x4f, 0x28, 0x91, 0xd9, 0x10, 0x91, + 0x39, 0x27, 0x23, 0x73, 0x1e, 0x21, 0x28, 0xae, 0x77, 0xda, 0xdb, 0x34, 0x48, 0x33, 0xd6, 0xcb, + 0xe9, 0x68, 0xfd, 0xa8, 0x0e, 0x35, 0x66, 0x9e, 0x9d, 0xb1, 0x4b, 0x0e, 0x13, 0x3f, 0x35, 0x00, + 0xe4, 0x86, 0x45, 0x8b, 0x50, 0xee, 0x31, 0x11, 0x9a, 0x06, 0xf5, 0x80, 0x97, 0xb5, 0x16, 0xb7, + 0x04, 0x15, 0xba, 0x07, 0xe5, 0x60, 0xdc, 0xeb, 0xe1, 0x40, 0x44, 0xee, 0xd7, 0x92, 0x4e, 0x98, + 0x3b, 0x44, 0x4b, 0xd0, 0x91, 0x21, 0x2f, 0x6d, 0x67, 0x30, 0xa6, 0x71, 0xfc, 0xe4, 0x21, 0x9c, + 0x4e, 0xfa, 0xd8, 0xbf, 0x30, 0xa0, 0xaa, 0x6c, 0x8b, 0x5f, 0x30, 0x04, 0x5c, 0x83, 0x0a, 0x15, + 0x06, 0xf7, 0x79, 0x10, 0x98, 0xb4, 0x64, 0x03, 0xfa, 0x0a, 0x54, 0xc4, 0x4e, 0x12, 0x71, 0xa0, + 0xa9, 0x67, 0xbb, 0x39, 0xb2, 0x24, 0xa9, 0x14, 0xb2, 0x0b, 0x33, 0x54, 0x4f, 0x3d, 0x72, 0xfb, + 0x10, 0x9a, 0x55, 0x8f, 0xe5, 0x46, 0xe2, 0x58, 0xde, 0x82, 0xc9, 0xd1, 0xfe, 0x71, 0xe0, 0xf4, + 0xec, 0x01, 0x17, 0x27, 0xfa, 0x96, 0x5c, 0xb7, 0x01, 0xa9, 0x5c, 0xcf, 0xa3, 0x00, 0xc9, 0xf4, + 0x0a, 0x54, 0x9f, 0xd8, 0xc1, 0x3e, 0x17, 0x52, 0xb6, 0xdf, 0x87, 0x29, 0xd2, 0xfe, 0xf4, 0xc5, + 0x19, 0xc4, 0x17, 0xa3, 0x96, 0xe9, 0x0d, 0x4b, 0x0c, 0x3b, 0x97, 0x81, 0x10, 0x14, 0xf6, 0xed, + 0x60, 0x9f, 0x2a, 0x63, 0xca, 0xa2, 0xbf, 0xd1, 0x3b, 0xd0, 0xe8, 0xb1, 0xf9, 0xef, 0x24, 0xee, + 0x5d, 0xd3, 0xbc, 0xdd, 0x4a, 0x09, 0x64, 0x43, 0x8d, 0x4d, 0xef, 0xa2, 0xa5, 0x91, 0x9a, 0x6a, + 0xc1, 0xf4, 0xb6, 0x6b, 0x8f, 0x82, 0x7d, 0x2f, 0x4c, 0x68, 0x71, 0xd9, 0xfc, 0x7b, 0x03, 0x1a, + 0xb2, 0xf3, 0x5c, 0x32, 0xbc, 0x0d, 0xd3, 0x3e, 0x1e, 0xda, 0x8e, 0xeb, 0xb8, 0x7b, 0x3b, 0xbb, + 0xc7, 0x21, 0x0e, 0xf8, 0x85, 0xb4, 0x1e, 0x35, 0x3f, 0x22, 0xad, 0x44, 0xd8, 0xdd, 0x81, 0xb7, + 0xcb, 0xdd, 0x2e, 0xfd, 0x8d, 0xde, 0x88, 0xfb, 0xdd, 0x8a, 0x70, 0x68, 0x5f, 0x89, 0xdc, 0xaf, + 0x94, 0xf9, 0x27, 0x39, 0xa8, 0x7d, 0x62, 0x87, 0x3d, 0xb1, 0x26, 0xd0, 0x1a, 0xd4, 0x23, 0xc7, + 0x4c, 0x5b, 0xb8, 0xdc, 0x89, 0x23, 0x04, 0x1d, 0x23, 0x6e, 0x2a, 0xe2, 0x08, 0x31, 0xd5, 0x53, + 0x1b, 0x28, 0x2b, 0xdb, 0xed, 0xe1, 0x41, 0xc4, 0x2a, 0x97, 0xcd, 0x8a, 0x12, 0xaa, 0xac, 0xd4, + 0x06, 0xf4, 0x75, 0x68, 0x8c, 0x7c, 0x6f, 0xcf, 0xc7, 0x41, 0x10, 0x31, 0x63, 0x41, 0xd9, 0xd4, + 0x30, 0xdb, 0xe2, 0xa4, 0x89, 0x73, 0xc9, 0xfd, 0x27, 0x13, 0xd6, 0xf4, 0x28, 0xde, 0x27, 0x5d, + 0xe5, 0xb4, 0x3c, 0xc1, 0x31, 0x5f, 0xf9, 0x83, 0x3c, 0xa0, 0xf4, 0x34, 0xbf, 0xe8, 0xc1, 0xf7, + 0x16, 0xd4, 0x83, 0xd0, 0xf6, 0x53, 0xab, 0x78, 0x8a, 0xb6, 0x46, 0xf1, 0xeb, 0x6d, 0x88, 0x24, + 0xdb, 0x71, 0xbd, 0xd0, 0x79, 0x79, 0xcc, 0xae, 0x1c, 0x56, 0x5d, 0x34, 0x6f, 0xd0, 0x56, 0xb4, + 0x01, 0xe5, 0x97, 0xce, 0x20, 0xc4, 0x7e, 0xd0, 0x2c, 0xce, 0xe7, 0x6f, 0xd7, 0x97, 0xde, 0x3d, + 0xcd, 0x30, 0x0b, 0x1f, 0x53, 0xfa, 0xee, 0xf1, 0x48, 0x3d, 0xcf, 0x72, 0x26, 0xea, 0xc1, 0xbc, + 0xa4, 0xbf, 0xe3, 0x98, 0x30, 0xf9, 0x8a, 0x30, 0xdd, 0x71, 0xfa, 0x34, 0xba, 0x46, 0x51, 0xf4, + 0xbe, 0x55, 0xa6, 0x1d, 0x6b, 0x7d, 0x74, 0x13, 0x26, 0x5f, 0xfa, 0xf6, 0xde, 0x10, 0xbb, 0x21, + 0xbb, 0xb7, 0x4b, 0x9a, 0xa8, 0xc3, 0x5c, 0x00, 0x90, 0xa2, 0x90, 0x58, 0xb6, 0xb1, 0xb9, 0xf5, + 0xbc, 0xdb, 0x98, 0x40, 0x35, 0x98, 0xdc, 0xd8, 0x5c, 0xed, 0xac, 0x77, 0x48, 0xb4, 0x13, 0x51, + 0xec, 0x9e, 0xdc, 0x74, 0x6d, 0x61, 0x88, 0xd8, 0x9a, 0x50, 0xe5, 0x32, 0xe2, 0xd7, 0x68, 0x21, + 0x97, 0x60, 0x71, 0xcf, 0xbc, 0x01, 0xb3, 0xba, 0xa5, 0x21, 0x08, 0xee, 0x9b, 0xff, 0x9a, 0x83, + 0x29, 0xbe, 0x11, 0xce, 0xb5, 0x73, 0xaf, 0x2a, 0x52, 0xf1, 0x0b, 0x87, 0x50, 0x52, 0x13, 0xca, + 0x6c, 0x83, 0xf4, 0xf9, 0x8d, 0x56, 0x7c, 0x12, 0x77, 0xcb, 0xd6, 0x3b, 0xee, 0x73, 0xb3, 0x47, + 0xdf, 0x5a, 0x47, 0x58, 0xd4, 0x3a, 0x42, 0xf4, 0x1e, 0x4c, 0x45, 0x1b, 0xce, 0x0e, 0xf8, 0x51, + 0xa9, 0x22, 0x4d, 0x51, 0x13, 0x9b, 0x8a, 0x74, 0xc6, 0x6c, 0x56, 0xce, 0xb0, 0x19, 0xba, 0x05, + 0x25, 0x7c, 0x88, 0xdd, 0x30, 0x68, 0x56, 0x69, 0x68, 0x9c, 0x12, 0x57, 0xa4, 0x0e, 0x69, 0xb5, + 0x78, 0xa7, 0x34, 0xd5, 0x47, 0x30, 0x43, 0x6f, 0xb0, 0x8f, 0x7d, 0xdb, 0x55, 0x6f, 0xe1, 0xdd, + 0xee, 0x3a, 0x0f, 0x24, 0xe4, 0x27, 0xaa, 0x43, 0x6e, 0x6d, 0x95, 0xeb, 0x27, 0xb7, 0xb6, 0x2a, + 0xc7, 0xff, 0xa1, 0x01, 0x48, 0x65, 0x70, 0x2e, 0x5b, 0x24, 0x50, 0x84, 0x1c, 0x79, 0x29, 0xc7, + 0x2c, 0x14, 0xb1, 0xef, 0x7b, 0x3e, 0x73, 0x94, 0x16, 0xfb, 0x90, 0xd2, 0xbc, 0xcf, 0x85, 0xb1, + 0xf0, 0xa1, 0x77, 0x10, 0x79, 0x00, 0xc6, 0xd6, 0x48, 0x0b, 0xdf, 0x85, 0x4b, 0x31, 0xf2, 0x8b, + 0x09, 0xda, 0x9b, 0x30, 0x4d, 0xb9, 0xae, 0xec, 0xe3, 0xde, 0xc1, 0xc8, 0x73, 0xdc, 0x94, 0x04, + 0xe8, 0x26, 0xf1, 0x5d, 0x22, 0x5c, 0x90, 0x29, 0xb2, 0x39, 0xd7, 0xa2, 0xc6, 0x6e, 0x77, 0x5d, + 0x2e, 0xf5, 0x5d, 0xb8, 0x92, 0x60, 0x28, 0x66, 0xf6, 0xeb, 0x50, 0xed, 0x45, 0x8d, 0x01, 0x3f, + 0x13, 0x5e, 0x8f, 0x8b, 0x9b, 0x1c, 0xaa, 0x8e, 0x90, 0x18, 0x5f, 0x87, 0xd7, 0x52, 0x18, 0x17, + 0xa1, 0x8e, 0xfb, 0xe6, 0x5d, 0xb8, 0x4c, 0x39, 0x3f, 0xc5, 0x78, 0xd4, 0x1e, 0x38, 0x87, 0xa7, + 0x9b, 0xe5, 0x98, 0xcf, 0x57, 0x19, 0xf1, 0xe5, 0x2e, 0x2b, 0x09, 0xdd, 0xe1, 0xd0, 0x5d, 0x67, + 0x88, 0xbb, 0xde, 0x7a, 0xb6, 0xb4, 0x24, 0x90, 0x1f, 0xe0, 0xe3, 0x80, 0x1f, 0x08, 0xe9, 0x6f, + 0xe9, 0xbd, 0xfe, 0xd6, 0xe0, 0xea, 0x54, 0xf9, 0x7c, 0xc9, 0x5b, 0x63, 0x0e, 0x60, 0x8f, 0xec, + 0x41, 0xdc, 0x27, 0x1d, 0x2c, 0xdb, 0xa6, 0xb4, 0x44, 0x02, 0x93, 0x28, 0x54, 0x4b, 0x0a, 0x7c, + 0x9d, 0x6f, 0x1c, 0xfa, 0x9f, 0x20, 0x75, 0x52, 0x7a, 0x0b, 0xaa, 0xb4, 0x67, 0x3b, 0xb4, 0xc3, + 0x71, 0x90, 0x65, 0xb9, 0x65, 0xf3, 0x07, 0x06, 0xdf, 0x51, 0x82, 0xcf, 0xb9, 0xe6, 0x7c, 0x0f, + 0x4a, 0xf4, 0xce, 0x27, 0xee, 0x2e, 0x57, 0x35, 0x0b, 0x9b, 0x49, 0x64, 0x71, 0x42, 0xe5, 0x9c, + 0x64, 0x40, 0xe9, 0x19, 0xad, 0x05, 0x28, 0xd2, 0x16, 0x84, 0xe5, 0x5c, 0x7b, 0xc8, 0x12, 0x8a, + 0x15, 0x8b, 0xfe, 0xa6, 0x47, 0x7c, 0x8c, 0xfd, 0xe7, 0xd6, 0x3a, 0xbb, 0x53, 0x54, 0xac, 0xe8, + 0x9b, 0x28, 0xb6, 0x37, 0x70, 0xb0, 0x1b, 0xd2, 0xde, 0x02, 0xed, 0x55, 0x5a, 0xd0, 0x2d, 0xa8, + 0x38, 0xc1, 0x3a, 0xb6, 0x7d, 0x97, 0x27, 0xed, 0x15, 0xc7, 0x2c, 0x7b, 0xe4, 0x1a, 0xfb, 0x06, + 0x34, 0x98, 0x64, 0xed, 0x7e, 0x5f, 0x39, 0xbf, 0x47, 0xf8, 0x46, 0x02, 0x3f, 0xc6, 0x3f, 0x77, + 0x3a, 0xff, 0xbf, 0x33, 0x60, 0x46, 0x01, 0x38, 0x97, 0x09, 0xde, 0x83, 0x12, 0xab, 0xa8, 0xf0, + 0xa3, 0xe0, 0x6c, 0x7c, 0x14, 0x83, 0xb1, 0x38, 0x0d, 0x5a, 0x80, 0x32, 0xfb, 0x25, 0x2e, 0x66, + 0x7a, 0x72, 0x41, 0x24, 0x45, 0x5e, 0x80, 0x4b, 0xbc, 0x0f, 0x0f, 0x3d, 0xdd, 0x9e, 0x2b, 0xc4, + 0x3d, 0xc4, 0xf7, 0x0d, 0x98, 0x8d, 0x0f, 0x38, 0xd7, 0x2c, 0x15, 0xb9, 0x73, 0x5f, 0x48, 0xee, + 0xdf, 0x10, 0x72, 0x3f, 0x1f, 0xf5, 0x95, 0x23, 0x67, 0x72, 0xc5, 0xa9, 0xd6, 0xcd, 0xc5, 0xad, + 0x2b, 0x79, 0xfd, 0x28, 0x9a, 0x93, 0x60, 0x76, 0xae, 0x39, 0x7d, 0x70, 0xa6, 0x39, 0x29, 0x47, + 0xb0, 0xd4, 0xe4, 0xd6, 0xc4, 0x32, 0x5a, 0x77, 0x82, 0x28, 0xe2, 0xbc, 0x0b, 0xb5, 0x81, 0xe3, + 0x62, 0xdb, 0xe7, 0x55, 0x21, 0x43, 0x5d, 0x8f, 0x0f, 0xac, 0x58, 0xa7, 0x64, 0xf5, 0xbb, 0x06, + 0x20, 0x95, 0xd7, 0x2f, 0xc7, 0x5a, 0x8b, 0x42, 0xc1, 0x5b, 0xbe, 0x37, 0xf4, 0xc2, 0xd3, 0x96, + 0xd9, 0x7d, 0xf3, 0xf7, 0x0d, 0xb8, 0x9c, 0x18, 0xf1, 0xcb, 0x90, 0xfc, 0xbe, 0x79, 0x0d, 0x66, + 0x56, 0xb1, 0x38, 0xe3, 0xa5, 0xb2, 0x01, 0xdb, 0x80, 0xd4, 0xde, 0x8b, 0x39, 0xc5, 0xfc, 0x0a, + 0xcc, 0x3c, 0xf3, 0x0e, 0x89, 0x23, 0x27, 0xdd, 0xd2, 0x4d, 0xb1, 0xf4, 0x54, 0xa4, 0xaf, 0xe8, + 0x5b, 0xba, 0xde, 0x6d, 0x40, 0xea, 0xc8, 0x8b, 0x10, 0x67, 0xd9, 0xfc, 0x1f, 0x03, 0x6a, 0xed, + 0x81, 0xed, 0x0f, 0x85, 0x28, 0x1f, 0x41, 0x89, 0xe5, 0x5a, 0x78, 0xe2, 0xf4, 0xad, 0x38, 0x3f, + 0x95, 0x96, 0x7d, 0xb4, 0x59, 0x66, 0x86, 0x8f, 0x22, 0x53, 0xe1, 0xb5, 0xe2, 0xd5, 0x44, 0xed, + 0x78, 0x15, 0xbd, 0x0f, 0x45, 0x9b, 0x0c, 0xa1, 0xe1, 0xb5, 0x9e, 0x4c, 0x80, 0x51, 0x6e, 0xe4, + 0x4a, 0x64, 0x31, 0x2a, 0xf3, 0x43, 0xa8, 0x2a, 0x08, 0xa8, 0x0c, 0xf9, 0xc7, 0x1d, 0x7e, 0x4d, + 0x6a, 0xaf, 0x74, 0xd7, 0x5e, 0xb0, 0xa4, 0x60, 0x1d, 0x60, 0xb5, 0x13, 0x7d, 0xe7, 0x34, 0xa5, + 0x3a, 0x9b, 0xf3, 0xe1, 0x71, 0x4b, 0x95, 0xd0, 0xc8, 0x92, 0x30, 0x77, 0x16, 0x09, 0x25, 0xc4, + 0xef, 0x18, 0x30, 0xc5, 0x55, 0x73, 0xde, 0xd0, 0x4c, 0x39, 0x67, 0x84, 0x66, 0x65, 0x1a, 0x16, + 0x27, 0x94, 0x32, 0xfc, 0xb3, 0x01, 0x8d, 0x55, 0xef, 0x95, 0xbb, 0xe7, 0xdb, 0xfd, 0x68, 0x0f, + 0x7e, 0x9c, 0x30, 0xe7, 0x42, 0x22, 0x77, 0x9f, 0xa0, 0x97, 0x0d, 0x09, 0xb3, 0x36, 0x65, 0x2e, + 0x85, 0xc5, 0x77, 0xf1, 0x69, 0x7e, 0x15, 0xa6, 0x13, 0x83, 0x88, 0x81, 0x5e, 0xb4, 0xd7, 0xd7, + 0x56, 0x89, 0x41, 0x68, 0x06, 0xb7, 0xb3, 0xd1, 0x7e, 0xb4, 0xde, 0xe1, 0x75, 0xd6, 0xf6, 0xc6, + 0x4a, 0x67, 0x5d, 0x1a, 0xea, 0x81, 0x98, 0xc1, 0x03, 0x73, 0x00, 0x33, 0x8a, 0x40, 0xe7, 0x2d, + 0x77, 0xe9, 0xe5, 0x95, 0x68, 0x4d, 0x98, 0xe2, 0xa7, 0x9c, 0xe4, 0xc6, 0xff, 0x69, 0x1e, 0xea, + 0xa2, 0xeb, 0xcb, 0x91, 0x02, 0x5d, 0x81, 0x52, 0x7f, 0x77, 0xdb, 0xf9, 0xb6, 0xa8, 0xb4, 0xf2, + 0x2f, 0xd2, 0x3e, 0x60, 0x38, 0xec, 0xfd, 0x04, 0xff, 0x42, 0xd7, 0xd8, 0xd3, 0x8a, 0x35, 0xb7, + 0x8f, 0x8f, 0xe8, 0x61, 0xa8, 0x60, 0xc9, 0x06, 0x9a, 0xa6, 0xe4, 0xef, 0x2c, 0xe8, 0x5d, 0x57, + 0x79, 0x77, 0x81, 0x96, 0xa1, 0x41, 0x7e, 0xb7, 0x47, 0xa3, 0x81, 0x83, 0xfb, 0x8c, 0x01, 0xb9, + 0xe6, 0x16, 0xe4, 0x69, 0x27, 0x45, 0x80, 0x6e, 0x40, 0x89, 0x5e, 0x01, 0x83, 0xe6, 0x24, 0x89, + 0xab, 0x92, 0x94, 0x37, 0xa3, 0x77, 0xa0, 0xca, 0x24, 0x5e, 0x73, 0x9f, 0x07, 0x98, 0xbe, 0x42, + 0x50, 0xf2, 0x21, 0x6a, 0x5f, 0xfc, 0x9c, 0x05, 0x59, 0xe7, 0x2c, 0xb4, 0x08, 0xf5, 0x20, 0xf4, + 0x7c, 0x7b, 0x0f, 0xbf, 0xe0, 0x2a, 0xab, 0xc6, 0x93, 0x76, 0x89, 0x6e, 0x69, 0xae, 0x6b, 0x30, + 0xd3, 0x1e, 0x87, 0xfb, 0x1d, 0x97, 0x04, 0xc7, 0x94, 0x31, 0xaf, 0x03, 0x22, 0xbd, 0xab, 0x4e, + 0xa0, 0xed, 0xe6, 0x83, 0xb5, 0x2b, 0xe1, 0x81, 0xb9, 0x01, 0x97, 0x48, 0x2f, 0x76, 0x43, 0xa7, + 0xa7, 0x1c, 0x44, 0xc4, 0x51, 0xd7, 0x48, 0x1c, 0x75, 0xed, 0x20, 0x78, 0xe5, 0xf9, 0x7d, 0x6e, + 0xec, 0xe8, 0x5b, 0xa2, 0xfd, 0xa3, 0xc1, 0xa4, 0x79, 0x1e, 0xc4, 0x8e, 0xa9, 0x5f, 0x90, 0x1f, + 0xfa, 0x55, 0x28, 0x7b, 0x23, 0xfa, 0xc8, 0x87, 0x67, 0xff, 0xae, 0x2c, 0xb0, 0x87, 0x43, 0x0b, + 0x9c, 0xf1, 0x26, 0xeb, 0x55, 0x32, 0x54, 0x9c, 0x9e, 0xa8, 0x79, 0xdf, 0x0e, 0xf6, 0x71, 0x7f, + 0x4b, 0x30, 0x8f, 0xe5, 0x46, 0x1f, 0x58, 0x89, 0x6e, 0x29, 0xfb, 0x3d, 0x29, 0xfa, 0x63, 0x1c, + 0x9e, 0x20, 0xba, 0x9a, 0x4f, 0xbf, 0x2c, 0x86, 0xf0, 0x32, 0xe0, 0x59, 0x46, 0xfd, 0xd0, 0x80, + 0xeb, 0x62, 0xd8, 0xca, 0xbe, 0xed, 0xee, 0x61, 0x21, 0xcc, 0x2f, 0xaa, 0xaf, 0xf4, 0xa4, 0xf3, + 0x67, 0x9c, 0xf4, 0x53, 0x68, 0x46, 0x93, 0xa6, 0x99, 0x18, 0x6f, 0xa0, 0x4e, 0x62, 0x1c, 0x70, + 0x8f, 0x50, 0xb1, 0xe8, 0x6f, 0xd2, 0xe6, 0x7b, 0x83, 0xe8, 0x12, 0x44, 0x7e, 0x4b, 0x66, 0xeb, + 0x70, 0x55, 0x30, 0xe3, 0xa9, 0x91, 0x38, 0xb7, 0xd4, 0x9c, 0x4e, 0xe4, 0xc6, 0xed, 0x41, 0x78, + 0x9c, 0xbc, 0x94, 0xb4, 0x43, 0xe2, 0x26, 0xa4, 0x28, 0x86, 0x0e, 0x65, 0x8e, 0xed, 0x00, 0x22, + 0xb3, 0x72, 0x5e, 0x4d, 0xf5, 0x13, 0x96, 0xda, 0x7e, 0xbe, 0x04, 0x48, 0x7f, 0x6a, 0x09, 0x64, + 0xa3, 0x62, 0x98, 0x8b, 0x04, 0x25, 0x6a, 0xdf, 0xc2, 0xfe, 0xd0, 0x09, 0x02, 0xa5, 0xb0, 0xa4, + 0x53, 0xd7, 0x5b, 0x50, 0x18, 0x61, 0x1e, 0xbc, 0xab, 0x4b, 0x48, 0xec, 0x09, 0x65, 0x30, 0xed, + 0x97, 0x30, 0x43, 0xb8, 0x21, 0x60, 0x98, 0x41, 0xb4, 0x38, 0x49, 0x31, 0x45, 0xea, 0x3b, 0x97, + 0x91, 0xfa, 0xce, 0xc7, 0x53, 0xdf, 0xb1, 0x03, 0xa5, 0xea, 0xa8, 0x2e, 0xe6, 0x40, 0xd9, 0x65, + 0x06, 0x88, 0xfc, 0xdb, 0xc5, 0x70, 0xfd, 0x23, 0xee, 0xa8, 0x2e, 0x2a, 0x0c, 0x62, 0x3a, 0x67, + 0x51, 0x76, 0x14, 0x9f, 0xc8, 0x84, 0x1a, 0x31, 0x92, 0xa5, 0xd6, 0x04, 0x0a, 0x56, 0xac, 0x4d, + 0x3a, 0xe3, 0x03, 0x98, 0x8d, 0x3b, 0xe3, 0x73, 0x09, 0x35, 0x0b, 0xc5, 0xd0, 0x3b, 0xc0, 0x22, + 0x32, 0xb3, 0x8f, 0x94, 0x5a, 0x23, 0x47, 0x7d, 0x31, 0x6a, 0xfd, 0xa6, 0xe4, 0x4a, 0x37, 0xe0, + 0x79, 0x67, 0x40, 0x96, 0xa3, 0xb8, 0xfb, 0xb2, 0x0f, 0x89, 0xf5, 0x09, 0x5c, 0x49, 0x3a, 0xdf, + 0x8b, 0x99, 0xc4, 0x0e, 0xdb, 0x9c, 0x3a, 0xf7, 0x7c, 0x31, 0x00, 0x9f, 0x49, 0x3f, 0xa9, 0x38, + 0xdd, 0x8b, 0xe1, 0xfd, 0x9b, 0xd0, 0xd2, 0xf9, 0xe0, 0x0b, 0xdd, 0x8b, 0x91, 0x4b, 0xbe, 0x18, + 0xae, 0xdf, 0x37, 0x24, 0x5b, 0x75, 0xd5, 0x7c, 0xf8, 0x45, 0xd8, 0x8a, 0x58, 0x77, 0x37, 0x5a, + 0x3e, 0x8b, 0x91, 0xb7, 0xcc, 0xeb, 0xbd, 0xa5, 0x1c, 0x42, 0x09, 0xc5, 0xfe, 0x93, 0xae, 0xfe, + 0xcb, 0x5c, 0xbd, 0x1c, 0x4c, 0xc6, 0x9d, 0xf3, 0x82, 0x91, 0xf0, 0x1c, 0x81, 0xd1, 0x8f, 0xd4, + 0x56, 0x51, 0x83, 0xd4, 0xc5, 0x98, 0xee, 0xb7, 0x64, 0x80, 0x49, 0xc5, 0xb1, 0x8b, 0x41, 0xb0, + 0x61, 0x3e, 0x3b, 0x84, 0x5d, 0x08, 0xc4, 0x9d, 0x36, 0x54, 0xa2, 0x9b, 0xaf, 0xf2, 0xf2, 0xb6, + 0x0a, 0xe5, 0x8d, 0xcd, 0xed, 0xad, 0xf6, 0x0a, 0xb9, 0xd8, 0xcd, 0x42, 0x79, 0x65, 0xd3, 0xb2, + 0x9e, 0x6f, 0x75, 0xc9, 0xcd, 0x2e, 0xf9, 0x10, 0x67, 0xe9, 0x67, 0x79, 0xc8, 0x3d, 0x7d, 0x81, + 0x3e, 0x85, 0x22, 0x7b, 0x08, 0x76, 0xc2, 0x7b, 0xc0, 0xd6, 0x49, 0x6f, 0xdd, 0xcc, 0xd7, 0xbe, + 0xf7, 0x5f, 0x3f, 0xfb, 0xe3, 0xdc, 0x8c, 0x59, 0x5b, 0x3c, 0x5c, 0x5e, 0x3c, 0x38, 0x5c, 0xa4, + 0x41, 0xf6, 0xa1, 0x71, 0x07, 0x7d, 0x0d, 0xf2, 0x5b, 0xe3, 0x10, 0x65, 0xbe, 0x13, 0x6c, 0x65, + 0x3f, 0x7f, 0x33, 0x2f, 0x53, 0xa6, 0xd3, 0x26, 0x70, 0xa6, 0xa3, 0x71, 0x48, 0x58, 0x7e, 0x0b, + 0xaa, 0xea, 0xe3, 0xb5, 0x53, 0x1f, 0x0f, 0xb6, 0x4e, 0x7f, 0x18, 0x67, 0x5e, 0xa7, 0x50, 0xaf, + 0x99, 0x88, 0x43, 0xb1, 0xe7, 0x75, 0xea, 0x2c, 0xba, 0x47, 0x2e, 0xca, 0x7c, 0x5a, 0xd8, 0xca, + 0x7e, 0x2b, 0x97, 0x9a, 0x45, 0x78, 0xe4, 0x12, 0x96, 0xdf, 0xe4, 0x8f, 0xe2, 0x7a, 0x21, 0xba, + 0xa1, 0x79, 0xd5, 0xa4, 0xbe, 0xd6, 0x69, 0xcd, 0x67, 0x13, 0x70, 0x90, 0x6b, 0x14, 0xe4, 0x8a, + 0x39, 0xc3, 0x41, 0x7a, 0x11, 0xc9, 0x43, 0xe3, 0xce, 0x52, 0x0f, 0x8a, 0xb4, 0x76, 0x8c, 0x3e, + 0x13, 0x3f, 0x5a, 0x9a, 0xaa, 0x7c, 0x86, 0xa1, 0x63, 0x55, 0x67, 0x73, 0x96, 0x02, 0xd5, 0xcd, + 0x0a, 0x01, 0xa2, 0x95, 0xe3, 0x87, 0xc6, 0x9d, 0xdb, 0xc6, 0x5d, 0x63, 0xe9, 0x6f, 0x8a, 0x50, + 0xa4, 0x35, 0x0a, 0x74, 0x00, 0x20, 0x6b, 0xa4, 0xc9, 0xd9, 0xa5, 0xca, 0xaf, 0xc9, 0xd9, 0xa5, + 0xcb, 0xab, 0x66, 0x8b, 0x82, 0xce, 0x9a, 0xd3, 0x04, 0x94, 0x96, 0x3e, 0x16, 0x69, 0xa5, 0x87, + 0xe8, 0xf1, 0x87, 0x06, 0x2f, 0xd6, 0xb0, 0x6d, 0x86, 0x74, 0xdc, 0x62, 0xf5, 0xd1, 0xe4, 0x72, + 0xd0, 0x94, 0x44, 0xcd, 0x07, 0x14, 0x70, 0xd1, 0x6c, 0x48, 0x40, 0x9f, 0x52, 0x3c, 0x34, 0xee, + 0x7c, 0xd6, 0x34, 0x2f, 0x71, 0x2d, 0x27, 0x7a, 0xd0, 0x77, 0xa0, 0x1e, 0xaf, 0xe4, 0xa1, 0x9b, + 0x1a, 0xac, 0x64, 0x65, 0xb0, 0xf5, 0xe6, 0xc9, 0x44, 0x5c, 0xa6, 0x39, 0x2a, 0x13, 0x07, 0x67, + 0xc8, 0x07, 0x18, 0x8f, 0x6c, 0x42, 0xc4, 0x6d, 0x80, 0xfe, 0xdc, 0xe0, 0xc5, 0x58, 0x59, 0x88, + 0x43, 0x3a, 0xee, 0xa9, 0x7a, 0x5f, 0xeb, 0xd6, 0x29, 0x54, 0x5c, 0x88, 0x0f, 0xa9, 0x10, 0x1f, + 0x98, 0xb3, 0x52, 0x88, 0xd0, 0x19, 0xe2, 0xd0, 0xe3, 0x52, 0x7c, 0x76, 0xcd, 0x7c, 0x2d, 0xa6, + 0x9c, 0x58, 0xaf, 0x34, 0x16, 0x2b, 0x98, 0x69, 0x8d, 0x15, 0xab, 0xc9, 0x69, 0x8d, 0x15, 0xaf, + 0xb6, 0xe9, 0x8c, 0xc5, 0xcb, 0x63, 0x1a, 0x63, 0x45, 0x3d, 0x4b, 0xff, 0x57, 0x80, 0xf2, 0x0a, + 0xfb, 0xe3, 0x1a, 0xe4, 0x41, 0x25, 0x2a, 0x21, 0xa1, 0x39, 0x5d, 0x96, 0x5a, 0x5e, 0xe5, 0x5a, + 0x37, 0x32, 0xfb, 0xb9, 0x40, 0x6f, 0x50, 0x81, 0x5e, 0x37, 0xaf, 0x10, 0x64, 0xfe, 0xf7, 0x3b, + 0x8b, 0x2c, 0x97, 0xb9, 0x68, 0xf7, 0xfb, 0x44, 0x11, 0xbf, 0x0d, 0x35, 0xb5, 0xa0, 0x83, 0xde, + 0xd0, 0x66, 0xc6, 0xd5, 0xea, 0x50, 0xcb, 0x3c, 0x89, 0x84, 0x23, 0xbf, 0x49, 0x91, 0xe7, 0xcc, + 0xab, 0x1a, 0x64, 0x9f, 0x92, 0xc6, 0xc0, 0x59, 0xe5, 0x45, 0x0f, 0x1e, 0x2b, 0xf1, 0xe8, 0xc1, + 0xe3, 0x85, 0x9b, 0x13, 0xc1, 0xc7, 0x94, 0x94, 0x80, 0x07, 0x00, 0xb2, 0x34, 0x82, 0xb4, 0xba, + 0x54, 0x2e, 0xac, 0x49, 0xe7, 0x90, 0xae, 0xaa, 0x98, 0x26, 0x85, 0xe5, 0xeb, 0x2e, 0x01, 0x3b, + 0x70, 0x82, 0x90, 0x6d, 0xcc, 0xa9, 0x58, 0x61, 0x03, 0x69, 0xe7, 0x13, 0xaf, 0x93, 0xb4, 0x6e, + 0x9e, 0x48, 0xc3, 0xd1, 0x6f, 0x51, 0xf4, 0x1b, 0x66, 0x4b, 0x83, 0x3e, 0x62, 0xb4, 0x64, 0xb1, + 0xfd, 0x7f, 0x09, 0xaa, 0xcf, 0x6c, 0xc7, 0x0d, 0xb1, 0x6b, 0xbb, 0x3d, 0x8c, 0x76, 0xa1, 0x48, + 0x63, 0x77, 0xd2, 0x11, 0xab, 0x79, 0xfc, 0xa4, 0x23, 0x8e, 0x25, 0xb2, 0xcd, 0x79, 0x0a, 0xdc, + 0x32, 0x2f, 0x13, 0xe0, 0xa1, 0x64, 0xbd, 0xc8, 0x52, 0xe0, 0xc6, 0x1d, 0xf4, 0x12, 0x4a, 0xbc, + 0x80, 0x9d, 0x60, 0x14, 0x4b, 0xaa, 0xb5, 0xae, 0xe9, 0x3b, 0x75, 0x6b, 0x59, 0x85, 0x09, 0x28, + 0x1d, 0xc1, 0x39, 0x04, 0x90, 0xf5, 0x98, 0xa4, 0x45, 0x53, 0x75, 0x9c, 0xd6, 0x7c, 0x36, 0x81, + 0x4e, 0xa7, 0x2a, 0x66, 0x3f, 0xa2, 0x25, 0xb8, 0xdf, 0x80, 0xc2, 0x13, 0x3b, 0xd8, 0x47, 0x89, + 0xd8, 0xab, 0xbc, 0x20, 0x6d, 0xb5, 0x74, 0x5d, 0x1c, 0xe5, 0x06, 0x45, 0xb9, 0xca, 0x5c, 0x99, + 0x8a, 0x42, 0x5f, 0x54, 0x1a, 0x77, 0x50, 0x1f, 0x4a, 0xec, 0xf9, 0x68, 0x52, 0x7f, 0xb1, 0xb7, + 0xa8, 0x49, 0xfd, 0xc5, 0x5f, 0x9c, 0x9e, 0x8e, 0x32, 0x82, 0x49, 0xf1, 0x28, 0x13, 0x25, 0x9e, + 0xb2, 0x24, 0x5e, 0x72, 0xb6, 0xe6, 0xb2, 0xba, 0x39, 0xd6, 0x4d, 0x8a, 0x75, 0xdd, 0x6c, 0xa6, + 0x6c, 0xc5, 0x29, 0x1f, 0x1a, 0x77, 0xee, 0x1a, 0xe8, 0x3b, 0x00, 0xb2, 0x60, 0x95, 0xda, 0x81, + 0xc9, 0x22, 0x58, 0x6a, 0x07, 0xa6, 0x6a, 0x5d, 0xe6, 0x02, 0xc5, 0xbd, 0x6d, 0xde, 0x4c, 0xe2, + 0x86, 0xbe, 0xed, 0x06, 0x2f, 0xb1, 0xff, 0x3e, 0xcb, 0x96, 0x07, 0xfb, 0xce, 0x88, 0x4c, 0xd9, + 0x87, 0x4a, 0x54, 0x4f, 0x48, 0x7a, 0xdb, 0x64, 0xe5, 0x23, 0xe9, 0x6d, 0x53, 0x85, 0x88, 0xb8, + 0xdb, 0x89, 0xad, 0x16, 0x41, 0x4a, 0x36, 0xe0, 0x5f, 0x35, 0xa0, 0x40, 0x0e, 0xe4, 0xe4, 0x70, + 0x22, 0x93, 0x3d, 0xc9, 0xd9, 0xa7, 0xf2, 0xd5, 0xc9, 0xd9, 0xa7, 0xf3, 0x44, 0xf1, 0xc3, 0x09, + 0xb9, 0xac, 0x2d, 0xb2, 0x2c, 0x0a, 0x99, 0xa9, 0x07, 0x55, 0x25, 0x09, 0x84, 0x34, 0xcc, 0xe2, + 0xf9, 0xef, 0x64, 0xb8, 0xd3, 0x64, 0x90, 0xcc, 0xd7, 0x29, 0xde, 0x65, 0x16, 0xee, 0x28, 0x5e, + 0x9f, 0x51, 0x10, 0x40, 0x3e, 0x3b, 0xbe, 0xef, 0x35, 0xb3, 0x8b, 0xef, 0xfd, 0xf9, 0x6c, 0x82, + 0xcc, 0xd9, 0xc9, 0x8d, 0xff, 0x0a, 0x6a, 0x6a, 0xe2, 0x07, 0x69, 0x84, 0x4f, 0x64, 0xe8, 0x93, + 0x71, 0x44, 0x97, 0x37, 0x8a, 0x7b, 0x36, 0x0a, 0x69, 0x2b, 0x64, 0x04, 0x78, 0x00, 0x65, 0x9e, + 0x00, 0xd2, 0xa9, 0x34, 0x9e, 0xc4, 0xd7, 0xa9, 0x34, 0x91, 0x3d, 0x8a, 0x9f, 0x9e, 0x29, 0x22, + 0xb9, 0x88, 0x8a, 0x58, 0xcd, 0xd1, 0x1e, 0xe3, 0x30, 0x0b, 0x4d, 0x26, 0x6d, 0xb3, 0xd0, 0x94, + 0xfc, 0x40, 0x16, 0xda, 0x1e, 0x0e, 0xb9, 0x3f, 0x10, 0x97, 0x6b, 0x94, 0xc1, 0x4c, 0x8d, 0x8f, + 0xe6, 0x49, 0x24, 0xba, 0xcb, 0x8d, 0x04, 0x14, 0xc1, 0xf1, 0x08, 0x40, 0x26, 0xa3, 0x92, 0x27, + 0x56, 0x6d, 0x9d, 0x20, 0x79, 0x62, 0xd5, 0xe7, 0xb3, 0xe2, 0xbe, 0x4f, 0xe2, 0xb2, 0xbb, 0x15, + 0x41, 0xfe, 0xb1, 0x01, 0x28, 0x9d, 0xae, 0x42, 0xef, 0xea, 0xb9, 0x6b, 0x6b, 0x0e, 0xad, 0xf7, + 0xce, 0x46, 0xac, 0x0b, 0x67, 0x52, 0xa4, 0x1e, 0xa5, 0x1e, 0xbd, 0x22, 0x42, 0x7d, 0xd7, 0x80, + 0xa9, 0x58, 0x8a, 0x0b, 0xbd, 0x95, 0x61, 0xd3, 0x44, 0xe1, 0xa1, 0xf5, 0xf6, 0xa9, 0x74, 0xba, + 0xa3, 0xbc, 0xb2, 0x02, 0xc4, 0x9d, 0xe6, 0xf7, 0x0c, 0xa8, 0xc7, 0x33, 0x61, 0x28, 0x83, 0x77, + 0xaa, 0x5e, 0xd1, 0xba, 0x7d, 0x3a, 0xe1, 0xc9, 0xe6, 0x91, 0xd7, 0x99, 0x01, 0x94, 0x79, 0xca, + 0x4c, 0xb7, 0xf0, 0xe3, 0x05, 0x0e, 0xdd, 0xc2, 0x4f, 0xe4, 0xdb, 0x34, 0x0b, 0xdf, 0xf7, 0x06, + 0x58, 0xd9, 0x66, 0x3c, 0x93, 0x96, 0x85, 0x76, 0xf2, 0x36, 0x4b, 0xa4, 0xe1, 0xb2, 0xd0, 0xe4, + 0x36, 0x13, 0x09, 0x33, 0x94, 0xc1, 0xec, 0x94, 0x6d, 0x96, 0xcc, 0xb7, 0x69, 0xb6, 0x19, 0x05, + 0x54, 0xb6, 0x99, 0x4c, 0x64, 0xe9, 0xb6, 0x59, 0xaa, 0x16, 0xa3, 0xdb, 0x66, 0xe9, 0x5c, 0x98, + 0xc6, 0x8e, 0x14, 0x37, 0xb6, 0xcd, 0x2e, 0x69, 0x52, 0x5d, 0xe8, 0xbd, 0x0c, 0x25, 0x6a, 0x2b, + 0x3b, 0xad, 0xf7, 0xcf, 0x48, 0x9d, 0xb9, 0xc6, 0x99, 0xfa, 0xc5, 0x1a, 0xff, 0x13, 0x03, 0x66, + 0x75, 0xd9, 0x31, 0x94, 0x81, 0x93, 0x51, 0x08, 0x6a, 0x2d, 0x9c, 0x95, 0xfc, 0x64, 0x6d, 0x45, + 0xab, 0xfe, 0x51, 0xe3, 0xdf, 0x3e, 0x9f, 0x33, 0xfe, 0xf3, 0xf3, 0x39, 0xe3, 0xbf, 0x3f, 0x9f, + 0x33, 0x7e, 0xf2, 0xbf, 0x73, 0x13, 0xbb, 0x25, 0xfa, 0x7f, 0x6c, 0x58, 0xfe, 0x79, 0x00, 0x00, + 0x00, 0xff, 0xff, 0x68, 0xa6, 0xc7, 0xa8, 0x58, 0x42, 0x00, 0x00, } // Reference imports to suppress errors if they are not otherwise used. @@ -11518,6 +11528,13 @@ func (m *StatusResponse) MarshalToSizedBuffer(dAtA []byte) (int, error) { i -= len(m.XXX_unrecognized) copy(dAtA[i:], m.XXX_unrecognized) } + if len(m.StorageVersion) > 0 { + i -= len(m.StorageVersion) + copy(dAtA[i:], m.StorageVersion) + i = encodeVarintRpc(dAtA, i, uint64(len(m.StorageVersion))) + i-- + dAtA[i] = 0x5a + } if m.IsLearner { i-- if m.IsLearner { @@ -14430,6 +14447,10 @@ func (m *StatusResponse) Size() (n int) { if m.IsLearner { n += 2 } + l = len(m.StorageVersion) + if l > 0 { + n += 1 + l + sovRpc(uint64(l)) + } if m.XXX_unrecognized != nil { n += len(m.XXX_unrecognized) } @@ -22532,6 +22553,38 @@ func (m *StatusResponse) Unmarshal(dAtA []byte) error { } } m.IsLearner = bool(v != 0) + case 11: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field StorageVersion", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowRpc + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + stringLen |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + intStringLen := int(stringLen) + if intStringLen < 0 { + return ErrInvalidLengthRpc + } + postIndex := iNdEx + intStringLen + if postIndex < 0 { + return ErrInvalidLengthRpc + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.StorageVersion = string(dAtA[iNdEx:postIndex]) + iNdEx = postIndex default: iNdEx = preIndex skippy, err := skipRpc(dAtA[iNdEx:]) diff --git a/api/etcdserverpb/rpc.proto b/api/etcdserverpb/rpc.proto index 29bca1fdf701..d9eeb5c86759 100644 --- a/api/etcdserverpb/rpc.proto +++ b/api/etcdserverpb/rpc.proto @@ -1158,6 +1158,8 @@ message StatusResponse { int64 dbSizeInUse = 9 [(versionpb.etcd_version_field)="3.4"]; // isLearner indicates if the member is raft learner. bool isLearner = 10 [(versionpb.etcd_version_field)="3.4"]; + // storageVersion is the version of the db file. + string storageVersion = 11 [(versionpb.etcd_version_field)="3.6"]; } message AuthEnableRequest { diff --git a/etcdctl/ctlv3/command/printer.go b/etcdctl/ctlv3/command/printer.go index 287f88984cb6..d5fc07377fbd 100644 --- a/etcdctl/ctlv3/command/printer.go +++ b/etcdctl/ctlv3/command/printer.go @@ -211,13 +211,14 @@ func makeEndpointHealthTable(healthList []epHealth) (hdr []string, rows [][]stri } func makeEndpointStatusTable(statusList []epStatus) (hdr []string, rows [][]string) { - hdr = []string{"endpoint", "ID", "version", "db size", "db size in use", "is leader", "is learner", "raft term", + hdr = []string{"endpoint", "ID", "version", "storage version", "db size", "db size in use", "is leader", "is learner", "raft term", "raft index", "raft applied index", "errors"} for _, status := range statusList { rows = append(rows, []string{ status.Ep, fmt.Sprintf("%x", status.Resp.Header.MemberId), status.Resp.Version, + status.Resp.StorageVersion, humanize.Bytes(uint64(status.Resp.DbSize)), humanize.Bytes(uint64(status.Resp.DbSizeInUse)), fmt.Sprint(status.Resp.Leader == status.Resp.Header.MemberId), diff --git a/etcdctl/ctlv3/command/printer_fields.go b/etcdctl/ctlv3/command/printer_fields.go index 2cb5def1b3c2..634ea5a8bcf2 100644 --- a/etcdctl/ctlv3/command/printer_fields.go +++ b/etcdctl/ctlv3/command/printer_fields.go @@ -155,6 +155,7 @@ func (p *fieldsPrinter) EndpointStatus(eps []epStatus) { for _, ep := range eps { p.hdr(ep.Resp.Header) fmt.Printf("\"Version\" : %q\n", ep.Resp.Version) + fmt.Printf("\"StorageVersion\" : %q\n", ep.Resp.StorageVersion) fmt.Println(`"DBSize" :`, ep.Resp.DbSize) fmt.Println(`"DBSizeInUse" :`, ep.Resp.DbSizeInUse) fmt.Println(`"Leader" :`, ep.Resp.Leader) diff --git a/scripts/etcd_version_annotations.txt b/scripts/etcd_version_annotations.txt index 155e9c47d4a8..17b587cf6271 100644 --- a/scripts/etcd_version_annotations.txt +++ b/scripts/etcd_version_annotations.txt @@ -384,6 +384,7 @@ etcdserverpb.StatusResponse.leader: "" etcdserverpb.StatusResponse.raftAppliedIndex: "3.4" etcdserverpb.StatusResponse.raftIndex: "" etcdserverpb.StatusResponse.raftTerm: "" +etcdserverpb.StatusResponse.storageVersion: "3.6" etcdserverpb.StatusResponse.version: "" etcdserverpb.TxnRequest: "3.0" etcdserverpb.TxnRequest.compare: "" diff --git a/server/etcdserver/adapters.go b/server/etcdserver/adapters.go index 110abd7e9519..c3a17c6ee205 100644 --- a/server/etcdserver/adapters.go +++ b/server/etcdserver/adapters.go @@ -26,12 +26,14 @@ import ( "go.etcd.io/etcd/server/v3/storage/schema" ) -// serverVersionAdapter implements Server interface needed by serverversion.Monitor +// serverVersionAdapter implements the interface Server defined in package +// go.etcd.io/etcd/server/v3/etcdserver/version, and it's needed by Monitor +// in the same package. type serverVersionAdapter struct { *EtcdServer } -func newServerVersionAdapter(s *EtcdServer) *serverVersionAdapter { +func NewServerVersionAdapter(s *EtcdServer) *serverVersionAdapter { return &serverVersionAdapter{ EtcdServer: s, } diff --git a/server/etcdserver/api/v3rpc/maintenance.go b/server/etcdserver/api/v3rpc/maintenance.go index 59732f619006..931f712db880 100644 --- a/server/etcdserver/api/v3rpc/maintenance.go +++ b/server/etcdserver/api/v3rpc/maintenance.go @@ -27,6 +27,7 @@ import ( "go.etcd.io/etcd/raft/v3" "go.etcd.io/etcd/server/v3/auth" "go.etcd.io/etcd/server/v3/etcdserver" + serverversion "go.etcd.io/etcd/server/v3/etcdserver/version" "go.etcd.io/etcd/server/v3/storage/backend" "go.etcd.io/etcd/server/v3/storage/mvcc" "go.etcd.io/etcd/server/v3/storage/schema" @@ -76,10 +77,11 @@ type maintenanceServer struct { hdr header cs ClusterStatusGetter d Downgrader + vs serverversion.Server } func NewMaintenanceServer(s *etcdserver.EtcdServer) pb.MaintenanceServer { - srv := &maintenanceServer{lg: s.Cfg.Logger, rg: s, kg: s, bg: s, a: s, lt: s, hdr: newHeader(s), cs: s, d: s} + srv := &maintenanceServer{lg: s.Cfg.Logger, rg: s, kg: s, bg: s, a: s, lt: s, hdr: newHeader(s), cs: s, d: s, vs: etcdserver.NewServerVersionAdapter(s)} if srv.lg == nil { srv.lg = zap.NewNop() } @@ -235,6 +237,9 @@ func (ms *maintenanceServer) Status(ctx context.Context, ar *pb.StatusRequest) ( DbSizeInUse: ms.bg.Backend().SizeInUse(), IsLearner: ms.cs.IsLearner(), } + if storageVersion := ms.vs.GetStorageVersion(); storageVersion != nil { + resp.StorageVersion = storageVersion.String() + } if resp.Leader == raft.None { resp.Errors = append(resp.Errors, etcdserver.ErrNoLeader.Error()) } diff --git a/server/etcdserver/server.go b/server/etcdserver/server.go index d10559a4e21d..e925f47d4501 100644 --- a/server/etcdserver/server.go +++ b/server/etcdserver/server.go @@ -2067,7 +2067,7 @@ func (s *EtcdServer) ClusterVersion() *semver.Version { // monitorClusterVersions every monitorVersionInterval checks if it's the leader and updates cluster version if needed. func (s *EtcdServer) monitorClusterVersions() { - monitor := serverversion.NewMonitor(s.Logger(), newServerVersionAdapter(s)) + monitor := serverversion.NewMonitor(s.Logger(), NewServerVersionAdapter(s)) for { select { case <-s.firstCommitInTerm.Receive(): @@ -2085,7 +2085,7 @@ func (s *EtcdServer) monitorClusterVersions() { // monitorStorageVersion every monitorVersionInterval updates storage version if needed. func (s *EtcdServer) monitorStorageVersion() { - monitor := serverversion.NewMonitor(s.Logger(), newServerVersionAdapter(s)) + monitor := serverversion.NewMonitor(s.Logger(), NewServerVersionAdapter(s)) for { select { case <-time.After(monitorVersionInterval): @@ -2175,7 +2175,7 @@ func (s *EtcdServer) updateClusterVersionV3(ver string) { // monitorDowngrade every DowngradeCheckTime checks if it's the leader and cancels downgrade if needed. func (s *EtcdServer) monitorDowngrade() { - monitor := serverversion.NewMonitor(s.Logger(), newServerVersionAdapter(s)) + monitor := serverversion.NewMonitor(s.Logger(), NewServerVersionAdapter(s)) t := s.Cfg.DowngradeCheckTime if t == 0 { return @@ -2294,5 +2294,5 @@ func (s *EtcdServer) raftStatus() raft.Status { } func (s *EtcdServer) Version() *serverversion.Manager { - return serverversion.NewManager(s.Logger(), newServerVersionAdapter(s)) + return serverversion.NewManager(s.Logger(), NewServerVersionAdapter(s)) } From d0688e0158045b773f1326a5c69a71bf89406531 Mon Sep 17 00:00:00 2001 From: ahrtr Date: Fri, 11 Mar 2022 11:09:43 +0800 Subject: [PATCH 187/258] update the example output of 'etcdctl endpoint status -w table' --- .../dev-guide/apispec/swagger/rpc.swagger.json | 2 +- api/etcdserverpb/rpc.pb.go | 2 +- api/etcdserverpb/rpc.proto | 2 +- etcdctl/README.md | 14 +++++++------- 4 files changed, 10 insertions(+), 10 deletions(-) diff --git a/Documentation/dev-guide/apispec/swagger/rpc.swagger.json b/Documentation/dev-guide/apispec/swagger/rpc.swagger.json index 35cc83fbddcb..dd12cf315cc7 100644 --- a/Documentation/dev-guide/apispec/swagger/rpc.swagger.json +++ b/Documentation/dev-guide/apispec/swagger/rpc.swagger.json @@ -2772,7 +2772,7 @@ "format": "uint64" }, "storageVersion": { - "description": "storageVersion is the version of the db file.", + "description": "storageVersion is the version of the db file. It might be get updated with delay in relationship to the target cluster version.", "type": "string" }, "version": { diff --git a/api/etcdserverpb/rpc.pb.go b/api/etcdserverpb/rpc.pb.go index 52c53f8afcb1..3ca2b50d4ba6 100644 --- a/api/etcdserverpb/rpc.pb.go +++ b/api/etcdserverpb/rpc.pb.go @@ -4236,7 +4236,7 @@ type StatusResponse struct { DbSizeInUse int64 `protobuf:"varint,9,opt,name=dbSizeInUse,proto3" json:"dbSizeInUse,omitempty"` // isLearner indicates if the member is raft learner. IsLearner bool `protobuf:"varint,10,opt,name=isLearner,proto3" json:"isLearner,omitempty"` - // storageVersion is the version of the db file. + // storageVersion is the version of the db file. It might be get updated with delay in relationship to the target cluster version. StorageVersion string `protobuf:"bytes,11,opt,name=storageVersion,proto3" json:"storageVersion,omitempty"` XXX_NoUnkeyedLiteral struct{} `json:"-"` XXX_unrecognized []byte `json:"-"` diff --git a/api/etcdserverpb/rpc.proto b/api/etcdserverpb/rpc.proto index d9eeb5c86759..9d60c0b9e5db 100644 --- a/api/etcdserverpb/rpc.proto +++ b/api/etcdserverpb/rpc.proto @@ -1158,7 +1158,7 @@ message StatusResponse { int64 dbSizeInUse = 9 [(versionpb.etcd_version_field)="3.4"]; // isLearner indicates if the member is raft learner. bool isLearner = 10 [(versionpb.etcd_version_field)="3.4"]; - // storageVersion is the version of the db file. + // storageVersion is the version of the db file. It might be get updated with delay in relationship to the target cluster version. string storageVersion = 11 [(versionpb.etcd_version_field)="3.6"]; } diff --git a/etcdctl/README.md b/etcdctl/README.md index 990a3fdcd18f..e0a11e635d0e 100644 --- a/etcdctl/README.md +++ b/etcdctl/README.md @@ -809,13 +809,13 @@ Get the status for all endpoints in the cluster associated with the default endp ```bash ./etcdctl -w table endpoint --cluster status -+------------------------+------------------+----------------+---------+-----------+-----------+------------+ -| ENDPOINT | ID | VERSION | DB SIZE | IS LEADER | RAFT TERM | RAFT INDEX | -+------------------------+------------------+----------------+---------+-----------+-----------+------------+ -| http://127.0.0.1:2379 | 8211f1d0f64f3269 | 3.2.0-rc.1+git | 25 kB | false | 2 | 8 | -| http://127.0.0.1:22379 | 91bc3c398fb3c146 | 3.2.0-rc.1+git | 25 kB | false | 2 | 8 | -| http://127.0.0.1:32379 | fd422379fda50e48 | 3.2.0-rc.1+git | 25 kB | true | 2 | 8 | -+------------------------+------------------+----------------+---------+-----------+-----------+------------+ ++------------------------+------------------+---------------+-----------------+---------+----------------+-----------+------------+-----------+------------+--------------------+--------+ +| ENDPOINT | ID | VERSION | STORAGE VERSION | DB SIZE | DB SIZE IN USE | IS LEADER | IS LEARNER | RAFT TERM | RAFT INDEX | RAFT APPLIED INDEX | ERRORS | ++------------------------+------------------+---------------+-----------------+---------+----------------+-----------+------------+-----------+------------+--------------------+--------+ +| http://127.0.0.1:2379 | 8211f1d0f64f3269 | 3.6.0-alpha.0 | 3.6.0 | 25 kB | 25 kB | false | false | 2 | 8 | 8 | | +| http://127.0.0.1:22379 | 91bc3c398fb3c146 | 3.6.0-alpha.0 | 3.6.0 | 25 kB | 25 kB | true | false | 2 | 8 | 8 | | +| http://127.0.0.1:32379 | fd422379fda50e48 | 3.6.0-alpha.0 | 3.6.0 | 25 kB | 25 kB | false | false | 2 | 8 | 8 | | ++------------------------+------------------+---------------+-----------------+---------+----------------+-----------+------------+-----------+------------+--------------------+--------+ ``` ### ENDPOINT HASHKV From 66eb3dbbdcad156c8a122940486f6ad194aa6dfe Mon Sep 17 00:00:00 2001 From: kkkkun Date: Fri, 18 Mar 2022 19:17:48 +0800 Subject: [PATCH 188/258] tests: Migrate defrag tests to common framework --- tests/common/defrag_test.go | 46 ++++++++++++++++++ tests/e2e/ctl_v3_alarm_test.go | 2 +- tests/e2e/ctl_v3_compact_test.go | 77 ------------------------------- tests/e2e/ctl_v3_defrag_test.go | 24 ++++------ tests/e2e/ctl_v3_snapshot_test.go | 3 -- tests/framework/config/client.go | 7 ++- tests/framework/e2e/etcdctl.go | 14 ++++++ tests/framework/integration.go | 16 +++++++ tests/framework/interface.go | 1 + 9 files changed, 94 insertions(+), 96 deletions(-) create mode 100644 tests/common/defrag_test.go delete mode 100644 tests/e2e/ctl_v3_compact_test.go diff --git a/tests/common/defrag_test.go b/tests/common/defrag_test.go new file mode 100644 index 000000000000..6cfce4c68070 --- /dev/null +++ b/tests/common/defrag_test.go @@ -0,0 +1,46 @@ +// Copyright 2022 The etcd Authors +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package common + +import ( + "testing" + "time" + + "go.etcd.io/etcd/tests/v3/framework/config" + "go.etcd.io/etcd/tests/v3/framework/testutils" +) + +func TestDefragOnline(t *testing.T) { + testRunner.BeforeTest(t) + options := config.DefragOption{Timeout: 10 * time.Second} + clus := testRunner.NewCluster(t, config.ClusterConfig{ClusterSize: 3}) + testutils.ExecuteWithTimeout(t, 10*time.Second, func() { + defer clus.Close() + var kvs = []testutils.KV{{Key: "key", Val: "val1"}, {Key: "key", Val: "val2"}, {Key: "key", Val: "val3"}} + for i := range kvs { + if err := clus.Client().Put(kvs[i].Key, kvs[i].Val); err != nil { + t.Fatalf("compactTest #%d: put kv error (%v)", i, err) + } + } + _, err := clus.Client().Compact(4, config.CompactOption{Physical: true, Timeout: 10 * time.Second}) + if err != nil { + t.Fatalf("defrag_test: compact with revision error (%v)", err) + } + + if err = clus.Client().Defragment(options); err != nil { + t.Fatalf("defrag_test: defrag error (%v)", err) + } + }) +} diff --git a/tests/e2e/ctl_v3_alarm_test.go b/tests/e2e/ctl_v3_alarm_test.go index f33654f000a4..b99d3a6a388e 100644 --- a/tests/e2e/ctl_v3_alarm_test.go +++ b/tests/e2e/ctl_v3_alarm_test.go @@ -21,7 +21,7 @@ import ( "testing" "time" - "go.etcd.io/etcd/client/v3" + clientv3 "go.etcd.io/etcd/client/v3" "go.etcd.io/etcd/tests/v3/framework/e2e" ) diff --git a/tests/e2e/ctl_v3_compact_test.go b/tests/e2e/ctl_v3_compact_test.go deleted file mode 100644 index f29e580d9f65..000000000000 --- a/tests/e2e/ctl_v3_compact_test.go +++ /dev/null @@ -1,77 +0,0 @@ -// Copyright 2016 The etcd Authors -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -package e2e - -import ( - "strconv" - "strings" - "testing" - - "go.etcd.io/etcd/tests/v3/framework/e2e" -) - -func TestCtlV3Compact(t *testing.T) { testCtl(t, compactTest) } -func TestCtlV3CompactPhysical(t *testing.T) { testCtl(t, compactTest, withCompactPhysical()) } - -func compactTest(cx ctlCtx) { - compactPhysical := cx.compactPhysical - if err := ctlV3Compact(cx, 2, compactPhysical); err != nil { - if !strings.Contains(err.Error(), "required revision is a future revision") { - cx.t.Fatal(err) - } - } else { - cx.t.Fatalf("expected '...future revision' error, got ") - } - - var kvs = []kv{{"key", "val1"}, {"key", "val2"}, {"key", "val3"}} - for i := range kvs { - if err := ctlV3Put(cx, kvs[i].key, kvs[i].val, ""); err != nil { - cx.t.Fatalf("compactTest #%d: ctlV3Put error (%v)", i, err) - } - } - - if err := ctlV3Get(cx, []string{"key", "--rev", "3"}, kvs[1:2]...); err != nil { - cx.t.Errorf("compactTest: ctlV3Get error (%v)", err) - } - - if err := ctlV3Compact(cx, 4, compactPhysical); err != nil { - cx.t.Fatal(err) - } - - if err := ctlV3Get(cx, []string{"key", "--rev", "3"}, kvs[1:2]...); err != nil { - if !strings.Contains(err.Error(), "required revision has been compacted") { - cx.t.Errorf("compactTest: ctlV3Get error (%v)", err) - } - } else { - cx.t.Fatalf("expected '...has been compacted' error, got ") - } - - if err := ctlV3Compact(cx, 2, compactPhysical); err != nil { - if !strings.Contains(err.Error(), "required revision has been compacted") { - cx.t.Fatal(err) - } - } else { - cx.t.Fatalf("expected '...has been compacted' error, got ") - } -} - -func ctlV3Compact(cx ctlCtx, rev int64, physical bool) error { - rs := strconv.FormatInt(rev, 10) - cmdArgs := append(cx.PrefixArgs(), "compact", rs) - if physical { - cmdArgs = append(cmdArgs, "--physical") - } - return e2e.SpawnWithExpectWithEnv(cmdArgs, cx.envMap, "compacted revision "+rs) -} diff --git a/tests/e2e/ctl_v3_defrag_test.go b/tests/e2e/ctl_v3_defrag_test.go index c47ed3f4cdfc..889bbbd078bf 100644 --- a/tests/e2e/ctl_v3_defrag_test.go +++ b/tests/e2e/ctl_v3_defrag_test.go @@ -15,13 +15,12 @@ package e2e import ( + "strconv" "testing" "go.etcd.io/etcd/tests/v3/framework/e2e" ) -func TestCtlV3DefragOnline(t *testing.T) { testCtl(t, defragOnlineTest) } - func TestCtlV3DefragOfflineEtcdutl(t *testing.T) { testCtlWithOffline(t, maintenanceInitKeys, defragOfflineTest, withEtcdutl()) } @@ -35,18 +34,6 @@ func maintenanceInitKeys(cx ctlCtx) { } } -func defragOnlineTest(cx ctlCtx) { - maintenanceInitKeys(cx) - - if err := ctlV3Compact(cx, 4, cx.compactPhysical); err != nil { - cx.t.Fatal(err) - } - - if err := ctlV3OnlineDefrag(cx); err != nil { - cx.t.Fatalf("defragTest ctlV3Defrag error (%v)", err) - } -} - func ctlV3OnlineDefrag(cx ctlCtx) error { cmdArgs := append(cx.PrefixArgs(), "defrag") lines := make([]string, cx.epc.Cfg.ClusterSize) @@ -67,3 +54,12 @@ func defragOfflineTest(cx ctlCtx) { cx.t.Fatalf("defragTest ctlV3Defrag error (%v)", err) } } + +func ctlV3Compact(cx ctlCtx, rev int64, physical bool) error { + rs := strconv.FormatInt(rev, 10) + cmdArgs := append(cx.PrefixArgs(), "compact", rs) + if physical { + cmdArgs = append(cmdArgs, "--physical") + } + return e2e.SpawnWithExpectWithEnv(cmdArgs, cx.envMap, "compacted revision "+rs) +} diff --git a/tests/e2e/ctl_v3_snapshot_test.go b/tests/e2e/ctl_v3_snapshot_test.go index 59e1dc770f27..c952b3aaed1a 100644 --- a/tests/e2e/ctl_v3_snapshot_test.go +++ b/tests/e2e/ctl_v3_snapshot_test.go @@ -294,9 +294,6 @@ func testIssue6361(t *testing.T, etcdutl bool) { // For storageVersion to be stored, all fields expected 3.6 fields need to be set. This happens after first WAL snapshot. // In this test we lower SnapshotCount to 1 to ensure WAL snapshot is triggered. -func TestCtlV3SnapshotVersion(t *testing.T) { - testCtl(t, snapshotVersionTest, withCfg(e2e.EtcdProcessClusterConfig{SnapshotCount: 1})) -} func TestCtlV3SnapshotVersionEtcdutl(t *testing.T) { testCtl(t, snapshotVersionTest, withEtcdutl(), withCfg(e2e.EtcdProcessClusterConfig{SnapshotCount: 1})) } diff --git a/tests/framework/config/client.go b/tests/framework/config/client.go index c41565b47186..6160d841da7f 100644 --- a/tests/framework/config/client.go +++ b/tests/framework/config/client.go @@ -15,8 +15,9 @@ package config import ( - clientv3 "go.etcd.io/etcd/client/v3" "time" + + clientv3 "go.etcd.io/etcd/client/v3" ) type GetOptions struct { @@ -41,3 +42,7 @@ type CompactOption struct { Physical bool Timeout time.Duration } + +type DefragOption struct { + Timeout time.Duration +} diff --git a/tests/framework/e2e/etcdctl.go b/tests/framework/e2e/etcdctl.go index 18c436748264..f11bdceadfc5 100644 --- a/tests/framework/e2e/etcdctl.go +++ b/tests/framework/e2e/etcdctl.go @@ -243,3 +243,17 @@ func (ctl *EtcdctlV3) Health() error { return SpawnWithExpects(args, map[string]string{}, lines...) } + +func (ctl *EtcdctlV3) Defragment(o config.DefragOption) error { + + args := append(ctl.cmdArgs(), "defrag") + if o.Timeout != 0 { + args = append(args, fmt.Sprintf("--command-timeout=%s", o.Timeout)) + } + lines := make([]string, len(ctl.endpoints)) + for i := range lines { + lines[i] = "Finished defragmenting etcd member" + } + _, err := SpawnWithExpectLines(args, map[string]string{}, lines...) + return err +} diff --git a/tests/framework/integration.go b/tests/framework/integration.go index 73e15f130ff0..94c1925b7c4c 100644 --- a/tests/framework/integration.go +++ b/tests/framework/integration.go @@ -196,3 +196,19 @@ func (c integrationClient) Health() error { } return nil } + +func (c integrationClient) Defragment(o config.DefragOption) error { + ctx := context.Background() + if o.Timeout != 0 { + var cancel context.CancelFunc + ctx, cancel = context.WithTimeout(ctx, o.Timeout) + defer cancel() + } + for _, ep := range c.Endpoints() { + _, err := c.Client.Defragment(ctx, ep) + if err != nil { + return err + } + } + return nil +} diff --git a/tests/framework/interface.go b/tests/framework/interface.go index f6982f321a89..db4b3b980cc3 100644 --- a/tests/framework/interface.go +++ b/tests/framework/interface.go @@ -41,4 +41,5 @@ type Client interface { Status() ([]*clientv3.StatusResponse, error) HashKV(rev int64) ([]*clientv3.HashKVResponse, error) Health() error + Defragment(opts config.DefragOption) error } From a5335847386ed5b4b729bf24c5a3b3e58f995d09 Mon Sep 17 00:00:00 2001 From: Danielle Lancashire Date: Wed, 16 Mar 2022 12:50:50 +0000 Subject: [PATCH 189/258] tests/framework: add basic lease operations --- tests/framework/config/client.go | 4 ++++ tests/framework/e2e/etcdctl.go | 36 +++++++++++++++++++++++++++++++- tests/framework/integration.go | 16 ++++++++++++++ tests/framework/interface.go | 3 ++- 4 files changed, 57 insertions(+), 2 deletions(-) diff --git a/tests/framework/config/client.go b/tests/framework/config/client.go index 6160d841da7f..c63dd5995002 100644 --- a/tests/framework/config/client.go +++ b/tests/framework/config/client.go @@ -46,3 +46,7 @@ type CompactOption struct { type DefragOption struct { Timeout time.Duration } + +type LeaseOption struct { + WithAttachedKeys bool +} diff --git a/tests/framework/e2e/etcdctl.go b/tests/framework/e2e/etcdctl.go index f11bdceadfc5..aae7a406e370 100644 --- a/tests/framework/e2e/etcdctl.go +++ b/tests/framework/e2e/etcdctl.go @@ -17,6 +17,7 @@ package e2e import ( "encoding/json" "fmt" + "strconv" "strings" clientv3 "go.etcd.io/etcd/client/v3" @@ -185,7 +186,6 @@ func (ctl *EtcdctlV3) Status() ([]*clientv3.StatusResponse, error) { if err != nil { return nil, err } - var epStatus []*struct { Endpoint string Status *clientv3.StatusResponse @@ -241,7 +241,41 @@ func (ctl *EtcdctlV3) Health() error { lines[i] = "is healthy" } return SpawnWithExpects(args, map[string]string{}, lines...) +} +func (ctl *EtcdctlV3) Grant(ttl int64) (*clientv3.LeaseGrantResponse, error) { + args := ctl.cmdArgs() + args = append(args, "lease", "grant", strconv.FormatInt(ttl, 10), "-w", "json") + cmd, err := SpawnCmd(args, nil) + if err != nil { + return nil, err + } + var resp clientv3.LeaseGrantResponse + line, err := cmd.Expect("ID") + if err != nil { + return nil, err + } + err = json.Unmarshal([]byte(line), &resp) + return &resp, err +} + +func (ctl *EtcdctlV3) TimeToLive(id clientv3.LeaseID, o config.LeaseOption) (*clientv3.LeaseTimeToLiveResponse, error) { + args := ctl.cmdArgs() + args = append(args, "lease", "timetolive", strconv.FormatInt(int64(id), 16), "-w", "json") + if o.WithAttachedKeys { + args = append(args, "--keys") + } + cmd, err := SpawnCmd(args, nil) + if err != nil { + return nil, err + } + var resp clientv3.LeaseTimeToLiveResponse + line, err := cmd.Expect("id") + if err != nil { + return nil, err + } + err = json.Unmarshal([]byte(line), &resp) + return &resp, err } func (ctl *EtcdctlV3) Defragment(o config.DefragOption) error { diff --git a/tests/framework/integration.go b/tests/framework/integration.go index 94c1925b7c4c..b0a7cd17a161 100644 --- a/tests/framework/integration.go +++ b/tests/framework/integration.go @@ -212,3 +212,19 @@ func (c integrationClient) Defragment(o config.DefragOption) error { } return nil } + +func (c integrationClient) Grant(ttl int64) (*clientv3.LeaseGrantResponse, error) { + ctx := context.Background() + return c.Client.Grant(ctx, ttl) +} + +func (c integrationClient) TimeToLive(id clientv3.LeaseID, o config.LeaseOption) (*clientv3.LeaseTimeToLiveResponse, error) { + ctx := context.Background() + + leaseOpts := []clientv3.LeaseOption{} + if o.WithAttachedKeys { + leaseOpts = append(leaseOpts, clientv3.WithAttachedKeys()) + } + + return c.Client.TimeToLive(ctx, id, leaseOpts...) +} diff --git a/tests/framework/interface.go b/tests/framework/interface.go index db4b3b980cc3..7ee691d99c74 100644 --- a/tests/framework/interface.go +++ b/tests/framework/interface.go @@ -37,9 +37,10 @@ type Client interface { Get(key string, opts config.GetOptions) (*clientv3.GetResponse, error) Delete(key string, opts config.DeleteOptions) (*clientv3.DeleteResponse, error) Compact(rev int64, opts config.CompactOption) (*clientv3.CompactResponse, error) - Status() ([]*clientv3.StatusResponse, error) HashKV(rev int64) ([]*clientv3.HashKVResponse, error) Health() error Defragment(opts config.DefragOption) error + Grant(ttl int64) (*clientv3.LeaseGrantResponse, error) + TimeToLive(id clientv3.LeaseID, opts config.LeaseOption) (*clientv3.LeaseTimeToLiveResponse, error) } From 6b7be72a4330e9ca3176c2c5401fbceac4ccf655 Mon Sep 17 00:00:00 2001 From: Danielle Lancashire Date: Wed, 16 Mar 2022 12:51:29 +0000 Subject: [PATCH 190/258] tests: migrate TestCtlV3LeaseGrantTimeToLive.* to common --- tests/common/lease_test.go | 71 ++++++++++++++++++++++++++++++++++ tests/e2e/ctl_v3_lease_test.go | 40 ------------------- 2 files changed, 71 insertions(+), 40 deletions(-) create mode 100644 tests/common/lease_test.go diff --git a/tests/common/lease_test.go b/tests/common/lease_test.go new file mode 100644 index 000000000000..df2c60a17340 --- /dev/null +++ b/tests/common/lease_test.go @@ -0,0 +1,71 @@ +// Copyright 2022 The etcd Authors +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package common + +import ( + "testing" + "time" + + "github.com/stretchr/testify/require" + "go.etcd.io/etcd/tests/v3/framework/config" + "go.etcd.io/etcd/tests/v3/framework/testutils" +) + +func TestLeaseGrantTimeToLive(t *testing.T) { + testRunner.BeforeTest(t) + + tcs := []struct { + name string + config config.ClusterConfig + }{ + { + name: "NoTLS", + config: config.ClusterConfig{ClusterSize: 1}, + }, + { + name: "PeerTLS", + config: config.ClusterConfig{ClusterSize: 3, PeerTLS: config.ManualTLS}, + }, + { + name: "PeerAutoTLS", + config: config.ClusterConfig{ClusterSize: 3, PeerTLS: config.AutoTLS}, + }, + { + name: "ClientTLS", + config: config.ClusterConfig{ClusterSize: 1, ClientTLS: config.ManualTLS}, + }, + { + name: "ClientAutoTLS", + config: config.ClusterConfig{ClusterSize: 1, ClientTLS: config.AutoTLS}, + }, + } + for _, tc := range tcs { + t.Run(tc.name, func(t *testing.T) { + clus := testRunner.NewCluster(t, tc.config) + defer clus.Close() + cc := clus.Client() + + testutils.ExecuteWithTimeout(t, 10*time.Second, func() { + ttl := int64(10) + leaseResp, err := cc.Grant(ttl) + require.NoError(t, err) + + ttlResp, err := cc.TimeToLive(leaseResp.ID, config.LeaseOption{}) + require.NoError(t, err) + require.Equal(t, ttl, ttlResp.GrantedTTL) + }) + }) + } +} diff --git a/tests/e2e/ctl_v3_lease_test.go b/tests/e2e/ctl_v3_lease_test.go index d13309bc5bdd..f1388c5a5ef2 100644 --- a/tests/e2e/ctl_v3_lease_test.go +++ b/tests/e2e/ctl_v3_lease_test.go @@ -24,20 +24,6 @@ import ( "go.etcd.io/etcd/tests/v3/framework/e2e" ) -func TestCtlV3LeaseGrantTimeToLive(t *testing.T) { testCtl(t, leaseTestGrantTimeToLive) } -func TestCtlV3LeaseGrantTimeToLiveNoTLS(t *testing.T) { - testCtl(t, leaseTestGrantTimeToLive, withCfg(*e2e.NewConfigNoTLS())) -} -func TestCtlV3LeaseGrantTimeToLiveClientTLS(t *testing.T) { - testCtl(t, leaseTestGrantTimeToLive, withCfg(*e2e.NewConfigClientTLS())) -} -func TestCtlV3LeaseGrantTimeToLiveClientAutoTLS(t *testing.T) { - testCtl(t, leaseTestGrantTimeToLive, withCfg(*e2e.NewConfigClientAutoTLS())) -} -func TestCtlV3LeaseGrantTimeToLivePeerTLS(t *testing.T) { - testCtl(t, leaseTestGrantTimeToLive, withCfg(*e2e.NewConfigPeerTLS())) -} - func TestCtlV3LeaseGrantLeases(t *testing.T) { testCtl(t, leaseTestGrantLeaseListed) } func TestCtlV3LeaseGrantLeasesNoTLS(t *testing.T) { testCtl(t, leaseTestGrantLeaseListed, withCfg(*e2e.NewConfigNoTLS())) @@ -108,32 +94,6 @@ func TestCtlV3LeaseRevokePeerTLS(t *testing.T) { testCtl(t, leaseTestRevoked, withCfg(*e2e.NewConfigPeerTLS())) } -func leaseTestGrantTimeToLive(cx ctlCtx) { - id, err := ctlV3LeaseGrant(cx, 10) - if err != nil { - cx.t.Fatalf("leaseTestGrantTimeToLive: ctlV3LeaseGrant error (%v)", err) - } - - cmdArgs := append(cx.PrefixArgs(), "lease", "timetolive", id, "--keys") - proc, err := e2e.SpawnCmd(cmdArgs, cx.envMap) - if err != nil { - cx.t.Fatalf("leaseTestGrantTimeToLive: error (%v)", err) - } - line, err := proc.Expect(" granted with TTL(") - if err != nil { - cx.t.Fatalf("leaseTestGrantTimeToLive: error (%v)", err) - } - if err = proc.Close(); err != nil { - cx.t.Fatalf("leaseTestGrantTimeToLive: error (%v)", err) - } - if !strings.Contains(line, ", attached keys") { - cx.t.Fatalf("leaseTestGrantTimeToLive: expected 'attached keys', got %q", line) - } - if !strings.Contains(line, id) { - cx.t.Fatalf("leaseTestGrantTimeToLive: expected leaseID %q, got %q", id, line) - } -} - func leaseTestGrantLeaseListed(cx ctlCtx) { err := leaseTestGrantLeasesList(cx) if err != nil { From 68e6493977ccd7ab6d7fe180e6af3748dc9fc79c Mon Sep 17 00:00:00 2001 From: Danielle Lancashire Date: Wed, 16 Mar 2022 15:00:29 +0000 Subject: [PATCH 191/258] tests/framework: add Client.LeaseList --- tests/framework/e2e/etcdctl.go | 17 ++++++++++++++++- tests/framework/integration.go | 6 ++++++ tests/framework/interface.go | 1 + 3 files changed, 23 insertions(+), 1 deletion(-) diff --git a/tests/framework/e2e/etcdctl.go b/tests/framework/e2e/etcdctl.go index aae7a406e370..f0714aeb7ff2 100644 --- a/tests/framework/e2e/etcdctl.go +++ b/tests/framework/e2e/etcdctl.go @@ -279,7 +279,6 @@ func (ctl *EtcdctlV3) TimeToLive(id clientv3.LeaseID, o config.LeaseOption) (*cl } func (ctl *EtcdctlV3) Defragment(o config.DefragOption) error { - args := append(ctl.cmdArgs(), "defrag") if o.Timeout != 0 { args = append(args, fmt.Sprintf("--command-timeout=%s", o.Timeout)) @@ -291,3 +290,19 @@ func (ctl *EtcdctlV3) Defragment(o config.DefragOption) error { _, err := SpawnWithExpectLines(args, map[string]string{}, lines...) return err } + +func (ctl *EtcdctlV3) LeaseList() (*clientv3.LeaseLeasesResponse, error) { + args := ctl.cmdArgs() + args = append(args, "lease", "list", "-w", "json") + cmd, err := SpawnCmd(args, nil) + if err != nil { + return nil, err + } + var resp clientv3.LeaseLeasesResponse + line, err := cmd.Expect("id") + if err != nil { + return nil, err + } + err = json.Unmarshal([]byte(line), &resp) + return &resp, err +} diff --git a/tests/framework/integration.go b/tests/framework/integration.go index b0a7cd17a161..6a5eac295bbb 100644 --- a/tests/framework/integration.go +++ b/tests/framework/integration.go @@ -228,3 +228,9 @@ func (c integrationClient) TimeToLive(id clientv3.LeaseID, o config.LeaseOption) return c.Client.TimeToLive(ctx, id, leaseOpts...) } + +func (c integrationClient) LeaseList() (*clientv3.LeaseLeasesResponse, error) { + ctx := context.Background() + + return c.Client.Leases(ctx) +} diff --git a/tests/framework/interface.go b/tests/framework/interface.go index 7ee691d99c74..c4fa9bda1c6c 100644 --- a/tests/framework/interface.go +++ b/tests/framework/interface.go @@ -43,4 +43,5 @@ type Client interface { Defragment(opts config.DefragOption) error Grant(ttl int64) (*clientv3.LeaseGrantResponse, error) TimeToLive(id clientv3.LeaseID, opts config.LeaseOption) (*clientv3.LeaseTimeToLiveResponse, error) + LeaseList() (*clientv3.LeaseLeasesResponse, error) } From b7beaf9c62e5472b7168a0a565af289f73a143f2 Mon Sep 17 00:00:00 2001 From: Danielle Lancashire Date: Wed, 16 Mar 2022 15:03:36 +0000 Subject: [PATCH 192/258] tests: migrate TestCtlV3LeaseGrantLeases.* to common --- tests/common/lease_test.go | 78 ++++++++++++++++++++++++++++++++++ tests/e2e/ctl_v3_auth_test.go | 18 ++++++++ tests/e2e/ctl_v3_lease_test.go | 39 ----------------- 3 files changed, 96 insertions(+), 39 deletions(-) diff --git a/tests/common/lease_test.go b/tests/common/lease_test.go index df2c60a17340..5676fbf24789 100644 --- a/tests/common/lease_test.go +++ b/tests/common/lease_test.go @@ -19,6 +19,7 @@ import ( "time" "github.com/stretchr/testify/require" + clientv3 "go.etcd.io/etcd/client/v3" "go.etcd.io/etcd/tests/v3/framework/config" "go.etcd.io/etcd/tests/v3/framework/testutils" ) @@ -69,3 +70,80 @@ func TestLeaseGrantTimeToLive(t *testing.T) { }) } } + +func TestLeaseGrantAndList(t *testing.T) { + testRunner.BeforeTest(t) + + tcs := []struct { + name string + config config.ClusterConfig + }{ + { + name: "NoTLS", + config: config.ClusterConfig{ClusterSize: 1}, + }, + { + name: "PeerTLS", + config: config.ClusterConfig{ClusterSize: 3, PeerTLS: config.ManualTLS}, + }, + { + name: "PeerAutoTLS", + config: config.ClusterConfig{ClusterSize: 3, PeerTLS: config.AutoTLS}, + }, + { + name: "ClientTLS", + config: config.ClusterConfig{ClusterSize: 1, ClientTLS: config.ManualTLS}, + }, + { + name: "ClientAutoTLS", + config: config.ClusterConfig{ClusterSize: 1, ClientTLS: config.AutoTLS}, + }, + } + for _, tc := range tcs { + nestedCases := []struct { + name string + leaseCount int + }{ + { + name: "no_leases", + leaseCount: 0, + }, + { + name: "one_lease", + leaseCount: 1, + }, + { + name: "many_leases", + leaseCount: 3, + }, + } + + for _, nc := range nestedCases { + t.Run(tc.name+"/"+nc.name, func(t *testing.T) { + clus := testRunner.NewCluster(t, tc.config) + defer clus.Close() + cc := clus.Client() + + testutils.ExecuteWithTimeout(t, 10*time.Second, func() { + createdLeases := []clientv3.LeaseID{} + for i := 0; i < nc.leaseCount; i++ { + leaseResp, err := cc.Grant(10) + require.NoError(t, err) + createdLeases = append(createdLeases, leaseResp.ID) + } + + resp, err := cc.LeaseList() + require.NoError(t, err) + require.Len(t, resp.Leases, nc.leaseCount) + + returnedLeases := make([]clientv3.LeaseID, 0, nc.leaseCount) + for _, status := range resp.Leases { + returnedLeases = append(returnedLeases, status.ID) + } + + require.ElementsMatch(t, createdLeases, returnedLeases) + }) + }) + } + } +} diff --git a/tests/e2e/ctl_v3_auth_test.go b/tests/e2e/ctl_v3_auth_test.go index fd15a9e617ec..8fd64097200f 100644 --- a/tests/e2e/ctl_v3_auth_test.go +++ b/tests/e2e/ctl_v3_auth_test.go @@ -862,6 +862,24 @@ func authLeaseTestLeaseGrantLeases(cx ctlCtx) { } } +func leaseTestGrantLeasesList(cx ctlCtx) error { + id, err := ctlV3LeaseGrant(cx, 10) + if err != nil { + return fmt.Errorf("ctlV3LeaseGrant error (%v)", err) + } + + cmdArgs := append(cx.PrefixArgs(), "lease", "list") + proc, err := e2e.SpawnCmd(cmdArgs, cx.envMap) + if err != nil { + return fmt.Errorf("lease list failed (%v)", err) + } + _, err = proc.Expect(id) + if err != nil { + return fmt.Errorf("lease id not in returned list (%v)", err) + } + return proc.Close() +} + func authLeaseTestLeaseRevoke(cx ctlCtx) { cx.user, cx.pass = "root", "root" authSetupTestUser(cx) diff --git a/tests/e2e/ctl_v3_lease_test.go b/tests/e2e/ctl_v3_lease_test.go index f1388c5a5ef2..4772ef2159c6 100644 --- a/tests/e2e/ctl_v3_lease_test.go +++ b/tests/e2e/ctl_v3_lease_test.go @@ -24,20 +24,6 @@ import ( "go.etcd.io/etcd/tests/v3/framework/e2e" ) -func TestCtlV3LeaseGrantLeases(t *testing.T) { testCtl(t, leaseTestGrantLeaseListed) } -func TestCtlV3LeaseGrantLeasesNoTLS(t *testing.T) { - testCtl(t, leaseTestGrantLeaseListed, withCfg(*e2e.NewConfigNoTLS())) -} -func TestCtlV3LeaseGrantLeasesClientTLS(t *testing.T) { - testCtl(t, leaseTestGrantLeaseListed, withCfg(*e2e.NewConfigClientTLS())) -} -func TestCtlV3LeaseGrantLeasesClientAutoTLS(t *testing.T) { - testCtl(t, leaseTestGrantLeaseListed, withCfg(*e2e.NewConfigClientAutoTLS())) -} -func TestCtlV3LeaseGrantLeasesPeerTLS(t *testing.T) { - testCtl(t, leaseTestGrantLeaseListed, withCfg(*e2e.NewConfigPeerTLS())) -} - func TestCtlV3LeaseTestTimeToLiveExpired(t *testing.T) { testCtl(t, leaseTestTimeToLiveExpired) } func TestCtlV3LeaseTestTimeToLiveExpiredNoTLS(t *testing.T) { testCtl(t, leaseTestTimeToLiveExpired, withCfg(*e2e.NewConfigNoTLS())) @@ -94,31 +80,6 @@ func TestCtlV3LeaseRevokePeerTLS(t *testing.T) { testCtl(t, leaseTestRevoked, withCfg(*e2e.NewConfigPeerTLS())) } -func leaseTestGrantLeaseListed(cx ctlCtx) { - err := leaseTestGrantLeasesList(cx) - if err != nil { - cx.t.Fatalf("leaseTestGrantLeasesList: (%v)", err) - } -} - -func leaseTestGrantLeasesList(cx ctlCtx) error { - id, err := ctlV3LeaseGrant(cx, 10) - if err != nil { - return fmt.Errorf("ctlV3LeaseGrant error (%v)", err) - } - - cmdArgs := append(cx.PrefixArgs(), "lease", "list") - proc, err := e2e.SpawnCmd(cmdArgs, cx.envMap) - if err != nil { - return fmt.Errorf("lease list failed (%v)", err) - } - _, err = proc.Expect(id) - if err != nil { - return fmt.Errorf("lease id not in returned list (%v)", err) - } - return proc.Close() -} - func leaseTestTimeToLiveExpired(cx ctlCtx) { err := leaseTestTimeToLiveExpire(cx, 3) if err != nil { From dca5874d4402ca5660d8a8bc2b63dbdda473727a Mon Sep 17 00:00:00 2001 From: nic-chen Date: Sat, 19 Mar 2022 00:46:42 +0800 Subject: [PATCH 193/258] tests: Migrate key value Get to common framework --- tests/common/alarm_test.go | 93 +++++++++++++++++++++++++++++++ tests/framework/config/cluster.go | 7 ++- tests/framework/e2e/etcdctl.go | 6 ++ tests/framework/integration.go | 9 +++ tests/framework/interface.go | 2 +- 5 files changed, 113 insertions(+), 4 deletions(-) create mode 100644 tests/common/alarm_test.go diff --git a/tests/common/alarm_test.go b/tests/common/alarm_test.go new file mode 100644 index 000000000000..1d5708663438 --- /dev/null +++ b/tests/common/alarm_test.go @@ -0,0 +1,93 @@ +// Copyright 2022 The etcd Authors +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package common + +import ( + "os" + "strings" + "testing" + "time" + + "go.etcd.io/etcd/tests/v3/framework/config" +) + +func TestAlarm(t *testing.T) { + testRunner.BeforeTest(t) + + clus := testRunner.NewCluster(t, config.ClusterConfig{ClusterSize: 3, QuotaBackendBytes: int64(13 * os.Getpagesize())}) + defer clus.Close() + + // test small put still works + smallbuf := strings.Repeat("a", 64) + if err := clus.Client().Put("1st_test", smallbuf); err != nil { + t.Fatalf("alarmTest: put kv error (%v)", err) + } + + // write some chunks to fill up the database + buf := strings.Repeat("b", os.Getpagesize()) + for { + if err := clus.Client().Put("2nd_test", buf); err != nil { + if !strings.Contains(err.Error(), "etcdserver: mvcc: database space exceeded") { + t.Fatal(err) + } + break + } + } + + // quota alarm should now be on + _, err := clus.Client().Alarm("list") + if err != nil { + t.Fatalf("alarmTest: Alarm error (%v)", err) + } + + // endpoint should not healthy + if err := clus.Client().Health(); err == nil { + t.Fatalf("endpoint should not healthy") + } + + // check that Put is rejected when alarm is on + if err := clus.Client().Put("3rd_test", smallbuf); err != nil { + if !strings.Contains(err.Error(), "etcdserver: mvcc: database space exceeded") { + t.Fatal(err) + } + } + + // get latest revision to compact + sresp, err := clus.Client().Status() + if err != nil { + t.Fatalf("get endpoint status error: %v", err) + } + + // make some space + _, err = clus.Client().Compact(sresp[0].Header.Revision, config.CompactOption{Physical: true, Timeout: 10 * time.Second}) + if err != nil { + t.Fatalf("alarmTest: Compact error (%v)", err) + } + + if err = clus.Client().Defragment(config.DefragOption{Timeout: 10 * time.Second}); err != nil { + t.Fatalf("alarmTest: defrag error (%v)", err) + } + + // turn off alarm + _, err = clus.Client().Alarm("disarm") + if err != nil { + t.Fatalf("alarmTest: Alarm error (%v)", err) + } + + // put one more key below quota + if err := clus.Client().Put("4th_test", smallbuf); err != nil { + t.Fatal(err) + } +} diff --git a/tests/framework/config/cluster.go b/tests/framework/config/cluster.go index c9deab294ebe..f18c6e5c4061 100644 --- a/tests/framework/config/cluster.go +++ b/tests/framework/config/cluster.go @@ -23,7 +23,8 @@ const ( ) type ClusterConfig struct { - ClusterSize int - PeerTLS TLSConfig - ClientTLS TLSConfig + ClusterSize int + PeerTLS TLSConfig + ClientTLS TLSConfig + QuotaBackendBytes int64 } diff --git a/tests/framework/e2e/etcdctl.go b/tests/framework/e2e/etcdctl.go index f11bdceadfc5..3f0fb87a7b35 100644 --- a/tests/framework/e2e/etcdctl.go +++ b/tests/framework/e2e/etcdctl.go @@ -241,7 +241,13 @@ func (ctl *EtcdctlV3) Health() error { lines[i] = "is healthy" } return SpawnWithExpects(args, map[string]string{}, lines...) +} + +func (ctl *EtcdctlV3) Alarm(cmd string) (*clientv3.AlarmResponse, error) { + args := ctl.cmdArgs() + args = append(args, "alarm", cmd) + return nil, SpawnWithExpect(args, "alarm:NOSPACE") } func (ctl *EtcdctlV3) Defragment(o config.DefragOption) error { diff --git a/tests/framework/integration.go b/tests/framework/integration.go index 94c1925b7c4c..e674de78511d 100644 --- a/tests/framework/integration.go +++ b/tests/framework/integration.go @@ -45,6 +45,7 @@ func (e integrationRunner) NewCluster(t testing.TB, cfg config.ClusterConfig) Cl var integrationCfg integration.ClusterConfig integrationCfg.Size = cfg.ClusterSize integrationCfg.ClientTLS, err = tlsInfo(t, cfg.ClientTLS) + integrationCfg.QuotaBackendBytes = cfg.QuotaBackendBytes if err != nil { t.Fatalf("ClientTLS: %s", err) } @@ -159,6 +160,14 @@ func (c integrationClient) Compact(rev int64, o config.CompactOption) (*clientv3 return c.Client.Compact(ctx, rev, clientOpts...) } +func (c integrationClient) Alarm(cmd string) (*clientv3.AlarmResponse, error) { + ctx := context.Background() + if cmd == "list" { + return c.Client.AlarmList(ctx) + } + return c.Client.AlarmDisarm(ctx, nil) +} + func (c integrationClient) Status() ([]*clientv3.StatusResponse, error) { endpoints := c.Client.Endpoints() var resp []*clientv3.StatusResponse diff --git a/tests/framework/interface.go b/tests/framework/interface.go index db4b3b980cc3..9b1b424f695e 100644 --- a/tests/framework/interface.go +++ b/tests/framework/interface.go @@ -37,9 +37,9 @@ type Client interface { Get(key string, opts config.GetOptions) (*clientv3.GetResponse, error) Delete(key string, opts config.DeleteOptions) (*clientv3.DeleteResponse, error) Compact(rev int64, opts config.CompactOption) (*clientv3.CompactResponse, error) - Status() ([]*clientv3.StatusResponse, error) HashKV(rev int64) ([]*clientv3.HashKVResponse, error) Health() error Defragment(opts config.DefragOption) error + Alarm(cmd string) (*clientv3.AlarmResponse, error) } From b50f10299b6f9aa9cef2ba5cf2dedd7fcb390841 Mon Sep 17 00:00:00 2001 From: Danielle Lancashire Date: Wed, 16 Mar 2022 15:26:08 +0000 Subject: [PATCH 194/258] tests/framework: Add PutOptions Put can take a leaseid to associate a value with a lease. This adds the ability for tests to make use of this. --- tests/common/compact_test.go | 2 +- tests/common/defrag_test.go | 2 +- tests/common/kv_test.go | 6 +++--- tests/e2e/ctl_v3_grpc_test.go | 3 ++- tests/framework/config/client.go | 4 ++++ tests/framework/e2e/etcdctl.go | 9 +++++++-- tests/framework/integration.go | 8 ++++++-- tests/framework/interface.go | 2 +- 8 files changed, 25 insertions(+), 11 deletions(-) diff --git a/tests/common/compact_test.go b/tests/common/compact_test.go index 8effa94e1277..d21d206aac3a 100644 --- a/tests/common/compact_test.go +++ b/tests/common/compact_test.go @@ -47,7 +47,7 @@ func TestCompact(t *testing.T) { testutils.ExecuteWithTimeout(t, 10*time.Second, func() { var kvs = []testutils.KV{{Key: "key", Val: "val1"}, {Key: "key", Val: "val2"}, {Key: "key", Val: "val3"}} for i := range kvs { - if err := clus.Client().Put(kvs[i].Key, kvs[i].Val); err != nil { + if err := clus.Client().Put(kvs[i].Key, kvs[i].Val, config.PutOptions{}); err != nil { t.Fatalf("compactTest #%d: put kv error (%v)", i, err) } } diff --git a/tests/common/defrag_test.go b/tests/common/defrag_test.go index 6cfce4c68070..2c7db2b7cd1a 100644 --- a/tests/common/defrag_test.go +++ b/tests/common/defrag_test.go @@ -30,7 +30,7 @@ func TestDefragOnline(t *testing.T) { defer clus.Close() var kvs = []testutils.KV{{Key: "key", Val: "val1"}, {Key: "key", Val: "val2"}, {Key: "key", Val: "val3"}} for i := range kvs { - if err := clus.Client().Put(kvs[i].Key, kvs[i].Val); err != nil { + if err := clus.Client().Put(kvs[i].Key, kvs[i].Val, config.PutOptions{}); err != nil { t.Fatalf("compactTest #%d: put kv error (%v)", i, err) } } diff --git a/tests/common/kv_test.go b/tests/common/kv_test.go index 2a4eccacc913..6f5849ee9599 100644 --- a/tests/common/kv_test.go +++ b/tests/common/kv_test.go @@ -60,7 +60,7 @@ func TestKVPut(t *testing.T) { testutils.ExecuteWithTimeout(t, 10*time.Second, func() { key, value := "foo", "bar" - if err := cc.Put(key, value); err != nil { + if err := cc.Put(key, value, config.PutOptions{}); err != nil { t.Fatalf("count not put key %q, err: %s", key, err) } resp, err := cc.Get(key, config.GetOptions{Serializable: true}) @@ -123,7 +123,7 @@ func TestKVGet(t *testing.T) { ) for i := range kvs { - if err := cc.Put(kvs[i], "bar"); err != nil { + if err := cc.Put(kvs[i], "bar", config.PutOptions{}); err != nil { t.Fatalf("count not put key %q, err: %s", kvs[i], err) } } @@ -246,7 +246,7 @@ func TestKVDelete(t *testing.T) { } for _, tt := range tests { for i := range kvs { - if err := cc.Put(kvs[i], "bar"); err != nil { + if err := cc.Put(kvs[i], "bar", config.PutOptions{}); err != nil { t.Fatalf("count not put key %q, err: %s", kvs[i], err) } } diff --git a/tests/e2e/ctl_v3_grpc_test.go b/tests/e2e/ctl_v3_grpc_test.go index 8c8be2c698ef..878dd7948285 100644 --- a/tests/e2e/ctl_v3_grpc_test.go +++ b/tests/e2e/ctl_v3_grpc_test.go @@ -24,6 +24,7 @@ import ( "time" "github.com/stretchr/testify/assert" + "go.etcd.io/etcd/tests/v3/framework/config" "go.etcd.io/etcd/tests/v3/framework/e2e" "go.etcd.io/etcd/tests/v3/framework/testutils" ) @@ -100,7 +101,7 @@ func TestAuthority(t *testing.T) { endpoints := templateEndpoints(t, tc.clientURLPattern, epc) client := e2e.NewEtcdctl(cfg, endpoints) - err = client.Put("foo", "bar") + err = client.Put("foo", "bar", config.PutOptions{}) if err != nil { t.Fatal(err) } diff --git a/tests/framework/config/client.go b/tests/framework/config/client.go index c63dd5995002..ef2ef9c273c0 100644 --- a/tests/framework/config/client.go +++ b/tests/framework/config/client.go @@ -32,6 +32,10 @@ type GetOptions struct { SortBy clientv3.SortTarget } +type PutOptions struct { + LeaseID clientv3.LeaseID +} + type DeleteOptions struct { Prefix bool FromKey bool diff --git a/tests/framework/e2e/etcdctl.go b/tests/framework/e2e/etcdctl.go index f0714aeb7ff2..2d30a83e0562 100644 --- a/tests/framework/e2e/etcdctl.go +++ b/tests/framework/e2e/etcdctl.go @@ -107,8 +107,13 @@ func (ctl *EtcdctlV3) Get(key string, o config.GetOptions) (*clientv3.GetRespons return &resp, err } -func (ctl *EtcdctlV3) Put(key, value string) error { - return SpawnWithExpect(ctl.cmdArgs("put", key, value), "OK") +func (ctl *EtcdctlV3) Put(key, value string, opts config.PutOptions) error { + args := ctl.cmdArgs() + args = append(args, "put", key, value) + if opts.LeaseID != 0 { + args = append(args, "--lease", strconv.FormatInt(int64(opts.LeaseID), 16)) + } + return SpawnWithExpect(args, "OK") } func (ctl *EtcdctlV3) Delete(key string, o config.DeleteOptions) (*clientv3.DeleteResponse, error) { diff --git a/tests/framework/integration.go b/tests/framework/integration.go index 6a5eac295bbb..3c4cf2567669 100644 --- a/tests/framework/integration.go +++ b/tests/framework/integration.go @@ -126,8 +126,12 @@ func (c integrationClient) Get(key string, o config.GetOptions) (*clientv3.GetRe return c.Client.Get(context.Background(), key, clientOpts...) } -func (c integrationClient) Put(key, value string) error { - _, err := c.Client.Put(context.Background(), key, value) +func (c integrationClient) Put(key, value string, opts config.PutOptions) error { + clientOpts := []clientv3.OpOption{} + if opts.LeaseID != 0 { + clientOpts = append(clientOpts, clientv3.WithLease(opts.LeaseID)) + } + _, err := c.Client.Put(context.Background(), key, value, clientOpts...) return err } diff --git a/tests/framework/interface.go b/tests/framework/interface.go index c4fa9bda1c6c..08ead6a80def 100644 --- a/tests/framework/interface.go +++ b/tests/framework/interface.go @@ -33,7 +33,7 @@ type Cluster interface { } type Client interface { - Put(key, value string) error + Put(key, value string, opts config.PutOptions) error Get(key string, opts config.GetOptions) (*clientv3.GetResponse, error) Delete(key string, opts config.DeleteOptions) (*clientv3.DeleteResponse, error) Compact(rev int64, opts config.CompactOption) (*clientv3.CompactResponse, error) From c12e03c8e64837eecf048b27dd7fcc9c4a8f7c89 Mon Sep 17 00:00:00 2001 From: Danielle Lancashire Date: Wed, 16 Mar 2022 15:27:51 +0000 Subject: [PATCH 195/258] tests: migrate TestCtlV3LeaseTestTimeToLiveExpired.* to common --- tests/common/lease_test.go | 60 ++++++++++++++++++++++++++++++++++ tests/e2e/ctl_v3_auth_test.go | 22 +++++++++++++ tests/e2e/ctl_v3_lease_test.go | 44 ------------------------- 3 files changed, 82 insertions(+), 44 deletions(-) diff --git a/tests/common/lease_test.go b/tests/common/lease_test.go index 5676fbf24789..caeabf7da0bf 100644 --- a/tests/common/lease_test.go +++ b/tests/common/lease_test.go @@ -147,3 +147,63 @@ func TestLeaseGrantAndList(t *testing.T) { } } } + +func TestLeaseGrantTimeToLiveExpired(t *testing.T) { + testRunner.BeforeTest(t) + + tcs := []struct { + name string + config config.ClusterConfig + }{ + { + name: "NoTLS", + config: config.ClusterConfig{ClusterSize: 1}, + }, + { + name: "PeerTLS", + config: config.ClusterConfig{ClusterSize: 3, PeerTLS: config.ManualTLS}, + }, + { + name: "PeerAutoTLS", + config: config.ClusterConfig{ClusterSize: 3, PeerTLS: config.AutoTLS}, + }, + { + name: "ClientTLS", + config: config.ClusterConfig{ClusterSize: 1, ClientTLS: config.ManualTLS}, + }, + { + name: "ClientAutoTLS", + config: config.ClusterConfig{ClusterSize: 1, ClientTLS: config.AutoTLS}, + }, + } + for _, tc := range tcs { + t.Run(tc.name, func(t *testing.T) { + clus := testRunner.NewCluster(t, tc.config) + defer clus.Close() + cc := clus.Client() + + testutils.ExecuteWithTimeout(t, 10*time.Second, func() { + leaseResp, err := cc.Grant(2) + require.NoError(t, err) + + err = cc.Put("foo", "bar", config.PutOptions{LeaseID: leaseResp.ID}) + require.NoError(t, err) + + getResp, err := cc.Get("foo", config.GetOptions{}) + require.NoError(t, err) + require.Equal(t, int64(1), getResp.Count) + + time.Sleep(3 * time.Second) + + ttlResp, err := cc.TimeToLive(leaseResp.ID, config.LeaseOption{}) + require.NoError(t, err) + require.Equal(t, int64(-1), ttlResp.TTL) + + getResp, err = cc.Get("foo", config.GetOptions{}) + require.NoError(t, err) + // Value should expire with the lease + require.Equal(t, int64(0), getResp.Count) + }) + }) + } +} diff --git a/tests/e2e/ctl_v3_auth_test.go b/tests/e2e/ctl_v3_auth_test.go index 8fd64097200f..6c75f5b06347 100644 --- a/tests/e2e/ctl_v3_auth_test.go +++ b/tests/e2e/ctl_v3_auth_test.go @@ -853,6 +853,28 @@ func authLeaseTestTimeToLiveExpired(cx ctlCtx) { } } +func leaseTestTimeToLiveExpire(cx ctlCtx, ttl int) error { + leaseID, err := ctlV3LeaseGrant(cx, ttl) + if err != nil { + return fmt.Errorf("ctlV3LeaseGrant error (%v)", err) + } + + if err = ctlV3Put(cx, "key", "val", leaseID); err != nil { + return fmt.Errorf("ctlV3Put error (%v)", err) + } + // eliminate false positive + time.Sleep(time.Duration(ttl+1) * time.Second) + cmdArgs := append(cx.PrefixArgs(), "lease", "timetolive", leaseID) + exp := fmt.Sprintf("lease %s already expired", leaseID) + if err = e2e.SpawnWithExpectWithEnv(cmdArgs, cx.envMap, exp); err != nil { + return fmt.Errorf("lease not properly expired: (%v)", err) + } + if err := ctlV3Get(cx, []string{"key"}); err != nil { + return fmt.Errorf("ctlV3Get error (%v)", err) + } + return nil +} + func authLeaseTestLeaseGrantLeases(cx ctlCtx) { cx.user, cx.pass = "root", "root" authSetupTestUser(cx) diff --git a/tests/e2e/ctl_v3_lease_test.go b/tests/e2e/ctl_v3_lease_test.go index 4772ef2159c6..0c1173cd2763 100644 --- a/tests/e2e/ctl_v3_lease_test.go +++ b/tests/e2e/ctl_v3_lease_test.go @@ -19,25 +19,10 @@ import ( "strconv" "strings" "testing" - "time" "go.etcd.io/etcd/tests/v3/framework/e2e" ) -func TestCtlV3LeaseTestTimeToLiveExpired(t *testing.T) { testCtl(t, leaseTestTimeToLiveExpired) } -func TestCtlV3LeaseTestTimeToLiveExpiredNoTLS(t *testing.T) { - testCtl(t, leaseTestTimeToLiveExpired, withCfg(*e2e.NewConfigNoTLS())) -} -func TestCtlV3LeaseTestTimeToLiveExpiredClientTLS(t *testing.T) { - testCtl(t, leaseTestTimeToLiveExpired, withCfg(*e2e.NewConfigClientTLS())) -} -func TestCtlV3LeaseTestTimeToLiveExpiredClientAutoTLS(t *testing.T) { - testCtl(t, leaseTestTimeToLiveExpired, withCfg(*e2e.NewConfigClientAutoTLS())) -} -func TestCtlV3LeaseTestTimeToLiveExpiredPeerTLS(t *testing.T) { - testCtl(t, leaseTestTimeToLiveExpired, withCfg(*e2e.NewConfigPeerTLS())) -} - func TestCtlV3LeaseKeepAlive(t *testing.T) { testCtl(t, leaseTestKeepAlive) } func TestCtlV3LeaseKeepAliveNoTLS(t *testing.T) { testCtl(t, leaseTestKeepAlive, withCfg(*e2e.NewConfigNoTLS())) @@ -80,35 +65,6 @@ func TestCtlV3LeaseRevokePeerTLS(t *testing.T) { testCtl(t, leaseTestRevoked, withCfg(*e2e.NewConfigPeerTLS())) } -func leaseTestTimeToLiveExpired(cx ctlCtx) { - err := leaseTestTimeToLiveExpire(cx, 3) - if err != nil { - cx.t.Fatalf("leaseTestTimeToLiveExpire: (%v)", err) - } -} - -func leaseTestTimeToLiveExpire(cx ctlCtx, ttl int) error { - leaseID, err := ctlV3LeaseGrant(cx, ttl) - if err != nil { - return fmt.Errorf("ctlV3LeaseGrant error (%v)", err) - } - - if err = ctlV3Put(cx, "key", "val", leaseID); err != nil { - return fmt.Errorf("ctlV3Put error (%v)", err) - } - // eliminate false positive - time.Sleep(time.Duration(ttl+1) * time.Second) - cmdArgs := append(cx.PrefixArgs(), "lease", "timetolive", leaseID) - exp := fmt.Sprintf("lease %s already expired", leaseID) - if err = e2e.SpawnWithExpectWithEnv(cmdArgs, cx.envMap, exp); err != nil { - return fmt.Errorf("lease not properly expired: (%v)", err) - } - if err := ctlV3Get(cx, []string{"key"}); err != nil { - return fmt.Errorf("ctlV3Get error (%v)", err) - } - return nil -} - func leaseTestKeepAlive(cx ctlCtx) { // put with TTL 10 seconds and keep-alive leaseID, err := ctlV3LeaseGrant(cx, 10) From 353b011f5943cdeb1e427f77972dd55e7b187e75 Mon Sep 17 00:00:00 2001 From: Danielle Lancashire Date: Wed, 16 Mar 2022 16:00:05 +0000 Subject: [PATCH 196/258] tests/framework: Add Client.LeaseKeepAliveOnce --- tests/framework/e2e/etcdctl.go | 16 ++++++++++++++++ tests/framework/integration.go | 6 ++++++ tests/framework/interface.go | 1 + 3 files changed, 23 insertions(+) diff --git a/tests/framework/e2e/etcdctl.go b/tests/framework/e2e/etcdctl.go index 2d30a83e0562..aa315ddf0fa0 100644 --- a/tests/framework/e2e/etcdctl.go +++ b/tests/framework/e2e/etcdctl.go @@ -311,3 +311,19 @@ func (ctl *EtcdctlV3) LeaseList() (*clientv3.LeaseLeasesResponse, error) { err = json.Unmarshal([]byte(line), &resp) return &resp, err } + +func (ctl *EtcdctlV3) LeaseKeepAliveOnce(id clientv3.LeaseID) (*clientv3.LeaseKeepAliveResponse, error) { + args := ctl.cmdArgs() + args = append(args, "lease", "keep-alive", strconv.FormatInt(int64(id), 16), "--once", "-w", "json") + cmd, err := SpawnCmd(args, nil) + if err != nil { + return nil, err + } + var resp clientv3.LeaseKeepAliveResponse + line, err := cmd.Expect("ID") + if err != nil { + return nil, err + } + err = json.Unmarshal([]byte(line), &resp) + return &resp, err +} diff --git a/tests/framework/integration.go b/tests/framework/integration.go index 3c4cf2567669..e5c8c01a445b 100644 --- a/tests/framework/integration.go +++ b/tests/framework/integration.go @@ -238,3 +238,9 @@ func (c integrationClient) LeaseList() (*clientv3.LeaseLeasesResponse, error) { return c.Client.Leases(ctx) } + +func (c integrationClient) LeaseKeepAliveOnce(id clientv3.LeaseID) (*clientv3.LeaseKeepAliveResponse, error) { + ctx := context.Background() + + return c.Client.KeepAliveOnce(ctx, id) +} diff --git a/tests/framework/interface.go b/tests/framework/interface.go index 08ead6a80def..ca7fb18decd8 100644 --- a/tests/framework/interface.go +++ b/tests/framework/interface.go @@ -44,4 +44,5 @@ type Client interface { Grant(ttl int64) (*clientv3.LeaseGrantResponse, error) TimeToLive(id clientv3.LeaseID, opts config.LeaseOption) (*clientv3.LeaseTimeToLiveResponse, error) LeaseList() (*clientv3.LeaseLeasesResponse, error) + LeaseKeepAliveOnce(id clientv3.LeaseID) (*clientv3.LeaseKeepAliveResponse, error) } From 36279e0797dbd2df4d658c20caceb4c2746e293e Mon Sep 17 00:00:00 2001 From: Danielle Lancashire Date: Wed, 16 Mar 2022 16:00:44 +0000 Subject: [PATCH 197/258] tests: migrate TestCtlV3LeaseKeepAliveOnce.* to common --- tests/common/lease_test.go | 52 ++++++++++++++++++++++++++++++++++ tests/e2e/ctl_v3_lease_test.go | 45 ----------------------------- 2 files changed, 52 insertions(+), 45 deletions(-) diff --git a/tests/common/lease_test.go b/tests/common/lease_test.go index caeabf7da0bf..98e382cebedd 100644 --- a/tests/common/lease_test.go +++ b/tests/common/lease_test.go @@ -207,3 +207,55 @@ func TestLeaseGrantTimeToLiveExpired(t *testing.T) { }) } } + +func TestLeaseGrantKeepAliveOnce(t *testing.T) { + testRunner.BeforeTest(t) + + tcs := []struct { + name string + config config.ClusterConfig + }{ + { + name: "NoTLS", + config: config.ClusterConfig{ClusterSize: 1}, + }, + { + name: "PeerTLS", + config: config.ClusterConfig{ClusterSize: 3, PeerTLS: config.ManualTLS}, + }, + { + name: "PeerAutoTLS", + config: config.ClusterConfig{ClusterSize: 3, PeerTLS: config.AutoTLS}, + }, + { + name: "ClientTLS", + config: config.ClusterConfig{ClusterSize: 1, ClientTLS: config.ManualTLS}, + }, + { + name: "ClientAutoTLS", + config: config.ClusterConfig{ClusterSize: 1, ClientTLS: config.AutoTLS}, + }, + } + for _, tc := range tcs { + t.Run(tc.name, func(t *testing.T) { + clus := testRunner.NewCluster(t, tc.config) + defer clus.Close() + cc := clus.Client() + + testutils.ExecuteWithTimeout(t, 10*time.Second, func() { + leaseResp, err := cc.Grant(2) + require.NoError(t, err) + + _, err = cc.LeaseKeepAliveOnce(leaseResp.ID) + require.NoError(t, err) + + time.Sleep(2 * time.Second) // Wait for the original lease to expire + + ttlResp, err := cc.TimeToLive(leaseResp.ID, config.LeaseOption{}) + require.NoError(t, err) + // We still have a lease! + require.Greater(t, int64(2), ttlResp.TTL) + }) + }) + } +} diff --git a/tests/e2e/ctl_v3_lease_test.go b/tests/e2e/ctl_v3_lease_test.go index 0c1173cd2763..905351c934ef 100644 --- a/tests/e2e/ctl_v3_lease_test.go +++ b/tests/e2e/ctl_v3_lease_test.go @@ -37,20 +37,6 @@ func TestCtlV3LeaseKeepAlivePeerTLS(t *testing.T) { testCtl(t, leaseTestKeepAlive, withCfg(*e2e.NewConfigPeerTLS())) } -func TestCtlV3LeaseKeepAliveOnce(t *testing.T) { testCtl(t, leaseTestKeepAliveOnce) } -func TestCtlV3LeaseKeepAliveOnceNoTLS(t *testing.T) { - testCtl(t, leaseTestKeepAliveOnce, withCfg(*e2e.NewConfigNoTLS())) -} -func TestCtlV3LeaseKeepAliveOnceClientTLS(t *testing.T) { - testCtl(t, leaseTestKeepAliveOnce, withCfg(*e2e.NewConfigClientTLS())) -} -func TestCtlV3LeaseKeepAliveOnceClientAutoTLS(t *testing.T) { - testCtl(t, leaseTestKeepAliveOnce, withCfg(*e2e.NewConfigClientAutoTLS())) -} -func TestCtlV3LeaseKeepAliveOncePeerTLS(t *testing.T) { - testCtl(t, leaseTestKeepAliveOnce, withCfg(*e2e.NewConfigPeerTLS())) -} - func TestCtlV3LeaseRevoke(t *testing.T) { testCtl(t, leaseTestRevoked) } func TestCtlV3LeaseRevokeNoTLS(t *testing.T) { testCtl(t, leaseTestRevoked, withCfg(*e2e.NewConfigNoTLS())) @@ -82,23 +68,6 @@ func leaseTestKeepAlive(cx ctlCtx) { } } -func leaseTestKeepAliveOnce(cx ctlCtx) { - // put with TTL 10 seconds and keep-alive once - leaseID, err := ctlV3LeaseGrant(cx, 10) - if err != nil { - cx.t.Fatalf("leaseTestKeepAlive: ctlV3LeaseGrant error (%v)", err) - } - if err := ctlV3Put(cx, "key", "val", leaseID); err != nil { - cx.t.Fatalf("leaseTestKeepAlive: ctlV3Put error (%v)", err) - } - if err := ctlV3LeaseKeepAliveOnce(cx, leaseID); err != nil { - cx.t.Fatalf("leaseTestKeepAlive: ctlV3LeaseKeepAliveOnce error (%v)", err) - } - if err := ctlV3Get(cx, []string{"key"}, kv{"key", "val"}); err != nil { - cx.t.Fatalf("leaseTestKeepAlive: ctlV3Get error (%v)", err) - } -} - func leaseTestRevoked(cx ctlCtx) { err := leaseTestRevoke(cx) if err != nil { @@ -161,20 +130,6 @@ func ctlV3LeaseKeepAlive(cx ctlCtx, leaseID string) error { return proc.Stop() } -func ctlV3LeaseKeepAliveOnce(cx ctlCtx, leaseID string) error { - cmdArgs := append(cx.PrefixArgs(), "lease", "keep-alive", "--once", leaseID) - - proc, err := e2e.SpawnCmd(cmdArgs, nil) - if err != nil { - return err - } - - if _, err = proc.Expect(fmt.Sprintf("lease %s keepalived with TTL(", leaseID)); err != nil { - return err - } - return proc.Stop() -} - func ctlV3LeaseRevoke(cx ctlCtx, leaseID string) error { cmdArgs := append(cx.PrefixArgs(), "lease", "revoke", leaseID) return e2e.SpawnWithExpectWithEnv(cmdArgs, cx.envMap, fmt.Sprintf("lease %s revoked", leaseID)) From ab3353582d0f4b3f89da53fe2974d01f623cc226 Mon Sep 17 00:00:00 2001 From: Danielle Lancashire Date: Wed, 16 Mar 2022 16:21:12 +0000 Subject: [PATCH 198/258] tests/framework: Add Client.LeaseRevoke --- tests/framework/e2e/etcdctl.go | 16 ++++++++++++++++ tests/framework/integration.go | 6 ++++++ tests/framework/interface.go | 1 + 3 files changed, 23 insertions(+) diff --git a/tests/framework/e2e/etcdctl.go b/tests/framework/e2e/etcdctl.go index aa315ddf0fa0..546c9c305107 100644 --- a/tests/framework/e2e/etcdctl.go +++ b/tests/framework/e2e/etcdctl.go @@ -327,3 +327,19 @@ func (ctl *EtcdctlV3) LeaseKeepAliveOnce(id clientv3.LeaseID) (*clientv3.LeaseKe err = json.Unmarshal([]byte(line), &resp) return &resp, err } + +func (ctl *EtcdctlV3) LeaseRevoke(id clientv3.LeaseID) (*clientv3.LeaseRevokeResponse, error) { + args := ctl.cmdArgs() + args = append(args, "lease", "revoke", strconv.FormatInt(int64(id), 16), "-w", "json") + cmd, err := SpawnCmd(args, nil) + if err != nil { + return nil, err + } + var resp clientv3.LeaseRevokeResponse + line, err := cmd.Expect("header") + if err != nil { + return nil, err + } + err = json.Unmarshal([]byte(line), &resp) + return &resp, err +} diff --git a/tests/framework/integration.go b/tests/framework/integration.go index e5c8c01a445b..28bb414220e2 100644 --- a/tests/framework/integration.go +++ b/tests/framework/integration.go @@ -244,3 +244,9 @@ func (c integrationClient) LeaseKeepAliveOnce(id clientv3.LeaseID) (*clientv3.Le return c.Client.KeepAliveOnce(ctx, id) } + +func (c integrationClient) LeaseRevoke(id clientv3.LeaseID) (*clientv3.LeaseRevokeResponse, error) { + ctx := context.Background() + + return c.Client.Revoke(ctx, id) +} diff --git a/tests/framework/interface.go b/tests/framework/interface.go index ca7fb18decd8..cde4c8a3a72e 100644 --- a/tests/framework/interface.go +++ b/tests/framework/interface.go @@ -45,4 +45,5 @@ type Client interface { TimeToLive(id clientv3.LeaseID, opts config.LeaseOption) (*clientv3.LeaseTimeToLiveResponse, error) LeaseList() (*clientv3.LeaseLeasesResponse, error) LeaseKeepAliveOnce(id clientv3.LeaseID) (*clientv3.LeaseKeepAliveResponse, error) + LeaseRevoke(id clientv3.LeaseID) (*clientv3.LeaseRevokeResponse, error) } From 87740f6c7be7ca6fba8764a9bbf7d835387e1770 Mon Sep 17 00:00:00 2001 From: Danielle Lancashire Date: Wed, 16 Mar 2022 16:21:43 +0000 Subject: [PATCH 199/258] tests: Migrate TestCtlV3LeaseRevoke.* to common --- tests/common/lease_test.go | 61 ++++++++++++++++++++++++++++++++++ tests/e2e/ctl_v3_lease_test.go | 39 ---------------------- 2 files changed, 61 insertions(+), 39 deletions(-) diff --git a/tests/common/lease_test.go b/tests/common/lease_test.go index 98e382cebedd..e64f3b86e348 100644 --- a/tests/common/lease_test.go +++ b/tests/common/lease_test.go @@ -259,3 +259,64 @@ func TestLeaseGrantKeepAliveOnce(t *testing.T) { }) } } + +func TestLeaseGrantRevoke(t *testing.T) { + testRunner.BeforeTest(t) + + tcs := []struct { + name string + config config.ClusterConfig + }{ + { + name: "NoTLS", + config: config.ClusterConfig{ClusterSize: 1}, + }, + { + name: "PeerTLS", + config: config.ClusterConfig{ClusterSize: 3, PeerTLS: config.ManualTLS}, + }, + { + name: "PeerAutoTLS", + config: config.ClusterConfig{ClusterSize: 3, PeerTLS: config.AutoTLS}, + }, + { + name: "ClientTLS", + config: config.ClusterConfig{ClusterSize: 1, ClientTLS: config.ManualTLS}, + }, + { + name: "ClientAutoTLS", + config: config.ClusterConfig{ClusterSize: 1, ClientTLS: config.AutoTLS}, + }, + } + for _, tc := range tcs { + t.Run(tc.name, func(t *testing.T) { + clus := testRunner.NewCluster(t, tc.config) + defer clus.Close() + cc := clus.Client() + + testutils.ExecuteWithTimeout(t, 10*time.Second, func() { + leaseResp, err := cc.Grant(20) + require.NoError(t, err) + + err = cc.Put("foo", "bar", config.PutOptions{LeaseID: leaseResp.ID}) + require.NoError(t, err) + + getResp, err := cc.Get("foo", config.GetOptions{}) + require.NoError(t, err) + require.Equal(t, int64(1), getResp.Count) + + _, err = cc.LeaseRevoke(leaseResp.ID) + require.NoError(t, err) + + ttlResp, err := cc.TimeToLive(leaseResp.ID, config.LeaseOption{}) + require.NoError(t, err) + require.Equal(t, int64(-1), ttlResp.TTL) + + getResp, err = cc.Get("foo", config.GetOptions{}) + require.NoError(t, err) + // Value should expire with the lease + require.Equal(t, int64(0), getResp.Count) + }) + }) + } +} diff --git a/tests/e2e/ctl_v3_lease_test.go b/tests/e2e/ctl_v3_lease_test.go index 905351c934ef..6ac44c44f240 100644 --- a/tests/e2e/ctl_v3_lease_test.go +++ b/tests/e2e/ctl_v3_lease_test.go @@ -37,20 +37,6 @@ func TestCtlV3LeaseKeepAlivePeerTLS(t *testing.T) { testCtl(t, leaseTestKeepAlive, withCfg(*e2e.NewConfigPeerTLS())) } -func TestCtlV3LeaseRevoke(t *testing.T) { testCtl(t, leaseTestRevoked) } -func TestCtlV3LeaseRevokeNoTLS(t *testing.T) { - testCtl(t, leaseTestRevoked, withCfg(*e2e.NewConfigNoTLS())) -} -func TestCtlV3LeaseRevokeClientTLS(t *testing.T) { - testCtl(t, leaseTestRevoked, withCfg(*e2e.NewConfigClientTLS())) -} -func TestCtlV3LeaseRevokeClientAutoTLS(t *testing.T) { - testCtl(t, leaseTestRevoked, withCfg(*e2e.NewConfigClientAutoTLS())) -} -func TestCtlV3LeaseRevokePeerTLS(t *testing.T) { - testCtl(t, leaseTestRevoked, withCfg(*e2e.NewConfigPeerTLS())) -} - func leaseTestKeepAlive(cx ctlCtx) { // put with TTL 10 seconds and keep-alive leaseID, err := ctlV3LeaseGrant(cx, 10) @@ -68,31 +54,6 @@ func leaseTestKeepAlive(cx ctlCtx) { } } -func leaseTestRevoked(cx ctlCtx) { - err := leaseTestRevoke(cx) - if err != nil { - cx.t.Fatalf("leaseTestRevoke: (%v)", err) - } -} - -func leaseTestRevoke(cx ctlCtx) error { - // put with TTL 10 seconds and revoke - leaseID, err := ctlV3LeaseGrant(cx, 10) - if err != nil { - return fmt.Errorf("ctlV3LeaseGrant error (%v)", err) - } - if err := ctlV3Put(cx, "key", "val", leaseID); err != nil { - return fmt.Errorf("ctlV3Put error (%v)", err) - } - if err := ctlV3LeaseRevoke(cx, leaseID); err != nil { - return fmt.Errorf("ctlV3LeaseRevoke error (%v)", err) - } - if err := ctlV3Get(cx, []string{"key"}); err != nil { // expect no output - return fmt.Errorf("ctlV3Get error (%v)", err) - } - return nil -} - func ctlV3LeaseGrant(cx ctlCtx, ttl int) (string, error) { cmdArgs := append(cx.PrefixArgs(), "lease", "grant", strconv.Itoa(ttl)) proc, err := e2e.SpawnCmd(cmdArgs, cx.envMap) From 3e657bdc5035c35e5c0c46ef1ca8598a828993a4 Mon Sep 17 00:00:00 2001 From: nic-chen Date: Sat, 19 Mar 2022 00:51:29 +0800 Subject: [PATCH 200/258] tests: Migrate key value Get to common framework --- tests/common/alarm_test.go | 103 +++++++++++++++++++------------------ 1 file changed, 52 insertions(+), 51 deletions(-) diff --git a/tests/common/alarm_test.go b/tests/common/alarm_test.go index 1d5708663438..9312703bb20b 100644 --- a/tests/common/alarm_test.go +++ b/tests/common/alarm_test.go @@ -21,73 +21,74 @@ import ( "time" "go.etcd.io/etcd/tests/v3/framework/config" + "go.etcd.io/etcd/tests/v3/framework/testutils" ) func TestAlarm(t *testing.T) { testRunner.BeforeTest(t) - clus := testRunner.NewCluster(t, config.ClusterConfig{ClusterSize: 3, QuotaBackendBytes: int64(13 * os.Getpagesize())}) defer clus.Close() + testutils.ExecuteWithTimeout(t, 10*time.Second, func() { + // test small put still works + smallbuf := strings.Repeat("a", 64) + if err := clus.Client().Put("1st_test", smallbuf); err != nil { + t.Fatalf("alarmTest: put kv error (%v)", err) + } - // test small put still works - smallbuf := strings.Repeat("a", 64) - if err := clus.Client().Put("1st_test", smallbuf); err != nil { - t.Fatalf("alarmTest: put kv error (%v)", err) - } - - // write some chunks to fill up the database - buf := strings.Repeat("b", os.Getpagesize()) - for { - if err := clus.Client().Put("2nd_test", buf); err != nil { - if !strings.Contains(err.Error(), "etcdserver: mvcc: database space exceeded") { - t.Fatal(err) + // write some chunks to fill up the database + buf := strings.Repeat("b", os.Getpagesize()) + for { + if err := clus.Client().Put("2nd_test", buf); err != nil { + if !strings.Contains(err.Error(), "etcdserver: mvcc: database space exceeded") { + t.Fatal(err) + } + break } - break } - } - // quota alarm should now be on - _, err := clus.Client().Alarm("list") - if err != nil { - t.Fatalf("alarmTest: Alarm error (%v)", err) - } + // quota alarm should now be on + _, err := clus.Client().Alarm("list") + if err != nil { + t.Fatalf("alarmTest: Alarm error (%v)", err) + } - // endpoint should not healthy - if err := clus.Client().Health(); err == nil { - t.Fatalf("endpoint should not healthy") - } + // endpoint should not healthy + if err := clus.Client().Health(); err == nil { + t.Fatalf("endpoint should not healthy") + } - // check that Put is rejected when alarm is on - if err := clus.Client().Put("3rd_test", smallbuf); err != nil { - if !strings.Contains(err.Error(), "etcdserver: mvcc: database space exceeded") { - t.Fatal(err) + // check that Put is rejected when alarm is on + if err := clus.Client().Put("3rd_test", smallbuf); err != nil { + if !strings.Contains(err.Error(), "etcdserver: mvcc: database space exceeded") { + t.Fatal(err) + } } - } - // get latest revision to compact - sresp, err := clus.Client().Status() - if err != nil { - t.Fatalf("get endpoint status error: %v", err) - } + // get latest revision to compact + sresp, err := clus.Client().Status() + if err != nil { + t.Fatalf("get endpoint status error: %v", err) + } - // make some space - _, err = clus.Client().Compact(sresp[0].Header.Revision, config.CompactOption{Physical: true, Timeout: 10 * time.Second}) - if err != nil { - t.Fatalf("alarmTest: Compact error (%v)", err) - } + // make some space + _, err = clus.Client().Compact(sresp[0].Header.Revision, config.CompactOption{Physical: true, Timeout: 10 * time.Second}) + if err != nil { + t.Fatalf("alarmTest: Compact error (%v)", err) + } - if err = clus.Client().Defragment(config.DefragOption{Timeout: 10 * time.Second}); err != nil { - t.Fatalf("alarmTest: defrag error (%v)", err) - } + if err = clus.Client().Defragment(config.DefragOption{Timeout: 10 * time.Second}); err != nil { + t.Fatalf("alarmTest: defrag error (%v)", err) + } - // turn off alarm - _, err = clus.Client().Alarm("disarm") - if err != nil { - t.Fatalf("alarmTest: Alarm error (%v)", err) - } + // turn off alarm + _, err = clus.Client().Alarm("disarm") + if err != nil { + t.Fatalf("alarmTest: Alarm error (%v)", err) + } - // put one more key below quota - if err := clus.Client().Put("4th_test", smallbuf); err != nil { - t.Fatal(err) - } + // put one more key below quota + if err := clus.Client().Put("4th_test", smallbuf); err != nil { + t.Fatal(err) + } + }) } From e9fa171665662860be9a951959dad1a533f02d13 Mon Sep 17 00:00:00 2001 From: nic-chen Date: Sat, 19 Mar 2022 16:31:19 +0800 Subject: [PATCH 201/258] fix test fail --- tests/common/alarm_test.go | 9 ++++++++- tests/e2e/ctl_v3_test.go | 4 ---- tests/framework/e2e.go | 5 +++-- 3 files changed, 11 insertions(+), 7 deletions(-) diff --git a/tests/common/alarm_test.go b/tests/common/alarm_test.go index 9312703bb20b..e96e99fc6e5f 100644 --- a/tests/common/alarm_test.go +++ b/tests/common/alarm_test.go @@ -69,9 +69,16 @@ func TestAlarm(t *testing.T) { if err != nil { t.Fatalf("get endpoint status error: %v", err) } + var rvs int64 + for _, resp := range sresp { + if resp != nil && resp.Header != nil { + rvs = resp.Header.Revision + break + } + } // make some space - _, err = clus.Client().Compact(sresp[0].Header.Revision, config.CompactOption{Physical: true, Timeout: 10 * time.Second}) + _, err = clus.Client().Compact(rvs, config.CompactOption{Physical: true, Timeout: 10 * time.Second}) if err != nil { t.Fatalf("alarmTest: Compact error (%v)", err) } diff --git a/tests/e2e/ctl_v3_test.go b/tests/e2e/ctl_v3_test.go index fc544603d5d3..ee309cdeb37a 100644 --- a/tests/e2e/ctl_v3_test.go +++ b/tests/e2e/ctl_v3_test.go @@ -181,10 +181,6 @@ func withQuota(b int64) ctlOption { return func(cx *ctlCtx) { cx.quotaBackendBytes = b } } -func withCompactPhysical() ctlOption { - return func(cx *ctlCtx) { cx.compactPhysical = true } -} - func withInitialCorruptCheck() ctlOption { return func(cx *ctlCtx) { cx.initialCorruptCheck = true } } diff --git a/tests/framework/e2e.go b/tests/framework/e2e.go index d0e799163e6f..8e068e3a846a 100644 --- a/tests/framework/e2e.go +++ b/tests/framework/e2e.go @@ -40,8 +40,9 @@ func (e e2eRunner) BeforeTest(t testing.TB) { func (e e2eRunner) NewCluster(t testing.TB, cfg config.ClusterConfig) Cluster { e2eConfig := e2e.EtcdProcessClusterConfig{ - InitialToken: "new", - ClusterSize: cfg.ClusterSize, + InitialToken: "new", + ClusterSize: cfg.ClusterSize, + QuotaBackendBytes: cfg.QuotaBackendBytes, } switch cfg.ClientTLS { case config.NoTLS: From 527edd39a6d7805efcc21da92664a42b9df7267a Mon Sep 17 00:00:00 2001 From: nic-chen Date: Sun, 20 Mar 2022 01:40:53 +0800 Subject: [PATCH 202/258] fix alarm test --- tests/common/alarm_test.go | 20 +++++++++++--------- tests/framework/e2e/etcdctl.go | 17 +++++++++++++---- tests/framework/integration.go | 4 ++-- tests/framework/interface.go | 2 +- 4 files changed, 27 insertions(+), 16 deletions(-) diff --git a/tests/common/alarm_test.go b/tests/common/alarm_test.go index 1188bab36a86..4bf12f994c74 100644 --- a/tests/common/alarm_test.go +++ b/tests/common/alarm_test.go @@ -20,6 +20,7 @@ import ( "testing" "time" + clientv3 "go.etcd.io/etcd/client/v3" "go.etcd.io/etcd/tests/v3/framework/config" "go.etcd.io/etcd/tests/v3/framework/testutils" ) @@ -47,16 +48,11 @@ func TestAlarm(t *testing.T) { } // quota alarm should now be on - _, err := clus.Client().Alarm("list") + alarmResp, err := clus.Client().Alarm("list", nil) if err != nil { t.Fatalf("alarmTest: Alarm error (%v)", err) } - // endpoint should not healthy - if err := clus.Client().Health(); err == nil { - t.Fatalf("endpoint should not healthy") - } - // check that Put is rejected when alarm is on if err := clus.Client().Put("3rd_test", smallbuf, config.PutOptions{}); err != nil { if !strings.Contains(err.Error(), "etcdserver: mvcc: database space exceeded") { @@ -88,9 +84,15 @@ func TestAlarm(t *testing.T) { } // turn off alarm - _, err = clus.Client().Alarm("disarm") - if err != nil { - t.Fatalf("alarmTest: Alarm error (%v)", err) + for _, alarm := range alarmResp.Alarms { + m := &clientv3.AlarmMember{ + MemberID: alarm.MemberID, + Alarm: alarm.Alarm, + } + _, err = clus.Client().Alarm("disarm", m) + if err != nil { + t.Fatalf("alarmTest: Alarm error (%v)", err) + } } // put one more key below quota diff --git a/tests/framework/e2e/etcdctl.go b/tests/framework/e2e/etcdctl.go index ee2ceacac1f8..25ea0eaf18b8 100644 --- a/tests/framework/e2e/etcdctl.go +++ b/tests/framework/e2e/etcdctl.go @@ -344,9 +344,18 @@ func (ctl *EtcdctlV3) LeaseRevoke(id clientv3.LeaseID) (*clientv3.LeaseRevokeRes return &resp, err } -func (ctl *EtcdctlV3) Alarm(cmd string) (*clientv3.AlarmResponse, error) { +func (ctl *EtcdctlV3) Alarm(cmd string, _ *clientv3.AlarmMember) (*clientv3.AlarmResponse, error) { args := ctl.cmdArgs() - args = append(args, "alarm", cmd) - - return nil, SpawnWithExpect(args, "alarm:NOSPACE") + args = append(args, "alarm", cmd, "-w", "json") + ep, err := SpawnCmd(args, nil) + if err != nil { + return nil, err + } + var resp clientv3.AlarmResponse + line, err := ep.Expect("alarm") + if err != nil { + return nil, err + } + err = json.Unmarshal([]byte(line), &resp) + return &resp, err } diff --git a/tests/framework/integration.go b/tests/framework/integration.go index b7403d81d4de..4ce431ff9dca 100644 --- a/tests/framework/integration.go +++ b/tests/framework/integration.go @@ -164,12 +164,12 @@ func (c integrationClient) Compact(rev int64, o config.CompactOption) (*clientv3 return c.Client.Compact(ctx, rev, clientOpts...) } -func (c integrationClient) Alarm(cmd string) (*clientv3.AlarmResponse, error) { +func (c integrationClient) Alarm(cmd string, member *clientv3.AlarmMember) (*clientv3.AlarmResponse, error) { ctx := context.Background() if cmd == "list" { return c.Client.AlarmList(ctx) } - return c.Client.AlarmDisarm(ctx, nil) + return c.Client.AlarmDisarm(ctx, member) } func (c integrationClient) Status() ([]*clientv3.StatusResponse, error) { diff --git a/tests/framework/interface.go b/tests/framework/interface.go index f925682df3c2..2864a22c6b4e 100644 --- a/tests/framework/interface.go +++ b/tests/framework/interface.go @@ -41,7 +41,7 @@ type Client interface { HashKV(rev int64) ([]*clientv3.HashKVResponse, error) Health() error Defragment(opts config.DefragOption) error - Alarm(cmd string) (*clientv3.AlarmResponse, error) + Alarm(cmd string, member *clientv3.AlarmMember) (*clientv3.AlarmResponse, error) Grant(ttl int64) (*clientv3.LeaseGrantResponse, error) TimeToLive(id clientv3.LeaseID, opts config.LeaseOption) (*clientv3.LeaseTimeToLiveResponse, error) LeaseList() (*clientv3.LeaseLeasesResponse, error) From bb7856090a8f3d08bfbb2c85c859de880fe0dd0f Mon Sep 17 00:00:00 2001 From: nic-chen Date: Sun, 20 Mar 2022 02:01:30 +0800 Subject: [PATCH 203/258] fix: set cluster size to 1 to avoid unstable --- tests/common/alarm_test.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/common/alarm_test.go b/tests/common/alarm_test.go index 4bf12f994c74..bb66fd727c1b 100644 --- a/tests/common/alarm_test.go +++ b/tests/common/alarm_test.go @@ -27,7 +27,7 @@ import ( func TestAlarm(t *testing.T) { testRunner.BeforeTest(t) - clus := testRunner.NewCluster(t, config.ClusterConfig{ClusterSize: 3, QuotaBackendBytes: int64(13 * os.Getpagesize())}) + clus := testRunner.NewCluster(t, config.ClusterConfig{ClusterSize: 1, QuotaBackendBytes: int64(13 * os.Getpagesize())}) defer clus.Close() testutils.ExecuteWithTimeout(t, 10*time.Second, func() { // test small put still works From 89146aa157c91b774bade97a7c354a73820bc5e4 Mon Sep 17 00:00:00 2001 From: nic-chen Date: Sun, 20 Mar 2022 02:06:42 +0800 Subject: [PATCH 204/258] chore: delete useless file --- tests/e2e/ctl_v3_alarm_test.go | 106 --------------------------------- 1 file changed, 106 deletions(-) delete mode 100644 tests/e2e/ctl_v3_alarm_test.go diff --git a/tests/e2e/ctl_v3_alarm_test.go b/tests/e2e/ctl_v3_alarm_test.go deleted file mode 100644 index b99d3a6a388e..000000000000 --- a/tests/e2e/ctl_v3_alarm_test.go +++ /dev/null @@ -1,106 +0,0 @@ -// Copyright 2016 The etcd Authors -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -package e2e - -import ( - "context" - "os" - "strings" - "testing" - "time" - - clientv3 "go.etcd.io/etcd/client/v3" - "go.etcd.io/etcd/tests/v3/framework/e2e" -) - -func TestCtlV3Alarm(t *testing.T) { - // The boltdb minimum working set is six pages. - testCtl(t, alarmTest, withQuota(int64(13*os.Getpagesize()))) -} - -func alarmTest(cx ctlCtx) { - // test small put still works - smallbuf := strings.Repeat("a", 64) - if err := ctlV3Put(cx, "1st_test", smallbuf, ""); err != nil { - cx.t.Fatal(err) - } - - // write some chunks to fill up the database - buf := strings.Repeat("b", os.Getpagesize()) - for { - if err := ctlV3Put(cx, "2nd_test", buf, ""); err != nil { - if !strings.Contains(err.Error(), "etcdserver: mvcc: database space exceeded") { - cx.t.Fatal(err) - } - break - } - } - - // quota alarm should now be on - if err := ctlV3Alarm(cx, "list", "alarm:NOSPACE"); err != nil { - cx.t.Fatal(err) - } - - // '/health' handler should return 'false' - if err := e2e.CURLGet(cx.epc, e2e.CURLReq{Endpoint: "/health", Expected: `{"health":"false","reason":"ALARM NOSPACE"}`}); err != nil { - cx.t.Fatalf("failed get with curl (%v)", err) - } - - // check that Put is rejected when alarm is on - if err := ctlV3Put(cx, "3rd_test", smallbuf, ""); err != nil { - if !strings.Contains(err.Error(), "etcdserver: mvcc: database space exceeded") { - cx.t.Fatal(err) - } - } - - eps := cx.epc.EndpointsV3() - - // get latest revision to compact - cli, err := clientv3.New(clientv3.Config{ - Endpoints: eps, - DialTimeout: 3 * time.Second, - }) - if err != nil { - cx.t.Fatal(err) - } - defer cli.Close() - sresp, err := cli.Status(context.TODO(), eps[0]) - if err != nil { - cx.t.Fatal(err) - } - - // make some space - if err := ctlV3Compact(cx, sresp.Header.Revision, true); err != nil { - cx.t.Fatal(err) - } - if err := ctlV3OnlineDefrag(cx); err != nil { - cx.t.Fatal(err) - } - - // turn off alarm - if err := ctlV3Alarm(cx, "disarm", "alarm:NOSPACE"); err != nil { - cx.t.Fatal(err) - } - - // put one more key below quota - if err := ctlV3Put(cx, "4th_test", smallbuf, ""); err != nil { - cx.t.Fatal(err) - } -} - -func ctlV3Alarm(cx ctlCtx, cmd string, as ...string) error { - cmdArgs := append(cx.PrefixArgs(), "alarm", cmd) - return e2e.SpawnWithExpects(cmdArgs, cx.envMap, as...) -} From c6488a2c56acf3d59168a603ca568a369edb1eea Mon Sep 17 00:00:00 2001 From: nic-chen Date: Sun, 20 Mar 2022 10:09:27 +0800 Subject: [PATCH 205/258] fix review --- tests/common/alarm_test.go | 6 +++--- tests/framework/e2e/etcdctl.go | 20 ++++++++++++++++++-- tests/framework/integration.go | 12 ++++++------ tests/framework/interface.go | 3 ++- 4 files changed, 29 insertions(+), 12 deletions(-) diff --git a/tests/common/alarm_test.go b/tests/common/alarm_test.go index bb66fd727c1b..9873743c2ff5 100644 --- a/tests/common/alarm_test.go +++ b/tests/common/alarm_test.go @@ -48,7 +48,7 @@ func TestAlarm(t *testing.T) { } // quota alarm should now be on - alarmResp, err := clus.Client().Alarm("list", nil) + alarmResp, err := clus.Client().AlarmList() if err != nil { t.Fatalf("alarmTest: Alarm error (%v)", err) } @@ -85,11 +85,11 @@ func TestAlarm(t *testing.T) { // turn off alarm for _, alarm := range alarmResp.Alarms { - m := &clientv3.AlarmMember{ + alarmMember := &clientv3.AlarmMember{ MemberID: alarm.MemberID, Alarm: alarm.Alarm, } - _, err = clus.Client().Alarm("disarm", m) + _, err = clus.Client().AlarmDisarm(alarmMember) if err != nil { t.Fatalf("alarmTest: Alarm error (%v)", err) } diff --git a/tests/framework/e2e/etcdctl.go b/tests/framework/e2e/etcdctl.go index 25ea0eaf18b8..dd5f57e35027 100644 --- a/tests/framework/e2e/etcdctl.go +++ b/tests/framework/e2e/etcdctl.go @@ -344,9 +344,25 @@ func (ctl *EtcdctlV3) LeaseRevoke(id clientv3.LeaseID) (*clientv3.LeaseRevokeRes return &resp, err } -func (ctl *EtcdctlV3) Alarm(cmd string, _ *clientv3.AlarmMember) (*clientv3.AlarmResponse, error) { +func (ctl *EtcdctlV3) AlarmList() (*clientv3.AlarmResponse, error) { args := ctl.cmdArgs() - args = append(args, "alarm", cmd, "-w", "json") + args = append(args, "alarm", "list", "-w", "json") + ep, err := SpawnCmd(args, nil) + if err != nil { + return nil, err + } + var resp clientv3.AlarmResponse + line, err := ep.Expect("alarm") + if err != nil { + return nil, err + } + err = json.Unmarshal([]byte(line), &resp) + return &resp, err +} + +func (ctl *EtcdctlV3) AlarmDisarm(_ *clientv3.AlarmMember) (*clientv3.AlarmResponse, error) { + args := ctl.cmdArgs() + args = append(args, "alarm", "disarm", "-w", "json") ep, err := SpawnCmd(args, nil) if err != nil { return nil, err diff --git a/tests/framework/integration.go b/tests/framework/integration.go index 4ce431ff9dca..f5867da4633d 100644 --- a/tests/framework/integration.go +++ b/tests/framework/integration.go @@ -164,12 +164,12 @@ func (c integrationClient) Compact(rev int64, o config.CompactOption) (*clientv3 return c.Client.Compact(ctx, rev, clientOpts...) } -func (c integrationClient) Alarm(cmd string, member *clientv3.AlarmMember) (*clientv3.AlarmResponse, error) { - ctx := context.Background() - if cmd == "list" { - return c.Client.AlarmList(ctx) - } - return c.Client.AlarmDisarm(ctx, member) +func (c integrationClient) AlarmList() (*clientv3.AlarmResponse, error) { + return c.Client.AlarmList(context.Background()) +} + +func (c integrationClient) AlarmDisarm(alarmMember *clientv3.AlarmMember) (*clientv3.AlarmResponse, error) { + return c.Client.AlarmDisarm(context.Background(), alarmMember) } func (c integrationClient) Status() ([]*clientv3.StatusResponse, error) { diff --git a/tests/framework/interface.go b/tests/framework/interface.go index 2864a22c6b4e..8460483dd572 100644 --- a/tests/framework/interface.go +++ b/tests/framework/interface.go @@ -41,7 +41,8 @@ type Client interface { HashKV(rev int64) ([]*clientv3.HashKVResponse, error) Health() error Defragment(opts config.DefragOption) error - Alarm(cmd string, member *clientv3.AlarmMember) (*clientv3.AlarmResponse, error) + AlarmList() (*clientv3.AlarmResponse, error) + AlarmDisarm(alarmMember *clientv3.AlarmMember) (*clientv3.AlarmResponse, error) Grant(ttl int64) (*clientv3.LeaseGrantResponse, error) TimeToLive(id clientv3.LeaseID, opts config.LeaseOption) (*clientv3.LeaseTimeToLiveResponse, error) LeaseList() (*clientv3.LeaseLeasesResponse, error) From adae7a659ecabb5f99366f6bc94cae51a4decd3c Mon Sep 17 00:00:00 2001 From: Danielle Lancashire Date: Thu, 17 Mar 2022 15:48:01 +0000 Subject: [PATCH 206/258] tests/framework: Add User operations --- tests/framework/config/client.go | 4 ++ tests/framework/e2e/etcdctl.go | 87 ++++++++++++++++++++++++++++++++ tests/framework/integration.go | 22 ++++++++ tests/framework/interface.go | 5 ++ 4 files changed, 118 insertions(+) diff --git a/tests/framework/config/client.go b/tests/framework/config/client.go index ef2ef9c273c0..ffbd8825abe7 100644 --- a/tests/framework/config/client.go +++ b/tests/framework/config/client.go @@ -54,3 +54,7 @@ type DefragOption struct { type LeaseOption struct { WithAttachedKeys bool } + +type UserAddOptions struct { + NoPassword bool +} diff --git a/tests/framework/e2e/etcdctl.go b/tests/framework/e2e/etcdctl.go index dd5f57e35027..d7629c2fbb9c 100644 --- a/tests/framework/e2e/etcdctl.go +++ b/tests/framework/e2e/etcdctl.go @@ -375,3 +375,90 @@ func (ctl *EtcdctlV3) AlarmDisarm(_ *clientv3.AlarmMember) (*clientv3.AlarmRespo err = json.Unmarshal([]byte(line), &resp) return &resp, err } + +func (ctl *EtcdctlV3) UserAdd(name, password string, opts config.UserAddOptions) (*clientv3.AuthUserAddResponse, error) { + args := ctl.cmdArgs() + args = append(args, "user", "add") + if password == "" { + args = append(args, name) + } else { + args = append(args, fmt.Sprintf("%s:%s", name, password)) + } + + if opts.NoPassword { + args = append(args, "--no-password") + } + + args = append(args, "--interactive=false", "-w", "json") + + cmd, err := SpawnCmd(args, nil) + if err != nil { + return nil, err + } + + // If no password is provided, and NoPassword isn't set, the CLI will always + // wait for a password, send an enter in this case for an "empty" password. + if !opts.NoPassword && password == "" { + err := cmd.Send("\n") + if err != nil { + return nil, err + } + } + + var resp clientv3.AuthUserAddResponse + line, err := cmd.Expect("header") + if err != nil { + return nil, err + } + err = json.Unmarshal([]byte(line), &resp) + return &resp, err +} + +func (ctl *EtcdctlV3) UserList() (*clientv3.AuthUserListResponse, error) { + args := ctl.cmdArgs() + args = append(args, "user", "list", "-w", "json") + cmd, err := SpawnCmd(args, nil) + if err != nil { + return nil, err + } + var resp clientv3.AuthUserListResponse + line, err := cmd.Expect("header") + if err != nil { + return nil, err + } + err = json.Unmarshal([]byte(line), &resp) + return &resp, err +} + +func (ctl *EtcdctlV3) UserDelete(name string) (*clientv3.AuthUserDeleteResponse, error) { + args := ctl.cmdArgs() + args = append(args, "user", "delete", name, "-w", "json") + cmd, err := SpawnCmd(args, nil) + if err != nil { + return nil, err + } + var resp clientv3.AuthUserDeleteResponse + line, err := cmd.Expect("header") + if err != nil { + return nil, err + } + err = json.Unmarshal([]byte(line), &resp) + return &resp, err +} + +func (ctl *EtcdctlV3) UserChangePass(user, newPass string) error { + args := ctl.cmdArgs() + args = append(args, "user", "passwd", user, "--interactive=false") + cmd, err := SpawnCmd(args, nil) + if err != nil { + return err + } + + err = cmd.Send(newPass + "\n") + if err != nil { + return err + } + + _, err = cmd.Expect("Password updated") + return err +} diff --git a/tests/framework/integration.go b/tests/framework/integration.go index f5867da4633d..38bca9618c0d 100644 --- a/tests/framework/integration.go +++ b/tests/framework/integration.go @@ -259,3 +259,25 @@ func (c integrationClient) LeaseRevoke(id clientv3.LeaseID) (*clientv3.LeaseRevo return c.Client.Revoke(ctx, id) } + +func (c integrationClient) UserAdd(name, password string, opts config.UserAddOptions) (*clientv3.AuthUserAddResponse, error) { + ctx := context.Background() + return c.Client.UserAddWithOptions(ctx, name, password, &clientv3.UserAddOptions{ + NoPassword: opts.NoPassword, + }) +} + +func (c integrationClient) UserList() (*clientv3.AuthUserListResponse, error) { + ctx := context.Background() + return c.Client.UserList(ctx) +} + +func (c integrationClient) UserDelete(name string) (*clientv3.AuthUserDeleteResponse, error) { + ctx := context.Background() + return c.Client.UserDelete(ctx, name) +} + +func (c integrationClient) UserChangePass(user, newPass string) error { + _, err := c.Client.UserChangePassword(context.Background(), user, newPass) + return err +} diff --git a/tests/framework/interface.go b/tests/framework/interface.go index 8460483dd572..55e51d58c790 100644 --- a/tests/framework/interface.go +++ b/tests/framework/interface.go @@ -48,4 +48,9 @@ type Client interface { LeaseList() (*clientv3.LeaseLeasesResponse, error) LeaseKeepAliveOnce(id clientv3.LeaseID) (*clientv3.LeaseKeepAliveResponse, error) LeaseRevoke(id clientv3.LeaseID) (*clientv3.LeaseRevokeResponse, error) + + UserAdd(name, password string, opts config.UserAddOptions) (*clientv3.AuthUserAddResponse, error) + UserList() (*clientv3.AuthUserListResponse, error) + UserDelete(name string) (*clientv3.AuthUserDeleteResponse, error) + UserChangePass(user, newPass string) error } From 3416042c507f225dc714e1c82a2822d05e6b27ed Mon Sep 17 00:00:00 2001 From: Danielle Lancashire Date: Thu, 17 Mar 2022 15:48:10 +0000 Subject: [PATCH 207/258] tests: migrate user tests to common fw --- tests/common/user_test.go | 366 ++++++++++++++++++++++++++++++++++ tests/e2e/ctl_v3_auth_test.go | 21 ++ tests/e2e/ctl_v3_user_test.go | 209 ------------------- 3 files changed, 387 insertions(+), 209 deletions(-) create mode 100644 tests/common/user_test.go delete mode 100644 tests/e2e/ctl_v3_user_test.go diff --git a/tests/common/user_test.go b/tests/common/user_test.go new file mode 100644 index 000000000000..a1f7dbb24bb4 --- /dev/null +++ b/tests/common/user_test.go @@ -0,0 +1,366 @@ +// Copyright 2022 The etcd Authors +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package common + +import ( + "testing" + "time" + + "github.com/stretchr/testify/assert" + "go.etcd.io/etcd/tests/v3/framework/config" + "go.etcd.io/etcd/tests/v3/framework/testutils" +) + +func TestUserAdd_Simple(t *testing.T) { + testRunner.BeforeTest(t) + tcs := []struct { + name string + config config.ClusterConfig + }{ + { + name: "NoTLS", + config: config.ClusterConfig{ClusterSize: 1}, + }, + { + name: "PeerTLS", + config: config.ClusterConfig{ClusterSize: 3, PeerTLS: config.ManualTLS}, + }, + { + name: "PeerAutoTLS", + config: config.ClusterConfig{ClusterSize: 3, PeerTLS: config.AutoTLS}, + }, + { + name: "ClientTLS", + config: config.ClusterConfig{ClusterSize: 1, ClientTLS: config.ManualTLS}, + }, + { + name: "ClientAutoTLS", + config: config.ClusterConfig{ClusterSize: 1, ClientTLS: config.AutoTLS}, + }, + } + for _, tc := range tcs { + nestedCases := []struct { + name string + username string + password string + noPassword bool + expectedError string + }{ + { + name: "empty_username_not_allowed", + username: "", + password: "foobar", + // Very Vague error expectation because the CLI and the API return very + // different error structures. + expectedError: "user name", + }, + { + // Can create a user with no password, restricted to CN auth + name: "no_password_with_noPassword_set", + username: "foo", + password: "", + noPassword: true, + }, + { + // Can create a user with no password, but not restricted to CN auth + name: "no_password_without_noPassword_set", + username: "foo", + password: "", + noPassword: false, + }, + { + name: "regular_user_with_password", + username: "foo", + password: "bar", + }, + } + for _, nc := range nestedCases { + t.Run(tc.name+"/"+nc.name, func(t *testing.T) { + clus := testRunner.NewCluster(t, tc.config) + defer clus.Close() + cc := clus.Client() + + testutils.ExecuteWithTimeout(t, 10*time.Second, func() { + resp, err := cc.UserAdd(nc.username, nc.password, config.UserAddOptions{NoPassword: nc.noPassword}) + if nc.expectedError != "" { + if err != nil { + assert.Contains(t, err.Error(), nc.expectedError) + return + } + + t.Fatalf("expected user creation to fail") + } + + if err != nil { + t.Fatalf("expected no error, err: %v", err) + } + + if resp == nil { + t.Fatalf("unexpected nil response to successful user creation") + } + }) + }) + } + } +} + +func TestUserAdd_DuplicateUserNotAllowed(t *testing.T) { + testRunner.BeforeTest(t) + tcs := []struct { + name string + config config.ClusterConfig + }{ + { + name: "NoTLS", + config: config.ClusterConfig{ClusterSize: 1}, + }, + { + name: "PeerTLS", + config: config.ClusterConfig{ClusterSize: 3, PeerTLS: config.ManualTLS}, + }, + { + name: "PeerAutoTLS", + config: config.ClusterConfig{ClusterSize: 3, PeerTLS: config.AutoTLS}, + }, + { + name: "ClientTLS", + config: config.ClusterConfig{ClusterSize: 1, ClientTLS: config.ManualTLS}, + }, + { + name: "ClientAutoTLS", + config: config.ClusterConfig{ClusterSize: 1, ClientTLS: config.AutoTLS}, + }, + } + for _, tc := range tcs { + t.Run(tc.name, func(t *testing.T) { + clus := testRunner.NewCluster(t, tc.config) + defer clus.Close() + cc := clus.Client() + + testutils.ExecuteWithTimeout(t, 10*time.Second, func() { + user := "barb" + password := "rhubarb" + + _, err := cc.UserAdd(user, password, config.UserAddOptions{}) + if err != nil { + t.Fatalf("first user creation should succeed, err: %v", err) + } + + _, err = cc.UserAdd(user, password, config.UserAddOptions{}) + if err == nil { + t.Fatalf("duplicate user creation should fail") + } + assert.Contains(t, err.Error(), "etcdserver: user name already exists") + }) + }) + } +} + +func TestUserList(t *testing.T) { + testRunner.BeforeTest(t) + tcs := []struct { + name string + config config.ClusterConfig + }{ + { + name: "NoTLS", + config: config.ClusterConfig{ClusterSize: 1}, + }, + { + name: "PeerTLS", + config: config.ClusterConfig{ClusterSize: 3, PeerTLS: config.ManualTLS}, + }, + { + name: "PeerAutoTLS", + config: config.ClusterConfig{ClusterSize: 3, PeerTLS: config.AutoTLS}, + }, + { + name: "ClientTLS", + config: config.ClusterConfig{ClusterSize: 1, ClientTLS: config.ManualTLS}, + }, + { + name: "ClientAutoTLS", + config: config.ClusterConfig{ClusterSize: 1, ClientTLS: config.AutoTLS}, + }, + } + for _, tc := range tcs { + t.Run(tc.name, func(t *testing.T) { + clus := testRunner.NewCluster(t, tc.config) + defer clus.Close() + cc := clus.Client() + + testutils.ExecuteWithTimeout(t, 10*time.Second, func() { + // No Users Yet + resp, err := cc.UserList() + if err != nil { + t.Fatalf("user listing should succeed, err: %v", err) + } + if len(resp.Users) != 0 { + t.Fatalf("expected no pre-existing users, found: %q", resp.Users) + } + + user := "barb" + password := "rhubarb" + + _, err = cc.UserAdd(user, password, config.UserAddOptions{}) + if err != nil { + t.Fatalf("user creation should succeed, err: %v", err) + } + + // Users! + resp, err = cc.UserList() + if err != nil { + t.Fatalf("user listing should succeed, err: %v", err) + } + if len(resp.Users) != 1 { + t.Fatalf("expected one user, found: %q", resp.Users) + } + }) + }) + } +} + +func TestUserDelete(t *testing.T) { + testRunner.BeforeTest(t) + tcs := []struct { + name string + config config.ClusterConfig + }{ + { + name: "NoTLS", + config: config.ClusterConfig{ClusterSize: 1}, + }, + { + name: "PeerTLS", + config: config.ClusterConfig{ClusterSize: 3, PeerTLS: config.ManualTLS}, + }, + { + name: "PeerAutoTLS", + config: config.ClusterConfig{ClusterSize: 3, PeerTLS: config.AutoTLS}, + }, + { + name: "ClientTLS", + config: config.ClusterConfig{ClusterSize: 1, ClientTLS: config.ManualTLS}, + }, + { + name: "ClientAutoTLS", + config: config.ClusterConfig{ClusterSize: 1, ClientTLS: config.AutoTLS}, + }, + } + for _, tc := range tcs { + t.Run(tc.name, func(t *testing.T) { + clus := testRunner.NewCluster(t, tc.config) + defer clus.Close() + cc := clus.Client() + + testutils.ExecuteWithTimeout(t, 10*time.Second, func() { + user := "barb" + password := "rhubarb" + + _, err := cc.UserAdd(user, password, config.UserAddOptions{}) + if err != nil { + t.Fatalf("user creation should succeed, err: %v", err) + } + + resp, err := cc.UserList() + if err != nil { + t.Fatalf("user listing should succeed, err: %v", err) + } + if len(resp.Users) != 1 { + t.Fatalf("expected one user, found: %q", resp.Users) + } + + // Delete barb, sorry barb! + _, err = cc.UserDelete(user) + if err != nil { + t.Fatalf("user deletion should succeed at first, err: %v", err) + } + + resp, err = cc.UserList() + if err != nil { + t.Fatalf("user listing should succeed, err: %v", err) + } + if len(resp.Users) != 0 { + t.Fatalf("expected no users after deletion, found: %q", resp.Users) + } + + // Try to delete barb again + _, err = cc.UserDelete(user) + if err == nil { + t.Fatalf("deleting a non-existent user should fail") + } + assert.Contains(t, err.Error(), "user name not found") + }) + }) + } +} + +func TestUserChangePassword(t *testing.T) { + testRunner.BeforeTest(t) + tcs := []struct { + name string + config config.ClusterConfig + }{ + { + name: "NoTLS", + config: config.ClusterConfig{ClusterSize: 1}, + }, + { + name: "PeerTLS", + config: config.ClusterConfig{ClusterSize: 3, PeerTLS: config.ManualTLS}, + }, + { + name: "PeerAutoTLS", + config: config.ClusterConfig{ClusterSize: 3, PeerTLS: config.AutoTLS}, + }, + { + name: "ClientTLS", + config: config.ClusterConfig{ClusterSize: 1, ClientTLS: config.ManualTLS}, + }, + { + name: "ClientAutoTLS", + config: config.ClusterConfig{ClusterSize: 1, ClientTLS: config.AutoTLS}, + }, + } + for _, tc := range tcs { + t.Run(tc.name, func(t *testing.T) { + clus := testRunner.NewCluster(t, tc.config) + defer clus.Close() + cc := clus.Client() + + testutils.ExecuteWithTimeout(t, 10*time.Second, func() { + user := "barb" + password := "rhubarb" + newPassword := "potato" + + _, err := cc.UserAdd(user, password, config.UserAddOptions{}) + if err != nil { + t.Fatalf("user creation should succeed, err: %v", err) + } + + err = cc.UserChangePass(user, newPassword) + if err != nil { + t.Fatalf("user password change should succeed, err: %v", err) + } + + err = cc.UserChangePass("non-existent-user", newPassword) + if err == nil { + t.Fatalf("user password change for non-existent user should fail") + } + assert.Contains(t, err.Error(), "user name not found") + }) + }) + } +} diff --git a/tests/e2e/ctl_v3_auth_test.go b/tests/e2e/ctl_v3_auth_test.go index 6c75f5b06347..8c9980049dfd 100644 --- a/tests/e2e/ctl_v3_auth_test.go +++ b/tests/e2e/ctl_v3_auth_test.go @@ -1305,3 +1305,24 @@ func ctlV3EndpointHealth(cx ctlCtx) error { } return e2e.SpawnWithExpects(cmdArgs, cx.envMap, lines...) } + +func ctlV3User(cx ctlCtx, args []string, expStr string, stdIn []string) error { + cmdArgs := append(cx.PrefixArgs(), "user") + cmdArgs = append(cmdArgs, args...) + + proc, err := e2e.SpawnCmd(cmdArgs, cx.envMap) + if err != nil { + return err + } + defer proc.Close() + + // Send 'stdIn' strings as input. + for _, s := range stdIn { + if err = proc.Send(s + "\r"); err != nil { + return err + } + } + + _, err = proc.Expect(expStr) + return err +} diff --git a/tests/e2e/ctl_v3_user_test.go b/tests/e2e/ctl_v3_user_test.go deleted file mode 100644 index 1bda2045e795..000000000000 --- a/tests/e2e/ctl_v3_user_test.go +++ /dev/null @@ -1,209 +0,0 @@ -// Copyright 2016 The etcd Authors -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -package e2e - -import ( - "testing" - - "go.etcd.io/etcd/tests/v3/framework/e2e" -) - -func TestCtlV3UserAdd(t *testing.T) { testCtl(t, userAddTest) } -func TestCtlV3UserAddNoTLS(t *testing.T) { testCtl(t, userAddTest, withCfg(*e2e.NewConfigNoTLS())) } -func TestCtlV3UserAddClientTLS(t *testing.T) { - testCtl(t, userAddTest, withCfg(*e2e.NewConfigClientTLS())) -} -func TestCtlV3UserAddPeerTLS(t *testing.T) { testCtl(t, userAddTest, withCfg(*e2e.NewConfigPeerTLS())) } -func TestCtlV3UserAddTimeout(t *testing.T) { testCtl(t, userAddTest, withDialTimeout(0)) } -func TestCtlV3UserAddClientAutoTLS(t *testing.T) { - testCtl(t, userAddTest, withCfg(*e2e.NewConfigClientAutoTLS())) -} -func TestCtlV3UserList(t *testing.T) { testCtl(t, userListTest) } -func TestCtlV3UserListNoTLS(t *testing.T) { testCtl(t, userListTest, withCfg(*e2e.NewConfigNoTLS())) } -func TestCtlV3UserListClientTLS(t *testing.T) { - testCtl(t, userListTest, withCfg(*e2e.NewConfigClientTLS())) -} -func TestCtlV3UserListPeerTLS(t *testing.T) { - testCtl(t, userListTest, withCfg(*e2e.NewConfigPeerTLS())) -} -func TestCtlV3UserListClientAutoTLS(t *testing.T) { - testCtl(t, userListTest, withCfg(*e2e.NewConfigClientAutoTLS())) -} -func TestCtlV3UserDelete(t *testing.T) { testCtl(t, userDelTest) } -func TestCtlV3UserDeleteNoTLS(t *testing.T) { testCtl(t, userDelTest, withCfg(*e2e.NewConfigNoTLS())) } -func TestCtlV3UserDeleteClientTLS(t *testing.T) { - testCtl(t, userDelTest, withCfg(*e2e.NewConfigClientTLS())) -} -func TestCtlV3UserDeletePeerTLS(t *testing.T) { - testCtl(t, userDelTest, withCfg(*e2e.NewConfigPeerTLS())) -} -func TestCtlV3UserDeleteClientAutoTLS(t *testing.T) { - testCtl(t, userDelTest, withCfg(*e2e.NewConfigClientAutoTLS())) -} -func TestCtlV3UserPasswd(t *testing.T) { testCtl(t, userPasswdTest) } -func TestCtlV3UserPasswdNoTLS(t *testing.T) { - testCtl(t, userPasswdTest, withCfg(*e2e.NewConfigNoTLS())) -} -func TestCtlV3UserPasswdClientTLS(t *testing.T) { - testCtl(t, userPasswdTest, withCfg(*e2e.NewConfigClientTLS())) -} -func TestCtlV3UserPasswdPeerTLS(t *testing.T) { - testCtl(t, userPasswdTest, withCfg(*e2e.NewConfigPeerTLS())) -} -func TestCtlV3UserPasswdClientAutoTLS(t *testing.T) { - testCtl(t, userPasswdTest, withCfg(*e2e.NewConfigClientAutoTLS())) -} - -type userCmdDesc struct { - args []string - expectedStr string - stdIn []string -} - -func userAddTest(cx ctlCtx) { - cmdSet := []userCmdDesc{ - // Adds a user name. - { - args: []string{"add", "username", "--interactive=false"}, - expectedStr: "User username created", - stdIn: []string{"password"}, - }, - // Adds a user name using the usertest:password syntax. - { - args: []string{"add", "usertest:password"}, - expectedStr: "User usertest created", - stdIn: []string{}, - }, - // Tries to add a user with empty username. - { - args: []string{"add", ":password"}, - expectedStr: "empty user name is not allowed", - stdIn: []string{}, - }, - // Tries to add a user name that already exists. - { - args: []string{"add", "username", "--interactive=false"}, - expectedStr: "user name already exists", - stdIn: []string{"password"}, - }, - // Adds a user without password. - { - args: []string{"add", "userwopasswd", "--no-password"}, - expectedStr: "User userwopasswd created", - stdIn: []string{}, - }, - } - - for i, cmd := range cmdSet { - if err := ctlV3User(cx, cmd.args, cmd.expectedStr, cmd.stdIn); err != nil { - if cx.dialTimeout > 0 && !isGRPCTimedout(err) { - cx.t.Fatalf("userAddTest #%d: ctlV3User error (%v)", i, err) - } - } - } -} - -func userListTest(cx ctlCtx) { - cmdSet := []userCmdDesc{ - // Adds a user name. - { - args: []string{"add", "username", "--interactive=false"}, - expectedStr: "User username created", - stdIn: []string{"password"}, - }, - // List user name - { - args: []string{"list"}, - expectedStr: "username", - }, - } - - for i, cmd := range cmdSet { - if err := ctlV3User(cx, cmd.args, cmd.expectedStr, cmd.stdIn); err != nil { - cx.t.Fatalf("userListTest #%d: ctlV3User error (%v)", i, err) - } - } -} - -func userDelTest(cx ctlCtx) { - cmdSet := []userCmdDesc{ - // Adds a user name. - { - args: []string{"add", "username", "--interactive=false"}, - expectedStr: "User username created", - stdIn: []string{"password"}, - }, - // Deletes the user name just added. - { - args: []string{"delete", "username"}, - expectedStr: "User username deleted", - }, - // Deletes a user name that is not present. - { - args: []string{"delete", "username"}, - expectedStr: "user name not found", - }, - } - - for i, cmd := range cmdSet { - if err := ctlV3User(cx, cmd.args, cmd.expectedStr, cmd.stdIn); err != nil { - cx.t.Fatalf("userDelTest #%d: ctlV3User error (%v)", i, err) - } - } -} - -func userPasswdTest(cx ctlCtx) { - cmdSet := []userCmdDesc{ - // Adds a user name. - { - args: []string{"add", "username", "--interactive=false"}, - expectedStr: "User username created", - stdIn: []string{"password"}, - }, - // Changes the password. - { - args: []string{"passwd", "username", "--interactive=false"}, - expectedStr: "Password updated", - stdIn: []string{"password1"}, - }, - } - - for i, cmd := range cmdSet { - if err := ctlV3User(cx, cmd.args, cmd.expectedStr, cmd.stdIn); err != nil { - cx.t.Fatalf("userPasswdTest #%d: ctlV3User error (%v)", i, err) - } - } -} - -func ctlV3User(cx ctlCtx, args []string, expStr string, stdIn []string) error { - cmdArgs := append(cx.PrefixArgs(), "user") - cmdArgs = append(cmdArgs, args...) - - proc, err := e2e.SpawnCmd(cmdArgs, cx.envMap) - if err != nil { - return err - } - defer proc.Close() - - // Send 'stdIn' strings as input. - for _, s := range stdIn { - if err = proc.Send(s + "\r"); err != nil { - return err - } - } - - _, err = proc.Expect(expStr) - return err -} From 7a0c254b73b47c589f53643d3845c4d368eaa69a Mon Sep 17 00:00:00 2001 From: Hitoshi Mitake Date: Mon, 21 Mar 2022 22:25:58 +0900 Subject: [PATCH 208/258] tests/integration: re-enable TestV3AuthOldRevConcurrent --- tests/integration/v3_auth_test.go | 1 - 1 file changed, 1 deletion(-) diff --git a/tests/integration/v3_auth_test.go b/tests/integration/v3_auth_test.go index 4f4e53e97f04..741ddccb824e 100644 --- a/tests/integration/v3_auth_test.go +++ b/tests/integration/v3_auth_test.go @@ -358,7 +358,6 @@ func TestV3AuthNonAuthorizedRPCs(t *testing.T) { } func TestV3AuthOldRevConcurrent(t *testing.T) { - t.Skip() // TODO(jingyih): re-enable the test when #10408 is fixed. integration.BeforeTest(t) clus := integration.NewCluster(t, &integration.ClusterConfig{Size: 1}) defer clus.Terminate(t) From 44aad460db1ce67e543d0b425d7a01227d3b6d47 Mon Sep 17 00:00:00 2001 From: Marek Siarkowicz Date: Wed, 2 Mar 2022 12:09:44 +0100 Subject: [PATCH 209/258] tests: Migrate noquorum kv tests to common framework --- tests/common/kv_test.go | 39 +++++++++++++ tests/e2e/ctl_v3_kv_no_quorum_test.go | 83 --------------------------- tests/framework/config/client.go | 1 + tests/framework/e2e.go | 24 ++++++++ tests/framework/e2e/etcdctl.go | 3 + tests/framework/integration.go | 34 ++++++++++- tests/framework/interface.go | 7 +++ 7 files changed, 106 insertions(+), 85 deletions(-) delete mode 100644 tests/e2e/ctl_v3_kv_no_quorum_test.go diff --git a/tests/common/kv_test.go b/tests/common/kv_test.go index 6f5849ee9599..93bc8d774925 100644 --- a/tests/common/kv_test.go +++ b/tests/common/kv_test.go @@ -266,3 +266,42 @@ func TestKVDelete(t *testing.T) { }) } } + +func TestKVGetNoQuorum(t *testing.T) { + testRunner.BeforeTest(t) + tcs := []struct { + name string + options config.GetOptions + + wantError bool + }{ + { + name: "Serializable", + options: config.GetOptions{Serializable: true}, + }, + { + name: "Linearizable", + options: config.GetOptions{Serializable: false, Timeout: time.Second}, + wantError: true, + }, + } + for _, tc := range tcs { + t.Run(tc.name, func(t *testing.T) { + clus := testRunner.NewCluster(t, config.ClusterConfig{ClusterSize: 3}) + defer clus.Close() + + clus.Members()[0].Stop() + clus.Members()[1].Stop() + + cc := clus.Members()[2].Client() + testutils.ExecuteWithTimeout(t, 10*time.Second, func() { + key := "foo" + _, err := cc.Get(key, tc.options) + gotError := err != nil + if gotError != tc.wantError { + t.Fatalf("Unexpeted result, wantError: %v, gotErr: %v, err: %s", tc.wantError, gotError, err) + } + }) + }) + } +} diff --git a/tests/e2e/ctl_v3_kv_no_quorum_test.go b/tests/e2e/ctl_v3_kv_no_quorum_test.go deleted file mode 100644 index dbc599b49765..000000000000 --- a/tests/e2e/ctl_v3_kv_no_quorum_test.go +++ /dev/null @@ -1,83 +0,0 @@ -// Copyright 2021 The etcd Authors -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -// When the quorum isn't satisfied, then each etcd member isn't able to -// publish/register server information(i.e., clientURL) into the cluster. -// Accordingly, the v2 proxy can't get any member's clientURL, so this -// case will fail for sure in this case. -// -// todo(ahrtr): When v2 proxy is removed, then we can remove the go build -// lines below. -//go:build !cluster_proxy -// +build !cluster_proxy - -package e2e - -import ( - "testing" - - "go.etcd.io/etcd/tests/v3/framework/e2e" -) - -func TestSerializableReadWithoutQuorum(t *testing.T) { - tcs := []struct { - name string - testFunc func(cx ctlCtx) - }{ - { - name: "serializableReadTest", - testFunc: serializableReadTest, - }, - { - name: "linearizableReadTest", - testFunc: linearizableReadTest, - }, - } - for _, tc := range tcs { - t.Run(tc.name, func(t *testing.T) { - // Initialize a cluster with 3 members - epc, err := e2e.InitEtcdProcessCluster(t, e2e.NewConfigAutoTLS()) - if err != nil { - t.Fatalf("Failed to initilize the etcd cluster: %v", err) - } - - // Remove two members, so that only one etcd will get started - epc.Procs = epc.Procs[:1] - - // Start the etcd cluster with only one member - if err := epc.Start(); err != nil { - t.Fatalf("Failed to start the etcd cluster: %v", err) - } - - // construct the ctl context - cx := getDefaultCtlCtx(t) - cx.epc = epc - runCtlTest(t, tc.testFunc, nil, cx) - }) - } -} - -func serializableReadTest(cx ctlCtx) { - cx.quorum = false - if err := ctlV3Get(cx, []string{"key1"}, []kv{}...); err != nil { - cx.t.Errorf("serializableReadTest failed: %v", err) - } -} - -func linearizableReadTest(cx ctlCtx) { - cx.quorum = true - if err := ctlV3GetWithErr(cx, []string{"key"}, []string{"retrying of unary invoker failed"}); err != nil { // expect errors - cx.t.Fatalf("ctlV3GetWithErr error (%v)", err) - } -} diff --git a/tests/framework/config/client.go b/tests/framework/config/client.go index ef2ef9c273c0..63ee8bf54e2a 100644 --- a/tests/framework/config/client.go +++ b/tests/framework/config/client.go @@ -30,6 +30,7 @@ type GetOptions struct { Limit int Order clientv3.SortOrder SortBy clientv3.SortTarget + Timeout time.Duration } type PutOptions struct { diff --git a/tests/framework/e2e.go b/tests/framework/e2e.go index 8e068e3a846a..01528aed0e58 100644 --- a/tests/framework/e2e.go +++ b/tests/framework/e2e.go @@ -84,6 +84,30 @@ func (c *e2eCluster) Client() Client { return e2eClient{e2e.NewEtcdctl(c.Cfg, c.EndpointsV3())} } +func (c *e2eCluster) Members() (ms []Member) { + for _, proc := range c.EtcdProcessCluster.Procs { + ms = append(ms, e2eMember{EtcdProcess: proc, Cfg: c.Cfg}) + } + return ms +} + type e2eClient struct { *e2e.EtcdctlV3 } + +type e2eMember struct { + e2e.EtcdProcess + Cfg *e2e.EtcdProcessClusterConfig +} + +func (m e2eMember) Client() Client { + return e2eClient{e2e.NewEtcdctl(m.Cfg, m.EndpointsV3())} +} + +func (m e2eMember) Start() error { + return m.Restart() +} + +func (m e2eMember) Stop() { + m.EtcdProcess.Stop() +} diff --git a/tests/framework/e2e/etcdctl.go b/tests/framework/e2e/etcdctl.go index dd5f57e35027..6d697582fa20 100644 --- a/tests/framework/e2e/etcdctl.go +++ b/tests/framework/e2e/etcdctl.go @@ -42,6 +42,9 @@ func (ctl *EtcdctlV3) DowngradeEnable(version string) error { func (ctl *EtcdctlV3) Get(key string, o config.GetOptions) (*clientv3.GetResponse, error) { args := ctl.cmdArgs() + if o.Timeout != 0 { + args = append(args, fmt.Sprintf("--command-timeout=%s", o.Timeout)) + } if o.Serializable { args = append(args, "--consistency", "s") } diff --git a/tests/framework/integration.go b/tests/framework/integration.go index f5867da4633d..c580a19f0623 100644 --- a/tests/framework/integration.go +++ b/tests/framework/integration.go @@ -81,6 +81,30 @@ type integrationCluster struct { t testing.TB } +func (c *integrationCluster) Members() (ms []Member) { + for _, m := range c.Cluster.Members { + ms = append(ms, integrationMember{m, c.t}) + } + return ms +} + +type integrationMember struct { + *integration.Member + t testing.TB +} + +func (m integrationMember) Client() Client { + return integrationClient{m.Member.Client} +} + +func (m integrationMember) Start() error { + return m.Member.Restart(m.t) +} + +func (m integrationMember) Stop() { + m.Member.Stop(m.t) +} + func (c *integrationCluster) Close() error { c.Terminate(c.t) return nil @@ -91,7 +115,7 @@ func (c *integrationCluster) Client() Client { if err != nil { c.t.Fatal(err) } - return &integrationClient{cc} + return integrationClient{cc} } type integrationClient struct { @@ -99,6 +123,12 @@ type integrationClient struct { } func (c integrationClient) Get(key string, o config.GetOptions) (*clientv3.GetResponse, error) { + ctx := context.Background() + if o.Timeout != 0 { + var cancel context.CancelFunc + ctx, cancel = context.WithTimeout(ctx, o.Timeout) + defer cancel() + } clientOpts := []clientv3.OpOption{} if o.Revision != 0 { clientOpts = append(clientOpts, clientv3.WithRev(int64(o.Revision))) @@ -124,7 +154,7 @@ func (c integrationClient) Get(key string, o config.GetOptions) (*clientv3.GetRe if o.SortBy != clientv3.SortByKey || o.Order != clientv3.SortNone { clientOpts = append(clientOpts, clientv3.WithSort(o.SortBy, o.Order)) } - return c.Client.Get(context.Background(), key, clientOpts...) + return c.Client.Get(ctx, key, clientOpts...) } func (c integrationClient) Put(key, value string, opts config.PutOptions) error { diff --git a/tests/framework/interface.go b/tests/framework/interface.go index 8460483dd572..c391056c4cd5 100644 --- a/tests/framework/interface.go +++ b/tests/framework/interface.go @@ -28,8 +28,15 @@ type testRunner interface { } type Cluster interface { + Members() []Member + Client() Client Close() error +} + +type Member interface { Client() Client + Start() error + Stop() } type Client interface { From 37804358312c886a260331ad246f41bb1e1a6e6d Mon Sep 17 00:00:00 2001 From: ahrtr Date: Tue, 22 Mar 2022 06:24:32 +0800 Subject: [PATCH 210/258] added unit test for newClientCfg --- etcdctl/ctlv3/command/global_test.go | 131 +++++++++++++++++++++++++++ etcdctl/go.mod | 4 + etcdctl/go.sum | 3 + 3 files changed, 138 insertions(+) create mode 100644 etcdctl/ctlv3/command/global_test.go diff --git a/etcdctl/ctlv3/command/global_test.go b/etcdctl/ctlv3/command/global_test.go new file mode 100644 index 000000000000..0dc56abdd25f --- /dev/null +++ b/etcdctl/ctlv3/command/global_test.go @@ -0,0 +1,131 @@ +// Copyright 2022 The etcd Authors +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package command + +import ( + "crypto/tls" + + "go.uber.org/zap" + "testing" + "time" + + "github.com/stretchr/testify/assert" + "go.etcd.io/etcd/client/pkg/v3/transport" + clientv3 "go.etcd.io/etcd/client/v3" +) + +func TestNewClientConfig(t *testing.T) { + cases := []struct { + name string + spec clientv3.ConfigSpec + expectedConf clientv3.Config + }{ + { + name: "default secure transport", + spec: clientv3.ConfigSpec{ + Endpoints: []string{"http://192.168.0.10:2379"}, + DialTimeout: 2 * time.Second, + KeepAliveTime: 3 * time.Second, + KeepAliveTimeout: 5 * time.Second, + Secure: &clientv3.SecureConfig{ + InsecureTransport: false, + }, + }, + expectedConf: clientv3.Config{ + Endpoints: []string{"http://192.168.0.10:2379"}, + DialTimeout: 2 * time.Second, + DialKeepAliveTime: 3 * time.Second, + DialKeepAliveTimeout: 5 * time.Second, + TLS: &tls.Config{}, + }, + }, + { + name: "default secure transport and auth enabled", + spec: clientv3.ConfigSpec{ + Endpoints: []string{"http://192.168.0.12:2379"}, + DialTimeout: 1 * time.Second, + KeepAliveTime: 4 * time.Second, + KeepAliveTimeout: 6 * time.Second, + Secure: &clientv3.SecureConfig{ + InsecureTransport: false, + }, + Auth: &clientv3.AuthConfig{ + Username: "test", + Password: "changeme", + }, + }, + expectedConf: clientv3.Config{ + Endpoints: []string{"http://192.168.0.12:2379"}, + DialTimeout: 1 * time.Second, + DialKeepAliveTime: 4 * time.Second, + DialKeepAliveTimeout: 6 * time.Second, + TLS: &tls.Config{}, + Username: "test", + Password: "changeme", + }, + }, + { + name: "default secure transport and skip TLS verification", + spec: clientv3.ConfigSpec{ + Endpoints: []string{"http://192.168.0.13:2379"}, + DialTimeout: 1 * time.Second, + KeepAliveTime: 3 * time.Second, + KeepAliveTimeout: 5 * time.Second, + Secure: &clientv3.SecureConfig{ + InsecureTransport: false, + InsecureSkipVerify: true, + }, + }, + expectedConf: clientv3.Config{ + Endpoints: []string{"http://192.168.0.13:2379"}, + DialTimeout: 1 * time.Second, + DialKeepAliveTime: 3 * time.Second, + DialKeepAliveTimeout: 5 * time.Second, + TLS: &tls.Config{ + InsecureSkipVerify: true, + }, + }, + }, + } + + for _, tc := range cases { + t.Run(tc.name, func(t *testing.T) { + cfg, err := newClientCfg(tc.spec.Endpoints, tc.spec.DialTimeout, tc.spec.KeepAliveTime, tc.spec.KeepAliveTimeout, tc.spec.Secure, tc.spec.Auth) + if err != nil { + t.Fatalf("Unexpected error: %v", err) + } + + assert.Equal(t, tc.expectedConf, *cfg) + }) + } +} + +func TestNewClientConfigWithSecureCfg(t *testing.T) { + tls, err := transport.SelfCert(zap.NewNop(), t.TempDir(), []string{"localhost"}, 1) + if err != nil { + t.Fatalf("Unexpected error: %v", err) + } + + scfg := &clientv3.SecureConfig{ + Cert: tls.CertFile, + Key: tls.KeyFile, + Cacert: tls.TrustedCAFile, + } + + cfg, err := newClientCfg([]string{"http://192.168.0.13:2379"}, 2*time.Second, 3*time.Second, 5*time.Second, scfg, nil) + if cfg == nil || err != nil { + t.Fatalf("Unexpected result client config: %v", err) + } +} diff --git a/etcdctl/go.mod b/etcdctl/go.mod index d6b770a4d614..49ded5f42e76 100644 --- a/etcdctl/go.mod +++ b/etcdctl/go.mod @@ -8,6 +8,7 @@ require ( github.com/olekukonko/tablewriter v0.0.5 github.com/spf13/cobra v1.2.1 github.com/spf13/pflag v1.0.5 + github.com/stretchr/testify v1.7.0 github.com/urfave/cli v1.22.4 go.etcd.io/etcd/api/v3 v3.6.0-alpha.0 go.etcd.io/etcd/client/pkg/v3 v3.6.0-alpha.0 @@ -27,6 +28,7 @@ require ( github.com/coreos/go-semver v0.3.0 // indirect github.com/coreos/go-systemd/v22 v22.3.2 // indirect github.com/cpuguy83/go-md2man/v2 v2.0.0 // indirect + github.com/davecgh/go-spew v1.1.1 // indirect github.com/gogo/protobuf v1.3.2 // indirect github.com/golang-jwt/jwt v3.2.2+incompatible // indirect github.com/golang/protobuf v1.5.2 // indirect @@ -35,6 +37,7 @@ require ( github.com/jonboulle/clockwork v0.2.2 // indirect github.com/mattn/go-runewidth v0.0.9 // indirect github.com/matttproud/golang_protobuf_extensions v1.0.1 // indirect + github.com/pmezard/go-difflib v1.0.0 // indirect github.com/prometheus/client_golang v1.11.0 // indirect github.com/prometheus/client_model v0.2.0 // indirect github.com/prometheus/common v0.26.0 // indirect @@ -56,6 +59,7 @@ require ( golang.org/x/text v0.3.7 // indirect google.golang.org/genproto v0.0.0-20211118181313-81c1377c94b1 // indirect google.golang.org/protobuf v1.27.1 // indirect + gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b // indirect sigs.k8s.io/json v0.0.0-20211020170558-c049b76a60c6 // indirect ) diff --git a/etcdctl/go.sum b/etcdctl/go.sum index af19c33748f5..5e8427fda7ab 100644 --- a/etcdctl/go.sum +++ b/etcdctl/go.sum @@ -242,9 +242,11 @@ github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxv github.com/konsorten/go-windows-terminal-sequences v1.0.3/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= github.com/kr/fs v0.1.0/go.mod h1:FFnZGqtBN9Gxj7eW1uZ42v5BccTP0vu6NEaFoC2HwRg= github.com/kr/logfmt v0.0.0-20140226030751-b84e30acd515/go.mod h1:+0opPa2QZZtGFBFZlji/RkVcI2GknAs/DXo4wKdlNEc= +github.com/kr/pretty v0.1.0 h1:L/CwN0zerZDmRFUapSPitk6f+Q3+0za1rQkzVuMiMFI= github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo= github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= +github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY= github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE= github.com/magiconair/properties v1.8.5/go.mod h1:y3VJvCyxH9uVvJTWEGAELF3aiYNyPKd5NZ3oSwXrF60= github.com/mattn/go-colorable v0.0.9 h1:UVL0vNpWh04HeJXV0KLcaT7r06gOH2l4OW6ddYRUIY4= @@ -729,6 +731,7 @@ google.golang.org/protobuf v1.27.1/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQ gopkg.in/alecthomas/kingpin.v2 v2.2.6/go.mod h1:FMv+mEhP44yOT+4EoQTLFTRgOQ1FBLkstjWtayDeSgw= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15 h1:YR8cESwS4TdDjEe65xsg0ogRM/Nc3DYOhEAlW+xobZo= gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/cheggaaa/pb.v1 v1.0.28 h1:n1tBJnnK2r7g9OW2btFH91V92STTUevLXYFb8gy9EMk= gopkg.in/cheggaaa/pb.v1 v1.0.28/go.mod h1:V/YB90LKu/1FcN3WVnfiiE5oMCibMjukxqG/qStrOgw= From 1649c9dfc216fa468ffe5c88759c6429a385f8be Mon Sep 17 00:00:00 2001 From: Kun Zhang Date: Wed, 23 Mar 2022 11:05:52 +0800 Subject: [PATCH 211/258] Removing deprecated commands in etcdctl & etcdutl --- CHANGELOG/CHANGELOG-3.6.md | 5 ++ etcdctl/README.md | 76 +---------------------- etcdctl/ctlv3/command/snapshot_command.go | 71 --------------------- etcdutl/README.md | 30 +++------ etcdutl/etcdutl/snapshot_command.go | 16 ----- tests/e2e/ctl_v3_snapshot_test.go | 7 +-- 6 files changed, 16 insertions(+), 189 deletions(-) diff --git a/CHANGELOG/CHANGELOG-3.6.md b/CHANGELOG/CHANGELOG-3.6.md index 06c5c6d6200b..c28da261e9eb 100644 --- a/CHANGELOG/CHANGELOG-3.6.md +++ b/CHANGELOG/CHANGELOG-3.6.md @@ -16,6 +16,11 @@ See [code changes](https://github.com/etcd-io/etcd/compare/v3.5.0...v3.6.0). ### Deprecations - Deprecated [V2 discovery](https://etcd.io/docs/v3.5/dev-internal/discovery_protocol/). +- Removed [etcdctl defrag --data-dir](https://github.com/etcd-io/etcd/pull/13793). +- Removed [etcdctl snapshot status](https://github.com/etcd-io/etcd/pull/13809). +- Removed [etcdctl snapshot restore](https://github.com/etcd-io/etcd/pull/13809). +- Removed [etcdutl snapshot save](https://github.com/etcd-io/etcd/pull/13809). + ### etcdctl v3 diff --git a/etcdctl/README.md b/etcdctl/README.md index 990a3fdcd18f..e3f00d0d33ef 100644 --- a/etcdctl/README.md +++ b/etcdctl/README.md @@ -968,84 +968,12 @@ Save a snapshot to "snapshot.db": ### SNAPSHOT RESTORE [options] \ -Note: Deprecated. Use `etcdutl snapshot restore` instead. To be removed in v3.6. +Removed in v3.6. Use `etcdutl snapshot restore` instead. -SNAPSHOT RESTORE creates an etcd data directory for an etcd cluster member from a backend database snapshot and a new cluster configuration. Restoring the snapshot into each member for a new cluster configuration will initialize a new etcd cluster preloaded by the snapshot data. - -#### Options - -The snapshot restore options closely resemble to those used in the `etcd` command for defining a cluster. - -- data-dir -- Path to the data directory. Uses \.etcd if none given. - -- wal-dir -- Path to the WAL directory. Uses data directory if none given. - -- initial-cluster -- The initial cluster configuration for the restored etcd cluster. - -- initial-cluster-token -- Initial cluster token for the restored etcd cluster. - -- initial-advertise-peer-urls -- List of peer URLs for the member being restored. - -- name -- Human-readable name for the etcd cluster member being restored. - -- skip-hash-check -- Ignore snapshot integrity hash value (required if copied from data directory) - -#### Output - -A new etcd data directory initialized with the snapshot. - -#### Example - -Save a snapshot, restore into a new 3 node cluster, and start the cluster: -``` -./etcdctl snapshot save snapshot.db - -# restore members -bin/etcdctl snapshot restore snapshot.db --initial-cluster-token etcd-cluster-1 --initial-advertise-peer-urls http://127.0.0.1:12380 --name sshot1 --initial-cluster 'sshot1=http://127.0.0.1:12380,sshot2=http://127.0.0.1:22380,sshot3=http://127.0.0.1:32380' -bin/etcdctl snapshot restore snapshot.db --initial-cluster-token etcd-cluster-1 --initial-advertise-peer-urls http://127.0.0.1:22380 --name sshot2 --initial-cluster 'sshot1=http://127.0.0.1:12380,sshot2=http://127.0.0.1:22380,sshot3=http://127.0.0.1:32380' -bin/etcdctl snapshot restore snapshot.db --initial-cluster-token etcd-cluster-1 --initial-advertise-peer-urls http://127.0.0.1:32380 --name sshot3 --initial-cluster 'sshot1=http://127.0.0.1:12380,sshot2=http://127.0.0.1:22380,sshot3=http://127.0.0.1:32380' - -# launch members -bin/etcd --name sshot1 --listen-client-urls http://127.0.0.1:2379 --advertise-client-urls http://127.0.0.1:2379 --listen-peer-urls http://127.0.0.1:12380 & -bin/etcd --name sshot2 --listen-client-urls http://127.0.0.1:22379 --advertise-client-urls http://127.0.0.1:22379 --listen-peer-urls http://127.0.0.1:22380 & -bin/etcd --name sshot3 --listen-client-urls http://127.0.0.1:32379 --advertise-client-urls http://127.0.0.1:32379 --listen-peer-urls http://127.0.0.1:32380 & -``` ### SNAPSHOT STATUS \ -Note: Deprecated. Use `etcdutl snapshot restore` instead. To be removed in v3.6. - -SNAPSHOT STATUS lists information about a given backend database snapshot file. - -#### Output - -##### Simple format - -Prints a humanized table of the database hash, revision, total keys, and size. - -##### JSON format - -Prints a line of JSON encoding the database hash, revision, total keys, and size. - -#### Examples -```bash -./etcdctl snapshot status file.db -# cf1550fb, 3, 3, 25 kB -``` - -```bash -./etcdctl --write-out=json snapshot status file.db -# {"hash":3474280699,"revision":3,"totalKey":3,"totalSize":24576} -``` - -```bash -./etcdctl --write-out=table snapshot status file.db -+----------+----------+------------+------------+ -| HASH | REVISION | TOTAL KEYS | TOTAL SIZE | -+----------+----------+------------+------------+ -| cf1550fb | 3 | 3 | 25 kB | -+----------+----------+------------+------------+ -``` +Removed in v3.6. Use `etcdutl snapshot status` instead. ### MOVE-LEADER \ diff --git a/etcdctl/ctlv3/command/snapshot_command.go b/etcdctl/ctlv3/command/snapshot_command.go index ea52f3a269ca..1b32a4d20234 100644 --- a/etcdctl/ctlv3/command/snapshot_command.go +++ b/etcdctl/ctlv3/command/snapshot_command.go @@ -17,30 +17,13 @@ package command import ( "context" "fmt" - "os" "github.com/spf13/cobra" snapshot "go.etcd.io/etcd/client/v3/snapshot" - "go.etcd.io/etcd/etcdutl/v3/etcdutl" "go.etcd.io/etcd/pkg/v3/cobrautl" "go.uber.org/zap" ) -const ( - defaultName = "default" - defaultInitialAdvertisePeerURLs = "http://localhost:2380" -) - -var ( - restoreCluster string - restoreClusterToken string - restoreDataDir string - restoreWalDir string - restorePeerURLs string - restoreName string - skipHashCheck bool -) - // NewSnapshotCommand returns the cobra command for "snapshot". func NewSnapshotCommand() *cobra.Command { cmd := &cobra.Command{ @@ -48,8 +31,6 @@ func NewSnapshotCommand() *cobra.Command { Short: "Manages etcd node snapshots", } cmd.AddCommand(NewSnapshotSaveCommand()) - cmd.AddCommand(NewSnapshotRestoreCommand()) - cmd.AddCommand(newSnapshotStatusCommand()) return cmd } @@ -61,39 +42,6 @@ func NewSnapshotSaveCommand() *cobra.Command { } } -func newSnapshotStatusCommand() *cobra.Command { - return &cobra.Command{ - Use: "status ", - Short: "[deprecated] Gets backend snapshot status of a given file", - Long: `When --write-out is set to simple, this command prints out comma-separated status lists for each endpoint. -The items in the lists are hash, revision, total keys, total size. - -Moved to 'etcdctl snapshot status ...' -`, - Run: snapshotStatusCommandFunc, - } -} - -func NewSnapshotRestoreCommand() *cobra.Command { - cmd := &cobra.Command{ - Use: "restore [options]", - Short: "Restores an etcd member snapshot to an etcd directory", - Run: snapshotRestoreCommandFunc, - Long: "Moved to `etcdctl snapshot restore ...`\n", - } - cmd.Flags().StringVar(&restoreDataDir, "data-dir", "", "Path to the data directory") - cmd.Flags().StringVar(&restoreWalDir, "wal-dir", "", "Path to the WAL directory (use --data-dir if none given)") - cmd.Flags().StringVar(&restoreCluster, "initial-cluster", initialClusterFromName(defaultName), "Initial cluster configuration for restore bootstrap") - cmd.Flags().StringVar(&restoreClusterToken, "initial-cluster-token", "etcd-cluster", "Initial cluster token for the etcd cluster during restore bootstrap") - cmd.Flags().StringVar(&restorePeerURLs, "initial-advertise-peer-urls", defaultInitialAdvertisePeerURLs, "List of this member's peer URLs to advertise to the rest of the cluster") - cmd.Flags().StringVar(&restoreName, "name", defaultName, "Human-readable name for this member") - cmd.Flags().BoolVar(&skipHashCheck, "skip-hash-check", false, "Ignore snapshot integrity hash value (required if copied from data directory)") - cmd.MarkFlagDirname("data-dir") - cmd.MarkFlagDirname("wal-dir") - - return cmd -} - func snapshotSaveCommandFunc(cmd *cobra.Command, args []string) { if len(args) != 1 { err := fmt.Errorf("snapshot save expects one argument") @@ -123,22 +71,3 @@ func snapshotSaveCommandFunc(cmd *cobra.Command, args []string) { fmt.Printf("Server version %s\n", version) } } - -func snapshotStatusCommandFunc(cmd *cobra.Command, args []string) { - fmt.Fprintf(os.Stderr, "Deprecated: Use `etcdutl snapshot status` instead.\n\n") - etcdutl.SnapshotStatusCommandFunc(cmd, args) -} - -func snapshotRestoreCommandFunc(cmd *cobra.Command, args []string) { - fmt.Fprintf(os.Stderr, "Deprecated: Use `etcdutl snapshot restore` instead.\n\n") - etcdutl.SnapshotRestoreCommandFunc(restoreCluster, restoreClusterToken, restoreDataDir, restoreWalDir, - restorePeerURLs, restoreName, skipHashCheck, args) -} - -func initialClusterFromName(name string) string { - n := name - if name == "" { - n = defaultName - } - return fmt.Sprintf("%s=http://localhost:2380", n) -} diff --git a/etcdutl/README.md b/etcdutl/README.md index 966a615110e1..6943a047858a 100644 --- a/etcdutl/README.md +++ b/etcdutl/README.md @@ -67,17 +67,18 @@ A new etcd data directory initialized with the snapshot. Save a snapshot, restore into a new 3 node cluster, and start the cluster: ``` -./etcdutl snapshot save snapshot.db +# save snapshot +./etcdctl snapshot save snapshot.db # restore members -bin/etcdutl snapshot restore snapshot.db --initial-cluster-token etcd-cluster-1 --initial-advertise-peer-urls http://127.0.0.1:12380 --name sshot1 --initial-cluster 'sshot1=http://127.0.0.1:12380,sshot2=http://127.0.0.1:22380,sshot3=http://127.0.0.1:32380' -bin/etcdutl snapshot restore snapshot.db --initial-cluster-token etcd-cluster-1 --initial-advertise-peer-urls http://127.0.0.1:22380 --name sshot2 --initial-cluster 'sshot1=http://127.0.0.1:12380,sshot2=http://127.0.0.1:22380,sshot3=http://127.0.0.1:32380' -bin/etcdutl snapshot restore snapshot.db --initial-cluster-token etcd-cluster-1 --initial-advertise-peer-urls http://127.0.0.1:32380 --name sshot3 --initial-cluster 'sshot1=http://127.0.0.1:12380,sshot2=http://127.0.0.1:22380,sshot3=http://127.0.0.1:32380' +./etcdutl snapshot restore snapshot.db --initial-cluster-token etcd-cluster-1 --initial-advertise-peer-urls http://127.0.0.1:12380 --name sshot1 --initial-cluster 'sshot1=http://127.0.0.1:12380,sshot2=http://127.0.0.1:22380,sshot3=http://127.0.0.1:32380' +./etcdutl snapshot restore snapshot.db --initial-cluster-token etcd-cluster-1 --initial-advertise-peer-urls http://127.0.0.1:22380 --name sshot2 --initial-cluster 'sshot1=http://127.0.0.1:12380,sshot2=http://127.0.0.1:22380,sshot3=http://127.0.0.1:32380' +./etcdutl snapshot restore snapshot.db --initial-cluster-token etcd-cluster-1 --initial-advertise-peer-urls http://127.0.0.1:32380 --name sshot3 --initial-cluster 'sshot1=http://127.0.0.1:12380,sshot2=http://127.0.0.1:22380,sshot3=http://127.0.0.1:32380' # launch members -bin/etcd --name sshot1 --listen-client-urls http://127.0.0.1:2379 --advertise-client-urls http://127.0.0.1:2379 --listen-peer-urls http://127.0.0.1:12380 & -bin/etcd --name sshot2 --listen-client-urls http://127.0.0.1:22379 --advertise-client-urls http://127.0.0.1:22379 --listen-peer-urls http://127.0.0.1:22380 & -bin/etcd --name sshot3 --listen-client-urls http://127.0.0.1:32379 --advertise-client-urls http://127.0.0.1:32379 --listen-peer-urls http://127.0.0.1:32380 & +./etcd --name sshot1 --listen-client-urls http://127.0.0.1:2379 --advertise-client-urls http://127.0.0.1:2379 --listen-peer-urls http://127.0.0.1:12380 & +./etcd --name sshot2 --listen-client-urls http://127.0.0.1:22379 --advertise-client-urls http://127.0.0.1:22379 --listen-peer-urls http://127.0.0.1:22380 & +./etcd --name sshot3 --listen-client-urls http://127.0.0.1:32379 --advertise-client-urls http://127.0.0.1:32379 --listen-peer-urls http://127.0.0.1:32380 & ``` ### SNAPSHOT STATUS \ @@ -124,21 +125,6 @@ Prints etcd version and API version. #### Examples -```bash -./etcdutl version -# etcdutl version: 3.1.0-alpha.0+git -# API version: 3.1 -``` - -### VERSION - -Prints the version of etcdctl. - -#### Output - -Prints etcd version and API version. - -#### Examples ```bash ./etcdutl version diff --git a/etcdutl/etcdutl/snapshot_command.go b/etcdutl/etcdutl/snapshot_command.go index 1b3f5ef6b9f4..28df31f8dd02 100644 --- a/etcdutl/etcdutl/snapshot_command.go +++ b/etcdutl/etcdutl/snapshot_command.go @@ -46,27 +46,11 @@ func NewSnapshotCommand() *cobra.Command { Use: "snapshot ", Short: "Manages etcd node snapshots", } - cmd.AddCommand(NewSnapshotSaveCommand()) cmd.AddCommand(NewSnapshotRestoreCommand()) cmd.AddCommand(newSnapshotStatusCommand()) return cmd } -func NewSnapshotSaveCommand() *cobra.Command { - return &cobra.Command{ - Use: "save ", - Short: "Stores an etcd node backend snapshot to a given file", - Hidden: true, - DisableFlagsInUseLine: true, - Run: func(cmd *cobra.Command, args []string) { - cobrautl.ExitWithError(cobrautl.ExitBadArgs, - fmt.Errorf("In order to download snapshot use: "+ - "`etcdctl snapshot save ...`")) - }, - Deprecated: "Use `etcdctl snapshot save` to download snapshot", - } -} - func newSnapshotStatusCommand() *cobra.Command { return &cobra.Command{ Use: "status ", diff --git a/tests/e2e/ctl_v3_snapshot_test.go b/tests/e2e/ctl_v3_snapshot_test.go index 59e1dc770f27..f67c605c5f87 100644 --- a/tests/e2e/ctl_v3_snapshot_test.go +++ b/tests/e2e/ctl_v3_snapshot_test.go @@ -62,7 +62,6 @@ func snapshotTest(cx ctlCtx) { } } -func TestCtlV3SnapshotCorrupt(t *testing.T) { testCtl(t, snapshotCorruptTest) } func TestCtlV3SnapshotCorruptEtcdutl(t *testing.T) { testCtl(t, snapshotCorruptTest, withEtcdutl()) } func snapshotCorruptTest(cx ctlCtx) { @@ -98,7 +97,6 @@ func snapshotCorruptTest(cx ctlCtx) { } // This test ensures that the snapshot status does not modify the snapshot file -func TestCtlV3SnapshotStatusBeforeRestore(t *testing.T) { testCtl(t, snapshotStatusBeforeRestoreTest) } func TestCtlV3SnapshotStatusBeforeRestoreEtcdutl(t *testing.T) { testCtl(t, snapshotStatusBeforeRestoreTest, withEtcdutl()) } @@ -136,6 +134,7 @@ func ctlV3SnapshotSave(cx ctlCtx, fpath string) error { } func getSnapshotStatus(cx ctlCtx, fpath string) (snapshot.Status, error) { + cx.etcdutl = true cmdArgs := append(cx.PrefixArgsUtl(), "--write-out", "json", "snapshot", "status", fpath) proc, err := e2e.SpawnCmd(cmdArgs, nil) @@ -159,7 +158,6 @@ func getSnapshotStatus(cx ctlCtx, fpath string) (snapshot.Status, error) { return resp, nil } -func TestIssue6361(t *testing.T) { testIssue6361(t, false) } func TestIssue6361etcdutl(t *testing.T) { testIssue6361(t, true) } // TestIssue6361 ensures new member that starts with snapshot correctly @@ -294,9 +292,6 @@ func testIssue6361(t *testing.T, etcdutl bool) { // For storageVersion to be stored, all fields expected 3.6 fields need to be set. This happens after first WAL snapshot. // In this test we lower SnapshotCount to 1 to ensure WAL snapshot is triggered. -func TestCtlV3SnapshotVersion(t *testing.T) { - testCtl(t, snapshotVersionTest, withCfg(e2e.EtcdProcessClusterConfig{SnapshotCount: 1})) -} func TestCtlV3SnapshotVersionEtcdutl(t *testing.T) { testCtl(t, snapshotVersionTest, withEtcdutl(), withCfg(e2e.EtcdProcessClusterConfig{SnapshotCount: 1})) } From 780e3ae935c4964ad16d18337a5d9a43ad40fd3b Mon Sep 17 00:00:00 2001 From: ahrtr Date: Wed, 23 Mar 2022 14:22:37 +0800 Subject: [PATCH 212/258] update 3.5 changelog to cover the fix for the watchablestore runlock bug --- CHANGELOG/CHANGELOG-3.5.md | 1 + CHANGELOG/CHANGELOG-3.6.md | 1 + 2 files changed, 2 insertions(+) diff --git a/CHANGELOG/CHANGELOG-3.5.md b/CHANGELOG/CHANGELOG-3.5.md index 526e86147c0a..6bf16109d38e 100644 --- a/CHANGELOG/CHANGELOG-3.5.md +++ b/CHANGELOG/CHANGELOG-3.5.md @@ -31,6 +31,7 @@ See [code changes](https://github.com/etcd-io/etcd/compare/v3.5.1...v3.5.2) and - Add [`etcd --experimental-enable-lease-checkpoint-persist`](https://github.com/etcd-io/etcd/pull/13508) flag to enable checkpoint persisting. - Fix [Lease checkpoints don't prevent to reset ttl on leader change](https://github.com/etcd-io/etcd/pull/13508), requires enabling checkpoint persisting. - Fix [assertion failed due to tx closed when recovering v3 backend from a snapshot db](https://github.com/etcd-io/etcd/pull/13501) +- Fix [segmentation violation(SIGSEGV) error due to premature unlocking of watchableStore](https://github.com/etcd-io/etcd/pull/13541)


diff --git a/CHANGELOG/CHANGELOG-3.6.md b/CHANGELOG/CHANGELOG-3.6.md index f33b697bf5a3..6d6e1f1787a8 100644 --- a/CHANGELOG/CHANGELOG-3.6.md +++ b/CHANGELOG/CHANGELOG-3.6.md @@ -57,6 +57,7 @@ See [code changes](https://github.com/etcd-io/etcd/compare/v3.5.0...v3.6.0). - Fix [etcd gateway doesn't format the endpoint of IPv6 address correctly](https://github.com/etcd-io/etcd/pull/13551) - Fix [A client can cause a nil dereference in etcd by passing an invalid SortTarget](https://github.com/etcd-io/etcd/pull/13555) - Fix [Grant lease with negative ID can possibly cause db out of sync](https://github.com/etcd-io/etcd/pull/13676) +- Fix [segmentation violation(SIGSEGV) error due to premature unlocking of watchableStore](https://github.com/etcd-io/etcd/pull/13505) ### tools/benchmark From bbc81bb6b72682cf54a1172f765855a351033746 Mon Sep 17 00:00:00 2001 From: ahrtr Date: Wed, 23 Mar 2022 13:33:49 +0800 Subject: [PATCH 213/258] enhance etcd-dump-db to display keys in meta more friendly --- tools/etcd-dump-db/backend.go | 16 +++++++++++++++- 1 file changed, 15 insertions(+), 1 deletion(-) diff --git a/tools/etcd-dump-db/backend.go b/tools/etcd-dump-db/backend.go index 3306f7f70b4d..0be477b4ec11 100644 --- a/tools/etcd-dump-db/backend.go +++ b/tools/etcd-dump-db/backend.go @@ -53,12 +53,14 @@ func getBuckets(dbPath string) (buckets []string, err error) { type decoder func(k, v []byte) +// key is the bucket name, and value is the function to decode K/V in the bucket. var decoders = map[string]decoder{ "key": keyDecoder, "lease": leaseDecoder, "auth": authDecoder, "authRoles": authRolesDecoder, "authUsers": authUsersDecoder, + "meta": metaDecoder, } type revision struct { @@ -73,6 +75,10 @@ func bytesToRev(bytes []byte) revision { } } +func defaultDecoder(k, v []byte) { + fmt.Printf("key=%q, value=%q\n", k, v) +} + func keyDecoder(k, v []byte) { rev := bytesToRev(k) var kv mvccpb.KeyValue @@ -125,6 +131,14 @@ func authUsersDecoder(k, v []byte) { fmt.Printf("user=%q, roles=%q, option=%v\n", user.Name, user.Roles, user.Options) } +func metaDecoder(k, v []byte) { + if string(k) == string(schema.MetaConsistentIndexKeyName) || string(k) == string(schema.MetaTermKeyName) { + fmt.Printf("key=%q, value=%v\n", k, binary.BigEndian.Uint64(v)) + } else { + defaultDecoder(k, v) + } +} + func iterateBucket(dbPath, bucket string, limit uint64, decode bool) (err error) { db, err := bolt.Open(dbPath, 0600, &bolt.Options{Timeout: flockTimeout}) if err != nil { @@ -147,7 +161,7 @@ func iterateBucket(dbPath, bucket string, limit uint64, decode bool) (err error) if dec, ok := decoders[bucket]; decode && ok { dec(k, v) } else { - fmt.Printf("key=%q, value=%q\n", k, v) + defaultDecoder(k, v) } limit-- From bd7d09255beb8726e0c0bfbea37670ff3d5175f8 Mon Sep 17 00:00:00 2001 From: EXEC Date: Sat, 19 Mar 2022 17:48:30 +0800 Subject: [PATCH 214/258] Fix panic in etcd validate secure endpoints #13810 `ValidateSecureEndpoints()` should call `t.DialContext()` instead of `t.Dial()`, because `t.Dial` is `nil` --- client/pkg/transport/tls.go | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/client/pkg/transport/tls.go b/client/pkg/transport/tls.go index 62fe0d385195..d99b772e38e2 100644 --- a/client/pkg/transport/tls.go +++ b/client/pkg/transport/tls.go @@ -15,6 +15,7 @@ package transport import ( + "context" "fmt" "strings" "time" @@ -34,7 +35,7 @@ func ValidateSecureEndpoints(tlsInfo TLSInfo, eps []string) ([]string, error) { errs = append(errs, fmt.Sprintf("%q is insecure", ep)) continue } - conn, cerr := t.Dial("tcp", ep[len("https://"):]) + conn, cerr := t.DialContext(context.Background(), "tcp", ep[len("https://"):]) if cerr != nil { errs = append(errs, fmt.Sprintf("%q failed to dial (%v)", ep, cerr)) continue From 983ee82c98570069f94287d11494cfb26aac90fc Mon Sep 17 00:00:00 2001 From: eval-exec Date: Sun, 20 Mar 2022 09:38:24 +0800 Subject: [PATCH 215/258] add test for transport/tls.go:ValidateSecureEndpoints() --- client/pkg/transport/tls_test.go | 36 ++++++++++++++++++++++++++++++++ 1 file changed, 36 insertions(+) create mode 100644 client/pkg/transport/tls_test.go diff --git a/client/pkg/transport/tls_test.go b/client/pkg/transport/tls_test.go new file mode 100644 index 000000000000..4e7b4a21b5e1 --- /dev/null +++ b/client/pkg/transport/tls_test.go @@ -0,0 +1,36 @@ +package transport + +import ( + "net/http" + "net/http/httptest" + "strings" + "testing" +) + +func TestValidateSecureEndpoints(t *testing.T) { + tlsInfo, err := createSelfCert(t) + if err != nil { + t.Fatalf("unable to create cert: %v", err) + } + + remoteAddr := func(w http.ResponseWriter, r *http.Request) { + w.Write([]byte(r.RemoteAddr)) + } + srv := httptest.NewServer(http.HandlerFunc(remoteAddr)) + defer srv.Close() + + insecureEps := []string{ + "http://" + srv.Listener.Addr().String(), + "invalid remote address", + } + if _, err := ValidateSecureEndpoints(*tlsInfo, insecureEps); err == nil || !strings.Contains(err.Error(), "is insecure") { + t.Error("validate secure endpoints should fail") + } + + secureEps := []string{ + "https://" + srv.Listener.Addr().String(), + } + if _, err := ValidateSecureEndpoints(*tlsInfo, secureEps); err != nil { + t.Error("validate secure endpoints should succeed") + } +} From df71f59c0e4bc5f2f9b03cd1f28c98010501de9b Mon Sep 17 00:00:00 2001 From: eval-exec Date: Sun, 20 Mar 2022 21:23:20 +0800 Subject: [PATCH 216/258] close idle connections --- client/pkg/transport/tls.go | 2 ++ 1 file changed, 2 insertions(+) diff --git a/client/pkg/transport/tls.go b/client/pkg/transport/tls.go index d99b772e38e2..8c3a35b140bb 100644 --- a/client/pkg/transport/tls.go +++ b/client/pkg/transport/tls.go @@ -28,6 +28,8 @@ func ValidateSecureEndpoints(tlsInfo TLSInfo, eps []string) ([]string, error) { if err != nil { return nil, err } + defer t.CloseIdleConnections() + var errs []string var endpoints []string for _, ep := range eps { From 4786a72cfc075fb7440636e65a996fca367cd394 Mon Sep 17 00:00:00 2001 From: EXEC Date: Mon, 21 Mar 2022 21:59:28 +0800 Subject: [PATCH 217/258] Update client/pkg/transport/tls_test.go Co-authored-by: Marek Siarkowicz --- client/pkg/transport/tls_test.go | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/client/pkg/transport/tls_test.go b/client/pkg/transport/tls_test.go index 4e7b4a21b5e1..e2747f87b703 100644 --- a/client/pkg/transport/tls_test.go +++ b/client/pkg/transport/tls_test.go @@ -1,3 +1,17 @@ +// Copyright 2022 The etcd Authors +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + package transport import ( From 88e1d6b126ad38809503893ad31b5bd64501078a Mon Sep 17 00:00:00 2001 From: eval-exec Date: Mon, 21 Mar 2022 22:36:39 +0800 Subject: [PATCH 218/258] using subtests for TestValidateSecureEndpoints() --- client/pkg/transport/tls_test.go | 72 ++++++++++++++++++++++++++------ 1 file changed, 59 insertions(+), 13 deletions(-) diff --git a/client/pkg/transport/tls_test.go b/client/pkg/transport/tls_test.go index e2747f87b703..aa2615257bcd 100644 --- a/client/pkg/transport/tls_test.go +++ b/client/pkg/transport/tls_test.go @@ -17,7 +17,7 @@ package transport import ( "net/http" "net/http/httptest" - "strings" + "reflect" "testing" ) @@ -33,18 +33,64 @@ func TestValidateSecureEndpoints(t *testing.T) { srv := httptest.NewServer(http.HandlerFunc(remoteAddr)) defer srv.Close() - insecureEps := []string{ - "http://" + srv.Listener.Addr().String(), - "invalid remote address", + tests := map[string]struct { + endPoints []string + expectedEndpoints []string + expectedErr bool + }{ + "invalidEndPoints": { + endPoints: []string{ + "invalid endpoint", + }, + expectedEndpoints: nil, + expectedErr: true, + }, + "insecureEndpoints": { + endPoints: []string{ + "http://127.0.0.1:8000", + "http://" + srv.Listener.Addr().String(), + }, + expectedEndpoints: nil, + expectedErr: true, + }, + "secureEndPoints": { + endPoints: []string{ + "https://" + srv.Listener.Addr().String(), + }, + expectedEndpoints: []string{ + "https://" + srv.Listener.Addr().String(), + }, + expectedErr: false, + }, + "mixEndPoints": { + endPoints: []string{ + "https://" + srv.Listener.Addr().String(), + "http://" + srv.Listener.Addr().String(), + "invalid end points", + }, + expectedEndpoints: []string{ + "https://" + srv.Listener.Addr().String(), + }, + expectedErr: true, + }, } - if _, err := ValidateSecureEndpoints(*tlsInfo, insecureEps); err == nil || !strings.Contains(err.Error(), "is insecure") { - t.Error("validate secure endpoints should fail") - } - - secureEps := []string{ - "https://" + srv.Listener.Addr().String(), - } - if _, err := ValidateSecureEndpoints(*tlsInfo, secureEps); err != nil { - t.Error("validate secure endpoints should succeed") + for name, test := range tests { + t.Run(name, func(t *testing.T) { + secureEps, err := ValidateSecureEndpoints(*tlsInfo, test.endPoints) + if test.expectedErr && err == nil { + t.Errorf("expected error") + } + if !test.expectedErr && err != nil { + t.Errorf("unexpected error: %v", err) + } + if err == nil && !test.expectedErr { + if len(secureEps) != len(test.expectedEndpoints) { + t.Errorf("expected %v endpoints, got %v", len(test.expectedEndpoints), len(secureEps)) + } + if !reflect.DeepEqual(test.expectedEndpoints, secureEps) { + t.Errorf("expected endpoints %v, got %v", test.expectedEndpoints, secureEps) + } + } + }) } } From ad78a74c42a27c9fc0a410487adbad1ac7c3f3e3 Mon Sep 17 00:00:00 2001 From: EXEC Date: Mon, 21 Mar 2022 23:06:29 +0800 Subject: [PATCH 219/258] Update client/pkg/transport/tls_test.go Co-authored-by: Marek Siarkowicz --- client/pkg/transport/tls_test.go | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/client/pkg/transport/tls_test.go b/client/pkg/transport/tls_test.go index aa2615257bcd..50e864f22432 100644 --- a/client/pkg/transport/tls_test.go +++ b/client/pkg/transport/tls_test.go @@ -77,12 +77,10 @@ func TestValidateSecureEndpoints(t *testing.T) { for name, test := range tests { t.Run(name, func(t *testing.T) { secureEps, err := ValidateSecureEndpoints(*tlsInfo, test.endPoints) - if test.expectedErr && err == nil { - t.Errorf("expected error") - } - if !test.expectedErr && err != nil { - t.Errorf("unexpected error: %v", err) + if test.expectedErr != (err != nil) { + t.Errorf("Unexpected error, got: %v, want: %v", err, test.expectedError) } + if err == nil && !test.expectedErr { if len(secureEps) != len(test.expectedEndpoints) { t.Errorf("expected %v endpoints, got %v", len(test.expectedEndpoints), len(secureEps)) From 8d01ac28162d79fd11ce71edad093370b190b0e4 Mon Sep 17 00:00:00 2001 From: eval-exec Date: Mon, 21 Mar 2022 23:08:35 +0800 Subject: [PATCH 220/258] remove endpoints length check in TestValidateSecureEndpoints() --- client/pkg/transport/tls_test.go | 11 +++-------- 1 file changed, 3 insertions(+), 8 deletions(-) diff --git a/client/pkg/transport/tls_test.go b/client/pkg/transport/tls_test.go index 50e864f22432..46af1db6786c 100644 --- a/client/pkg/transport/tls_test.go +++ b/client/pkg/transport/tls_test.go @@ -78,16 +78,11 @@ func TestValidateSecureEndpoints(t *testing.T) { t.Run(name, func(t *testing.T) { secureEps, err := ValidateSecureEndpoints(*tlsInfo, test.endPoints) if test.expectedErr != (err != nil) { - t.Errorf("Unexpected error, got: %v, want: %v", err, test.expectedError) + t.Errorf("Unexpected error, got: %v, want: %v", err, test.expectedErr) } - if err == nil && !test.expectedErr { - if len(secureEps) != len(test.expectedEndpoints) { - t.Errorf("expected %v endpoints, got %v", len(test.expectedEndpoints), len(secureEps)) - } - if !reflect.DeepEqual(test.expectedEndpoints, secureEps) { - t.Errorf("expected endpoints %v, got %v", test.expectedEndpoints, secureEps) - } + if !reflect.DeepEqual(test.expectedEndpoints, secureEps) { + t.Errorf("expected endpoints %v, got %v", test.expectedEndpoints, secureEps) } }) } From c544b2a2a58004aeb67afe3a4fbbb5b573121a6d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Manuel=20R=C3=BCger?= Date: Mon, 21 Mar 2022 23:55:38 +0100 Subject: [PATCH 221/258] Update go to 1.17.8 --- .github/workflows/build.yaml | 2 +- .github/workflows/contrib.yaml | 2 +- .github/workflows/coverage.yaml | 2 +- .github/workflows/e2e.yaml | 2 +- .github/workflows/functional.yaml | 2 +- .github/workflows/grpcproxy.yaml | 2 +- .github/workflows/static-analysis.yaml | 2 +- .github/workflows/tests.yaml | 2 +- Makefile | 2 +- tests/functional/Dockerfile | 2 +- tests/manual/Makefile | 2 +- 11 files changed, 11 insertions(+), 11 deletions(-) diff --git a/.github/workflows/build.yaml b/.github/workflows/build.yaml index 5d766b513f04..f5b4cfe8bae5 100644 --- a/.github/workflows/build.yaml +++ b/.github/workflows/build.yaml @@ -20,7 +20,7 @@ jobs: - uses: actions/checkout@v2 - uses: actions/setup-go@v2 with: - go-version: "1.17.6" + go-version: "1.17.8" - env: TARGET: ${{ matrix.target }} run: | diff --git a/.github/workflows/contrib.yaml b/.github/workflows/contrib.yaml index 612580ce246e..bda6686ba696 100644 --- a/.github/workflows/contrib.yaml +++ b/.github/workflows/contrib.yaml @@ -7,5 +7,5 @@ jobs: - uses: actions/checkout@v2 - uses: actions/setup-go@v2 with: - go-version: "1.17.6" + go-version: "1.17.8" - run: make -C contrib/mixin tools test diff --git a/.github/workflows/coverage.yaml b/.github/workflows/coverage.yaml index 0bab51853434..916920f4685f 100644 --- a/.github/workflows/coverage.yaml +++ b/.github/workflows/coverage.yaml @@ -12,7 +12,7 @@ jobs: - uses: actions/checkout@v2 - uses: actions/setup-go@v2 with: - go-version: "1.17.6" + go-version: "1.17.8" - env: TARGET: ${{ matrix.target }} run: | diff --git a/.github/workflows/e2e.yaml b/.github/workflows/e2e.yaml index 940002e2c67e..0e96cb61b90f 100644 --- a/.github/workflows/e2e.yaml +++ b/.github/workflows/e2e.yaml @@ -13,7 +13,7 @@ jobs: - uses: actions/checkout@v2 - uses: actions/setup-go@v2 with: - go-version: "1.17.6" + go-version: "1.17.8" - run: date - env: TARGET: ${{ matrix.target }} diff --git a/.github/workflows/functional.yaml b/.github/workflows/functional.yaml index 3aa9572666de..59dd6452f385 100644 --- a/.github/workflows/functional.yaml +++ b/.github/workflows/functional.yaml @@ -12,7 +12,7 @@ jobs: - uses: actions/checkout@v2 - uses: actions/setup-go@v2 with: - go-version: "1.17.6" + go-version: "1.17.8" - run: date - env: TARGET: ${{ matrix.target }} diff --git a/.github/workflows/grpcproxy.yaml b/.github/workflows/grpcproxy.yaml index b20d60413607..6ef4c389e00b 100644 --- a/.github/workflows/grpcproxy.yaml +++ b/.github/workflows/grpcproxy.yaml @@ -13,7 +13,7 @@ jobs: - uses: actions/checkout@v2 - uses: actions/setup-go@v2 with: - go-version: "1.17.6" + go-version: "1.17.8" - run: date - env: TARGET: ${{ matrix.target }} diff --git a/.github/workflows/static-analysis.yaml b/.github/workflows/static-analysis.yaml index 0f87a5d0f3b6..4bbd50979608 100644 --- a/.github/workflows/static-analysis.yaml +++ b/.github/workflows/static-analysis.yaml @@ -12,7 +12,7 @@ jobs: - uses: actions/checkout@v2 - uses: actions/setup-go@v2 with: - go-version: "1.17.6" + go-version: "1.17.8" - run: date - env: TARGET: ${{ matrix.target }} diff --git a/.github/workflows/tests.yaml b/.github/workflows/tests.yaml index 2348d0aa7175..b3b107dab306 100644 --- a/.github/workflows/tests.yaml +++ b/.github/workflows/tests.yaml @@ -16,7 +16,7 @@ jobs: - uses: actions/checkout@v2 - uses: actions/setup-go@v2 with: - go-version: "1.17.6" + go-version: "1.17.8" - run: date - env: TARGET: ${{ matrix.target }} diff --git a/Makefile b/Makefile index 07f183c74b4d..c6a08e06d34a 100644 --- a/Makefile +++ b/Makefile @@ -39,7 +39,7 @@ clean: rm -rf ./tests/e2e/default.proxy find ./ -name "127.0.0.1:*" -o -name "localhost:*" -o -name "*.log" -o -name "agent-*" -o -name "*.coverprofile" -o -name "testname-proxy-*" | $(XARGS) -GO_VERSION ?= 1.17.6 +GO_VERSION ?= 1.17.8 ETCD_VERSION ?= $(shell git rev-parse --short HEAD || echo "GitNotFound") TEST_SUFFIX = $(shell date +%s | base64 | head -c 15) diff --git a/tests/functional/Dockerfile b/tests/functional/Dockerfile index 74b6e3775671..15b55e9a1971 100644 --- a/tests/functional/Dockerfile +++ b/tests/functional/Dockerfile @@ -13,7 +13,7 @@ RUN dnf check-update || true \ ENV GOROOT /usr/local/go ENV GOPATH /go ENV PATH ${GOPATH}/bin:${GOROOT}/bin:${PATH} -ENV GO_VERSION 1.17.6 +ENV GO_VERSION 1.17.8 ENV GO_DOWNLOAD_URL https://storage.googleapis.com/golang RUN rm -rf ${GOROOT} \ && curl -s ${GO_DOWNLOAD_URL}/go${GO_VERSION}.linux-amd64.tar.gz | tar -v -C /usr/local/ -xz \ diff --git a/tests/manual/Makefile b/tests/manual/Makefile index 4e4f5e84d3d4..d61f82eba40e 100644 --- a/tests/manual/Makefile +++ b/tests/manual/Makefile @@ -1,5 +1,5 @@ TMP_DOCKERFILE:=$(shell mktemp) -GO_VERSION ?= 1.17.2 +GO_VERSION ?= 1.17.8 TMP_DIR_MOUNT_FLAG = --tmpfs=/tmp:exec ifdef HOST_TMP_DIR TMP_DIR_MOUNT_FLAG = --mount type=bind,source=$(HOST_TMP_DIR),destination=/tmp From f978da4f4f33421c22ce0e3198370d709e9cdfa2 Mon Sep 17 00:00:00 2001 From: ahrtr Date: Fri, 18 Mar 2022 14:14:21 +0800 Subject: [PATCH 222/258] move the newClientCfg into clientv3 package so as to be reused by both etcdctl and v3discovery --- client/v3/config.go | 63 +++++++++ client/v3/go.mod | 2 +- etcdctl/ctlv3/command/ep_command.go | 37 +++-- etcdctl/ctlv3/command/global.go | 68 +-------- etcdctl/ctlv3/command/global_test.go | 131 ------------------ .../etcdserver/api/v3discovery/discovery.go | 51 +------ 6 files changed, 94 insertions(+), 258 deletions(-) delete mode 100644 etcdctl/ctlv3/command/global_test.go diff --git a/client/v3/config.go b/client/v3/config.go index 29726160852a..47462905ca28 100644 --- a/client/v3/config.go +++ b/client/v3/config.go @@ -19,6 +19,7 @@ import ( "crypto/tls" "time" + "go.etcd.io/etcd/client/pkg/v3/transport" "go.uber.org/zap" "google.golang.org/grpc" ) @@ -118,3 +119,65 @@ type AuthConfig struct { Username string `json:"username"` Password string `json:"password"` } + +// NewClientConfig creates a Config based on the provided ConfigSpec. +func NewClientConfig(confSpec *ConfigSpec, lg *zap.Logger) (*Config, error) { + tlsCfg, err := newTLSConfig(confSpec.Secure, lg) + if err != nil { + return nil, err + } + + cfg := &Config{ + Endpoints: confSpec.Endpoints, + DialTimeout: confSpec.DialTimeout, + DialKeepAliveTime: confSpec.KeepAliveTime, + DialKeepAliveTimeout: confSpec.KeepAliveTimeout, + TLS: tlsCfg, + } + + if confSpec.Auth != nil { + cfg.Username = confSpec.Auth.Username + cfg.Password = confSpec.Auth.Password + } + + return cfg, nil +} + +func newTLSConfig(scfg *SecureConfig, lg *zap.Logger) (*tls.Config, error) { + var ( + tlsCfg *tls.Config + err error + ) + + if scfg == nil { + return nil, nil + } + + if scfg.Cert != "" || scfg.Key != "" || scfg.Cacert != "" || scfg.ServerName != "" { + cfgtls := &transport.TLSInfo{ + CertFile: scfg.Cert, + KeyFile: scfg.Key, + TrustedCAFile: scfg.Cacert, + ServerName: scfg.ServerName, + Logger: lg, + } + if tlsCfg, err = cfgtls.ClientConfig(); err != nil { + return nil, err + } + } + + // If key/cert is not given but user wants secure connection, we + // should still setup an empty tls configuration for gRPC to setup + // secure connection. + if tlsCfg == nil && !scfg.InsecureTransport { + tlsCfg = &tls.Config{} + } + + // If the user wants to skip TLS verification then we should set + // the InsecureSkipVerify flag in tls configuration. + if tlsCfg != nil && scfg.InsecureSkipVerify { + tlsCfg.InsecureSkipVerify = true + } + + return tlsCfg, nil +} diff --git a/client/v3/go.mod b/client/v3/go.mod index 18ada51125b7..f8b11edbd926 100644 --- a/client/v3/go.mod +++ b/client/v3/go.mod @@ -6,6 +6,7 @@ require ( github.com/dustin/go-humanize v1.0.0 github.com/grpc-ecosystem/go-grpc-prometheus v1.2.0 github.com/prometheus/client_golang v1.11.0 + github.com/stretchr/testify v1.7.0 go.etcd.io/etcd/api/v3 v3.6.0-alpha.0 go.etcd.io/etcd/client/pkg/v3 v3.6.0-alpha.0 go.uber.org/zap v1.17.0 @@ -26,7 +27,6 @@ require ( github.com/prometheus/client_model v0.2.0 // indirect github.com/prometheus/common v0.26.0 // indirect github.com/prometheus/procfs v0.6.0 // indirect - github.com/stretchr/testify v1.7.0 // indirect go.uber.org/atomic v1.7.0 // indirect go.uber.org/multierr v1.6.0 // indirect golang.org/x/net v0.0.0-20210405180319-a5a99cb37ef4 // indirect diff --git a/etcdctl/ctlv3/command/ep_command.go b/etcdctl/ctlv3/command/ep_command.go index 9e4aad04d8f5..2a6db17a4e57 100644 --- a/etcdctl/ctlv3/command/ep_command.go +++ b/etcdctl/ctlv3/command/ep_command.go @@ -22,7 +22,7 @@ import ( "go.etcd.io/etcd/api/v3/etcdserverpb" "go.etcd.io/etcd/api/v3/v3rpc/rpctypes" - v3 "go.etcd.io/etcd/client/v3" + "go.etcd.io/etcd/client/v3" "go.etcd.io/etcd/pkg/v3/cobrautl" "go.etcd.io/etcd/pkg/v3/flags" @@ -100,9 +100,16 @@ func epHealthCommandFunc(cmd *cobra.Command, args []string) { ka := keepAliveTimeFromCmd(cmd) kat := keepAliveTimeoutFromCmd(cmd) auth := authCfgFromCmd(cmd) - cfgs := []*v3.Config{} + cfgs := []*clientv3.Config{} for _, ep := range endpointsFromCluster(cmd) { - cfg, err := newClientCfg([]string{ep}, dt, ka, kat, sec, auth) + cfg, err := clientv3.NewClientConfig(&clientv3.ConfigSpec{ + Endpoints: []string{ep}, + DialTimeout: dt, + KeepAliveTime: ka, + KeepAliveTimeout: kat, + Secure: sec, + Auth: auth, + }, lg) if err != nil { cobrautl.ExitWithError(cobrautl.ExitBadArgs, err) } @@ -113,11 +120,11 @@ func epHealthCommandFunc(cmd *cobra.Command, args []string) { hch := make(chan epHealth, len(cfgs)) for _, cfg := range cfgs { wg.Add(1) - go func(cfg *v3.Config) { + go func(cfg *clientv3.Config) { defer wg.Done() ep := cfg.Endpoints[0] cfg.Logger = lg.Named("client") - cli, err := v3.New(*cfg) + cli, err := clientv3.New(*cfg) if err != nil { hch <- epHealth{Ep: ep, Health: false, Error: err.Error()} return @@ -178,8 +185,8 @@ func epHealthCommandFunc(cmd *cobra.Command, args []string) { } type epStatus struct { - Ep string `json:"Endpoint"` - Resp *v3.StatusResponse `json:"Status"` + Ep string `json:"Endpoint"` + Resp *clientv3.StatusResponse `json:"Status"` } func epStatusCommandFunc(cmd *cobra.Command, args []string) { @@ -207,8 +214,8 @@ func epStatusCommandFunc(cmd *cobra.Command, args []string) { } type epHashKV struct { - Ep string `json:"Endpoint"` - Resp *v3.HashKVResponse `json:"HashKV"` + Ep string `json:"Endpoint"` + Resp *clientv3.HashKVResponse `json:"HashKV"` } func epHashKVCommandFunc(cmd *cobra.Command, args []string) { @@ -253,12 +260,18 @@ func endpointsFromCluster(cmd *cobra.Command) []string { cobrautl.ExitWithError(cobrautl.ExitError, err) } // exclude auth for not asking needless password (MemberList() doesn't need authentication) - - cfg, err := newClientCfg(eps, dt, ka, kat, sec, nil) + lg, _ := zap.NewProduction() + cfg, err := clientv3.NewClientConfig(&clientv3.ConfigSpec{ + Endpoints: eps, + DialTimeout: dt, + KeepAliveTime: ka, + KeepAliveTimeout: kat, + Secure: sec, + }, lg) if err != nil { cobrautl.ExitWithError(cobrautl.ExitError, err) } - c, err := v3.New(*cfg) + c, err := clientv3.New(*cfg) if err != nil { cobrautl.ExitWithError(cobrautl.ExitError, err) } diff --git a/etcdctl/ctlv3/command/global.go b/etcdctl/ctlv3/command/global.go index 57adae28f00a..e151c1dd39f9 100644 --- a/etcdctl/ctlv3/command/global.go +++ b/etcdctl/ctlv3/command/global.go @@ -15,7 +15,6 @@ package command import ( - "crypto/tls" "errors" "fmt" "io" @@ -138,7 +137,8 @@ func clientConfigFromCmd(cmd *cobra.Command) *clientv3.ConfigSpec { func mustClientCfgFromCmd(cmd *cobra.Command) *clientv3.Config { cc := clientConfigFromCmd(cmd) - cfg, err := newClientCfg(cc.Endpoints, cc.DialTimeout, cc.KeepAliveTime, cc.KeepAliveTimeout, cc.Secure, cc.Auth) + lg, _ := zap.NewProduction() + cfg, err := clientv3.NewClientConfig(cc, lg) if err != nil { cobrautl.ExitWithError(cobrautl.ExitBadArgs, err) } @@ -151,7 +151,8 @@ func mustClientFromCmd(cmd *cobra.Command) *clientv3.Client { } func mustClient(cc *clientv3.ConfigSpec) *clientv3.Client { - cfg, err := newClientCfg(cc.Endpoints, cc.DialTimeout, cc.KeepAliveTime, cc.KeepAliveTimeout, cc.Secure, cc.Auth) + lg, _ := zap.NewProduction() + cfg, err := clientv3.NewClientConfig(cc, lg) if err != nil { cobrautl.ExitWithError(cobrautl.ExitBadArgs, err) } @@ -164,67 +165,6 @@ func mustClient(cc *clientv3.ConfigSpec) *clientv3.Client { return client } -func newClientCfg(endpoints []string, dialTimeout, keepAliveTime, keepAliveTimeout time.Duration, scfg *clientv3.SecureConfig, acfg *clientv3.AuthConfig) (*clientv3.Config, error) { - // set tls if any one tls option set - var cfgtls *transport.TLSInfo - tlsinfo := transport.TLSInfo{} - tlsinfo.Logger, _ = zap.NewProduction() - if scfg.Cert != "" { - tlsinfo.CertFile = scfg.Cert - cfgtls = &tlsinfo - } - - if scfg.Key != "" { - tlsinfo.KeyFile = scfg.Key - cfgtls = &tlsinfo - } - - if scfg.Cacert != "" { - tlsinfo.TrustedCAFile = scfg.Cacert - cfgtls = &tlsinfo - } - - if scfg.ServerName != "" { - tlsinfo.ServerName = scfg.ServerName - cfgtls = &tlsinfo - } - - cfg := &clientv3.Config{ - Endpoints: endpoints, - DialTimeout: dialTimeout, - DialKeepAliveTime: keepAliveTime, - DialKeepAliveTimeout: keepAliveTimeout, - } - - if cfgtls != nil { - clientTLS, err := cfgtls.ClientConfig() - if err != nil { - return nil, err - } - cfg.TLS = clientTLS - } - - // if key/cert is not given but user wants secure connection, we - // should still setup an empty tls configuration for gRPC to setup - // secure connection. - if cfg.TLS == nil && !scfg.InsecureTransport { - cfg.TLS = &tls.Config{} - } - - // If the user wants to skip TLS verification then we should set - // the InsecureSkipVerify flag in tls configuration. - if scfg.InsecureSkipVerify && cfg.TLS != nil { - cfg.TLS.InsecureSkipVerify = true - } - - if acfg != nil { - cfg.Username = acfg.Username - cfg.Password = acfg.Password - } - - return cfg, nil -} - func argOrStdin(args []string, stdin io.Reader, i int) (string, error) { if i < len(args) { return args[i], nil diff --git a/etcdctl/ctlv3/command/global_test.go b/etcdctl/ctlv3/command/global_test.go deleted file mode 100644 index 0dc56abdd25f..000000000000 --- a/etcdctl/ctlv3/command/global_test.go +++ /dev/null @@ -1,131 +0,0 @@ -// Copyright 2022 The etcd Authors -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -package command - -import ( - "crypto/tls" - - "go.uber.org/zap" - "testing" - "time" - - "github.com/stretchr/testify/assert" - "go.etcd.io/etcd/client/pkg/v3/transport" - clientv3 "go.etcd.io/etcd/client/v3" -) - -func TestNewClientConfig(t *testing.T) { - cases := []struct { - name string - spec clientv3.ConfigSpec - expectedConf clientv3.Config - }{ - { - name: "default secure transport", - spec: clientv3.ConfigSpec{ - Endpoints: []string{"http://192.168.0.10:2379"}, - DialTimeout: 2 * time.Second, - KeepAliveTime: 3 * time.Second, - KeepAliveTimeout: 5 * time.Second, - Secure: &clientv3.SecureConfig{ - InsecureTransport: false, - }, - }, - expectedConf: clientv3.Config{ - Endpoints: []string{"http://192.168.0.10:2379"}, - DialTimeout: 2 * time.Second, - DialKeepAliveTime: 3 * time.Second, - DialKeepAliveTimeout: 5 * time.Second, - TLS: &tls.Config{}, - }, - }, - { - name: "default secure transport and auth enabled", - spec: clientv3.ConfigSpec{ - Endpoints: []string{"http://192.168.0.12:2379"}, - DialTimeout: 1 * time.Second, - KeepAliveTime: 4 * time.Second, - KeepAliveTimeout: 6 * time.Second, - Secure: &clientv3.SecureConfig{ - InsecureTransport: false, - }, - Auth: &clientv3.AuthConfig{ - Username: "test", - Password: "changeme", - }, - }, - expectedConf: clientv3.Config{ - Endpoints: []string{"http://192.168.0.12:2379"}, - DialTimeout: 1 * time.Second, - DialKeepAliveTime: 4 * time.Second, - DialKeepAliveTimeout: 6 * time.Second, - TLS: &tls.Config{}, - Username: "test", - Password: "changeme", - }, - }, - { - name: "default secure transport and skip TLS verification", - spec: clientv3.ConfigSpec{ - Endpoints: []string{"http://192.168.0.13:2379"}, - DialTimeout: 1 * time.Second, - KeepAliveTime: 3 * time.Second, - KeepAliveTimeout: 5 * time.Second, - Secure: &clientv3.SecureConfig{ - InsecureTransport: false, - InsecureSkipVerify: true, - }, - }, - expectedConf: clientv3.Config{ - Endpoints: []string{"http://192.168.0.13:2379"}, - DialTimeout: 1 * time.Second, - DialKeepAliveTime: 3 * time.Second, - DialKeepAliveTimeout: 5 * time.Second, - TLS: &tls.Config{ - InsecureSkipVerify: true, - }, - }, - }, - } - - for _, tc := range cases { - t.Run(tc.name, func(t *testing.T) { - cfg, err := newClientCfg(tc.spec.Endpoints, tc.spec.DialTimeout, tc.spec.KeepAliveTime, tc.spec.KeepAliveTimeout, tc.spec.Secure, tc.spec.Auth) - if err != nil { - t.Fatalf("Unexpected error: %v", err) - } - - assert.Equal(t, tc.expectedConf, *cfg) - }) - } -} - -func TestNewClientConfigWithSecureCfg(t *testing.T) { - tls, err := transport.SelfCert(zap.NewNop(), t.TempDir(), []string{"localhost"}, 1) - if err != nil { - t.Fatalf("Unexpected error: %v", err) - } - - scfg := &clientv3.SecureConfig{ - Cert: tls.CertFile, - Key: tls.KeyFile, - Cacert: tls.TrustedCAFile, - } - - cfg, err := newClientCfg([]string{"http://192.168.0.13:2379"}, 2*time.Second, 3*time.Second, 5*time.Second, scfg, nil) - if cfg == nil || err != nil { - t.Fatalf("Unexpected result client config: %v", err) - } -} diff --git a/server/etcdserver/api/v3discovery/discovery.go b/server/etcdserver/api/v3discovery/discovery.go index 1c274cdba17f..f5be6b8f7ba0 100644 --- a/server/etcdserver/api/v3discovery/discovery.go +++ b/server/etcdserver/api/v3discovery/discovery.go @@ -18,7 +18,6 @@ package v3discovery import ( "context" - "crypto/tls" "errors" "math" @@ -28,7 +27,6 @@ import ( "strings" "time" - "go.etcd.io/etcd/client/pkg/v3/transport" "go.etcd.io/etcd/client/pkg/v3/types" "go.etcd.io/etcd/client/v3" @@ -173,7 +171,7 @@ func newDiscovery(lg *zap.Logger, dcfg *DiscoveryConfig, id types.ID) (*discover } lg = lg.With(zap.String("discovery-token", dcfg.Token), zap.String("discovery-endpoints", strings.Join(dcfg.Endpoints, ","))) - cfg, err := newClientCfg(dcfg, lg) + cfg, err := clientv3.NewClientConfig(&dcfg.ConfigSpec, lg) if err != nil { return nil, err } @@ -192,53 +190,6 @@ func newDiscovery(lg *zap.Logger, dcfg *DiscoveryConfig, id types.ID) (*discover }, nil } -// The following function follows the same logic as etcdctl, refer to -// https://github.com/etcd-io/etcd/blob/f9a8c49c695b098d66a07948666664ea10d01a82/etcdctl/ctlv3/command/global.go#L191-L250 -func newClientCfg(dcfg *DiscoveryConfig, lg *zap.Logger) (*clientv3.Config, error) { - var cfgtls *transport.TLSInfo - - if dcfg.Secure.Cert != "" || dcfg.Secure.Key != "" || dcfg.Secure.Cacert != "" { - cfgtls = &transport.TLSInfo{ - CertFile: dcfg.Secure.Cert, - KeyFile: dcfg.Secure.Key, - TrustedCAFile: dcfg.Secure.Cacert, - Logger: lg, - } - } - - cfg := &clientv3.Config{ - Endpoints: dcfg.Endpoints, - DialTimeout: dcfg.DialTimeout, - DialKeepAliveTime: dcfg.KeepAliveTime, - DialKeepAliveTimeout: dcfg.KeepAliveTimeout, - Username: dcfg.Auth.Username, - Password: dcfg.Auth.Password, - } - - if cfgtls != nil { - if clientTLS, err := cfgtls.ClientConfig(); err == nil { - cfg.TLS = clientTLS - } else { - return nil, err - } - } - - // If key/cert is not given but user wants secure connection, we - // should still setup an empty tls configuration for gRPC to setup - // secure connection. - if cfg.TLS == nil && !dcfg.Secure.InsecureTransport { - cfg.TLS = &tls.Config{} - } - - // If the user wants to skip TLS verification then we should set - // the InsecureSkipVerify flag in tls configuration. - if cfg.TLS != nil && dcfg.Secure.InsecureSkipVerify { - cfg.TLS.InsecureSkipVerify = true - } - - return cfg, nil -} - func (d *discovery) getCluster() (string, error) { cls, clusterSize, rev, err := d.checkCluster() if err != nil { From 49e9a145807555eaa56968fa71a6a0ec348206a1 Mon Sep 17 00:00:00 2001 From: ahrtr Date: Wed, 23 Mar 2022 19:02:10 +0800 Subject: [PATCH 223/258] migrate unit test to cover the logic of converting ConfigSpec to Config --- client/v3/config_test.go | 148 +++++++++++++++++++++++++++++++++++++++ etcdctl/go.mod | 4 -- etcdctl/go.sum | 3 - 3 files changed, 148 insertions(+), 7 deletions(-) create mode 100644 client/v3/config_test.go diff --git a/client/v3/config_test.go b/client/v3/config_test.go new file mode 100644 index 000000000000..da8d3be56804 --- /dev/null +++ b/client/v3/config_test.go @@ -0,0 +1,148 @@ +// Copyright 2022 The etcd Authors +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package clientv3 + +import ( + "crypto/tls" + "testing" + "time" + + "github.com/stretchr/testify/assert" + "go.etcd.io/etcd/client/pkg/v3/transport" + "go.uber.org/zap" +) + +func TestNewClientConfig(t *testing.T) { + cases := []struct { + name string + spec ConfigSpec + expectedConf Config + }{ + { + name: "only has basic info", + spec: ConfigSpec{ + Endpoints: []string{"http://192.168.0.10:2379"}, + DialTimeout: 2 * time.Second, + KeepAliveTime: 3 * time.Second, + KeepAliveTimeout: 5 * time.Second, + }, + expectedConf: Config{ + Endpoints: []string{"http://192.168.0.10:2379"}, + DialTimeout: 2 * time.Second, + DialKeepAliveTime: 3 * time.Second, + DialKeepAliveTimeout: 5 * time.Second, + }, + }, + { + name: "auth enabled", + spec: ConfigSpec{ + Endpoints: []string{"http://192.168.0.12:2379"}, + DialTimeout: 1 * time.Second, + KeepAliveTime: 4 * time.Second, + KeepAliveTimeout: 6 * time.Second, + Auth: &AuthConfig{ + Username: "test", + Password: "changeme", + }, + }, + expectedConf: Config{ + Endpoints: []string{"http://192.168.0.12:2379"}, + DialTimeout: 1 * time.Second, + DialKeepAliveTime: 4 * time.Second, + DialKeepAliveTimeout: 6 * time.Second, + Username: "test", + Password: "changeme", + }, + }, + { + name: "default secure transport", + spec: ConfigSpec{ + Endpoints: []string{"http://192.168.0.10:2379"}, + DialTimeout: 2 * time.Second, + KeepAliveTime: 3 * time.Second, + KeepAliveTimeout: 5 * time.Second, + Secure: &SecureConfig{ + InsecureTransport: false, + }, + }, + expectedConf: Config{ + Endpoints: []string{"http://192.168.0.10:2379"}, + DialTimeout: 2 * time.Second, + DialKeepAliveTime: 3 * time.Second, + DialKeepAliveTimeout: 5 * time.Second, + TLS: &tls.Config{}, + }, + }, + { + name: "default secure transport and skip TLS verification", + spec: ConfigSpec{ + Endpoints: []string{"http://192.168.0.13:2379"}, + DialTimeout: 1 * time.Second, + KeepAliveTime: 3 * time.Second, + KeepAliveTimeout: 5 * time.Second, + Secure: &SecureConfig{ + InsecureTransport: false, + InsecureSkipVerify: true, + }, + }, + expectedConf: Config{ + Endpoints: []string{"http://192.168.0.13:2379"}, + DialTimeout: 1 * time.Second, + DialKeepAliveTime: 3 * time.Second, + DialKeepAliveTimeout: 5 * time.Second, + TLS: &tls.Config{ + InsecureSkipVerify: true, + }, + }, + }, + } + + for _, tc := range cases { + t.Run(tc.name, func(t *testing.T) { + lg, _ := zap.NewProduction() + + cfg, err := NewClientConfig(&tc.spec, lg) + if err != nil { + t.Fatalf("Unexpected error: %v", err) + } + + assert.Equal(t, tc.expectedConf, *cfg) + }) + } +} + +func TestNewClientConfigWithSecureCfg(t *testing.T) { + tls, err := transport.SelfCert(zap.NewNop(), t.TempDir(), []string{"localhost"}, 1) + if err != nil { + t.Fatalf("Unexpected error: %v", err) + } + + scfg := &SecureConfig{ + Cert: tls.CertFile, + Key: tls.KeyFile, + Cacert: tls.TrustedCAFile, + } + + cfg, err := NewClientConfig(&ConfigSpec{ + Endpoints: []string{"http://192.168.0.13:2379"}, + DialTimeout: 2 * time.Second, + KeepAliveTime: 3 * time.Second, + KeepAliveTimeout: 5 * time.Second, + Secure: scfg, + }, nil) + if err != nil || cfg == nil || cfg.TLS == nil { + t.Fatalf("Unexpected result client config: %v", err) + } +} diff --git a/etcdctl/go.mod b/etcdctl/go.mod index 49ded5f42e76..d6b770a4d614 100644 --- a/etcdctl/go.mod +++ b/etcdctl/go.mod @@ -8,7 +8,6 @@ require ( github.com/olekukonko/tablewriter v0.0.5 github.com/spf13/cobra v1.2.1 github.com/spf13/pflag v1.0.5 - github.com/stretchr/testify v1.7.0 github.com/urfave/cli v1.22.4 go.etcd.io/etcd/api/v3 v3.6.0-alpha.0 go.etcd.io/etcd/client/pkg/v3 v3.6.0-alpha.0 @@ -28,7 +27,6 @@ require ( github.com/coreos/go-semver v0.3.0 // indirect github.com/coreos/go-systemd/v22 v22.3.2 // indirect github.com/cpuguy83/go-md2man/v2 v2.0.0 // indirect - github.com/davecgh/go-spew v1.1.1 // indirect github.com/gogo/protobuf v1.3.2 // indirect github.com/golang-jwt/jwt v3.2.2+incompatible // indirect github.com/golang/protobuf v1.5.2 // indirect @@ -37,7 +35,6 @@ require ( github.com/jonboulle/clockwork v0.2.2 // indirect github.com/mattn/go-runewidth v0.0.9 // indirect github.com/matttproud/golang_protobuf_extensions v1.0.1 // indirect - github.com/pmezard/go-difflib v1.0.0 // indirect github.com/prometheus/client_golang v1.11.0 // indirect github.com/prometheus/client_model v0.2.0 // indirect github.com/prometheus/common v0.26.0 // indirect @@ -59,7 +56,6 @@ require ( golang.org/x/text v0.3.7 // indirect google.golang.org/genproto v0.0.0-20211118181313-81c1377c94b1 // indirect google.golang.org/protobuf v1.27.1 // indirect - gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b // indirect sigs.k8s.io/json v0.0.0-20211020170558-c049b76a60c6 // indirect ) diff --git a/etcdctl/go.sum b/etcdctl/go.sum index 5e8427fda7ab..af19c33748f5 100644 --- a/etcdctl/go.sum +++ b/etcdctl/go.sum @@ -242,11 +242,9 @@ github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxv github.com/konsorten/go-windows-terminal-sequences v1.0.3/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= github.com/kr/fs v0.1.0/go.mod h1:FFnZGqtBN9Gxj7eW1uZ42v5BccTP0vu6NEaFoC2HwRg= github.com/kr/logfmt v0.0.0-20140226030751-b84e30acd515/go.mod h1:+0opPa2QZZtGFBFZlji/RkVcI2GknAs/DXo4wKdlNEc= -github.com/kr/pretty v0.1.0 h1:L/CwN0zerZDmRFUapSPitk6f+Q3+0za1rQkzVuMiMFI= github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo= github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= -github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY= github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE= github.com/magiconair/properties v1.8.5/go.mod h1:y3VJvCyxH9uVvJTWEGAELF3aiYNyPKd5NZ3oSwXrF60= github.com/mattn/go-colorable v0.0.9 h1:UVL0vNpWh04HeJXV0KLcaT7r06gOH2l4OW6ddYRUIY4= @@ -731,7 +729,6 @@ google.golang.org/protobuf v1.27.1/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQ gopkg.in/alecthomas/kingpin.v2 v2.2.6/go.mod h1:FMv+mEhP44yOT+4EoQTLFTRgOQ1FBLkstjWtayDeSgw= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= -gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15 h1:YR8cESwS4TdDjEe65xsg0ogRM/Nc3DYOhEAlW+xobZo= gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/cheggaaa/pb.v1 v1.0.28 h1:n1tBJnnK2r7g9OW2btFH91V92STTUevLXYFb8gy9EMk= gopkg.in/cheggaaa/pb.v1 v1.0.28/go.mod h1:V/YB90LKu/1FcN3WVnfiiE5oMCibMjukxqG/qStrOgw= From 62641d33854e206f915398332dbc2b976e9ae5c8 Mon Sep 17 00:00:00 2001 From: Kun Zhang Date: Thu, 24 Mar 2022 16:20:28 +0800 Subject: [PATCH 224/258] set etcdutl to default --- tests/e2e/ctl_v3_defrag_test.go | 14 ++------------ tests/e2e/ctl_v3_snapshot_test.go | 26 +++++++++----------------- tests/e2e/ctl_v3_test.go | 15 ++------------- 3 files changed, 13 insertions(+), 42 deletions(-) diff --git a/tests/e2e/ctl_v3_defrag_test.go b/tests/e2e/ctl_v3_defrag_test.go index 889bbbd078bf..07f6bd443439 100644 --- a/tests/e2e/ctl_v3_defrag_test.go +++ b/tests/e2e/ctl_v3_defrag_test.go @@ -15,14 +15,13 @@ package e2e import ( - "strconv" "testing" "go.etcd.io/etcd/tests/v3/framework/e2e" ) -func TestCtlV3DefragOfflineEtcdutl(t *testing.T) { - testCtlWithOffline(t, maintenanceInitKeys, defragOfflineTest, withEtcdutl()) +func TestCtlV3DefragOffline(t *testing.T) { + testCtlWithOffline(t, maintenanceInitKeys, defragOfflineTest) } func maintenanceInitKeys(cx ctlCtx) { @@ -54,12 +53,3 @@ func defragOfflineTest(cx ctlCtx) { cx.t.Fatalf("defragTest ctlV3Defrag error (%v)", err) } } - -func ctlV3Compact(cx ctlCtx, rev int64, physical bool) error { - rs := strconv.FormatInt(rev, 10) - cmdArgs := append(cx.PrefixArgs(), "compact", rs) - if physical { - cmdArgs = append(cmdArgs, "--physical") - } - return e2e.SpawnWithExpectWithEnv(cmdArgs, cx.envMap, "compacted revision "+rs) -} diff --git a/tests/e2e/ctl_v3_snapshot_test.go b/tests/e2e/ctl_v3_snapshot_test.go index f67c605c5f87..6db55fa4b658 100644 --- a/tests/e2e/ctl_v3_snapshot_test.go +++ b/tests/e2e/ctl_v3_snapshot_test.go @@ -29,8 +29,7 @@ import ( "go.etcd.io/etcd/tests/v3/framework/e2e" ) -func TestCtlV3Snapshot(t *testing.T) { testCtl(t, snapshotTest) } -func TestCtlV3SnapshotEtcdutl(t *testing.T) { testCtl(t, snapshotTest, withEtcdutl()) } +func TestCtlV3Snapshot(t *testing.T) { testCtl(t, snapshotTest) } func snapshotTest(cx ctlCtx) { maintenanceInitKeys(cx) @@ -62,7 +61,7 @@ func snapshotTest(cx ctlCtx) { } } -func TestCtlV3SnapshotCorruptEtcdutl(t *testing.T) { testCtl(t, snapshotCorruptTest, withEtcdutl()) } +func TestCtlV3SnapshotCorrupt(t *testing.T) { testCtl(t, snapshotCorruptTest) } func snapshotCorruptTest(cx ctlCtx) { fpath := filepath.Join(cx.t.TempDir(), "snapshot") @@ -97,8 +96,8 @@ func snapshotCorruptTest(cx ctlCtx) { } // This test ensures that the snapshot status does not modify the snapshot file -func TestCtlV3SnapshotStatusBeforeRestoreEtcdutl(t *testing.T) { - testCtl(t, snapshotStatusBeforeRestoreTest, withEtcdutl()) +func TestCtlV3SnapshotStatusBeforeRestore(t *testing.T) { + testCtl(t, snapshotStatusBeforeRestoreTest) } func snapshotStatusBeforeRestoreTest(cx ctlCtx) { @@ -134,7 +133,6 @@ func ctlV3SnapshotSave(cx ctlCtx, fpath string) error { } func getSnapshotStatus(cx ctlCtx, fpath string) (snapshot.Status, error) { - cx.etcdutl = true cmdArgs := append(cx.PrefixArgsUtl(), "--write-out", "json", "snapshot", "status", fpath) proc, err := e2e.SpawnCmd(cmdArgs, nil) @@ -158,11 +156,11 @@ func getSnapshotStatus(cx ctlCtx, fpath string) (snapshot.Status, error) { return resp, nil } -func TestIssue6361etcdutl(t *testing.T) { testIssue6361(t, true) } +func TestIssue6361(t *testing.T) { testIssue6361(t) } // TestIssue6361 ensures new member that starts with snapshot correctly // syncs up with other members and serve correct data. -func testIssue6361(t *testing.T, etcdutl bool) { +func testIssue6361(t *testing.T) { { // This tests is pretty flaky on semaphoreci as of 2021-01-10. // TODO: Remove when the flakiness source is identified. @@ -216,14 +214,8 @@ func testIssue6361(t *testing.T, etcdutl bool) { } newDataDir := filepath.Join(t.TempDir(), "test.data") - - uctlBinPath := e2e.CtlBinPath - if etcdutl { - uctlBinPath = e2e.UtlBinPath - } - t.Log("etcdctl restoring the snapshot...") - err = e2e.SpawnWithExpect([]string{uctlBinPath, "snapshot", "restore", fpath, "--name", epc.Procs[0].Config().Name, "--initial-cluster", epc.Procs[0].Config().InitialCluster, "--initial-cluster-token", epc.Procs[0].Config().InitialToken, "--initial-advertise-peer-urls", epc.Procs[0].Config().Purl.String(), "--data-dir", newDataDir}, "added member") + err = e2e.SpawnWithExpect([]string{e2e.UtlBinPath, "snapshot", "restore", fpath, "--name", epc.Procs[0].Config().Name, "--initial-cluster", epc.Procs[0].Config().InitialCluster, "--initial-cluster-token", epc.Procs[0].Config().InitialToken, "--initial-advertise-peer-urls", epc.Procs[0].Config().Purl.String(), "--data-dir", newDataDir}, "added member") if err != nil { t.Fatal(err) } @@ -292,8 +284,8 @@ func testIssue6361(t *testing.T, etcdutl bool) { // For storageVersion to be stored, all fields expected 3.6 fields need to be set. This happens after first WAL snapshot. // In this test we lower SnapshotCount to 1 to ensure WAL snapshot is triggered. -func TestCtlV3SnapshotVersionEtcdutl(t *testing.T) { - testCtl(t, snapshotVersionTest, withEtcdutl(), withCfg(e2e.EtcdProcessClusterConfig{SnapshotCount: 1})) +func TestCtlV3SnapshotVersion(t *testing.T) { + testCtl(t, snapshotVersionTest, withCfg(e2e.EtcdProcessClusterConfig{SnapshotCount: 1})) } func snapshotVersionTest(cx ctlCtx) { diff --git a/tests/e2e/ctl_v3_test.go b/tests/e2e/ctl_v3_test.go index ee309cdeb37a..ebb24e59742a 100644 --- a/tests/e2e/ctl_v3_test.go +++ b/tests/e2e/ctl_v3_test.go @@ -145,9 +145,6 @@ type ctlCtx struct { // for compaction compactPhysical bool - // to run etcdutl instead of etcdctl for suitable commands. - etcdutl bool - // dir that was used during the test dataDir string } @@ -201,10 +198,6 @@ func withFlagByEnv() ctlOption { return func(cx *ctlCtx) { cx.envMap = make(map[string]string) } } -func withEtcdutl() ctlOption { - return func(cx *ctlCtx) { cx.etcdutl = true } -} - func testCtl(t *testing.T, testFunc func(ctlCtx), opts ...ctlOption) { testCtlWithOffline(t, testFunc, nil, opts...) } @@ -331,14 +324,10 @@ func (cx *ctlCtx) PrefixArgs() []string { return cx.prefixArgs(cx.epc.EndpointsV3()) } -// PrefixArgsUtl returns prefix of the command that is either etcdctl or etcdutl -// depending on cx configuration. +// PrefixArgsUtl returns prefix of the command that is etcdutl // Please not thet 'utl' compatible commands does not consume --endpoints flag. func (cx *ctlCtx) PrefixArgsUtl() []string { - if cx.etcdutl { - return []string{e2e.UtlBinPath} - } - return []string{e2e.CtlBinPath} + return []string{e2e.UtlBinPath} } func isGRPCTimedout(err error) bool { From b8c1ac8efd9d407119181ebc66d6d6700390ec95 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Manuel=20R=C3=BCger?= Date: Thu, 24 Mar 2022 09:58:05 +0100 Subject: [PATCH 225/258] Add Changelog entry --- CHANGELOG/CHANGELOG-3.6.md | 3 +++ 1 file changed, 3 insertions(+) diff --git a/CHANGELOG/CHANGELOG-3.6.md b/CHANGELOG/CHANGELOG-3.6.md index 386e2265f0fa..9210d427f7ca 100644 --- a/CHANGELOG/CHANGELOG-3.6.md +++ b/CHANGELOG/CHANGELOG-3.6.md @@ -74,6 +74,9 @@ See [List of metrics](https://etcd.io/docs/latest/metrics/) for all metrics per - Add [`etcd_disk_defrag_inflight`](https://github.com/etcd-io/etcd/pull/13371). +### Go +- Compile with [Go 1.17+](https://golang.org/doc/devel/release.html#go1.17) + ### Other - Use Distroless as base image to make the image less vulnerable and reduce image size. From afecd3139cee913e22c19ed96c37748f25336fe3 Mon Sep 17 00:00:00 2001 From: Kay Yan Date: Tue, 15 Mar 2022 14:19:00 +0800 Subject: [PATCH 226/258] fix the api dependency in pkg, and update cobra to 1.4.0 Signed-off-by: Kay Yan --- bill-of-materials.json | 9 - etcdctl/go.mod | 9 +- etcdctl/go.sum | 418 ++------------------------------------ etcdutl/go.mod | 2 +- etcdutl/go.sum | 403 +------------------------------------ go.mod | 6 +- go.sum | 87 ++------ pkg/go.mod | 12 +- pkg/go.sum | 441 +---------------------------------------- server/go.mod | 2 +- server/go.sum | 403 +------------------------------------ tests/go.mod | 2 +- tests/go.sum | 402 +------------------------------------ 13 files changed, 80 insertions(+), 2116 deletions(-) diff --git a/bill-of-materials.json b/bill-of-materials.json index 82254a5aa7b7..083162c4f37c 100644 --- a/bill-of-materials.json +++ b/bill-of-materials.json @@ -332,15 +332,6 @@ } ] }, - { - "project": "github.com/shurcooL/sanitized_anchor_name", - "licenses": [ - { - "type": "MIT License", - "confidence": 1 - } - ] - }, { "project": "github.com/sirupsen/logrus", "licenses": [ diff --git a/etcdctl/go.mod b/etcdctl/go.mod index d6b770a4d614..741e07929bd3 100644 --- a/etcdctl/go.mod +++ b/etcdctl/go.mod @@ -6,7 +6,7 @@ require ( github.com/bgentry/speakeasy v0.1.0 github.com/dustin/go-humanize v1.0.0 github.com/olekukonko/tablewriter v0.0.5 - github.com/spf13/cobra v1.2.1 + github.com/spf13/cobra v1.4.0 github.com/spf13/pflag v1.0.5 github.com/urfave/cli v1.22.4 go.etcd.io/etcd/api/v3 v3.6.0-alpha.0 @@ -26,21 +26,22 @@ require ( github.com/cespare/xxhash/v2 v2.1.1 // indirect github.com/coreos/go-semver v0.3.0 // indirect github.com/coreos/go-systemd/v22 v22.3.2 // indirect - github.com/cpuguy83/go-md2man/v2 v2.0.0 // indirect + github.com/cpuguy83/go-md2man/v2 v2.0.1 // indirect + github.com/fatih/color v1.13.0 // indirect github.com/gogo/protobuf v1.3.2 // indirect github.com/golang-jwt/jwt v3.2.2+incompatible // indirect github.com/golang/protobuf v1.5.2 // indirect github.com/google/btree v1.0.1 // indirect github.com/inconshreveable/mousetrap v1.0.0 // indirect github.com/jonboulle/clockwork v0.2.2 // indirect + github.com/mattn/go-colorable v0.1.12 // indirect github.com/mattn/go-runewidth v0.0.9 // indirect github.com/matttproud/golang_protobuf_extensions v1.0.1 // indirect github.com/prometheus/client_golang v1.11.0 // indirect github.com/prometheus/client_model v0.2.0 // indirect github.com/prometheus/common v0.26.0 // indirect github.com/prometheus/procfs v0.6.0 // indirect - github.com/russross/blackfriday/v2 v2.0.1 // indirect - github.com/shurcooL/sanitized_anchor_name v1.0.0 // indirect + github.com/russross/blackfriday/v2 v2.1.0 // indirect github.com/xiang90/probing v0.0.0-20190116061207-43a291ad63a2 // indirect go.etcd.io/bbolt v1.3.6 // indirect go.etcd.io/etcd/raft/v3 v3.6.0-alpha.0 // indirect diff --git a/etcdctl/go.sum b/etcdctl/go.sum index af19c33748f5..362c5247e267 100644 --- a/etcdctl/go.sum +++ b/etcdctl/go.sum @@ -1,45 +1,7 @@ cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= +cloud.google.com/go v0.34.0 h1:eOI3/cP2VTU6uZLDYAoic+eyzzB9YyGmJ7eIjl8rOPg= cloud.google.com/go v0.34.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= -cloud.google.com/go v0.38.0/go.mod h1:990N+gfupTy94rShfmMCWGDn0LpTmnzTp2qbd1dvSRU= -cloud.google.com/go v0.44.1/go.mod h1:iSa0KzasP4Uvy3f1mN/7PiObzGgflwredwwASm/v6AU= -cloud.google.com/go v0.44.2/go.mod h1:60680Gw3Yr4ikxnPRS/oxxkBccT6SA1yMk63TGekxKY= -cloud.google.com/go v0.45.1/go.mod h1:RpBamKRgapWJb87xiFSdk4g1CME7QZg3uwTez+TSTjc= -cloud.google.com/go v0.46.3/go.mod h1:a6bKKbmY7er1mI7TEI4lsAkts/mkhTSZK8w33B4RAg0= -cloud.google.com/go v0.50.0/go.mod h1:r9sluTvynVuxRIOHXQEHMFffphuXHOMZMycpNR5e6To= -cloud.google.com/go v0.52.0/go.mod h1:pXajvRH/6o3+F9jDHZWQ5PbGhn+o8w9qiu/CffaVdO4= -cloud.google.com/go v0.53.0/go.mod h1:fp/UouUEsRkN6ryDKNW/Upv/JBKnv6WDthjR6+vze6M= -cloud.google.com/go v0.54.0/go.mod h1:1rq2OEkV3YMf6n/9ZvGWI3GWw0VoqH/1x2nd8Is/bPc= -cloud.google.com/go v0.56.0/go.mod h1:jr7tqZxxKOVYizybht9+26Z/gUq7tiRzu+ACVAMbKVk= -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.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 h1:at8Tk2zUz63cLPR0JPWm5vp77pEZmzxEQBEfRKn1VV8= -cloud.google.com/go v0.81.0/go.mod h1:mk/AM35KwGk/Nm2YSeZbxXdrNK3KZOYHmLkOqC2V6E0= -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.4.0/go.mod h1:S8dzgnTigyfTmLBfrtrhyYhwRxG72rYxvftPBK2Dvzc= -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.8.0/go.mod h1:J5hqkt3O0uAFnINi6JXValWIb1v0goeZM77hZzJN/fQ= -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/firestore v1.1.0/go.mod h1:ulACoGHTpvq5r8rxGJ4ddJZBZqakUQqClKRT5SZwBmk= -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.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/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.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.10.0/go.mod h1:FLPqc6j+Ki4BU591ie1oL6qBQGu2Bl/tZ9ullr3+Kg0= -dmitri.shuralyov.com/gpu/mtl v0.0.0-20190408044501-666a987793e9/go.mod h1:H6x//7gZCb22OMCxBHrMx7a5I7Hp++hsVxbQ4BYO7hU= github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= -github.com/BurntSushi/xgb v0.0.0-20160522181843-27f122750802/go.mod h1:IVnqGOEym/WlBOVXweHU+Q+/VP0lqqI8lqeDx9IjBqo= github.com/OneOfOne/xxhash v1.2.2/go.mod h1:HSdplMjZKSmBqAxg5vPj2TmRDmfkzw+cTzAElWljhcU= github.com/alecthomas/template v0.0.0-20160405071501-a0175ee3bccc/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc= github.com/alecthomas/template v0.0.0-20190718012654-fb15b899a751/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc= @@ -47,16 +9,12 @@ github.com/alecthomas/units v0.0.0-20151022065526-2efee857e7cf/go.mod h1:ybxpYRF github.com/alecthomas/units v0.0.0-20190717042225-c3de453c63f4/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0= github.com/alecthomas/units v0.0.0-20190924025748-f65c72e2690d/go.mod h1:rBZYJk541a8SKzHPHnH3zbiI+7dagKZ0cgpgrD7Fyho= github.com/antihax/optional v1.0.0/go.mod h1:uupD/76wgC+ih3iEmQUL+0Ugr19nfwCT1kdvxnR2qWY= -github.com/armon/circbuf v0.0.0-20150827004946-bbbad097214e/go.mod h1:3U/XgcO3hCbHZ8TKRvWD2dDTCfh9M9ya+I9JpbB7O8o= -github.com/armon/go-metrics v0.0.0-20180917152333-f0300d1749da/go.mod h1:Q73ZrmVTwzkszR9V5SSuryQ31EELlFMUz1kKyl939pY= -github.com/armon/go-radix v0.0.0-20180808171621-7fddfc383310/go.mod h1:ufUuZ+zHj4x4TnLV4JWEpy2hxWSpsRywHrMgIH9cCH8= github.com/beorn7/perks v0.0.0-20180321164747-3a771d992973/go.mod h1:Dwedo/Wpr24TaqPxmxbtue+5NUziq4I4S80YR8gNf3Q= github.com/beorn7/perks v1.0.0/go.mod h1:KWe93zE9D1o94FZ5RNwFwVgaQK1VOXiVxmqh+CedLV8= github.com/beorn7/perks v1.0.1 h1:VlbKKnNfV8bJzeqoa4cOKqO6bYr3WgKZxO8Z16+hsOM= github.com/beorn7/perks v1.0.1/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6rlkpw= github.com/bgentry/speakeasy v0.1.0 h1:ByYyxL9InA1OWqxJqqp2A5pYHUrCiAL6K3J+LKSsQkY= github.com/bgentry/speakeasy v0.1.0/go.mod h1:+zsyZBPWlz7T6j88CTgSN5bM796AkVf0kBD4zp0CCIs= -github.com/bketelsen/crypt v0.0.4/go.mod h1:aI6NrJ0pMGgvZKL1iVgXLnfIFJtfV+bKCoqOes/6LfM= github.com/cenkalti/backoff/v4 v4.1.1/go.mod h1:scbssz8iZGpm3xbr14ovlUdkxfGXNInqkPWOWmG2CLw= github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU= github.com/certifi/gocertifi v0.0.0-20191021191039-0944d244cd40/go.mod h1:sGbDF6GwGcLpkNXPUTkMRoywsNa/ol15pxFe6ERfguA= @@ -66,12 +24,8 @@ github.com/cespare/xxhash v1.1.0 h1:a6HrQnmkObjyL+Gs60czilIUGqrzKutQD6XZog3p+ko= github.com/cespare/xxhash v1.1.0/go.mod h1:XrSqR1VqqWfGrhpAt58auRo0WTKS1nRRg3ghfAqPWnc= github.com/cespare/xxhash/v2 v2.1.1 h1:6MnRN8NT7+YBpUIWxHtefFZOKTAPgGjpQSxqLNn0+qY= github.com/cespare/xxhash/v2 v2.1.1/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= -github.com/chzyer/logex v1.1.10/go.mod h1:+Ywpsq7O8HXn0nuIou7OrIPyXbp3wmkHB+jjWRnGsAI= -github.com/chzyer/readline v0.0.0-20180603132655-2972be24d48e/go.mod h1:nSuG5e5PlCu98SY8svDHJxuZscDgtXS6KTTbou5AhLI= -github.com/chzyer/test v0.0.0-20180213035817-a1ea475d72b1/go.mod h1:Q3SI9o4m/ZMnBNeIyt5eFwwo7qiLfzFZmjNmxjkiQlU= github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw= 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/xds/go v0.0.0-20210312221358-fbca930ec8ed/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs= github.com/cncf/xds/go v0.0.0-20210805033703-aa0b78936158/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs= @@ -86,8 +40,8 @@ github.com/coreos/go-semver v0.3.0/go.mod h1:nnelYz7RCh+5ahJtPPxZlU+153eP4D4r3Ee github.com/coreos/go-systemd/v22 v22.3.2 h1:D9/bQk5vlXQFZ6Kwuu6zaiXJ9oTPe68++AzAJc1DzSI= github.com/coreos/go-systemd/v22 v22.3.2/go.mod h1:Y58oyj3AT4RCenI/lSvhwexgC+NSVTIJ3seZv2GcEnc= github.com/cpuguy83/go-md2man/v2 v2.0.0-20190314233015-f79a8a8ca69d/go.mod h1:maD7wRr/U5Z6m/iR4s+kqSMx2CaBsrgA7czyZG/E6dU= -github.com/cpuguy83/go-md2man/v2 v2.0.0 h1:EoUDS0afbrsXAZ9YQ9jdu/mZ2sXgT1/2yyNng4PGlyM= -github.com/cpuguy83/go-md2man/v2 v2.0.0/go.mod h1:maD7wRr/U5Z6m/iR4s+kqSMx2CaBsrgA7czyZG/E6dU= +github.com/cpuguy83/go-md2man/v2 v2.0.1 h1:r/myEWzV9lfsM1tFLgDyu0atFtJ1fXn261LKYj/3DxU= +github.com/cpuguy83/go-md2man/v2 v2.0.1/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o= github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E= github.com/creack/pty v1.1.11/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E= github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= @@ -98,21 +52,16 @@ github.com/dustin/go-humanize v1.0.0/go.mod h1:HtrtbFcZ19U5GC7JDqmcUSB87Iq5E25Kn 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.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.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.10-0.20210907150352-cf90f659a021/go.mod h1:AFq3mo9L8Lqqiid3OhADV3RfLJnjiw63cSpi+fDTRC0= github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c= -github.com/fatih/color v1.7.0 h1:DkWD4oS2D8LGGgTQ6IvwJJXSL5Vp2ffcQg58nFV38Ys= -github.com/fatih/color v1.7.0/go.mod h1:Zm6kSWBoL9eyXnKyktHP6abPY2pDugNf5KwzbycvMj4= -github.com/fsnotify/fsnotify v1.4.9/go.mod h1:znqG4EE+3YCdAaPaxE2ZRY/06pZUdp0tY4IgpuI1SZQ= +github.com/fatih/color v1.13.0 h1:8LOYc1KYPPmyKMuN8QV2DNRWNbLo6LZ0iLs8+mlH53w= +github.com/fatih/color v1.13.0/go.mod h1:kLAiJbzzSOZDVNGyDpeOxJ47H46qBXwg5ILebYFFOfk= github.com/getsentry/raven-go v0.2.0 h1:no+xWJRb5ZI7eE8TWgIq1jLulQiIoLG0IfYxv5JYMGs= github.com/getsentry/raven-go v0.2.0/go.mod h1:KungGk8q33+aIAZUIVWZDr2OfAEBsO49PX4NzFV5kcQ= github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04= -github.com/go-gl/glfw v0.0.0-20190409004039-e6da0acd62b1/go.mod h1:vR7hzQXu2zJy9AVAgeJqvqgH9Q5CA+iKCZ2gyEVpxRU= -github.com/go-gl/glfw/v3.3/glfw v0.0.0-20191125211704-12ad95a8df72/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8= -github.com/go-gl/glfw/v3.3/glfw v0.0.0-20200222043503-6f7a984d4dc4/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8= github.com/go-kit/kit v0.8.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as= github.com/go-kit/kit v0.9.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as= github.com/go-kit/log v0.1.0/go.mod h1:zbhenjAZHb184qTLMA9ZjW7ThYL0H2mk7Q6pNt4vbaY= @@ -128,24 +77,12 @@ github.com/gogo/protobuf v1.3.2/go.mod h1:P1XiOD3dCwIKUDQYPy72D8LYyHL2YPYrpS2s69 github.com/golang-jwt/jwt v3.2.2+incompatible h1:IfV12K8xAKAnZqdXVzCZ+TOjboZ2keLg81eXfW3O+oY= github.com/golang-jwt/jwt v3.2.2+incompatible/go.mod h1:8pz2t5EyA70fFQQSrl6XZXzqecmYZeUEB8OUGHkxJ+I= github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q= -github.com/golang/groupcache v0.0.0-20190702054246-869f871628b6/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= -github.com/golang/groupcache v0.0.0-20191227052852-215e87163ea7/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= -github.com/golang/groupcache v0.0.0-20200121045136-8c9f03a8e57e/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= github.com/golang/mock v1.1.1/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A= -github.com/golang/mock v1.2.0/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A= -github.com/golang/mock v1.3.1/go.mod h1:sBzyDLLjw3U8JLTeZvSv8jJB+tU5PVekmnlKIyFUx0Y= -github.com/golang/mock v1.4.0/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.4/go.mod h1:l3mdAwkq5BuhzHwde/uurv3sEJeZMXNpwsxVWU71h+4= -github.com/golang/mock v1.5.0/go.mod h1:CWnOUgYIOo4TcNZ0wHX3YZCqsaM1I1Jvs6v3mP3KVu8= github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= github.com/golang/protobuf v1.3.1/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= github.com/golang/protobuf v1.3.2/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= github.com/golang/protobuf v1.3.3/go.mod h1:vzj43D7+SQXF/4pzW/hwtAqwc6iTitCiVSaWz5lYuqw= -github.com/golang/protobuf v1.3.4/go.mod h1:vzj43D7+SQXF/4pzW/hwtAqwc6iTitCiVSaWz5lYuqw= -github.com/golang/protobuf v1.3.5/go.mod h1:6O5/vntMXwX2lRkT1hjjk0nAC1IDOTvTlVgjlRvqsdk= github.com/golang/protobuf v1.4.0-rc.1/go.mod h1:ceaxUfeHdC40wWswd/P6IGgMaK3YpKi5j83Wpe3EHw8= github.com/golang/protobuf v1.4.0-rc.1.0.20200221234624-67d41d38c208/go.mod h1:xKAWHe0F5eneWXFV3EuXVDTCmh+JuBKY0li0aMyXATA= github.com/golang/protobuf v1.4.0-rc.2/go.mod h1:LlEzMj4AhA7rCAGe4KMBDvJI+AwstrUpVNzEA03Pprs= @@ -155,73 +92,26 @@ 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.3/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI= 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/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY= -github.com/google/btree v0.0.0-20180813153112-4030bb1f1f0c/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ= -github.com/google/btree v1.0.0/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ= github.com/google/btree v1.0.1 h1:gK4Kx5IaGY9CD5sPJ36FHiBJ6ZXl0kilRiiCj+jdYp4= github.com/google/btree v1.0.1/go.mod h1:xXMiIv4Fb/0kKde4SpL7qlzvu5cMJDRkFDxJfI9uaxA= github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M= github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= -github.com/google/go-cmp v0.4.1/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.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.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.6 h1:BKbKCqvP6I+rmFHt06ZmyQtvB8xAkWdhFyr0ZUNZcxQ= github.com/google/go-cmp v0.5.6/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= -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.1.0/go.mod h1:y5Zk1BBys9G+gd6Jrk0W3cC1+ELVxBWuIGO+w/tUAp0= -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-20191218002539-d4f498aebedc/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= -github.com/google/pprof v0.0.0-20200212024743-f11f1df84d12/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-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/renameio v0.1.0/go.mod h1:KWCgfxg9yswjAJkECMjeO8J8rahYeXnNhOm40UhjYkI= github.com/google/uuid v1.1.2/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= -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/gopherjs/gopherjs v0.0.0-20181017120253-0766667cb4d1/go.mod h1:wJfORRmW1u3UXTncJ5qlYoELFm8eSnnEO6hX4iZ3EWY= github.com/gorilla/websocket v1.4.2/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE= github.com/grpc-ecosystem/go-grpc-middleware v1.3.0/go.mod h1:z0ButlSOZa5vEBq9m2m2hlwIgKw+rp3sdCBRoJY+30Y= github.com/grpc-ecosystem/go-grpc-prometheus v1.2.0 h1:Ovs26xHkKqVztRpIrF/92BcuyuQ/YW4NSIpoGtfXNho= github.com/grpc-ecosystem/go-grpc-prometheus v1.2.0/go.mod h1:8NvIoxWQoOIhqOTXgfV/d3M/q6VIi02HzZEHgUlZvzk= github.com/grpc-ecosystem/grpc-gateway v1.16.0/go.mod h1:BDjrQk3hbvj6Nolgz8mAMFbcEtjT1g+wF4CSlocrBnw= -github.com/hashicorp/consul/api v1.1.0/go.mod h1:VmuI/Lkw1nC05EYQWNKwWGbkg+FbDBtguAZLlVdkD9Q= -github.com/hashicorp/consul/sdk v0.1.1/go.mod h1:VKf9jXwCTEY1QZP2MOLRhb5i/I/ssyNV1vwHyQBF0x8= -github.com/hashicorp/errwrap v1.0.0/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4= -github.com/hashicorp/go-cleanhttp v0.5.1/go.mod h1:JpRdi6/HCYpAwUzNwuwqhbovhLtngrth3wmdIIUrZ80= -github.com/hashicorp/go-immutable-radix v1.0.0/go.mod h1:0y9vanUI8NX6FsYoO3zeMjhV/C5i9g4Q3DwcSNZ4P60= -github.com/hashicorp/go-msgpack v0.5.3/go.mod h1:ahLV/dePpqEmjfWmKiqvPkv/twdG7iPBM1vqhUKIvfM= -github.com/hashicorp/go-multierror v1.0.0/go.mod h1:dHtQlpGsu+cZNNAkkCN/P3hoUDHhCYQXV3UM06sGGrk= -github.com/hashicorp/go-rootcerts v1.0.0/go.mod h1:K6zTfqpRlCUIjkwsN4Z+hiSfzSTQa6eBIzfwKfwNnHU= -github.com/hashicorp/go-sockaddr v1.0.0/go.mod h1:7Xibr9yA9JjQq1JpNB2Vw7kxv8xerXegt+ozgdvDeDU= -github.com/hashicorp/go-syslog v1.0.0/go.mod h1:qPfqrKkXGihmCqbJM2mZgkZGvKG1dFdvsLplgctolz4= -github.com/hashicorp/go-uuid v1.0.0/go.mod h1:6SBZvOh/SIDV7/2o3Jml5SYk/TvGqwFJ/bN7x4byOro= -github.com/hashicorp/go-uuid v1.0.1/go.mod h1:6SBZvOh/SIDV7/2o3Jml5SYk/TvGqwFJ/bN7x4byOro= -github.com/hashicorp/go.net v0.0.1/go.mod h1:hjKkEWcCURg++eb33jQU7oqQcI9XDCnUzHA0oac0k90= -github.com/hashicorp/golang-lru v0.5.0/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8= -github.com/hashicorp/golang-lru v0.5.1/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8= -github.com/hashicorp/hcl v1.0.0/go.mod h1:E5yfLk+7swimpb2L/Alb/PJmXilQ/rhwaUYs4T20WEQ= -github.com/hashicorp/logutils v1.0.0/go.mod h1:QIAnNjmIWmVIIkWDTG1z5v++HQmx9WQRO+LraFDTW64= -github.com/hashicorp/mdns v1.0.0/go.mod h1:tL+uN++7HEJ6SQLQ2/p+z2pH24WQKWjBPkE0mNTz8vQ= -github.com/hashicorp/memberlist v0.1.3/go.mod h1:ajVTdAv/9Im8oMAAj5G31PhhMCZJV2pPBoIllUwCN7I= -github.com/hashicorp/serf v0.8.2/go.mod h1:6hOLApaqBFA1NXqRQAsxw9QxuDEvNxSQRwA/JwenrHc= -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/inconshreveable/mousetrap v1.0.0 h1:Z8tu5sraLXCXIcARxBp/8cbvlwVa7Z1NHg9XEKhtSvM= github.com/inconshreveable/mousetrap v1.0.0/go.mod h1:PxqpIevigyE2G7u3NXJIT2ANytuPF1OarO4DADm73n8= github.com/jonboulle/clockwork v0.2.2 h1:UOGuzwb1PwsrDAObMuhUnj0p5ULPj8V/xJ7Kx9qUBdQ= @@ -230,9 +120,6 @@ github.com/jpillora/backoff v1.0.0/go.mod h1:J/6gKK9jxlEcS3zixgDgUAsiuZ7yrSoa/FX github.com/json-iterator/go v1.1.6/go.mod h1:+SdeFBvtyEkXs7REEP0seUULqWtbJapLOCVDaaPEHmU= github.com/json-iterator/go v1.1.10/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4= github.com/json-iterator/go v1.1.11/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4= -github.com/jstemmer/go-junit-report v0.0.0-20190106144839-af01ea7f8024/go.mod h1:6v2b51hI/fHJwM22ozAgKL4VKDeJcHhJFhtBdhmNjmU= -github.com/jstemmer/go-junit-report v0.9.1/go.mod h1:Brl9GWCQeLvo8nXZwPNNblvFj/XSXhF0NWZEnDohbsk= -github.com/jtolds/gls v4.20.0+incompatible/go.mod h1:QJZ7F/aHp+rZTRtaJ1ow/lLfFfVYBRgL+9YlvaHOwJU= github.com/julienschmidt/httprouter v1.2.0/go.mod h1:SYymIcj16QtmaHHD7aYtjjsJG7VTCxuUUipMqKk8s4w= github.com/julienschmidt/httprouter v1.3.0/go.mod h1:JR6WtHb+2LUe8TCKY3cZOxFyyO8IZAc4RVcycCCAKdM= github.com/kisielk/errcheck v1.2.0/go.mod h1:/BMXB+zMLi60iA8Vv6Ksmxu/1UDYcXs4uQLJ+jE2L00= @@ -240,30 +127,21 @@ github.com/kisielk/errcheck v1.5.0/go.mod h1:pFxgyoBC7bSaBwPgfKdkLd5X25qrDl4LWUI github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck= github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= github.com/konsorten/go-windows-terminal-sequences v1.0.3/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= -github.com/kr/fs v0.1.0/go.mod h1:FFnZGqtBN9Gxj7eW1uZ42v5BccTP0vu6NEaFoC2HwRg= github.com/kr/logfmt v0.0.0-20140226030751-b84e30acd515/go.mod h1:+0opPa2QZZtGFBFZlji/RkVcI2GknAs/DXo4wKdlNEc= github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo= github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE= -github.com/magiconair/properties v1.8.5/go.mod h1:y3VJvCyxH9uVvJTWEGAELF3aiYNyPKd5NZ3oSwXrF60= -github.com/mattn/go-colorable v0.0.9 h1:UVL0vNpWh04HeJXV0KLcaT7r06gOH2l4OW6ddYRUIY4= -github.com/mattn/go-colorable v0.0.9/go.mod h1:9vuHe8Xs5qXnSaW/c/ABM9alt+Vo+STaOChaDxuIBZU= -github.com/mattn/go-isatty v0.0.3 h1:ns/ykhmWi7G9O+8a448SecJU3nSMBXJfqQkl0upE1jI= -github.com/mattn/go-isatty v0.0.3/go.mod h1:M+lRXTBqGeGNdLjl/ufCoiOlB5xdOkqRJdNxMWT7Zi4= +github.com/mattn/go-colorable v0.1.9/go.mod h1:u6P/XSegPjTcexA+o6vUJrdnUu04hMope9wVRipJSqc= +github.com/mattn/go-colorable v0.1.12 h1:jF+Du6AlPIjs2BiUiQlKOX0rt3SujHxPnksPKZbaA40= +github.com/mattn/go-colorable v0.1.12/go.mod h1:u5H1YNBxpqRaxsYJYSkiCWKzEfiAb1Gb520KVy5xxl4= +github.com/mattn/go-isatty v0.0.12/go.mod h1:cbi8OIDigv2wuxKPP5vlRcQ1OAZbq2CE4Kysco4FUpU= +github.com/mattn/go-isatty v0.0.14 h1:yVuAays6BHfxijgZPzw+3Zlu5yQgKGP2/hcQbHb7S9Y= +github.com/mattn/go-isatty v0.0.14/go.mod h1:7GGIvUiUoEMVVmxf/4nioHXj79iQHKdU27kJ6hsGG94= github.com/mattn/go-runewidth v0.0.9 h1:Lm995f3rfxdpd6TSmuVCHVb/QhupuXlYr8sCI/QdE+0= github.com/mattn/go-runewidth v0.0.9/go.mod h1:H031xJmbD/WCDINGzjvQ9THkh0rPKHF+m2gUSrubnMI= github.com/matttproud/golang_protobuf_extensions v1.0.1 h1:4hp9jkHxhMHkqkrB3Ix0jegS5sx/RkqARlsWZ6pIwiU= github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0= -github.com/miekg/dns v1.0.14/go.mod h1:W1PPwlIAgtquWBMBEV9nkV9Cazfe8ScdGz/Lj7v3Nrg= -github.com/mitchellh/cli v1.0.0/go.mod h1:hNIlj7HEI86fIcpObd7a0FcrxTWetlwJDGcceTlRvqc= -github.com/mitchellh/go-homedir v1.0.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0= -github.com/mitchellh/go-testing-interface v1.0.0/go.mod h1:kRemZodwjscx+RGhAo8eIhFbs2+BFgRtFPeD/KE+zxI= -github.com/mitchellh/gox v0.4.0/go.mod h1:Sd9lOJ0+aimLBi73mGofS1ycjY8lL3uZM3JPS42BGNg= -github.com/mitchellh/iochan v1.0.0/go.mod h1:JwYml1nuB7xOzsp52dPpHFffvOCDupsG0QubkSMEySY= -github.com/mitchellh/mapstructure v0.0.0-20160808181253-ca63d7c062ee/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y= -github.com/mitchellh/mapstructure v1.1.2/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y= -github.com/mitchellh/mapstructure v1.4.1/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo= github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= github.com/modern-go/reflect2 v0.0.0-20180701023420-4b7aa43c6742/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0= @@ -273,16 +151,12 @@ github.com/mwitkow/go-conntrack v0.0.0-20190716064945-2f068394615f/go.mod h1:qRW github.com/olekukonko/tablewriter v0.0.5 h1:P2Ga83D34wi1o9J6Wh1mRuqd4mF/x/lgBS7N7AbDhec= github.com/olekukonko/tablewriter v0.0.5/go.mod h1:hPp6KlRPjbx+hW8ykQs1w3UBbZlj6HuIJcUGPhkA7kY= github.com/opentracing/opentracing-go v1.1.0/go.mod h1:UkNAQd3GIcIGf0SeVgPpRdFStlNbqXla1AfSYxPUl2o= -github.com/pascaldekloe/goe v0.0.0-20180627143212-57f6aae5913c/go.mod h1:lzWF7FIEvWOWxwDKqyGYQf6ZUaNfKdP144TG7ZOy1lc= -github.com/pelletier/go-toml v1.9.3/go.mod h1:u1nR/EPcESfeI/szUZKdtJ0xRNbUoANCkoOuaOx1Y+c= github.com/pkg/errors v0.8.0/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4= github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= -github.com/pkg/sftp v1.10.1/go.mod h1:lYOWFsE0bwd1+KfKJaKeuokY15vzFx25BLbzYYoAxZI= github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= -github.com/posener/complete v1.1.1/go.mod h1:em0nMJCgc9GFtwrmVmEMR/ZL6WyhyjMBndrE9hABlRI= github.com/prometheus/client_golang v0.9.1/go.mod h1:7SWBe2y4D6OKWSNQJUaRYU/AaXPKyh/dDVn+NZz0KFw= github.com/prometheus/client_golang v1.0.0/go.mod h1:db9x61etRT2tGnBNRi70OPL5FsnadC4Ky3P0J6CfImo= github.com/prometheus/client_golang v1.7.1/go.mod h1:PY5Wy2awLA44sXw4AOSfFBetzPP4j5+D6mVACh+pe2M= @@ -303,57 +177,37 @@ github.com/prometheus/procfs v0.1.3/go.mod h1:lV6e/gmhEcM9IjHGsFOCxxuZ+z1YqCvr4O github.com/prometheus/procfs v0.6.0 h1:mxy4L2jP6qMonqmq+aTtOx1ifVWUgG/TAmntgbh3xv4= github.com/prometheus/procfs v0.6.0/go.mod h1:cz+aTbrPOrUb4q7XlbU9ygM+/jj0fzG6c1xBZuNvfVA= github.com/rogpeppe/fastuuid v1.2.0/go.mod h1:jVj6XXZzXRy/MSR5jhDC/2q6DgLz+nrA6LYCDYWNEvQ= -github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4= -github.com/russross/blackfriday/v2 v2.0.1 h1:lPqVAte+HuHNfhJ/0LC98ESWRz8afy9tM/0RK8m9o+Q= github.com/russross/blackfriday/v2 v2.0.1/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= -github.com/ryanuber/columnize v0.0.0-20160712163229-9b3edd62028f/go.mod h1:sm1tb6uqfes/u+d4ooFouqFdy9/2g9QGwK3SQygK0Ts= -github.com/sean-/seed v0.0.0-20170313163322-e2103e2c3529/go.mod h1:DxrIzT+xaE7yg65j358z/aeFdxmN0P9QXhEzd20vsDc= -github.com/shurcooL/sanitized_anchor_name v1.0.0 h1:PdmoCO6wvbs+7yrJyMORt4/BmY5IYyJwS/kOiWx8mHo= +github.com/russross/blackfriday/v2 v2.1.0 h1:JIOH55/0cWyOuilr9/qlrm0BSXldqnqwMsf35Ld67mk= +github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= github.com/shurcooL/sanitized_anchor_name v1.0.0/go.mod h1:1NzhyTcUVG4SuEtjjoZeVRXNmyL/1OwPU0+IJeTBvfc= github.com/sirupsen/logrus v1.2.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPxbbu5VWo= github.com/sirupsen/logrus v1.4.2/go.mod h1:tLMulIdttU9McNUspp0xgXVQah82FyeX6MwdIuYE2rE= github.com/sirupsen/logrus v1.6.0/go.mod h1:7uNnSEd1DgxDLC74fIahvMZmmYsHGZGEOFrfsX/uA88= github.com/sirupsen/logrus v1.8.1/go.mod h1:yWOB1SBYBC5VeMP7gHvWumXLIWorT60ONWic61uBYv0= -github.com/smartystreets/assertions v0.0.0-20180927180507-b2de0cb4f26d/go.mod h1:OnSkiWE9lh6wB0YB77sQom3nweQdgAjqCqsofrRNTgc= -github.com/smartystreets/goconvey v1.6.4/go.mod h1:syvi0/a8iFYH4r/RixwvyeAJjdLS9QV7WQ/tjFTllLA= github.com/soheilhy/cmux v0.1.5/go.mod h1:T7TcVDs9LWfQgPlPsdngu6I6QIoyIFZDDC6sNE1GqG0= github.com/spaolacci/murmur3 v0.0.0-20180118202830-f09979ecbc72/go.mod h1:JwIasOWyU6f++ZhiEuf87xNszmSA2myDM2Kzu9HwQUA= -github.com/spf13/afero v1.6.0/go.mod h1:Ai8FlHk4v/PARR026UzYexafAt9roJ7LcLMAmO6Z93I= -github.com/spf13/cast v1.3.1/go.mod h1:Qx5cxh0v+4UWYiBimWS+eyWzqEqokIECu5etghLkUJE= -github.com/spf13/cobra v1.2.1 h1:+KmjbUw1hriSNMF55oPrkZcb27aECyrj8V2ytv7kWDw= -github.com/spf13/cobra v1.2.1/go.mod h1:ExllRjgxM/piMAM+3tAZvg8fsklGAf3tPfi+i8t68Nk= -github.com/spf13/jwalterweatherman v1.1.0/go.mod h1:aNWZUN0dPAAO/Ljvb5BEdw96iTZ0EXowPYD95IqWIGo= +github.com/spf13/cobra v1.4.0 h1:y+wJpx64xcgO1V+RcnwW0LEHxTKRi2ZDPSBjWnrg88Q= +github.com/spf13/cobra v1.4.0/go.mod h1:Wo4iy3BUC+X2Fybo0PDqwJIv3dNRiZLHQymsfxlB84g= github.com/spf13/pflag v1.0.5 h1:iy+VFUOCP1a+8yFto/drg2CJ5u0yRoB7fZw3DKv/JXA= github.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg= -github.com/spf13/viper v1.8.1/go.mod h1:o0Pch8wJ9BVSWGQMbra6iw0oQ5oktSIBaujf1rJH9Ns= github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= 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.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA= -github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/stretchr/testify v1.7.0 h1:nwc3DEeHmmLAfoZucVR881uASk0Mfjw8xYJ99tb5CcY= github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= -github.com/subosito/gotenv v1.2.0/go.mod h1:N0PQaV/YGNqwC0u51sEeR/aUtSLEXKX9iv69rRypqCw= github.com/tmc/grpc-websocket-proxy v0.0.0-20201229170055-e5319fda7802/go.mod h1:ncp9v5uamzpCO7NfCPTXjqaC+bZgJeR0sMTm6dMHP7U= github.com/urfave/cli v1.22.4 h1:u7tSpNPPswAFymm8IehJhy4uJMlUuU/GmqSkvJ1InXA= github.com/urfave/cli v1.22.4/go.mod h1:Gos4lmkARVdJ6EkW0WaNv/tZAAMe9V7XWyB60NtXRu0= github.com/xiang90/probing v0.0.0-20190116061207-43a291ad63a2 h1:eY9dn8+vbi4tKz5Qo6v2eYzo7kUS51QINcR5jNpbZS8= github.com/xiang90/probing v0.0.0-20190116061207-43a291ad63a2/go.mod h1:UETIi67q53MR2AWcXfiuqkDkRtnGDLqkBTpCHuJHxtU= -github.com/yuin/goldmark v1.1.25/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= -github.com/yuin/goldmark v1.1.32/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= go.etcd.io/bbolt v1.3.6 h1:/ecaJf0sk1l4l6V4awd65v2C3ILy7MSj+s/x1ADCIMU= go.etcd.io/bbolt v1.3.6/go.mod h1:qXsaaIqmgQH0T+OPdb99Bf+PKfBBQVAdyD6TY9G8XM4= -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.2/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.5/go.mod h1:5pWMHQbX5EPX2/62yrJeAkowc+lfs/XD7Uxpq3pI6kk= -go.opencensus.io v0.23.0/go.mod h1:XItmlyltB5F7CS4xOC1DcqMoFqwtC6OG2xF7mCv7P7E= go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.26.1 h1:puWrOArBwWlr5dq6vyZ6fKykHyS8JgMIVhTBA8XsGuU= go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.26.1/go.mod h1:4wsfAAW5N9wUHM0QTmZS8z7fvYZ1rv3m+sVeSpf8NhU= go.opentelemetry.io/otel v1.1.0/go.mod h1:7cww0OW51jQ8IaZChIEdqLwgh+44+7uiTdWsAL0wQpA= @@ -380,183 +234,81 @@ go.uber.org/zap v1.10.0/go.mod h1:vwi/ZaCAaUcBkycHslxD9B2zi4UTXhF60s6SWpuDF0Q= go.uber.org/zap v1.17.0 h1:MTjgFu6ZLKvY6Pvaqk97GlxNBuMpV4Hy/3P6tRGlI2U= go.uber.org/zap v1.17.0/go.mod h1:MXVU+bhUf/A7Xi2HNOnopQOrmycQ5Ih87HtOu4q5SSo= golang.org/x/crypto v0.0.0-20180904163835-0709b304e793/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= -golang.org/x/crypto v0.0.0-20181029021203-45a5f77698d3/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= -golang.org/x/crypto v0.0.0-20190510104115-cbcb75029529/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= -golang.org/x/crypto v0.0.0-20190605123033-f99c8df09eb5/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= -golang.org/x/crypto v0.0.0-20190820162420-60c769a6c586/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= golang.org/x/crypto v0.0.0-20210513164829-c07d793c2f9a h1:kr2P4QFmQr29mSLA43kwrOcgcReGTfbE9N577tCTuBc= golang.org/x/crypto v0.0.0-20210513164829-c07d793c2f9a/go.mod h1:P+XmwS30IXTQdn5tA2iutPOUgjI07+tq3H3K9MVA1s8= golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= -golang.org/x/exp v0.0.0-20190306152737-a1d7652674e8/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= -golang.org/x/exp v0.0.0-20190510132918-efd6b22b2522/go.mod h1:ZjyILWgesfNpC6sMxTJOJm9Kp84zZh5NQWvqDGG3Qr8= -golang.org/x/exp v0.0.0-20190829153037-c13cbed26979/go.mod h1:86+5VVa7VpoJ4kLfm080zCjGlMRFzhUhsZKEZO7MGek= -golang.org/x/exp v0.0.0-20191030013958-a1ab85dbe136/go.mod h1:JXzH8nQsPlswgeRAPE3MuO9GYsAcnJvJ4vnMwN/5qkY= -golang.org/x/exp v0.0.0-20191129062945-2f5052295587/go.mod h1:2RIsYlXP63K8oxa1u096TMicItID8zy7Y6sNkU49FU4= -golang.org/x/exp v0.0.0-20191227195350-da58074b4299/go.mod h1:2RIsYlXP63K8oxa1u096TMicItID8zy7Y6sNkU49FU4= -golang.org/x/exp v0.0.0-20200119233911-0405dc783f0a/go.mod h1:2RIsYlXP63K8oxa1u096TMicItID8zy7Y6sNkU49FU4= -golang.org/x/exp v0.0.0-20200207192155-f17229e696bd/go.mod h1:J/WKrq2StrnmMY6+EHIKF9dgMWnmCNThgcyBT1FY9mM= -golang.org/x/exp v0.0.0-20200224162631-6cc2880d07d6/go.mod h1:3jZMyOhIsHpP37uCMkUooju7aAi5cS1Q23tOzKc+0MU= -golang.org/x/image v0.0.0-20190227222117-0694c2d4d067/go.mod h1:kZ7UVZpmo3dzQBMxlp+ypCbDeSB+sBbTgSJuh5dn5js= -golang.org/x/image v0.0.0-20190802002840-cff245a6509b/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0= golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE= golang.org/x/lint v0.0.0-20190227174305-5b3e6a55c961/go.mod h1:wehouNa3lNwaWXcvxsM5YxQ5yQlVC4a0KAMCusXpPoU= -golang.org/x/lint v0.0.0-20190301231843-5614ed5bae6f/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE= golang.org/x/lint v0.0.0-20190313153728-d0100b6bd8b3/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= -golang.org/x/lint v0.0.0-20190409202823-959b441ac422/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= -golang.org/x/lint v0.0.0-20190909230951-414d861bb4ac/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= -golang.org/x/lint v0.0.0-20190930215403-16217165b5de/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= -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-20200302205851-738671d3881b/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY= -golang.org/x/lint v0.0.0-20201208152925-83fdc39ff7b5/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-20190719004257-d2bd2a29d028/go.mod h1:E/iHnbuqvinMTCcRqshq8CkpyQDoeVncDDYHnLhea+o= -golang.org/x/mod v0.0.0-20190513183733-4bf6d317e70e/go.mod h1:mXi4GBBbnImb6dmsKGUJ2LatrhH/nqhxcFungHvyanc= -golang.org/x/mod v0.1.0/go.mod h1:0QHyrYULN0/3qlju5TqG8bIK38QM8yzMo5ekMj3DlcY= -golang.org/x/mod v0.1.1-0.20191105210325-c90efee705ee/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.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/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-20181023162649-9b4f9f5ad519/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20181114220301-adae6a3d119a/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= -golang.org/x/net v0.0.0-20181201002055-351d144fa1fc/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20190108225652-1e06a53dbb7e/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20190213061140-3a22650c66bd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= -golang.org/x/net v0.0.0-20190501004415-9ce7a6920f09/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= -golang.org/x/net v0.0.0-20190503192946-f4e77d36d62c/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= -golang.org/x/net v0.0.0-20190603091049-60506f45cf65/go.mod h1:HSz+uSET+XFnRR8LxR5pz3Of3rY3CfYBVs4xY44aLks= golang.org/x/net v0.0.0-20190613194153-d28f0bde5980/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= -golang.org/x/net v0.0.0-20190628185345-da137c7871d7/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= -golang.org/x/net v0.0.0-20190724013045-ca1201d0de80/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= -golang.org/x/net v0.0.0-20191209160850-c0dbc17a3553/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= -golang.org/x/net v0.0.0-20200114155413-6afb5195e5aa/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= -golang.org/x/net v0.0.0-20200202094626-16171245cfb2/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= -golang.org/x/net v0.0.0-20200222125558-5a598a2470a0/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20200226121028-0de0cce0169b/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= -golang.org/x/net v0.0.0-20200301022130-244492dfa37a/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= -golang.org/x/net v0.0.0-20200324143707-d3edc9973b7e/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= -golang.org/x/net v0.0.0-20200501053045-e0ff5e5a1de5/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= -golang.org/x/net v0.0.0-20200506145744-7e3656a0809f/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= -golang.org/x/net v0.0.0-20200513185701-a91f0712d120/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= -golang.org/x/net v0.0.0-20200520182314-0ba52f642ac2/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= golang.org/x/net v0.0.0-20200625001655-4c5254603344/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-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-20201202161906-c7110b5ffcbb/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-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-20220105145211-5b0dc2dfae98 h1:+6WJMRLHlD7X7frgp7TUZ36RnQzSf9wVVTNakEp+nqY= golang.org/x/net v0.0.0-20220105145211-5b0dc2dfae98/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= 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-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-20200107190931-bf48bf16ab8d h1:TzXSXBo42m9gQenoE3b9BGiEpg5IG2JkU5FkPIawgtw= 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-20210402161424-2e8d93401602 h1:0Ja1LBD+yisY6RWM/BH7TJVXWsSjs2VwBSmvSX4HdBc= -golang.org/x/oauth2 v0.0.0-20210402161424-2e8d93401602/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= 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-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.0.0-20190227155943-e225da77a7e6/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.0.0-20200317015054-43a5402ce75a/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.0.0-20200625203802-6e8e738ad208/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-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sys v0.0.0-20180823144017-11551d06cbcc/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= -golang.org/x/sys v0.0.0-20181026203630-95b1ffbd15a5/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20181116152217-5ac8a444bdc5/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= -golang.org/x/sys v0.0.0-20190312061237-fead79001313/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190422165155-953cdadca894/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20190502145724-3ef323f4f1fd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20190507160741-ecd444e8653b/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20190606165138-5da285871e9c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20190624142023-c5567b49c5d0/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20190726091711-fc99dfbffb4e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20191001151750-bb3f8db39f24/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20191005200804-aed5e4c7ecf9/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20191026070338-33540a1f6037/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20191204072324-ce4227a45e2e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20191228213918-04cbcbbfeed8/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200106162015-b016eb3dc98e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200113162924-86b910548bc1/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200122134326-e047566fdf82/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200202164722-d101bd2416d5/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200212091648-12a6c2dcc1e4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200116001909-b77594299b42/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200223170610-d5e6a3e2c0ae/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200302150141-5c8b2ff67527/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200331124033-c3d80250170d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200501052902-10377860bb8e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200511232937-7e40ca221e25/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200515095857-1151b9dac4a9/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200523222454-059865788121/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-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-20200923182605-d9f96fdee20d/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-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-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-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-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-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-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-20210630005230-0f9fa26af87c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20210927094055-39ccf1dd6fa6/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20211123173158-ef496fb156ab h1:rfJ1bsoJQQIAoAxTxB7bme+vHrNkRw8CqfsYh9w54cw= golang.org/x/sys v0.0.0-20211123173158-ef496fb156ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= -golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= -golang.org/x/text v0.3.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.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.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/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-20191024005414-555d28b269f0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.0.0-20210220033141-f8bda1e9f3ba h1:O8mE0/t419eoIwhTFpKVkHiTs/Igowgfkj25AcZrtiE= golang.org/x/time v0.0.0-20210220033141-f8bda1e9f3ba/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= @@ -564,151 +316,33 @@ golang.org/x/tools v0.0.0-20181030221726-6c7e314b6563/go.mod h1:n7NCudcB/nEzxVGm 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-20190311212946-11955173bddd/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= -golang.org/x/tools v0.0.0-20190312151545-0bb0c0a6e846/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= -golang.org/x/tools v0.0.0-20190312170243-e65039ee4138/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= -golang.org/x/tools v0.0.0-20190328211700-ab21143f2384/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= -golang.org/x/tools v0.0.0-20190425150028-36563e24a262/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q= -golang.org/x/tools v0.0.0-20190506145303-2d16b83fe98c/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q= golang.org/x/tools v0.0.0-20190524140312-2c0ae7006135/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q= -golang.org/x/tools v0.0.0-20190606124116-d0a3d012864b/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc= -golang.org/x/tools v0.0.0-20190621195816-6e04913cbbac/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc= -golang.org/x/tools v0.0.0-20190628153133-6cdbf07be9d0/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc= -golang.org/x/tools v0.0.0-20190816200558-6889da9d5479/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= -golang.org/x/tools v0.0.0-20190911174233-4f2ddba30aff/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= -golang.org/x/tools v0.0.0-20191012152004-8de300cfc20a/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= -golang.org/x/tools v0.0.0-20191112195655-aa38f8e97acc/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= -golang.org/x/tools v0.0.0-20191113191852-77e3bb0ad9e7/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= -golang.org/x/tools v0.0.0-20191115202509-3a792d9c32b2/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= -golang.org/x/tools v0.0.0-20191125144606-a911d9008d1f/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= -golang.org/x/tools v0.0.0-20191130070609-6e064ea0cf2d/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= -golang.org/x/tools v0.0.0-20191216173652-a0e659d51361/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= -golang.org/x/tools v0.0.0-20191227053925-7b8e75db28f4/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= -golang.org/x/tools v0.0.0-20200117161641-43d50277825c/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= -golang.org/x/tools v0.0.0-20200122220014-bf1340f18c4a/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= -golang.org/x/tools v0.0.0-20200130002326-2f3ba24bd6e7/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= -golang.org/x/tools v0.0.0-20200204074204-1cc6d1ef6c74/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= -golang.org/x/tools v0.0.0-20200207183749-b753a1ba74fa/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= -golang.org/x/tools v0.0.0-20200212150539-ea181f53ac56/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= -golang.org/x/tools v0.0.0-20200224181240-023911ca70b2/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= -golang.org/x/tools v0.0.0-20200227222343-706bc42d1f0d/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= -golang.org/x/tools v0.0.0-20200304193943-95d2e580d8eb/go.mod h1:o4KQGtdN14AW+yjsvvwRTJJuXz8XRtIHtEnmAXLyFUw= -golang.org/x/tools v0.0.0-20200312045724-11d5b4c81c7d/go.mod h1:o4KQGtdN14AW+yjsvvwRTJJuXz8XRtIHtEnmAXLyFUw= -golang.org/x/tools v0.0.0-20200331025713-a30bf2db82d4/go.mod h1:Sl4aGygMT6LrqrWclx+PTx3U+LnKx/seiNR+3G19Ar8= -golang.org/x/tools v0.0.0-20200501065659-ab2804fb9c9d/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= -golang.org/x/tools v0.0.0-20200512131952-2bc93b1c0c88/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= -golang.org/x/tools v0.0.0-20200515010526-7d3b6ebf133d/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= -golang.org/x/tools v0.0.0-20200618134242-20370b0cb4b2/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= golang.org/x/tools v0.0.0-20200619180055-7c47624df98f/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= -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-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-20210105154028-b0ab187a4818/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/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-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1 h1:go1bK/D/BFZV2I8cIQd1NKEZ+0owSTG1fDTci4IqFcE= golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= -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.8.0/go.mod h1:o4eAsZoiT+ibD93RtjEohWalFOjRDx6CVaqeizhEnKg= -google.golang.org/api v0.9.0/go.mod h1:o4eAsZoiT+ibD93RtjEohWalFOjRDx6CVaqeizhEnKg= -google.golang.org/api v0.13.0/go.mod h1:iLdEw5Ide6rF15KTC1Kkl0iskquN2gFfn9o9XIsbkAI= -google.golang.org/api v0.14.0/go.mod h1:iLdEw5Ide6rF15KTC1Kkl0iskquN2gFfn9o9XIsbkAI= -google.golang.org/api v0.15.0/go.mod h1:iLdEw5Ide6rF15KTC1Kkl0iskquN2gFfn9o9XIsbkAI= -google.golang.org/api v0.17.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE= -google.golang.org/api v0.18.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE= -google.golang.org/api v0.19.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE= -google.golang.org/api v0.20.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE= -google.golang.org/api v0.22.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE= -google.golang.org/api v0.24.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.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.44.0/go.mod h1:EBOGZqzyhtvMDoxwS97ctnh0zUmYY6CxqXsc1AvkYD8= google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM= +google.golang.org/appengine v1.4.0 h1:/wp5JvzpHIxhs/dumFmF7BXTf3Z+dd4uXta4kVyO508= 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.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.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-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-20190425155659-357c62f0e4bb/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= -google.golang.org/genproto v0.0.0-20190502173448-54afdca5d873/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= -google.golang.org/genproto v0.0.0-20190801165951-fa694d86fc64/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc= google.golang.org/genproto v0.0.0-20190819201941-24fa4b261c55/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc= -google.golang.org/genproto v0.0.0-20190911173649-1774047e7e51/go.mod h1:IbNlFCBrqXvoKpeg0TB2l7cyZUmoaFKYIwrEpbDKLA8= -google.golang.org/genproto v0.0.0-20191108220845-16a3f7862a1a/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= -google.golang.org/genproto v0.0.0-20191115194625-c23dd37a84c9/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= -google.golang.org/genproto v0.0.0-20191216164720-4f79533eabd1/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= -google.golang.org/genproto v0.0.0-20191230161307-f3c370f40bfb/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= -google.golang.org/genproto v0.0.0-20200115191322-ca5a22157cba/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= -google.golang.org/genproto v0.0.0-20200122232147-0452cf42e150/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= -google.golang.org/genproto v0.0.0-20200204135345-fa8e72b47b90/go.mod h1:GmwEX6Z4W5gMy59cAlVYjN9JhxgbQH6Gn+gFDQe2lzA= -google.golang.org/genproto v0.0.0-20200212174721-66ed5ce911ce/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= -google.golang.org/genproto v0.0.0-20200224152610-e50cd9704f63/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= -google.golang.org/genproto v0.0.0-20200228133532-8c2c7df3a383/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= -google.golang.org/genproto v0.0.0-20200305110556-506484158171/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= -google.golang.org/genproto v0.0.0-20200312145019-da6875a35672/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= -google.golang.org/genproto v0.0.0-20200331122359-1ee6d9798940/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= google.golang.org/genproto v0.0.0-20200423170343-7949de9c1215/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= -google.golang.org/genproto v0.0.0-20200430143042-b979b6f78d84/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= -google.golang.org/genproto v0.0.0-20200511104702-f5ebc3bea380/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= google.golang.org/genproto v0.0.0-20200513103714-09dca8ec2884/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= -google.golang.org/genproto v0.0.0-20200515170657-fc4c6c6a6587/go.mod h1:YsZOwe1myG/8QRHRsmBRE1LrgQY60beZKjly0O1fX9U= google.golang.org/genproto v0.0.0-20200526211855-cb27e3aa2013/go.mod h1:NbSheEEYHJ7i3ixzK3sjbqSGDJWnxyFXZblF3eUsNvo= -google.golang.org/genproto v0.0.0-20200618031413-b414f8b61790/go.mod h1:jDfRM7FcilCzHH/e9qn6dsT145K34l5v+OpcnNgKAAA= -google.golang.org/genproto v0.0.0-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-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-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-20210402141018-6c239bbf2bb1/go.mod h1:9lPAdzaEmUacj36I+k7YKbEc5CXzPIeORRgDAUOu28A= google.golang.org/genproto v0.0.0-20211118181313-81c1377c94b1 h1:b9mVrqYfq3P4bCdaLg1qtBnPzUYgglsIdjZkL/fQVOE= google.golang.org/genproto v0.0.0-20211118181313-81c1377c94b1/go.mod h1:5CzLGKJ67TSI2B9POpiiyGha0AjJvZIUgRMt1dSmuhc= 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.21.1/go.mod h1:oYelfM1adQP15Ek0mdvEgi9Df8B9CZIaU1084ijfRaM= google.golang.org/grpc v1.23.0/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg= google.golang.org/grpc v1.25.1/go.mod h1:c3i+UQWmh7LiEpx4sFZnkU36qjEYZ0imhYfXVyQciAY= -google.golang.org/grpc v1.26.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk= google.golang.org/grpc v1.27.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk= -google.golang.org/grpc v1.27.1/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk= -google.golang.org/grpc v1.28.0/go.mod h1:rpkK4SK4GF4Ach/+MFLZUBavHOvF2JJB5uozKKal+60= 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.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.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.1/go.mod h1:qjiiYl8FncCW8feJPdyg3v6XW24KsRHe+dy9BAGRRjU= 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.40.0/go.mod h1:ogyxbiOoUXAkP+4+xa6PZSE9DZgIHtSpzjDTB9KAK34= google.golang.org/grpc v1.41.0 h1:f+PlOh7QV4iIJkPrx5NQ7qaNGFQ3OTse67yaDHfju4E= google.golang.org/grpc v1.41.0/go.mod h1:U3l9uK9J0sini8mHphKoXyaqDA/8VyGnDee1zzIUK6k= @@ -720,7 +354,6 @@ google.golang.org/protobuf v1.21.0/go.mod h1:47Nbq4nVaFHyn7ilMalzfO3qCViNmqZ2kzi google.golang.org/protobuf v1.22.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= google.golang.org/protobuf v1.23.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= google.golang.org/protobuf v1.23.1-0.20200526195155-81db48ad09cc/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= -google.golang.org/protobuf v1.24.0/go.mod h1:r/3tXBNzIEhYS9I1OUVjXDlt8tc493IdKGjtUeSXeh4= google.golang.org/protobuf v1.25.0/go.mod h1:9JNX74DMeImyA3h4bdi1ymwjUzf21/xIlbajtzgsN7c= google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw= google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc= @@ -728,12 +361,9 @@ google.golang.org/protobuf v1.27.1 h1:SnqbnDw1V7RiZcXPx5MEeqPv2s79L9i7BJUlG/+Rur google.golang.org/protobuf v1.27.1/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc= gopkg.in/alecthomas/kingpin.v2 v2.2.6/go.mod h1:FMv+mEhP44yOT+4EoQTLFTRgOQ1FBLkstjWtayDeSgw= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= -gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/cheggaaa/pb.v1 v1.0.28 h1:n1tBJnnK2r7g9OW2btFH91V92STTUevLXYFb8gy9EMk= gopkg.in/cheggaaa/pb.v1 v1.0.28/go.mod h1:V/YB90LKu/1FcN3WVnfiiE5oMCibMjukxqG/qStrOgw= -gopkg.in/errgo.v2 v2.1.0/go.mod h1:hNsd1EY+bozCKY1Ytp96fpM3vjJbqLJn88ws8XvfDNI= -gopkg.in/ini.v1 v1.62.0/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k= gopkg.in/natefinch/lumberjack.v2 v2.0.0/go.mod h1:l0ndWWf7gzL7RNwBG7wST/UCcT4T24xpD6X8LsfU/+k= gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= @@ -748,15 +378,7 @@ gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b h1:h8qDotaEPuJATrMmW04NCwg7v22aHH28wwpauUhK9Oo= gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= -honnef.co/go/tools v0.0.0-20190106161140-3f1c8253044a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= -honnef.co/go/tools v0.0.0-20190418001031-e561f6794a2a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= honnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= -honnef.co/go/tools v0.0.1-2019.2.3/go.mod h1:a3bituU0lyd329TUQxRnasdCoJDkEUEAqEt0JzvZhAg= -honnef.co/go/tools v0.0.1-2020.1.3/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9vFzvIQ3k= -honnef.co/go/tools v0.0.1-2020.1.4/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9vFzvIQ3k= -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/sampler v1.3.0/go.mod h1:T1hPZKmBbMNahiBKFy5HrXp6adAjACjK9JXDnKaTXpA= sigs.k8s.io/json v0.0.0-20211020170558-c049b76a60c6 h1:fD1pz4yfdADVNfFmcP2aBEtudwUQ1AlLnRBALr33v3s= sigs.k8s.io/json v0.0.0-20211020170558-c049b76a60c6/go.mod h1:p4QtZmO4uMYipTQNzagwnNoseA6OxSUutVw05NhYDRs= sigs.k8s.io/yaml v1.2.0/go.mod h1:yfXDCHCao9+ENCvLSE62v9VSji2MKu5jeNfTrofGhJc= diff --git a/etcdutl/go.mod b/etcdutl/go.mod index 719335f1a32f..82f39a6ad0a1 100644 --- a/etcdutl/go.mod +++ b/etcdutl/go.mod @@ -24,7 +24,7 @@ require ( github.com/coreos/go-semver v0.3.0 github.com/dustin/go-humanize v1.0.0 github.com/olekukonko/tablewriter v0.0.5 - github.com/spf13/cobra v1.2.1 + github.com/spf13/cobra v1.4.0 go.etcd.io/bbolt v1.3.6 go.etcd.io/etcd/api/v3 v3.6.0-alpha.0 go.etcd.io/etcd/client/pkg/v3 v3.6.0-alpha.0 diff --git a/etcdutl/go.sum b/etcdutl/go.sum index ffcd56428784..673bd9eef83e 100644 --- a/etcdutl/go.sum +++ b/etcdutl/go.sum @@ -1,45 +1,7 @@ cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= +cloud.google.com/go v0.34.0 h1:eOI3/cP2VTU6uZLDYAoic+eyzzB9YyGmJ7eIjl8rOPg= cloud.google.com/go v0.34.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= -cloud.google.com/go v0.38.0/go.mod h1:990N+gfupTy94rShfmMCWGDn0LpTmnzTp2qbd1dvSRU= -cloud.google.com/go v0.44.1/go.mod h1:iSa0KzasP4Uvy3f1mN/7PiObzGgflwredwwASm/v6AU= -cloud.google.com/go v0.44.2/go.mod h1:60680Gw3Yr4ikxnPRS/oxxkBccT6SA1yMk63TGekxKY= -cloud.google.com/go v0.45.1/go.mod h1:RpBamKRgapWJb87xiFSdk4g1CME7QZg3uwTez+TSTjc= -cloud.google.com/go v0.46.3/go.mod h1:a6bKKbmY7er1mI7TEI4lsAkts/mkhTSZK8w33B4RAg0= -cloud.google.com/go v0.50.0/go.mod h1:r9sluTvynVuxRIOHXQEHMFffphuXHOMZMycpNR5e6To= -cloud.google.com/go v0.52.0/go.mod h1:pXajvRH/6o3+F9jDHZWQ5PbGhn+o8w9qiu/CffaVdO4= -cloud.google.com/go v0.53.0/go.mod h1:fp/UouUEsRkN6ryDKNW/Upv/JBKnv6WDthjR6+vze6M= -cloud.google.com/go v0.54.0/go.mod h1:1rq2OEkV3YMf6n/9ZvGWI3GWw0VoqH/1x2nd8Is/bPc= -cloud.google.com/go v0.56.0/go.mod h1:jr7tqZxxKOVYizybht9+26Z/gUq7tiRzu+ACVAMbKVk= -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.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 h1:at8Tk2zUz63cLPR0JPWm5vp77pEZmzxEQBEfRKn1VV8= -cloud.google.com/go v0.81.0/go.mod h1:mk/AM35KwGk/Nm2YSeZbxXdrNK3KZOYHmLkOqC2V6E0= -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.4.0/go.mod h1:S8dzgnTigyfTmLBfrtrhyYhwRxG72rYxvftPBK2Dvzc= -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.8.0/go.mod h1:J5hqkt3O0uAFnINi6JXValWIb1v0goeZM77hZzJN/fQ= -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/firestore v1.1.0/go.mod h1:ulACoGHTpvq5r8rxGJ4ddJZBZqakUQqClKRT5SZwBmk= -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.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/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.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.10.0/go.mod h1:FLPqc6j+Ki4BU591ie1oL6qBQGu2Bl/tZ9ullr3+Kg0= -dmitri.shuralyov.com/gpu/mtl v0.0.0-20190408044501-666a987793e9/go.mod h1:H6x//7gZCb22OMCxBHrMx7a5I7Hp++hsVxbQ4BYO7hU= github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= -github.com/BurntSushi/xgb v0.0.0-20160522181843-27f122750802/go.mod h1:IVnqGOEym/WlBOVXweHU+Q+/VP0lqqI8lqeDx9IjBqo= github.com/OneOfOne/xxhash v1.2.2/go.mod h1:HSdplMjZKSmBqAxg5vPj2TmRDmfkzw+cTzAElWljhcU= github.com/alecthomas/template v0.0.0-20160405071501-a0175ee3bccc/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc= github.com/alecthomas/template v0.0.0-20190718012654-fb15b899a751/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc= @@ -47,15 +9,10 @@ github.com/alecthomas/units v0.0.0-20151022065526-2efee857e7cf/go.mod h1:ybxpYRF github.com/alecthomas/units v0.0.0-20190717042225-c3de453c63f4/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0= github.com/alecthomas/units v0.0.0-20190924025748-f65c72e2690d/go.mod h1:rBZYJk541a8SKzHPHnH3zbiI+7dagKZ0cgpgrD7Fyho= github.com/antihax/optional v1.0.0/go.mod h1:uupD/76wgC+ih3iEmQUL+0Ugr19nfwCT1kdvxnR2qWY= -github.com/armon/circbuf v0.0.0-20150827004946-bbbad097214e/go.mod h1:3U/XgcO3hCbHZ8TKRvWD2dDTCfh9M9ya+I9JpbB7O8o= -github.com/armon/go-metrics v0.0.0-20180917152333-f0300d1749da/go.mod h1:Q73ZrmVTwzkszR9V5SSuryQ31EELlFMUz1kKyl939pY= -github.com/armon/go-radix v0.0.0-20180808171621-7fddfc383310/go.mod h1:ufUuZ+zHj4x4TnLV4JWEpy2hxWSpsRywHrMgIH9cCH8= github.com/beorn7/perks v0.0.0-20180321164747-3a771d992973/go.mod h1:Dwedo/Wpr24TaqPxmxbtue+5NUziq4I4S80YR8gNf3Q= github.com/beorn7/perks v1.0.0/go.mod h1:KWe93zE9D1o94FZ5RNwFwVgaQK1VOXiVxmqh+CedLV8= github.com/beorn7/perks v1.0.1 h1:VlbKKnNfV8bJzeqoa4cOKqO6bYr3WgKZxO8Z16+hsOM= github.com/beorn7/perks v1.0.1/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6rlkpw= -github.com/bgentry/speakeasy v0.1.0/go.mod h1:+zsyZBPWlz7T6j88CTgSN5bM796AkVf0kBD4zp0CCIs= -github.com/bketelsen/crypt v0.0.4/go.mod h1:aI6NrJ0pMGgvZKL1iVgXLnfIFJtfV+bKCoqOes/6LfM= github.com/cenkalti/backoff/v4 v4.1.1/go.mod h1:scbssz8iZGpm3xbr14ovlUdkxfGXNInqkPWOWmG2CLw= github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU= github.com/certifi/gocertifi v0.0.0-20191021191039-0944d244cd40/go.mod h1:sGbDF6GwGcLpkNXPUTkMRoywsNa/ol15pxFe6ERfguA= @@ -65,12 +22,8 @@ github.com/cespare/xxhash v1.1.0 h1:a6HrQnmkObjyL+Gs60czilIUGqrzKutQD6XZog3p+ko= github.com/cespare/xxhash v1.1.0/go.mod h1:XrSqR1VqqWfGrhpAt58auRo0WTKS1nRRg3ghfAqPWnc= github.com/cespare/xxhash/v2 v2.1.1 h1:6MnRN8NT7+YBpUIWxHtefFZOKTAPgGjpQSxqLNn0+qY= github.com/cespare/xxhash/v2 v2.1.1/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= -github.com/chzyer/logex v1.1.10/go.mod h1:+Ywpsq7O8HXn0nuIou7OrIPyXbp3wmkHB+jjWRnGsAI= -github.com/chzyer/readline v0.0.0-20180603132655-2972be24d48e/go.mod h1:nSuG5e5PlCu98SY8svDHJxuZscDgtXS6KTTbou5AhLI= -github.com/chzyer/test v0.0.0-20180213035817-a1ea475d72b1/go.mod h1:Q3SI9o4m/ZMnBNeIyt5eFwwo7qiLfzFZmjNmxjkiQlU= github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw= 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/xds/go v0.0.0-20210312221358-fbca930ec8ed/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs= github.com/cncf/xds/go v0.0.0-20210805033703-aa0b78936158/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs= @@ -84,7 +37,7 @@ github.com/coreos/go-semver v0.3.0 h1:wkHLiw0WNATZnSG7epLsujiMCgPAc9xhjJ4tgnAxmf github.com/coreos/go-semver v0.3.0/go.mod h1:nnelYz7RCh+5ahJtPPxZlU+153eP4D4r3EedlOD2RNk= github.com/coreos/go-systemd/v22 v22.3.2 h1:D9/bQk5vlXQFZ6Kwuu6zaiXJ9oTPe68++AzAJc1DzSI= github.com/coreos/go-systemd/v22 v22.3.2/go.mod h1:Y58oyj3AT4RCenI/lSvhwexgC+NSVTIJ3seZv2GcEnc= -github.com/cpuguy83/go-md2man/v2 v2.0.0/go.mod h1:maD7wRr/U5Z6m/iR4s+kqSMx2CaBsrgA7czyZG/E6dU= +github.com/cpuguy83/go-md2man/v2 v2.0.1/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o= github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E= github.com/creack/pty v1.1.11/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E= github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= @@ -95,20 +48,14 @@ github.com/dustin/go-humanize v1.0.0/go.mod h1:HtrtbFcZ19U5GC7JDqmcUSB87Iq5E25Kn 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.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.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.10-0.20210907150352-cf90f659a021/go.mod h1:AFq3mo9L8Lqqiid3OhADV3RfLJnjiw63cSpi+fDTRC0= github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c= -github.com/fatih/color v1.7.0/go.mod h1:Zm6kSWBoL9eyXnKyktHP6abPY2pDugNf5KwzbycvMj4= -github.com/fsnotify/fsnotify v1.4.9/go.mod h1:znqG4EE+3YCdAaPaxE2ZRY/06pZUdp0tY4IgpuI1SZQ= github.com/getsentry/raven-go v0.2.0 h1:no+xWJRb5ZI7eE8TWgIq1jLulQiIoLG0IfYxv5JYMGs= github.com/getsentry/raven-go v0.2.0/go.mod h1:KungGk8q33+aIAZUIVWZDr2OfAEBsO49PX4NzFV5kcQ= github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04= -github.com/go-gl/glfw v0.0.0-20190409004039-e6da0acd62b1/go.mod h1:vR7hzQXu2zJy9AVAgeJqvqgH9Q5CA+iKCZ2gyEVpxRU= -github.com/go-gl/glfw/v3.3/glfw v0.0.0-20191125211704-12ad95a8df72/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8= -github.com/go-gl/glfw/v3.3/glfw v0.0.0-20200222043503-6f7a984d4dc4/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8= github.com/go-kit/kit v0.8.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as= github.com/go-kit/kit v0.9.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as= github.com/go-kit/log v0.1.0/go.mod h1:zbhenjAZHb184qTLMA9ZjW7ThYL0H2mk7Q6pNt4vbaY= @@ -124,24 +71,12 @@ github.com/gogo/protobuf v1.3.2/go.mod h1:P1XiOD3dCwIKUDQYPy72D8LYyHL2YPYrpS2s69 github.com/golang-jwt/jwt v3.2.2+incompatible h1:IfV12K8xAKAnZqdXVzCZ+TOjboZ2keLg81eXfW3O+oY= github.com/golang-jwt/jwt v3.2.2+incompatible/go.mod h1:8pz2t5EyA70fFQQSrl6XZXzqecmYZeUEB8OUGHkxJ+I= github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q= -github.com/golang/groupcache v0.0.0-20190702054246-869f871628b6/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= -github.com/golang/groupcache v0.0.0-20191227052852-215e87163ea7/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= -github.com/golang/groupcache v0.0.0-20200121045136-8c9f03a8e57e/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= github.com/golang/mock v1.1.1/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A= -github.com/golang/mock v1.2.0/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A= -github.com/golang/mock v1.3.1/go.mod h1:sBzyDLLjw3U8JLTeZvSv8jJB+tU5PVekmnlKIyFUx0Y= -github.com/golang/mock v1.4.0/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.4/go.mod h1:l3mdAwkq5BuhzHwde/uurv3sEJeZMXNpwsxVWU71h+4= -github.com/golang/mock v1.5.0/go.mod h1:CWnOUgYIOo4TcNZ0wHX3YZCqsaM1I1Jvs6v3mP3KVu8= github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= github.com/golang/protobuf v1.3.1/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= github.com/golang/protobuf v1.3.2/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= github.com/golang/protobuf v1.3.3/go.mod h1:vzj43D7+SQXF/4pzW/hwtAqwc6iTitCiVSaWz5lYuqw= -github.com/golang/protobuf v1.3.4/go.mod h1:vzj43D7+SQXF/4pzW/hwtAqwc6iTitCiVSaWz5lYuqw= -github.com/golang/protobuf v1.3.5/go.mod h1:6O5/vntMXwX2lRkT1hjjk0nAC1IDOTvTlVgjlRvqsdk= github.com/golang/protobuf v1.4.0-rc.1/go.mod h1:ceaxUfeHdC40wWswd/P6IGgMaK3YpKi5j83Wpe3EHw8= github.com/golang/protobuf v1.4.0-rc.1.0.20200221234624-67d41d38c208/go.mod h1:xKAWHe0F5eneWXFV3EuXVDTCmh+JuBKY0li0aMyXATA= github.com/golang/protobuf v1.4.0-rc.2/go.mod h1:LlEzMj4AhA7rCAGe4KMBDvJI+AwstrUpVNzEA03Pprs= @@ -151,73 +86,26 @@ 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.3/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI= 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/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY= -github.com/google/btree v0.0.0-20180813153112-4030bb1f1f0c/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ= -github.com/google/btree v1.0.0/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ= github.com/google/btree v1.0.1 h1:gK4Kx5IaGY9CD5sPJ36FHiBJ6ZXl0kilRiiCj+jdYp4= github.com/google/btree v1.0.1/go.mod h1:xXMiIv4Fb/0kKde4SpL7qlzvu5cMJDRkFDxJfI9uaxA= github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M= github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= -github.com/google/go-cmp v0.4.1/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.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.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.6 h1:BKbKCqvP6I+rmFHt06ZmyQtvB8xAkWdhFyr0ZUNZcxQ= github.com/google/go-cmp v0.5.6/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= -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.1.0/go.mod h1:y5Zk1BBys9G+gd6Jrk0W3cC1+ELVxBWuIGO+w/tUAp0= -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-20191218002539-d4f498aebedc/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= -github.com/google/pprof v0.0.0-20200212024743-f11f1df84d12/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-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/renameio v0.1.0/go.mod h1:KWCgfxg9yswjAJkECMjeO8J8rahYeXnNhOm40UhjYkI= github.com/google/uuid v1.1.2/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= -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/gopherjs/gopherjs v0.0.0-20181017120253-0766667cb4d1/go.mod h1:wJfORRmW1u3UXTncJ5qlYoELFm8eSnnEO6hX4iZ3EWY= github.com/gorilla/websocket v1.4.2/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE= github.com/grpc-ecosystem/go-grpc-middleware v1.3.0/go.mod h1:z0ButlSOZa5vEBq9m2m2hlwIgKw+rp3sdCBRoJY+30Y= github.com/grpc-ecosystem/go-grpc-prometheus v1.2.0 h1:Ovs26xHkKqVztRpIrF/92BcuyuQ/YW4NSIpoGtfXNho= github.com/grpc-ecosystem/go-grpc-prometheus v1.2.0/go.mod h1:8NvIoxWQoOIhqOTXgfV/d3M/q6VIi02HzZEHgUlZvzk= github.com/grpc-ecosystem/grpc-gateway v1.16.0/go.mod h1:BDjrQk3hbvj6Nolgz8mAMFbcEtjT1g+wF4CSlocrBnw= -github.com/hashicorp/consul/api v1.1.0/go.mod h1:VmuI/Lkw1nC05EYQWNKwWGbkg+FbDBtguAZLlVdkD9Q= -github.com/hashicorp/consul/sdk v0.1.1/go.mod h1:VKf9jXwCTEY1QZP2MOLRhb5i/I/ssyNV1vwHyQBF0x8= -github.com/hashicorp/errwrap v1.0.0/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4= -github.com/hashicorp/go-cleanhttp v0.5.1/go.mod h1:JpRdi6/HCYpAwUzNwuwqhbovhLtngrth3wmdIIUrZ80= -github.com/hashicorp/go-immutable-radix v1.0.0/go.mod h1:0y9vanUI8NX6FsYoO3zeMjhV/C5i9g4Q3DwcSNZ4P60= -github.com/hashicorp/go-msgpack v0.5.3/go.mod h1:ahLV/dePpqEmjfWmKiqvPkv/twdG7iPBM1vqhUKIvfM= -github.com/hashicorp/go-multierror v1.0.0/go.mod h1:dHtQlpGsu+cZNNAkkCN/P3hoUDHhCYQXV3UM06sGGrk= -github.com/hashicorp/go-rootcerts v1.0.0/go.mod h1:K6zTfqpRlCUIjkwsN4Z+hiSfzSTQa6eBIzfwKfwNnHU= -github.com/hashicorp/go-sockaddr v1.0.0/go.mod h1:7Xibr9yA9JjQq1JpNB2Vw7kxv8xerXegt+ozgdvDeDU= -github.com/hashicorp/go-syslog v1.0.0/go.mod h1:qPfqrKkXGihmCqbJM2mZgkZGvKG1dFdvsLplgctolz4= -github.com/hashicorp/go-uuid v1.0.0/go.mod h1:6SBZvOh/SIDV7/2o3Jml5SYk/TvGqwFJ/bN7x4byOro= -github.com/hashicorp/go-uuid v1.0.1/go.mod h1:6SBZvOh/SIDV7/2o3Jml5SYk/TvGqwFJ/bN7x4byOro= -github.com/hashicorp/go.net v0.0.1/go.mod h1:hjKkEWcCURg++eb33jQU7oqQcI9XDCnUzHA0oac0k90= -github.com/hashicorp/golang-lru v0.5.0/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8= -github.com/hashicorp/golang-lru v0.5.1/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8= -github.com/hashicorp/hcl v1.0.0/go.mod h1:E5yfLk+7swimpb2L/Alb/PJmXilQ/rhwaUYs4T20WEQ= -github.com/hashicorp/logutils v1.0.0/go.mod h1:QIAnNjmIWmVIIkWDTG1z5v++HQmx9WQRO+LraFDTW64= -github.com/hashicorp/mdns v1.0.0/go.mod h1:tL+uN++7HEJ6SQLQ2/p+z2pH24WQKWjBPkE0mNTz8vQ= -github.com/hashicorp/memberlist v0.1.3/go.mod h1:ajVTdAv/9Im8oMAAj5G31PhhMCZJV2pPBoIllUwCN7I= -github.com/hashicorp/serf v0.8.2/go.mod h1:6hOLApaqBFA1NXqRQAsxw9QxuDEvNxSQRwA/JwenrHc= -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/inconshreveable/mousetrap v1.0.0 h1:Z8tu5sraLXCXIcARxBp/8cbvlwVa7Z1NHg9XEKhtSvM= github.com/inconshreveable/mousetrap v1.0.0/go.mod h1:PxqpIevigyE2G7u3NXJIT2ANytuPF1OarO4DADm73n8= github.com/jonboulle/clockwork v0.2.2 h1:UOGuzwb1PwsrDAObMuhUnj0p5ULPj8V/xJ7Kx9qUBdQ= @@ -226,9 +114,6 @@ github.com/jpillora/backoff v1.0.0/go.mod h1:J/6gKK9jxlEcS3zixgDgUAsiuZ7yrSoa/FX github.com/json-iterator/go v1.1.6/go.mod h1:+SdeFBvtyEkXs7REEP0seUULqWtbJapLOCVDaaPEHmU= github.com/json-iterator/go v1.1.10/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4= github.com/json-iterator/go v1.1.11/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4= -github.com/jstemmer/go-junit-report v0.0.0-20190106144839-af01ea7f8024/go.mod h1:6v2b51hI/fHJwM22ozAgKL4VKDeJcHhJFhtBdhmNjmU= -github.com/jstemmer/go-junit-report v0.9.1/go.mod h1:Brl9GWCQeLvo8nXZwPNNblvFj/XSXhF0NWZEnDohbsk= -github.com/jtolds/gls v4.20.0+incompatible/go.mod h1:QJZ7F/aHp+rZTRtaJ1ow/lLfFfVYBRgL+9YlvaHOwJU= github.com/julienschmidt/httprouter v1.2.0/go.mod h1:SYymIcj16QtmaHHD7aYtjjsJG7VTCxuUUipMqKk8s4w= github.com/julienschmidt/httprouter v1.3.0/go.mod h1:JR6WtHb+2LUe8TCKY3cZOxFyyO8IZAc4RVcycCCAKdM= github.com/kisielk/errcheck v1.2.0/go.mod h1:/BMXB+zMLi60iA8Vv6Ksmxu/1UDYcXs4uQLJ+jE2L00= @@ -236,28 +121,15 @@ github.com/kisielk/errcheck v1.5.0/go.mod h1:pFxgyoBC7bSaBwPgfKdkLd5X25qrDl4LWUI github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck= github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= github.com/konsorten/go-windows-terminal-sequences v1.0.3/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= -github.com/kr/fs v0.1.0/go.mod h1:FFnZGqtBN9Gxj7eW1uZ42v5BccTP0vu6NEaFoC2HwRg= github.com/kr/logfmt v0.0.0-20140226030751-b84e30acd515/go.mod h1:+0opPa2QZZtGFBFZlji/RkVcI2GknAs/DXo4wKdlNEc= github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo= github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE= -github.com/magiconair/properties v1.8.5/go.mod h1:y3VJvCyxH9uVvJTWEGAELF3aiYNyPKd5NZ3oSwXrF60= -github.com/mattn/go-colorable v0.0.9/go.mod h1:9vuHe8Xs5qXnSaW/c/ABM9alt+Vo+STaOChaDxuIBZU= -github.com/mattn/go-isatty v0.0.3/go.mod h1:M+lRXTBqGeGNdLjl/ufCoiOlB5xdOkqRJdNxMWT7Zi4= github.com/mattn/go-runewidth v0.0.9 h1:Lm995f3rfxdpd6TSmuVCHVb/QhupuXlYr8sCI/QdE+0= github.com/mattn/go-runewidth v0.0.9/go.mod h1:H031xJmbD/WCDINGzjvQ9THkh0rPKHF+m2gUSrubnMI= github.com/matttproud/golang_protobuf_extensions v1.0.1 h1:4hp9jkHxhMHkqkrB3Ix0jegS5sx/RkqARlsWZ6pIwiU= github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0= -github.com/miekg/dns v1.0.14/go.mod h1:W1PPwlIAgtquWBMBEV9nkV9Cazfe8ScdGz/Lj7v3Nrg= -github.com/mitchellh/cli v1.0.0/go.mod h1:hNIlj7HEI86fIcpObd7a0FcrxTWetlwJDGcceTlRvqc= -github.com/mitchellh/go-homedir v1.0.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0= -github.com/mitchellh/go-testing-interface v1.0.0/go.mod h1:kRemZodwjscx+RGhAo8eIhFbs2+BFgRtFPeD/KE+zxI= -github.com/mitchellh/gox v0.4.0/go.mod h1:Sd9lOJ0+aimLBi73mGofS1ycjY8lL3uZM3JPS42BGNg= -github.com/mitchellh/iochan v1.0.0/go.mod h1:JwYml1nuB7xOzsp52dPpHFffvOCDupsG0QubkSMEySY= -github.com/mitchellh/mapstructure v0.0.0-20160808181253-ca63d7c062ee/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y= -github.com/mitchellh/mapstructure v1.1.2/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y= -github.com/mitchellh/mapstructure v1.4.1/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo= github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= github.com/modern-go/reflect2 v0.0.0-20180701023420-4b7aa43c6742/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0= @@ -267,16 +139,12 @@ github.com/mwitkow/go-conntrack v0.0.0-20190716064945-2f068394615f/go.mod h1:qRW github.com/olekukonko/tablewriter v0.0.5 h1:P2Ga83D34wi1o9J6Wh1mRuqd4mF/x/lgBS7N7AbDhec= github.com/olekukonko/tablewriter v0.0.5/go.mod h1:hPp6KlRPjbx+hW8ykQs1w3UBbZlj6HuIJcUGPhkA7kY= github.com/opentracing/opentracing-go v1.1.0/go.mod h1:UkNAQd3GIcIGf0SeVgPpRdFStlNbqXla1AfSYxPUl2o= -github.com/pascaldekloe/goe v0.0.0-20180627143212-57f6aae5913c/go.mod h1:lzWF7FIEvWOWxwDKqyGYQf6ZUaNfKdP144TG7ZOy1lc= -github.com/pelletier/go-toml v1.9.3/go.mod h1:u1nR/EPcESfeI/szUZKdtJ0xRNbUoANCkoOuaOx1Y+c= github.com/pkg/errors v0.8.0/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4= github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= -github.com/pkg/sftp v1.10.1/go.mod h1:lYOWFsE0bwd1+KfKJaKeuokY15vzFx25BLbzYYoAxZI= github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= -github.com/posener/complete v1.1.1/go.mod h1:em0nMJCgc9GFtwrmVmEMR/ZL6WyhyjMBndrE9hABlRI= github.com/prometheus/client_golang v0.9.1/go.mod h1:7SWBe2y4D6OKWSNQJUaRYU/AaXPKyh/dDVn+NZz0KFw= github.com/prometheus/client_golang v1.0.0/go.mod h1:db9x61etRT2tGnBNRi70OPL5FsnadC4Ky3P0J6CfImo= github.com/prometheus/client_golang v1.7.1/go.mod h1:PY5Wy2awLA44sXw4AOSfFBetzPP4j5+D6mVACh+pe2M= @@ -297,53 +165,32 @@ github.com/prometheus/procfs v0.1.3/go.mod h1:lV6e/gmhEcM9IjHGsFOCxxuZ+z1YqCvr4O github.com/prometheus/procfs v0.6.0 h1:mxy4L2jP6qMonqmq+aTtOx1ifVWUgG/TAmntgbh3xv4= github.com/prometheus/procfs v0.6.0/go.mod h1:cz+aTbrPOrUb4q7XlbU9ygM+/jj0fzG6c1xBZuNvfVA= github.com/rogpeppe/fastuuid v1.2.0/go.mod h1:jVj6XXZzXRy/MSR5jhDC/2q6DgLz+nrA6LYCDYWNEvQ= -github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4= -github.com/russross/blackfriday/v2 v2.0.1/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= -github.com/ryanuber/columnize v0.0.0-20160712163229-9b3edd62028f/go.mod h1:sm1tb6uqfes/u+d4ooFouqFdy9/2g9QGwK3SQygK0Ts= -github.com/sean-/seed v0.0.0-20170313163322-e2103e2c3529/go.mod h1:DxrIzT+xaE7yg65j358z/aeFdxmN0P9QXhEzd20vsDc= -github.com/shurcooL/sanitized_anchor_name v1.0.0/go.mod h1:1NzhyTcUVG4SuEtjjoZeVRXNmyL/1OwPU0+IJeTBvfc= +github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= github.com/sirupsen/logrus v1.2.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPxbbu5VWo= github.com/sirupsen/logrus v1.4.2/go.mod h1:tLMulIdttU9McNUspp0xgXVQah82FyeX6MwdIuYE2rE= github.com/sirupsen/logrus v1.6.0/go.mod h1:7uNnSEd1DgxDLC74fIahvMZmmYsHGZGEOFrfsX/uA88= github.com/sirupsen/logrus v1.8.1/go.mod h1:yWOB1SBYBC5VeMP7gHvWumXLIWorT60ONWic61uBYv0= -github.com/smartystreets/assertions v0.0.0-20180927180507-b2de0cb4f26d/go.mod h1:OnSkiWE9lh6wB0YB77sQom3nweQdgAjqCqsofrRNTgc= -github.com/smartystreets/goconvey v1.6.4/go.mod h1:syvi0/a8iFYH4r/RixwvyeAJjdLS9QV7WQ/tjFTllLA= github.com/soheilhy/cmux v0.1.5/go.mod h1:T7TcVDs9LWfQgPlPsdngu6I6QIoyIFZDDC6sNE1GqG0= github.com/spaolacci/murmur3 v0.0.0-20180118202830-f09979ecbc72/go.mod h1:JwIasOWyU6f++ZhiEuf87xNszmSA2myDM2Kzu9HwQUA= -github.com/spf13/afero v1.6.0/go.mod h1:Ai8FlHk4v/PARR026UzYexafAt9roJ7LcLMAmO6Z93I= -github.com/spf13/cast v1.3.1/go.mod h1:Qx5cxh0v+4UWYiBimWS+eyWzqEqokIECu5etghLkUJE= -github.com/spf13/cobra v1.2.1 h1:+KmjbUw1hriSNMF55oPrkZcb27aECyrj8V2ytv7kWDw= -github.com/spf13/cobra v1.2.1/go.mod h1:ExllRjgxM/piMAM+3tAZvg8fsklGAf3tPfi+i8t68Nk= -github.com/spf13/jwalterweatherman v1.1.0/go.mod h1:aNWZUN0dPAAO/Ljvb5BEdw96iTZ0EXowPYD95IqWIGo= +github.com/spf13/cobra v1.4.0 h1:y+wJpx64xcgO1V+RcnwW0LEHxTKRi2ZDPSBjWnrg88Q= +github.com/spf13/cobra v1.4.0/go.mod h1:Wo4iy3BUC+X2Fybo0PDqwJIv3dNRiZLHQymsfxlB84g= github.com/spf13/pflag v1.0.5 h1:iy+VFUOCP1a+8yFto/drg2CJ5u0yRoB7fZw3DKv/JXA= github.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg= -github.com/spf13/viper v1.8.1/go.mod h1:o0Pch8wJ9BVSWGQMbra6iw0oQ5oktSIBaujf1rJH9Ns= github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= 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.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA= -github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/stretchr/testify v1.7.0 h1:nwc3DEeHmmLAfoZucVR881uASk0Mfjw8xYJ99tb5CcY= github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= -github.com/subosito/gotenv v1.2.0/go.mod h1:N0PQaV/YGNqwC0u51sEeR/aUtSLEXKX9iv69rRypqCw= github.com/tmc/grpc-websocket-proxy v0.0.0-20201229170055-e5319fda7802/go.mod h1:ncp9v5uamzpCO7NfCPTXjqaC+bZgJeR0sMTm6dMHP7U= github.com/xiang90/probing v0.0.0-20190116061207-43a291ad63a2 h1:eY9dn8+vbi4tKz5Qo6v2eYzo7kUS51QINcR5jNpbZS8= github.com/xiang90/probing v0.0.0-20190116061207-43a291ad63a2/go.mod h1:UETIi67q53MR2AWcXfiuqkDkRtnGDLqkBTpCHuJHxtU= -github.com/yuin/goldmark v1.1.25/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= -github.com/yuin/goldmark v1.1.32/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= go.etcd.io/bbolt v1.3.6 h1:/ecaJf0sk1l4l6V4awd65v2C3ILy7MSj+s/x1ADCIMU= go.etcd.io/bbolt v1.3.6/go.mod h1:qXsaaIqmgQH0T+OPdb99Bf+PKfBBQVAdyD6TY9G8XM4= -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.2/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.5/go.mod h1:5pWMHQbX5EPX2/62yrJeAkowc+lfs/XD7Uxpq3pI6kk= -go.opencensus.io v0.23.0/go.mod h1:XItmlyltB5F7CS4xOC1DcqMoFqwtC6OG2xF7mCv7P7E= go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.26.1 h1:puWrOArBwWlr5dq6vyZ6fKykHyS8JgMIVhTBA8XsGuU= go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.26.1/go.mod h1:4wsfAAW5N9wUHM0QTmZS8z7fvYZ1rv3m+sVeSpf8NhU= go.opentelemetry.io/otel v1.1.0/go.mod h1:7cww0OW51jQ8IaZChIEdqLwgh+44+7uiTdWsAL0wQpA= @@ -370,162 +217,62 @@ go.uber.org/zap v1.10.0/go.mod h1:vwi/ZaCAaUcBkycHslxD9B2zi4UTXhF60s6SWpuDF0Q= go.uber.org/zap v1.17.0 h1:MTjgFu6ZLKvY6Pvaqk97GlxNBuMpV4Hy/3P6tRGlI2U= go.uber.org/zap v1.17.0/go.mod h1:MXVU+bhUf/A7Xi2HNOnopQOrmycQ5Ih87HtOu4q5SSo= golang.org/x/crypto v0.0.0-20180904163835-0709b304e793/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= -golang.org/x/crypto v0.0.0-20181029021203-45a5f77698d3/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= -golang.org/x/crypto v0.0.0-20190510104115-cbcb75029529/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= -golang.org/x/crypto v0.0.0-20190605123033-f99c8df09eb5/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= -golang.org/x/crypto v0.0.0-20190820162420-60c769a6c586/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= golang.org/x/crypto v0.0.0-20210513164829-c07d793c2f9a h1:kr2P4QFmQr29mSLA43kwrOcgcReGTfbE9N577tCTuBc= golang.org/x/crypto v0.0.0-20210513164829-c07d793c2f9a/go.mod h1:P+XmwS30IXTQdn5tA2iutPOUgjI07+tq3H3K9MVA1s8= golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= -golang.org/x/exp v0.0.0-20190306152737-a1d7652674e8/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= -golang.org/x/exp v0.0.0-20190510132918-efd6b22b2522/go.mod h1:ZjyILWgesfNpC6sMxTJOJm9Kp84zZh5NQWvqDGG3Qr8= -golang.org/x/exp v0.0.0-20190829153037-c13cbed26979/go.mod h1:86+5VVa7VpoJ4kLfm080zCjGlMRFzhUhsZKEZO7MGek= -golang.org/x/exp v0.0.0-20191030013958-a1ab85dbe136/go.mod h1:JXzH8nQsPlswgeRAPE3MuO9GYsAcnJvJ4vnMwN/5qkY= -golang.org/x/exp v0.0.0-20191129062945-2f5052295587/go.mod h1:2RIsYlXP63K8oxa1u096TMicItID8zy7Y6sNkU49FU4= -golang.org/x/exp v0.0.0-20191227195350-da58074b4299/go.mod h1:2RIsYlXP63K8oxa1u096TMicItID8zy7Y6sNkU49FU4= -golang.org/x/exp v0.0.0-20200119233911-0405dc783f0a/go.mod h1:2RIsYlXP63K8oxa1u096TMicItID8zy7Y6sNkU49FU4= -golang.org/x/exp v0.0.0-20200207192155-f17229e696bd/go.mod h1:J/WKrq2StrnmMY6+EHIKF9dgMWnmCNThgcyBT1FY9mM= -golang.org/x/exp v0.0.0-20200224162631-6cc2880d07d6/go.mod h1:3jZMyOhIsHpP37uCMkUooju7aAi5cS1Q23tOzKc+0MU= -golang.org/x/image v0.0.0-20190227222117-0694c2d4d067/go.mod h1:kZ7UVZpmo3dzQBMxlp+ypCbDeSB+sBbTgSJuh5dn5js= -golang.org/x/image v0.0.0-20190802002840-cff245a6509b/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0= golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE= golang.org/x/lint v0.0.0-20190227174305-5b3e6a55c961/go.mod h1:wehouNa3lNwaWXcvxsM5YxQ5yQlVC4a0KAMCusXpPoU= -golang.org/x/lint v0.0.0-20190301231843-5614ed5bae6f/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE= golang.org/x/lint v0.0.0-20190313153728-d0100b6bd8b3/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= -golang.org/x/lint v0.0.0-20190409202823-959b441ac422/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= -golang.org/x/lint v0.0.0-20190909230951-414d861bb4ac/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= -golang.org/x/lint v0.0.0-20190930215403-16217165b5de/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= -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-20200302205851-738671d3881b/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY= -golang.org/x/lint v0.0.0-20201208152925-83fdc39ff7b5/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-20190719004257-d2bd2a29d028/go.mod h1:E/iHnbuqvinMTCcRqshq8CkpyQDoeVncDDYHnLhea+o= -golang.org/x/mod v0.0.0-20190513183733-4bf6d317e70e/go.mod h1:mXi4GBBbnImb6dmsKGUJ2LatrhH/nqhxcFungHvyanc= -golang.org/x/mod v0.1.0/go.mod h1:0QHyrYULN0/3qlju5TqG8bIK38QM8yzMo5ekMj3DlcY= -golang.org/x/mod v0.1.1-0.20191105210325-c90efee705ee/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.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/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-20181023162649-9b4f9f5ad519/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20181114220301-adae6a3d119a/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= -golang.org/x/net v0.0.0-20181201002055-351d144fa1fc/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20190108225652-1e06a53dbb7e/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20190213061140-3a22650c66bd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= -golang.org/x/net v0.0.0-20190501004415-9ce7a6920f09/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= -golang.org/x/net v0.0.0-20190503192946-f4e77d36d62c/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= -golang.org/x/net v0.0.0-20190603091049-60506f45cf65/go.mod h1:HSz+uSET+XFnRR8LxR5pz3Of3rY3CfYBVs4xY44aLks= golang.org/x/net v0.0.0-20190613194153-d28f0bde5980/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= -golang.org/x/net v0.0.0-20190628185345-da137c7871d7/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= -golang.org/x/net v0.0.0-20190724013045-ca1201d0de80/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= -golang.org/x/net v0.0.0-20191209160850-c0dbc17a3553/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= -golang.org/x/net v0.0.0-20200114155413-6afb5195e5aa/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= -golang.org/x/net v0.0.0-20200202094626-16171245cfb2/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= -golang.org/x/net v0.0.0-20200222125558-5a598a2470a0/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20200226121028-0de0cce0169b/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= -golang.org/x/net v0.0.0-20200301022130-244492dfa37a/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= -golang.org/x/net v0.0.0-20200324143707-d3edc9973b7e/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= -golang.org/x/net v0.0.0-20200501053045-e0ff5e5a1de5/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= -golang.org/x/net v0.0.0-20200506145744-7e3656a0809f/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= -golang.org/x/net v0.0.0-20200513185701-a91f0712d120/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= -golang.org/x/net v0.0.0-20200520182314-0ba52f642ac2/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= golang.org/x/net v0.0.0-20200625001655-4c5254603344/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-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-20201202161906-c7110b5ffcbb/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-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-20220105145211-5b0dc2dfae98 h1:+6WJMRLHlD7X7frgp7TUZ36RnQzSf9wVVTNakEp+nqY= golang.org/x/net v0.0.0-20220105145211-5b0dc2dfae98/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= 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-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-20200107190931-bf48bf16ab8d h1:TzXSXBo42m9gQenoE3b9BGiEpg5IG2JkU5FkPIawgtw= 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-20210402161424-2e8d93401602 h1:0Ja1LBD+yisY6RWM/BH7TJVXWsSjs2VwBSmvSX4HdBc= -golang.org/x/oauth2 v0.0.0-20210402161424-2e8d93401602/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= 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-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.0.0-20190227155943-e225da77a7e6/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.0.0-20200317015054-43a5402ce75a/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.0.0-20200625203802-6e8e738ad208/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-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sys v0.0.0-20180823144017-11551d06cbcc/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= -golang.org/x/sys v0.0.0-20181026203630-95b1ffbd15a5/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20181116152217-5ac8a444bdc5/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= -golang.org/x/sys v0.0.0-20190312061237-fead79001313/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190422165155-953cdadca894/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20190502145724-3ef323f4f1fd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20190507160741-ecd444e8653b/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20190606165138-5da285871e9c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20190624142023-c5567b49c5d0/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20190726091711-fc99dfbffb4e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20191001151750-bb3f8db39f24/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20191005200804-aed5e4c7ecf9/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20191026070338-33540a1f6037/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20191204072324-ce4227a45e2e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20191228213918-04cbcbbfeed8/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200106162015-b016eb3dc98e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200113162924-86b910548bc1/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200122134326-e047566fdf82/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200202164722-d101bd2416d5/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200212091648-12a6c2dcc1e4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200223170610-d5e6a3e2c0ae/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200302150141-5c8b2ff67527/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200331124033-c3d80250170d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200501052902-10377860bb8e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200511232937-7e40ca221e25/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200515095857-1151b9dac4a9/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200523222454-059865788121/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-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-20200923182605-d9f96fdee20d/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-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-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-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-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-20210423185535-09eb48e85fd7/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210510120138-977fb7262007/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= @@ -534,19 +281,13 @@ golang.org/x/sys v0.0.0-20210603125802-9665404d3644/go.mod h1:oPkhp1MJrh7nUepCBc golang.org/x/sys v0.0.0-20211123173158-ef496fb156ab h1:rfJ1bsoJQQIAoAxTxB7bme+vHrNkRw8CqfsYh9w54cw= golang.org/x/sys v0.0.0-20211123173158-ef496fb156ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= -golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= -golang.org/x/text v0.3.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.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.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/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-20191024005414-555d28b269f0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.0.0-20210220033141-f8bda1e9f3ba h1:O8mE0/t419eoIwhTFpKVkHiTs/Igowgfkj25AcZrtiE= golang.org/x/time v0.0.0-20210220033141-f8bda1e9f3ba/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= @@ -554,151 +295,33 @@ golang.org/x/tools v0.0.0-20181030221726-6c7e314b6563/go.mod h1:n7NCudcB/nEzxVGm 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-20190311212946-11955173bddd/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= -golang.org/x/tools v0.0.0-20190312151545-0bb0c0a6e846/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= -golang.org/x/tools v0.0.0-20190312170243-e65039ee4138/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= -golang.org/x/tools v0.0.0-20190328211700-ab21143f2384/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= -golang.org/x/tools v0.0.0-20190425150028-36563e24a262/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q= -golang.org/x/tools v0.0.0-20190506145303-2d16b83fe98c/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q= golang.org/x/tools v0.0.0-20190524140312-2c0ae7006135/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q= -golang.org/x/tools v0.0.0-20190606124116-d0a3d012864b/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc= -golang.org/x/tools v0.0.0-20190621195816-6e04913cbbac/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc= -golang.org/x/tools v0.0.0-20190628153133-6cdbf07be9d0/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc= -golang.org/x/tools v0.0.0-20190816200558-6889da9d5479/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= -golang.org/x/tools v0.0.0-20190911174233-4f2ddba30aff/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= -golang.org/x/tools v0.0.0-20191012152004-8de300cfc20a/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= -golang.org/x/tools v0.0.0-20191112195655-aa38f8e97acc/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= -golang.org/x/tools v0.0.0-20191113191852-77e3bb0ad9e7/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= -golang.org/x/tools v0.0.0-20191115202509-3a792d9c32b2/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= -golang.org/x/tools v0.0.0-20191125144606-a911d9008d1f/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= -golang.org/x/tools v0.0.0-20191130070609-6e064ea0cf2d/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= -golang.org/x/tools v0.0.0-20191216173652-a0e659d51361/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= -golang.org/x/tools v0.0.0-20191227053925-7b8e75db28f4/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= -golang.org/x/tools v0.0.0-20200117161641-43d50277825c/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= -golang.org/x/tools v0.0.0-20200122220014-bf1340f18c4a/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= -golang.org/x/tools v0.0.0-20200130002326-2f3ba24bd6e7/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= -golang.org/x/tools v0.0.0-20200204074204-1cc6d1ef6c74/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= -golang.org/x/tools v0.0.0-20200207183749-b753a1ba74fa/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= -golang.org/x/tools v0.0.0-20200212150539-ea181f53ac56/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= -golang.org/x/tools v0.0.0-20200224181240-023911ca70b2/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= -golang.org/x/tools v0.0.0-20200227222343-706bc42d1f0d/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= -golang.org/x/tools v0.0.0-20200304193943-95d2e580d8eb/go.mod h1:o4KQGtdN14AW+yjsvvwRTJJuXz8XRtIHtEnmAXLyFUw= -golang.org/x/tools v0.0.0-20200312045724-11d5b4c81c7d/go.mod h1:o4KQGtdN14AW+yjsvvwRTJJuXz8XRtIHtEnmAXLyFUw= -golang.org/x/tools v0.0.0-20200331025713-a30bf2db82d4/go.mod h1:Sl4aGygMT6LrqrWclx+PTx3U+LnKx/seiNR+3G19Ar8= -golang.org/x/tools v0.0.0-20200501065659-ab2804fb9c9d/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= -golang.org/x/tools v0.0.0-20200512131952-2bc93b1c0c88/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= -golang.org/x/tools v0.0.0-20200515010526-7d3b6ebf133d/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= -golang.org/x/tools v0.0.0-20200618134242-20370b0cb4b2/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= golang.org/x/tools v0.0.0-20200619180055-7c47624df98f/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= -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-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-20210105154028-b0ab187a4818/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/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-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1 h1:go1bK/D/BFZV2I8cIQd1NKEZ+0owSTG1fDTci4IqFcE= golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= -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.8.0/go.mod h1:o4eAsZoiT+ibD93RtjEohWalFOjRDx6CVaqeizhEnKg= -google.golang.org/api v0.9.0/go.mod h1:o4eAsZoiT+ibD93RtjEohWalFOjRDx6CVaqeizhEnKg= -google.golang.org/api v0.13.0/go.mod h1:iLdEw5Ide6rF15KTC1Kkl0iskquN2gFfn9o9XIsbkAI= -google.golang.org/api v0.14.0/go.mod h1:iLdEw5Ide6rF15KTC1Kkl0iskquN2gFfn9o9XIsbkAI= -google.golang.org/api v0.15.0/go.mod h1:iLdEw5Ide6rF15KTC1Kkl0iskquN2gFfn9o9XIsbkAI= -google.golang.org/api v0.17.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE= -google.golang.org/api v0.18.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE= -google.golang.org/api v0.19.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE= -google.golang.org/api v0.20.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE= -google.golang.org/api v0.22.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE= -google.golang.org/api v0.24.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.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.44.0/go.mod h1:EBOGZqzyhtvMDoxwS97ctnh0zUmYY6CxqXsc1AvkYD8= google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM= +google.golang.org/appengine v1.4.0 h1:/wp5JvzpHIxhs/dumFmF7BXTf3Z+dd4uXta4kVyO508= 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.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.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-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-20190425155659-357c62f0e4bb/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= -google.golang.org/genproto v0.0.0-20190502173448-54afdca5d873/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= -google.golang.org/genproto v0.0.0-20190801165951-fa694d86fc64/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc= google.golang.org/genproto v0.0.0-20190819201941-24fa4b261c55/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc= -google.golang.org/genproto v0.0.0-20190911173649-1774047e7e51/go.mod h1:IbNlFCBrqXvoKpeg0TB2l7cyZUmoaFKYIwrEpbDKLA8= -google.golang.org/genproto v0.0.0-20191108220845-16a3f7862a1a/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= -google.golang.org/genproto v0.0.0-20191115194625-c23dd37a84c9/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= -google.golang.org/genproto v0.0.0-20191216164720-4f79533eabd1/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= -google.golang.org/genproto v0.0.0-20191230161307-f3c370f40bfb/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= -google.golang.org/genproto v0.0.0-20200115191322-ca5a22157cba/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= -google.golang.org/genproto v0.0.0-20200122232147-0452cf42e150/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= -google.golang.org/genproto v0.0.0-20200204135345-fa8e72b47b90/go.mod h1:GmwEX6Z4W5gMy59cAlVYjN9JhxgbQH6Gn+gFDQe2lzA= -google.golang.org/genproto v0.0.0-20200212174721-66ed5ce911ce/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= -google.golang.org/genproto v0.0.0-20200224152610-e50cd9704f63/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= -google.golang.org/genproto v0.0.0-20200228133532-8c2c7df3a383/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= -google.golang.org/genproto v0.0.0-20200305110556-506484158171/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= -google.golang.org/genproto v0.0.0-20200312145019-da6875a35672/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= -google.golang.org/genproto v0.0.0-20200331122359-1ee6d9798940/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= google.golang.org/genproto v0.0.0-20200423170343-7949de9c1215/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= -google.golang.org/genproto v0.0.0-20200430143042-b979b6f78d84/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= -google.golang.org/genproto v0.0.0-20200511104702-f5ebc3bea380/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= google.golang.org/genproto v0.0.0-20200513103714-09dca8ec2884/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= -google.golang.org/genproto v0.0.0-20200515170657-fc4c6c6a6587/go.mod h1:YsZOwe1myG/8QRHRsmBRE1LrgQY60beZKjly0O1fX9U= google.golang.org/genproto v0.0.0-20200526211855-cb27e3aa2013/go.mod h1:NbSheEEYHJ7i3ixzK3sjbqSGDJWnxyFXZblF3eUsNvo= -google.golang.org/genproto v0.0.0-20200618031413-b414f8b61790/go.mod h1:jDfRM7FcilCzHH/e9qn6dsT145K34l5v+OpcnNgKAAA= -google.golang.org/genproto v0.0.0-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-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-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-20210402141018-6c239bbf2bb1/go.mod h1:9lPAdzaEmUacj36I+k7YKbEc5CXzPIeORRgDAUOu28A= google.golang.org/genproto v0.0.0-20211118181313-81c1377c94b1 h1:b9mVrqYfq3P4bCdaLg1qtBnPzUYgglsIdjZkL/fQVOE= google.golang.org/genproto v0.0.0-20211118181313-81c1377c94b1/go.mod h1:5CzLGKJ67TSI2B9POpiiyGha0AjJvZIUgRMt1dSmuhc= 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.21.1/go.mod h1:oYelfM1adQP15Ek0mdvEgi9Df8B9CZIaU1084ijfRaM= google.golang.org/grpc v1.23.0/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg= google.golang.org/grpc v1.25.1/go.mod h1:c3i+UQWmh7LiEpx4sFZnkU36qjEYZ0imhYfXVyQciAY= -google.golang.org/grpc v1.26.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk= google.golang.org/grpc v1.27.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk= -google.golang.org/grpc v1.27.1/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk= -google.golang.org/grpc v1.28.0/go.mod h1:rpkK4SK4GF4Ach/+MFLZUBavHOvF2JJB5uozKKal+60= 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.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.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.1/go.mod h1:qjiiYl8FncCW8feJPdyg3v6XW24KsRHe+dy9BAGRRjU= 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.40.0/go.mod h1:ogyxbiOoUXAkP+4+xa6PZSE9DZgIHtSpzjDTB9KAK34= google.golang.org/grpc v1.41.0 h1:f+PlOh7QV4iIJkPrx5NQ7qaNGFQ3OTse67yaDHfju4E= google.golang.org/grpc v1.41.0/go.mod h1:U3l9uK9J0sini8mHphKoXyaqDA/8VyGnDee1zzIUK6k= @@ -710,7 +333,6 @@ google.golang.org/protobuf v1.21.0/go.mod h1:47Nbq4nVaFHyn7ilMalzfO3qCViNmqZ2kzi google.golang.org/protobuf v1.22.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= google.golang.org/protobuf v1.23.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= google.golang.org/protobuf v1.23.1-0.20200526195155-81db48ad09cc/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= -google.golang.org/protobuf v1.24.0/go.mod h1:r/3tXBNzIEhYS9I1OUVjXDlt8tc493IdKGjtUeSXeh4= google.golang.org/protobuf v1.25.0/go.mod h1:9JNX74DMeImyA3h4bdi1ymwjUzf21/xIlbajtzgsN7c= google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw= google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc= @@ -718,10 +340,7 @@ google.golang.org/protobuf v1.27.1 h1:SnqbnDw1V7RiZcXPx5MEeqPv2s79L9i7BJUlG/+Rur google.golang.org/protobuf v1.27.1/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc= gopkg.in/alecthomas/kingpin.v2 v2.2.6/go.mod h1:FMv+mEhP44yOT+4EoQTLFTRgOQ1FBLkstjWtayDeSgw= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= -gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= -gopkg.in/errgo.v2 v2.1.0/go.mod h1:hNsd1EY+bozCKY1Ytp96fpM3vjJbqLJn88ws8XvfDNI= -gopkg.in/ini.v1 v1.62.0/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k= gopkg.in/natefinch/lumberjack.v2 v2.0.0/go.mod h1:l0ndWWf7gzL7RNwBG7wST/UCcT4T24xpD6X8LsfU/+k= gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= @@ -736,15 +355,7 @@ gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b h1:h8qDotaEPuJATrMmW04NCwg7v22aHH28wwpauUhK9Oo= gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= -honnef.co/go/tools v0.0.0-20190106161140-3f1c8253044a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= -honnef.co/go/tools v0.0.0-20190418001031-e561f6794a2a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= honnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= -honnef.co/go/tools v0.0.1-2019.2.3/go.mod h1:a3bituU0lyd329TUQxRnasdCoJDkEUEAqEt0JzvZhAg= -honnef.co/go/tools v0.0.1-2020.1.3/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9vFzvIQ3k= -honnef.co/go/tools v0.0.1-2020.1.4/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9vFzvIQ3k= -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/sampler v1.3.0/go.mod h1:T1hPZKmBbMNahiBKFy5HrXp6adAjACjK9JXDnKaTXpA= sigs.k8s.io/json v0.0.0-20211020170558-c049b76a60c6 h1:fD1pz4yfdADVNfFmcP2aBEtudwUQ1AlLnRBALr33v3s= sigs.k8s.io/json v0.0.0-20211020170558-c049b76a60c6/go.mod h1:p4QtZmO4uMYipTQNzagwnNoseA6OxSUutVw05NhYDRs= sigs.k8s.io/yaml v1.2.0/go.mod h1:yfXDCHCao9+ENCvLSE62v9VSji2MKu5jeNfTrofGhJc= diff --git a/go.mod b/go.mod index 618e1446cf41..1d74e65a0d92 100644 --- a/go.mod +++ b/go.mod @@ -19,7 +19,7 @@ require ( github.com/bgentry/speakeasy v0.1.0 github.com/coreos/go-semver v0.3.0 github.com/dustin/go-humanize v1.0.0 - github.com/spf13/cobra v1.2.1 + github.com/spf13/cobra v1.4.0 go.etcd.io/bbolt v1.3.6 go.etcd.io/etcd/api/v3 v3.6.0-alpha.0 go.etcd.io/etcd/client/pkg/v3 v3.6.0-alpha.0 @@ -39,6 +39,7 @@ require ( ) require ( + cloud.google.com/go v0.81.0 // indirect github.com/beorn7/perks v1.0.1 // indirect github.com/cenkalti/backoff/v4 v4.1.1 // indirect github.com/cespare/xxhash/v2 v2.1.1 // indirect @@ -56,6 +57,7 @@ require ( github.com/grpc-ecosystem/grpc-gateway v1.16.0 // indirect github.com/inconshreveable/mousetrap v1.0.0 // indirect github.com/jonboulle/clockwork v0.2.2 // indirect + github.com/mattn/go-isatty v0.0.14 // indirect github.com/mattn/go-runewidth v0.0.9 // indirect github.com/matttproud/golang_protobuf_extensions v1.0.1 // indirect github.com/olekukonko/tablewriter v0.0.5 // indirect @@ -81,9 +83,11 @@ require ( go.uber.org/multierr v1.7.0 // indirect golang.org/x/crypto v0.0.0-20210513164829-c07d793c2f9a // indirect golang.org/x/net v0.0.0-20220105145211-5b0dc2dfae98 // indirect + golang.org/x/oauth2 v0.0.0-20210402161424-2e8d93401602 // indirect golang.org/x/sys v0.0.0-20211123173158-ef496fb156ab // indirect golang.org/x/text v0.3.7 // indirect golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1 // indirect + google.golang.org/appengine v1.6.7 // indirect google.golang.org/genproto v0.0.0-20211118181313-81c1377c94b1 // indirect gopkg.in/natefinch/lumberjack.v2 v2.0.0 // indirect gopkg.in/yaml.v2 v2.4.0 // indirect diff --git a/go.sum b/go.sum index 120df214c605..7237b981a87f 100644 --- a/go.sum +++ b/go.sum @@ -27,7 +27,6 @@ cloud.google.com/go/bigquery v1.7.0/go.mod h1://okPTzCYNXSlb24MZs83e2Do+h+VXtc4g cloud.google.com/go/bigquery v1.8.0/go.mod h1:J5hqkt3O0uAFnINi6JXValWIb1v0goeZM77hZzJN/fQ= 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/firestore v1.1.0/go.mod h1:ulACoGHTpvq5r8rxGJ4ddJZBZqakUQqClKRT5SZwBmk= 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.2.0/go.mod h1:jhfEVHT8odbXTkndysNHCcx0awwzvfOlguIAii9o8iA= @@ -48,16 +47,12 @@ github.com/alecthomas/units v0.0.0-20151022065526-2efee857e7cf/go.mod h1:ybxpYRF github.com/alecthomas/units v0.0.0-20190717042225-c3de453c63f4/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0= github.com/alecthomas/units v0.0.0-20190924025748-f65c72e2690d/go.mod h1:rBZYJk541a8SKzHPHnH3zbiI+7dagKZ0cgpgrD7Fyho= github.com/antihax/optional v1.0.0/go.mod h1:uupD/76wgC+ih3iEmQUL+0Ugr19nfwCT1kdvxnR2qWY= -github.com/armon/circbuf v0.0.0-20150827004946-bbbad097214e/go.mod h1:3U/XgcO3hCbHZ8TKRvWD2dDTCfh9M9ya+I9JpbB7O8o= -github.com/armon/go-metrics v0.0.0-20180917152333-f0300d1749da/go.mod h1:Q73ZrmVTwzkszR9V5SSuryQ31EELlFMUz1kKyl939pY= -github.com/armon/go-radix v0.0.0-20180808171621-7fddfc383310/go.mod h1:ufUuZ+zHj4x4TnLV4JWEpy2hxWSpsRywHrMgIH9cCH8= github.com/beorn7/perks v0.0.0-20180321164747-3a771d992973/go.mod h1:Dwedo/Wpr24TaqPxmxbtue+5NUziq4I4S80YR8gNf3Q= github.com/beorn7/perks v1.0.0/go.mod h1:KWe93zE9D1o94FZ5RNwFwVgaQK1VOXiVxmqh+CedLV8= github.com/beorn7/perks v1.0.1 h1:VlbKKnNfV8bJzeqoa4cOKqO6bYr3WgKZxO8Z16+hsOM= github.com/beorn7/perks v1.0.1/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6rlkpw= github.com/bgentry/speakeasy v0.1.0 h1:ByYyxL9InA1OWqxJqqp2A5pYHUrCiAL6K3J+LKSsQkY= github.com/bgentry/speakeasy v0.1.0/go.mod h1:+zsyZBPWlz7T6j88CTgSN5bM796AkVf0kBD4zp0CCIs= -github.com/bketelsen/crypt v0.0.4/go.mod h1:aI6NrJ0pMGgvZKL1iVgXLnfIFJtfV+bKCoqOes/6LfM= github.com/cenkalti/backoff/v4 v4.1.1 h1:G2HAfAmvm/GcKan2oOQpBXOd2tT2G57ZnZGWa1PxPBQ= github.com/cenkalti/backoff/v4 v4.1.1/go.mod h1:scbssz8iZGpm3xbr14ovlUdkxfGXNInqkPWOWmG2CLw= github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU= @@ -88,7 +83,7 @@ github.com/coreos/go-semver v0.3.0/go.mod h1:nnelYz7RCh+5ahJtPPxZlU+153eP4D4r3Ee github.com/coreos/go-systemd/v22 v22.3.2 h1:D9/bQk5vlXQFZ6Kwuu6zaiXJ9oTPe68++AzAJc1DzSI= github.com/coreos/go-systemd/v22 v22.3.2/go.mod h1:Y58oyj3AT4RCenI/lSvhwexgC+NSVTIJ3seZv2GcEnc= github.com/cpuguy83/go-md2man/v2 v2.0.0-20190314233015-f79a8a8ca69d/go.mod h1:maD7wRr/U5Z6m/iR4s+kqSMx2CaBsrgA7czyZG/E6dU= -github.com/cpuguy83/go-md2man/v2 v2.0.0/go.mod h1:maD7wRr/U5Z6m/iR4s+kqSMx2CaBsrgA7czyZG/E6dU= +github.com/cpuguy83/go-md2man/v2 v2.0.1/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o= github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E= github.com/creack/pty v1.1.11/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E= github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= @@ -105,9 +100,8 @@ github.com/envoyproxy/go-control-plane v0.9.9-0.20210217033140-668b12f5399d/go.m 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.10-0.20210907150352-cf90f659a021/go.mod h1:AFq3mo9L8Lqqiid3OhADV3RfLJnjiw63cSpi+fDTRC0= github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c= -github.com/fatih/color v1.7.0 h1:DkWD4oS2D8LGGgTQ6IvwJJXSL5Vp2ffcQg58nFV38Ys= -github.com/fatih/color v1.7.0/go.mod h1:Zm6kSWBoL9eyXnKyktHP6abPY2pDugNf5KwzbycvMj4= -github.com/fsnotify/fsnotify v1.4.9/go.mod h1:znqG4EE+3YCdAaPaxE2ZRY/06pZUdp0tY4IgpuI1SZQ= +github.com/fatih/color v1.13.0 h1:8LOYc1KYPPmyKMuN8QV2DNRWNbLo6LZ0iLs8+mlH53w= +github.com/fatih/color v1.13.0/go.mod h1:kLAiJbzzSOZDVNGyDpeOxJ47H46qBXwg5ILebYFFOfk= github.com/getsentry/raven-go v0.2.0 h1:no+xWJRb5ZI7eE8TWgIq1jLulQiIoLG0IfYxv5JYMGs= github.com/getsentry/raven-go v0.2.0/go.mod h1:KungGk8q33+aIAZUIVWZDr2OfAEBsO49PX4NzFV5kcQ= github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04= @@ -196,7 +190,6 @@ github.com/google/renameio v0.1.0/go.mod h1:KWCgfxg9yswjAJkECMjeO8J8rahYeXnNhOm4 github.com/google/uuid v1.1.2/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= 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/gopherjs/gopherjs v0.0.0-20181017120253-0766667cb4d1/go.mod h1:wJfORRmW1u3UXTncJ5qlYoELFm8eSnnEO6hX4iZ3EWY= github.com/gorilla/websocket v1.4.2 h1:+/TMaTYc4QFitKJxsQ7Yye35DkWvkdLcvGKqM+x0Ufc= github.com/gorilla/websocket v1.4.2/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE= github.com/grpc-ecosystem/go-grpc-middleware v1.3.0 h1:+9834+KizmvFV7pXQGSXQTsaWhq2GjuNUt0aUU0YBYw= @@ -205,26 +198,8 @@ github.com/grpc-ecosystem/go-grpc-prometheus v1.2.0 h1:Ovs26xHkKqVztRpIrF/92Bcuy github.com/grpc-ecosystem/go-grpc-prometheus v1.2.0/go.mod h1:8NvIoxWQoOIhqOTXgfV/d3M/q6VIi02HzZEHgUlZvzk= github.com/grpc-ecosystem/grpc-gateway v1.16.0 h1:gmcG1KaJ57LophUzW0Hy8NmPhnMZb4M0+kPpLofRdBo= github.com/grpc-ecosystem/grpc-gateway v1.16.0/go.mod h1:BDjrQk3hbvj6Nolgz8mAMFbcEtjT1g+wF4CSlocrBnw= -github.com/hashicorp/consul/api v1.1.0/go.mod h1:VmuI/Lkw1nC05EYQWNKwWGbkg+FbDBtguAZLlVdkD9Q= -github.com/hashicorp/consul/sdk v0.1.1/go.mod h1:VKf9jXwCTEY1QZP2MOLRhb5i/I/ssyNV1vwHyQBF0x8= -github.com/hashicorp/errwrap v1.0.0/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4= -github.com/hashicorp/go-cleanhttp v0.5.1/go.mod h1:JpRdi6/HCYpAwUzNwuwqhbovhLtngrth3wmdIIUrZ80= -github.com/hashicorp/go-immutable-radix v1.0.0/go.mod h1:0y9vanUI8NX6FsYoO3zeMjhV/C5i9g4Q3DwcSNZ4P60= -github.com/hashicorp/go-msgpack v0.5.3/go.mod h1:ahLV/dePpqEmjfWmKiqvPkv/twdG7iPBM1vqhUKIvfM= -github.com/hashicorp/go-multierror v1.0.0/go.mod h1:dHtQlpGsu+cZNNAkkCN/P3hoUDHhCYQXV3UM06sGGrk= -github.com/hashicorp/go-rootcerts v1.0.0/go.mod h1:K6zTfqpRlCUIjkwsN4Z+hiSfzSTQa6eBIzfwKfwNnHU= -github.com/hashicorp/go-sockaddr v1.0.0/go.mod h1:7Xibr9yA9JjQq1JpNB2Vw7kxv8xerXegt+ozgdvDeDU= -github.com/hashicorp/go-syslog v1.0.0/go.mod h1:qPfqrKkXGihmCqbJM2mZgkZGvKG1dFdvsLplgctolz4= -github.com/hashicorp/go-uuid v1.0.0/go.mod h1:6SBZvOh/SIDV7/2o3Jml5SYk/TvGqwFJ/bN7x4byOro= -github.com/hashicorp/go-uuid v1.0.1/go.mod h1:6SBZvOh/SIDV7/2o3Jml5SYk/TvGqwFJ/bN7x4byOro= -github.com/hashicorp/go.net v0.0.1/go.mod h1:hjKkEWcCURg++eb33jQU7oqQcI9XDCnUzHA0oac0k90= github.com/hashicorp/golang-lru v0.5.0/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8= github.com/hashicorp/golang-lru v0.5.1/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8= -github.com/hashicorp/hcl v1.0.0/go.mod h1:E5yfLk+7swimpb2L/Alb/PJmXilQ/rhwaUYs4T20WEQ= -github.com/hashicorp/logutils v1.0.0/go.mod h1:QIAnNjmIWmVIIkWDTG1z5v++HQmx9WQRO+LraFDTW64= -github.com/hashicorp/mdns v1.0.0/go.mod h1:tL+uN++7HEJ6SQLQ2/p+z2pH24WQKWjBPkE0mNTz8vQ= -github.com/hashicorp/memberlist v0.1.3/go.mod h1:ajVTdAv/9Im8oMAAj5G31PhhMCZJV2pPBoIllUwCN7I= -github.com/hashicorp/serf v0.8.2/go.mod h1:6hOLApaqBFA1NXqRQAsxw9QxuDEvNxSQRwA/JwenrHc= 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/inconshreveable/mousetrap v1.0.0 h1:Z8tu5sraLXCXIcARxBp/8cbvlwVa7Z1NHg9XEKhtSvM= @@ -237,7 +212,6 @@ github.com/json-iterator/go v1.1.10/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/ github.com/json-iterator/go v1.1.11/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4= github.com/jstemmer/go-junit-report v0.0.0-20190106144839-af01ea7f8024/go.mod h1:6v2b51hI/fHJwM22ozAgKL4VKDeJcHhJFhtBdhmNjmU= github.com/jstemmer/go-junit-report v0.9.1/go.mod h1:Brl9GWCQeLvo8nXZwPNNblvFj/XSXhF0NWZEnDohbsk= -github.com/jtolds/gls v4.20.0+incompatible/go.mod h1:QJZ7F/aHp+rZTRtaJ1ow/lLfFfVYBRgL+9YlvaHOwJU= github.com/julienschmidt/httprouter v1.2.0/go.mod h1:SYymIcj16QtmaHHD7aYtjjsJG7VTCxuUUipMqKk8s4w= github.com/julienschmidt/httprouter v1.3.0/go.mod h1:JR6WtHb+2LUe8TCKY3cZOxFyyO8IZAc4RVcycCCAKdM= github.com/kisielk/errcheck v1.2.0/go.mod h1:/BMXB+zMLi60iA8Vv6Ksmxu/1UDYcXs4uQLJ+jE2L00= @@ -245,7 +219,6 @@ github.com/kisielk/errcheck v1.5.0/go.mod h1:pFxgyoBC7bSaBwPgfKdkLd5X25qrDl4LWUI github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck= github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= github.com/konsorten/go-windows-terminal-sequences v1.0.3/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= -github.com/kr/fs v0.1.0/go.mod h1:FFnZGqtBN9Gxj7eW1uZ42v5BccTP0vu6NEaFoC2HwRg= github.com/kr/logfmt v0.0.0-20140226030751-b84e30acd515/go.mod h1:+0opPa2QZZtGFBFZlji/RkVcI2GknAs/DXo4wKdlNEc= github.com/kr/pretty v0.1.0 h1:L/CwN0zerZDmRFUapSPitk6f+Q3+0za1rQkzVuMiMFI= github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo= @@ -253,24 +226,16 @@ github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY= github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE= -github.com/magiconair/properties v1.8.5/go.mod h1:y3VJvCyxH9uVvJTWEGAELF3aiYNyPKd5NZ3oSwXrF60= -github.com/mattn/go-colorable v0.0.9 h1:UVL0vNpWh04HeJXV0KLcaT7r06gOH2l4OW6ddYRUIY4= -github.com/mattn/go-colorable v0.0.9/go.mod h1:9vuHe8Xs5qXnSaW/c/ABM9alt+Vo+STaOChaDxuIBZU= -github.com/mattn/go-isatty v0.0.3 h1:ns/ykhmWi7G9O+8a448SecJU3nSMBXJfqQkl0upE1jI= -github.com/mattn/go-isatty v0.0.3/go.mod h1:M+lRXTBqGeGNdLjl/ufCoiOlB5xdOkqRJdNxMWT7Zi4= +github.com/mattn/go-colorable v0.1.9/go.mod h1:u6P/XSegPjTcexA+o6vUJrdnUu04hMope9wVRipJSqc= +github.com/mattn/go-colorable v0.1.12 h1:jF+Du6AlPIjs2BiUiQlKOX0rt3SujHxPnksPKZbaA40= +github.com/mattn/go-colorable v0.1.12/go.mod h1:u5H1YNBxpqRaxsYJYSkiCWKzEfiAb1Gb520KVy5xxl4= +github.com/mattn/go-isatty v0.0.12/go.mod h1:cbi8OIDigv2wuxKPP5vlRcQ1OAZbq2CE4Kysco4FUpU= +github.com/mattn/go-isatty v0.0.14 h1:yVuAays6BHfxijgZPzw+3Zlu5yQgKGP2/hcQbHb7S9Y= +github.com/mattn/go-isatty v0.0.14/go.mod h1:7GGIvUiUoEMVVmxf/4nioHXj79iQHKdU27kJ6hsGG94= github.com/mattn/go-runewidth v0.0.9 h1:Lm995f3rfxdpd6TSmuVCHVb/QhupuXlYr8sCI/QdE+0= github.com/mattn/go-runewidth v0.0.9/go.mod h1:H031xJmbD/WCDINGzjvQ9THkh0rPKHF+m2gUSrubnMI= github.com/matttproud/golang_protobuf_extensions v1.0.1 h1:4hp9jkHxhMHkqkrB3Ix0jegS5sx/RkqARlsWZ6pIwiU= github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0= -github.com/miekg/dns v1.0.14/go.mod h1:W1PPwlIAgtquWBMBEV9nkV9Cazfe8ScdGz/Lj7v3Nrg= -github.com/mitchellh/cli v1.0.0/go.mod h1:hNIlj7HEI86fIcpObd7a0FcrxTWetlwJDGcceTlRvqc= -github.com/mitchellh/go-homedir v1.0.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0= -github.com/mitchellh/go-testing-interface v1.0.0/go.mod h1:kRemZodwjscx+RGhAo8eIhFbs2+BFgRtFPeD/KE+zxI= -github.com/mitchellh/gox v0.4.0/go.mod h1:Sd9lOJ0+aimLBi73mGofS1ycjY8lL3uZM3JPS42BGNg= -github.com/mitchellh/iochan v1.0.0/go.mod h1:JwYml1nuB7xOzsp52dPpHFffvOCDupsG0QubkSMEySY= -github.com/mitchellh/mapstructure v0.0.0-20160808181253-ca63d7c062ee/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y= -github.com/mitchellh/mapstructure v1.1.2/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y= -github.com/mitchellh/mapstructure v1.4.1/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo= github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= github.com/modern-go/reflect2 v0.0.0-20180701023420-4b7aa43c6742/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0= @@ -280,16 +245,12 @@ github.com/mwitkow/go-conntrack v0.0.0-20190716064945-2f068394615f/go.mod h1:qRW github.com/olekukonko/tablewriter v0.0.5 h1:P2Ga83D34wi1o9J6Wh1mRuqd4mF/x/lgBS7N7AbDhec= github.com/olekukonko/tablewriter v0.0.5/go.mod h1:hPp6KlRPjbx+hW8ykQs1w3UBbZlj6HuIJcUGPhkA7kY= github.com/opentracing/opentracing-go v1.1.0/go.mod h1:UkNAQd3GIcIGf0SeVgPpRdFStlNbqXla1AfSYxPUl2o= -github.com/pascaldekloe/goe v0.0.0-20180627143212-57f6aae5913c/go.mod h1:lzWF7FIEvWOWxwDKqyGYQf6ZUaNfKdP144TG7ZOy1lc= -github.com/pelletier/go-toml v1.9.3/go.mod h1:u1nR/EPcESfeI/szUZKdtJ0xRNbUoANCkoOuaOx1Y+c= github.com/pkg/errors v0.8.0/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4= github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= -github.com/pkg/sftp v1.10.1/go.mod h1:lYOWFsE0bwd1+KfKJaKeuokY15vzFx25BLbzYYoAxZI= github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= -github.com/posener/complete v1.1.1/go.mod h1:em0nMJCgc9GFtwrmVmEMR/ZL6WyhyjMBndrE9hABlRI= github.com/prometheus/client_golang v0.9.1/go.mod h1:7SWBe2y4D6OKWSNQJUaRYU/AaXPKyh/dDVn+NZz0KFw= github.com/prometheus/client_golang v1.0.0/go.mod h1:db9x61etRT2tGnBNRi70OPL5FsnadC4Ky3P0J6CfImo= github.com/prometheus/client_golang v1.7.1/go.mod h1:PY5Wy2awLA44sXw4AOSfFBetzPP4j5+D6mVACh+pe2M= @@ -312,27 +273,20 @@ github.com/prometheus/procfs v0.6.0/go.mod h1:cz+aTbrPOrUb4q7XlbU9ygM+/jj0fzG6c1 github.com/rogpeppe/fastuuid v1.2.0/go.mod h1:jVj6XXZzXRy/MSR5jhDC/2q6DgLz+nrA6LYCDYWNEvQ= github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4= github.com/russross/blackfriday/v2 v2.0.1/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= -github.com/ryanuber/columnize v0.0.0-20160712163229-9b3edd62028f/go.mod h1:sm1tb6uqfes/u+d4ooFouqFdy9/2g9QGwK3SQygK0Ts= -github.com/sean-/seed v0.0.0-20170313163322-e2103e2c3529/go.mod h1:DxrIzT+xaE7yg65j358z/aeFdxmN0P9QXhEzd20vsDc= +github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= github.com/shurcooL/sanitized_anchor_name v1.0.0/go.mod h1:1NzhyTcUVG4SuEtjjoZeVRXNmyL/1OwPU0+IJeTBvfc= github.com/sirupsen/logrus v1.2.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPxbbu5VWo= github.com/sirupsen/logrus v1.4.2/go.mod h1:tLMulIdttU9McNUspp0xgXVQah82FyeX6MwdIuYE2rE= github.com/sirupsen/logrus v1.6.0/go.mod h1:7uNnSEd1DgxDLC74fIahvMZmmYsHGZGEOFrfsX/uA88= github.com/sirupsen/logrus v1.8.1 h1:dJKuHgqk1NNQlqoA6BTlM1Wf9DOH3NBjQyu0h9+AZZE= github.com/sirupsen/logrus v1.8.1/go.mod h1:yWOB1SBYBC5VeMP7gHvWumXLIWorT60ONWic61uBYv0= -github.com/smartystreets/assertions v0.0.0-20180927180507-b2de0cb4f26d/go.mod h1:OnSkiWE9lh6wB0YB77sQom3nweQdgAjqCqsofrRNTgc= -github.com/smartystreets/goconvey v1.6.4/go.mod h1:syvi0/a8iFYH4r/RixwvyeAJjdLS9QV7WQ/tjFTllLA= github.com/soheilhy/cmux v0.1.5 h1:jjzc5WVemNEDTLwv9tlmemhC73tI08BNOIGwBOo10Js= github.com/soheilhy/cmux v0.1.5/go.mod h1:T7TcVDs9LWfQgPlPsdngu6I6QIoyIFZDDC6sNE1GqG0= github.com/spaolacci/murmur3 v0.0.0-20180118202830-f09979ecbc72/go.mod h1:JwIasOWyU6f++ZhiEuf87xNszmSA2myDM2Kzu9HwQUA= -github.com/spf13/afero v1.6.0/go.mod h1:Ai8FlHk4v/PARR026UzYexafAt9roJ7LcLMAmO6Z93I= -github.com/spf13/cast v1.3.1/go.mod h1:Qx5cxh0v+4UWYiBimWS+eyWzqEqokIECu5etghLkUJE= -github.com/spf13/cobra v1.2.1 h1:+KmjbUw1hriSNMF55oPrkZcb27aECyrj8V2ytv7kWDw= -github.com/spf13/cobra v1.2.1/go.mod h1:ExllRjgxM/piMAM+3tAZvg8fsklGAf3tPfi+i8t68Nk= -github.com/spf13/jwalterweatherman v1.1.0/go.mod h1:aNWZUN0dPAAO/Ljvb5BEdw96iTZ0EXowPYD95IqWIGo= +github.com/spf13/cobra v1.4.0 h1:y+wJpx64xcgO1V+RcnwW0LEHxTKRi2ZDPSBjWnrg88Q= +github.com/spf13/cobra v1.4.0/go.mod h1:Wo4iy3BUC+X2Fybo0PDqwJIv3dNRiZLHQymsfxlB84g= github.com/spf13/pflag v1.0.5 h1:iy+VFUOCP1a+8yFto/drg2CJ5u0yRoB7fZw3DKv/JXA= github.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg= -github.com/spf13/viper v1.8.1/go.mod h1:o0Pch8wJ9BVSWGQMbra6iw0oQ5oktSIBaujf1rJH9Ns= github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= @@ -342,7 +296,6 @@ 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.7.0 h1:nwc3DEeHmmLAfoZucVR881uASk0Mfjw8xYJ99tb5CcY= github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= -github.com/subosito/gotenv v1.2.0/go.mod h1:N0PQaV/YGNqwC0u51sEeR/aUtSLEXKX9iv69rRypqCw= github.com/tmc/grpc-websocket-proxy v0.0.0-20201229170055-e5319fda7802 h1:uruHq4dN7GR16kFc5fp3d1RIYzJW5onx8Ybykw2YQFA= github.com/tmc/grpc-websocket-proxy v0.0.0-20201229170055-e5319fda7802/go.mod h1:ncp9v5uamzpCO7NfCPTXjqaC+bZgJeR0sMTm6dMHP7U= github.com/urfave/cli v1.22.4/go.mod h1:Gos4lmkARVdJ6EkW0WaNv/tZAAMe9V7XWyB60NtXRu0= @@ -391,11 +344,9 @@ go.uber.org/zap v1.10.0/go.mod h1:vwi/ZaCAaUcBkycHslxD9B2zi4UTXhF60s6SWpuDF0Q= go.uber.org/zap v1.17.0 h1:MTjgFu6ZLKvY6Pvaqk97GlxNBuMpV4Hy/3P6tRGlI2U= go.uber.org/zap v1.17.0/go.mod h1:MXVU+bhUf/A7Xi2HNOnopQOrmycQ5Ih87HtOu4q5SSo= golang.org/x/crypto v0.0.0-20180904163835-0709b304e793/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= -golang.org/x/crypto v0.0.0-20181029021203-45a5f77698d3/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= golang.org/x/crypto v0.0.0-20190510104115-cbcb75029529/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20190605123033-f99c8df09eb5/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= -golang.org/x/crypto v0.0.0-20190820162420-60c769a6c586/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= golang.org/x/crypto v0.0.0-20210513164829-c07d793c2f9a h1:kr2P4QFmQr29mSLA43kwrOcgcReGTfbE9N577tCTuBc= @@ -435,9 +386,7 @@ 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/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-20181023162649-9b4f9f5ad519/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20181114220301-adae6a3d119a/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= -golang.org/x/net v0.0.0-20181201002055-351d144fa1fc/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20190108225652-1e06a53dbb7e/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20190213061140-3a22650c66bd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= @@ -499,10 +448,8 @@ golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJ golang.org/x/sync v0.0.0-20201207232520-09787c993a3a/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20210220032951-036812b2e83c h1:5KslGYwFpkhGh+Q16bwMP3cOontH8FOep7tGV86Y7SQ= golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sys v0.0.0-20180823144017-11551d06cbcc/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= -golang.org/x/sys v0.0.0-20181026203630-95b1ffbd15a5/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20181116152217-5ac8a444bdc5/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190312061237-fead79001313/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= @@ -514,12 +461,12 @@ golang.org/x/sys v0.0.0-20190606165138-5da285871e9c/go.mod h1:h1NjWce9XRLGQEsW7w golang.org/x/sys v0.0.0-20190624142023-c5567b49c5d0/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190726091711-fc99dfbffb4e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20191001151750-bb3f8db39f24/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20191005200804-aed5e4c7ecf9/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20191026070338-33540a1f6037/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20191204072324-ce4227a45e2e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20191228213918-04cbcbbfeed8/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200106162015-b016eb3dc98e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200113162924-86b910548bc1/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200116001909-b77594299b42/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200122134326-e047566fdf82/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200202164722-d101bd2416d5/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200212091648-12a6c2dcc1e4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= @@ -547,12 +494,13 @@ golang.org/x/sys v0.0.0-20210305230114-8fe3ee5dd75b/go.mod h1:h1NjWce9XRLGQEsW7w 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-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-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-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-20210630005230-0f9fa26af87c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20210927094055-39ccf1dd6fa6/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20211123173158-ef496fb156ab h1:rfJ1bsoJQQIAoAxTxB7bme+vHrNkRw8CqfsYh9w54cw= golang.org/x/sys v0.0.0-20211123173158-ef496fb156ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= @@ -578,7 +526,6 @@ golang.org/x/tools v0.0.0-20190226205152-f727befe758c/go.mod h1:9Yl7xja0Znq3iFh3 golang.org/x/tools v0.0.0-20190311212946-11955173bddd/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= golang.org/x/tools v0.0.0-20190312151545-0bb0c0a6e846/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= golang.org/x/tools v0.0.0-20190312170243-e65039ee4138/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= -golang.org/x/tools v0.0.0-20190328211700-ab21143f2384/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= golang.org/x/tools v0.0.0-20190425150028-36563e24a262/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q= golang.org/x/tools v0.0.0-20190506145303-2d16b83fe98c/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q= golang.org/x/tools v0.0.0-20190524140312-2c0ae7006135/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q= @@ -588,7 +535,6 @@ golang.org/x/tools v0.0.0-20190628153133-6cdbf07be9d0/go.mod h1:/rFqwRUd4F7ZHNgw golang.org/x/tools v0.0.0-20190816200558-6889da9d5479/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.0.0-20190911174233-4f2ddba30aff/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.0.0-20191012152004-8de300cfc20a/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= -golang.org/x/tools v0.0.0-20191112195655-aa38f8e97acc/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.0.0-20191113191852-77e3bb0ad9e7/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.0.0-20191115202509-3a792d9c32b2/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= @@ -648,7 +594,6 @@ google.golang.org/api v0.36.0/go.mod h1:+z5ficQTmoYpPn8LCUNVpK5I7hwkpjbcgqA7I34q 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.44.0/go.mod h1:EBOGZqzyhtvMDoxwS97ctnh0zUmYY6CxqXsc1AvkYD8= 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.5.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= @@ -720,7 +665,6 @@ google.golang.org/grpc v1.35.0/go.mod h1:qjiiYl8FncCW8feJPdyg3v6XW24KsRHe+dy9BAG 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.1/go.mod h1:NREThFqKR1f3iQ6oBuvc5LadQuXVGo9rkm5ZGrQdJfM= -google.golang.org/grpc v1.38.0/go.mod h1:NREThFqKR1f3iQ6oBuvc5LadQuXVGo9rkm5ZGrQdJfM= google.golang.org/grpc v1.40.0/go.mod h1:ogyxbiOoUXAkP+4+xa6PZSE9DZgIHtSpzjDTB9KAK34= google.golang.org/grpc v1.41.0 h1:f+PlOh7QV4iIJkPrx5NQ7qaNGFQ3OTse67yaDHfju4E= google.golang.org/grpc v1.41.0/go.mod h1:U3l9uK9J0sini8mHphKoXyaqDA/8VyGnDee1zzIUK6k= @@ -746,7 +690,6 @@ gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8 gopkg.in/cheggaaa/pb.v1 v1.0.28 h1:n1tBJnnK2r7g9OW2btFH91V92STTUevLXYFb8gy9EMk= gopkg.in/cheggaaa/pb.v1 v1.0.28/go.mod h1:V/YB90LKu/1FcN3WVnfiiE5oMCibMjukxqG/qStrOgw= gopkg.in/errgo.v2 v2.1.0/go.mod h1:hNsd1EY+bozCKY1Ytp96fpM3vjJbqLJn88ws8XvfDNI= -gopkg.in/ini.v1 v1.62.0/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k= gopkg.in/natefinch/lumberjack.v2 v2.0.0 h1:1Lc07Kr7qY4U2YPouBjpCLxpiyxIVoxqXgkXLknAOE8= gopkg.in/natefinch/lumberjack.v2 v2.0.0/go.mod h1:l0ndWWf7gzL7RNwBG7wST/UCcT4T24xpD6X8LsfU/+k= gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= diff --git a/pkg/go.mod b/pkg/go.mod index f6f240f04e01..03f6461091b6 100644 --- a/pkg/go.mod +++ b/pkg/go.mod @@ -6,7 +6,7 @@ require ( github.com/creack/pty v1.1.11 github.com/dustin/go-humanize v1.0.0 github.com/golang/protobuf v1.5.2 // indirect - github.com/spf13/cobra v1.2.1 + github.com/spf13/cobra v1.4.0 github.com/spf13/pflag v1.0.5 github.com/stretchr/testify v1.7.0 go.etcd.io/etcd/client/pkg/v3 v3.6.0-alpha.0 @@ -28,15 +28,15 @@ require ( gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b // indirect ) -replace ( - go.etcd.io/etcd/api/v3 => ../api - go.etcd.io/etcd/client/pkg/v3 => ../client/pkg -) +replace go.etcd.io/etcd/client/pkg/v3 => ../client/pkg // Bad imports are sometimes causing attempts to pull that code. // This makes the error more explicit. +// Etcd contains lots of packages and dependency relationship. +// Shouldn't import unnecessary dependencies replace ( go.etcd.io/etcd => ./FORBIDDEN_DEPENDENCY + go.etcd.io/etcd/api/v3 => ./FORBIDDEN_DEPENDENCY + go.etcd.io/etcd/tests/v3 => ./FORBIDDEN_DEPENDENCY go.etcd.io/etcd/v3 => ./FORBIDDEN_DEPENDENCY - go.etcd.io/tests/v3 => ./FORBIDDEN_DEPENDENCY ) diff --git a/pkg/go.sum b/pkg/go.sum index 7657ad489756..c03af252897e 100644 --- a/pkg/go.sum +++ b/pkg/go.sum @@ -1,66 +1,18 @@ cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= cloud.google.com/go v0.34.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= -cloud.google.com/go v0.38.0/go.mod h1:990N+gfupTy94rShfmMCWGDn0LpTmnzTp2qbd1dvSRU= -cloud.google.com/go v0.44.1/go.mod h1:iSa0KzasP4Uvy3f1mN/7PiObzGgflwredwwASm/v6AU= -cloud.google.com/go v0.44.2/go.mod h1:60680Gw3Yr4ikxnPRS/oxxkBccT6SA1yMk63TGekxKY= -cloud.google.com/go v0.45.1/go.mod h1:RpBamKRgapWJb87xiFSdk4g1CME7QZg3uwTez+TSTjc= -cloud.google.com/go v0.46.3/go.mod h1:a6bKKbmY7er1mI7TEI4lsAkts/mkhTSZK8w33B4RAg0= -cloud.google.com/go v0.50.0/go.mod h1:r9sluTvynVuxRIOHXQEHMFffphuXHOMZMycpNR5e6To= -cloud.google.com/go v0.52.0/go.mod h1:pXajvRH/6o3+F9jDHZWQ5PbGhn+o8w9qiu/CffaVdO4= -cloud.google.com/go v0.53.0/go.mod h1:fp/UouUEsRkN6ryDKNW/Upv/JBKnv6WDthjR6+vze6M= -cloud.google.com/go v0.54.0/go.mod h1:1rq2OEkV3YMf6n/9ZvGWI3GWw0VoqH/1x2nd8Is/bPc= -cloud.google.com/go v0.56.0/go.mod h1:jr7tqZxxKOVYizybht9+26Z/gUq7tiRzu+ACVAMbKVk= -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.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/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.4.0/go.mod h1:S8dzgnTigyfTmLBfrtrhyYhwRxG72rYxvftPBK2Dvzc= -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.8.0/go.mod h1:J5hqkt3O0uAFnINi6JXValWIb1v0goeZM77hZzJN/fQ= -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/firestore v1.1.0/go.mod h1:ulACoGHTpvq5r8rxGJ4ddJZBZqakUQqClKRT5SZwBmk= -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.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/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.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.10.0/go.mod h1:FLPqc6j+Ki4BU591ie1oL6qBQGu2Bl/tZ9ullr3+Kg0= -dmitri.shuralyov.com/gpu/mtl v0.0.0-20190408044501-666a987793e9/go.mod h1:H6x//7gZCb22OMCxBHrMx7a5I7Hp++hsVxbQ4BYO7hU= github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= -github.com/BurntSushi/xgb v0.0.0-20160522181843-27f122750802/go.mod h1:IVnqGOEym/WlBOVXweHU+Q+/VP0lqqI8lqeDx9IjBqo= github.com/OneOfOne/xxhash v1.2.2/go.mod h1:HSdplMjZKSmBqAxg5vPj2TmRDmfkzw+cTzAElWljhcU= github.com/antihax/optional v1.0.0/go.mod h1:uupD/76wgC+ih3iEmQUL+0Ugr19nfwCT1kdvxnR2qWY= -github.com/armon/circbuf v0.0.0-20150827004946-bbbad097214e/go.mod h1:3U/XgcO3hCbHZ8TKRvWD2dDTCfh9M9ya+I9JpbB7O8o= -github.com/armon/go-metrics v0.0.0-20180917152333-f0300d1749da/go.mod h1:Q73ZrmVTwzkszR9V5SSuryQ31EELlFMUz1kKyl939pY= -github.com/armon/go-radix v0.0.0-20180808171621-7fddfc383310/go.mod h1:ufUuZ+zHj4x4TnLV4JWEpy2hxWSpsRywHrMgIH9cCH8= -github.com/bgentry/speakeasy v0.1.0/go.mod h1:+zsyZBPWlz7T6j88CTgSN5bM796AkVf0kBD4zp0CCIs= -github.com/bketelsen/crypt v0.0.4/go.mod h1:aI6NrJ0pMGgvZKL1iVgXLnfIFJtfV+bKCoqOes/6LfM= github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU= github.com/cespare/xxhash v1.1.0/go.mod h1:XrSqR1VqqWfGrhpAt58auRo0WTKS1nRRg3ghfAqPWnc= github.com/cespare/xxhash/v2 v2.1.1/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= -github.com/chzyer/logex v1.1.10/go.mod h1:+Ywpsq7O8HXn0nuIou7OrIPyXbp3wmkHB+jjWRnGsAI= -github.com/chzyer/readline v0.0.0-20180603132655-2972be24d48e/go.mod h1:nSuG5e5PlCu98SY8svDHJxuZscDgtXS6KTTbou5AhLI= -github.com/chzyer/test v0.0.0-20180213035817-a1ea475d72b1/go.mod h1:Q3SI9o4m/ZMnBNeIyt5eFwwo7qiLfzFZmjNmxjkiQlU= github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw= 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/xds/go v0.0.0-20210312221358-fbca930ec8ed/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs= github.com/cncf/xds/go v0.0.0-20210805033703-aa0b78936158/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs= -github.com/coreos/go-semver v0.3.0/go.mod h1:nnelYz7RCh+5ahJtPPxZlU+153eP4D4r3EedlOD2RNk= github.com/coreos/go-systemd/v22 v22.3.2/go.mod h1:Y58oyj3AT4RCenI/lSvhwexgC+NSVTIJ3seZv2GcEnc= -github.com/cpuguy83/go-md2man/v2 v2.0.0/go.mod h1:maD7wRr/U5Z6m/iR4s+kqSMx2CaBsrgA7czyZG/E6dU= +github.com/cpuguy83/go-md2man/v2 v2.0.1/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o= github.com/creack/pty v1.1.11 h1:07n33Z8lZxZ2qwegKbObQohDhXDQxiMMz1NOUGYlesw= github.com/creack/pty v1.1.11/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E= github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= @@ -71,38 +23,17 @@ github.com/dustin/go-humanize v1.0.0/go.mod h1:HtrtbFcZ19U5GC7JDqmcUSB87Iq5E25Kn 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.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.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.10-0.20210907150352-cf90f659a021/go.mod h1:AFq3mo9L8Lqqiid3OhADV3RfLJnjiw63cSpi+fDTRC0= github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c= -github.com/fatih/color v1.7.0/go.mod h1:Zm6kSWBoL9eyXnKyktHP6abPY2pDugNf5KwzbycvMj4= -github.com/fsnotify/fsnotify v1.4.9/go.mod h1:znqG4EE+3YCdAaPaxE2ZRY/06pZUdp0tY4IgpuI1SZQ= github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04= -github.com/go-gl/glfw v0.0.0-20190409004039-e6da0acd62b1/go.mod h1:vR7hzQXu2zJy9AVAgeJqvqgH9Q5CA+iKCZ2gyEVpxRU= -github.com/go-gl/glfw/v3.3/glfw v0.0.0-20191125211704-12ad95a8df72/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8= -github.com/go-gl/glfw/v3.3/glfw v0.0.0-20200222043503-6f7a984d4dc4/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8= github.com/godbus/dbus/v5 v5.0.4/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA= -github.com/gogo/protobuf v1.3.2/go.mod h1:P1XiOD3dCwIKUDQYPy72D8LYyHL2YPYrpS2s69NZV8Q= github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q= -github.com/golang/groupcache v0.0.0-20190702054246-869f871628b6/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= -github.com/golang/groupcache v0.0.0-20191227052852-215e87163ea7/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= -github.com/golang/groupcache v0.0.0-20200121045136-8c9f03a8e57e/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= github.com/golang/mock v1.1.1/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A= -github.com/golang/mock v1.2.0/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A= -github.com/golang/mock v1.3.1/go.mod h1:sBzyDLLjw3U8JLTeZvSv8jJB+tU5PVekmnlKIyFUx0Y= -github.com/golang/mock v1.4.0/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.4/go.mod h1:l3mdAwkq5BuhzHwde/uurv3sEJeZMXNpwsxVWU71h+4= -github.com/golang/mock v1.5.0/go.mod h1:CWnOUgYIOo4TcNZ0wHX3YZCqsaM1I1Jvs6v3mP3KVu8= github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= -github.com/golang/protobuf v1.3.1/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= github.com/golang/protobuf v1.3.2/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= github.com/golang/protobuf v1.3.3/go.mod h1:vzj43D7+SQXF/4pzW/hwtAqwc6iTitCiVSaWz5lYuqw= -github.com/golang/protobuf v1.3.4/go.mod h1:vzj43D7+SQXF/4pzW/hwtAqwc6iTitCiVSaWz5lYuqw= -github.com/golang/protobuf v1.3.5/go.mod h1:6O5/vntMXwX2lRkT1hjjk0nAC1IDOTvTlVgjlRvqsdk= github.com/golang/protobuf v1.4.0-rc.1/go.mod h1:ceaxUfeHdC40wWswd/P6IGgMaK3YpKi5j83Wpe3EHw8= github.com/golang/protobuf v1.4.0-rc.1.0.20200221234624-67d41d38c208/go.mod h1:xKAWHe0F5eneWXFV3EuXVDTCmh+JuBKY0li0aMyXATA= github.com/golang/protobuf v1.4.0-rc.2/go.mod h1:LlEzMj4AhA7rCAGe4KMBDvJI+AwstrUpVNzEA03Pprs= @@ -112,142 +43,36 @@ 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.3/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI= 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/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY= -github.com/google/btree v0.0.0-20180813153112-4030bb1f1f0c/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ= -github.com/google/btree v1.0.0/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ= github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M= github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= -github.com/google/go-cmp v0.4.1/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.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.5 h1:Khx7svrCpmxxtHBq5j2mp/xVjsi8hQMfNLvJFAlrGgU= github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= -github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= -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.1.0/go.mod h1:y5Zk1BBys9G+gd6Jrk0W3cC1+ELVxBWuIGO+w/tUAp0= -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-20191218002539-d4f498aebedc/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= -github.com/google/pprof v0.0.0-20200212024743-f11f1df84d12/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-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/renameio v0.1.0/go.mod h1:KWCgfxg9yswjAJkECMjeO8J8rahYeXnNhOm40UhjYkI= github.com/google/uuid v1.1.2/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= -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/gopherjs/gopherjs v0.0.0-20181017120253-0766667cb4d1/go.mod h1:wJfORRmW1u3UXTncJ5qlYoELFm8eSnnEO6hX4iZ3EWY= github.com/grpc-ecosystem/grpc-gateway v1.16.0/go.mod h1:BDjrQk3hbvj6Nolgz8mAMFbcEtjT1g+wF4CSlocrBnw= -github.com/hashicorp/consul/api v1.1.0/go.mod h1:VmuI/Lkw1nC05EYQWNKwWGbkg+FbDBtguAZLlVdkD9Q= -github.com/hashicorp/consul/sdk v0.1.1/go.mod h1:VKf9jXwCTEY1QZP2MOLRhb5i/I/ssyNV1vwHyQBF0x8= -github.com/hashicorp/errwrap v1.0.0/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4= -github.com/hashicorp/go-cleanhttp v0.5.1/go.mod h1:JpRdi6/HCYpAwUzNwuwqhbovhLtngrth3wmdIIUrZ80= -github.com/hashicorp/go-immutable-radix v1.0.0/go.mod h1:0y9vanUI8NX6FsYoO3zeMjhV/C5i9g4Q3DwcSNZ4P60= -github.com/hashicorp/go-msgpack v0.5.3/go.mod h1:ahLV/dePpqEmjfWmKiqvPkv/twdG7iPBM1vqhUKIvfM= -github.com/hashicorp/go-multierror v1.0.0/go.mod h1:dHtQlpGsu+cZNNAkkCN/P3hoUDHhCYQXV3UM06sGGrk= -github.com/hashicorp/go-rootcerts v1.0.0/go.mod h1:K6zTfqpRlCUIjkwsN4Z+hiSfzSTQa6eBIzfwKfwNnHU= -github.com/hashicorp/go-sockaddr v1.0.0/go.mod h1:7Xibr9yA9JjQq1JpNB2Vw7kxv8xerXegt+ozgdvDeDU= -github.com/hashicorp/go-syslog v1.0.0/go.mod h1:qPfqrKkXGihmCqbJM2mZgkZGvKG1dFdvsLplgctolz4= -github.com/hashicorp/go-uuid v1.0.0/go.mod h1:6SBZvOh/SIDV7/2o3Jml5SYk/TvGqwFJ/bN7x4byOro= -github.com/hashicorp/go-uuid v1.0.1/go.mod h1:6SBZvOh/SIDV7/2o3Jml5SYk/TvGqwFJ/bN7x4byOro= -github.com/hashicorp/go.net v0.0.1/go.mod h1:hjKkEWcCURg++eb33jQU7oqQcI9XDCnUzHA0oac0k90= -github.com/hashicorp/golang-lru v0.5.0/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8= -github.com/hashicorp/golang-lru v0.5.1/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8= -github.com/hashicorp/hcl v1.0.0/go.mod h1:E5yfLk+7swimpb2L/Alb/PJmXilQ/rhwaUYs4T20WEQ= -github.com/hashicorp/logutils v1.0.0/go.mod h1:QIAnNjmIWmVIIkWDTG1z5v++HQmx9WQRO+LraFDTW64= -github.com/hashicorp/mdns v1.0.0/go.mod h1:tL+uN++7HEJ6SQLQ2/p+z2pH24WQKWjBPkE0mNTz8vQ= -github.com/hashicorp/memberlist v0.1.3/go.mod h1:ajVTdAv/9Im8oMAAj5G31PhhMCZJV2pPBoIllUwCN7I= -github.com/hashicorp/serf v0.8.2/go.mod h1:6hOLApaqBFA1NXqRQAsxw9QxuDEvNxSQRwA/JwenrHc= -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/inconshreveable/mousetrap v1.0.0 h1:Z8tu5sraLXCXIcARxBp/8cbvlwVa7Z1NHg9XEKhtSvM= github.com/inconshreveable/mousetrap v1.0.0/go.mod h1:PxqpIevigyE2G7u3NXJIT2ANytuPF1OarO4DADm73n8= -github.com/json-iterator/go v1.1.11/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4= -github.com/jstemmer/go-junit-report v0.0.0-20190106144839-af01ea7f8024/go.mod h1:6v2b51hI/fHJwM22ozAgKL4VKDeJcHhJFhtBdhmNjmU= -github.com/jstemmer/go-junit-report v0.9.1/go.mod h1:Brl9GWCQeLvo8nXZwPNNblvFj/XSXhF0NWZEnDohbsk= -github.com/jtolds/gls v4.20.0+incompatible/go.mod h1:QJZ7F/aHp+rZTRtaJ1ow/lLfFfVYBRgL+9YlvaHOwJU= -github.com/kisielk/errcheck v1.5.0/go.mod h1:pFxgyoBC7bSaBwPgfKdkLd5X25qrDl4LWUI2bnpBCr8= -github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck= -github.com/kr/fs v0.1.0/go.mod h1:FFnZGqtBN9Gxj7eW1uZ42v5BccTP0vu6NEaFoC2HwRg= -github.com/kr/pretty v0.1.0 h1:L/CwN0zerZDmRFUapSPitk6f+Q3+0za1rQkzVuMiMFI= -github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo= -github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= -github.com/kr/text v0.1.0 h1:45sCR5RtlFHMR4UwH9sdQ5TC8v0qDQCHnXt+kaKSTVE= -github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= -github.com/magiconair/properties v1.8.5/go.mod h1:y3VJvCyxH9uVvJTWEGAELF3aiYNyPKd5NZ3oSwXrF60= -github.com/mattn/go-colorable v0.0.9/go.mod h1:9vuHe8Xs5qXnSaW/c/ABM9alt+Vo+STaOChaDxuIBZU= -github.com/mattn/go-isatty v0.0.3/go.mod h1:M+lRXTBqGeGNdLjl/ufCoiOlB5xdOkqRJdNxMWT7Zi4= -github.com/miekg/dns v1.0.14/go.mod h1:W1PPwlIAgtquWBMBEV9nkV9Cazfe8ScdGz/Lj7v3Nrg= -github.com/mitchellh/cli v1.0.0/go.mod h1:hNIlj7HEI86fIcpObd7a0FcrxTWetlwJDGcceTlRvqc= -github.com/mitchellh/go-homedir v1.0.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0= -github.com/mitchellh/go-testing-interface v1.0.0/go.mod h1:kRemZodwjscx+RGhAo8eIhFbs2+BFgRtFPeD/KE+zxI= -github.com/mitchellh/gox v0.4.0/go.mod h1:Sd9lOJ0+aimLBi73mGofS1ycjY8lL3uZM3JPS42BGNg= -github.com/mitchellh/iochan v1.0.0/go.mod h1:JwYml1nuB7xOzsp52dPpHFffvOCDupsG0QubkSMEySY= -github.com/mitchellh/mapstructure v0.0.0-20160808181253-ca63d7c062ee/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y= -github.com/mitchellh/mapstructure v1.1.2/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y= -github.com/mitchellh/mapstructure v1.4.1/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo= -github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= -github.com/modern-go/reflect2 v0.0.0-20180701023420-4b7aa43c6742/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0= -github.com/modern-go/reflect2 v1.0.1/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0= -github.com/pascaldekloe/goe v0.0.0-20180627143212-57f6aae5913c/go.mod h1:lzWF7FIEvWOWxwDKqyGYQf6ZUaNfKdP144TG7ZOy1lc= -github.com/pelletier/go-toml v1.9.3/go.mod h1:u1nR/EPcESfeI/szUZKdtJ0xRNbUoANCkoOuaOx1Y+c= github.com/pkg/errors v0.8.1 h1:iURUrRGxPUNPdy5/HRSm+Yj6okJ6UtLINN0Q9M4+h3I= github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= -github.com/pkg/sftp v1.10.1/go.mod h1:lYOWFsE0bwd1+KfKJaKeuokY15vzFx25BLbzYYoAxZI= github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= -github.com/posener/complete v1.1.1/go.mod h1:em0nMJCgc9GFtwrmVmEMR/ZL6WyhyjMBndrE9hABlRI= github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= github.com/rogpeppe/fastuuid v1.2.0/go.mod h1:jVj6XXZzXRy/MSR5jhDC/2q6DgLz+nrA6LYCDYWNEvQ= -github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4= -github.com/russross/blackfriday/v2 v2.0.1/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= -github.com/ryanuber/columnize v0.0.0-20160712163229-9b3edd62028f/go.mod h1:sm1tb6uqfes/u+d4ooFouqFdy9/2g9QGwK3SQygK0Ts= -github.com/sean-/seed v0.0.0-20170313163322-e2103e2c3529/go.mod h1:DxrIzT+xaE7yg65j358z/aeFdxmN0P9QXhEzd20vsDc= -github.com/shurcooL/sanitized_anchor_name v1.0.0/go.mod h1:1NzhyTcUVG4SuEtjjoZeVRXNmyL/1OwPU0+IJeTBvfc= -github.com/smartystreets/assertions v0.0.0-20180927180507-b2de0cb4f26d/go.mod h1:OnSkiWE9lh6wB0YB77sQom3nweQdgAjqCqsofrRNTgc= -github.com/smartystreets/goconvey v1.6.4/go.mod h1:syvi0/a8iFYH4r/RixwvyeAJjdLS9QV7WQ/tjFTllLA= +github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= github.com/spaolacci/murmur3 v0.0.0-20180118202830-f09979ecbc72/go.mod h1:JwIasOWyU6f++ZhiEuf87xNszmSA2myDM2Kzu9HwQUA= -github.com/spf13/afero v1.6.0/go.mod h1:Ai8FlHk4v/PARR026UzYexafAt9roJ7LcLMAmO6Z93I= -github.com/spf13/cast v1.3.1/go.mod h1:Qx5cxh0v+4UWYiBimWS+eyWzqEqokIECu5etghLkUJE= -github.com/spf13/cobra v1.2.1 h1:+KmjbUw1hriSNMF55oPrkZcb27aECyrj8V2ytv7kWDw= -github.com/spf13/cobra v1.2.1/go.mod h1:ExllRjgxM/piMAM+3tAZvg8fsklGAf3tPfi+i8t68Nk= -github.com/spf13/jwalterweatherman v1.1.0/go.mod h1:aNWZUN0dPAAO/Ljvb5BEdw96iTZ0EXowPYD95IqWIGo= +github.com/spf13/cobra v1.4.0 h1:y+wJpx64xcgO1V+RcnwW0LEHxTKRi2ZDPSBjWnrg88Q= +github.com/spf13/cobra v1.4.0/go.mod h1:Wo4iy3BUC+X2Fybo0PDqwJIv3dNRiZLHQymsfxlB84g= github.com/spf13/pflag v1.0.5 h1:iy+VFUOCP1a+8yFto/drg2CJ5u0yRoB7fZw3DKv/JXA= github.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg= -github.com/spf13/viper v1.8.1/go.mod h1:o0Pch8wJ9BVSWGQMbra6iw0oQ5oktSIBaujf1rJH9Ns= github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= -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.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4= github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA= -github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/stretchr/testify v1.7.0 h1:nwc3DEeHmmLAfoZucVR881uASk0Mfjw8xYJ99tb5CcY= github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= -github.com/subosito/gotenv v1.2.0/go.mod h1:N0PQaV/YGNqwC0u51sEeR/aUtSLEXKX9iv69rRypqCw= -github.com/yuin/goldmark v1.1.25/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= -github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= -github.com/yuin/goldmark v1.1.32/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= -github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= -go.etcd.io/etcd/client/v2 v2.305.0/go.mod h1:h9puh54ZTgAKtEbut2oe9P4L/oqKCVB6xsXlzd7alYQ= -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.2/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.5/go.mod h1:5pWMHQbX5EPX2/62yrJeAkowc+lfs/XD7Uxpq3pI6kk= -go.opencensus.io v0.23.0/go.mod h1:XItmlyltB5F7CS4xOC1DcqMoFqwtC6OG2xF7mCv7P7E= go.opentelemetry.io/proto/otlp v0.7.0/go.mod h1:PqfVotwruBrMGOCsRd/89rSnXhoiJIqeYNgFYFoEGnI= go.uber.org/atomic v1.7.0 h1:ADUqmZGgLDDfbSL9ZmPxKTybcoEYHgpYfELNoN+7hsw= go.uber.org/atomic v1.7.0/go.mod h1:fEN4uk6kAWBTFdckzkM89CLk9XfWZrxpCo0nPH17wJc= @@ -255,307 +80,63 @@ go.uber.org/multierr v1.6.0 h1:y6IPFStTAIT5Ytl7/XYmHvzXQ7S3g/IeZW9hyZ5thw4= go.uber.org/multierr v1.6.0/go.mod h1:cdWPpRnG4AhwMwsgIHip0KRBQjJy5kYEpYjJxpXp9iU= go.uber.org/zap v1.17.0 h1:MTjgFu6ZLKvY6Pvaqk97GlxNBuMpV4Hy/3P6tRGlI2U= go.uber.org/zap v1.17.0/go.mod h1:MXVU+bhUf/A7Xi2HNOnopQOrmycQ5Ih87HtOu4q5SSo= -golang.org/x/crypto v0.0.0-20181029021203-45a5f77698d3/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= -golang.org/x/crypto v0.0.0-20190510104115-cbcb75029529/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= -golang.org/x/crypto v0.0.0-20190605123033-f99c8df09eb5/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= -golang.org/x/crypto v0.0.0-20190820162420-60c769a6c586/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= -golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= -golang.org/x/exp v0.0.0-20190306152737-a1d7652674e8/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= -golang.org/x/exp v0.0.0-20190510132918-efd6b22b2522/go.mod h1:ZjyILWgesfNpC6sMxTJOJm9Kp84zZh5NQWvqDGG3Qr8= -golang.org/x/exp v0.0.0-20190829153037-c13cbed26979/go.mod h1:86+5VVa7VpoJ4kLfm080zCjGlMRFzhUhsZKEZO7MGek= -golang.org/x/exp v0.0.0-20191030013958-a1ab85dbe136/go.mod h1:JXzH8nQsPlswgeRAPE3MuO9GYsAcnJvJ4vnMwN/5qkY= -golang.org/x/exp v0.0.0-20191129062945-2f5052295587/go.mod h1:2RIsYlXP63K8oxa1u096TMicItID8zy7Y6sNkU49FU4= -golang.org/x/exp v0.0.0-20191227195350-da58074b4299/go.mod h1:2RIsYlXP63K8oxa1u096TMicItID8zy7Y6sNkU49FU4= -golang.org/x/exp v0.0.0-20200119233911-0405dc783f0a/go.mod h1:2RIsYlXP63K8oxa1u096TMicItID8zy7Y6sNkU49FU4= -golang.org/x/exp v0.0.0-20200207192155-f17229e696bd/go.mod h1:J/WKrq2StrnmMY6+EHIKF9dgMWnmCNThgcyBT1FY9mM= -golang.org/x/exp v0.0.0-20200224162631-6cc2880d07d6/go.mod h1:3jZMyOhIsHpP37uCMkUooju7aAi5cS1Q23tOzKc+0MU= -golang.org/x/image v0.0.0-20190227222117-0694c2d4d067/go.mod h1:kZ7UVZpmo3dzQBMxlp+ypCbDeSB+sBbTgSJuh5dn5js= -golang.org/x/image v0.0.0-20190802002840-cff245a6509b/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0= golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE= golang.org/x/lint v0.0.0-20190227174305-5b3e6a55c961/go.mod h1:wehouNa3lNwaWXcvxsM5YxQ5yQlVC4a0KAMCusXpPoU= -golang.org/x/lint v0.0.0-20190301231843-5614ed5bae6f/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE= golang.org/x/lint v0.0.0-20190313153728-d0100b6bd8b3/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= -golang.org/x/lint v0.0.0-20190409202823-959b441ac422/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= -golang.org/x/lint v0.0.0-20190909230951-414d861bb4ac/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= -golang.org/x/lint v0.0.0-20190930215403-16217165b5de/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= -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-20200302205851-738671d3881b/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY= -golang.org/x/lint v0.0.0-20201208152925-83fdc39ff7b5/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-20190719004257-d2bd2a29d028/go.mod h1:E/iHnbuqvinMTCcRqshq8CkpyQDoeVncDDYHnLhea+o= -golang.org/x/mod v0.0.0-20190513183733-4bf6d317e70e/go.mod h1:mXi4GBBbnImb6dmsKGUJ2LatrhH/nqhxcFungHvyanc= -golang.org/x/mod v0.1.0/go.mod h1:0QHyrYULN0/3qlju5TqG8bIK38QM8yzMo5ekMj3DlcY= -golang.org/x/mod v0.1.1-0.20191105210325-c90efee705ee/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.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/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-20181023162649-9b4f9f5ad519/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= -golang.org/x/net v0.0.0-20181201002055-351d144fa1fc/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20190108225652-1e06a53dbb7e/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20190213061140-3a22650c66bd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= -golang.org/x/net v0.0.0-20190501004415-9ce7a6920f09/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= -golang.org/x/net v0.0.0-20190503192946-f4e77d36d62c/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= -golang.org/x/net v0.0.0-20190603091049-60506f45cf65/go.mod h1:HSz+uSET+XFnRR8LxR5pz3Of3rY3CfYBVs4xY44aLks= -golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= -golang.org/x/net v0.0.0-20190628185345-da137c7871d7/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= -golang.org/x/net v0.0.0-20190724013045-ca1201d0de80/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= -golang.org/x/net v0.0.0-20191209160850-c0dbc17a3553/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= -golang.org/x/net v0.0.0-20200114155413-6afb5195e5aa/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= -golang.org/x/net v0.0.0-20200202094626-16171245cfb2/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= -golang.org/x/net v0.0.0-20200222125558-5a598a2470a0/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= -golang.org/x/net v0.0.0-20200226121028-0de0cce0169b/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= -golang.org/x/net v0.0.0-20200301022130-244492dfa37a/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= -golang.org/x/net v0.0.0-20200324143707-d3edc9973b7e/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= -golang.org/x/net v0.0.0-20200501053045-e0ff5e5a1de5/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= -golang.org/x/net v0.0.0-20200506145744-7e3656a0809f/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= -golang.org/x/net v0.0.0-20200513185701-a91f0712d120/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= -golang.org/x/net v0.0.0-20200520182314-0ba52f642ac2/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= -golang.org/x/net v0.0.0-20200625001655-4c5254603344/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-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-20210316092652-d523dce5a7f4/go.mod h1:RBQZq4jEuRlivfhVLdyRGr576XBO4/greRjx4P4O3yc= golang.org/x/net v0.0.0-20210405180319-a5a99cb37ef4 h1:4nGaVu0QrbjT/AK2PRLuQfQuh6DJve+pELhqTdAj3x0= golang.org/x/net v0.0.0-20210405180319-a5a99cb37ef4/go.mod h1:p54w0d4576C0XHj96bSt6lcn1PtDYWL6XObtHCRCNQM= 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-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-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-20210402161424-2e8d93401602/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= 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-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.0.0-20190227155943-e225da77a7e6/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.0.0-20200317015054-43a5402ce75a/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.0.0-20200625203802-6e8e738ad208/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-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sys v0.0.0-20180823144017-11551d06cbcc/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= -golang.org/x/sys v0.0.0-20181026203630-95b1ffbd15a5/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= -golang.org/x/sys v0.0.0-20190312061237-fead79001313/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20190502145724-3ef323f4f1fd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20190507160741-ecd444e8653b/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20190606165138-5da285871e9c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20190624142023-c5567b49c5d0/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20190726091711-fc99dfbffb4e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20191001151750-bb3f8db39f24/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20191005200804-aed5e4c7ecf9/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20191204072324-ce4227a45e2e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20191228213918-04cbcbbfeed8/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200113162924-86b910548bc1/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200122134326-e047566fdf82/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200202164722-d101bd2416d5/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200212091648-12a6c2dcc1e4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200223170610-d5e6a3e2c0ae/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200302150141-5c8b2ff67527/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200331124033-c3d80250170d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200501052902-10377860bb8e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200511232937-7e40ca221e25/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200515095857-1151b9dac4a9/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200523222454-059865788121/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-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-20210119212857-b64e53b001e4/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-20210403161142-5e06dd20ab57/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-20210603125802-9665404d3644 h1:CA1DEQ4NdKphKeL70tvsWNdT5oFh1lOjihRcEDROi0I= golang.org/x/sys v0.0.0-20210603125802-9665404d3644/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= -golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= -golang.org/x/text v0.3.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.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 h1:i6eZZ+zk0SOf0xgBpEpPD18qWcJda6q1sxt3S0kzyUQ= golang.org/x/text v0.3.5/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= -golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= -golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= -golang.org/x/time v0.0.0-20191024005414-555d28b269f0/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-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-20190311212946-11955173bddd/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= -golang.org/x/tools v0.0.0-20190312151545-0bb0c0a6e846/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= -golang.org/x/tools v0.0.0-20190312170243-e65039ee4138/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= -golang.org/x/tools v0.0.0-20190328211700-ab21143f2384/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= -golang.org/x/tools v0.0.0-20190425150028-36563e24a262/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q= -golang.org/x/tools v0.0.0-20190506145303-2d16b83fe98c/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q= golang.org/x/tools v0.0.0-20190524140312-2c0ae7006135/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q= -golang.org/x/tools v0.0.0-20190606124116-d0a3d012864b/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc= -golang.org/x/tools v0.0.0-20190621195816-6e04913cbbac/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc= -golang.org/x/tools v0.0.0-20190628153133-6cdbf07be9d0/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc= -golang.org/x/tools v0.0.0-20190816200558-6889da9d5479/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= -golang.org/x/tools v0.0.0-20190911174233-4f2ddba30aff/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= -golang.org/x/tools v0.0.0-20191012152004-8de300cfc20a/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= -golang.org/x/tools v0.0.0-20191112195655-aa38f8e97acc/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= -golang.org/x/tools v0.0.0-20191113191852-77e3bb0ad9e7/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= -golang.org/x/tools v0.0.0-20191115202509-3a792d9c32b2/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= -golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= -golang.org/x/tools v0.0.0-20191125144606-a911d9008d1f/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= -golang.org/x/tools v0.0.0-20191130070609-6e064ea0cf2d/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= -golang.org/x/tools v0.0.0-20191216173652-a0e659d51361/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= -golang.org/x/tools v0.0.0-20191227053925-7b8e75db28f4/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= -golang.org/x/tools v0.0.0-20200117161641-43d50277825c/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= -golang.org/x/tools v0.0.0-20200122220014-bf1340f18c4a/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= -golang.org/x/tools v0.0.0-20200130002326-2f3ba24bd6e7/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= -golang.org/x/tools v0.0.0-20200204074204-1cc6d1ef6c74/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= -golang.org/x/tools v0.0.0-20200207183749-b753a1ba74fa/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= -golang.org/x/tools v0.0.0-20200212150539-ea181f53ac56/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= -golang.org/x/tools v0.0.0-20200224181240-023911ca70b2/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= -golang.org/x/tools v0.0.0-20200227222343-706bc42d1f0d/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= -golang.org/x/tools v0.0.0-20200304193943-95d2e580d8eb/go.mod h1:o4KQGtdN14AW+yjsvvwRTJJuXz8XRtIHtEnmAXLyFUw= -golang.org/x/tools v0.0.0-20200312045724-11d5b4c81c7d/go.mod h1:o4KQGtdN14AW+yjsvvwRTJJuXz8XRtIHtEnmAXLyFUw= -golang.org/x/tools v0.0.0-20200331025713-a30bf2db82d4/go.mod h1:Sl4aGygMT6LrqrWclx+PTx3U+LnKx/seiNR+3G19Ar8= -golang.org/x/tools v0.0.0-20200501065659-ab2804fb9c9d/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= -golang.org/x/tools v0.0.0-20200512131952-2bc93b1c0c88/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= -golang.org/x/tools v0.0.0-20200515010526-7d3b6ebf133d/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= -golang.org/x/tools v0.0.0-20200618134242-20370b0cb4b2/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= -golang.org/x/tools v0.0.0-20200619180055-7c47624df98f/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= -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-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-20210105154028-b0ab187a4818/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/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-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1 h1:go1bK/D/BFZV2I8cIQd1NKEZ+0owSTG1fDTci4IqFcE= golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= -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.8.0/go.mod h1:o4eAsZoiT+ibD93RtjEohWalFOjRDx6CVaqeizhEnKg= -google.golang.org/api v0.9.0/go.mod h1:o4eAsZoiT+ibD93RtjEohWalFOjRDx6CVaqeizhEnKg= -google.golang.org/api v0.13.0/go.mod h1:iLdEw5Ide6rF15KTC1Kkl0iskquN2gFfn9o9XIsbkAI= -google.golang.org/api v0.14.0/go.mod h1:iLdEw5Ide6rF15KTC1Kkl0iskquN2gFfn9o9XIsbkAI= -google.golang.org/api v0.15.0/go.mod h1:iLdEw5Ide6rF15KTC1Kkl0iskquN2gFfn9o9XIsbkAI= -google.golang.org/api v0.17.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE= -google.golang.org/api v0.18.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE= -google.golang.org/api v0.19.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE= -google.golang.org/api v0.20.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE= -google.golang.org/api v0.22.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE= -google.golang.org/api v0.24.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.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.44.0/go.mod h1:EBOGZqzyhtvMDoxwS97ctnh0zUmYY6CxqXsc1AvkYD8= 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.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.5/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc= -google.golang.org/appengine v1.6.6/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc= -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-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-20190425155659-357c62f0e4bb/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= -google.golang.org/genproto v0.0.0-20190502173448-54afdca5d873/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= -google.golang.org/genproto v0.0.0-20190801165951-fa694d86fc64/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc= google.golang.org/genproto v0.0.0-20190819201941-24fa4b261c55/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc= -google.golang.org/genproto v0.0.0-20190911173649-1774047e7e51/go.mod h1:IbNlFCBrqXvoKpeg0TB2l7cyZUmoaFKYIwrEpbDKLA8= -google.golang.org/genproto v0.0.0-20191108220845-16a3f7862a1a/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= -google.golang.org/genproto v0.0.0-20191115194625-c23dd37a84c9/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= -google.golang.org/genproto v0.0.0-20191216164720-4f79533eabd1/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= -google.golang.org/genproto v0.0.0-20191230161307-f3c370f40bfb/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= -google.golang.org/genproto v0.0.0-20200115191322-ca5a22157cba/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= -google.golang.org/genproto v0.0.0-20200122232147-0452cf42e150/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= -google.golang.org/genproto v0.0.0-20200204135345-fa8e72b47b90/go.mod h1:GmwEX6Z4W5gMy59cAlVYjN9JhxgbQH6Gn+gFDQe2lzA= -google.golang.org/genproto v0.0.0-20200212174721-66ed5ce911ce/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= -google.golang.org/genproto v0.0.0-20200224152610-e50cd9704f63/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= -google.golang.org/genproto v0.0.0-20200228133532-8c2c7df3a383/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= -google.golang.org/genproto v0.0.0-20200305110556-506484158171/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= -google.golang.org/genproto v0.0.0-20200312145019-da6875a35672/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= -google.golang.org/genproto v0.0.0-20200331122359-1ee6d9798940/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= -google.golang.org/genproto v0.0.0-20200430143042-b979b6f78d84/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= -google.golang.org/genproto v0.0.0-20200511104702-f5ebc3bea380/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= google.golang.org/genproto v0.0.0-20200513103714-09dca8ec2884/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= -google.golang.org/genproto v0.0.0-20200515170657-fc4c6c6a6587/go.mod h1:YsZOwe1myG/8QRHRsmBRE1LrgQY60beZKjly0O1fX9U= google.golang.org/genproto v0.0.0-20200526211855-cb27e3aa2013/go.mod h1:NbSheEEYHJ7i3ixzK3sjbqSGDJWnxyFXZblF3eUsNvo= -google.golang.org/genproto v0.0.0-20200618031413-b414f8b61790/go.mod h1:jDfRM7FcilCzHH/e9qn6dsT145K34l5v+OpcnNgKAAA= -google.golang.org/genproto v0.0.0-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-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-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-20210402141018-6c239bbf2bb1/go.mod h1:9lPAdzaEmUacj36I+k7YKbEc5CXzPIeORRgDAUOu28A= google.golang.org/genproto v0.0.0-20211118181313-81c1377c94b1 h1:b9mVrqYfq3P4bCdaLg1qtBnPzUYgglsIdjZkL/fQVOE= google.golang.org/genproto v0.0.0-20211118181313-81c1377c94b1/go.mod h1:5CzLGKJ67TSI2B9POpiiyGha0AjJvZIUgRMt1dSmuhc= 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.21.1/go.mod h1:oYelfM1adQP15Ek0mdvEgi9Df8B9CZIaU1084ijfRaM= google.golang.org/grpc v1.23.0/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg= google.golang.org/grpc v1.25.1/go.mod h1:c3i+UQWmh7LiEpx4sFZnkU36qjEYZ0imhYfXVyQciAY= -google.golang.org/grpc v1.26.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk= google.golang.org/grpc v1.27.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk= -google.golang.org/grpc v1.27.1/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk= -google.golang.org/grpc v1.28.0/go.mod h1:rpkK4SK4GF4Ach/+MFLZUBavHOvF2JJB5uozKKal+60= -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.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.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.1/go.mod h1:qjiiYl8FncCW8feJPdyg3v6XW24KsRHe+dy9BAGRRjU= -google.golang.org/grpc v1.38.0/go.mod h1:NREThFqKR1f3iQ6oBuvc5LadQuXVGo9rkm5ZGrQdJfM= google.golang.org/grpc v1.40.0/go.mod h1:ogyxbiOoUXAkP+4+xa6PZSE9DZgIHtSpzjDTB9KAK34= google.golang.org/grpc v1.41.0 h1:f+PlOh7QV4iIJkPrx5NQ7qaNGFQ3OTse67yaDHfju4E= google.golang.org/grpc v1.41.0/go.mod h1:U3l9uK9J0sini8mHphKoXyaqDA/8VyGnDee1zzIUK6k= @@ -567,17 +148,13 @@ google.golang.org/protobuf v1.21.0/go.mod h1:47Nbq4nVaFHyn7ilMalzfO3qCViNmqZ2kzi google.golang.org/protobuf v1.22.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= google.golang.org/protobuf v1.23.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= google.golang.org/protobuf v1.23.1-0.20200526195155-81db48ad09cc/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= -google.golang.org/protobuf v1.24.0/go.mod h1:r/3tXBNzIEhYS9I1OUVjXDlt8tc493IdKGjtUeSXeh4= google.golang.org/protobuf v1.25.0/go.mod h1:9JNX74DMeImyA3h4bdi1ymwjUzf21/xIlbajtzgsN7c= google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw= google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc= google.golang.org/protobuf v1.27.1 h1:SnqbnDw1V7RiZcXPx5MEeqPv2s79L9i7BJUlG/+RurQ= google.golang.org/protobuf v1.27.1/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc= +gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= -gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127 h1:qIbj1fsPNlZgppZ+VLlY7N33q108Sa+fhmuc+sWQYwY= -gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= -gopkg.in/errgo.v2 v2.1.0/go.mod h1:hNsd1EY+bozCKY1Ytp96fpM3vjJbqLJn88ws8XvfDNI= -gopkg.in/ini.v1 v1.62.0/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k= gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.2.3/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.2.8/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= @@ -587,12 +164,4 @@ gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b h1:h8qDotaEPuJATrMmW04NCwg7v22aHH28wwpauUhK9Oo= gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= -honnef.co/go/tools v0.0.0-20190106161140-3f1c8253044a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= -honnef.co/go/tools v0.0.0-20190418001031-e561f6794a2a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= honnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= -honnef.co/go/tools v0.0.1-2019.2.3/go.mod h1:a3bituU0lyd329TUQxRnasdCoJDkEUEAqEt0JzvZhAg= -honnef.co/go/tools v0.0.1-2020.1.3/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9vFzvIQ3k= -honnef.co/go/tools v0.0.1-2020.1.4/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9vFzvIQ3k= -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/sampler v1.3.0/go.mod h1:T1hPZKmBbMNahiBKFy5HrXp6adAjACjK9JXDnKaTXpA= diff --git a/server/go.mod b/server/go.mod index b64ee751d7ff..241c4d9e7782 100644 --- a/server/go.mod +++ b/server/go.mod @@ -18,7 +18,7 @@ require ( github.com/prometheus/client_golang v1.11.0 github.com/prometheus/client_model v0.2.0 github.com/soheilhy/cmux v0.1.5 - github.com/spf13/cobra v1.2.1 + github.com/spf13/cobra v1.4.0 github.com/stretchr/testify v1.7.0 github.com/tmc/grpc-websocket-proxy v0.0.0-20201229170055-e5319fda7802 github.com/xiang90/probing v0.0.0-20190116061207-43a291ad63a2 diff --git a/server/go.sum b/server/go.sum index 4f6800c21f30..33dc67b849df 100644 --- a/server/go.sum +++ b/server/go.sum @@ -1,46 +1,8 @@ cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= +cloud.google.com/go v0.34.0 h1:eOI3/cP2VTU6uZLDYAoic+eyzzB9YyGmJ7eIjl8rOPg= cloud.google.com/go v0.34.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= -cloud.google.com/go v0.38.0/go.mod h1:990N+gfupTy94rShfmMCWGDn0LpTmnzTp2qbd1dvSRU= -cloud.google.com/go v0.44.1/go.mod h1:iSa0KzasP4Uvy3f1mN/7PiObzGgflwredwwASm/v6AU= -cloud.google.com/go v0.44.2/go.mod h1:60680Gw3Yr4ikxnPRS/oxxkBccT6SA1yMk63TGekxKY= -cloud.google.com/go v0.45.1/go.mod h1:RpBamKRgapWJb87xiFSdk4g1CME7QZg3uwTez+TSTjc= -cloud.google.com/go v0.46.3/go.mod h1:a6bKKbmY7er1mI7TEI4lsAkts/mkhTSZK8w33B4RAg0= -cloud.google.com/go v0.50.0/go.mod h1:r9sluTvynVuxRIOHXQEHMFffphuXHOMZMycpNR5e6To= -cloud.google.com/go v0.52.0/go.mod h1:pXajvRH/6o3+F9jDHZWQ5PbGhn+o8w9qiu/CffaVdO4= -cloud.google.com/go v0.53.0/go.mod h1:fp/UouUEsRkN6ryDKNW/Upv/JBKnv6WDthjR6+vze6M= -cloud.google.com/go v0.54.0/go.mod h1:1rq2OEkV3YMf6n/9ZvGWI3GWw0VoqH/1x2nd8Is/bPc= -cloud.google.com/go v0.56.0/go.mod h1:jr7tqZxxKOVYizybht9+26Z/gUq7tiRzu+ACVAMbKVk= -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.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 h1:at8Tk2zUz63cLPR0JPWm5vp77pEZmzxEQBEfRKn1VV8= -cloud.google.com/go v0.81.0/go.mod h1:mk/AM35KwGk/Nm2YSeZbxXdrNK3KZOYHmLkOqC2V6E0= -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.4.0/go.mod h1:S8dzgnTigyfTmLBfrtrhyYhwRxG72rYxvftPBK2Dvzc= -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.8.0/go.mod h1:J5hqkt3O0uAFnINi6JXValWIb1v0goeZM77hZzJN/fQ= -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/firestore v1.1.0/go.mod h1:ulACoGHTpvq5r8rxGJ4ddJZBZqakUQqClKRT5SZwBmk= -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.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/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.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.10.0/go.mod h1:FLPqc6j+Ki4BU591ie1oL6qBQGu2Bl/tZ9ullr3+Kg0= -dmitri.shuralyov.com/gpu/mtl v0.0.0-20190408044501-666a987793e9/go.mod h1:H6x//7gZCb22OMCxBHrMx7a5I7Hp++hsVxbQ4BYO7hU= github.com/BurntSushi/toml v0.3.1 h1:WXkYYl6Yr3qBf1K79EBnL4mak0OimBfB0XUf9Vl28OQ= github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= -github.com/BurntSushi/xgb v0.0.0-20160522181843-27f122750802/go.mod h1:IVnqGOEym/WlBOVXweHU+Q+/VP0lqqI8lqeDx9IjBqo= github.com/OneOfOne/xxhash v1.2.2/go.mod h1:HSdplMjZKSmBqAxg5vPj2TmRDmfkzw+cTzAElWljhcU= github.com/alecthomas/template v0.0.0-20160405071501-a0175ee3bccc/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc= github.com/alecthomas/template v0.0.0-20190718012654-fb15b899a751/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc= @@ -48,15 +10,10 @@ github.com/alecthomas/units v0.0.0-20151022065526-2efee857e7cf/go.mod h1:ybxpYRF github.com/alecthomas/units v0.0.0-20190717042225-c3de453c63f4/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0= github.com/alecthomas/units v0.0.0-20190924025748-f65c72e2690d/go.mod h1:rBZYJk541a8SKzHPHnH3zbiI+7dagKZ0cgpgrD7Fyho= github.com/antihax/optional v1.0.0/go.mod h1:uupD/76wgC+ih3iEmQUL+0Ugr19nfwCT1kdvxnR2qWY= -github.com/armon/circbuf v0.0.0-20150827004946-bbbad097214e/go.mod h1:3U/XgcO3hCbHZ8TKRvWD2dDTCfh9M9ya+I9JpbB7O8o= -github.com/armon/go-metrics v0.0.0-20180917152333-f0300d1749da/go.mod h1:Q73ZrmVTwzkszR9V5SSuryQ31EELlFMUz1kKyl939pY= -github.com/armon/go-radix v0.0.0-20180808171621-7fddfc383310/go.mod h1:ufUuZ+zHj4x4TnLV4JWEpy2hxWSpsRywHrMgIH9cCH8= github.com/beorn7/perks v0.0.0-20180321164747-3a771d992973/go.mod h1:Dwedo/Wpr24TaqPxmxbtue+5NUziq4I4S80YR8gNf3Q= github.com/beorn7/perks v1.0.0/go.mod h1:KWe93zE9D1o94FZ5RNwFwVgaQK1VOXiVxmqh+CedLV8= github.com/beorn7/perks v1.0.1 h1:VlbKKnNfV8bJzeqoa4cOKqO6bYr3WgKZxO8Z16+hsOM= github.com/beorn7/perks v1.0.1/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6rlkpw= -github.com/bgentry/speakeasy v0.1.0/go.mod h1:+zsyZBPWlz7T6j88CTgSN5bM796AkVf0kBD4zp0CCIs= -github.com/bketelsen/crypt v0.0.4/go.mod h1:aI6NrJ0pMGgvZKL1iVgXLnfIFJtfV+bKCoqOes/6LfM= github.com/cenkalti/backoff/v4 v4.1.1 h1:G2HAfAmvm/GcKan2oOQpBXOd2tT2G57ZnZGWa1PxPBQ= github.com/cenkalti/backoff/v4 v4.1.1/go.mod h1:scbssz8iZGpm3xbr14ovlUdkxfGXNInqkPWOWmG2CLw= github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU= @@ -67,12 +24,8 @@ github.com/cespare/xxhash v1.1.0 h1:a6HrQnmkObjyL+Gs60czilIUGqrzKutQD6XZog3p+ko= github.com/cespare/xxhash v1.1.0/go.mod h1:XrSqR1VqqWfGrhpAt58auRo0WTKS1nRRg3ghfAqPWnc= github.com/cespare/xxhash/v2 v2.1.1 h1:6MnRN8NT7+YBpUIWxHtefFZOKTAPgGjpQSxqLNn0+qY= github.com/cespare/xxhash/v2 v2.1.1/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= -github.com/chzyer/logex v1.1.10/go.mod h1:+Ywpsq7O8HXn0nuIou7OrIPyXbp3wmkHB+jjWRnGsAI= -github.com/chzyer/readline v0.0.0-20180603132655-2972be24d48e/go.mod h1:nSuG5e5PlCu98SY8svDHJxuZscDgtXS6KTTbou5AhLI= -github.com/chzyer/test v0.0.0-20180213035817-a1ea475d72b1/go.mod h1:Q3SI9o4m/ZMnBNeIyt5eFwwo7qiLfzFZmjNmxjkiQlU= github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw= 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/xds/go v0.0.0-20210312221358-fbca930ec8ed/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs= github.com/cncf/xds/go v0.0.0-20210805033703-aa0b78936158/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs= @@ -86,7 +39,7 @@ github.com/coreos/go-semver v0.3.0 h1:wkHLiw0WNATZnSG7epLsujiMCgPAc9xhjJ4tgnAxmf github.com/coreos/go-semver v0.3.0/go.mod h1:nnelYz7RCh+5ahJtPPxZlU+153eP4D4r3EedlOD2RNk= github.com/coreos/go-systemd/v22 v22.3.2 h1:D9/bQk5vlXQFZ6Kwuu6zaiXJ9oTPe68++AzAJc1DzSI= github.com/coreos/go-systemd/v22 v22.3.2/go.mod h1:Y58oyj3AT4RCenI/lSvhwexgC+NSVTIJ3seZv2GcEnc= -github.com/cpuguy83/go-md2man/v2 v2.0.0/go.mod h1:maD7wRr/U5Z6m/iR4s+kqSMx2CaBsrgA7czyZG/E6dU= +github.com/cpuguy83/go-md2man/v2 v2.0.1/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o= github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E= github.com/creack/pty v1.1.11/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E= github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= @@ -97,20 +50,14 @@ github.com/dustin/go-humanize v1.0.0/go.mod h1:HtrtbFcZ19U5GC7JDqmcUSB87Iq5E25Kn 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.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.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.10-0.20210907150352-cf90f659a021/go.mod h1:AFq3mo9L8Lqqiid3OhADV3RfLJnjiw63cSpi+fDTRC0= github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c= -github.com/fatih/color v1.7.0/go.mod h1:Zm6kSWBoL9eyXnKyktHP6abPY2pDugNf5KwzbycvMj4= -github.com/fsnotify/fsnotify v1.4.9/go.mod h1:znqG4EE+3YCdAaPaxE2ZRY/06pZUdp0tY4IgpuI1SZQ= github.com/getsentry/raven-go v0.2.0 h1:no+xWJRb5ZI7eE8TWgIq1jLulQiIoLG0IfYxv5JYMGs= github.com/getsentry/raven-go v0.2.0/go.mod h1:KungGk8q33+aIAZUIVWZDr2OfAEBsO49PX4NzFV5kcQ= github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04= -github.com/go-gl/glfw v0.0.0-20190409004039-e6da0acd62b1/go.mod h1:vR7hzQXu2zJy9AVAgeJqvqgH9Q5CA+iKCZ2gyEVpxRU= -github.com/go-gl/glfw/v3.3/glfw v0.0.0-20191125211704-12ad95a8df72/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8= -github.com/go-gl/glfw/v3.3/glfw v0.0.0-20200222043503-6f7a984d4dc4/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8= github.com/go-kit/kit v0.8.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as= github.com/go-kit/kit v0.9.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as= github.com/go-kit/log v0.1.0/go.mod h1:zbhenjAZHb184qTLMA9ZjW7ThYL0H2mk7Q6pNt4vbaY= @@ -126,25 +73,13 @@ github.com/gogo/protobuf v1.3.2/go.mod h1:P1XiOD3dCwIKUDQYPy72D8LYyHL2YPYrpS2s69 github.com/golang-jwt/jwt v3.2.2+incompatible h1:IfV12K8xAKAnZqdXVzCZ+TOjboZ2keLg81eXfW3O+oY= github.com/golang-jwt/jwt v3.2.2+incompatible/go.mod h1:8pz2t5EyA70fFQQSrl6XZXzqecmYZeUEB8OUGHkxJ+I= github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q= -github.com/golang/groupcache v0.0.0-20190702054246-869f871628b6/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= -github.com/golang/groupcache v0.0.0-20191227052852-215e87163ea7/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= -github.com/golang/groupcache v0.0.0-20200121045136-8c9f03a8e57e/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da h1:oI5xCqsCo564l8iNU+DwB5epxmsaqB+rhGL0m5jtYqE= github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= github.com/golang/mock v1.1.1/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A= -github.com/golang/mock v1.2.0/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A= -github.com/golang/mock v1.3.1/go.mod h1:sBzyDLLjw3U8JLTeZvSv8jJB+tU5PVekmnlKIyFUx0Y= -github.com/golang/mock v1.4.0/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.4/go.mod h1:l3mdAwkq5BuhzHwde/uurv3sEJeZMXNpwsxVWU71h+4= -github.com/golang/mock v1.5.0/go.mod h1:CWnOUgYIOo4TcNZ0wHX3YZCqsaM1I1Jvs6v3mP3KVu8= github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= github.com/golang/protobuf v1.3.1/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= github.com/golang/protobuf v1.3.2/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= github.com/golang/protobuf v1.3.3/go.mod h1:vzj43D7+SQXF/4pzW/hwtAqwc6iTitCiVSaWz5lYuqw= -github.com/golang/protobuf v1.3.4/go.mod h1:vzj43D7+SQXF/4pzW/hwtAqwc6iTitCiVSaWz5lYuqw= -github.com/golang/protobuf v1.3.5/go.mod h1:6O5/vntMXwX2lRkT1hjjk0nAC1IDOTvTlVgjlRvqsdk= github.com/golang/protobuf v1.4.0-rc.1/go.mod h1:ceaxUfeHdC40wWswd/P6IGgMaK3YpKi5j83Wpe3EHw8= github.com/golang/protobuf v1.4.0-rc.1.0.20200221234624-67d41d38c208/go.mod h1:xKAWHe0F5eneWXFV3EuXVDTCmh+JuBKY0li0aMyXATA= github.com/golang/protobuf v1.4.0-rc.2/go.mod h1:LlEzMj4AhA7rCAGe4KMBDvJI+AwstrUpVNzEA03Pprs= @@ -154,46 +89,21 @@ 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.3/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI= 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/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY= -github.com/google/btree v0.0.0-20180813153112-4030bb1f1f0c/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ= -github.com/google/btree v1.0.0/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ= github.com/google/btree v1.0.1 h1:gK4Kx5IaGY9CD5sPJ36FHiBJ6ZXl0kilRiiCj+jdYp4= github.com/google/btree v1.0.1/go.mod h1:xXMiIv4Fb/0kKde4SpL7qlzvu5cMJDRkFDxJfI9uaxA= github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M= github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= -github.com/google/go-cmp v0.4.1/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.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.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.6 h1:BKbKCqvP6I+rmFHt06ZmyQtvB8xAkWdhFyr0ZUNZcxQ= github.com/google/go-cmp v0.5.6/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= -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.1.0/go.mod h1:y5Zk1BBys9G+gd6Jrk0W3cC1+ELVxBWuIGO+w/tUAp0= -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-20191218002539-d4f498aebedc/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= -github.com/google/pprof v0.0.0-20200212024743-f11f1df84d12/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-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/renameio v0.1.0/go.mod h1:KWCgfxg9yswjAJkECMjeO8J8rahYeXnNhOm40UhjYkI= github.com/google/uuid v1.1.2/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= -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/gopherjs/gopherjs v0.0.0-20181017120253-0766667cb4d1/go.mod h1:wJfORRmW1u3UXTncJ5qlYoELFm8eSnnEO6hX4iZ3EWY= github.com/gorilla/websocket v1.4.2 h1:+/TMaTYc4QFitKJxsQ7Yye35DkWvkdLcvGKqM+x0Ufc= github.com/gorilla/websocket v1.4.2/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE= github.com/grpc-ecosystem/go-grpc-middleware v1.3.0 h1:+9834+KizmvFV7pXQGSXQTsaWhq2GjuNUt0aUU0YBYw= @@ -202,28 +112,6 @@ github.com/grpc-ecosystem/go-grpc-prometheus v1.2.0 h1:Ovs26xHkKqVztRpIrF/92Bcuy github.com/grpc-ecosystem/go-grpc-prometheus v1.2.0/go.mod h1:8NvIoxWQoOIhqOTXgfV/d3M/q6VIi02HzZEHgUlZvzk= github.com/grpc-ecosystem/grpc-gateway v1.16.0 h1:gmcG1KaJ57LophUzW0Hy8NmPhnMZb4M0+kPpLofRdBo= github.com/grpc-ecosystem/grpc-gateway v1.16.0/go.mod h1:BDjrQk3hbvj6Nolgz8mAMFbcEtjT1g+wF4CSlocrBnw= -github.com/hashicorp/consul/api v1.1.0/go.mod h1:VmuI/Lkw1nC05EYQWNKwWGbkg+FbDBtguAZLlVdkD9Q= -github.com/hashicorp/consul/sdk v0.1.1/go.mod h1:VKf9jXwCTEY1QZP2MOLRhb5i/I/ssyNV1vwHyQBF0x8= -github.com/hashicorp/errwrap v1.0.0/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4= -github.com/hashicorp/go-cleanhttp v0.5.1/go.mod h1:JpRdi6/HCYpAwUzNwuwqhbovhLtngrth3wmdIIUrZ80= -github.com/hashicorp/go-immutable-radix v1.0.0/go.mod h1:0y9vanUI8NX6FsYoO3zeMjhV/C5i9g4Q3DwcSNZ4P60= -github.com/hashicorp/go-msgpack v0.5.3/go.mod h1:ahLV/dePpqEmjfWmKiqvPkv/twdG7iPBM1vqhUKIvfM= -github.com/hashicorp/go-multierror v1.0.0/go.mod h1:dHtQlpGsu+cZNNAkkCN/P3hoUDHhCYQXV3UM06sGGrk= -github.com/hashicorp/go-rootcerts v1.0.0/go.mod h1:K6zTfqpRlCUIjkwsN4Z+hiSfzSTQa6eBIzfwKfwNnHU= -github.com/hashicorp/go-sockaddr v1.0.0/go.mod h1:7Xibr9yA9JjQq1JpNB2Vw7kxv8xerXegt+ozgdvDeDU= -github.com/hashicorp/go-syslog v1.0.0/go.mod h1:qPfqrKkXGihmCqbJM2mZgkZGvKG1dFdvsLplgctolz4= -github.com/hashicorp/go-uuid v1.0.0/go.mod h1:6SBZvOh/SIDV7/2o3Jml5SYk/TvGqwFJ/bN7x4byOro= -github.com/hashicorp/go-uuid v1.0.1/go.mod h1:6SBZvOh/SIDV7/2o3Jml5SYk/TvGqwFJ/bN7x4byOro= -github.com/hashicorp/go.net v0.0.1/go.mod h1:hjKkEWcCURg++eb33jQU7oqQcI9XDCnUzHA0oac0k90= -github.com/hashicorp/golang-lru v0.5.0/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8= -github.com/hashicorp/golang-lru v0.5.1/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8= -github.com/hashicorp/hcl v1.0.0/go.mod h1:E5yfLk+7swimpb2L/Alb/PJmXilQ/rhwaUYs4T20WEQ= -github.com/hashicorp/logutils v1.0.0/go.mod h1:QIAnNjmIWmVIIkWDTG1z5v++HQmx9WQRO+LraFDTW64= -github.com/hashicorp/mdns v1.0.0/go.mod h1:tL+uN++7HEJ6SQLQ2/p+z2pH24WQKWjBPkE0mNTz8vQ= -github.com/hashicorp/memberlist v0.1.3/go.mod h1:ajVTdAv/9Im8oMAAj5G31PhhMCZJV2pPBoIllUwCN7I= -github.com/hashicorp/serf v0.8.2/go.mod h1:6hOLApaqBFA1NXqRQAsxw9QxuDEvNxSQRwA/JwenrHc= -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/inconshreveable/mousetrap v1.0.0 h1:Z8tu5sraLXCXIcARxBp/8cbvlwVa7Z1NHg9XEKhtSvM= github.com/inconshreveable/mousetrap v1.0.0/go.mod h1:PxqpIevigyE2G7u3NXJIT2ANytuPF1OarO4DADm73n8= github.com/jonboulle/clockwork v0.2.2 h1:UOGuzwb1PwsrDAObMuhUnj0p5ULPj8V/xJ7Kx9qUBdQ= @@ -232,9 +120,6 @@ github.com/jpillora/backoff v1.0.0/go.mod h1:J/6gKK9jxlEcS3zixgDgUAsiuZ7yrSoa/FX github.com/json-iterator/go v1.1.6/go.mod h1:+SdeFBvtyEkXs7REEP0seUULqWtbJapLOCVDaaPEHmU= github.com/json-iterator/go v1.1.10/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4= github.com/json-iterator/go v1.1.11/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4= -github.com/jstemmer/go-junit-report v0.0.0-20190106144839-af01ea7f8024/go.mod h1:6v2b51hI/fHJwM22ozAgKL4VKDeJcHhJFhtBdhmNjmU= -github.com/jstemmer/go-junit-report v0.9.1/go.mod h1:Brl9GWCQeLvo8nXZwPNNblvFj/XSXhF0NWZEnDohbsk= -github.com/jtolds/gls v4.20.0+incompatible/go.mod h1:QJZ7F/aHp+rZTRtaJ1ow/lLfFfVYBRgL+9YlvaHOwJU= github.com/julienschmidt/httprouter v1.2.0/go.mod h1:SYymIcj16QtmaHHD7aYtjjsJG7VTCxuUUipMqKk8s4w= github.com/julienschmidt/httprouter v1.3.0/go.mod h1:JR6WtHb+2LUe8TCKY3cZOxFyyO8IZAc4RVcycCCAKdM= github.com/kisielk/errcheck v1.2.0/go.mod h1:/BMXB+zMLi60iA8Vv6Ksmxu/1UDYcXs4uQLJ+jE2L00= @@ -242,7 +127,6 @@ github.com/kisielk/errcheck v1.5.0/go.mod h1:pFxgyoBC7bSaBwPgfKdkLd5X25qrDl4LWUI github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck= github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= github.com/konsorten/go-windows-terminal-sequences v1.0.3/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= -github.com/kr/fs v0.1.0/go.mod h1:FFnZGqtBN9Gxj7eW1uZ42v5BccTP0vu6NEaFoC2HwRg= github.com/kr/logfmt v0.0.0-20140226030751-b84e30acd515/go.mod h1:+0opPa2QZZtGFBFZlji/RkVcI2GknAs/DXo4wKdlNEc= github.com/kr/pretty v0.1.0 h1:L/CwN0zerZDmRFUapSPitk6f+Q3+0za1rQkzVuMiMFI= github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo= @@ -250,20 +134,8 @@ github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY= github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE= -github.com/magiconair/properties v1.8.5/go.mod h1:y3VJvCyxH9uVvJTWEGAELF3aiYNyPKd5NZ3oSwXrF60= -github.com/mattn/go-colorable v0.0.9/go.mod h1:9vuHe8Xs5qXnSaW/c/ABM9alt+Vo+STaOChaDxuIBZU= -github.com/mattn/go-isatty v0.0.3/go.mod h1:M+lRXTBqGeGNdLjl/ufCoiOlB5xdOkqRJdNxMWT7Zi4= github.com/matttproud/golang_protobuf_extensions v1.0.1 h1:4hp9jkHxhMHkqkrB3Ix0jegS5sx/RkqARlsWZ6pIwiU= github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0= -github.com/miekg/dns v1.0.14/go.mod h1:W1PPwlIAgtquWBMBEV9nkV9Cazfe8ScdGz/Lj7v3Nrg= -github.com/mitchellh/cli v1.0.0/go.mod h1:hNIlj7HEI86fIcpObd7a0FcrxTWetlwJDGcceTlRvqc= -github.com/mitchellh/go-homedir v1.0.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0= -github.com/mitchellh/go-testing-interface v1.0.0/go.mod h1:kRemZodwjscx+RGhAo8eIhFbs2+BFgRtFPeD/KE+zxI= -github.com/mitchellh/gox v0.4.0/go.mod h1:Sd9lOJ0+aimLBi73mGofS1ycjY8lL3uZM3JPS42BGNg= -github.com/mitchellh/iochan v1.0.0/go.mod h1:JwYml1nuB7xOzsp52dPpHFffvOCDupsG0QubkSMEySY= -github.com/mitchellh/mapstructure v0.0.0-20160808181253-ca63d7c062ee/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y= -github.com/mitchellh/mapstructure v1.1.2/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y= -github.com/mitchellh/mapstructure v1.4.1/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo= github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= github.com/modern-go/reflect2 v0.0.0-20180701023420-4b7aa43c6742/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0= @@ -271,16 +143,12 @@ github.com/modern-go/reflect2 v1.0.1/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3Rllmb github.com/mwitkow/go-conntrack v0.0.0-20161129095857-cc309e4a2223/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U= github.com/mwitkow/go-conntrack v0.0.0-20190716064945-2f068394615f/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U= github.com/opentracing/opentracing-go v1.1.0/go.mod h1:UkNAQd3GIcIGf0SeVgPpRdFStlNbqXla1AfSYxPUl2o= -github.com/pascaldekloe/goe v0.0.0-20180627143212-57f6aae5913c/go.mod h1:lzWF7FIEvWOWxwDKqyGYQf6ZUaNfKdP144TG7ZOy1lc= -github.com/pelletier/go-toml v1.9.3/go.mod h1:u1nR/EPcESfeI/szUZKdtJ0xRNbUoANCkoOuaOx1Y+c= github.com/pkg/errors v0.8.0/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4= github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= -github.com/pkg/sftp v1.10.1/go.mod h1:lYOWFsE0bwd1+KfKJaKeuokY15vzFx25BLbzYYoAxZI= github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= -github.com/posener/complete v1.1.1/go.mod h1:em0nMJCgc9GFtwrmVmEMR/ZL6WyhyjMBndrE9hABlRI= github.com/prometheus/client_golang v0.9.1/go.mod h1:7SWBe2y4D6OKWSNQJUaRYU/AaXPKyh/dDVn+NZz0KFw= github.com/prometheus/client_golang v1.0.0/go.mod h1:db9x61etRT2tGnBNRi70OPL5FsnadC4Ky3P0J6CfImo= github.com/prometheus/client_golang v1.7.1/go.mod h1:PY5Wy2awLA44sXw4AOSfFBetzPP4j5+D6mVACh+pe2M= @@ -301,56 +169,35 @@ github.com/prometheus/procfs v0.1.3/go.mod h1:lV6e/gmhEcM9IjHGsFOCxxuZ+z1YqCvr4O github.com/prometheus/procfs v0.6.0 h1:mxy4L2jP6qMonqmq+aTtOx1ifVWUgG/TAmntgbh3xv4= github.com/prometheus/procfs v0.6.0/go.mod h1:cz+aTbrPOrUb4q7XlbU9ygM+/jj0fzG6c1xBZuNvfVA= github.com/rogpeppe/fastuuid v1.2.0/go.mod h1:jVj6XXZzXRy/MSR5jhDC/2q6DgLz+nrA6LYCDYWNEvQ= -github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4= -github.com/russross/blackfriday/v2 v2.0.1/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= -github.com/ryanuber/columnize v0.0.0-20160712163229-9b3edd62028f/go.mod h1:sm1tb6uqfes/u+d4ooFouqFdy9/2g9QGwK3SQygK0Ts= -github.com/sean-/seed v0.0.0-20170313163322-e2103e2c3529/go.mod h1:DxrIzT+xaE7yg65j358z/aeFdxmN0P9QXhEzd20vsDc= -github.com/shurcooL/sanitized_anchor_name v1.0.0/go.mod h1:1NzhyTcUVG4SuEtjjoZeVRXNmyL/1OwPU0+IJeTBvfc= +github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= github.com/sirupsen/logrus v1.2.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPxbbu5VWo= github.com/sirupsen/logrus v1.4.2/go.mod h1:tLMulIdttU9McNUspp0xgXVQah82FyeX6MwdIuYE2rE= github.com/sirupsen/logrus v1.6.0/go.mod h1:7uNnSEd1DgxDLC74fIahvMZmmYsHGZGEOFrfsX/uA88= github.com/sirupsen/logrus v1.8.1 h1:dJKuHgqk1NNQlqoA6BTlM1Wf9DOH3NBjQyu0h9+AZZE= github.com/sirupsen/logrus v1.8.1/go.mod h1:yWOB1SBYBC5VeMP7gHvWumXLIWorT60ONWic61uBYv0= -github.com/smartystreets/assertions v0.0.0-20180927180507-b2de0cb4f26d/go.mod h1:OnSkiWE9lh6wB0YB77sQom3nweQdgAjqCqsofrRNTgc= -github.com/smartystreets/goconvey v1.6.4/go.mod h1:syvi0/a8iFYH4r/RixwvyeAJjdLS9QV7WQ/tjFTllLA= github.com/soheilhy/cmux v0.1.5 h1:jjzc5WVemNEDTLwv9tlmemhC73tI08BNOIGwBOo10Js= github.com/soheilhy/cmux v0.1.5/go.mod h1:T7TcVDs9LWfQgPlPsdngu6I6QIoyIFZDDC6sNE1GqG0= github.com/spaolacci/murmur3 v0.0.0-20180118202830-f09979ecbc72/go.mod h1:JwIasOWyU6f++ZhiEuf87xNszmSA2myDM2Kzu9HwQUA= -github.com/spf13/afero v1.6.0/go.mod h1:Ai8FlHk4v/PARR026UzYexafAt9roJ7LcLMAmO6Z93I= -github.com/spf13/cast v1.3.1/go.mod h1:Qx5cxh0v+4UWYiBimWS+eyWzqEqokIECu5etghLkUJE= -github.com/spf13/cobra v1.2.1 h1:+KmjbUw1hriSNMF55oPrkZcb27aECyrj8V2ytv7kWDw= -github.com/spf13/cobra v1.2.1/go.mod h1:ExllRjgxM/piMAM+3tAZvg8fsklGAf3tPfi+i8t68Nk= -github.com/spf13/jwalterweatherman v1.1.0/go.mod h1:aNWZUN0dPAAO/Ljvb5BEdw96iTZ0EXowPYD95IqWIGo= +github.com/spf13/cobra v1.4.0 h1:y+wJpx64xcgO1V+RcnwW0LEHxTKRi2ZDPSBjWnrg88Q= +github.com/spf13/cobra v1.4.0/go.mod h1:Wo4iy3BUC+X2Fybo0PDqwJIv3dNRiZLHQymsfxlB84g= github.com/spf13/pflag v1.0.5 h1:iy+VFUOCP1a+8yFto/drg2CJ5u0yRoB7fZw3DKv/JXA= github.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg= -github.com/spf13/viper v1.8.1/go.mod h1:o0Pch8wJ9BVSWGQMbra6iw0oQ5oktSIBaujf1rJH9Ns= github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= 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.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA= -github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/stretchr/testify v1.7.0 h1:nwc3DEeHmmLAfoZucVR881uASk0Mfjw8xYJ99tb5CcY= github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= -github.com/subosito/gotenv v1.2.0/go.mod h1:N0PQaV/YGNqwC0u51sEeR/aUtSLEXKX9iv69rRypqCw= github.com/tmc/grpc-websocket-proxy v0.0.0-20201229170055-e5319fda7802 h1:uruHq4dN7GR16kFc5fp3d1RIYzJW5onx8Ybykw2YQFA= github.com/tmc/grpc-websocket-proxy v0.0.0-20201229170055-e5319fda7802/go.mod h1:ncp9v5uamzpCO7NfCPTXjqaC+bZgJeR0sMTm6dMHP7U= github.com/xiang90/probing v0.0.0-20190116061207-43a291ad63a2 h1:eY9dn8+vbi4tKz5Qo6v2eYzo7kUS51QINcR5jNpbZS8= github.com/xiang90/probing v0.0.0-20190116061207-43a291ad63a2/go.mod h1:UETIi67q53MR2AWcXfiuqkDkRtnGDLqkBTpCHuJHxtU= -github.com/yuin/goldmark v1.1.25/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= -github.com/yuin/goldmark v1.1.32/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= go.etcd.io/bbolt v1.3.6 h1:/ecaJf0sk1l4l6V4awd65v2C3ILy7MSj+s/x1ADCIMU= go.etcd.io/bbolt v1.3.6/go.mod h1:qXsaaIqmgQH0T+OPdb99Bf+PKfBBQVAdyD6TY9G8XM4= -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.2/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.5/go.mod h1:5pWMHQbX5EPX2/62yrJeAkowc+lfs/XD7Uxpq3pI6kk= -go.opencensus.io v0.23.0/go.mod h1:XItmlyltB5F7CS4xOC1DcqMoFqwtC6OG2xF7mCv7P7E= go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.26.1 h1:puWrOArBwWlr5dq6vyZ6fKykHyS8JgMIVhTBA8XsGuU= go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.26.1/go.mod h1:4wsfAAW5N9wUHM0QTmZS8z7fvYZ1rv3m+sVeSpf8NhU= go.opentelemetry.io/otel v1.1.0/go.mod h1:7cww0OW51jQ8IaZChIEdqLwgh+44+7uiTdWsAL0wQpA= @@ -381,162 +228,62 @@ go.uber.org/zap v1.10.0/go.mod h1:vwi/ZaCAaUcBkycHslxD9B2zi4UTXhF60s6SWpuDF0Q= go.uber.org/zap v1.17.0 h1:MTjgFu6ZLKvY6Pvaqk97GlxNBuMpV4Hy/3P6tRGlI2U= go.uber.org/zap v1.17.0/go.mod h1:MXVU+bhUf/A7Xi2HNOnopQOrmycQ5Ih87HtOu4q5SSo= golang.org/x/crypto v0.0.0-20180904163835-0709b304e793/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= -golang.org/x/crypto v0.0.0-20181029021203-45a5f77698d3/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= -golang.org/x/crypto v0.0.0-20190510104115-cbcb75029529/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= -golang.org/x/crypto v0.0.0-20190605123033-f99c8df09eb5/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= -golang.org/x/crypto v0.0.0-20190820162420-60c769a6c586/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= golang.org/x/crypto v0.0.0-20210513164829-c07d793c2f9a h1:kr2P4QFmQr29mSLA43kwrOcgcReGTfbE9N577tCTuBc= golang.org/x/crypto v0.0.0-20210513164829-c07d793c2f9a/go.mod h1:P+XmwS30IXTQdn5tA2iutPOUgjI07+tq3H3K9MVA1s8= golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= -golang.org/x/exp v0.0.0-20190306152737-a1d7652674e8/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= -golang.org/x/exp v0.0.0-20190510132918-efd6b22b2522/go.mod h1:ZjyILWgesfNpC6sMxTJOJm9Kp84zZh5NQWvqDGG3Qr8= -golang.org/x/exp v0.0.0-20190829153037-c13cbed26979/go.mod h1:86+5VVa7VpoJ4kLfm080zCjGlMRFzhUhsZKEZO7MGek= -golang.org/x/exp v0.0.0-20191030013958-a1ab85dbe136/go.mod h1:JXzH8nQsPlswgeRAPE3MuO9GYsAcnJvJ4vnMwN/5qkY= -golang.org/x/exp v0.0.0-20191129062945-2f5052295587/go.mod h1:2RIsYlXP63K8oxa1u096TMicItID8zy7Y6sNkU49FU4= -golang.org/x/exp v0.0.0-20191227195350-da58074b4299/go.mod h1:2RIsYlXP63K8oxa1u096TMicItID8zy7Y6sNkU49FU4= -golang.org/x/exp v0.0.0-20200119233911-0405dc783f0a/go.mod h1:2RIsYlXP63K8oxa1u096TMicItID8zy7Y6sNkU49FU4= -golang.org/x/exp v0.0.0-20200207192155-f17229e696bd/go.mod h1:J/WKrq2StrnmMY6+EHIKF9dgMWnmCNThgcyBT1FY9mM= -golang.org/x/exp v0.0.0-20200224162631-6cc2880d07d6/go.mod h1:3jZMyOhIsHpP37uCMkUooju7aAi5cS1Q23tOzKc+0MU= -golang.org/x/image v0.0.0-20190227222117-0694c2d4d067/go.mod h1:kZ7UVZpmo3dzQBMxlp+ypCbDeSB+sBbTgSJuh5dn5js= -golang.org/x/image v0.0.0-20190802002840-cff245a6509b/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0= golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE= golang.org/x/lint v0.0.0-20190227174305-5b3e6a55c961/go.mod h1:wehouNa3lNwaWXcvxsM5YxQ5yQlVC4a0KAMCusXpPoU= -golang.org/x/lint v0.0.0-20190301231843-5614ed5bae6f/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE= golang.org/x/lint v0.0.0-20190313153728-d0100b6bd8b3/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= -golang.org/x/lint v0.0.0-20190409202823-959b441ac422/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= -golang.org/x/lint v0.0.0-20190909230951-414d861bb4ac/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= -golang.org/x/lint v0.0.0-20190930215403-16217165b5de/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= -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-20200302205851-738671d3881b/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY= -golang.org/x/lint v0.0.0-20201208152925-83fdc39ff7b5/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-20190719004257-d2bd2a29d028/go.mod h1:E/iHnbuqvinMTCcRqshq8CkpyQDoeVncDDYHnLhea+o= -golang.org/x/mod v0.0.0-20190513183733-4bf6d317e70e/go.mod h1:mXi4GBBbnImb6dmsKGUJ2LatrhH/nqhxcFungHvyanc= -golang.org/x/mod v0.1.0/go.mod h1:0QHyrYULN0/3qlju5TqG8bIK38QM8yzMo5ekMj3DlcY= -golang.org/x/mod v0.1.1-0.20191105210325-c90efee705ee/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.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/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-20181023162649-9b4f9f5ad519/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20181114220301-adae6a3d119a/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= -golang.org/x/net v0.0.0-20181201002055-351d144fa1fc/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20190108225652-1e06a53dbb7e/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20190213061140-3a22650c66bd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= -golang.org/x/net v0.0.0-20190501004415-9ce7a6920f09/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= -golang.org/x/net v0.0.0-20190503192946-f4e77d36d62c/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= -golang.org/x/net v0.0.0-20190603091049-60506f45cf65/go.mod h1:HSz+uSET+XFnRR8LxR5pz3Of3rY3CfYBVs4xY44aLks= golang.org/x/net v0.0.0-20190613194153-d28f0bde5980/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= -golang.org/x/net v0.0.0-20190628185345-da137c7871d7/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= -golang.org/x/net v0.0.0-20190724013045-ca1201d0de80/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= -golang.org/x/net v0.0.0-20191209160850-c0dbc17a3553/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= -golang.org/x/net v0.0.0-20200114155413-6afb5195e5aa/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= -golang.org/x/net v0.0.0-20200202094626-16171245cfb2/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= -golang.org/x/net v0.0.0-20200222125558-5a598a2470a0/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20200226121028-0de0cce0169b/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= -golang.org/x/net v0.0.0-20200301022130-244492dfa37a/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= -golang.org/x/net v0.0.0-20200324143707-d3edc9973b7e/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= -golang.org/x/net v0.0.0-20200501053045-e0ff5e5a1de5/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= -golang.org/x/net v0.0.0-20200506145744-7e3656a0809f/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= -golang.org/x/net v0.0.0-20200513185701-a91f0712d120/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= -golang.org/x/net v0.0.0-20200520182314-0ba52f642ac2/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= golang.org/x/net v0.0.0-20200625001655-4c5254603344/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-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-20201202161906-c7110b5ffcbb/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-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-20220105145211-5b0dc2dfae98 h1:+6WJMRLHlD7X7frgp7TUZ36RnQzSf9wVVTNakEp+nqY= golang.org/x/net v0.0.0-20220105145211-5b0dc2dfae98/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= 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-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-20200107190931-bf48bf16ab8d h1:TzXSXBo42m9gQenoE3b9BGiEpg5IG2JkU5FkPIawgtw= 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-20210402161424-2e8d93401602 h1:0Ja1LBD+yisY6RWM/BH7TJVXWsSjs2VwBSmvSX4HdBc= -golang.org/x/oauth2 v0.0.0-20210402161424-2e8d93401602/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= 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-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.0.0-20190227155943-e225da77a7e6/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.0.0-20200317015054-43a5402ce75a/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.0.0-20200625203802-6e8e738ad208/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-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sys v0.0.0-20180823144017-11551d06cbcc/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= -golang.org/x/sys v0.0.0-20181026203630-95b1ffbd15a5/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20181116152217-5ac8a444bdc5/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= -golang.org/x/sys v0.0.0-20190312061237-fead79001313/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190422165155-953cdadca894/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20190502145724-3ef323f4f1fd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20190507160741-ecd444e8653b/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20190606165138-5da285871e9c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20190624142023-c5567b49c5d0/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20190726091711-fc99dfbffb4e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20191001151750-bb3f8db39f24/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20191005200804-aed5e4c7ecf9/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20191026070338-33540a1f6037/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20191204072324-ce4227a45e2e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20191228213918-04cbcbbfeed8/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200106162015-b016eb3dc98e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200113162924-86b910548bc1/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200122134326-e047566fdf82/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200202164722-d101bd2416d5/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200212091648-12a6c2dcc1e4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200223170610-d5e6a3e2c0ae/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200302150141-5c8b2ff67527/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200331124033-c3d80250170d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200501052902-10377860bb8e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200511232937-7e40ca221e25/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200515095857-1151b9dac4a9/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200523222454-059865788121/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-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-20200923182605-d9f96fdee20d/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-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-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-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-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-20210423185535-09eb48e85fd7/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210510120138-977fb7262007/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= @@ -545,19 +292,13 @@ golang.org/x/sys v0.0.0-20210603125802-9665404d3644/go.mod h1:oPkhp1MJrh7nUepCBc golang.org/x/sys v0.0.0-20211123173158-ef496fb156ab h1:rfJ1bsoJQQIAoAxTxB7bme+vHrNkRw8CqfsYh9w54cw= golang.org/x/sys v0.0.0-20211123173158-ef496fb156ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= -golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= -golang.org/x/text v0.3.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.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.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/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-20191024005414-555d28b269f0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.0.0-20210220033141-f8bda1e9f3ba h1:O8mE0/t419eoIwhTFpKVkHiTs/Igowgfkj25AcZrtiE= golang.org/x/time v0.0.0-20210220033141-f8bda1e9f3ba/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= @@ -565,151 +306,33 @@ golang.org/x/tools v0.0.0-20181030221726-6c7e314b6563/go.mod h1:n7NCudcB/nEzxVGm 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-20190311212946-11955173bddd/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= -golang.org/x/tools v0.0.0-20190312151545-0bb0c0a6e846/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= -golang.org/x/tools v0.0.0-20190312170243-e65039ee4138/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= -golang.org/x/tools v0.0.0-20190328211700-ab21143f2384/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= -golang.org/x/tools v0.0.0-20190425150028-36563e24a262/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q= -golang.org/x/tools v0.0.0-20190506145303-2d16b83fe98c/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q= golang.org/x/tools v0.0.0-20190524140312-2c0ae7006135/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q= -golang.org/x/tools v0.0.0-20190606124116-d0a3d012864b/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc= -golang.org/x/tools v0.0.0-20190621195816-6e04913cbbac/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc= -golang.org/x/tools v0.0.0-20190628153133-6cdbf07be9d0/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc= -golang.org/x/tools v0.0.0-20190816200558-6889da9d5479/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= -golang.org/x/tools v0.0.0-20190911174233-4f2ddba30aff/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= -golang.org/x/tools v0.0.0-20191012152004-8de300cfc20a/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= -golang.org/x/tools v0.0.0-20191112195655-aa38f8e97acc/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= -golang.org/x/tools v0.0.0-20191113191852-77e3bb0ad9e7/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= -golang.org/x/tools v0.0.0-20191115202509-3a792d9c32b2/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= -golang.org/x/tools v0.0.0-20191125144606-a911d9008d1f/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= -golang.org/x/tools v0.0.0-20191130070609-6e064ea0cf2d/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= -golang.org/x/tools v0.0.0-20191216173652-a0e659d51361/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= -golang.org/x/tools v0.0.0-20191227053925-7b8e75db28f4/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= -golang.org/x/tools v0.0.0-20200117161641-43d50277825c/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= -golang.org/x/tools v0.0.0-20200122220014-bf1340f18c4a/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= -golang.org/x/tools v0.0.0-20200130002326-2f3ba24bd6e7/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= -golang.org/x/tools v0.0.0-20200204074204-1cc6d1ef6c74/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= -golang.org/x/tools v0.0.0-20200207183749-b753a1ba74fa/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= -golang.org/x/tools v0.0.0-20200212150539-ea181f53ac56/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= -golang.org/x/tools v0.0.0-20200224181240-023911ca70b2/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= -golang.org/x/tools v0.0.0-20200227222343-706bc42d1f0d/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= -golang.org/x/tools v0.0.0-20200304193943-95d2e580d8eb/go.mod h1:o4KQGtdN14AW+yjsvvwRTJJuXz8XRtIHtEnmAXLyFUw= -golang.org/x/tools v0.0.0-20200312045724-11d5b4c81c7d/go.mod h1:o4KQGtdN14AW+yjsvvwRTJJuXz8XRtIHtEnmAXLyFUw= -golang.org/x/tools v0.0.0-20200331025713-a30bf2db82d4/go.mod h1:Sl4aGygMT6LrqrWclx+PTx3U+LnKx/seiNR+3G19Ar8= -golang.org/x/tools v0.0.0-20200501065659-ab2804fb9c9d/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= -golang.org/x/tools v0.0.0-20200512131952-2bc93b1c0c88/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= -golang.org/x/tools v0.0.0-20200515010526-7d3b6ebf133d/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= -golang.org/x/tools v0.0.0-20200618134242-20370b0cb4b2/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= golang.org/x/tools v0.0.0-20200619180055-7c47624df98f/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= -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-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-20210105154028-b0ab187a4818/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/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-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1 h1:go1bK/D/BFZV2I8cIQd1NKEZ+0owSTG1fDTci4IqFcE= golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= -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.8.0/go.mod h1:o4eAsZoiT+ibD93RtjEohWalFOjRDx6CVaqeizhEnKg= -google.golang.org/api v0.9.0/go.mod h1:o4eAsZoiT+ibD93RtjEohWalFOjRDx6CVaqeizhEnKg= -google.golang.org/api v0.13.0/go.mod h1:iLdEw5Ide6rF15KTC1Kkl0iskquN2gFfn9o9XIsbkAI= -google.golang.org/api v0.14.0/go.mod h1:iLdEw5Ide6rF15KTC1Kkl0iskquN2gFfn9o9XIsbkAI= -google.golang.org/api v0.15.0/go.mod h1:iLdEw5Ide6rF15KTC1Kkl0iskquN2gFfn9o9XIsbkAI= -google.golang.org/api v0.17.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE= -google.golang.org/api v0.18.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE= -google.golang.org/api v0.19.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE= -google.golang.org/api v0.20.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE= -google.golang.org/api v0.22.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE= -google.golang.org/api v0.24.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.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.44.0/go.mod h1:EBOGZqzyhtvMDoxwS97ctnh0zUmYY6CxqXsc1AvkYD8= google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM= +google.golang.org/appengine v1.4.0 h1:/wp5JvzpHIxhs/dumFmF7BXTf3Z+dd4uXta4kVyO508= 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.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.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-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-20190425155659-357c62f0e4bb/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= -google.golang.org/genproto v0.0.0-20190502173448-54afdca5d873/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= -google.golang.org/genproto v0.0.0-20190801165951-fa694d86fc64/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc= google.golang.org/genproto v0.0.0-20190819201941-24fa4b261c55/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc= -google.golang.org/genproto v0.0.0-20190911173649-1774047e7e51/go.mod h1:IbNlFCBrqXvoKpeg0TB2l7cyZUmoaFKYIwrEpbDKLA8= -google.golang.org/genproto v0.0.0-20191108220845-16a3f7862a1a/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= -google.golang.org/genproto v0.0.0-20191115194625-c23dd37a84c9/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= -google.golang.org/genproto v0.0.0-20191216164720-4f79533eabd1/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= -google.golang.org/genproto v0.0.0-20191230161307-f3c370f40bfb/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= -google.golang.org/genproto v0.0.0-20200115191322-ca5a22157cba/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= -google.golang.org/genproto v0.0.0-20200122232147-0452cf42e150/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= -google.golang.org/genproto v0.0.0-20200204135345-fa8e72b47b90/go.mod h1:GmwEX6Z4W5gMy59cAlVYjN9JhxgbQH6Gn+gFDQe2lzA= -google.golang.org/genproto v0.0.0-20200212174721-66ed5ce911ce/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= -google.golang.org/genproto v0.0.0-20200224152610-e50cd9704f63/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= -google.golang.org/genproto v0.0.0-20200228133532-8c2c7df3a383/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= -google.golang.org/genproto v0.0.0-20200305110556-506484158171/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= -google.golang.org/genproto v0.0.0-20200312145019-da6875a35672/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= -google.golang.org/genproto v0.0.0-20200331122359-1ee6d9798940/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= google.golang.org/genproto v0.0.0-20200423170343-7949de9c1215/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= -google.golang.org/genproto v0.0.0-20200430143042-b979b6f78d84/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= -google.golang.org/genproto v0.0.0-20200511104702-f5ebc3bea380/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= google.golang.org/genproto v0.0.0-20200513103714-09dca8ec2884/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= -google.golang.org/genproto v0.0.0-20200515170657-fc4c6c6a6587/go.mod h1:YsZOwe1myG/8QRHRsmBRE1LrgQY60beZKjly0O1fX9U= google.golang.org/genproto v0.0.0-20200526211855-cb27e3aa2013/go.mod h1:NbSheEEYHJ7i3ixzK3sjbqSGDJWnxyFXZblF3eUsNvo= -google.golang.org/genproto v0.0.0-20200618031413-b414f8b61790/go.mod h1:jDfRM7FcilCzHH/e9qn6dsT145K34l5v+OpcnNgKAAA= -google.golang.org/genproto v0.0.0-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-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-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-20210402141018-6c239bbf2bb1/go.mod h1:9lPAdzaEmUacj36I+k7YKbEc5CXzPIeORRgDAUOu28A= google.golang.org/genproto v0.0.0-20211118181313-81c1377c94b1 h1:b9mVrqYfq3P4bCdaLg1qtBnPzUYgglsIdjZkL/fQVOE= google.golang.org/genproto v0.0.0-20211118181313-81c1377c94b1/go.mod h1:5CzLGKJ67TSI2B9POpiiyGha0AjJvZIUgRMt1dSmuhc= 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.21.1/go.mod h1:oYelfM1adQP15Ek0mdvEgi9Df8B9CZIaU1084ijfRaM= google.golang.org/grpc v1.23.0/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg= google.golang.org/grpc v1.25.1/go.mod h1:c3i+UQWmh7LiEpx4sFZnkU36qjEYZ0imhYfXVyQciAY= -google.golang.org/grpc v1.26.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk= google.golang.org/grpc v1.27.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk= -google.golang.org/grpc v1.27.1/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk= -google.golang.org/grpc v1.28.0/go.mod h1:rpkK4SK4GF4Ach/+MFLZUBavHOvF2JJB5uozKKal+60= 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.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.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.1/go.mod h1:qjiiYl8FncCW8feJPdyg3v6XW24KsRHe+dy9BAGRRjU= 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.40.0/go.mod h1:ogyxbiOoUXAkP+4+xa6PZSE9DZgIHtSpzjDTB9KAK34= google.golang.org/grpc v1.41.0 h1:f+PlOh7QV4iIJkPrx5NQ7qaNGFQ3OTse67yaDHfju4E= google.golang.org/grpc v1.41.0/go.mod h1:U3l9uK9J0sini8mHphKoXyaqDA/8VyGnDee1zzIUK6k= @@ -721,7 +344,6 @@ google.golang.org/protobuf v1.21.0/go.mod h1:47Nbq4nVaFHyn7ilMalzfO3qCViNmqZ2kzi google.golang.org/protobuf v1.22.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= google.golang.org/protobuf v1.23.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= google.golang.org/protobuf v1.23.1-0.20200526195155-81db48ad09cc/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= -google.golang.org/protobuf v1.24.0/go.mod h1:r/3tXBNzIEhYS9I1OUVjXDlt8tc493IdKGjtUeSXeh4= google.golang.org/protobuf v1.25.0/go.mod h1:9JNX74DMeImyA3h4bdi1ymwjUzf21/xIlbajtzgsN7c= google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw= google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc= @@ -729,11 +351,8 @@ google.golang.org/protobuf v1.27.1 h1:SnqbnDw1V7RiZcXPx5MEeqPv2s79L9i7BJUlG/+Rur google.golang.org/protobuf v1.27.1/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc= gopkg.in/alecthomas/kingpin.v2 v2.2.6/go.mod h1:FMv+mEhP44yOT+4EoQTLFTRgOQ1FBLkstjWtayDeSgw= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= -gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15 h1:YR8cESwS4TdDjEe65xsg0ogRM/Nc3DYOhEAlW+xobZo= gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= -gopkg.in/errgo.v2 v2.1.0/go.mod h1:hNsd1EY+bozCKY1Ytp96fpM3vjJbqLJn88ws8XvfDNI= -gopkg.in/ini.v1 v1.62.0/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k= gopkg.in/natefinch/lumberjack.v2 v2.0.0 h1:1Lc07Kr7qY4U2YPouBjpCLxpiyxIVoxqXgkXLknAOE8= gopkg.in/natefinch/lumberjack.v2 v2.0.0/go.mod h1:l0ndWWf7gzL7RNwBG7wST/UCcT4T24xpD6X8LsfU/+k= gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= @@ -749,15 +368,7 @@ gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b h1:h8qDotaEPuJATrMmW04NCwg7v22aHH28wwpauUhK9Oo= gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= -honnef.co/go/tools v0.0.0-20190106161140-3f1c8253044a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= -honnef.co/go/tools v0.0.0-20190418001031-e561f6794a2a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= honnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= -honnef.co/go/tools v0.0.1-2019.2.3/go.mod h1:a3bituU0lyd329TUQxRnasdCoJDkEUEAqEt0JzvZhAg= -honnef.co/go/tools v0.0.1-2020.1.3/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9vFzvIQ3k= -honnef.co/go/tools v0.0.1-2020.1.4/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9vFzvIQ3k= -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/sampler v1.3.0/go.mod h1:T1hPZKmBbMNahiBKFy5HrXp6adAjACjK9JXDnKaTXpA= sigs.k8s.io/json v0.0.0-20211020170558-c049b76a60c6 h1:fD1pz4yfdADVNfFmcP2aBEtudwUQ1AlLnRBALr33v3s= sigs.k8s.io/json v0.0.0-20211020170558-c049b76a60c6/go.mod h1:p4QtZmO4uMYipTQNzagwnNoseA6OxSUutVw05NhYDRs= sigs.k8s.io/yaml v1.2.0 h1:kr/MCeFWJWTwyaHoR9c8EjH9OumOmoF9YGiZd7lFm/Q= diff --git a/tests/go.mod b/tests/go.mod index f2871f5004cb..6ddea1a12740 100644 --- a/tests/go.mod +++ b/tests/go.mod @@ -25,7 +25,7 @@ require ( github.com/grpc-ecosystem/grpc-gateway v1.16.0 github.com/prometheus/client_golang v1.11.0 github.com/soheilhy/cmux v0.1.5 - github.com/spf13/cobra v1.2.1 + github.com/spf13/cobra v1.4.0 github.com/spf13/pflag v1.0.5 github.com/stretchr/testify v1.7.0 go.etcd.io/bbolt v1.3.6 diff --git a/tests/go.sum b/tests/go.sum index 8c6fc404223d..e86ba267986c 100644 --- a/tests/go.sum +++ b/tests/go.sum @@ -1,46 +1,8 @@ cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= +cloud.google.com/go v0.34.0 h1:eOI3/cP2VTU6uZLDYAoic+eyzzB9YyGmJ7eIjl8rOPg= cloud.google.com/go v0.34.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= -cloud.google.com/go v0.38.0/go.mod h1:990N+gfupTy94rShfmMCWGDn0LpTmnzTp2qbd1dvSRU= -cloud.google.com/go v0.44.1/go.mod h1:iSa0KzasP4Uvy3f1mN/7PiObzGgflwredwwASm/v6AU= -cloud.google.com/go v0.44.2/go.mod h1:60680Gw3Yr4ikxnPRS/oxxkBccT6SA1yMk63TGekxKY= -cloud.google.com/go v0.45.1/go.mod h1:RpBamKRgapWJb87xiFSdk4g1CME7QZg3uwTez+TSTjc= -cloud.google.com/go v0.46.3/go.mod h1:a6bKKbmY7er1mI7TEI4lsAkts/mkhTSZK8w33B4RAg0= -cloud.google.com/go v0.50.0/go.mod h1:r9sluTvynVuxRIOHXQEHMFffphuXHOMZMycpNR5e6To= -cloud.google.com/go v0.52.0/go.mod h1:pXajvRH/6o3+F9jDHZWQ5PbGhn+o8w9qiu/CffaVdO4= -cloud.google.com/go v0.53.0/go.mod h1:fp/UouUEsRkN6ryDKNW/Upv/JBKnv6WDthjR6+vze6M= -cloud.google.com/go v0.54.0/go.mod h1:1rq2OEkV3YMf6n/9ZvGWI3GWw0VoqH/1x2nd8Is/bPc= -cloud.google.com/go v0.56.0/go.mod h1:jr7tqZxxKOVYizybht9+26Z/gUq7tiRzu+ACVAMbKVk= -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.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 h1:at8Tk2zUz63cLPR0JPWm5vp77pEZmzxEQBEfRKn1VV8= -cloud.google.com/go v0.81.0/go.mod h1:mk/AM35KwGk/Nm2YSeZbxXdrNK3KZOYHmLkOqC2V6E0= -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.4.0/go.mod h1:S8dzgnTigyfTmLBfrtrhyYhwRxG72rYxvftPBK2Dvzc= -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.8.0/go.mod h1:J5hqkt3O0uAFnINi6JXValWIb1v0goeZM77hZzJN/fQ= -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/firestore v1.1.0/go.mod h1:ulACoGHTpvq5r8rxGJ4ddJZBZqakUQqClKRT5SZwBmk= -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.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/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.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.10.0/go.mod h1:FLPqc6j+Ki4BU591ie1oL6qBQGu2Bl/tZ9ullr3+Kg0= -dmitri.shuralyov.com/gpu/mtl v0.0.0-20190408044501-666a987793e9/go.mod h1:H6x//7gZCb22OMCxBHrMx7a5I7Hp++hsVxbQ4BYO7hU= github.com/BurntSushi/toml v0.3.1 h1:WXkYYl6Yr3qBf1K79EBnL4mak0OimBfB0XUf9Vl28OQ= github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= -github.com/BurntSushi/xgb v0.0.0-20160522181843-27f122750802/go.mod h1:IVnqGOEym/WlBOVXweHU+Q+/VP0lqqI8lqeDx9IjBqo= github.com/OneOfOne/xxhash v1.2.2/go.mod h1:HSdplMjZKSmBqAxg5vPj2TmRDmfkzw+cTzAElWljhcU= github.com/alecthomas/template v0.0.0-20160405071501-a0175ee3bccc/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc= github.com/alecthomas/template v0.0.0-20190718012654-fb15b899a751/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc= @@ -48,15 +10,10 @@ github.com/alecthomas/units v0.0.0-20151022065526-2efee857e7cf/go.mod h1:ybxpYRF github.com/alecthomas/units v0.0.0-20190717042225-c3de453c63f4/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0= github.com/alecthomas/units v0.0.0-20190924025748-f65c72e2690d/go.mod h1:rBZYJk541a8SKzHPHnH3zbiI+7dagKZ0cgpgrD7Fyho= github.com/antihax/optional v1.0.0/go.mod h1:uupD/76wgC+ih3iEmQUL+0Ugr19nfwCT1kdvxnR2qWY= -github.com/armon/circbuf v0.0.0-20150827004946-bbbad097214e/go.mod h1:3U/XgcO3hCbHZ8TKRvWD2dDTCfh9M9ya+I9JpbB7O8o= -github.com/armon/go-metrics v0.0.0-20180917152333-f0300d1749da/go.mod h1:Q73ZrmVTwzkszR9V5SSuryQ31EELlFMUz1kKyl939pY= -github.com/armon/go-radix v0.0.0-20180808171621-7fddfc383310/go.mod h1:ufUuZ+zHj4x4TnLV4JWEpy2hxWSpsRywHrMgIH9cCH8= github.com/beorn7/perks v0.0.0-20180321164747-3a771d992973/go.mod h1:Dwedo/Wpr24TaqPxmxbtue+5NUziq4I4S80YR8gNf3Q= github.com/beorn7/perks v1.0.0/go.mod h1:KWe93zE9D1o94FZ5RNwFwVgaQK1VOXiVxmqh+CedLV8= github.com/beorn7/perks v1.0.1 h1:VlbKKnNfV8bJzeqoa4cOKqO6bYr3WgKZxO8Z16+hsOM= github.com/beorn7/perks v1.0.1/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6rlkpw= -github.com/bgentry/speakeasy v0.1.0/go.mod h1:+zsyZBPWlz7T6j88CTgSN5bM796AkVf0kBD4zp0CCIs= -github.com/bketelsen/crypt v0.0.4/go.mod h1:aI6NrJ0pMGgvZKL1iVgXLnfIFJtfV+bKCoqOes/6LfM= github.com/cenkalti/backoff/v4 v4.1.1 h1:G2HAfAmvm/GcKan2oOQpBXOd2tT2G57ZnZGWa1PxPBQ= github.com/cenkalti/backoff/v4 v4.1.1/go.mod h1:scbssz8iZGpm3xbr14ovlUdkxfGXNInqkPWOWmG2CLw= github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU= @@ -67,12 +24,8 @@ github.com/cespare/xxhash v1.1.0 h1:a6HrQnmkObjyL+Gs60czilIUGqrzKutQD6XZog3p+ko= github.com/cespare/xxhash v1.1.0/go.mod h1:XrSqR1VqqWfGrhpAt58auRo0WTKS1nRRg3ghfAqPWnc= github.com/cespare/xxhash/v2 v2.1.1 h1:6MnRN8NT7+YBpUIWxHtefFZOKTAPgGjpQSxqLNn0+qY= github.com/cespare/xxhash/v2 v2.1.1/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= -github.com/chzyer/logex v1.1.10/go.mod h1:+Ywpsq7O8HXn0nuIou7OrIPyXbp3wmkHB+jjWRnGsAI= -github.com/chzyer/readline v0.0.0-20180603132655-2972be24d48e/go.mod h1:nSuG5e5PlCu98SY8svDHJxuZscDgtXS6KTTbou5AhLI= -github.com/chzyer/test v0.0.0-20180213035817-a1ea475d72b1/go.mod h1:Q3SI9o4m/ZMnBNeIyt5eFwwo7qiLfzFZmjNmxjkiQlU= github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw= 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/xds/go v0.0.0-20210312221358-fbca930ec8ed/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs= github.com/cncf/xds/go v0.0.0-20210805033703-aa0b78936158/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs= @@ -86,7 +39,7 @@ github.com/coreos/go-semver v0.3.0 h1:wkHLiw0WNATZnSG7epLsujiMCgPAc9xhjJ4tgnAxmf github.com/coreos/go-semver v0.3.0/go.mod h1:nnelYz7RCh+5ahJtPPxZlU+153eP4D4r3EedlOD2RNk= github.com/coreos/go-systemd/v22 v22.3.2 h1:D9/bQk5vlXQFZ6Kwuu6zaiXJ9oTPe68++AzAJc1DzSI= github.com/coreos/go-systemd/v22 v22.3.2/go.mod h1:Y58oyj3AT4RCenI/lSvhwexgC+NSVTIJ3seZv2GcEnc= -github.com/cpuguy83/go-md2man/v2 v2.0.0/go.mod h1:maD7wRr/U5Z6m/iR4s+kqSMx2CaBsrgA7czyZG/E6dU= +github.com/cpuguy83/go-md2man/v2 v2.0.1/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o= github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E= github.com/creack/pty v1.1.11 h1:07n33Z8lZxZ2qwegKbObQohDhXDQxiMMz1NOUGYlesw= github.com/creack/pty v1.1.11/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E= @@ -98,20 +51,14 @@ github.com/dustin/go-humanize v1.0.0/go.mod h1:HtrtbFcZ19U5GC7JDqmcUSB87Iq5E25Kn 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.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.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.10-0.20210907150352-cf90f659a021/go.mod h1:AFq3mo9L8Lqqiid3OhADV3RfLJnjiw63cSpi+fDTRC0= github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c= -github.com/fatih/color v1.7.0/go.mod h1:Zm6kSWBoL9eyXnKyktHP6abPY2pDugNf5KwzbycvMj4= -github.com/fsnotify/fsnotify v1.4.9/go.mod h1:znqG4EE+3YCdAaPaxE2ZRY/06pZUdp0tY4IgpuI1SZQ= github.com/getsentry/raven-go v0.2.0 h1:no+xWJRb5ZI7eE8TWgIq1jLulQiIoLG0IfYxv5JYMGs= github.com/getsentry/raven-go v0.2.0/go.mod h1:KungGk8q33+aIAZUIVWZDr2OfAEBsO49PX4NzFV5kcQ= github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04= -github.com/go-gl/glfw v0.0.0-20190409004039-e6da0acd62b1/go.mod h1:vR7hzQXu2zJy9AVAgeJqvqgH9Q5CA+iKCZ2gyEVpxRU= -github.com/go-gl/glfw/v3.3/glfw v0.0.0-20191125211704-12ad95a8df72/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8= -github.com/go-gl/glfw/v3.3/glfw v0.0.0-20200222043503-6f7a984d4dc4/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8= github.com/go-kit/kit v0.8.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as= github.com/go-kit/kit v0.9.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as= github.com/go-kit/log v0.1.0/go.mod h1:zbhenjAZHb184qTLMA9ZjW7ThYL0H2mk7Q6pNt4vbaY= @@ -127,25 +74,13 @@ github.com/gogo/protobuf v1.3.2/go.mod h1:P1XiOD3dCwIKUDQYPy72D8LYyHL2YPYrpS2s69 github.com/golang-jwt/jwt v3.2.2+incompatible h1:IfV12K8xAKAnZqdXVzCZ+TOjboZ2keLg81eXfW3O+oY= github.com/golang-jwt/jwt v3.2.2+incompatible/go.mod h1:8pz2t5EyA70fFQQSrl6XZXzqecmYZeUEB8OUGHkxJ+I= github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q= -github.com/golang/groupcache v0.0.0-20190702054246-869f871628b6/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= -github.com/golang/groupcache v0.0.0-20191227052852-215e87163ea7/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= -github.com/golang/groupcache v0.0.0-20200121045136-8c9f03a8e57e/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da h1:oI5xCqsCo564l8iNU+DwB5epxmsaqB+rhGL0m5jtYqE= github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= github.com/golang/mock v1.1.1/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A= -github.com/golang/mock v1.2.0/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A= -github.com/golang/mock v1.3.1/go.mod h1:sBzyDLLjw3U8JLTeZvSv8jJB+tU5PVekmnlKIyFUx0Y= -github.com/golang/mock v1.4.0/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.4/go.mod h1:l3mdAwkq5BuhzHwde/uurv3sEJeZMXNpwsxVWU71h+4= -github.com/golang/mock v1.5.0/go.mod h1:CWnOUgYIOo4TcNZ0wHX3YZCqsaM1I1Jvs6v3mP3KVu8= github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= github.com/golang/protobuf v1.3.1/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= github.com/golang/protobuf v1.3.2/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= github.com/golang/protobuf v1.3.3/go.mod h1:vzj43D7+SQXF/4pzW/hwtAqwc6iTitCiVSaWz5lYuqw= -github.com/golang/protobuf v1.3.4/go.mod h1:vzj43D7+SQXF/4pzW/hwtAqwc6iTitCiVSaWz5lYuqw= -github.com/golang/protobuf v1.3.5/go.mod h1:6O5/vntMXwX2lRkT1hjjk0nAC1IDOTvTlVgjlRvqsdk= github.com/golang/protobuf v1.4.0-rc.1/go.mod h1:ceaxUfeHdC40wWswd/P6IGgMaK3YpKi5j83Wpe3EHw8= github.com/golang/protobuf v1.4.0-rc.1.0.20200221234624-67d41d38c208/go.mod h1:xKAWHe0F5eneWXFV3EuXVDTCmh+JuBKY0li0aMyXATA= github.com/golang/protobuf v1.4.0-rc.2/go.mod h1:LlEzMj4AhA7rCAGe4KMBDvJI+AwstrUpVNzEA03Pprs= @@ -155,46 +90,21 @@ 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.3/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI= 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/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY= -github.com/google/btree v0.0.0-20180813153112-4030bb1f1f0c/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ= -github.com/google/btree v1.0.0/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ= github.com/google/btree v1.0.1 h1:gK4Kx5IaGY9CD5sPJ36FHiBJ6ZXl0kilRiiCj+jdYp4= github.com/google/btree v1.0.1/go.mod h1:xXMiIv4Fb/0kKde4SpL7qlzvu5cMJDRkFDxJfI9uaxA= github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M= github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= -github.com/google/go-cmp v0.4.1/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.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.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.6 h1:BKbKCqvP6I+rmFHt06ZmyQtvB8xAkWdhFyr0ZUNZcxQ= github.com/google/go-cmp v0.5.6/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= -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.1.0/go.mod h1:y5Zk1BBys9G+gd6Jrk0W3cC1+ELVxBWuIGO+w/tUAp0= -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-20191218002539-d4f498aebedc/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= -github.com/google/pprof v0.0.0-20200212024743-f11f1df84d12/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-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/renameio v0.1.0/go.mod h1:KWCgfxg9yswjAJkECMjeO8J8rahYeXnNhOm40UhjYkI= github.com/google/uuid v1.1.2/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= -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/gopherjs/gopherjs v0.0.0-20181017120253-0766667cb4d1/go.mod h1:wJfORRmW1u3UXTncJ5qlYoELFm8eSnnEO6hX4iZ3EWY= github.com/gorilla/websocket v1.4.2 h1:+/TMaTYc4QFitKJxsQ7Yye35DkWvkdLcvGKqM+x0Ufc= github.com/gorilla/websocket v1.4.2/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE= github.com/grpc-ecosystem/go-grpc-middleware v1.3.0 h1:+9834+KizmvFV7pXQGSXQTsaWhq2GjuNUt0aUU0YBYw= @@ -203,28 +113,6 @@ github.com/grpc-ecosystem/go-grpc-prometheus v1.2.0 h1:Ovs26xHkKqVztRpIrF/92Bcuy github.com/grpc-ecosystem/go-grpc-prometheus v1.2.0/go.mod h1:8NvIoxWQoOIhqOTXgfV/d3M/q6VIi02HzZEHgUlZvzk= github.com/grpc-ecosystem/grpc-gateway v1.16.0 h1:gmcG1KaJ57LophUzW0Hy8NmPhnMZb4M0+kPpLofRdBo= github.com/grpc-ecosystem/grpc-gateway v1.16.0/go.mod h1:BDjrQk3hbvj6Nolgz8mAMFbcEtjT1g+wF4CSlocrBnw= -github.com/hashicorp/consul/api v1.1.0/go.mod h1:VmuI/Lkw1nC05EYQWNKwWGbkg+FbDBtguAZLlVdkD9Q= -github.com/hashicorp/consul/sdk v0.1.1/go.mod h1:VKf9jXwCTEY1QZP2MOLRhb5i/I/ssyNV1vwHyQBF0x8= -github.com/hashicorp/errwrap v1.0.0/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4= -github.com/hashicorp/go-cleanhttp v0.5.1/go.mod h1:JpRdi6/HCYpAwUzNwuwqhbovhLtngrth3wmdIIUrZ80= -github.com/hashicorp/go-immutable-radix v1.0.0/go.mod h1:0y9vanUI8NX6FsYoO3zeMjhV/C5i9g4Q3DwcSNZ4P60= -github.com/hashicorp/go-msgpack v0.5.3/go.mod h1:ahLV/dePpqEmjfWmKiqvPkv/twdG7iPBM1vqhUKIvfM= -github.com/hashicorp/go-multierror v1.0.0/go.mod h1:dHtQlpGsu+cZNNAkkCN/P3hoUDHhCYQXV3UM06sGGrk= -github.com/hashicorp/go-rootcerts v1.0.0/go.mod h1:K6zTfqpRlCUIjkwsN4Z+hiSfzSTQa6eBIzfwKfwNnHU= -github.com/hashicorp/go-sockaddr v1.0.0/go.mod h1:7Xibr9yA9JjQq1JpNB2Vw7kxv8xerXegt+ozgdvDeDU= -github.com/hashicorp/go-syslog v1.0.0/go.mod h1:qPfqrKkXGihmCqbJM2mZgkZGvKG1dFdvsLplgctolz4= -github.com/hashicorp/go-uuid v1.0.0/go.mod h1:6SBZvOh/SIDV7/2o3Jml5SYk/TvGqwFJ/bN7x4byOro= -github.com/hashicorp/go-uuid v1.0.1/go.mod h1:6SBZvOh/SIDV7/2o3Jml5SYk/TvGqwFJ/bN7x4byOro= -github.com/hashicorp/go.net v0.0.1/go.mod h1:hjKkEWcCURg++eb33jQU7oqQcI9XDCnUzHA0oac0k90= -github.com/hashicorp/golang-lru v0.5.0/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8= -github.com/hashicorp/golang-lru v0.5.1/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8= -github.com/hashicorp/hcl v1.0.0/go.mod h1:E5yfLk+7swimpb2L/Alb/PJmXilQ/rhwaUYs4T20WEQ= -github.com/hashicorp/logutils v1.0.0/go.mod h1:QIAnNjmIWmVIIkWDTG1z5v++HQmx9WQRO+LraFDTW64= -github.com/hashicorp/mdns v1.0.0/go.mod h1:tL+uN++7HEJ6SQLQ2/p+z2pH24WQKWjBPkE0mNTz8vQ= -github.com/hashicorp/memberlist v0.1.3/go.mod h1:ajVTdAv/9Im8oMAAj5G31PhhMCZJV2pPBoIllUwCN7I= -github.com/hashicorp/serf v0.8.2/go.mod h1:6hOLApaqBFA1NXqRQAsxw9QxuDEvNxSQRwA/JwenrHc= -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/inconshreveable/mousetrap v1.0.0 h1:Z8tu5sraLXCXIcARxBp/8cbvlwVa7Z1NHg9XEKhtSvM= github.com/inconshreveable/mousetrap v1.0.0/go.mod h1:PxqpIevigyE2G7u3NXJIT2ANytuPF1OarO4DADm73n8= github.com/jonboulle/clockwork v0.2.2 h1:UOGuzwb1PwsrDAObMuhUnj0p5ULPj8V/xJ7Kx9qUBdQ= @@ -233,9 +121,6 @@ github.com/jpillora/backoff v1.0.0/go.mod h1:J/6gKK9jxlEcS3zixgDgUAsiuZ7yrSoa/FX github.com/json-iterator/go v1.1.6/go.mod h1:+SdeFBvtyEkXs7REEP0seUULqWtbJapLOCVDaaPEHmU= github.com/json-iterator/go v1.1.10/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4= github.com/json-iterator/go v1.1.11/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4= -github.com/jstemmer/go-junit-report v0.0.0-20190106144839-af01ea7f8024/go.mod h1:6v2b51hI/fHJwM22ozAgKL4VKDeJcHhJFhtBdhmNjmU= -github.com/jstemmer/go-junit-report v0.9.1/go.mod h1:Brl9GWCQeLvo8nXZwPNNblvFj/XSXhF0NWZEnDohbsk= -github.com/jtolds/gls v4.20.0+incompatible/go.mod h1:QJZ7F/aHp+rZTRtaJ1ow/lLfFfVYBRgL+9YlvaHOwJU= github.com/julienschmidt/httprouter v1.2.0/go.mod h1:SYymIcj16QtmaHHD7aYtjjsJG7VTCxuUUipMqKk8s4w= github.com/julienschmidt/httprouter v1.3.0/go.mod h1:JR6WtHb+2LUe8TCKY3cZOxFyyO8IZAc4RVcycCCAKdM= github.com/kisielk/errcheck v1.2.0/go.mod h1:/BMXB+zMLi60iA8Vv6Ksmxu/1UDYcXs4uQLJ+jE2L00= @@ -243,7 +128,6 @@ github.com/kisielk/errcheck v1.5.0/go.mod h1:pFxgyoBC7bSaBwPgfKdkLd5X25qrDl4LWUI github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck= github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= github.com/konsorten/go-windows-terminal-sequences v1.0.3/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= -github.com/kr/fs v0.1.0/go.mod h1:FFnZGqtBN9Gxj7eW1uZ42v5BccTP0vu6NEaFoC2HwRg= github.com/kr/logfmt v0.0.0-20140226030751-b84e30acd515/go.mod h1:+0opPa2QZZtGFBFZlji/RkVcI2GknAs/DXo4wKdlNEc= github.com/kr/pretty v0.1.0 h1:L/CwN0zerZDmRFUapSPitk6f+Q3+0za1rQkzVuMiMFI= github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo= @@ -251,21 +135,9 @@ github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY= github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE= -github.com/magiconair/properties v1.8.5/go.mod h1:y3VJvCyxH9uVvJTWEGAELF3aiYNyPKd5NZ3oSwXrF60= -github.com/mattn/go-colorable v0.0.9/go.mod h1:9vuHe8Xs5qXnSaW/c/ABM9alt+Vo+STaOChaDxuIBZU= -github.com/mattn/go-isatty v0.0.3/go.mod h1:M+lRXTBqGeGNdLjl/ufCoiOlB5xdOkqRJdNxMWT7Zi4= github.com/mattn/go-runewidth v0.0.9/go.mod h1:H031xJmbD/WCDINGzjvQ9THkh0rPKHF+m2gUSrubnMI= github.com/matttproud/golang_protobuf_extensions v1.0.1 h1:4hp9jkHxhMHkqkrB3Ix0jegS5sx/RkqARlsWZ6pIwiU= github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0= -github.com/miekg/dns v1.0.14/go.mod h1:W1PPwlIAgtquWBMBEV9nkV9Cazfe8ScdGz/Lj7v3Nrg= -github.com/mitchellh/cli v1.0.0/go.mod h1:hNIlj7HEI86fIcpObd7a0FcrxTWetlwJDGcceTlRvqc= -github.com/mitchellh/go-homedir v1.0.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0= -github.com/mitchellh/go-testing-interface v1.0.0/go.mod h1:kRemZodwjscx+RGhAo8eIhFbs2+BFgRtFPeD/KE+zxI= -github.com/mitchellh/gox v0.4.0/go.mod h1:Sd9lOJ0+aimLBi73mGofS1ycjY8lL3uZM3JPS42BGNg= -github.com/mitchellh/iochan v1.0.0/go.mod h1:JwYml1nuB7xOzsp52dPpHFffvOCDupsG0QubkSMEySY= -github.com/mitchellh/mapstructure v0.0.0-20160808181253-ca63d7c062ee/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y= -github.com/mitchellh/mapstructure v1.1.2/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y= -github.com/mitchellh/mapstructure v1.4.1/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo= github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= github.com/modern-go/reflect2 v0.0.0-20180701023420-4b7aa43c6742/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0= @@ -274,16 +146,12 @@ github.com/mwitkow/go-conntrack v0.0.0-20161129095857-cc309e4a2223/go.mod h1:qRW github.com/mwitkow/go-conntrack v0.0.0-20190716064945-2f068394615f/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U= github.com/olekukonko/tablewriter v0.0.5/go.mod h1:hPp6KlRPjbx+hW8ykQs1w3UBbZlj6HuIJcUGPhkA7kY= github.com/opentracing/opentracing-go v1.1.0/go.mod h1:UkNAQd3GIcIGf0SeVgPpRdFStlNbqXla1AfSYxPUl2o= -github.com/pascaldekloe/goe v0.0.0-20180627143212-57f6aae5913c/go.mod h1:lzWF7FIEvWOWxwDKqyGYQf6ZUaNfKdP144TG7ZOy1lc= -github.com/pelletier/go-toml v1.9.3/go.mod h1:u1nR/EPcESfeI/szUZKdtJ0xRNbUoANCkoOuaOx1Y+c= github.com/pkg/errors v0.8.0/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4= github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= -github.com/pkg/sftp v1.10.1/go.mod h1:lYOWFsE0bwd1+KfKJaKeuokY15vzFx25BLbzYYoAxZI= github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= -github.com/posener/complete v1.1.1/go.mod h1:em0nMJCgc9GFtwrmVmEMR/ZL6WyhyjMBndrE9hABlRI= github.com/prometheus/client_golang v0.9.1/go.mod h1:7SWBe2y4D6OKWSNQJUaRYU/AaXPKyh/dDVn+NZz0KFw= github.com/prometheus/client_golang v1.0.0/go.mod h1:db9x61etRT2tGnBNRi70OPL5FsnadC4Ky3P0J6CfImo= github.com/prometheus/client_golang v1.7.1/go.mod h1:PY5Wy2awLA44sXw4AOSfFBetzPP4j5+D6mVACh+pe2M= @@ -304,56 +172,35 @@ github.com/prometheus/procfs v0.1.3/go.mod h1:lV6e/gmhEcM9IjHGsFOCxxuZ+z1YqCvr4O github.com/prometheus/procfs v0.6.0 h1:mxy4L2jP6qMonqmq+aTtOx1ifVWUgG/TAmntgbh3xv4= github.com/prometheus/procfs v0.6.0/go.mod h1:cz+aTbrPOrUb4q7XlbU9ygM+/jj0fzG6c1xBZuNvfVA= github.com/rogpeppe/fastuuid v1.2.0/go.mod h1:jVj6XXZzXRy/MSR5jhDC/2q6DgLz+nrA6LYCDYWNEvQ= -github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4= -github.com/russross/blackfriday/v2 v2.0.1/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= -github.com/ryanuber/columnize v0.0.0-20160712163229-9b3edd62028f/go.mod h1:sm1tb6uqfes/u+d4ooFouqFdy9/2g9QGwK3SQygK0Ts= -github.com/sean-/seed v0.0.0-20170313163322-e2103e2c3529/go.mod h1:DxrIzT+xaE7yg65j358z/aeFdxmN0P9QXhEzd20vsDc= -github.com/shurcooL/sanitized_anchor_name v1.0.0/go.mod h1:1NzhyTcUVG4SuEtjjoZeVRXNmyL/1OwPU0+IJeTBvfc= +github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= github.com/sirupsen/logrus v1.2.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPxbbu5VWo= github.com/sirupsen/logrus v1.4.2/go.mod h1:tLMulIdttU9McNUspp0xgXVQah82FyeX6MwdIuYE2rE= github.com/sirupsen/logrus v1.6.0/go.mod h1:7uNnSEd1DgxDLC74fIahvMZmmYsHGZGEOFrfsX/uA88= github.com/sirupsen/logrus v1.8.1 h1:dJKuHgqk1NNQlqoA6BTlM1Wf9DOH3NBjQyu0h9+AZZE= github.com/sirupsen/logrus v1.8.1/go.mod h1:yWOB1SBYBC5VeMP7gHvWumXLIWorT60ONWic61uBYv0= -github.com/smartystreets/assertions v0.0.0-20180927180507-b2de0cb4f26d/go.mod h1:OnSkiWE9lh6wB0YB77sQom3nweQdgAjqCqsofrRNTgc= -github.com/smartystreets/goconvey v1.6.4/go.mod h1:syvi0/a8iFYH4r/RixwvyeAJjdLS9QV7WQ/tjFTllLA= github.com/soheilhy/cmux v0.1.5 h1:jjzc5WVemNEDTLwv9tlmemhC73tI08BNOIGwBOo10Js= github.com/soheilhy/cmux v0.1.5/go.mod h1:T7TcVDs9LWfQgPlPsdngu6I6QIoyIFZDDC6sNE1GqG0= github.com/spaolacci/murmur3 v0.0.0-20180118202830-f09979ecbc72/go.mod h1:JwIasOWyU6f++ZhiEuf87xNszmSA2myDM2Kzu9HwQUA= -github.com/spf13/afero v1.6.0/go.mod h1:Ai8FlHk4v/PARR026UzYexafAt9roJ7LcLMAmO6Z93I= -github.com/spf13/cast v1.3.1/go.mod h1:Qx5cxh0v+4UWYiBimWS+eyWzqEqokIECu5etghLkUJE= -github.com/spf13/cobra v1.2.1 h1:+KmjbUw1hriSNMF55oPrkZcb27aECyrj8V2ytv7kWDw= -github.com/spf13/cobra v1.2.1/go.mod h1:ExllRjgxM/piMAM+3tAZvg8fsklGAf3tPfi+i8t68Nk= -github.com/spf13/jwalterweatherman v1.1.0/go.mod h1:aNWZUN0dPAAO/Ljvb5BEdw96iTZ0EXowPYD95IqWIGo= +github.com/spf13/cobra v1.4.0 h1:y+wJpx64xcgO1V+RcnwW0LEHxTKRi2ZDPSBjWnrg88Q= +github.com/spf13/cobra v1.4.0/go.mod h1:Wo4iy3BUC+X2Fybo0PDqwJIv3dNRiZLHQymsfxlB84g= github.com/spf13/pflag v1.0.5 h1:iy+VFUOCP1a+8yFto/drg2CJ5u0yRoB7fZw3DKv/JXA= github.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg= -github.com/spf13/viper v1.8.1/go.mod h1:o0Pch8wJ9BVSWGQMbra6iw0oQ5oktSIBaujf1rJH9Ns= github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= 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.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA= -github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/stretchr/testify v1.7.0 h1:nwc3DEeHmmLAfoZucVR881uASk0Mfjw8xYJ99tb5CcY= github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= -github.com/subosito/gotenv v1.2.0/go.mod h1:N0PQaV/YGNqwC0u51sEeR/aUtSLEXKX9iv69rRypqCw= github.com/tmc/grpc-websocket-proxy v0.0.0-20201229170055-e5319fda7802 h1:uruHq4dN7GR16kFc5fp3d1RIYzJW5onx8Ybykw2YQFA= github.com/tmc/grpc-websocket-proxy v0.0.0-20201229170055-e5319fda7802/go.mod h1:ncp9v5uamzpCO7NfCPTXjqaC+bZgJeR0sMTm6dMHP7U= github.com/xiang90/probing v0.0.0-20190116061207-43a291ad63a2 h1:eY9dn8+vbi4tKz5Qo6v2eYzo7kUS51QINcR5jNpbZS8= github.com/xiang90/probing v0.0.0-20190116061207-43a291ad63a2/go.mod h1:UETIi67q53MR2AWcXfiuqkDkRtnGDLqkBTpCHuJHxtU= -github.com/yuin/goldmark v1.1.25/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= -github.com/yuin/goldmark v1.1.32/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= go.etcd.io/bbolt v1.3.6 h1:/ecaJf0sk1l4l6V4awd65v2C3ILy7MSj+s/x1ADCIMU= go.etcd.io/bbolt v1.3.6/go.mod h1:qXsaaIqmgQH0T+OPdb99Bf+PKfBBQVAdyD6TY9G8XM4= -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.2/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.5/go.mod h1:5pWMHQbX5EPX2/62yrJeAkowc+lfs/XD7Uxpq3pI6kk= -go.opencensus.io v0.23.0/go.mod h1:XItmlyltB5F7CS4xOC1DcqMoFqwtC6OG2xF7mCv7P7E= go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.26.1 h1:puWrOArBwWlr5dq6vyZ6fKykHyS8JgMIVhTBA8XsGuU= go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.26.1/go.mod h1:4wsfAAW5N9wUHM0QTmZS8z7fvYZ1rv3m+sVeSpf8NhU= go.opentelemetry.io/otel v1.1.0/go.mod h1:7cww0OW51jQ8IaZChIEdqLwgh+44+7uiTdWsAL0wQpA= @@ -384,163 +231,64 @@ go.uber.org/zap v1.10.0/go.mod h1:vwi/ZaCAaUcBkycHslxD9B2zi4UTXhF60s6SWpuDF0Q= go.uber.org/zap v1.17.0 h1:MTjgFu6ZLKvY6Pvaqk97GlxNBuMpV4Hy/3P6tRGlI2U= go.uber.org/zap v1.17.0/go.mod h1:MXVU+bhUf/A7Xi2HNOnopQOrmycQ5Ih87HtOu4q5SSo= golang.org/x/crypto v0.0.0-20180904163835-0709b304e793/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= -golang.org/x/crypto v0.0.0-20181029021203-45a5f77698d3/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= -golang.org/x/crypto v0.0.0-20190510104115-cbcb75029529/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= -golang.org/x/crypto v0.0.0-20190605123033-f99c8df09eb5/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= -golang.org/x/crypto v0.0.0-20190820162420-60c769a6c586/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= golang.org/x/crypto v0.0.0-20210513164829-c07d793c2f9a h1:kr2P4QFmQr29mSLA43kwrOcgcReGTfbE9N577tCTuBc= golang.org/x/crypto v0.0.0-20210513164829-c07d793c2f9a/go.mod h1:P+XmwS30IXTQdn5tA2iutPOUgjI07+tq3H3K9MVA1s8= golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= -golang.org/x/exp v0.0.0-20190306152737-a1d7652674e8/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= -golang.org/x/exp v0.0.0-20190510132918-efd6b22b2522/go.mod h1:ZjyILWgesfNpC6sMxTJOJm9Kp84zZh5NQWvqDGG3Qr8= -golang.org/x/exp v0.0.0-20190829153037-c13cbed26979/go.mod h1:86+5VVa7VpoJ4kLfm080zCjGlMRFzhUhsZKEZO7MGek= -golang.org/x/exp v0.0.0-20191030013958-a1ab85dbe136/go.mod h1:JXzH8nQsPlswgeRAPE3MuO9GYsAcnJvJ4vnMwN/5qkY= -golang.org/x/exp v0.0.0-20191129062945-2f5052295587/go.mod h1:2RIsYlXP63K8oxa1u096TMicItID8zy7Y6sNkU49FU4= -golang.org/x/exp v0.0.0-20191227195350-da58074b4299/go.mod h1:2RIsYlXP63K8oxa1u096TMicItID8zy7Y6sNkU49FU4= -golang.org/x/exp v0.0.0-20200119233911-0405dc783f0a/go.mod h1:2RIsYlXP63K8oxa1u096TMicItID8zy7Y6sNkU49FU4= -golang.org/x/exp v0.0.0-20200207192155-f17229e696bd/go.mod h1:J/WKrq2StrnmMY6+EHIKF9dgMWnmCNThgcyBT1FY9mM= -golang.org/x/exp v0.0.0-20200224162631-6cc2880d07d6/go.mod h1:3jZMyOhIsHpP37uCMkUooju7aAi5cS1Q23tOzKc+0MU= -golang.org/x/image v0.0.0-20190227222117-0694c2d4d067/go.mod h1:kZ7UVZpmo3dzQBMxlp+ypCbDeSB+sBbTgSJuh5dn5js= -golang.org/x/image v0.0.0-20190802002840-cff245a6509b/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0= golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE= golang.org/x/lint v0.0.0-20190227174305-5b3e6a55c961/go.mod h1:wehouNa3lNwaWXcvxsM5YxQ5yQlVC4a0KAMCusXpPoU= -golang.org/x/lint v0.0.0-20190301231843-5614ed5bae6f/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE= golang.org/x/lint v0.0.0-20190313153728-d0100b6bd8b3/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= -golang.org/x/lint v0.0.0-20190409202823-959b441ac422/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= -golang.org/x/lint v0.0.0-20190909230951-414d861bb4ac/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= -golang.org/x/lint v0.0.0-20190930215403-16217165b5de/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= -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-20200302205851-738671d3881b/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY= -golang.org/x/lint v0.0.0-20201208152925-83fdc39ff7b5/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-20190719004257-d2bd2a29d028/go.mod h1:E/iHnbuqvinMTCcRqshq8CkpyQDoeVncDDYHnLhea+o= -golang.org/x/mod v0.0.0-20190513183733-4bf6d317e70e/go.mod h1:mXi4GBBbnImb6dmsKGUJ2LatrhH/nqhxcFungHvyanc= -golang.org/x/mod v0.1.0/go.mod h1:0QHyrYULN0/3qlju5TqG8bIK38QM8yzMo5ekMj3DlcY= -golang.org/x/mod v0.1.1-0.20191105210325-c90efee705ee/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.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/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-20181023162649-9b4f9f5ad519/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20181114220301-adae6a3d119a/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= -golang.org/x/net v0.0.0-20181201002055-351d144fa1fc/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20190108225652-1e06a53dbb7e/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20190213061140-3a22650c66bd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= -golang.org/x/net v0.0.0-20190501004415-9ce7a6920f09/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= -golang.org/x/net v0.0.0-20190503192946-f4e77d36d62c/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= -golang.org/x/net v0.0.0-20190603091049-60506f45cf65/go.mod h1:HSz+uSET+XFnRR8LxR5pz3Of3rY3CfYBVs4xY44aLks= golang.org/x/net v0.0.0-20190613194153-d28f0bde5980/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= -golang.org/x/net v0.0.0-20190628185345-da137c7871d7/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= -golang.org/x/net v0.0.0-20190724013045-ca1201d0de80/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= -golang.org/x/net v0.0.0-20191209160850-c0dbc17a3553/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= -golang.org/x/net v0.0.0-20200114155413-6afb5195e5aa/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= -golang.org/x/net v0.0.0-20200202094626-16171245cfb2/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= -golang.org/x/net v0.0.0-20200222125558-5a598a2470a0/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20200226121028-0de0cce0169b/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= -golang.org/x/net v0.0.0-20200301022130-244492dfa37a/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= -golang.org/x/net v0.0.0-20200324143707-d3edc9973b7e/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= -golang.org/x/net v0.0.0-20200501053045-e0ff5e5a1de5/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= -golang.org/x/net v0.0.0-20200506145744-7e3656a0809f/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= -golang.org/x/net v0.0.0-20200513185701-a91f0712d120/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= -golang.org/x/net v0.0.0-20200520182314-0ba52f642ac2/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= golang.org/x/net v0.0.0-20200625001655-4c5254603344/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-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-20201202161906-c7110b5ffcbb/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-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-20220105145211-5b0dc2dfae98 h1:+6WJMRLHlD7X7frgp7TUZ36RnQzSf9wVVTNakEp+nqY= golang.org/x/net v0.0.0-20220105145211-5b0dc2dfae98/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= 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-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-20200107190931-bf48bf16ab8d h1:TzXSXBo42m9gQenoE3b9BGiEpg5IG2JkU5FkPIawgtw= 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-20210402161424-2e8d93401602 h1:0Ja1LBD+yisY6RWM/BH7TJVXWsSjs2VwBSmvSX4HdBc= -golang.org/x/oauth2 v0.0.0-20210402161424-2e8d93401602/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= 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-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.0.0-20190227155943-e225da77a7e6/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.0.0-20200317015054-43a5402ce75a/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.0.0-20200625203802-6e8e738ad208/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-20210220032951-036812b2e83c h1:5KslGYwFpkhGh+Q16bwMP3cOontH8FOep7tGV86Y7SQ= golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sys v0.0.0-20180823144017-11551d06cbcc/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= -golang.org/x/sys v0.0.0-20181026203630-95b1ffbd15a5/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20181116152217-5ac8a444bdc5/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= -golang.org/x/sys v0.0.0-20190312061237-fead79001313/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190422165155-953cdadca894/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20190502145724-3ef323f4f1fd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20190507160741-ecd444e8653b/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20190606165138-5da285871e9c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20190624142023-c5567b49c5d0/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20190726091711-fc99dfbffb4e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20191001151750-bb3f8db39f24/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20191005200804-aed5e4c7ecf9/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20191026070338-33540a1f6037/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20191204072324-ce4227a45e2e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20191228213918-04cbcbbfeed8/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200106162015-b016eb3dc98e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200113162924-86b910548bc1/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200122134326-e047566fdf82/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200202164722-d101bd2416d5/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200212091648-12a6c2dcc1e4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200223170610-d5e6a3e2c0ae/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200302150141-5c8b2ff67527/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200331124033-c3d80250170d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200501052902-10377860bb8e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200511232937-7e40ca221e25/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200515095857-1151b9dac4a9/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200523222454-059865788121/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-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-20200923182605-d9f96fdee20d/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-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-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-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-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-20210423185535-09eb48e85fd7/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210510120138-977fb7262007/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= @@ -549,19 +297,13 @@ golang.org/x/sys v0.0.0-20210603125802-9665404d3644/go.mod h1:oPkhp1MJrh7nUepCBc golang.org/x/sys v0.0.0-20211123173158-ef496fb156ab h1:rfJ1bsoJQQIAoAxTxB7bme+vHrNkRw8CqfsYh9w54cw= golang.org/x/sys v0.0.0-20211123173158-ef496fb156ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= -golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= -golang.org/x/text v0.3.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.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.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/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-20191024005414-555d28b269f0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.0.0-20210220033141-f8bda1e9f3ba h1:O8mE0/t419eoIwhTFpKVkHiTs/Igowgfkj25AcZrtiE= golang.org/x/time v0.0.0-20210220033141-f8bda1e9f3ba/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= @@ -569,151 +311,33 @@ golang.org/x/tools v0.0.0-20181030221726-6c7e314b6563/go.mod h1:n7NCudcB/nEzxVGm 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-20190311212946-11955173bddd/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= -golang.org/x/tools v0.0.0-20190312151545-0bb0c0a6e846/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= -golang.org/x/tools v0.0.0-20190312170243-e65039ee4138/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= -golang.org/x/tools v0.0.0-20190328211700-ab21143f2384/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= -golang.org/x/tools v0.0.0-20190425150028-36563e24a262/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q= -golang.org/x/tools v0.0.0-20190506145303-2d16b83fe98c/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q= golang.org/x/tools v0.0.0-20190524140312-2c0ae7006135/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q= -golang.org/x/tools v0.0.0-20190606124116-d0a3d012864b/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc= -golang.org/x/tools v0.0.0-20190621195816-6e04913cbbac/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc= -golang.org/x/tools v0.0.0-20190628153133-6cdbf07be9d0/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc= -golang.org/x/tools v0.0.0-20190816200558-6889da9d5479/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= -golang.org/x/tools v0.0.0-20190911174233-4f2ddba30aff/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= -golang.org/x/tools v0.0.0-20191012152004-8de300cfc20a/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= -golang.org/x/tools v0.0.0-20191112195655-aa38f8e97acc/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= -golang.org/x/tools v0.0.0-20191113191852-77e3bb0ad9e7/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= -golang.org/x/tools v0.0.0-20191115202509-3a792d9c32b2/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= -golang.org/x/tools v0.0.0-20191125144606-a911d9008d1f/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= -golang.org/x/tools v0.0.0-20191130070609-6e064ea0cf2d/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= -golang.org/x/tools v0.0.0-20191216173652-a0e659d51361/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= -golang.org/x/tools v0.0.0-20191227053925-7b8e75db28f4/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= -golang.org/x/tools v0.0.0-20200117161641-43d50277825c/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= -golang.org/x/tools v0.0.0-20200122220014-bf1340f18c4a/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= -golang.org/x/tools v0.0.0-20200130002326-2f3ba24bd6e7/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= -golang.org/x/tools v0.0.0-20200204074204-1cc6d1ef6c74/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= -golang.org/x/tools v0.0.0-20200207183749-b753a1ba74fa/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= -golang.org/x/tools v0.0.0-20200212150539-ea181f53ac56/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= -golang.org/x/tools v0.0.0-20200224181240-023911ca70b2/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= -golang.org/x/tools v0.0.0-20200227222343-706bc42d1f0d/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= -golang.org/x/tools v0.0.0-20200304193943-95d2e580d8eb/go.mod h1:o4KQGtdN14AW+yjsvvwRTJJuXz8XRtIHtEnmAXLyFUw= -golang.org/x/tools v0.0.0-20200312045724-11d5b4c81c7d/go.mod h1:o4KQGtdN14AW+yjsvvwRTJJuXz8XRtIHtEnmAXLyFUw= -golang.org/x/tools v0.0.0-20200331025713-a30bf2db82d4/go.mod h1:Sl4aGygMT6LrqrWclx+PTx3U+LnKx/seiNR+3G19Ar8= -golang.org/x/tools v0.0.0-20200501065659-ab2804fb9c9d/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= -golang.org/x/tools v0.0.0-20200512131952-2bc93b1c0c88/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= -golang.org/x/tools v0.0.0-20200515010526-7d3b6ebf133d/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= -golang.org/x/tools v0.0.0-20200618134242-20370b0cb4b2/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= golang.org/x/tools v0.0.0-20200619180055-7c47624df98f/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= -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-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-20210105154028-b0ab187a4818/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/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-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1 h1:go1bK/D/BFZV2I8cIQd1NKEZ+0owSTG1fDTci4IqFcE= golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= -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.8.0/go.mod h1:o4eAsZoiT+ibD93RtjEohWalFOjRDx6CVaqeizhEnKg= -google.golang.org/api v0.9.0/go.mod h1:o4eAsZoiT+ibD93RtjEohWalFOjRDx6CVaqeizhEnKg= -google.golang.org/api v0.13.0/go.mod h1:iLdEw5Ide6rF15KTC1Kkl0iskquN2gFfn9o9XIsbkAI= -google.golang.org/api v0.14.0/go.mod h1:iLdEw5Ide6rF15KTC1Kkl0iskquN2gFfn9o9XIsbkAI= -google.golang.org/api v0.15.0/go.mod h1:iLdEw5Ide6rF15KTC1Kkl0iskquN2gFfn9o9XIsbkAI= -google.golang.org/api v0.17.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE= -google.golang.org/api v0.18.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE= -google.golang.org/api v0.19.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE= -google.golang.org/api v0.20.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE= -google.golang.org/api v0.22.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE= -google.golang.org/api v0.24.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.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.44.0/go.mod h1:EBOGZqzyhtvMDoxwS97ctnh0zUmYY6CxqXsc1AvkYD8= google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM= +google.golang.org/appengine v1.4.0 h1:/wp5JvzpHIxhs/dumFmF7BXTf3Z+dd4uXta4kVyO508= 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.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.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-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-20190425155659-357c62f0e4bb/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= -google.golang.org/genproto v0.0.0-20190502173448-54afdca5d873/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= -google.golang.org/genproto v0.0.0-20190801165951-fa694d86fc64/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc= google.golang.org/genproto v0.0.0-20190819201941-24fa4b261c55/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc= -google.golang.org/genproto v0.0.0-20190911173649-1774047e7e51/go.mod h1:IbNlFCBrqXvoKpeg0TB2l7cyZUmoaFKYIwrEpbDKLA8= -google.golang.org/genproto v0.0.0-20191108220845-16a3f7862a1a/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= -google.golang.org/genproto v0.0.0-20191115194625-c23dd37a84c9/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= -google.golang.org/genproto v0.0.0-20191216164720-4f79533eabd1/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= -google.golang.org/genproto v0.0.0-20191230161307-f3c370f40bfb/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= -google.golang.org/genproto v0.0.0-20200115191322-ca5a22157cba/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= -google.golang.org/genproto v0.0.0-20200122232147-0452cf42e150/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= -google.golang.org/genproto v0.0.0-20200204135345-fa8e72b47b90/go.mod h1:GmwEX6Z4W5gMy59cAlVYjN9JhxgbQH6Gn+gFDQe2lzA= -google.golang.org/genproto v0.0.0-20200212174721-66ed5ce911ce/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= -google.golang.org/genproto v0.0.0-20200224152610-e50cd9704f63/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= -google.golang.org/genproto v0.0.0-20200228133532-8c2c7df3a383/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= -google.golang.org/genproto v0.0.0-20200305110556-506484158171/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= -google.golang.org/genproto v0.0.0-20200312145019-da6875a35672/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= -google.golang.org/genproto v0.0.0-20200331122359-1ee6d9798940/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= google.golang.org/genproto v0.0.0-20200423170343-7949de9c1215/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= -google.golang.org/genproto v0.0.0-20200430143042-b979b6f78d84/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= -google.golang.org/genproto v0.0.0-20200511104702-f5ebc3bea380/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= google.golang.org/genproto v0.0.0-20200513103714-09dca8ec2884/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= -google.golang.org/genproto v0.0.0-20200515170657-fc4c6c6a6587/go.mod h1:YsZOwe1myG/8QRHRsmBRE1LrgQY60beZKjly0O1fX9U= google.golang.org/genproto v0.0.0-20200526211855-cb27e3aa2013/go.mod h1:NbSheEEYHJ7i3ixzK3sjbqSGDJWnxyFXZblF3eUsNvo= -google.golang.org/genproto v0.0.0-20200618031413-b414f8b61790/go.mod h1:jDfRM7FcilCzHH/e9qn6dsT145K34l5v+OpcnNgKAAA= -google.golang.org/genproto v0.0.0-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-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-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-20210402141018-6c239bbf2bb1/go.mod h1:9lPAdzaEmUacj36I+k7YKbEc5CXzPIeORRgDAUOu28A= google.golang.org/genproto v0.0.0-20211118181313-81c1377c94b1 h1:b9mVrqYfq3P4bCdaLg1qtBnPzUYgglsIdjZkL/fQVOE= google.golang.org/genproto v0.0.0-20211118181313-81c1377c94b1/go.mod h1:5CzLGKJ67TSI2B9POpiiyGha0AjJvZIUgRMt1dSmuhc= 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.21.1/go.mod h1:oYelfM1adQP15Ek0mdvEgi9Df8B9CZIaU1084ijfRaM= google.golang.org/grpc v1.23.0/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg= google.golang.org/grpc v1.25.1/go.mod h1:c3i+UQWmh7LiEpx4sFZnkU36qjEYZ0imhYfXVyQciAY= -google.golang.org/grpc v1.26.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk= google.golang.org/grpc v1.27.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk= -google.golang.org/grpc v1.27.1/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk= -google.golang.org/grpc v1.28.0/go.mod h1:rpkK4SK4GF4Ach/+MFLZUBavHOvF2JJB5uozKKal+60= 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.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.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.1/go.mod h1:qjiiYl8FncCW8feJPdyg3v6XW24KsRHe+dy9BAGRRjU= 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.40.0/go.mod h1:ogyxbiOoUXAkP+4+xa6PZSE9DZgIHtSpzjDTB9KAK34= google.golang.org/grpc v1.41.0 h1:f+PlOh7QV4iIJkPrx5NQ7qaNGFQ3OTse67yaDHfju4E= google.golang.org/grpc v1.41.0/go.mod h1:U3l9uK9J0sini8mHphKoXyaqDA/8VyGnDee1zzIUK6k= @@ -725,7 +349,6 @@ google.golang.org/protobuf v1.21.0/go.mod h1:47Nbq4nVaFHyn7ilMalzfO3qCViNmqZ2kzi google.golang.org/protobuf v1.22.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= google.golang.org/protobuf v1.23.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= google.golang.org/protobuf v1.23.1-0.20200526195155-81db48ad09cc/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= -google.golang.org/protobuf v1.24.0/go.mod h1:r/3tXBNzIEhYS9I1OUVjXDlt8tc493IdKGjtUeSXeh4= google.golang.org/protobuf v1.25.0/go.mod h1:9JNX74DMeImyA3h4bdi1ymwjUzf21/xIlbajtzgsN7c= google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw= google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc= @@ -733,11 +356,8 @@ google.golang.org/protobuf v1.27.1 h1:SnqbnDw1V7RiZcXPx5MEeqPv2s79L9i7BJUlG/+Rur google.golang.org/protobuf v1.27.1/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc= gopkg.in/alecthomas/kingpin.v2 v2.2.6/go.mod h1:FMv+mEhP44yOT+4EoQTLFTRgOQ1FBLkstjWtayDeSgw= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= -gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15 h1:YR8cESwS4TdDjEe65xsg0ogRM/Nc3DYOhEAlW+xobZo= gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= -gopkg.in/errgo.v2 v2.1.0/go.mod h1:hNsd1EY+bozCKY1Ytp96fpM3vjJbqLJn88ws8XvfDNI= -gopkg.in/ini.v1 v1.62.0/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k= gopkg.in/natefinch/lumberjack.v2 v2.0.0 h1:1Lc07Kr7qY4U2YPouBjpCLxpiyxIVoxqXgkXLknAOE8= gopkg.in/natefinch/lumberjack.v2 v2.0.0/go.mod h1:l0ndWWf7gzL7RNwBG7wST/UCcT4T24xpD6X8LsfU/+k= gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= @@ -753,15 +373,7 @@ gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b h1:h8qDotaEPuJATrMmW04NCwg7v22aHH28wwpauUhK9Oo= gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= -honnef.co/go/tools v0.0.0-20190106161140-3f1c8253044a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= -honnef.co/go/tools v0.0.0-20190418001031-e561f6794a2a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= honnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= -honnef.co/go/tools v0.0.1-2019.2.3/go.mod h1:a3bituU0lyd329TUQxRnasdCoJDkEUEAqEt0JzvZhAg= -honnef.co/go/tools v0.0.1-2020.1.3/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9vFzvIQ3k= -honnef.co/go/tools v0.0.1-2020.1.4/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9vFzvIQ3k= -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/sampler v1.3.0/go.mod h1:T1hPZKmBbMNahiBKFy5HrXp6adAjACjK9JXDnKaTXpA= sigs.k8s.io/json v0.0.0-20211020170558-c049b76a60c6 h1:fD1pz4yfdADVNfFmcP2aBEtudwUQ1AlLnRBALr33v3s= sigs.k8s.io/json v0.0.0-20211020170558-c049b76a60c6/go.mod h1:p4QtZmO4uMYipTQNzagwnNoseA6OxSUutVw05NhYDRs= sigs.k8s.io/yaml v1.2.0 h1:kr/MCeFWJWTwyaHoR9c8EjH9OumOmoF9YGiZd7lFm/Q= From 88a39d780f209945a4cb6d14e70b86fa52d9840e Mon Sep 17 00:00:00 2001 From: Marek Siarkowicz Date: Tue, 29 Mar 2022 17:53:21 +0200 Subject: [PATCH 227/258] changelog: Update and deduplicate production recommendations --- CHANGELOG/CHANGELOG-3.1.md | 4 ---- CHANGELOG/CHANGELOG-3.2.md | 2 -- CHANGELOG/CHANGELOG-3.3.md | 3 --- CHANGELOG/CHANGELOG-3.4.md | 3 --- CHANGELOG/CHANGELOG-3.5.md | 2 -- CHANGELOG/README.md | 21 +++++++++++++++++++++ 6 files changed, 21 insertions(+), 14 deletions(-) create mode 100644 CHANGELOG/README.md diff --git a/CHANGELOG/CHANGELOG-3.1.md b/CHANGELOG/CHANGELOG-3.1.md index 090104fa3c86..0c97517a7e24 100644 --- a/CHANGELOG/CHANGELOG-3.1.md +++ b/CHANGELOG/CHANGELOG-3.1.md @@ -2,10 +2,6 @@ Previous change logs can be found at [CHANGELOG-3.0](https://github.com/etcd-io/etcd/blob/main/CHANGELOG/CHANGELOG-3.0.md). - -The minimum recommended etcd versions to run in **production** are 3.3.18+, 3.4.2+, and 3.5.2+. - -
## [v3.1.21](https://github.com/etcd-io/etcd/releases/tag/v3.1.21) (2019-TBD) diff --git a/CHANGELOG/CHANGELOG-3.2.md b/CHANGELOG/CHANGELOG-3.2.md index 37efc787721a..095ff6e9f2af 100644 --- a/CHANGELOG/CHANGELOG-3.2.md +++ b/CHANGELOG/CHANGELOG-3.2.md @@ -3,8 +3,6 @@ Previous change logs can be found at [CHANGELOG-3.1](https://github.com/etcd-io/etcd/blob/main/CHANGELOG/CHANGELOG-3.1.md). -The minimum recommended etcd versions to run in **production** are 3.3.18+, 3.4.2+, and 3.5.2+. - ## v3.2.33 (TBD)
diff --git a/CHANGELOG/CHANGELOG-3.3.md b/CHANGELOG/CHANGELOG-3.3.md index c7043d730a11..8addba112f6f 100644 --- a/CHANGELOG/CHANGELOG-3.3.md +++ b/CHANGELOG/CHANGELOG-3.3.md @@ -2,9 +2,6 @@ Previous change logs can be found at [CHANGELOG-3.2](https://github.com/etcd-io/etcd/blob/main/CHANGELOG/CHANGELOG-3.2.md). - -The minimum recommended etcd versions to run in **production** are 3.3.18+, 3.4.2+, and 3.5.2+. Refer to the [versioning policy](https://etcd.io/docs/v3.3/op-guide/versioning/) for more details. -
## v3.3.27 (2021-10-15) diff --git a/CHANGELOG/CHANGELOG-3.4.md b/CHANGELOG/CHANGELOG-3.4.md index 4b37e233acda..0eba3053486d 100644 --- a/CHANGELOG/CHANGELOG-3.4.md +++ b/CHANGELOG/CHANGELOG-3.4.md @@ -2,9 +2,6 @@ Previous change logs can be found at [CHANGELOG-3.3](https://github.com/etcd-io/etcd/blob/main/CHANGELOG/CHANGELOG-3.3.md). - -The minimum recommended etcd versions to run in **production** are 3.3.18+, 3.4.2+, and 3.5.2+. Refer to the [versioning policy](https://etcd.io/docs/v3.4/op-guide/versioning/) for more details. -
## v3.4.19 (TODO) diff --git a/CHANGELOG/CHANGELOG-3.5.md b/CHANGELOG/CHANGELOG-3.5.md index 6bf16109d38e..7d2038813a93 100644 --- a/CHANGELOG/CHANGELOG-3.5.md +++ b/CHANGELOG/CHANGELOG-3.5.md @@ -3,8 +3,6 @@ Previous change logs can be found at [CHANGELOG-3.4](https://github.com/etcd-io/etcd/blob/main/CHANGELOG/CHANGELOG-3.4.md). -The minimum recommended etcd versions to run in **production** are 3.3.18+, 3.4.2+, and 3.5.2+. Refer to the [versioning policy](https://etcd.io/docs/v3.5/op-guide/versioning/) for more details. -
## v3.5.3 (TBD) diff --git a/CHANGELOG/README.md b/CHANGELOG/README.md new file mode 100644 index 000000000000..173713e63f15 --- /dev/null +++ b/CHANGELOG/README.md @@ -0,0 +1,21 @@ +# Production recommendation + +The minimum recommended etcd versions to run in **production** are 3.3.18+, 3.4.2+. Refer to the [versioning policy](https://etcd.io/docs/v3.5/op-guide/versioning/) for more details. + +Etcd v3.5.[0-2] versions are no longer recommended for production due to data corruption issue. + +### v3.5 data corruption issue + +Running etcd v3.5.2, v3.5.1 and v3.5.0 under high load can cause a data corruption issue. +If etcd process is killed, occasionally some committed transactions are not reflected on all the members. + +Recommendations if you are running v3.4.X: +* **Don't upgrade your etcd clusters to v3.5** until the problem is fixed in the upcoming v3.5.3 release. +* There are no breaking changes in API, meaning **it’s safe to let v3.5 clients (e.g. the latest Kubernetes releases) talk to v3.4 servers**. + +Recommendations if you are running v3.5.0, v3.5.1, or v3.5.2: +* **Enable data corruption check** with `--experimental-initial-corrupt-check` flag. The flag is the only reliable automated way of detecting an inconsistency. This mode has seen significant usage in production and is going to be promoted as default in etcd v3.6. +* **Ensure etcd cluster is not memory pressured or sigkill interrupted**, which could lead to processes being disrupted in the middle of business logic and trigger the issue. +* **Etcd downgrade should be avoided** as they are not officially supported and clusters can be safely recovered as long as data corruption check is enabled. + +If you have encountered data corruption, please follow instructions on https://etcd.io/docs/v3.5/op-guide/data_corruption/. From 9b3b383366a9c94577888db142c4fbc76bc8500d Mon Sep 17 00:00:00 2001 From: ahrtr Date: Thu, 31 Mar 2022 10:14:46 +0800 Subject: [PATCH 228/258] the file server/storage/mvcc/util.go isn't used at all, so removing it --- server/storage/mvcc/util.go | 37 ------------------------------------- 1 file changed, 37 deletions(-) delete mode 100644 server/storage/mvcc/util.go diff --git a/server/storage/mvcc/util.go b/server/storage/mvcc/util.go deleted file mode 100644 index bf5d9c196bba..000000000000 --- a/server/storage/mvcc/util.go +++ /dev/null @@ -1,37 +0,0 @@ -// Copyright 2016 The etcd Authors -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -package mvcc - -import ( - "fmt" - - "go.etcd.io/etcd/api/v3/mvccpb" - "go.etcd.io/etcd/server/v3/storage/backend" - "go.etcd.io/etcd/server/v3/storage/schema" -) - -func WriteKV(be backend.Backend, kv mvccpb.KeyValue) { - ibytes := newRevBytes() - revToBytes(revision{main: kv.ModRevision}, ibytes) - - d, err := kv.Marshal() - if err != nil { - panic(fmt.Errorf("cannot marshal event: %v", err)) - } - - be.BatchTx().Lock() - be.BatchTx().UnsafePut(schema.Key, ibytes, d) - be.BatchTx().Unlock() -} From ec29b9ee36d2f420a7827d66150ed1c0d5ca7469 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Manuel=20R=C3=BCger?= Date: Thu, 31 Mar 2022 09:48:18 +0200 Subject: [PATCH 229/258] Makefile: Fix wrong target MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Manuel Rüger --- Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Makefile b/Makefile index c6a08e06d34a..ab18f4040c78 100644 --- a/Makefile +++ b/Makefile @@ -108,7 +108,7 @@ test-full: PASSES="fmt build release unit integration functional e2e grpcproxy" ./scripts/test.sh 2<&1 | tee test-$(TEST_SUFFIX).log ensure-docker-test-image-exists: - make push-docker-test || echo "WARNING: Container Image not found in registry, building locally"; make build-docker-test + make pull-docker-test || echo "WARNING: Container Image not found in registry, building locally"; make build-docker-test docker-test: ensure-docker-test-image-exists $(info GO_VERSION: $(GO_VERSION)) From 29905029f695da7942b0762455149c33553a8bfe Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Manuel=20R=C3=BCger?= Date: Thu, 31 Mar 2022 11:18:33 +0200 Subject: [PATCH 230/258] Makefile: Additional logic fix MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Manuel Rüger --- Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Makefile b/Makefile index ab18f4040c78..3d3f4dc3fc6f 100644 --- a/Makefile +++ b/Makefile @@ -108,7 +108,7 @@ test-full: PASSES="fmt build release unit integration functional e2e grpcproxy" ./scripts/test.sh 2<&1 | tee test-$(TEST_SUFFIX).log ensure-docker-test-image-exists: - make pull-docker-test || echo "WARNING: Container Image not found in registry, building locally"; make build-docker-test + make pull-docker-test || ( echo "WARNING: Container Image not found in registry, building locally"; make build-docker-test ) docker-test: ensure-docker-test-image-exists $(info GO_VERSION: $(GO_VERSION)) From e5bf23037ab7ce9453bddade5d339da98724e296 Mon Sep 17 00:00:00 2001 From: Marek Siarkowicz Date: Thu, 31 Mar 2022 20:19:40 +0200 Subject: [PATCH 231/258] tests: Keeps log in expect to allow their analysis --- pkg/expect/expect.go | 59 +++++++++++++++++------------ tests/framework/e2e/etcd_process.go | 2 + tests/framework/e2e/util.go | 18 +++------ 3 files changed, 42 insertions(+), 37 deletions(-) diff --git a/pkg/expect/expect.go b/pkg/expect/expect.go index 3dcc6e8a2ad3..31102c9c1a30 100644 --- a/pkg/expect/expect.go +++ b/pkg/expect/expect.go @@ -25,6 +25,7 @@ import ( "strings" "sync" "syscall" + "time" "github.com/creack/pty" ) @@ -36,7 +37,6 @@ type ExpectProcess struct { fpty *os.File wg sync.WaitGroup - cond *sync.Cond // for broadcasting updates are available mu sync.Mutex // protects lines and err lines []string count int // increment whenever new line gets added @@ -60,7 +60,6 @@ func NewExpectWithEnv(name string, args []string, env []string) (ep *ExpectProce cmd: cmd, StopSignal: syscall.SIGKILL, } - ep.cond = sync.NewCond(&ep.mu) ep.cmd.Stderr = ep.cmd.Stdout ep.cmd.Stdin = nil @@ -77,52 +76,56 @@ func (ep *ExpectProcess) read() { defer ep.wg.Done() printDebugLines := os.Getenv("EXPECT_DEBUG") != "" r := bufio.NewReader(ep.fpty) - for ep.err == nil { - l, rerr := r.ReadString('\n') + for { + l, err := r.ReadString('\n') ep.mu.Lock() - ep.err = rerr if l != "" { if printDebugLines { fmt.Printf("%s-%d: %s", ep.cmd.Path, ep.cmd.Process.Pid, l) } ep.lines = append(ep.lines, l) ep.count++ - if len(ep.lines) == 1 { - ep.cond.Signal() - } + } + if err != nil { + ep.err = err + ep.mu.Unlock() + break } ep.mu.Unlock() } - ep.cond.Signal() } // ExpectFunc returns the first line satisfying the function f. func (ep *ExpectProcess) ExpectFunc(f func(string) bool) (string, error) { - lastLinesBuffer := make([]string, 0) + i := 0 - ep.mu.Lock() for { - for len(ep.lines) == 0 && ep.err == nil { - ep.cond.Wait() - } - if len(ep.lines) == 0 { - break - } - l := ep.lines[0] - ep.lines = ep.lines[1:] - lastLinesBuffer = append(lastLinesBuffer, l) - if l := len(lastLinesBuffer); l > DEBUG_LINES_TAIL { - lastLinesBuffer = lastLinesBuffer[l-DEBUG_LINES_TAIL : l-1] + ep.mu.Lock() + for i < len(ep.lines) { + line := ep.lines[i] + i++ + if f(line) { + ep.mu.Unlock() + return line, nil + } } - if f(l) { + if ep.err != nil { ep.mu.Unlock() - return l, nil + break } + ep.mu.Unlock() + time.Sleep(time.Millisecond * 100) + } + ep.mu.Lock() + lastLinesIndex := len(ep.lines) - DEBUG_LINES_TAIL + if lastLinesIndex < 0 { + lastLinesIndex = 0 } + lastLines := strings.Join(ep.lines[lastLinesIndex:], "") ep.mu.Unlock() return "", fmt.Errorf("match not found."+ " Set EXPECT_DEBUG for more info Err: %v, last lines:\n%s", - ep.err, strings.Join(lastLinesBuffer, "")) + ep.err, lastLines) } // Expect returns the first line containing the given string. @@ -189,3 +192,9 @@ func (ep *ExpectProcess) ProcessError() error { } return ep.err } + +func (ep *ExpectProcess) Lines() []string { + ep.mu.Lock() + defer ep.mu.Unlock() + return ep.lines +} diff --git a/tests/framework/e2e/etcd_process.go b/tests/framework/e2e/etcd_process.go index e31f906aeac5..d80710c4048c 100644 --- a/tests/framework/e2e/etcd_process.go +++ b/tests/framework/e2e/etcd_process.go @@ -48,6 +48,8 @@ type EtcdProcess interface { type LogsExpect interface { Expect(string) (string, error) + Lines() []string + LineCount() int } type EtcdServerProcess struct { diff --git a/tests/framework/e2e/util.go b/tests/framework/e2e/util.go index 7d997e08a92e..6db4e404db8e 100644 --- a/tests/framework/e2e/util.go +++ b/tests/framework/e2e/util.go @@ -61,21 +61,15 @@ func SpawnWithExpectLines(args []string, envVars map[string]string, xs ...string // process until either stdout or stderr contains // the expected string var ( - lines []string - lineFunc = func(txt string) bool { return true } + lines []string ) for _, txt := range xs { - for { - l, lerr := proc.ExpectFunc(lineFunc) - if lerr != nil { - proc.Close() - return nil, fmt.Errorf("%v %v (expected %q, got %q). Try EXPECT_DEBUG=TRUE", args, lerr, txt, lines) - } - lines = append(lines, l) - if strings.Contains(l, txt) { - break - } + l, lerr := proc.Expect(txt) + if lerr != nil { + proc.Close() + return nil, fmt.Errorf("%v %v (expected %q, got %q). Try EXPECT_DEBUG=TRUE", args, lerr, txt, lines) } + lines = append(lines, l) } perr := proc.Close() l := proc.LineCount() From 63346bfead7dd9ad071485d7cc7d6c8bd9fc36b7 Mon Sep 17 00:00:00 2001 From: Marek Siarkowicz Date: Thu, 31 Mar 2022 20:23:45 +0200 Subject: [PATCH 232/258] server: Use default logging configuration instead of zap production one This fixes problem where logs json changes format of timestamp. --- CHANGELOG/CHANGELOG-3.5.md | 1 + CHANGELOG/CHANGELOG-3.6.md | 1 + client/pkg/logutil/zap.go | 11 ++++ client/v3/client.go | 6 +- client/v3/logger.go | 22 +------ client/v3/snapshot/v3_snapshot.go | 3 - etcdctl/ctlv3/command/ep_command.go | 5 +- etcdctl/ctlv3/command/global.go | 7 +- etcdctl/ctlv3/command/snapshot_command.go | 3 +- etcdutl/etcdutl/common.go | 3 +- etcdutl/snapshot/v3_snapshot.go | 3 - pkg/netutil/netutil.go | 6 -- pkg/proxy/server.go | 12 ---- server/etcdmain/config.go | 3 +- server/etcdmain/etcd.go | 12 ++-- server/etcdmain/gateway.go | 4 +- server/etcdmain/grpc_proxy.go | 10 ++- server/etcdmain/main.go | 3 - tests/e2e/zap_logging_test.go | 78 +++++++++++++++++++++++ tests/framework/e2e/cluster.go | 5 ++ 20 files changed, 129 insertions(+), 69 deletions(-) create mode 100644 tests/e2e/zap_logging_test.go diff --git a/CHANGELOG/CHANGELOG-3.5.md b/CHANGELOG/CHANGELOG-3.5.md index 6bf16109d38e..4e8477ad76f1 100644 --- a/CHANGELOG/CHANGELOG-3.5.md +++ b/CHANGELOG/CHANGELOG-3.5.md @@ -11,6 +11,7 @@ The minimum recommended etcd versions to run in **production** are 3.3.18+, 3.4. ### etcd server - Fix [Provide a better liveness probe for when etcd runs as a Kubernetes pod](https://github.com/etcd-io/etcd/pull/13706) +- Fix [inconsistent log format](https://github.com/etcd-io/etcd/pull/13864) ### package `client/pkg/v3` diff --git a/CHANGELOG/CHANGELOG-3.6.md b/CHANGELOG/CHANGELOG-3.6.md index 9210d427f7ca..383cf82e7f1d 100644 --- a/CHANGELOG/CHANGELOG-3.6.md +++ b/CHANGELOG/CHANGELOG-3.6.md @@ -63,6 +63,7 @@ See [code changes](https://github.com/etcd-io/etcd/compare/v3.5.0...v3.6.0). - Fix [A client can cause a nil dereference in etcd by passing an invalid SortTarget](https://github.com/etcd-io/etcd/pull/13555) - Fix [Grant lease with negative ID can possibly cause db out of sync](https://github.com/etcd-io/etcd/pull/13676) - Fix [segmentation violation(SIGSEGV) error due to premature unlocking of watchableStore](https://github.com/etcd-io/etcd/pull/13505) +- Fix [inconsistent log format](https://github.com/etcd-io/etcd/pull/13864) ### tools/benchmark diff --git a/client/pkg/logutil/zap.go b/client/pkg/logutil/zap.go index 33d95e9cb177..0a4374c77b8d 100644 --- a/client/pkg/logutil/zap.go +++ b/client/pkg/logutil/zap.go @@ -21,6 +21,17 @@ import ( "go.uber.org/zap/zapcore" ) +// CreateDefaultZapLogger creates a logger with default zap configuration +func CreateDefaultZapLogger(level zapcore.Level) (*zap.Logger, error) { + lcfg := DefaultZapLoggerConfig + lcfg.Level = zap.NewAtomicLevelAt(level) + c, err := lcfg.Build() + if err != nil { + return nil, err + } + return c, nil +} + // DefaultZapLoggerConfig defines default zap logger configuration. var DefaultZapLoggerConfig = zap.Config{ Level: zap.NewAtomicLevelAt(ConvertToZapLevel(DefaultLogLevel)), diff --git a/client/v3/client.go b/client/v3/client.go index 971fea607cf9..91c091adfc91 100644 --- a/client/v3/client.go +++ b/client/v3/client.go @@ -24,6 +24,7 @@ import ( "time" "go.etcd.io/etcd/api/v3/v3rpc/rpctypes" + "go.etcd.io/etcd/client/pkg/v3/logutil" "go.etcd.io/etcd/client/v3/credentials" "go.etcd.io/etcd/client/v3/internal/endpoint" "go.etcd.io/etcd/client/v3/internal/resolver" @@ -370,7 +371,10 @@ func newClient(cfg *Config) (*Client, error) { } else if cfg.LogConfig != nil { client.lg, err = cfg.LogConfig.Build() } else { - client.lg, err = CreateDefaultZapLogger() + client.lg, err = logutil.CreateDefaultZapLogger(etcdClientDebugLevel()) + if client.lg != nil { + client.lg = client.lg.Named("etcd-client") + } } if err != nil { return nil, err diff --git a/client/v3/logger.go b/client/v3/logger.go index 71a9e161ce84..ecac42730f61 100644 --- a/client/v3/logger.go +++ b/client/v3/logger.go @@ -19,7 +19,6 @@ import ( "os" "go.etcd.io/etcd/client/pkg/v3/logutil" - "go.uber.org/zap" "go.uber.org/zap/zapcore" "go.uber.org/zap/zapgrpc" "google.golang.org/grpc/grpclog" @@ -29,10 +28,11 @@ func init() { // We override grpc logger only when the environment variable is set // in order to not interfere by default with user's code or other libraries. if os.Getenv("ETCD_CLIENT_DEBUG") != "" { - lg, err := CreateDefaultZapLogger() + lg, err := logutil.CreateDefaultZapLogger(etcdClientDebugLevel()) if err != nil { panic(err) } + lg = lg.Named("etcd-client") grpclog.SetLoggerV2(zapgrpc.NewLogger(lg)) } } @@ -57,21 +57,3 @@ func etcdClientDebugLevel() zapcore.Level { } return l } - -// CreateDefaultZapLoggerConfig creates a logger config that is configurable using env variable: -// ETCD_CLIENT_DEBUG= debug|info|warn|error|dpanic|panic|fatal|true (true=info) -func CreateDefaultZapLoggerConfig() zap.Config { - lcfg := logutil.DefaultZapLoggerConfig - lcfg.Level = zap.NewAtomicLevelAt(etcdClientDebugLevel()) - return lcfg -} - -// CreateDefaultZapLogger creates a logger that is configurable using env variable: -// ETCD_CLIENT_DEBUG= debug|info|warn|error|dpanic|panic|fatal|true (true=info) -func CreateDefaultZapLogger() (*zap.Logger, error) { - c, err := CreateDefaultZapLoggerConfig().Build() - if err != nil { - return nil, err - } - return c.Named("etcd-client"), nil -} diff --git a/client/v3/snapshot/v3_snapshot.go b/client/v3/snapshot/v3_snapshot.go index d5a8c2682888..3ad13cf4cbeb 100644 --- a/client/v3/snapshot/v3_snapshot.go +++ b/client/v3/snapshot/v3_snapshot.go @@ -45,9 +45,6 @@ func hasChecksum(n int64) bool { // the selected node. // Etcd Date: Fri, 1 Apr 2022 10:34:52 -0700 Subject: [PATCH 233/258] Makefile: Drop log tee calls We've had these since in one form or another since 23a302364c (Makefile: initial commit, 2017-09-29), but in at least some cases the underlying shell does not pipefail, a test failure gets swallowed, and the make call exits zero despite failing the tests [1]: $ curl -s https://gcsweb-ci.apps.ci.l2s4.p1.openshiftapps.com/gcs/origin-ci-test/pr-logs/pull/openshift_etcd/109/pull-ci-openshift-etcd-openshift-4.11-unit/1509260812278042624/artifacts/test/build-log.txt TEST_OPTS: PASSES='unit' log-file: test-MTY0ODY3MTA1MQo.log PASSES='unit' ./test.sh 2>&1 | tee test-MTY0ODY3MTA1MQo.log % env GO111MODULE=off go get github.com/myitcv/gobin Running with --race Starting at: Wed Mar 30 20:10:52 UTC 2022 'unit' started at Wed Mar 30 20:10:52 UTC 2022 % (cd api && env go test -short -timeout=3m --race ./...) stderr: authpb/auth.pb.go:12:2: open /go/pkg/mod/github.com/gogo/protobuf@v1.3.2/gogoproto: permission denied stderr: authpb/auth.pb.go:13:2: open /go/pkg/mod/github.com/golang/protobuf@v1.5.2/proto: permission denied stderr: etcdserverpb/rpc.pb.go:17:2: open /go/pkg/mod/google.golang.org/genproto@v0.0.0-20210602131652-f16073e35f0c/googleapis/api/annotations: permission denied stderr: etcdserverpb/rpc.pb.go:18:2: open /go/pkg/mod/google.golang.org/grpc@v1.38.0: permission denied stderr: etcdserverpb/rpc.pb.go:19:2: open /go/pkg/mod/google.golang.org/grpc@v1.38.0/codes: permission denied stderr: etcdserverpb/rpc.pb.go:20:2: open /go/pkg/mod/google.golang.org/grpc@v1.38.0/status: permission denied stderr: etcdserverpb/gw/rpc.pb.gw.go:17:2: open /go/pkg/mod/github.com/golang/protobuf@v1.5.2/descriptor: permission denied stderr: etcdserverpb/gw/rpc.pb.gw.go:19:2: open /go/pkg/mod/github.com/grpc-ecosystem/grpc-gateway@v1.16.0/runtime: permission denied stderr: etcdserverpb/gw/rpc.pb.gw.go:20:2: open /go/pkg/mod/github.com/grpc-ecosystem/grpc-gateway@v1.16.0/utilities: permission denied FAIL: (code:1): % (cd api && env go test -short -timeout=3m --race ./...) stderr: etcdserverpb/gw/rpc.pb.gw.go:23:2: open /go/pkg/mod/google.golang.org/grpc@v1.38.0/grpclog: permission denied stderr: version/version.go:23:2: open /go/pkg/mod/github.com/coreos/go-semver@v0.3.0/semver: permission denied FAIL: 'unit' failed at Wed Mar 30 20:10:52 UTC 2022 ! egrep "(--- FAIL:|DATA RACE|panic: test timed out|appears to have leaked)" -B50 -A10 test-MTY0ODY3MTA1MQo.log We can't drop the log aggregation, because the log files are used for the panic/race grepping. But I'm dropping the tee (so no more synchronous updates, but we no longer have to worry about pipefail handling). And then if the test script fails, I'm dumping the log file to stdout and exiting 1, so the overall run fails. [1]: https://prow.ci.openshift.org/view/gs/origin-ci-test/pr-logs/pull/openshift_etcd/109/pull-ci-openshift-etcd-openshift-4.11-unit/1509260812278042624 --- Makefile | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/Makefile b/Makefile index ab18f4040c78..2768123c72c9 100644 --- a/Makefile +++ b/Makefile @@ -96,16 +96,16 @@ pull-docker-test: test: $(info TEST_OPTS: $(TEST_OPTS)) $(info log-file: test-$(TEST_SUFFIX).log) - $(TEST_OPTS) ./scripts/test.sh 2>&1 | tee test-$(TEST_SUFFIX).log + $(TEST_OPTS) ./scripts/test.sh > test-$(TEST_SUFFIX).log 2>&1 || (cat test-$(TEST_SUFFIX).log && exit 1) ! egrep "(--- FAIL:|FAIL:|DATA RACE|panic: test timed out|appears to have leaked)" -B50 -A10 test-$(TEST_SUFFIX).log test-smoke: $(info log-file: test-$(TEST_SUFFIX).log) - PASSES="fmt build unit" ./scripts/test.sh 2<&1 | tee test-$(TEST_SUFFIX).log + PASSES="fmt build unit" ./scripts/test.sh > test-$(TEST_SUFFIX).log 2>&1 || (cat test-$(TEST_SUFFIX).log && exit 1) test-full: $(info log-file: test-$(TEST_SUFFIX).log) - PASSES="fmt build release unit integration functional e2e grpcproxy" ./scripts/test.sh 2<&1 | tee test-$(TEST_SUFFIX).log + PASSES="fmt build release unit integration functional e2e grpcproxy" ./scripts/test.sh > test-$(TEST_SUFFIX).log 2>&1 || (cat test-$(TEST_SUFFIX).log && exit 1) ensure-docker-test-image-exists: make pull-docker-test || echo "WARNING: Container Image not found in registry, building locally"; make build-docker-test @@ -122,7 +122,7 @@ docker-test: ensure-docker-test-image-exists $(TMP_DIR_MOUNT_FLAG) \ --mount type=bind,source=`pwd`,destination=/go/src/go.etcd.io/etcd \ gcr.io/etcd-development/etcd-test:go$(GO_VERSION) \ - /bin/bash -c "$(TEST_OPTS) ./scripts/test.sh 2>&1 | tee test-$(TEST_SUFFIX).log" + /bin/bash -c "$(TEST_OPTS) ./scripts/test.sh 2>&1" > test-$(TEST_SUFFIX).log 2>&1 || (cat test-$(TEST_SUFFIX).log && exit 1) ! egrep "(--- FAIL:|FAIL:|DATA RACE|panic: test timed out|appears to have leaked)" -B50 -A10 test-$(TEST_SUFFIX).log docker-test-coverage: From f9c9bfa44ccca839338e3dedfca2b1f203900c97 Mon Sep 17 00:00:00 2001 From: howz97 <964701944@qq.com> Date: Sat, 2 Apr 2022 14:27:33 +0800 Subject: [PATCH 234/258] fix comment in raft.go --- raft/raft.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/raft/raft.go b/raft/raft.go index 5e3026ac8877..14b5b76dda10 100644 --- a/raft/raft.go +++ b/raft/raft.go @@ -1154,7 +1154,7 @@ func stepLeader(r *raft, m pb.Message) error { // the rejection's log term. If a probe at one of these indexes // succeeded, its log term at that index would match the leader's, // i.e. 3 or 5 in this example. But the follower already told the - // leader that it is still at term 2 at index 9, and since the + // leader that it is still at term 2 at index 6, and since the // log term only ever goes up (within a log), this is a contradiction. // // At index 1, however, the leader can draw no such conclusion, From 3b589fb3b2a2c3a3e34a998e8806d1e8641c61f0 Mon Sep 17 00:00:00 2001 From: Piotr Tabor Date: Sat, 2 Apr 2022 15:22:41 +0200 Subject: [PATCH 235/258] Fix TestauthTokenBundleOnOverwrite on OsX: ``` % (cd client/v3 && env go test -short -timeout=3m --race ./...) --- FAIL: TestAuthTokenBundleNoOverwrite (0.00s) client_test.go:210: listen unix /var/folders/t1/3m8z9xz93t9c3vpt7zyzjm6w00374n/T/TestAuthTokenBundleNoOverwrite3197524989/001/etcd-auth-test:0: bind: invalid argument FAIL FAIL go.etcd.io/etcd/client/v3 4.270s ``` The reason was that the path exceeded 108 chars (that is too much for socket). In the mitigation we first change chroot (working directory) to the tempDir... such the path is 'local'. --- client/pkg/testutil/before.go | 40 ++++++++++++++++++++++++++++++++++ client/v3/client_test.go | 8 +++++-- tests/framework/e2e/testing.go | 14 +----------- 3 files changed, 47 insertions(+), 15 deletions(-) create mode 100644 client/pkg/testutil/before.go diff --git a/client/pkg/testutil/before.go b/client/pkg/testutil/before.go new file mode 100644 index 000000000000..801aa042da5e --- /dev/null +++ b/client/pkg/testutil/before.go @@ -0,0 +1,40 @@ +// Copyright 2022 The etcd Authors +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package testutil + +import ( + "os" + "testing" + + "github.com/stretchr/testify/assert" +) + +// These are constants from "go.etcd.io/etcd/server/v3/verify", +// but we don't want to take dependency. +const ENV_VERIFY = "ETCD_VERIFY" +const ENV_VERIFY_ALL_VALUE = "all" + +func BeforeTest(t testing.TB) { + RegisterLeakDetection(t) + os.Setenv(ENV_VERIFY, ENV_VERIFY_ALL_VALUE) + + path, err := os.Getwd() + assert.NoError(t, err) + tempDir := t.TempDir() + assert.NoError(t, os.Chdir(tempDir)) + t.Logf("Changing working directory to: %s", tempDir) + + t.Cleanup(func() { assert.NoError(t, os.Chdir(path)) }) +} diff --git a/client/v3/client_test.go b/client/v3/client_test.go index b8c62a95b9c7..4884fe6466e0 100644 --- a/client/v3/client_test.go +++ b/client/v3/client_test.go @@ -18,7 +18,6 @@ import ( "context" "fmt" "net" - "path/filepath" "testing" "time" @@ -204,8 +203,13 @@ func TestZapWithLogger(t *testing.T) { } func TestAuthTokenBundleNoOverwrite(t *testing.T) { + // This call in particular changes working directory to the tmp dir of + // the test. The `etcd-auth-test:0` can be created in local directory, + // not exceeding the longest allowed path on OsX. + testutil.BeforeTest(t) + // Create a mock AuthServer to handle Authenticate RPCs. - lis, err := net.Listen("unix", filepath.Join(t.TempDir(), "etcd-auth-test:0")) + lis, err := net.Listen("unix", "etcd-auth-test:0") if err != nil { t.Fatal(err) } diff --git a/tests/framework/e2e/testing.go b/tests/framework/e2e/testing.go index e1447146c50a..7d7de27fdddf 100644 --- a/tests/framework/e2e/testing.go +++ b/tests/framework/e2e/testing.go @@ -15,24 +15,12 @@ package e2e import ( - "os" "testing" - "github.com/stretchr/testify/assert" "go.etcd.io/etcd/client/pkg/v3/testutil" - "go.etcd.io/etcd/server/v3/verify" ) func BeforeTest(t testing.TB) { SkipInShortMode(t) - testutil.RegisterLeakDetection(t) - os.Setenv(verify.ENV_VERIFY, verify.ENV_VERIFY_ALL_VALUE) - - path, err := os.Getwd() - assert.NoError(t, err) - tempDir := t.TempDir() - assert.NoError(t, os.Chdir(tempDir)) - t.Logf("Changing working directory to: %s", tempDir) - - t.Cleanup(func() { assert.NoError(t, os.Chdir(path)) }) + testutil.BeforeTest(t) } From 8cd8a1ea10abf73c2bc5462a0c3b5c254028b551 Mon Sep 17 00:00:00 2001 From: Piotr Tabor Date: Sat, 2 Apr 2022 16:16:25 +0200 Subject: [PATCH 236/258] Flakes in integration/clientv3/examples/... The tests sometimes flaked due to already existing socket-files. Now each execution works in a tempoarary directory. --- tests/integration/clientv3/examples/main_test.go | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/tests/integration/clientv3/examples/main_test.go b/tests/integration/clientv3/examples/main_test.go index d347fa730414..223ec2cdb96f 100644 --- a/tests/integration/clientv3/examples/main_test.go +++ b/tests/integration/clientv3/examples/main_test.go @@ -15,6 +15,7 @@ package clientv3_test import ( + "log" "os" "testing" "time" @@ -44,6 +45,16 @@ func forUnitTestsRunInMockedContext(mocking func(), example func()) { // TestMain sets up an etcd cluster if running the examples. func TestMain(m *testing.M) { testutil.ExitInShortMode("Skipping: the tests require real cluster") + + tempDir := os.TempDir() + defer os.RemoveAll(tempDir) + + err := os.Chdir(tempDir) + if err != nil { + log.Printf("Failed to change working dir to: %s: %v", tempDir, err) + os.Exit(1) + } + v := m.Run() lazyCluster.Terminate() From 836bd6bc3a7669b25169b4d666c404ad1cdc751f Mon Sep 17 00:00:00 2001 From: ahrtr Date: Sun, 3 Apr 2022 06:01:10 +0800 Subject: [PATCH 237/258] fix WARNING: DATA RACE issue when multiple goroutines access the backend concurrently --- server/etcdserver/adapters.go | 8 ++++++++ server/etcdserver/server.go | 6 +++--- server/etcdserver/v3_server.go | 4 ++++ server/storage/backend/backend.go | 2 ++ 4 files changed, 17 insertions(+), 3 deletions(-) diff --git a/server/etcdserver/adapters.go b/server/etcdserver/adapters.go index c3a17c6ee205..9511bc6a6acf 100644 --- a/server/etcdserver/adapters.go +++ b/server/etcdserver/adapters.go @@ -74,6 +74,10 @@ func (s *serverVersionAdapter) GetMembersVersions() map[string]*version.Versions } func (s *serverVersionAdapter) GetStorageVersion() *semver.Version { + // `applySnapshot` sets a new backend instance, so we need to acquire the bemu lock. + s.bemu.RLock() + defer s.bemu.RUnlock() + tx := s.be.BatchTx() tx.Lock() defer tx.Unlock() @@ -85,6 +89,10 @@ func (s *serverVersionAdapter) GetStorageVersion() *semver.Version { } func (s *serverVersionAdapter) UpdateStorageVersion(target semver.Version) error { + // `applySnapshot` sets a new backend instance, so we need to acquire the bemu lock. + s.bemu.RLock() + defer s.bemu.RUnlock() + tx := s.be.BatchTx() tx.Lock() defer tx.Unlock() diff --git a/server/etcdserver/server.go b/server/etcdserver/server.go index e925f47d4501..f5632318eab6 100644 --- a/server/etcdserver/server.go +++ b/server/etcdserver/server.go @@ -256,7 +256,7 @@ type EtcdServer struct { kv mvcc.WatchableKV lessor lease.Lessor - bemu sync.Mutex + bemu sync.RWMutex be backend.Backend beHooks *serverstorage.BackendHooks authStore auth.AuthStore @@ -2229,8 +2229,8 @@ func (s *EtcdServer) parseProposeCtxErr(err error, start time.Time) error { func (s *EtcdServer) KV() mvcc.WatchableKV { return s.kv } func (s *EtcdServer) Backend() backend.Backend { - s.bemu.Lock() - defer s.bemu.Unlock() + s.bemu.RLock() + defer s.bemu.RUnlock() return s.be } diff --git a/server/etcdserver/v3_server.go b/server/etcdserver/v3_server.go index 3e868bebda98..7da9a2c4d04e 100644 --- a/server/etcdserver/v3_server.go +++ b/server/etcdserver/v3_server.go @@ -237,7 +237,11 @@ func (s *EtcdServer) Compact(ctx context.Context, r *pb.CompactionRequest) (*pb. // the hash may revert to a hash prior to compaction completing // if the compaction resumes. Force the finished compaction to // commit so it won't resume following a crash. + // + // `applySnapshot` sets a new backend instance, so we need to acquire the bemu lock. + s.bemu.RLock() s.be.ForceCommit() + s.bemu.RUnlock() trace.Step("physically apply compaction") } if err != nil { diff --git a/server/storage/backend/backend.go b/server/storage/backend/backend.go index c558ecacd68a..67cfab9dd3a8 100644 --- a/server/storage/backend/backend.go +++ b/server/storage/backend/backend.go @@ -419,6 +419,8 @@ func (b *backend) run() { func (b *backend) Close() error { close(b.stopc) <-b.donec + b.mu.Lock() + defer b.mu.Unlock() return b.db.Close() } From 2fab3f3ae5fba86d7b9934911c25230367be01b6 Mon Sep 17 00:00:00 2001 From: Piotr Tabor Date: Sun, 3 Apr 2022 09:16:55 +0200 Subject: [PATCH 238/258] Make naming of test-nodes consistent and positive: m0, m1, m2 The nodes used to be named: m-1, m0, m1, that was generating very confusing logs in integration tests. --- tests/framework/integration/cluster.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/framework/integration/cluster.go b/tests/framework/integration/cluster.go index a0479689473e..19618aff9623 100644 --- a/tests/framework/integration/cluster.go +++ b/tests/framework/integration/cluster.go @@ -259,7 +259,7 @@ func (c *Cluster) mustNewMember(t testutil.TB) *Member { c.LastMemberNum++ m := MustNewMember(t, MemberConfig{ - Name: fmt.Sprintf("m%v", memberNumber-1), + Name: fmt.Sprintf("m%v", memberNumber), MemberNumber: memberNumber, AuthToken: c.Cfg.AuthToken, PeerTLS: c.Cfg.PeerTLS, From d57f8dba628a37418680adbce53340d5f7d31945 Mon Sep 17 00:00:00 2001 From: Piotr Tabor Date: Sun, 3 Apr 2022 09:17:10 +0200 Subject: [PATCH 239/258] Deflaking: Make WaitLeader (and WaitMembersForLeader) aggressively (30s) wait for leader being established. Nearly none of the tests was checking the value... just assuming WaitLeader success. ``` maintenance_test.go:277: Waiting for leader... logger.go:130: 2022-04-03T08:01:09.914+0200 INFO m0 cluster version differs from storage version. {"member": "m0", "cluster-version": "3.6.0", "storage-version": "3.5.0"} logger.go:130: 2022-04-03T08:01:09.915+0200 WARN m0 leader failed to send out heartbeat on time; took too long, leader is overloaded likely from slow disk {"member": "m0", "to": "2acc3d3b521981", "heartbeat-interval": "10ms", "expected-duration": "20ms", "exceeded-duration": "103.756219ms"} logger.go:130: 2022-04-03T08:01:09.916+0200 INFO m0 updated storage version {"member": "m0", "new-storage-version": "3.6.0"} ... logger.go:130: 2022-04-03T08:01:09.926+0200 INFO grpc [[roundrobin] roundrobinPicker: Build called with info: {map[0xc002630ac0:{{unix:localhost:m0 localhost 0 }} 0xc002630af0:{{unix:localhost:m1 localhost 0 }} 0xc002630b20:{{unix:localhost:m2 localhost 0 }}]}] logger.go:130: 2022-04-03T08:01:09.926+0200 WARN m0 apply request took too long {"member": "m0", "took": "114.661766ms", "expected-duration": "100ms", "prefix": "", "request": "header: cluster_version_set: ", "response": ""} logger.go:130: 2022-04-03T08:01:09.927+0200 INFO m0 cluster version is updated {"member": "m0", "cluster-version": "3.6"} logger.go:130: 2022-04-03T08:01:09.955+0200 INFO m2.raft 9f96af25a04e2ec3 [logterm: 2, index: 8, vote: 9903a56eaf96afac] ignored MsgVote from 2acc3d3b521981 [logterm: 2, index: 8] at term 2: lease is not expired (remaining ticks: 10) {"member": "m2"} logger.go:130: 2022-04-03T08:01:09.955+0200 INFO m0.raft 9903a56eaf96afac [logterm: 2, index: 8, vote: 9903a56eaf96afac] ignored MsgVote from 2acc3d3b521981 [logterm: 2, index: 8] at term 2: lease is not expired (remaining ticks: 5) {"member": "m0"} logger.go:130: 2022-04-03T08:01:09.955+0200 INFO m0.raft 9903a56eaf96afac [term: 2] received a MsgAppResp message with higher term from 2acc3d3b521981 [term: 3] {"member": "m0"} logger.go:130: 2022-04-03T08:01:09.955+0200 INFO m0.raft 9903a56eaf96afac became follower at term 3 {"member": "m0"} logger.go:130: 2022-04-03T08:01:09.955+0200 INFO m0.raft raft.node: 9903a56eaf96afac lost leader 9903a56eaf96afac at term 3 {"member": "m0"} maintenance_test.go:279: Leader established. ``` Tmp --- tests/framework/integration/cluster.go | 41 +++++++++++++++++-- .../integration/clientv3/maintenance_test.go | 5 +++ tests/integration/clientv3/watch_test.go | 10 +---- 3 files changed, 43 insertions(+), 13 deletions(-) diff --git a/tests/framework/integration/cluster.go b/tests/framework/integration/cluster.go index 19618aff9623..b09d0547097b 100644 --- a/tests/framework/integration/cluster.go +++ b/tests/framework/integration/cluster.go @@ -398,12 +398,43 @@ func (c *Cluster) WaitMembersMatch(t testutil.TB, membs []*pb.Member) { } } -// WaitLeader returns index of the member in c.Members that is leader (or -1). -func (c *Cluster) WaitLeader(t testutil.TB) int { return c.WaitMembersForLeader(t, c.Members) } +// WaitLeader returns index of the member in c.Members that is leader +// or fails the test (if not established in 30min). +func (c *Cluster) WaitLeader(t testutil.TB) int { + return c.WaitMembersForLeader(t, c.Members) +} // WaitMembersForLeader waits until given members agree on the same leader, -// and returns its 'index' in the 'membs' list (or -1). +// and returns its 'index' in the 'membs' list func (c *Cluster) WaitMembersForLeader(t testutil.TB, membs []*Member) int { + t.Logf("WaitMembersForLeader") + ctx, cancel := context.WithTimeout(context.Background(), 30*time.Second) + defer cancel() + l := 0 + for l = c.waitMembersForLeader(t, ctx, membs); l < 0; { + if ctx.Err() != nil { + t.Fatal("WaitLeader FAILED: %v", ctx.Err()) + } + } + t.Logf("WaitMembersForLeader succeeded. Cluster leader index: %v", l) + + // TODO: Consider second pass check as sometimes leadership is lost + // soon after election: + // + // We perform multiple attempts, as some-times just after successful WaitLLeader + // there is a race and leadership is quickly lost: + // - MsgAppResp message with higher term from 2acc3d3b521981 [term: 3] {"member": "m0"} + // - 9903a56eaf96afac became follower at term 3 {"member": "m0"} + // - 9903a56eaf96afac lost leader 9903a56eaf96afac at term 3 {"member": "m0"} + + + return l +} + +// WaitMembersForLeader waits until given members agree on the same leader, +// and returns its 'index' in the 'membs' list +func (c *Cluster) waitMembersForLeader(t testutil.TB, ctx context.Context, membs []*Member) int { + t.Logf("WaitMembersForLeader...") possibleLead := make(map[uint64]bool) var lead uint64 for _, m := range membs { @@ -415,7 +446,7 @@ func (c *Cluster) WaitMembersForLeader(t testutil.TB, membs []*Member) int { } // ensure leader is up via linearizable get for { - ctx, cancel := context.WithTimeout(context.Background(), 10*TickDuration+time.Second) + ctx, cancel := context.WithTimeout(ctx, 10*TickDuration+time.Second) _, err := cc.Get(ctx, "0") cancel() if err == nil || strings.Contains(err.Error(), "Key not found") { @@ -442,10 +473,12 @@ func (c *Cluster) WaitMembersForLeader(t testutil.TB, membs []*Member) int { for i, m := range membs { if uint64(m.Server.ID()) == lead { + t.Logf("WaitMembersForLeader found leader. Member: %v lead: %x", i, lead) return i } } + t.Logf("WaitMembersForLeader FAILED (-1)") return -1 } diff --git a/tests/integration/clientv3/maintenance_test.go b/tests/integration/clientv3/maintenance_test.go index ce1e629c0105..75b134413cce 100644 --- a/tests/integration/clientv3/maintenance_test.go +++ b/tests/integration/clientv3/maintenance_test.go @@ -274,18 +274,22 @@ func TestMaintenanceStatus(t *testing.T) { clus := integration2.NewCluster(t, &integration2.ClusterConfig{Size: 3}) defer clus.Terminate(t) + t.Logf("Waiting for leader...") clus.WaitLeader(t) + t.Logf("Leader established.") eps := make([]string, 3) for i := 0; i < 3; i++ { eps[i] = clus.Members[i].GRPCURL() } + t.Logf("Creating client...") cli, err := integration2.NewClient(t, clientv3.Config{Endpoints: eps, DialOptions: []grpc.DialOption{grpc.WithBlock()}}) if err != nil { t.Fatal(err) } defer cli.Close() + t.Logf("Creating client [DONE]") prevID, leaderFound := uint64(0), false for i := 0; i < 3; i++ { @@ -293,6 +297,7 @@ func TestMaintenanceStatus(t *testing.T) { if err != nil { t.Fatal(err) } + t.Logf("Response from %v: %v", i, resp) if prevID == 0 { prevID, leaderFound = resp.Header.MemberId, resp.Header.MemberId == resp.Leader continue diff --git a/tests/integration/clientv3/watch_test.go b/tests/integration/clientv3/watch_test.go index f464ec9bb964..d52cb8a7cba3 100644 --- a/tests/integration/clientv3/watch_test.go +++ b/tests/integration/clientv3/watch_test.go @@ -415,15 +415,7 @@ func TestWatchResumeCompacted(t *testing.T) { } clus.Members[0].Stop(t) - ticker := time.After(time.Second * 10) - for clus.WaitLeader(t) <= 0 { - select { - case <-ticker: - t.Fatalf("failed to wait for new leader") - default: - time.Sleep(10 * time.Millisecond) - } - } + clus.WaitLeader(t) // put some data and compact away numPuts := 5 From 68f2cb8c7736e2b80fb9aceef6127563884d9ea4 Mon Sep 17 00:00:00 2001 From: Piotr Tabor Date: Sun, 3 Apr 2022 10:46:51 +0200 Subject: [PATCH 240/258] Fix ExampleAuth from integration/clientv3/examples (on OsX) The code now ensures that each of the test is running in its own directory as opposed to shared os.tempdir. ``` $ (cd tests && env go test -timeout=15m --race go.etcd.io/etcd/tests/v3/integration/clientv3/examples -run ExampleAuth) 2022/04/03 10:24:59 Running tests (examples): ... 2022/04/03 10:24:59 the function can be called only in the test context. Was integration.BeforeTest() called ? 2022/04/03 10:24:59 2022-04-03T10:24:59.462+0200 INFO m0 LISTEN GRPC {"member": "m0", "grpcAddr": "localhost:m0", "m.Name": "m0"} ``` --- client/pkg/testutil/before.go | 20 +++++++++++++ tests/framework/integration/cluster.go | 28 +++++++++++++------ .../clientv3/concurrency/main_test.go | 3 +- .../clientv3/examples/main_test.go | 13 ++++++--- tests/integration/lazy_cluster.go | 2 ++ 5 files changed, 52 insertions(+), 14 deletions(-) diff --git a/client/pkg/testutil/before.go b/client/pkg/testutil/before.go index 801aa042da5e..c3a01b1e6b9f 100644 --- a/client/pkg/testutil/before.go +++ b/client/pkg/testutil/before.go @@ -15,6 +15,8 @@ package testutil import ( + "io/ioutil" + "log" "os" "testing" @@ -38,3 +40,21 @@ func BeforeTest(t testing.TB) { t.Cleanup(func() { assert.NoError(t, os.Chdir(path)) }) } + +func BeforeIntegrationExamples(*testing.M) func() { + ExitInShortMode("Skipping: the tests require real cluster") + + tempDir, err := ioutil.TempDir(os.TempDir(), "etcd-integration") + if err != nil { + log.Printf("Failed to obtain tempDir: %v", tempDir) + os.Exit(1) + } + + err = os.Chdir(tempDir) + if err != nil { + log.Printf("Failed to change working dir to: %s: %v", tempDir, err) + os.Exit(1) + } + log.Printf("Running tests (examples) in dir(%v): ...", tempDir) + return func() { os.RemoveAll(tempDir) } +} diff --git a/tests/framework/integration/cluster.go b/tests/framework/integration/cluster.go index b09d0547097b..089a0d29a5d9 100644 --- a/tests/framework/integration/cluster.go +++ b/tests/framework/integration/cluster.go @@ -214,6 +214,7 @@ func (c *Cluster) fillClusterForMembers() error { } func (c *Cluster) Launch(t testutil.TB) { + t.Logf("Launching new cluster...") errc := make(chan error) for _, m := range c.Members { // Members are launched in separate goroutines because if they boot @@ -411,7 +412,7 @@ func (c *Cluster) WaitMembersForLeader(t testutil.TB, membs []*Member) int { ctx, cancel := context.WithTimeout(context.Background(), 30*time.Second) defer cancel() l := 0 - for l = c.waitMembersForLeader(t, ctx, membs); l < 0; { + for l = c.waitMembersForLeader(ctx, t, membs); l < 0; { if ctx.Err() != nil { t.Fatal("WaitLeader FAILED: %v", ctx.Err()) } @@ -427,14 +428,12 @@ func (c *Cluster) WaitMembersForLeader(t testutil.TB, membs []*Member) int { // - 9903a56eaf96afac became follower at term 3 {"member": "m0"} // - 9903a56eaf96afac lost leader 9903a56eaf96afac at term 3 {"member": "m0"} - return l } // WaitMembersForLeader waits until given members agree on the same leader, // and returns its 'index' in the 'membs' list -func (c *Cluster) waitMembersForLeader(t testutil.TB, ctx context.Context, membs []*Member) int { - t.Logf("WaitMembersForLeader...") +func (c *Cluster) waitMembersForLeader(ctx context.Context, t testutil.TB, membs []*Member) int { possibleLead := make(map[uint64]bool) var lead uint64 for _, m := range membs { @@ -473,12 +472,12 @@ func (c *Cluster) waitMembersForLeader(t testutil.TB, ctx context.Context, membs for i, m := range membs { if uint64(m.Server.ID()) == lead { - t.Logf("WaitMembersForLeader found leader. Member: %v lead: %x", i, lead) + t.Logf("waitMembersForLeader found leader. Member: %v lead: %x", i, lead) return i } } - t.Logf("WaitMembersForLeader FAILED (-1)") + t.Logf("waitMembersForLeader failed (-1)") return -1 } @@ -531,6 +530,7 @@ func newLocalListener(t testutil.TB) net.Listener { } func NewListenerWithAddr(t testutil.TB, addr string) net.Listener { + t.Logf("Creating listener with addr: %v", addr) l, err := transport.NewUnixListener(addr) if err != nil { t.Fatal(err) @@ -722,7 +722,7 @@ func MustNewMember(t testutil.TB, mcfg MemberConfig) *Member { m.Logger = memberLogger(t, mcfg.Name) m.StrictReconfigCheck = mcfg.StrictReconfigCheck if err := m.listenGRPC(); err != nil { - t.Fatal(err) + t.Fatalf("listenGRPC FAILED: %v", err) } t.Cleanup(func() { // if we didn't cleanup the logger, the consecutive test @@ -747,7 +747,11 @@ func (m *Member) listenGRPC() error { // prefix with localhost so cert has right domain network, host, port := m.grpcAddr() grpcAddr := host + ":" + port - m.Logger.Info("LISTEN GRPC", zap.String("grpcAddr", grpcAddr), zap.String("m.Name", m.Name)) + wd, err := os.Getwd() + if err != nil { + return err + } + m.Logger.Info("LISTEN GRPC", zap.String("grpcAddr", grpcAddr), zap.String("m.Name", m.Name), zap.String("workdir", wd)) grpcListener, err := net.Listen(network, grpcAddr) if err != nil { return fmt.Errorf("listen failed on grpc socket %s (%v)", grpcAddr, err) @@ -1346,7 +1350,7 @@ func NewCluster(t testutil.TB, cfg *ClusterConfig) *Cluster { } c.Members = ms if err := c.fillClusterForMembers(); err != nil { - t.Fatal(err) + t.Fatalf("fillClusterForMembers failed: %v", err) } c.Launch(t) @@ -1360,6 +1364,9 @@ func (c *Cluster) TakeClient(idx int) { } func (c *Cluster) Terminate(t testutil.TB) { + if t != nil { + t.Logf("========= Cluster termination started =====================") + } c.mu.Lock() if c.clusterClient != nil { if err := c.clusterClient.Close(); err != nil { @@ -1381,6 +1388,9 @@ func (c *Cluster) Terminate(t testutil.TB) { }(m) } wg.Wait() + if t != nil { + t.Logf("========= Cluster termination succeeded ===================") + } } func (c *Cluster) RandClient() *clientv3.Client { diff --git a/tests/integration/clientv3/concurrency/main_test.go b/tests/integration/clientv3/concurrency/main_test.go index c54df6b4b0f8..62a6e73a03e0 100644 --- a/tests/integration/clientv3/concurrency/main_test.go +++ b/tests/integration/clientv3/concurrency/main_test.go @@ -33,12 +33,13 @@ func forUnitTestsRunInMockedContext(mocking func(), example func()) { // TestMain sets up an etcd cluster if running the examples. func TestMain(m *testing.M) { - testutil.ExitInShortMode("Skipping: the tests require real cluster") + cleanup := testutil.BeforeIntegrationExamples(m) v := m.Run() lazyCluster.Terminate() if v == 0 { testutil.MustCheckLeakedGoroutine() } + cleanup() os.Exit(v) } diff --git a/tests/integration/clientv3/examples/main_test.go b/tests/integration/clientv3/examples/main_test.go index 223ec2cdb96f..5803739f0e10 100644 --- a/tests/integration/clientv3/examples/main_test.go +++ b/tests/integration/clientv3/examples/main_test.go @@ -15,6 +15,7 @@ package clientv3_test import ( + "io/ioutil" "log" "os" "testing" @@ -37,7 +38,7 @@ var lazyCluster = integration.NewLazyClusterWithConfig( func exampleEndpoints() []string { return lazyCluster.EndpointsV3() } -func forUnitTestsRunInMockedContext(mocking func(), example func()) { +func forUnitTestsRunInMockedContext(_ func(), example func()) { // For integration tests runs in the provided environment example() } @@ -46,15 +47,19 @@ func forUnitTestsRunInMockedContext(mocking func(), example func()) { func TestMain(m *testing.M) { testutil.ExitInShortMode("Skipping: the tests require real cluster") - tempDir := os.TempDir() + tempDir, err := ioutil.TempDir(os.TempDir(), "etcd-integration") + if err != nil { + log.Printf("Failed to obtain tempDir: %v", tempDir) + os.Exit(1) + } defer os.RemoveAll(tempDir) - err := os.Chdir(tempDir) + err = os.Chdir(tempDir) if err != nil { log.Printf("Failed to change working dir to: %s: %v", tempDir, err) os.Exit(1) } - + log.Printf("Running tests (examples) in dir(%v): ...", tempDir) v := m.Run() lazyCluster.Terminate() diff --git a/tests/integration/lazy_cluster.go b/tests/integration/lazy_cluster.go index 02fc759dc732..1d16d2d38184 100644 --- a/tests/integration/lazy_cluster.go +++ b/tests/integration/lazy_cluster.go @@ -77,12 +77,14 @@ func NewLazyClusterWithConfig(cfg integration.ClusterConfig) LazyCluster { func (lc *lazyCluster) mustLazyInit() { lc.once.Do(func() { + lc.tb.Logf("LazyIniting ...") var err error lc.transport, err = transport.NewTransport(transport.TLSInfo{}, time.Second) if err != nil { log.Fatal(err) } lc.cluster = integration.NewCluster(lc.tb, &lc.cfg) + lc.tb.Logf("LazyIniting [Done]") }) } From ed1bc447c7540d61b61e5561cecb6fb877305f81 Mon Sep 17 00:00:00 2001 From: Piotr Tabor Date: Sun, 3 Apr 2022 13:20:29 +0200 Subject: [PATCH 241/258] Flakes: Additional logging and timeouts to understand common flakes. --- tests/common/lease_test.go | 5 +++- .../experimental/recipes/v3_lock_test.go | 26 +++++++++++-------- tests/integration/cluster_test.go | 12 +++++++-- 3 files changed, 29 insertions(+), 14 deletions(-) diff --git a/tests/common/lease_test.go b/tests/common/lease_test.go index e64f3b86e348..34260c6c2870 100644 --- a/tests/common/lease_test.go +++ b/tests/common/lease_test.go @@ -120,19 +120,22 @@ func TestLeaseGrantAndList(t *testing.T) { for _, nc := range nestedCases { t.Run(tc.name+"/"+nc.name, func(t *testing.T) { + t.Logf("Creating cluster...") clus := testRunner.NewCluster(t, tc.config) defer clus.Close() cc := clus.Client() - + t.Logf("Created cluster and client") testutils.ExecuteWithTimeout(t, 10*time.Second, func() { createdLeases := []clientv3.LeaseID{} for i := 0; i < nc.leaseCount; i++ { leaseResp, err := cc.Grant(10) + t.Logf("Grant returned: resp:%s err:%v", leaseResp.String(), err) require.NoError(t, err) createdLeases = append(createdLeases, leaseResp.ID) } resp, err := cc.LeaseList() + t.Logf("Lease list returned: resp:%s err:%v", resp.String(), err) require.NoError(t, err) require.Len(t, resp.Leases, nc.leaseCount) diff --git a/tests/integration/clientv3/experimental/recipes/v3_lock_test.go b/tests/integration/clientv3/experimental/recipes/v3_lock_test.go index ab7e7ff9e9cd..8a8229a8714c 100644 --- a/tests/integration/clientv3/experimental/recipes/v3_lock_test.go +++ b/tests/integration/clientv3/experimental/recipes/v3_lock_test.go @@ -96,7 +96,7 @@ func TestMutexTryLockSingleNode(t *testing.T) { integration2.BeforeTest(t) clus := integration2.NewCluster(t, &integration2.ClusterConfig{Size: 3}) defer clus.Terminate(t) - + t.Logf("3 nodes cluster created...") var clients []*clientv3.Client testMutexTryLock(t, 5, integration2.MakeSingleNodeClients(t, clus, &clients)) integration2.CloseClients(t, clients) @@ -113,35 +113,39 @@ func TestMutexTryLockMultiNode(t *testing.T) { } func testMutexTryLock(t *testing.T, lockers int, chooseClient func() *clientv3.Client) { + ctx, cancel := context.WithTimeout(context.Background(), 30*time.Second) + defer cancel() + lockedC := make(chan *concurrency.Mutex) notlockedC := make(chan *concurrency.Mutex) - stopC := make(chan struct{}) - defer close(stopC) + for i := 0; i < lockers; i++ { - go func() { + go func(i int) { session, err := concurrency.NewSession(chooseClient()) if err != nil { t.Error(err) } m := concurrency.NewMutex(session, "test-mutex-try-lock") - err = m.TryLock(context.TODO()) + err = m.TryLock(ctx) if err == nil { select { case lockedC <- m: - case <-stopC: + case <-ctx.Done(): + t.Errorf("Thread: %v, Context failed: %v", i, err) } } else if err == concurrency.ErrLocked { select { case notlockedC <- m: - case <-stopC: + case <-ctx.Done(): + t.Errorf("Thread: %v, Context failed: %v", i, err) } } else { - t.Errorf("Unexpected Error %v", err) + t.Errorf("Thread: %v; Unexpected Error %v", i, err) } - }() + }(i) } - timerC := time.After(time.Second) + timerC := time.After(30 * time.Second) select { case <-lockedC: for i := 0; i < lockers-1; i++ { @@ -154,7 +158,7 @@ func testMutexTryLock(t *testing.T, lockers int, chooseClient func() *clientv3.C } } case <-timerC: - t.Errorf("timed out waiting for lock") + t.Errorf("timed out waiting for lock (30s)") } } diff --git a/tests/integration/cluster_test.go b/tests/integration/cluster_test.go index 4e0d4a0f0fb6..5a7ff45920d4 100644 --- a/tests/integration/cluster_test.go +++ b/tests/integration/cluster_test.go @@ -284,6 +284,8 @@ func TestIssue3699(t *testing.T) { // add node d c.AddMember(t) + t.Logf("Disturbing cluster till member:3 will become a leader") + // electing node d as leader makes node a unable to participate leaderID := c.WaitMembersForLeader(t, c.Members) for leaderID != 3 { @@ -297,11 +299,16 @@ func TestIssue3699(t *testing.T) { leaderID = c.WaitMembersForLeader(t, c.Members) } + t.Logf("Finally elected member 3 as the leader.") + + t.Logf("Restarting member '0'...") // bring back node a // node a will remain useless as long as d is the leader. if err := c.Members[0].Restart(t); err != nil { t.Fatal(err) } + t.Logf("Restarted member '0'.") + select { // waiting for ReadyNotify can take several seconds case <-time.After(10 * time.Second): @@ -311,12 +318,13 @@ func TestIssue3699(t *testing.T) { case <-c.Members[0].Server.ReadyNotify(): } // must WaitMembersForLeader so goroutines don't leak on terminate - c.WaitMembersForLeader(t, c.Members) + c.WaitLeader(t) + t.Logf("Expecting successful put...") // try to participate in Cluster ctx, cancel := context.WithTimeout(context.Background(), integration.RequestTimeout) if _, err := c.Members[0].Client.Put(ctx, "/foo", "bar"); err != nil { - t.Fatalf("unexpected error on Set (%v)", err) + t.Fatalf("unexpected error on Put (%v)", err) } cancel() } From 90796720c1224d266b7e4883d59b3a1c4f7e11d2 Mon Sep 17 00:00:00 2001 From: Piotr Tabor Date: Sun, 3 Apr 2022 13:49:02 +0200 Subject: [PATCH 242/258] Reduce integration test parallelism to 2 packages at once. Especially with 'race' detection, running O(cpu) integrational tests was causing CPU overloads and timeouts. --- scripts/test.sh | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/scripts/test.sh b/scripts/test.sh index 687b32433fe2..932ab953a896 100755 --- a/scripts/test.sh +++ b/scripts/test.sh @@ -107,8 +107,8 @@ function integration_extra { } function integration_pass { - run_for_module "tests" go_test "./integration/..." "parallel" : -timeout="${TIMEOUT:-15m}" "${COMMON_TEST_FLAGS[@]}" "${RUN_ARG[@]}" "$@" || return $? - run_for_module "tests" go_test "./common/..." "parallel" : --tags=integration -timeout="${TIMEOUT:-15m}" "${COMMON_TEST_FLAGS[@]}" "${RUN_ARG[@]}" "$@" || return $? + run_for_module "tests" go_test "./integration/..." "parallel" : -timeout="${TIMEOUT:-15m}" "${COMMON_TEST_FLAGS[@]}" "${RUN_ARG[@]}" -p=2 "$@" || return $? + run_for_module "tests" go_test "./common/..." "parallel" : --tags=integration -timeout="${TIMEOUT:-15m}" "${COMMON_TEST_FLAGS[@]}" "${RUN_ARG[@]}" -p=2 "$@" || return $? integration_extra "$@" } From d4dcd3061dff943418f8d413cd431916f9807fd7 Mon Sep 17 00:00:00 2001 From: Piotr Tabor Date: Sun, 3 Apr 2022 23:13:01 +0200 Subject: [PATCH 243/258] Fix flakes in TestV3LeaseCheckpoint/Checkpointing_disabled,_lease_TTL_is_reset I think strong (not-equal) relationship was too restrictive when expressed with 1s granularity. ``` logger.go:130: 2022-04-03T22:15:15.242+0200 WARN m1 leader failed to send out heartbeat on time; took too long, leader is overloaded likely from slow disk {"member": "m1", "to": "cb785755eb80ac1", "heartbeat-interval": "10ms", "expected-duration": "20ms", "exceeded-duration": "24.666613ms"} logger.go:130: 2022-04-03T22:15:15.262+0200 INFO m-1 published local member to cluster through raft {"member": "m-1", "local-member-id": "e2dd9f523aa7be87", "local-member-attributes": "{Name:m-1 ClientURLs:[unix://127.0.0.1:2196386040]}", "cluster-id": "b4b8e7e41c23c8b5", "publish-timeout": "5.2s"} v3_lease_test.go:415: Expected lease ttl (4m58s) to be greather than (4m58s) ``` --- scripts/test.sh | 2 +- tests/integration/v3_lease_test.go | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/scripts/test.sh b/scripts/test.sh index 932ab953a896..9f5b38772801 100755 --- a/scripts/test.sh +++ b/scripts/test.sh @@ -108,7 +108,7 @@ function integration_extra { function integration_pass { run_for_module "tests" go_test "./integration/..." "parallel" : -timeout="${TIMEOUT:-15m}" "${COMMON_TEST_FLAGS[@]}" "${RUN_ARG[@]}" -p=2 "$@" || return $? - run_for_module "tests" go_test "./common/..." "parallel" : --tags=integration -timeout="${TIMEOUT:-15m}" "${COMMON_TEST_FLAGS[@]}" "${RUN_ARG[@]}" -p=2 "$@" || return $? + run_for_module "tests" go_test "./common/..." "parallel" : --tags=integration -timeout="${TIMEOUT:-15m}" "${COMMON_TEST_FLAGS[@]}" -p=2 "${RUN_ARG[@]}" "$@" || return $? integration_extra "$@" } diff --git a/tests/integration/v3_lease_test.go b/tests/integration/v3_lease_test.go index 520c983a30ea..df277267c5b3 100644 --- a/tests/integration/v3_lease_test.go +++ b/tests/integration/v3_lease_test.go @@ -411,8 +411,8 @@ func TestV3LeaseCheckpoint(t *testing.T) { } } - if tc.expectTTLIsGT != 0 && time.Duration(ttlresp.TTL)*time.Second <= tc.expectTTLIsGT { - t.Errorf("Expected lease ttl (%v) to be greather than (%v)", time.Duration(ttlresp.TTL)*time.Second, tc.expectTTLIsGT) + if tc.expectTTLIsGT != 0 && time.Duration(ttlresp.TTL)*time.Second < tc.expectTTLIsGT { + t.Errorf("Expected lease ttl (%v) to be >= than (%v)", time.Duration(ttlresp.TTL)*time.Second, tc.expectTTLIsGT) } if tc.expectTTLIsLT != 0 && time.Duration(ttlresp.TTL)*time.Second > tc.expectTTLIsLT { From 543c87cc3824c035f484d7a899122c9c3765ec4a Mon Sep 17 00:00:00 2001 From: ahrtr Date: Mon, 4 Apr 2022 18:58:18 +0800 Subject: [PATCH 244/258] etcd-dump-logs will panic if there is no WAL entry after the snapshot --- tools/etcd-dump-logs/main.go | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/tools/etcd-dump-logs/main.go b/tools/etcd-dump-logs/main.go index cda3dd5b8b78..82789c810029 100644 --- a/tools/etcd-dump-logs/main.go +++ b/tools/etcd-dump-logs/main.go @@ -123,8 +123,10 @@ and output a hex encoded line of binary for each input line`) fmt.Printf("WAL metadata:\nnodeID=%s clusterID=%s term=%d commitIndex=%d vote=%s\n", id, cid, state.Term, state.Commit, vid) - fmt.Printf("WAL entries:\n") - fmt.Printf("lastIndex=%d\n", ents[len(ents)-1].Index) + fmt.Printf("WAL entries: %d\n", len(ents)) + if len(ents) > 0 { + fmt.Printf("lastIndex=%d\n", ents[len(ents)-1].Index) + } fmt.Printf("%4s\t%10s\ttype\tdata", "term", "index") if *streamdecoder != "" { From 804fddf9218df71e077e6d089e15cb2430f9f233 Mon Sep 17 00:00:00 2001 From: Marek Siarkowicz Date: Fri, 1 Apr 2022 11:31:05 +0200 Subject: [PATCH 245/258] tests: Use zaptest.NewLogger in tests --- pkg/flags/flag_test.go | 8 +- pkg/netutil/netutil_test.go | 8 +- pkg/osutil/osutil_test.go | 4 +- server/auth/range_perm_cache_test.go | 7 +- server/auth/simple_token_test.go | 8 +- server/auth/store_test.go | 35 +++---- server/config/config_test.go | 15 ++- .../etcdserver/api/etcdhttp/metrics_test.go | 4 +- server/etcdserver/api/etcdhttp/peer_test.go | 6 +- .../etcdserver/api/membership/cluster_test.go | 10 +- .../api/rafthttp/functional_test.go | 11 +-- server/etcdserver/api/rafthttp/http_test.go | 5 +- .../etcdserver/api/rafthttp/pipeline_test.go | 23 +++-- .../etcdserver/api/rafthttp/snapshot_test.go | 7 +- server/etcdserver/api/rafthttp/stream_test.go | 14 +-- .../api/rafthttp/transport_bench_test.go | 7 +- .../etcdserver/api/rafthttp/transport_test.go | 8 +- .../etcdserver/api/snap/snapshotter_test.go | 22 ++--- .../api/v2discovery/discovery_test.go | 28 +++--- .../api/v3compactor/periodic_test.go | 8 +- .../api/v3compactor/revision_test.go | 6 +- .../api/v3discovery/discovery_test.go | 28 ++---- server/etcdserver/bootstrap_test.go | 17 ++-- server/etcdserver/cluster_util_test.go | 6 +- server/etcdserver/raft_test.go | 20 ++-- server/etcdserver/server_test.go | 93 ++++++++++--------- server/etcdserver/util_bench_test.go | 6 +- server/etcdserver/util_test.go | 4 +- server/proxy/httpproxy/director_test.go | 4 +- server/proxy/httpproxy/proxy_test.go | 4 +- server/proxy/httpproxy/reverse_test.go | 4 +- server/storage/mvcc/index_test.go | 14 +-- server/storage/mvcc/key_index_test.go | 73 ++++++++------- server/storage/mvcc/kv_test.go | 42 ++++----- server/storage/mvcc/kvstore_bench_test.go | 15 ++- .../storage/mvcc/kvstore_compaction_test.go | 8 +- server/storage/mvcc/kvstore_test.go | 68 +++++++------- .../mvcc/watchable_store_bench_test.go | 13 ++- server/storage/mvcc/watchable_store_test.go | 28 +++--- server/storage/mvcc/watcher_bench_test.go | 5 +- server/storage/mvcc/watcher_test.go | 18 ++-- server/storage/wal/file_pipeline_test.go | 8 +- server/storage/wal/repair_test.go | 27 +++--- server/storage/wal/wal_bench_test.go | 5 +- server/storage/wal/wal_test.go | 76 ++++++++------- tests/functional/tester/cluster_test.go | 8 +- tools/etcd-dump-logs/etcd-dump-log_test.go | 4 +- 47 files changed, 408 insertions(+), 434 deletions(-) diff --git a/pkg/flags/flag_test.go b/pkg/flags/flag_test.go index a176497ae50a..b7030da727cd 100644 --- a/pkg/flags/flag_test.go +++ b/pkg/flags/flag_test.go @@ -20,7 +20,7 @@ import ( "strings" "testing" - "go.uber.org/zap" + "go.uber.org/zap/zaptest" ) func TestSetFlagsFromEnv(t *testing.T) { @@ -49,7 +49,7 @@ func TestSetFlagsFromEnv(t *testing.T) { } // now read the env and verify flags were updated as expected - err := SetFlagsFromEnv(zap.NewExample(), "ETCD", fs) + err := SetFlagsFromEnv(zaptest.NewLogger(t), "ETCD", fs) if err != nil { t.Errorf("err=%v, want nil", err) } @@ -68,7 +68,7 @@ func TestSetFlagsFromEnvBad(t *testing.T) { fs := flag.NewFlagSet("testing", flag.ExitOnError) fs.Int("x", 0, "") os.Setenv("ETCD_X", "not_a_number") - if err := SetFlagsFromEnv(zap.NewExample(), "ETCD", fs); err == nil { + if err := SetFlagsFromEnv(zaptest.NewLogger(t), "ETCD", fs); err == nil { t.Errorf("err=nil, want != nil") } } @@ -83,7 +83,7 @@ func TestSetFlagsFromEnvParsingError(t *testing.T) { } defer os.Unsetenv("ETCD_HEARTBEAT_INTERVAL") - err := SetFlagsFromEnv(zap.NewExample(), "ETCD", fs) + err := SetFlagsFromEnv(zaptest.NewLogger(t), "ETCD", fs) for _, v := range []string{"invalid syntax", "parse error"} { if strings.Contains(err.Error(), v) { err = nil diff --git a/pkg/netutil/netutil_test.go b/pkg/netutil/netutil_test.go index 22db427e0a02..b6cc1bfcf9d3 100644 --- a/pkg/netutil/netutil_test.go +++ b/pkg/netutil/netutil_test.go @@ -25,7 +25,7 @@ import ( "testing" "time" - "go.uber.org/zap" + "go.uber.org/zap/zaptest" ) func TestResolveTCPAddrs(t *testing.T) { @@ -130,7 +130,7 @@ func TestResolveTCPAddrs(t *testing.T) { return &net.TCPAddr{IP: net.ParseIP(tt.hostMap[host]), Port: i, Zone: ""}, nil } ctx, cancel := context.WithTimeout(context.TODO(), time.Second) - urls, err := resolveTCPAddrs(ctx, zap.NewExample(), tt.urls) + urls, err := resolveTCPAddrs(ctx, zaptest.NewLogger(t), tt.urls) cancel() if tt.hasError { if err == nil { @@ -301,7 +301,7 @@ func TestURLsEqual(t *testing.T) { } for i, test := range tests { - result, err := urlsEqual(context.TODO(), zap.NewExample(), test.a, test.b) + result, err := urlsEqual(context.TODO(), zaptest.NewLogger(t), test.a, test.b) if result != test.expect { t.Errorf("idx=%d #%d: a:%v b:%v, expected %v but %v", i, test.n, test.a, test.b, test.expect, result) } @@ -334,7 +334,7 @@ func TestURLStringsEqual(t *testing.T) { for idx, c := range cases { t.Logf("TestURLStringsEqual, case #%d", idx) resolveTCPAddr = c.resolver - result, err := URLStringsEqual(context.TODO(), zap.NewExample(), c.urlsA, c.urlsB) + result, err := URLStringsEqual(context.TODO(), zaptest.NewLogger(t), c.urlsA, c.urlsB) if !result { t.Errorf("unexpected result %v", result) } diff --git a/pkg/osutil/osutil_test.go b/pkg/osutil/osutil_test.go index c03895b8ac99..322d2770c3a1 100644 --- a/pkg/osutil/osutil_test.go +++ b/pkg/osutil/osutil_test.go @@ -22,7 +22,7 @@ import ( "testing" "time" - "go.uber.org/zap" + "go.uber.org/zap/zaptest" ) func init() { setDflSignal = func(syscall.Signal) {} } @@ -71,7 +71,7 @@ func TestHandleInterrupts(t *testing.T) { c := make(chan os.Signal, 2) signal.Notify(c, sig) - HandleInterrupts(zap.NewExample()) + HandleInterrupts(zaptest.NewLogger(t)) syscall.Kill(syscall.Getpid(), sig) // we should receive the signal once from our own kill and diff --git a/server/auth/range_perm_cache_test.go b/server/auth/range_perm_cache_test.go index 2f325159309c..f4002c58945f 100644 --- a/server/auth/range_perm_cache_test.go +++ b/server/auth/range_perm_cache_test.go @@ -19,8 +19,7 @@ import ( "go.etcd.io/etcd/api/v3/authpb" "go.etcd.io/etcd/pkg/v3/adt" - - "go.uber.org/zap" + "go.uber.org/zap/zaptest" ) func TestRangePermission(t *testing.T) { @@ -53,7 +52,7 @@ func TestRangePermission(t *testing.T) { readPerms.Insert(p, struct{}{}) } - result := checkKeyInterval(zap.NewExample(), &unifiedRangePermissions{readPerms: readPerms}, tt.begin, tt.end, authpb.READ) + result := checkKeyInterval(zaptest.NewLogger(t), &unifiedRangePermissions{readPerms: readPerms}, tt.begin, tt.end, authpb.READ) if result != tt.want { t.Errorf("#%d: result=%t, want=%t", i, result, tt.want) } @@ -94,7 +93,7 @@ func TestKeyPermission(t *testing.T) { readPerms.Insert(p, struct{}{}) } - result := checkKeyPoint(zap.NewExample(), &unifiedRangePermissions{readPerms: readPerms}, tt.key, authpb.READ) + result := checkKeyPoint(zaptest.NewLogger(t), &unifiedRangePermissions{readPerms: readPerms}, tt.key, authpb.READ) if result != tt.want { t.Errorf("#%d: result=%t, want=%t", i, result, tt.want) } diff --git a/server/auth/simple_token_test.go b/server/auth/simple_token_test.go index 1bea56961139..13db76efe4a3 100644 --- a/server/auth/simple_token_test.go +++ b/server/auth/simple_token_test.go @@ -18,15 +18,15 @@ import ( "context" "testing" - "go.uber.org/zap" + "go.uber.org/zap/zaptest" ) // TestSimpleTokenDisabled ensures that TokenProviderSimple behaves correctly when // disabled. func TestSimpleTokenDisabled(t *testing.T) { - initialState := newTokenProviderSimple(zap.NewExample(), dummyIndexWaiter, simpleTokenTTLDefault) + initialState := newTokenProviderSimple(zaptest.NewLogger(t), dummyIndexWaiter, simpleTokenTTLDefault) - explicitlyDisabled := newTokenProviderSimple(zap.NewExample(), dummyIndexWaiter, simpleTokenTTLDefault) + explicitlyDisabled := newTokenProviderSimple(zaptest.NewLogger(t), dummyIndexWaiter, simpleTokenTTLDefault) explicitlyDisabled.enable() explicitlyDisabled.disable() @@ -48,7 +48,7 @@ func TestSimpleTokenDisabled(t *testing.T) { // TestSimpleTokenAssign ensures that TokenProviderSimple can correctly assign a // token, look it up with info, and invalidate it by user. func TestSimpleTokenAssign(t *testing.T) { - tp := newTokenProviderSimple(zap.NewExample(), dummyIndexWaiter, simpleTokenTTLDefault) + tp := newTokenProviderSimple(zaptest.NewLogger(t), dummyIndexWaiter, simpleTokenTTLDefault) tp.enable() defer tp.disable() ctx := context.WithValue(context.WithValue(context.TODO(), AuthenticateParamIndex{}, uint64(1)), AuthenticateParamSimpleTokenPrefix{}, "dummy") diff --git a/server/auth/store_test.go b/server/auth/store_test.go index 9b637dfe2d62..192bd72d8733 100644 --- a/server/auth/store_test.go +++ b/server/auth/store_test.go @@ -18,16 +18,17 @@ import ( "context" "encoding/base64" "fmt" - "github.com/stretchr/testify/assert" "strings" "sync" "testing" "time" + "github.com/stretchr/testify/assert" + "go.uber.org/zap/zaptest" + "go.etcd.io/etcd/api/v3/authpb" pb "go.etcd.io/etcd/api/v3/etcdserverpb" "go.etcd.io/etcd/api/v3/v3rpc/rpctypes" - "go.uber.org/zap" "golang.org/x/crypto/bcrypt" "google.golang.org/grpc/metadata" ) @@ -43,12 +44,12 @@ func dummyIndexWaiter(index uint64) <-chan struct{} { // TestNewAuthStoreRevision ensures newly auth store // keeps the old revision when there are no changes. func TestNewAuthStoreRevision(t *testing.T) { - tp, err := NewTokenProvider(zap.NewExample(), tokenTypeSimple, dummyIndexWaiter, simpleTokenTTLDefault) + tp, err := NewTokenProvider(zaptest.NewLogger(t), tokenTypeSimple, dummyIndexWaiter, simpleTokenTTLDefault) if err != nil { t.Fatal(err) } be := newBackendMock() - as := NewAuthStore(zap.NewExample(), be, tp, bcrypt.MinCost) + as := NewAuthStore(zaptest.NewLogger(t), be, tp, bcrypt.MinCost) err = enableAuthAndCreateRoot(as) if err != nil { t.Fatal(err) @@ -57,7 +58,7 @@ func TestNewAuthStoreRevision(t *testing.T) { as.Close() // no changes to commit - as = NewAuthStore(zap.NewExample(), be, tp, bcrypt.MinCost) + as = NewAuthStore(zaptest.NewLogger(t), be, tp, bcrypt.MinCost) defer as.Close() new := as.Revision() @@ -68,14 +69,14 @@ func TestNewAuthStoreRevision(t *testing.T) { // TestNewAuthStoreBryptCost ensures that NewAuthStore uses default when given bcrypt-cost is invalid func TestNewAuthStoreBcryptCost(t *testing.T) { - tp, err := NewTokenProvider(zap.NewExample(), tokenTypeSimple, dummyIndexWaiter, simpleTokenTTLDefault) + tp, err := NewTokenProvider(zaptest.NewLogger(t), tokenTypeSimple, dummyIndexWaiter, simpleTokenTTLDefault) if err != nil { t.Fatal(err) } invalidCosts := [2]int{bcrypt.MinCost - 1, bcrypt.MaxCost + 1} for _, invalidCost := range invalidCosts { - as := NewAuthStore(zap.NewExample(), newBackendMock(), tp, invalidCost) + as := NewAuthStore(zaptest.NewLogger(t), newBackendMock(), tp, invalidCost) defer as.Close() if as.BcryptCost() != bcrypt.DefaultCost { t.Fatalf("expected DefaultCost when bcryptcost is invalid") @@ -89,11 +90,11 @@ func encodePassword(s string) string { } func setupAuthStore(t *testing.T) (store *authStore, teardownfunc func(t *testing.T)) { - tp, err := NewTokenProvider(zap.NewExample(), tokenTypeSimple, dummyIndexWaiter, simpleTokenTTLDefault) + tp, err := NewTokenProvider(zaptest.NewLogger(t), tokenTypeSimple, dummyIndexWaiter, simpleTokenTTLDefault) if err != nil { t.Fatal(err) } - as := NewAuthStore(zap.NewExample(), newBackendMock(), tp, bcrypt.MinCost) + as := NewAuthStore(zaptest.NewLogger(t), newBackendMock(), tp, bcrypt.MinCost) err = enableAuthAndCreateRoot(as) if err != nil { t.Fatal(err) @@ -680,11 +681,11 @@ func TestIsAuthEnabled(t *testing.T) { // TestAuthRevisionRace ensures that access to authStore.revision is thread-safe. func TestAuthInfoFromCtxRace(t *testing.T) { - tp, err := NewTokenProvider(zap.NewExample(), tokenTypeSimple, dummyIndexWaiter, simpleTokenTTLDefault) + tp, err := NewTokenProvider(zaptest.NewLogger(t), tokenTypeSimple, dummyIndexWaiter, simpleTokenTTLDefault) if err != nil { t.Fatal(err) } - as := NewAuthStore(zap.NewExample(), newBackendMock(), tp, bcrypt.MinCost) + as := NewAuthStore(zaptest.NewLogger(t), newBackendMock(), tp, bcrypt.MinCost) defer as.Close() donec := make(chan struct{}) @@ -753,11 +754,11 @@ func TestRecoverFromSnapshot(t *testing.T) { as.Close() - tp, err := NewTokenProvider(zap.NewExample(), tokenTypeSimple, dummyIndexWaiter, simpleTokenTTLDefault) + tp, err := NewTokenProvider(zaptest.NewLogger(t), tokenTypeSimple, dummyIndexWaiter, simpleTokenTTLDefault) if err != nil { t.Fatal(err) } - as2 := NewAuthStore(zap.NewExample(), as.be, tp, bcrypt.MinCost) + as2 := NewAuthStore(zaptest.NewLogger(t), as.be, tp, bcrypt.MinCost) defer as2.Close() if !as2.IsAuthEnabled() { @@ -830,12 +831,12 @@ func TestHammerSimpleAuthenticate(t *testing.T) { // TestRolesOrder tests authpb.User.Roles is sorted func TestRolesOrder(t *testing.T) { - tp, err := NewTokenProvider(zap.NewExample(), tokenTypeSimple, dummyIndexWaiter, simpleTokenTTLDefault) + tp, err := NewTokenProvider(zaptest.NewLogger(t), tokenTypeSimple, dummyIndexWaiter, simpleTokenTTLDefault) defer tp.disable() if err != nil { t.Fatal(err) } - as := NewAuthStore(zap.NewExample(), newBackendMock(), tp, bcrypt.MinCost) + as := NewAuthStore(zaptest.NewLogger(t), newBackendMock(), tp, bcrypt.MinCost) defer as.Close() err = enableAuthAndCreateRoot(as) if err != nil { @@ -884,11 +885,11 @@ func TestAuthInfoFromCtxWithRootJWT(t *testing.T) { // testAuthInfoFromCtxWithRoot ensures "WithRoot" properly embeds token in the context. func testAuthInfoFromCtxWithRoot(t *testing.T, opts string) { - tp, err := NewTokenProvider(zap.NewExample(), opts, dummyIndexWaiter, simpleTokenTTLDefault) + tp, err := NewTokenProvider(zaptest.NewLogger(t), opts, dummyIndexWaiter, simpleTokenTTLDefault) if err != nil { t.Fatal(err) } - as := NewAuthStore(zap.NewExample(), newBackendMock(), tp, bcrypt.MinCost) + as := NewAuthStore(zaptest.NewLogger(t), newBackendMock(), tp, bcrypt.MinCost) defer as.Close() if err = enableAuthAndCreateRoot(as); err != nil { diff --git a/server/config/config_test.go b/server/config/config_test.go index 24ae5eb55a16..8283f7d13361 100644 --- a/server/config/config_test.go +++ b/server/config/config_test.go @@ -19,8 +19,7 @@ import ( "testing" "go.etcd.io/etcd/client/pkg/v3/types" - - "go.uber.org/zap" + "go.uber.org/zap/zaptest" ) func mustNewURLs(t *testing.T, urls []string) []url.URL { @@ -39,7 +38,7 @@ func TestConfigVerifyBootstrapWithoutClusterAndDiscoveryURLFail(t *testing.T) { Name: "node1", DiscoveryURL: "", InitialPeerURLsMap: types.URLsMap{}, - Logger: zap.NewExample(), + Logger: zaptest.NewLogger(t), } if err := c.VerifyBootstrap(); err == nil { t.Errorf("err = nil, want not nil") @@ -57,7 +56,7 @@ func TestConfigVerifyExistingWithDiscoveryURLFail(t *testing.T) { PeerURLs: mustNewURLs(t, []string{"http://127.0.0.1:2380"}), InitialPeerURLsMap: cluster, NewCluster: false, - Logger: zap.NewExample(), + Logger: zaptest.NewLogger(t), } if err := c.VerifyJoinExisting(); err == nil { t.Errorf("err = nil, want not nil") @@ -145,7 +144,7 @@ func TestConfigVerifyLocalMember(t *testing.T) { cfg := ServerConfig{ Name: "node1", InitialPeerURLsMap: cluster, - Logger: zap.NewExample(), + Logger: zaptest.NewLogger(t), } if tt.apurls != nil { cfg.PeerURLs = mustNewURLs(t, tt.apurls) @@ -170,7 +169,7 @@ func TestSnapDir(t *testing.T) { for dd, w := range tests { cfg := ServerConfig{ DataDir: dd, - Logger: zap.NewExample(), + Logger: zaptest.NewLogger(t), } if g := cfg.SnapDir(); g != w { t.Errorf("DataDir=%q: SnapDir()=%q, want=%q", dd, g, w) @@ -186,7 +185,7 @@ func TestWALDir(t *testing.T) { for dd, w := range tests { cfg := ServerConfig{ DataDir: dd, - Logger: zap.NewExample(), + Logger: zaptest.NewLogger(t), } if g := cfg.WALDir(); g != w { t.Errorf("DataDir=%q: WALDir()=%q, want=%q", dd, g, w) @@ -203,7 +202,7 @@ func TestShouldDiscover(t *testing.T) { for durl, w := range tests { cfg := ServerConfig{ DiscoveryURL: durl, - Logger: zap.NewExample(), + Logger: zaptest.NewLogger(t), } if g := cfg.ShouldDiscover(); g != w { t.Errorf("durl=%q: ShouldDiscover()=%t, want=%t", durl, g, w) diff --git a/server/etcdserver/api/etcdhttp/metrics_test.go b/server/etcdserver/api/etcdhttp/metrics_test.go index 1a0605b51c93..9c07cca5930c 100644 --- a/server/etcdserver/api/etcdhttp/metrics_test.go +++ b/server/etcdserver/api/etcdhttp/metrics_test.go @@ -14,7 +14,7 @@ import ( "go.etcd.io/etcd/client/pkg/v3/types" "go.etcd.io/etcd/raft/v3" "go.etcd.io/etcd/server/v3/etcdserver" - "go.uber.org/zap" + "go.uber.org/zap/zaptest" ) type fakeStats struct{} @@ -98,7 +98,7 @@ func TestHealthHandler(t *testing.T) { for i, tt := range tests { func() { mux := http.NewServeMux() - HandleMetricsHealth(zap.NewExample(), mux, &fakeServerV2{ + HandleMetricsHealth(zaptest.NewLogger(t), mux, &fakeServerV2{ fakeServer: fakeServer{alarms: tt.alarms}, health: tt.health, }) diff --git a/server/etcdserver/api/etcdhttp/peer_test.go b/server/etcdserver/api/etcdhttp/peer_test.go index 9a9f9fd884f6..68f651aef892 100644 --- a/server/etcdserver/api/etcdhttp/peer_test.go +++ b/server/etcdserver/api/etcdhttp/peer_test.go @@ -26,7 +26,7 @@ import ( "strings" "testing" - "go.uber.org/zap" + "go.uber.org/zap/zaptest" "github.com/coreos/go-semver/semver" pb "go.etcd.io/etcd/api/v3/etcdserverpb" @@ -85,7 +85,7 @@ var fakeRaftHandler = http.HandlerFunc(func(w http.ResponseWriter, r *http.Reque // TestNewPeerHandlerOnRaftPrefix tests that NewPeerHandler returns a handler that // handles raft-prefix requests well. func TestNewPeerHandlerOnRaftPrefix(t *testing.T) { - ph := newPeerHandler(zap.NewExample(), &fakeServer{cluster: &fakeCluster{}}, fakeRaftHandler, nil, nil, nil) + ph := newPeerHandler(zaptest.NewLogger(t), &fakeServer{cluster: &fakeCluster{}}, fakeRaftHandler, nil, nil, nil) srv := httptest.NewServer(ph) defer srv.Close() @@ -233,7 +233,7 @@ func TestServeMemberPromoteFails(t *testing.T) { // TestNewPeerHandlerOnMembersPromotePrefix verifies the request with members promote prefix is routed correctly func TestNewPeerHandlerOnMembersPromotePrefix(t *testing.T) { - ph := newPeerHandler(zap.NewExample(), &fakeServer{cluster: &fakeCluster{}}, fakeRaftHandler, nil, nil, nil) + ph := newPeerHandler(zaptest.NewLogger(t), &fakeServer{cluster: &fakeCluster{}}, fakeRaftHandler, nil, nil, nil) srv := httptest.NewServer(ph) defer srv.Close() diff --git a/server/etcdserver/api/membership/cluster_test.go b/server/etcdserver/api/membership/cluster_test.go index c8dc18c8a3f6..9ccfab4a7107 100644 --- a/server/etcdserver/api/membership/cluster_test.go +++ b/server/etcdserver/api/membership/cluster_test.go @@ -28,8 +28,6 @@ import ( "go.etcd.io/etcd/raft/v3/raftpb" "go.etcd.io/etcd/server/v3/etcdserver/api/v2store" "go.etcd.io/etcd/server/v3/mock/mockstore" - - "go.uber.org/zap" ) func TestClusterMember(t *testing.T) { @@ -241,7 +239,7 @@ func TestClusterValidateAndAssignIDsBad(t *testing.T) { for i, tt := range tests { ecl := newTestCluster(t, tt.clmembs) lcl := newTestCluster(t, tt.membs) - if err := ValidateClusterAndAssignIDs(zap.NewExample(), lcl, ecl); err == nil { + if err := ValidateClusterAndAssignIDs(zaptest.NewLogger(t), lcl, ecl); err == nil { t.Errorf("#%d: unexpected update success", i) } } @@ -268,7 +266,7 @@ func TestClusterValidateAndAssignIDs(t *testing.T) { for i, tt := range tests { lcl := newTestCluster(t, tt.clmembs) ecl := newTestCluster(t, tt.membs) - if err := ValidateClusterAndAssignIDs(zap.NewExample(), lcl, ecl); err != nil { + if err := ValidateClusterAndAssignIDs(zaptest.NewLogger(t), lcl, ecl); err != nil { t.Errorf("#%d: unexpect update error: %v", i, err) } if !reflect.DeepEqual(lcl.MemberIDs(), tt.wids) { @@ -509,7 +507,7 @@ func TestNodeToMemberBad(t *testing.T) { }}, } for i, tt := range tests { - if _, err := nodeToMember(zap.NewExample(), tt); err == nil { + if _, err := nodeToMember(zaptest.NewLogger(t), tt); err == nil { t.Errorf("#%d: unexpected nil error", i) } } @@ -638,7 +636,7 @@ func TestNodeToMember(t *testing.T) { {Key: "/1234/raftAttributes", Value: stringp(`{"peerURLs":null}`)}, }} wm := &Member{ID: 0x1234, RaftAttributes: RaftAttributes{}, Attributes: Attributes{Name: "node1"}} - m, err := nodeToMember(zap.NewExample(), n) + m, err := nodeToMember(zaptest.NewLogger(t), n) if err != nil { t.Fatalf("unexpected nodeToMember error: %v", err) } diff --git a/server/etcdserver/api/rafthttp/functional_test.go b/server/etcdserver/api/rafthttp/functional_test.go index 44d6aea5e50f..c6314b3dcd6f 100644 --- a/server/etcdserver/api/rafthttp/functional_test.go +++ b/server/etcdserver/api/rafthttp/functional_test.go @@ -25,8 +25,7 @@ import ( "go.etcd.io/etcd/raft/v3" "go.etcd.io/etcd/raft/v3/raftpb" stats "go.etcd.io/etcd/server/v3/etcdserver/api/v2stats" - - "go.uber.org/zap" + "go.uber.org/zap/zaptest" ) func TestSendMessage(t *testing.T) { @@ -36,7 +35,7 @@ func TestSendMessage(t *testing.T) { ClusterID: types.ID(1), Raft: &fakeRaft{}, ServerStats: newServerStats(), - LeaderStats: stats.NewLeaderStats(zap.NewExample(), "1"), + LeaderStats: stats.NewLeaderStats(zaptest.NewLogger(t), "1"), } tr.Start() srv := httptest.NewServer(tr.Handler()) @@ -50,7 +49,7 @@ func TestSendMessage(t *testing.T) { ClusterID: types.ID(1), Raft: p, ServerStats: newServerStats(), - LeaderStats: stats.NewLeaderStats(zap.NewExample(), "2"), + LeaderStats: stats.NewLeaderStats(zaptest.NewLogger(t), "2"), } tr2.Start() srv2 := httptest.NewServer(tr2.Handler()) @@ -94,7 +93,7 @@ func TestSendMessageWhenStreamIsBroken(t *testing.T) { ClusterID: types.ID(1), Raft: &fakeRaft{}, ServerStats: newServerStats(), - LeaderStats: stats.NewLeaderStats(zap.NewExample(), "1"), + LeaderStats: stats.NewLeaderStats(zaptest.NewLogger(t), "1"), } tr.Start() srv := httptest.NewServer(tr.Handler()) @@ -108,7 +107,7 @@ func TestSendMessageWhenStreamIsBroken(t *testing.T) { ClusterID: types.ID(1), Raft: p, ServerStats: newServerStats(), - LeaderStats: stats.NewLeaderStats(zap.NewExample(), "2"), + LeaderStats: stats.NewLeaderStats(zaptest.NewLogger(t), "2"), } tr2.Start() srv2 := httptest.NewServer(tr2.Handler()) diff --git a/server/etcdserver/api/rafthttp/http_test.go b/server/etcdserver/api/rafthttp/http_test.go index dbb370bf8b16..ad92c82dc364 100644 --- a/server/etcdserver/api/rafthttp/http_test.go +++ b/server/etcdserver/api/rafthttp/http_test.go @@ -31,8 +31,7 @@ import ( "go.etcd.io/etcd/pkg/v3/pbutil" "go.etcd.io/etcd/raft/v3/raftpb" "go.etcd.io/etcd/server/v3/etcdserver/api/snap" - - "go.uber.org/zap" + "go.uber.org/zap/zaptest" ) func TestServeRaftPrefix(t *testing.T) { @@ -153,7 +152,7 @@ func TestServeRaftPrefix(t *testing.T) { req.Header.Set("X-Etcd-Cluster-ID", tt.clusterID) req.Header.Set("X-Server-Version", version.Version) rw := httptest.NewRecorder() - h := newPipelineHandler(&Transport{Logger: zap.NewExample()}, tt.p, types.ID(0)) + h := newPipelineHandler(&Transport{Logger: zaptest.NewLogger(t)}, tt.p, types.ID(0)) // goroutine because the handler panics to disconnect on raft error donec := make(chan struct{}) diff --git a/server/etcdserver/api/rafthttp/pipeline_test.go b/server/etcdserver/api/rafthttp/pipeline_test.go index c7b7bb896997..83b33e96527d 100644 --- a/server/etcdserver/api/rafthttp/pipeline_test.go +++ b/server/etcdserver/api/rafthttp/pipeline_test.go @@ -28,8 +28,7 @@ import ( "go.etcd.io/etcd/client/pkg/v3/types" "go.etcd.io/etcd/raft/v3/raftpb" stats "go.etcd.io/etcd/server/v3/etcdserver/api/v2stats" - - "go.uber.org/zap" + "go.uber.org/zap/zaptest" ) // TestPipelineSend tests that pipeline could send data using roundtripper @@ -38,7 +37,7 @@ func TestPipelineSend(t *testing.T) { tr := &roundTripperRecorder{rec: testutil.NewRecorderStream()} picker := mustNewURLPicker(t, []string{"http://localhost:2380"}) tp := &Transport{pipelineRt: tr} - p := startTestPipeline(tp, picker) + p := startTestPipeline(t, tp, picker) p.msgc <- raftpb.Message{Type: raftpb.MsgApp} tr.rec.Wait(1) @@ -54,7 +53,7 @@ func TestPipelineKeepSendingWhenPostError(t *testing.T) { tr := &respRoundTripper{rec: testutil.NewRecorderStream(), err: fmt.Errorf("roundtrip error")} picker := mustNewURLPicker(t, []string{"http://localhost:2380"}) tp := &Transport{pipelineRt: tr} - p := startTestPipeline(tp, picker) + p := startTestPipeline(t, tp, picker) defer p.stop() for i := 0; i < 50; i++ { @@ -71,7 +70,7 @@ func TestPipelineExceedMaximumServing(t *testing.T) { rt := newRoundTripperBlocker() picker := mustNewURLPicker(t, []string{"http://localhost:2380"}) tp := &Transport{pipelineRt: rt} - p := startTestPipeline(tp, picker) + p := startTestPipeline(t, tp, picker) defer p.stop() // keep the sender busy and make the buffer full @@ -109,7 +108,7 @@ func TestPipelineSendFailed(t *testing.T) { rt := newRespRoundTripper(0, errors.New("blah")) rt.rec = testutil.NewRecorderStream() tp := &Transport{pipelineRt: rt} - p := startTestPipeline(tp, picker) + p := startTestPipeline(t, tp, picker) p.msgc <- raftpb.Message{Type: raftpb.MsgApp} if _, err := rt.rec.Wait(1); err != nil { @@ -127,7 +126,7 @@ func TestPipelinePost(t *testing.T) { tr := &roundTripperRecorder{rec: &testutil.RecorderBuffered{}} picker := mustNewURLPicker(t, []string{"http://localhost:2380"}) tp := &Transport{ClusterID: types.ID(1), pipelineRt: tr} - p := startTestPipeline(tp, picker) + p := startTestPipeline(t, tp, picker) if err := p.post([]byte("some data")); err != nil { t.Fatalf("unexpected post error: %v", err) } @@ -181,7 +180,7 @@ func TestPipelinePostBad(t *testing.T) { for i, tt := range tests { picker := mustNewURLPicker(t, []string{tt.u}) tp := &Transport{pipelineRt: newRespRoundTripper(tt.code, tt.err)} - p := startTestPipeline(tp, picker) + p := startTestPipeline(t, tp, picker) err := p.post([]byte("some data")) p.stop() @@ -202,7 +201,7 @@ func TestPipelinePostErrorc(t *testing.T) { for i, tt := range tests { picker := mustNewURLPicker(t, []string{tt.u}) tp := &Transport{pipelineRt: newRespRoundTripper(tt.code, tt.err)} - p := startTestPipeline(tp, picker) + p := startTestPipeline(t, tp, picker) p.post([]byte("some data")) p.stop() select { @@ -216,7 +215,7 @@ func TestPipelinePostErrorc(t *testing.T) { func TestStopBlockedPipeline(t *testing.T) { picker := mustNewURLPicker(t, []string{"http://localhost:2380"}) tp := &Transport{pipelineRt: newRoundTripperBlocker()} - p := startTestPipeline(tp, picker) + p := startTestPipeline(t, tp, picker) // send many messages that most of them will be blocked in buffer for i := 0; i < connPerPipeline*10; i++ { p.msgc <- raftpb.Message{} @@ -297,12 +296,12 @@ type nopReadCloser struct{} func (n *nopReadCloser) Read(p []byte) (int, error) { return 0, io.EOF } func (n *nopReadCloser) Close() error { return nil } -func startTestPipeline(tr *Transport, picker *urlPicker) *pipeline { +func startTestPipeline(t *testing.T, tr *Transport, picker *urlPicker) *pipeline { p := &pipeline{ peerID: types.ID(1), tr: tr, picker: picker, - status: newPeerStatus(zap.NewExample(), tr.ID, types.ID(1)), + status: newPeerStatus(zaptest.NewLogger(t), tr.ID, types.ID(1)), raft: &fakeRaft{}, followerStats: &stats.FollowerStats{}, errorc: make(chan error, 1), diff --git a/server/etcdserver/api/rafthttp/snapshot_test.go b/server/etcdserver/api/rafthttp/snapshot_test.go index b1d8cdbbdeb8..e67abf37f738 100644 --- a/server/etcdserver/api/rafthttp/snapshot_test.go +++ b/server/etcdserver/api/rafthttp/snapshot_test.go @@ -27,8 +27,7 @@ import ( "go.etcd.io/etcd/client/pkg/v3/types" "go.etcd.io/etcd/raft/v3/raftpb" "go.etcd.io/etcd/server/v3/etcdserver/api/snap" - - "go.uber.org/zap" + "go.uber.org/zap/zaptest" ) type strReaderCloser struct{ *strings.Reader } @@ -99,12 +98,12 @@ func testSnapshotSend(t *testing.T, sm *snap.Message) (bool, []os.DirEntry) { r := &fakeRaft{} tr := &Transport{pipelineRt: &http.Transport{}, ClusterID: types.ID(1), Raft: r} ch := make(chan struct{}, 1) - h := &syncHandler{newSnapshotHandler(tr, r, snap.New(zap.NewExample(), d), types.ID(1)), ch} + h := &syncHandler{newSnapshotHandler(tr, r, snap.New(zaptest.NewLogger(t), d), types.ID(1)), ch} srv := httptest.NewServer(h) defer srv.Close() picker := mustNewURLPicker(t, []string{srv.URL}) - snapsend := newSnapshotSender(tr, picker, types.ID(1), newPeerStatus(zap.NewExample(), types.ID(0), types.ID(1))) + snapsend := newSnapshotSender(tr, picker, types.ID(1), newPeerStatus(zaptest.NewLogger(t), types.ID(0), types.ID(1))) defer snapsend.stop() snapsend.send(*sm) diff --git a/server/etcdserver/api/rafthttp/stream_test.go b/server/etcdserver/api/rafthttp/stream_test.go index 5006bd0898a3..c9767b3c45ba 100644 --- a/server/etcdserver/api/rafthttp/stream_test.go +++ b/server/etcdserver/api/rafthttp/stream_test.go @@ -31,9 +31,9 @@ import ( "go.etcd.io/etcd/client/pkg/v3/types" "go.etcd.io/etcd/raft/v3/raftpb" stats "go.etcd.io/etcd/server/v3/etcdserver/api/v2stats" + "go.uber.org/zap/zaptest" "github.com/coreos/go-semver/semver" - "go.uber.org/zap" "golang.org/x/time/rate" ) @@ -41,7 +41,7 @@ import ( // to streamWriter. After that, streamWriter can use it to send messages // continuously, and closes it when stopped. func TestStreamWriterAttachOutgoingConn(t *testing.T) { - sw := startStreamWriter(zap.NewExample(), types.ID(0), types.ID(1), newPeerStatus(zap.NewExample(), types.ID(0), types.ID(1)), &stats.FollowerStats{}, &fakeRaft{}) + sw := startStreamWriter(zaptest.NewLogger(t), types.ID(0), types.ID(1), newPeerStatus(zaptest.NewLogger(t), types.ID(0), types.ID(1)), &stats.FollowerStats{}, &fakeRaft{}) // the expected initial state of streamWriter is not working if _, ok := sw.writec(); ok { t.Errorf("initial working status = %v, want false", ok) @@ -93,7 +93,7 @@ func TestStreamWriterAttachOutgoingConn(t *testing.T) { // TestStreamWriterAttachBadOutgoingConn tests that streamWriter with bad // outgoingConn will close the outgoingConn and fall back to non-working status. func TestStreamWriterAttachBadOutgoingConn(t *testing.T) { - sw := startStreamWriter(zap.NewExample(), types.ID(0), types.ID(1), newPeerStatus(zap.NewExample(), types.ID(0), types.ID(1)), &stats.FollowerStats{}, &fakeRaft{}) + sw := startStreamWriter(zaptest.NewLogger(t), types.ID(0), types.ID(1), newPeerStatus(zaptest.NewLogger(t), types.ID(0), types.ID(1)), &stats.FollowerStats{}, &fakeRaft{}) defer sw.stop() wfc := newFakeWriteFlushCloser(errors.New("blah")) sw.attach(&outgoingConn{t: streamTypeMessage, Writer: wfc, Flusher: wfc, Closer: wfc}) @@ -127,7 +127,7 @@ func TestStreamReaderDialRequest(t *testing.T) { } req := act[0].Params[0].(*http.Request) - wurl := fmt.Sprintf("http://localhost:2380" + tt.endpoint(zap.NewExample()) + "/1") + wurl := fmt.Sprintf("http://localhost:2380" + tt.endpoint(zaptest.NewLogger(t)) + "/1") if req.URL.String() != wurl { t.Errorf("#%d: url = %s, want %s", i, req.URL.String(), wurl) } @@ -197,7 +197,7 @@ func TestStreamReaderStopOnDial(t *testing.T) { picker: mustNewURLPicker(t, []string{"http://localhost:2380"}), errorc: make(chan error, 1), typ: streamTypeMessage, - status: newPeerStatus(zap.NewExample(), types.ID(1), types.ID(2)), + status: newPeerStatus(zaptest.NewLogger(t), types.ID(1), types.ID(2)), rl: rate.NewLimiter(rate.Every(100*time.Millisecond), 1), } tr.onResp = func() { @@ -304,7 +304,7 @@ func TestStream(t *testing.T) { srv := httptest.NewServer(h) defer srv.Close() - sw := startStreamWriter(zap.NewExample(), types.ID(0), types.ID(1), newPeerStatus(zap.NewExample(), types.ID(0), types.ID(1)), &stats.FollowerStats{}, &fakeRaft{}) + sw := startStreamWriter(zaptest.NewLogger(t), types.ID(0), types.ID(1), newPeerStatus(zaptest.NewLogger(t), types.ID(0), types.ID(1)), &stats.FollowerStats{}, &fakeRaft{}) defer sw.stop() h.sw = sw @@ -316,7 +316,7 @@ func TestStream(t *testing.T) { typ: tt.t, tr: tr, picker: picker, - status: newPeerStatus(zap.NewExample(), types.ID(0), types.ID(2)), + status: newPeerStatus(zaptest.NewLogger(t), types.ID(0), types.ID(2)), recvc: recvc, propc: propc, rl: rate.NewLimiter(rate.Every(100*time.Millisecond), 1), diff --git a/server/etcdserver/api/rafthttp/transport_bench_test.go b/server/etcdserver/api/rafthttp/transport_bench_test.go index 20659b3829c4..1e34bdd9f136 100644 --- a/server/etcdserver/api/rafthttp/transport_bench_test.go +++ b/server/etcdserver/api/rafthttp/transport_bench_test.go @@ -25,8 +25,7 @@ import ( "go.etcd.io/etcd/raft/v3" "go.etcd.io/etcd/raft/v3/raftpb" stats "go.etcd.io/etcd/server/v3/etcdserver/api/v2stats" - - "go.uber.org/zap" + "go.uber.org/zap/zaptest" ) func BenchmarkSendingMsgApp(b *testing.B) { @@ -36,7 +35,7 @@ func BenchmarkSendingMsgApp(b *testing.B) { ClusterID: types.ID(1), Raft: &fakeRaft{}, ServerStats: newServerStats(), - LeaderStats: stats.NewLeaderStats(zap.NewExample(), "1"), + LeaderStats: stats.NewLeaderStats(zaptest.NewLogger(b), "1"), } tr.Start() srv := httptest.NewServer(tr.Handler()) @@ -49,7 +48,7 @@ func BenchmarkSendingMsgApp(b *testing.B) { ClusterID: types.ID(1), Raft: r, ServerStats: newServerStats(), - LeaderStats: stats.NewLeaderStats(zap.NewExample(), "2"), + LeaderStats: stats.NewLeaderStats(zaptest.NewLogger(b), "2"), } tr2.Start() srv2 := httptest.NewServer(tr2.Handler()) diff --git a/server/etcdserver/api/rafthttp/transport_test.go b/server/etcdserver/api/rafthttp/transport_test.go index c35a70264446..dd942bf8fbd7 100644 --- a/server/etcdserver/api/rafthttp/transport_test.go +++ b/server/etcdserver/api/rafthttp/transport_test.go @@ -24,9 +24,9 @@ import ( "go.etcd.io/etcd/client/pkg/v3/types" "go.etcd.io/etcd/raft/v3/raftpb" stats "go.etcd.io/etcd/server/v3/etcdserver/api/v2stats" + "go.uber.org/zap/zaptest" "github.com/xiang90/probing" - "go.uber.org/zap" ) // TestTransportSend tests that transport can send messages using correct @@ -96,7 +96,7 @@ func TestTransportCutMend(t *testing.T) { } func TestTransportAdd(t *testing.T) { - ls := stats.NewLeaderStats(zap.NewExample(), "") + ls := stats.NewLeaderStats(zaptest.NewLogger(t), "") tr := &Transport{ LeaderStats: ls, streamRt: &roundTripperRecorder{}, @@ -127,7 +127,7 @@ func TestTransportAdd(t *testing.T) { func TestTransportRemove(t *testing.T) { tr := &Transport{ - LeaderStats: stats.NewLeaderStats(zap.NewExample(), ""), + LeaderStats: stats.NewLeaderStats(zaptest.NewLogger(t), ""), streamRt: &roundTripperRecorder{}, peers: make(map[types.ID]Peer), pipelineProber: probing.NewProber(nil), @@ -161,7 +161,7 @@ func TestTransportErrorc(t *testing.T) { errorc := make(chan error, 1) tr := &Transport{ Raft: &fakeRaft{}, - LeaderStats: stats.NewLeaderStats(zap.NewExample(), ""), + LeaderStats: stats.NewLeaderStats(zaptest.NewLogger(t), ""), ErrorC: errorc, streamRt: newRespRoundTripper(http.StatusForbidden, nil), pipelineRt: newRespRoundTripper(http.StatusForbidden, nil), diff --git a/server/etcdserver/api/snap/snapshotter_test.go b/server/etcdserver/api/snap/snapshotter_test.go index 15766ae96e15..0364c1e73e06 100644 --- a/server/etcdserver/api/snap/snapshotter_test.go +++ b/server/etcdserver/api/snap/snapshotter_test.go @@ -25,7 +25,7 @@ import ( "go.etcd.io/etcd/client/pkg/v3/fileutil" "go.etcd.io/etcd/raft/v3/raftpb" "go.etcd.io/etcd/server/v3/storage/wal/walpb" - "go.uber.org/zap" + "go.uber.org/zap/zaptest" ) var testSnap = &raftpb.Snapshot{ @@ -46,7 +46,7 @@ func TestSaveAndLoad(t *testing.T) { t.Fatal(err) } defer os.RemoveAll(dir) - ss := New(zap.NewExample(), dir) + ss := New(zaptest.NewLogger(t), dir) err = ss.save(testSnap) if err != nil { t.Fatal(err) @@ -68,7 +68,7 @@ func TestBadCRC(t *testing.T) { t.Fatal(err) } defer os.RemoveAll(dir) - ss := New(zap.NewExample(), dir) + ss := New(zaptest.NewLogger(t), dir) err = ss.save(testSnap) if err != nil { t.Fatal(err) @@ -78,7 +78,7 @@ func TestBadCRC(t *testing.T) { // fake a crc mismatch crcTable = crc32.MakeTable(crc32.Koopman) - _, err = Read(zap.NewExample(), filepath.Join(dir, fmt.Sprintf("%016x-%016x.snap", 1, 1))) + _, err = Read(zaptest.NewLogger(t), filepath.Join(dir, fmt.Sprintf("%016x-%016x.snap", 1, 1))) if err == nil || err != ErrCRCMismatch { t.Errorf("err = %v, want %v", err, ErrCRCMismatch) } @@ -98,7 +98,7 @@ func TestFailback(t *testing.T) { t.Fatal(err) } - ss := New(zap.NewExample(), dir) + ss := New(zaptest.NewLogger(t), dir) err = ss.save(testSnap) if err != nil { t.Fatal(err) @@ -133,7 +133,7 @@ func TestSnapNames(t *testing.T) { f.Close() } } - ss := New(zap.NewExample(), dir) + ss := New(zaptest.NewLogger(t), dir) names, err := ss.snapNames() if err != nil { t.Errorf("err = %v, want nil", err) @@ -154,7 +154,7 @@ func TestLoadNewestSnap(t *testing.T) { t.Fatal(err) } defer os.RemoveAll(dir) - ss := New(zap.NewExample(), dir) + ss := New(zaptest.NewLogger(t), dir) err = ss.save(testSnap) if err != nil { t.Fatal(err) @@ -218,7 +218,7 @@ func TestNoSnapshot(t *testing.T) { t.Fatal(err) } defer os.RemoveAll(dir) - ss := New(zap.NewExample(), dir) + ss := New(zaptest.NewLogger(t), dir) _, err = ss.Load() if err != ErrNoSnapshot { t.Errorf("err = %v, want %v", err, ErrNoSnapshot) @@ -238,7 +238,7 @@ func TestEmptySnapshot(t *testing.T) { t.Fatal(err) } - _, err = Read(zap.NewExample(), filepath.Join(dir, "1.snap")) + _, err = Read(zaptest.NewLogger(t), filepath.Join(dir, "1.snap")) if err != ErrEmptySnapshot { t.Errorf("err = %v, want %v", err, ErrEmptySnapshot) } @@ -259,7 +259,7 @@ func TestAllSnapshotBroken(t *testing.T) { t.Fatal(err) } - ss := New(zap.NewExample(), dir) + ss := New(zaptest.NewLogger(t), dir) _, err = ss.Load() if err != ErrNoSnapshot { t.Errorf("err = %v, want %v", err, ErrNoSnapshot) @@ -282,7 +282,7 @@ func TestReleaseSnapDBs(t *testing.T) { } } - ss := New(zap.NewExample(), dir) + ss := New(zaptest.NewLogger(t), dir) if err := ss.ReleaseSnapDBs(raftpb.Snapshot{Metadata: raftpb.SnapshotMetadata{Index: 300}}); err != nil { t.Fatal(err) diff --git a/server/etcdserver/api/v2discovery/discovery_test.go b/server/etcdserver/api/v2discovery/discovery_test.go index d94150d421d1..afcb9f78f7eb 100644 --- a/server/etcdserver/api/v2discovery/discovery_test.go +++ b/server/etcdserver/api/v2discovery/discovery_test.go @@ -29,9 +29,9 @@ import ( "go.etcd.io/etcd/client/pkg/v3/types" "go.etcd.io/etcd/client/v2" + "go.uber.org/zap/zaptest" "github.com/jonboulle/clockwork" - "go.uber.org/zap" ) const ( @@ -39,7 +39,7 @@ const ( ) func TestNewProxyFuncUnset(t *testing.T) { - pf, err := newProxyFunc(zap.NewExample(), "") + pf, err := newProxyFunc(zaptest.NewLogger(t), "") if pf != nil { t.Fatal("unexpected non-nil proxyFunc") } @@ -54,7 +54,7 @@ func TestNewProxyFuncBad(t *testing.T) { "http://foo.com/%1", } for i, in := range tests { - pf, err := newProxyFunc(zap.NewExample(), in) + pf, err := newProxyFunc(zaptest.NewLogger(t), in) if pf != nil { t.Errorf("#%d: unexpected non-nil proxyFunc", i) } @@ -70,7 +70,7 @@ func TestNewProxyFunc(t *testing.T) { "http://disco.foo.bar": "http://disco.foo.bar", } for in, w := range tests { - pf, err := newProxyFunc(zap.NewExample(), in) + pf, err := newProxyFunc(zaptest.NewLogger(t), in) if pf == nil { t.Errorf("%s: unexpected nil proxyFunc", in) continue @@ -197,12 +197,12 @@ func TestCheckCluster(t *testing.T) { }) } c := &clientWithResp{rs: rs} - dBase := newTestDiscovery(cluster, 1, c) + dBase := newTestDiscovery(t, cluster, 1, c) cRetry := &clientWithRetry{failTimes: 3} cRetry.rs = rs fc := clockwork.NewFakeClock() - dRetry := newTestDiscoveryWithClock(cluster, 1, cRetry, fc) + dRetry := newTestDiscoveryWithClock(t, cluster, 1, cRetry, fc) for _, d := range []*discovery{dBase, dRetry} { go func() { @@ -267,7 +267,7 @@ func TestWaitNodes(t *testing.T) { for i, tt := range tests { // Basic case c := &clientWithResp{rs: nil, w: &watcherWithResp{rs: tt.rs}} - dBase := newTestDiscovery("1000", 1, c) + dBase := newTestDiscovery(t, "1000", 1, c) // Retry case var retryScanResp []*client.Response @@ -289,7 +289,7 @@ func TestWaitNodes(t *testing.T) { w: &watcherWithRetry{rs: tt.rs, failTimes: 2}, } fc := clockwork.NewFakeClock() - dRetry := newTestDiscoveryWithClock("1000", 1, cRetry, fc) + dRetry := newTestDiscoveryWithClock(t, "1000", 1, cRetry, fc) for _, d := range []*discovery{dBase, dRetry} { go func() { @@ -335,7 +335,7 @@ func TestCreateSelf(t *testing.T) { } for i, tt := range tests { - d := newTestDiscovery("1000", 1, tt.c) + d := newTestDiscovery(t, "1000", 1, tt.c) if err := d.createSelf(""); err != tt.werr { t.Errorf("#%d: err = %v, want %v", i, err, nil) } @@ -428,7 +428,7 @@ func TestRetryFailure(t *testing.T) { cluster := "1000" c := &clientWithRetry{failTimes: 4} fc := clockwork.NewFakeClock() - d := newTestDiscoveryWithClock(cluster, 1, c, fc) + d := newTestDiscoveryWithClock(t, cluster, 1, c, fc) go func() { for i := uint(1); i <= maxRetryInTest; i++ { fc.BlockUntil(1) @@ -551,9 +551,9 @@ func (w *watcherWithRetry) Next(context.Context) (*client.Response, error) { return r, nil } -func newTestDiscovery(cluster string, id types.ID, c client.KeysAPI) *discovery { +func newTestDiscovery(t *testing.T, cluster string, id types.ID, c client.KeysAPI) *discovery { return &discovery{ - lg: zap.NewExample(), + lg: zaptest.NewLogger(t), cluster: cluster, id: id, c: c, @@ -561,9 +561,9 @@ func newTestDiscovery(cluster string, id types.ID, c client.KeysAPI) *discovery } } -func newTestDiscoveryWithClock(cluster string, id types.ID, c client.KeysAPI, clock clockwork.Clock) *discovery { +func newTestDiscoveryWithClock(t *testing.T, cluster string, id types.ID, c client.KeysAPI, clock clockwork.Clock) *discovery { return &discovery{ - lg: zap.NewExample(), + lg: zaptest.NewLogger(t), cluster: cluster, id: id, c: c, diff --git a/server/etcdserver/api/v3compactor/periodic_test.go b/server/etcdserver/api/v3compactor/periodic_test.go index 7a806bfe8992..07313cc68ea8 100644 --- a/server/etcdserver/api/v3compactor/periodic_test.go +++ b/server/etcdserver/api/v3compactor/periodic_test.go @@ -21,9 +21,9 @@ import ( pb "go.etcd.io/etcd/api/v3/etcdserverpb" "go.etcd.io/etcd/client/pkg/v3/testutil" + "go.uber.org/zap/zaptest" "github.com/jonboulle/clockwork" - "go.uber.org/zap" ) func TestPeriodicHourly(t *testing.T) { @@ -34,7 +34,7 @@ func TestPeriodicHourly(t *testing.T) { // TODO: Do not depand or real time (Recorder.Wait) in unit tests. rg := &fakeRevGetter{testutil.NewRecorderStreamWithWaitTimout(10 * time.Millisecond), 0} compactable := &fakeCompactable{testutil.NewRecorderStreamWithWaitTimout(10 * time.Millisecond)} - tb := newPeriodic(zap.NewExample(), fc, retentionDuration, rg, compactable) + tb := newPeriodic(zaptest.NewLogger(t), fc, retentionDuration, rg, compactable) tb.Run() defer tb.Stop() @@ -85,7 +85,7 @@ func TestPeriodicMinutes(t *testing.T) { fc := clockwork.NewFakeClock() rg := &fakeRevGetter{testutil.NewRecorderStreamWithWaitTimout(10 * time.Millisecond), 0} compactable := &fakeCompactable{testutil.NewRecorderStreamWithWaitTimout(10 * time.Millisecond)} - tb := newPeriodic(zap.NewExample(), fc, retentionDuration, rg, compactable) + tb := newPeriodic(zaptest.NewLogger(t), fc, retentionDuration, rg, compactable) tb.Run() defer tb.Stop() @@ -133,7 +133,7 @@ func TestPeriodicPause(t *testing.T) { retentionDuration := time.Hour rg := &fakeRevGetter{testutil.NewRecorderStreamWithWaitTimout(10 * time.Millisecond), 0} compactable := &fakeCompactable{testutil.NewRecorderStreamWithWaitTimout(10 * time.Millisecond)} - tb := newPeriodic(zap.NewExample(), fc, retentionDuration, rg, compactable) + tb := newPeriodic(zaptest.NewLogger(t), fc, retentionDuration, rg, compactable) tb.Run() tb.Pause() diff --git a/server/etcdserver/api/v3compactor/revision_test.go b/server/etcdserver/api/v3compactor/revision_test.go index a3ae3d3478dc..58472e1ecb54 100644 --- a/server/etcdserver/api/v3compactor/revision_test.go +++ b/server/etcdserver/api/v3compactor/revision_test.go @@ -21,16 +21,16 @@ import ( pb "go.etcd.io/etcd/api/v3/etcdserverpb" "go.etcd.io/etcd/client/pkg/v3/testutil" + "go.uber.org/zap/zaptest" "github.com/jonboulle/clockwork" - "go.uber.org/zap" ) func TestRevision(t *testing.T) { fc := clockwork.NewFakeClock() rg := &fakeRevGetter{testutil.NewRecorderStreamWithWaitTimout(10 * time.Millisecond), 0} compactable := &fakeCompactable{testutil.NewRecorderStreamWithWaitTimout(10 * time.Millisecond)} - tb := newRevision(zap.NewExample(), fc, 10, rg, compactable) + tb := newRevision(zaptest.NewLogger(t), fc, 10, rg, compactable) tb.Run() defer tb.Stop() @@ -73,7 +73,7 @@ func TestRevisionPause(t *testing.T) { fc := clockwork.NewFakeClock() rg := &fakeRevGetter{testutil.NewRecorderStream(), 99} // will be 100 compactable := &fakeCompactable{testutil.NewRecorderStream()} - tb := newRevision(zap.NewExample(), fc, 10, rg, compactable) + tb := newRevision(zaptest.NewLogger(t), fc, 10, rg, compactable) tb.Run() tb.Pause() diff --git a/server/etcdserver/api/v3discovery/discovery_test.go b/server/etcdserver/api/v3discovery/discovery_test.go index 529bb3984623..dc6f52bf5139 100644 --- a/server/etcdserver/api/v3discovery/discovery_test.go +++ b/server/etcdserver/api/v3discovery/discovery_test.go @@ -10,9 +10,9 @@ import ( "go.etcd.io/etcd/api/v3/mvccpb" "go.etcd.io/etcd/client/pkg/v3/types" "go.etcd.io/etcd/client/v3" + "go.uber.org/zap/zaptest" "github.com/jonboulle/clockwork" - "go.uber.org/zap" ) // fakeKVForClusterSize is used to test getClusterSize. @@ -62,12 +62,9 @@ func TestGetClusterSize(t *testing.T) { }, } - lg, err := zap.NewProduction() - if err != nil { - t.Errorf("Failed to create a logger, error: %v", err) - } for _, tc := range cases { t.Run(tc.name, func(t *testing.T) { + lg := zaptest.NewLogger(t) d := &discovery{ lg: lg, c: &clientv3.Client{ @@ -178,10 +175,7 @@ func TestGetClusterMembers(t *testing.T) { }, } - lg, err := zap.NewProduction() - if err != nil { - t.Errorf("Failed to create a logger, error: %v", err) - } + lg := zaptest.NewLogger(t) d := &discovery{ lg: lg, @@ -356,10 +350,7 @@ func TestCheckCluster(t *testing.T) { for _, tc := range cases { t.Run(tc.name, func(t *testing.T) { - lg, err := zap.NewProduction() - if err != nil { - t.Errorf("Failed to create a logger, error: %v", err) - } + lg := zaptest.NewLogger(t) fkv := &fakeKVForCheckCluster{ fakeBaseKV: &fakeBaseKV{}, @@ -469,13 +460,9 @@ func TestRegisterSelf(t *testing.T) { }, } - lg, err := zap.NewProduction() - if err != nil { - t.Errorf("Failed to create a logger, error: %v", err) - } - for _, tc := range cases { t.Run(tc.name, func(t *testing.T) { + lg := zaptest.NewLogger(t) fkv := &fakeKVForRegisterSelf{ fakeBaseKV: &fakeBaseKV{}, t: t, @@ -597,10 +584,7 @@ func TestWaitPeers(t *testing.T) { }, } - lg, err := zap.NewProduction() - if err != nil { - t.Errorf("Failed to create a logger, error: %v", err) - } + lg := zaptest.NewLogger(t) d := &discovery{ lg: lg, diff --git a/server/etcdserver/bootstrap_test.go b/server/etcdserver/bootstrap_test.go index 3db684d56747..a95ff34800ed 100644 --- a/server/etcdserver/bootstrap_test.go +++ b/server/etcdserver/bootstrap_test.go @@ -20,11 +20,6 @@ package etcdserver import ( "encoding/json" "fmt" - bolt "go.etcd.io/bbolt" - "go.etcd.io/etcd/server/v3/storage/datadir" - "go.etcd.io/etcd/server/v3/storage/schema" - "go.etcd.io/etcd/server/v3/storage/wal" - "go.etcd.io/etcd/server/v3/storage/wal/walpb" "io" "net/http" "os" @@ -32,6 +27,13 @@ import ( "strings" "testing" + bolt "go.etcd.io/bbolt" + "go.etcd.io/etcd/server/v3/storage/datadir" + "go.etcd.io/etcd/server/v3/storage/schema" + "go.etcd.io/etcd/server/v3/storage/wal" + "go.etcd.io/etcd/server/v3/storage/wal/walpb" + "go.uber.org/zap/zaptest" + "go.etcd.io/etcd/api/v3/etcdserverpb" "go.etcd.io/etcd/api/v3/version" "go.etcd.io/etcd/client/pkg/v3/types" @@ -41,7 +43,6 @@ import ( "go.etcd.io/etcd/server/v3/etcdserver/api/snap" "go.etcd.io/etcd/server/v3/etcdserver/api/v2store" serverstorage "go.etcd.io/etcd/server/v3/storage" - "go.uber.org/zap" ) func TestBootstrapExistingClusterNoWALMaxLearner(t *testing.T) { @@ -95,7 +96,7 @@ func TestBootstrapExistingClusterNoWALMaxLearner(t *testing.T) { cfg := config.ServerConfig{ Name: "node0", InitialPeerURLsMap: cluster, - Logger: zap.NewExample(), + Logger: zaptest.NewLogger(t), ExperimentalMaxLearners: tt.maxLearner, } _, err = bootstrapExistingClusterNoWAL(cfg, mockBootstrapRoundTrip(tt.members)) @@ -184,7 +185,7 @@ func TestBootstrapBackend(t *testing.T) { Name: "demoNode", DataDir: dataDir, BackendFreelistType: bolt.FreelistArrayType, - Logger: zap.NewExample(), + Logger: zaptest.NewLogger(t), } if tt.prepareData != nil { diff --git a/server/etcdserver/cluster_util_test.go b/server/etcdserver/cluster_util_test.go index 0397634d9372..2548294707e9 100644 --- a/server/etcdserver/cluster_util_test.go +++ b/server/etcdserver/cluster_util_test.go @@ -19,13 +19,11 @@ import ( "go.etcd.io/etcd/api/v3/version" "go.etcd.io/etcd/client/pkg/v3/types" + "go.uber.org/zap/zaptest" "github.com/coreos/go-semver/semver" - "go.uber.org/zap" ) -var testLogger = zap.NewExample() - func TestIsCompatibleWithVers(t *testing.T) { tests := []struct { vers map[string]*version.Versions @@ -90,7 +88,7 @@ func TestIsCompatibleWithVers(t *testing.T) { } for i, tt := range tests { - ok := isCompatibleWithVers(testLogger, tt.vers, tt.local, tt.minV, tt.maxV) + ok := isCompatibleWithVers(zaptest.NewLogger(t), tt.vers, tt.local, tt.minV, tt.maxV) if ok != tt.wok { t.Errorf("#%d: ok = %+v, want %+v", i, ok, tt.wok) } diff --git a/server/etcdserver/raft_test.go b/server/etcdserver/raft_test.go index f552f81808dd..9921929892d8 100644 --- a/server/etcdserver/raft_test.go +++ b/server/etcdserver/raft_test.go @@ -29,7 +29,7 @@ import ( "go.etcd.io/etcd/server/v3/etcdserver/api/membership" "go.etcd.io/etcd/server/v3/mock/mockstorage" serverstorage "go.etcd.io/etcd/server/v3/storage" - "go.uber.org/zap" + "go.uber.org/zap/zaptest" ) func TestGetIDs(t *testing.T) { @@ -67,7 +67,7 @@ func TestGetIDs(t *testing.T) { if tt.confState != nil { snap.Metadata.ConfState = *tt.confState } - idSet := serverstorage.GetEffectiveNodeIDsFromWalEntries(testLogger, &snap, tt.ents) + idSet := serverstorage.GetEffectiveNodeIDsFromWalEntries(zaptest.NewLogger(t), &snap, tt.ents) if !reflect.DeepEqual(idSet, tt.widSet) { t.Errorf("#%d: idset = %#v, want %#v", i, idSet, tt.widSet) } @@ -147,7 +147,7 @@ func TestCreateConfigChangeEnts(t *testing.T) { } for i, tt := range tests { - gents := serverstorage.CreateConfigChangeEnts(testLogger, tt.ids, tt.self, tt.term, tt.index) + gents := serverstorage.CreateConfigChangeEnts(zaptest.NewLogger(t), tt.ids, tt.self, tt.term, tt.index) if !reflect.DeepEqual(gents, tt.wents) { t.Errorf("#%d: ents = %v, want %v", i, gents, tt.wents) } @@ -157,13 +157,13 @@ func TestCreateConfigChangeEnts(t *testing.T) { func TestStopRaftWhenWaitingForApplyDone(t *testing.T) { n := newNopReadyNode() r := newRaftNode(raftNodeConfig{ - lg: zap.NewExample(), + lg: zaptest.NewLogger(t), Node: n, storage: mockstorage.NewStorageRecorder(""), raftStorage: raft.NewMemoryStorage(), transport: newNopTransporter(), }) - srv := &EtcdServer{lgMu: new(sync.RWMutex), lg: zap.NewExample(), r: *r} + srv := &EtcdServer{lgMu: new(sync.RWMutex), lg: zaptest.NewLogger(t), r: *r} srv.r.start(nil) n.readyc <- raft.Ready{} select { @@ -185,13 +185,13 @@ func TestConfigChangeBlocksApply(t *testing.T) { n := newNopReadyNode() r := newRaftNode(raftNodeConfig{ - lg: zap.NewExample(), + lg: zaptest.NewLogger(t), Node: n, storage: mockstorage.NewStorageRecorder(""), raftStorage: raft.NewMemoryStorage(), transport: newNopTransporter(), }) - srv := &EtcdServer{lgMu: new(sync.RWMutex), lg: zap.NewExample(), r: *r} + srv := &EtcdServer{lgMu: new(sync.RWMutex), lg: zaptest.NewLogger(t), r: *r} srv.r.start(&raftReadyHandler{ getLead: func() uint64 { return 0 }, @@ -231,13 +231,13 @@ func TestConfigChangeBlocksApply(t *testing.T) { func TestProcessDuplicatedAppRespMessage(t *testing.T) { n := newNopReadyNode() - cl := membership.NewCluster(zap.NewExample()) + cl := membership.NewCluster(zaptest.NewLogger(t)) rs := raft.NewMemoryStorage() p := mockstorage.NewStorageRecorder("") tr, sendc := newSendMsgAppRespTransporter() r := newRaftNode(raftNodeConfig{ - lg: zap.NewExample(), + lg: zaptest.NewLogger(t), isIDRemoved: func(id uint64) bool { return cl.IsIDRemoved(types.ID(id)) }, Node: n, transport: tr, @@ -247,7 +247,7 @@ func TestProcessDuplicatedAppRespMessage(t *testing.T) { s := &EtcdServer{ lgMu: new(sync.RWMutex), - lg: zap.NewExample(), + lg: zaptest.NewLogger(t), r: *r, cluster: cl, SyncTicker: &time.Ticker{}, diff --git a/server/etcdserver/server_test.go b/server/etcdserver/server_test.go index 07636c6e468c..cb4386976d92 100644 --- a/server/etcdserver/server_test.go +++ b/server/etcdserver/server_test.go @@ -101,7 +101,7 @@ func TestDoLocalAction(t *testing.T) { st := mockstore.NewRecorder() srv := &EtcdServer{ lgMu: new(sync.RWMutex), - lg: zap.NewExample(), + lg: zaptest.NewLogger(t), v2store: st, reqIDGen: idutil.NewGenerator(0, time.Time{}), } @@ -156,7 +156,7 @@ func TestDoBadLocalAction(t *testing.T) { st := mockstore.NewErrRecorder(storeErr) srv := &EtcdServer{ lgMu: new(sync.RWMutex), - lg: zap.NewExample(), + lg: zaptest.NewLogger(t), v2store: st, reqIDGen: idutil.NewGenerator(0, time.Time{}), } @@ -186,7 +186,7 @@ func TestApplyRepeat(t *testing.T) { cl.SetStore(v2store.New()) cl.AddMember(&membership.Member{ID: 1234}, true) r := newRaftNode(raftNodeConfig{ - lg: zap.NewExample(), + lg: zaptest.NewLogger(t), Node: n, raftStorage: raft.NewMemoryStorage(), storage: mockstorage.NewStorageRecorder(""), @@ -194,7 +194,7 @@ func TestApplyRepeat(t *testing.T) { }) s := &EtcdServer{ lgMu: new(sync.RWMutex), - lg: zap.NewExample(), + lg: zaptest.NewLogger(t), r: *r, v2store: st, cluster: cl, @@ -469,7 +469,7 @@ func TestApplyRequest(t *testing.T) { st := mockstore.NewRecorder() srv := &EtcdServer{ lgMu: new(sync.RWMutex), - lg: zap.NewExample(), + lg: zaptest.NewLogger(t), v2store: st, } srv.applyV2 = &applierV2store{store: srv.v2store, cluster: srv.cluster} @@ -489,7 +489,7 @@ func TestApplyRequestOnAdminMemberAttributes(t *testing.T) { cl := newTestCluster(t, []*membership.Member{{ID: 1}}) srv := &EtcdServer{ lgMu: new(sync.RWMutex), - lg: zap.NewExample(), + lg: zaptest.NewLogger(t), v2store: mockstore.NewRecorder(), cluster: cl, } @@ -575,8 +575,8 @@ func TestApplyConfChangeError(t *testing.T) { n := newNodeRecorder() srv := &EtcdServer{ lgMu: new(sync.RWMutex), - lg: zap.NewExample(), - r: *newRaftNode(raftNodeConfig{lg: zap.NewExample(), Node: n}), + lg: zaptest.NewLogger(t), + r: *newRaftNode(raftNodeConfig{lg: zaptest.NewLogger(t), Node: n}), cluster: cl, } _, err := srv.applyConfChange(tt.cc, nil, true) @@ -603,7 +603,7 @@ func TestApplyConfChangeShouldStop(t *testing.T) { cl.AddMember(&membership.Member{ID: types.ID(i)}, true) } r := newRaftNode(raftNodeConfig{ - lg: zap.NewExample(), + lg: zaptest.NewLogger(t), Node: newNodeNop(), transport: newNopTransporter(), }) @@ -778,7 +778,7 @@ func TestDoProposal(t *testing.T) { for i, tt := range tests { st := mockstore.NewRecorder() r := newRaftNode(raftNodeConfig{ - lg: zap.NewExample(), + lg: zaptest.NewLogger(t), Node: newNodeCommitter(), storage: mockstorage.NewStorageRecorder(""), raftStorage: raft.NewMemoryStorage(), @@ -786,8 +786,8 @@ func TestDoProposal(t *testing.T) { }) srv := &EtcdServer{ lgMu: new(sync.RWMutex), - lg: zap.NewExample(), - Cfg: config.ServerConfig{Logger: zap.NewExample(), TickMs: 1, SnapshotCatchUpEntries: DefaultSnapshotCatchUpEntries}, + lg: zaptest.NewLogger(t), + Cfg: config.ServerConfig{Logger: zaptest.NewLogger(t), TickMs: 1, SnapshotCatchUpEntries: DefaultSnapshotCatchUpEntries}, r: *r, v2store: st, reqIDGen: idutil.NewGenerator(0, time.Time{}), @@ -818,8 +818,8 @@ func TestDoProposalCancelled(t *testing.T) { wt := mockwait.NewRecorder() srv := &EtcdServer{ lgMu: new(sync.RWMutex), - lg: zap.NewExample(), - Cfg: config.ServerConfig{Logger: zap.NewExample(), TickMs: 1, SnapshotCatchUpEntries: DefaultSnapshotCatchUpEntries}, + lg: zaptest.NewLogger(t), + Cfg: config.ServerConfig{Logger: zaptest.NewLogger(t), TickMs: 1, SnapshotCatchUpEntries: DefaultSnapshotCatchUpEntries}, r: *newRaftNode(raftNodeConfig{Node: newNodeNop()}), w: wt, reqIDGen: idutil.NewGenerator(0, time.Time{}), @@ -842,8 +842,8 @@ func TestDoProposalCancelled(t *testing.T) { func TestDoProposalTimeout(t *testing.T) { srv := &EtcdServer{ lgMu: new(sync.RWMutex), - lg: zap.NewExample(), - Cfg: config.ServerConfig{Logger: zap.NewExample(), TickMs: 1, SnapshotCatchUpEntries: DefaultSnapshotCatchUpEntries}, + lg: zaptest.NewLogger(t), + Cfg: config.ServerConfig{Logger: zaptest.NewLogger(t), TickMs: 1, SnapshotCatchUpEntries: DefaultSnapshotCatchUpEntries}, r: *newRaftNode(raftNodeConfig{Node: newNodeNop()}), w: mockwait.NewNop(), reqIDGen: idutil.NewGenerator(0, time.Time{}), @@ -861,9 +861,9 @@ func TestDoProposalTimeout(t *testing.T) { func TestDoProposalStopped(t *testing.T) { srv := &EtcdServer{ lgMu: new(sync.RWMutex), - lg: zap.NewExample(), - Cfg: config.ServerConfig{Logger: zap.NewExample(), TickMs: 1, SnapshotCatchUpEntries: DefaultSnapshotCatchUpEntries}, - r: *newRaftNode(raftNodeConfig{lg: zap.NewExample(), Node: newNodeNop()}), + lg: zaptest.NewLogger(t), + Cfg: config.ServerConfig{Logger: zaptest.NewLogger(t), TickMs: 1, SnapshotCatchUpEntries: DefaultSnapshotCatchUpEntries}, + r: *newRaftNode(raftNodeConfig{lg: zaptest.NewLogger(t), Node: newNodeNop()}), w: mockwait.NewNop(), reqIDGen: idutil.NewGenerator(0, time.Time{}), } @@ -883,8 +883,8 @@ func TestSync(t *testing.T) { ctx, cancel := context.WithCancel(context.Background()) srv := &EtcdServer{ lgMu: new(sync.RWMutex), - lg: zap.NewExample(), - r: *newRaftNode(raftNodeConfig{lg: zap.NewExample(), Node: n}), + lg: zaptest.NewLogger(t), + r: *newRaftNode(raftNodeConfig{lg: zaptest.NewLogger(t), Node: n}), reqIDGen: idutil.NewGenerator(0, time.Time{}), ctx: ctx, cancel: cancel, @@ -928,8 +928,8 @@ func TestSyncTimeout(t *testing.T) { ctx, cancel := context.WithCancel(context.Background()) srv := &EtcdServer{ lgMu: new(sync.RWMutex), - lg: zap.NewExample(), - r: *newRaftNode(raftNodeConfig{lg: zap.NewExample(), Node: n}), + lg: zaptest.NewLogger(t), + r: *newRaftNode(raftNodeConfig{lg: zaptest.NewLogger(t), Node: n}), reqIDGen: idutil.NewGenerator(0, time.Time{}), ctx: ctx, cancel: cancel, @@ -963,7 +963,7 @@ func TestSyncTrigger(t *testing.T) { st := make(chan time.Time, 1) tk := &time.Ticker{C: st} r := newRaftNode(raftNodeConfig{ - lg: zap.NewExample(), + lg: zaptest.NewLogger(t), Node: n, raftStorage: raft.NewMemoryStorage(), transport: newNopTransporter(), @@ -972,8 +972,8 @@ func TestSyncTrigger(t *testing.T) { srv := &EtcdServer{ lgMu: new(sync.RWMutex), - lg: zap.NewExample(), - Cfg: config.ServerConfig{Logger: zap.NewExample(), TickMs: 1, SnapshotCatchUpEntries: DefaultSnapshotCatchUpEntries}, + lg: zaptest.NewLogger(t), + Cfg: config.ServerConfig{Logger: zaptest.NewLogger(t), TickMs: 1, SnapshotCatchUpEntries: DefaultSnapshotCatchUpEntries}, r: *r, v2store: mockstore.NewNop(), SyncTicker: tk, @@ -1023,19 +1023,19 @@ func TestSnapshot(t *testing.T) { st := mockstore.NewRecorderStream() p := mockstorage.NewStorageRecorderStream("") r := newRaftNode(raftNodeConfig{ - lg: zap.NewExample(), + lg: zaptest.NewLogger(t), Node: newNodeNop(), raftStorage: s, storage: p, }) srv := &EtcdServer{ lgMu: new(sync.RWMutex), - lg: zap.NewExample(), + lg: zaptest.NewLogger(t), r: *r, v2store: st, consistIndex: cindex.NewConsistentIndex(be), } - srv.kv = mvcc.New(zap.NewExample(), be, &lease.FakeLessor{}, mvcc.StoreConfig{}) + srv.kv = mvcc.New(zaptest.NewLogger(t), be, &lease.FakeLessor{}, mvcc.StoreConfig{}) srv.be = be ch := make(chan struct{}, 2) @@ -1095,7 +1095,7 @@ func TestSnapshotOrdering(t *testing.T) { rs := raft.NewMemoryStorage() p := mockstorage.NewStorageRecorderStream(testdir) - tr, snapDoneC := newSnapTransporter(snapdir) + tr, snapDoneC := newSnapTransporter(lg, snapdir) r := newRaftNode(raftNodeConfig{ lg: lg, isIDRemoved: func(id uint64) bool { return cl.IsIDRemoved(types.ID(id)) }, @@ -1176,7 +1176,7 @@ func TestTriggerSnap(t *testing.T) { st := mockstore.NewRecorder() p := mockstorage.NewStorageRecorderStream("") r := newRaftNode(raftNodeConfig{ - lg: zap.NewExample(), + lg: zaptest.NewLogger(t), Node: newNodeCommitter(), raftStorage: raft.NewMemoryStorage(), storage: p, @@ -1184,8 +1184,8 @@ func TestTriggerSnap(t *testing.T) { }) srv := &EtcdServer{ lgMu: new(sync.RWMutex), - lg: zap.NewExample(), - Cfg: config.ServerConfig{Logger: zap.NewExample(), TickMs: 1, SnapshotCount: uint64(snapc), SnapshotCatchUpEntries: DefaultSnapshotCatchUpEntries}, + lg: zaptest.NewLogger(t), + Cfg: config.ServerConfig{Logger: zaptest.NewLogger(t), TickMs: 1, SnapshotCount: uint64(snapc), SnapshotCatchUpEntries: DefaultSnapshotCatchUpEntries}, r: *r, v2store: st, reqIDGen: idutil.NewGenerator(0, time.Time{}), @@ -1194,7 +1194,7 @@ func TestTriggerSnap(t *testing.T) { } srv.applyV2 = &applierV2store{store: srv.v2store, cluster: srv.cluster} - srv.kv = mvcc.New(zap.NewExample(), be, &lease.FakeLessor{}, mvcc.StoreConfig{}) + srv.kv = mvcc.New(zaptest.NewLogger(t), be, &lease.FakeLessor{}, mvcc.StoreConfig{}) srv.be = be srv.start() @@ -1244,7 +1244,7 @@ func TestConcurrentApplyAndSnapshotV3(t *testing.T) { } rs := raft.NewMemoryStorage() - tr, snapDoneC := newSnapTransporter(testdir) + tr, snapDoneC := newSnapTransporter(lg, testdir) r := newRaftNode(raftNodeConfig{ lg: lg, isIDRemoved: func(id uint64) bool { return cl.IsIDRemoved(types.ID(id)) }, @@ -1390,7 +1390,7 @@ func TestRemoveMember(t *testing.T) { }) s := &EtcdServer{ lgMu: new(sync.RWMutex), - lg: zap.NewExample(), + lg: zaptest.NewLogger(t), r: *r, v2store: st, cluster: cl, @@ -1513,14 +1513,14 @@ func TestPublishV3(t *testing.T) { func TestPublishV3Stopped(t *testing.T) { ctx, cancel := context.WithCancel(context.Background()) r := newRaftNode(raftNodeConfig{ - lg: zap.NewExample(), + lg: zaptest.NewLogger(t), Node: newNodeNop(), transport: newNopTransporter(), }) srv := &EtcdServer{ lgMu: new(sync.RWMutex), - lg: zap.NewExample(), - Cfg: config.ServerConfig{Logger: zap.NewExample(), TickMs: 1, SnapshotCatchUpEntries: DefaultSnapshotCatchUpEntries}, + lg: zaptest.NewLogger(t), + Cfg: config.ServerConfig{Logger: zaptest.NewLogger(t), TickMs: 1, SnapshotCatchUpEntries: DefaultSnapshotCatchUpEntries}, r: *r, cluster: &membership.RaftCluster{}, w: mockwait.NewNop(), @@ -1595,10 +1595,10 @@ func TestUpdateVersion(t *testing.T) { ctx, cancel := context.WithCancel(context.TODO()) srv := &EtcdServer{ lgMu: new(sync.RWMutex), - lg: zap.NewExample(), + lg: zaptest.NewLogger(t), id: 1, - Cfg: config.ServerConfig{Logger: zap.NewExample(), TickMs: 1, SnapshotCatchUpEntries: DefaultSnapshotCatchUpEntries}, - r: *newRaftNode(raftNodeConfig{lg: zap.NewExample(), Node: n}), + Cfg: config.ServerConfig{Logger: zaptest.NewLogger(t), TickMs: 1, SnapshotCatchUpEntries: DefaultSnapshotCatchUpEntries}, + r: *newRaftNode(raftNodeConfig{lg: zaptest.NewLogger(t), Node: n}), attributes: membership.Attributes{Name: "node1", ClientURLs: []string{"http://node1.com"}}, cluster: &membership.RaftCluster{}, w: w, @@ -1636,7 +1636,7 @@ func TestUpdateVersion(t *testing.T) { func TestStopNotify(t *testing.T) { s := &EtcdServer{ lgMu: new(sync.RWMutex), - lg: zap.NewExample(), + lg: zaptest.NewLogger(t), stop: make(chan struct{}), done: make(chan struct{}), } @@ -1873,16 +1873,17 @@ type snapTransporter struct { nopTransporter snapDoneC chan snap.Message snapDir string + lg *zap.Logger } -func newSnapTransporter(snapDir string) (rafthttp.Transporter, <-chan snap.Message) { +func newSnapTransporter(lg *zap.Logger, snapDir string) (rafthttp.Transporter, <-chan snap.Message) { ch := make(chan snap.Message, 1) - tr := &snapTransporter{snapDoneC: ch, snapDir: snapDir} + tr := &snapTransporter{snapDoneC: ch, snapDir: snapDir, lg: lg} return tr, ch } func (s *snapTransporter) SendSnapshot(m snap.Message) { - ss := snap.New(zap.NewExample(), s.snapDir) + ss := snap.New(s.lg, s.snapDir) ss.SaveDBFrom(m.ReadCloser, m.Snapshot.Metadata.Index+1) m.CloseWithError(nil) s.snapDoneC <- m diff --git a/server/etcdserver/util_bench_test.go b/server/etcdserver/util_bench_test.go index 7a716d88bad6..57d7d46131e8 100644 --- a/server/etcdserver/util_bench_test.go +++ b/server/etcdserver/util_bench_test.go @@ -16,9 +16,11 @@ package etcdserver import ( "errors" - "go.etcd.io/etcd/raft/v3/raftpb" "testing" "time" + + "go.etcd.io/etcd/raft/v3/raftpb" + "go.uber.org/zap/zaptest" ) func BenchmarkWarnOfExpensiveRequestNoLog(b *testing.B) { @@ -45,6 +47,6 @@ func BenchmarkWarnOfExpensiveRequestNoLog(b *testing.B) { } err := errors.New("benchmarking warn of expensive request") for n := 0; n < b.N; n++ { - warnOfExpensiveRequest(testLogger, time.Second, time.Now(), nil, m, err) + warnOfExpensiveRequest(zaptest.NewLogger(b), time.Second, time.Now(), nil, m, err) } } diff --git a/server/etcdserver/util_test.go b/server/etcdserver/util_test.go index dd57c7e1d2e9..06c3e5a7bd0e 100644 --- a/server/etcdserver/util_test.go +++ b/server/etcdserver/util_test.go @@ -19,7 +19,7 @@ import ( "testing" "time" - "go.uber.org/zap" + "go.uber.org/zap/zaptest" "go.etcd.io/etcd/client/pkg/v3/types" "go.etcd.io/etcd/raft/v3/raftpb" @@ -33,7 +33,7 @@ func TestLongestConnected(t *testing.T) { if err != nil { t.Fatal(err) } - clus, err := membership.NewClusterFromURLsMap(zap.NewExample(), "test", umap) + clus, err := membership.NewClusterFromURLsMap(zaptest.NewLogger(t), "test", umap) if err != nil { t.Fatal(err) } diff --git a/server/proxy/httpproxy/director_test.go b/server/proxy/httpproxy/director_test.go index 952506729dc6..9bba5987c7a5 100644 --- a/server/proxy/httpproxy/director_test.go +++ b/server/proxy/httpproxy/director_test.go @@ -21,7 +21,7 @@ import ( "testing" "time" - "go.uber.org/zap" + "go.uber.org/zap/zaptest" ) func TestNewDirectorScheme(t *testing.T) { @@ -55,7 +55,7 @@ func TestNewDirectorScheme(t *testing.T) { uf := func() []string { return tt.urls } - got := newDirector(zap.NewExample(), uf, time.Minute, time.Minute) + got := newDirector(zaptest.NewLogger(t), uf, time.Minute, time.Minute) var gep []string for _, ep := range got.ep { diff --git a/server/proxy/httpproxy/proxy_test.go b/server/proxy/httpproxy/proxy_test.go index 2c4d26a66880..5506e0b3c10d 100644 --- a/server/proxy/httpproxy/proxy_test.go +++ b/server/proxy/httpproxy/proxy_test.go @@ -22,7 +22,7 @@ import ( "testing" "time" - "go.uber.org/zap" + "go.uber.org/zap/zaptest" ) func TestReadonlyHandler(t *testing.T) { @@ -73,7 +73,7 @@ func TestConfigHandlerGET(t *testing.T) { t.Fatal(err) } - lg := zap.NewExample() + lg := zaptest.NewLogger(t) rp := reverseProxy{ lg: lg, director: &director{ diff --git a/server/proxy/httpproxy/reverse_test.go b/server/proxy/httpproxy/reverse_test.go index 1b4bcf189f5e..6e12edae5c75 100644 --- a/server/proxy/httpproxy/reverse_test.go +++ b/server/proxy/httpproxy/reverse_test.go @@ -24,7 +24,7 @@ import ( "reflect" "testing" - "go.uber.org/zap" + "go.uber.org/zap/zaptest" ) type staticRoundTripper struct { @@ -38,7 +38,7 @@ func (srt *staticRoundTripper) RoundTrip(*http.Request) (*http.Response, error) func TestReverseProxyServe(t *testing.T) { u := url.URL{Scheme: "http", Host: "192.0.2.3:4040"} - lg := zap.NewExample() + lg := zaptest.NewLogger(t) tests := []struct { eps []*endpoint diff --git a/server/storage/mvcc/index_test.go b/server/storage/mvcc/index_test.go index 87c31dd905fa..dd65e661d57c 100644 --- a/server/storage/mvcc/index_test.go +++ b/server/storage/mvcc/index_test.go @@ -19,11 +19,11 @@ import ( "testing" "github.com/google/btree" - "go.uber.org/zap" + "go.uber.org/zap/zaptest" ) func TestIndexGet(t *testing.T) { - ti := newTreeIndex(zap.NewExample()) + ti := newTreeIndex(zaptest.NewLogger(t)) ti.Put([]byte("foo"), revision{main: 2}) ti.Put([]byte("foo"), revision{main: 4}) ti.Tombstone([]byte("foo"), revision{main: 6}) @@ -65,7 +65,7 @@ func TestIndexRange(t *testing.T) { allKeys := [][]byte{[]byte("foo"), []byte("foo1"), []byte("foo2")} allRevs := []revision{{main: 1}, {main: 2}, {main: 3}} - ti := newTreeIndex(zap.NewExample()) + ti := newTreeIndex(zaptest.NewLogger(t)) for i := range allKeys { ti.Put(allKeys[i], allRevs[i]) } @@ -121,7 +121,7 @@ func TestIndexRange(t *testing.T) { } func TestIndexTombstone(t *testing.T) { - ti := newTreeIndex(zap.NewExample()) + ti := newTreeIndex(zaptest.NewLogger(t)) ti.Put([]byte("foo"), revision{main: 1}) err := ti.Tombstone([]byte("foo"), revision{main: 2}) @@ -143,7 +143,7 @@ func TestIndexRangeSince(t *testing.T) { allKeys := [][]byte{[]byte("foo"), []byte("foo1"), []byte("foo2"), []byte("foo2"), []byte("foo1"), []byte("foo")} allRevs := []revision{{main: 1}, {main: 2}, {main: 3}, {main: 4}, {main: 5}, {main: 6}} - ti := newTreeIndex(zap.NewExample()) + ti := newTreeIndex(zaptest.NewLogger(t)) for i := range allKeys { ti.Put(allKeys[i], allRevs[i]) } @@ -217,7 +217,7 @@ func TestIndexCompactAndKeep(t *testing.T) { } // Continuous Compact and Keep - ti := newTreeIndex(zap.NewExample()) + ti := newTreeIndex(zaptest.NewLogger(t)) for _, tt := range tests { if tt.remove { ti.Tombstone(tt.key, tt.rev) @@ -248,7 +248,7 @@ func TestIndexCompactAndKeep(t *testing.T) { // Once Compact and Keep for i := int64(1); i < maxRev; i++ { - ti := newTreeIndex(zap.NewExample()) + ti := newTreeIndex(zaptest.NewLogger(t)) for _, tt := range tests { if tt.remove { ti.Tombstone(tt.key, tt.rev) diff --git a/server/storage/mvcc/key_index_test.go b/server/storage/mvcc/key_index_test.go index 9e7da6ad90b2..b44bd4e0dd45 100644 --- a/server/storage/mvcc/key_index_test.go +++ b/server/storage/mvcc/key_index_test.go @@ -19,6 +19,7 @@ import ( "testing" "go.uber.org/zap" + "go.uber.org/zap/zaptest" ) func TestKeyIndexGet(t *testing.T) { @@ -29,8 +30,8 @@ func TestKeyIndexGet(t *testing.T) { // {{14, 0}[1], {14, 1}[2], {16, 0}(t)[3]} // {{8, 0}[1], {10, 0}[2], {12, 0}(t)[3]} // {{2, 0}[1], {4, 0}[2], {6, 0}(t)[3]} - ki := newTestKeyIndex() - ki.compact(zap.NewExample(), 4, make(map[revision]struct{})) + ki := newTestKeyIndex(zaptest.NewLogger(t)) + ki.compact(zaptest.NewLogger(t), 4, make(map[revision]struct{})) tests := []struct { rev int64 @@ -70,7 +71,7 @@ func TestKeyIndexGet(t *testing.T) { } for i, tt := range tests { - mod, creat, ver, err := ki.get(zap.NewExample(), tt.rev) + mod, creat, ver, err := ki.get(zaptest.NewLogger(t), tt.rev) if err != tt.werr { t.Errorf("#%d: err = %v, want %v", i, err, tt.werr) } @@ -87,8 +88,8 @@ func TestKeyIndexGet(t *testing.T) { } func TestKeyIndexSince(t *testing.T) { - ki := newTestKeyIndex() - ki.compact(zap.NewExample(), 4, make(map[revision]struct{})) + ki := newTestKeyIndex(zaptest.NewLogger(t)) + ki.compact(zaptest.NewLogger(t), 4, make(map[revision]struct{})) allRevs := []revision{{4, 0}, {6, 0}, {8, 0}, {10, 0}, {12, 0}, {14, 1}, {16, 0}} tests := []struct { @@ -117,7 +118,7 @@ func TestKeyIndexSince(t *testing.T) { } for i, tt := range tests { - revs := ki.since(zap.NewExample(), tt.rev) + revs := ki.since(zaptest.NewLogger(t), tt.rev) if !reflect.DeepEqual(revs, tt.wrevs) { t.Errorf("#%d: revs = %+v, want %+v", i, revs, tt.wrevs) } @@ -126,7 +127,7 @@ func TestKeyIndexSince(t *testing.T) { func TestKeyIndexPut(t *testing.T) { ki := &keyIndex{key: []byte("foo")} - ki.put(zap.NewExample(), 5, 0) + ki.put(zaptest.NewLogger(t), 5, 0) wki := &keyIndex{ key: []byte("foo"), @@ -137,7 +138,7 @@ func TestKeyIndexPut(t *testing.T) { t.Errorf("ki = %+v, want %+v", ki, wki) } - ki.put(zap.NewExample(), 7, 0) + ki.put(zaptest.NewLogger(t), 7, 0) wki = &keyIndex{ key: []byte("foo"), @@ -151,7 +152,7 @@ func TestKeyIndexPut(t *testing.T) { func TestKeyIndexRestore(t *testing.T) { ki := &keyIndex{key: []byte("foo")} - ki.restore(zap.NewExample(), revision{5, 0}, revision{7, 0}, 2) + ki.restore(zaptest.NewLogger(t), revision{5, 0}, revision{7, 0}, 2) wki := &keyIndex{ key: []byte("foo"), @@ -165,9 +166,9 @@ func TestKeyIndexRestore(t *testing.T) { func TestKeyIndexTombstone(t *testing.T) { ki := &keyIndex{key: []byte("foo")} - ki.put(zap.NewExample(), 5, 0) + ki.put(zaptest.NewLogger(t), 5, 0) - err := ki.tombstone(zap.NewExample(), 7, 0) + err := ki.tombstone(zaptest.NewLogger(t), 7, 0) if err != nil { t.Errorf("unexpected tombstone error: %v", err) } @@ -181,9 +182,9 @@ func TestKeyIndexTombstone(t *testing.T) { t.Errorf("ki = %+v, want %+v", ki, wki) } - ki.put(zap.NewExample(), 8, 0) - ki.put(zap.NewExample(), 9, 0) - err = ki.tombstone(zap.NewExample(), 15, 0) + ki.put(zaptest.NewLogger(t), 8, 0) + ki.put(zaptest.NewLogger(t), 9, 0) + err = ki.tombstone(zaptest.NewLogger(t), 15, 0) if err != nil { t.Errorf("unexpected tombstone error: %v", err) } @@ -201,7 +202,7 @@ func TestKeyIndexTombstone(t *testing.T) { t.Errorf("ki = %+v, want %+v", ki, wki) } - err = ki.tombstone(zap.NewExample(), 16, 0) + err = ki.tombstone(zaptest.NewLogger(t), 16, 0) if err != ErrRevisionNotFound { t.Errorf("tombstone error = %v, want %v", err, ErrRevisionNotFound) } @@ -444,7 +445,7 @@ func TestKeyIndexCompactAndKeep(t *testing.T) { } // Continuous Compaction and finding Keep - ki := newTestKeyIndex() + ki := newTestKeyIndex(zaptest.NewLogger(t)) for i, tt := range tests { am := make(map[revision]struct{}) kiclone := cloneKeyIndex(ki) @@ -456,7 +457,7 @@ func TestKeyIndexCompactAndKeep(t *testing.T) { t.Errorf("#%d: am = %+v, want %+v", i, am, tt.wam) } am = make(map[revision]struct{}) - ki.compact(zap.NewExample(), tt.compact, am) + ki.compact(zaptest.NewLogger(t), tt.compact, am) if !reflect.DeepEqual(ki, tt.wki) { t.Errorf("#%d: ki = %+v, want %+v", i, ki, tt.wki) } @@ -466,7 +467,7 @@ func TestKeyIndexCompactAndKeep(t *testing.T) { } // Jump Compaction and finding Keep - ki = newTestKeyIndex() + ki = newTestKeyIndex(zaptest.NewLogger(t)) for i, tt := range tests { if (i%2 == 0 && i < 6) || (i%2 == 1 && i > 6) { am := make(map[revision]struct{}) @@ -479,7 +480,7 @@ func TestKeyIndexCompactAndKeep(t *testing.T) { t.Errorf("#%d: am = %+v, want %+v", i, am, tt.wam) } am = make(map[revision]struct{}) - ki.compact(zap.NewExample(), tt.compact, am) + ki.compact(zaptest.NewLogger(t), tt.compact, am) if !reflect.DeepEqual(ki, tt.wki) { t.Errorf("#%d: ki = %+v, want %+v", i, ki, tt.wki) } @@ -489,10 +490,10 @@ func TestKeyIndexCompactAndKeep(t *testing.T) { } } - kiClone := newTestKeyIndex() + kiClone := newTestKeyIndex(zaptest.NewLogger(t)) // Once Compaction and finding Keep for i, tt := range tests { - ki := newTestKeyIndex() + ki := newTestKeyIndex(zaptest.NewLogger(t)) am := make(map[revision]struct{}) ki.keep(tt.compact, am) if !reflect.DeepEqual(ki, kiClone) { @@ -502,7 +503,7 @@ func TestKeyIndexCompactAndKeep(t *testing.T) { t.Errorf("#%d: am = %+v, want %+v", i, am, tt.wam) } am = make(map[revision]struct{}) - ki.compact(zap.NewExample(), tt.compact, am) + ki.compact(zaptest.NewLogger(t), tt.compact, am) if !reflect.DeepEqual(ki, tt.wki) { t.Errorf("#%d: ki = %+v, want %+v", i, ki, tt.wki) } @@ -532,10 +533,10 @@ func cloneGeneration(g *generation) *generation { // test that compact on version that higher than last modified version works well func TestKeyIndexCompactOnFurtherRev(t *testing.T) { ki := &keyIndex{key: []byte("foo")} - ki.put(zap.NewExample(), 1, 0) - ki.put(zap.NewExample(), 2, 0) + ki.put(zaptest.NewLogger(t), 1, 0) + ki.put(zaptest.NewLogger(t), 2, 0) am := make(map[revision]struct{}) - ki.compact(zap.NewExample(), 3, am) + ki.compact(zaptest.NewLogger(t), 3, am) wki := &keyIndex{ key: []byte("foo"), @@ -587,7 +588,7 @@ func TestKeyIndexIsEmpty(t *testing.T) { } func TestKeyIndexFindGeneration(t *testing.T) { - ki := newTestKeyIndex() + ki := newTestKeyIndex(zaptest.NewLogger(t)) tests := []struct { rev int64 @@ -677,7 +678,7 @@ func TestGenerationWalk(t *testing.T) { } } -func newTestKeyIndex() *keyIndex { +func newTestKeyIndex(lg *zap.Logger) *keyIndex { // key: "foo" // rev: 16 // generations: @@ -687,14 +688,14 @@ func newTestKeyIndex() *keyIndex { // {{2, 0}[1], {4, 0}[2], {6, 0}(t)[3]} ki := &keyIndex{key: []byte("foo")} - ki.put(zap.NewExample(), 2, 0) - ki.put(zap.NewExample(), 4, 0) - ki.tombstone(zap.NewExample(), 6, 0) - ki.put(zap.NewExample(), 8, 0) - ki.put(zap.NewExample(), 10, 0) - ki.tombstone(zap.NewExample(), 12, 0) - ki.put(zap.NewExample(), 14, 0) - ki.put(zap.NewExample(), 14, 1) - ki.tombstone(zap.NewExample(), 16, 0) + ki.put(lg, 2, 0) + ki.put(lg, 4, 0) + ki.tombstone(lg, 6, 0) + ki.put(lg, 8, 0) + ki.put(lg, 10, 0) + ki.tombstone(lg, 12, 0) + ki.put(lg, 14, 0) + ki.put(lg, 14, 1) + ki.tombstone(lg, 16, 0) return ki } diff --git a/server/storage/mvcc/kv_test.go b/server/storage/mvcc/kv_test.go index a4e13d693937..80fb8064cdf8 100644 --- a/server/storage/mvcc/kv_test.go +++ b/server/storage/mvcc/kv_test.go @@ -28,10 +28,10 @@ import ( "go.etcd.io/etcd/server/v3/lease" "go.etcd.io/etcd/server/v3/storage/backend" betesting "go.etcd.io/etcd/server/v3/storage/backend/testing" + "go.uber.org/zap/zaptest" "github.com/prometheus/client_golang/prometheus" dto "github.com/prometheus/client_model/go" - "go.uber.org/zap" ) // Functional tests for features implemented in v3 store. It treats v3 store @@ -79,7 +79,7 @@ func TestKVTxnRange(t *testing.T) { testKVRange(t, txnRangeFunc) } func testKVRange(t *testing.T, f rangeFunc) { b, tmpPath := betesting.NewDefaultTmpBackend(t) - s := NewStore(zap.NewExample(), b, &lease.FakeLessor{}, StoreConfig{}) + s := NewStore(zaptest.NewLogger(t), b, &lease.FakeLessor{}, StoreConfig{}) defer cleanup(s, b, tmpPath) kvs := put3TestKVs(s) @@ -145,7 +145,7 @@ func TestKVTxnRangeRev(t *testing.T) { testKVRangeRev(t, txnRangeFunc) } func testKVRangeRev(t *testing.T, f rangeFunc) { b, tmpPath := betesting.NewDefaultTmpBackend(t) - s := NewStore(zap.NewExample(), b, &lease.FakeLessor{}, StoreConfig{}) + s := NewStore(zaptest.NewLogger(t), b, &lease.FakeLessor{}, StoreConfig{}) defer cleanup(s, b, tmpPath) kvs := put3TestKVs(s) @@ -181,7 +181,7 @@ func TestKVTxnRangeBadRev(t *testing.T) { testKVRangeBadRev(t, txnRangeFunc) } func testKVRangeBadRev(t *testing.T, f rangeFunc) { b, tmpPath := betesting.NewDefaultTmpBackend(t) - s := NewStore(zap.NewExample(), b, &lease.FakeLessor{}, StoreConfig{}) + s := NewStore(zaptest.NewLogger(t), b, &lease.FakeLessor{}, StoreConfig{}) defer cleanup(s, b, tmpPath) put3TestKVs(s) @@ -214,7 +214,7 @@ func TestKVTxnRangeLimit(t *testing.T) { testKVRangeLimit(t, txnRangeFunc) } func testKVRangeLimit(t *testing.T, f rangeFunc) { b, tmpPath := betesting.NewDefaultTmpBackend(t) - s := NewStore(zap.NewExample(), b, &lease.FakeLessor{}, StoreConfig{}) + s := NewStore(zaptest.NewLogger(t), b, &lease.FakeLessor{}, StoreConfig{}) defer cleanup(s, b, tmpPath) kvs := put3TestKVs(s) @@ -260,7 +260,7 @@ func TestKVTxnPutMultipleTimes(t *testing.T) { testKVPutMultipleTimes(t, txnPutF func testKVPutMultipleTimes(t *testing.T, f putFunc) { b, tmpPath := betesting.NewDefaultTmpBackend(t) - s := NewStore(zap.NewExample(), b, &lease.FakeLessor{}, StoreConfig{}) + s := NewStore(zaptest.NewLogger(t), b, &lease.FakeLessor{}, StoreConfig{}) defer cleanup(s, b, tmpPath) for i := 0; i < 10; i++ { @@ -322,7 +322,7 @@ func testKVDeleteRange(t *testing.T, f deleteRangeFunc) { for i, tt := range tests { b, tmpPath := betesting.NewDefaultTmpBackend(t) - s := NewStore(zap.NewExample(), b, &lease.FakeLessor{}, StoreConfig{}) + s := NewStore(zaptest.NewLogger(t), b, &lease.FakeLessor{}, StoreConfig{}) s.Put([]byte("foo"), []byte("bar"), lease.NoLease) s.Put([]byte("foo1"), []byte("bar1"), lease.NoLease) @@ -342,7 +342,7 @@ func TestKVTxnDeleteMultipleTimes(t *testing.T) { testKVDeleteMultipleTimes(t, t func testKVDeleteMultipleTimes(t *testing.T, f deleteRangeFunc) { b, tmpPath := betesting.NewDefaultTmpBackend(t) - s := NewStore(zap.NewExample(), b, &lease.FakeLessor{}, StoreConfig{}) + s := NewStore(zaptest.NewLogger(t), b, &lease.FakeLessor{}, StoreConfig{}) defer cleanup(s, b, tmpPath) s.Put([]byte("foo"), []byte("bar"), lease.NoLease) @@ -365,7 +365,7 @@ func TestKVTxnPutWithSameLease(t *testing.T) { testKVPutWithSameLease(t, txnPutF func testKVPutWithSameLease(t *testing.T, f putFunc) { b, tmpPath := betesting.NewDefaultTmpBackend(t) - s := NewStore(zap.NewExample(), b, &lease.FakeLessor{}, StoreConfig{}) + s := NewStore(zaptest.NewLogger(t), b, &lease.FakeLessor{}, StoreConfig{}) defer cleanup(s, b, tmpPath) leaseID := int64(1) @@ -397,7 +397,7 @@ func testKVPutWithSameLease(t *testing.T, f putFunc) { // test that range, put, delete on single key in sequence repeatedly works correctly. func TestKVOperationInSequence(t *testing.T) { b, tmpPath := betesting.NewDefaultTmpBackend(t) - s := NewStore(zap.NewExample(), b, &lease.FakeLessor{}, StoreConfig{}) + s := NewStore(zaptest.NewLogger(t), b, &lease.FakeLessor{}, StoreConfig{}) defer cleanup(s, b, tmpPath) for i := 0; i < 10; i++ { @@ -444,7 +444,7 @@ func TestKVOperationInSequence(t *testing.T) { func TestKVTxnBlockWriteOperations(t *testing.T) { b, tmpPath := betesting.NewDefaultTmpBackend(t) - s := NewStore(zap.NewExample(), b, &lease.FakeLessor{}, StoreConfig{}) + s := NewStore(zaptest.NewLogger(t), b, &lease.FakeLessor{}, StoreConfig{}) tests := []func(){ func() { s.Put([]byte("foo"), nil, lease.NoLease) }, @@ -478,7 +478,7 @@ func TestKVTxnBlockWriteOperations(t *testing.T) { func TestKVTxnNonBlockRange(t *testing.T) { b, tmpPath := betesting.NewDefaultTmpBackend(t) - s := NewStore(zap.NewExample(), b, &lease.FakeLessor{}, StoreConfig{}) + s := NewStore(zaptest.NewLogger(t), b, &lease.FakeLessor{}, StoreConfig{}) defer cleanup(s, b, tmpPath) txn := s.Write(traceutil.TODO()) @@ -499,7 +499,7 @@ func TestKVTxnNonBlockRange(t *testing.T) { // test that txn range, put, delete on single key in sequence repeatedly works correctly. func TestKVTxnOperationInSequence(t *testing.T) { b, tmpPath := betesting.NewDefaultTmpBackend(t) - s := NewStore(zap.NewExample(), b, &lease.FakeLessor{}, StoreConfig{}) + s := NewStore(zaptest.NewLogger(t), b, &lease.FakeLessor{}, StoreConfig{}) defer cleanup(s, b, tmpPath) for i := 0; i < 10; i++ { @@ -549,7 +549,7 @@ func TestKVTxnOperationInSequence(t *testing.T) { func TestKVCompactReserveLastValue(t *testing.T) { b, tmpPath := betesting.NewDefaultTmpBackend(t) - s := NewStore(zap.NewExample(), b, &lease.FakeLessor{}, StoreConfig{}) + s := NewStore(zaptest.NewLogger(t), b, &lease.FakeLessor{}, StoreConfig{}) defer cleanup(s, b, tmpPath) s.Put([]byte("foo"), []byte("bar0"), 1) @@ -603,7 +603,7 @@ func TestKVCompactReserveLastValue(t *testing.T) { func TestKVCompactBad(t *testing.T) { b, tmpPath := betesting.NewDefaultTmpBackend(t) - s := NewStore(zap.NewExample(), b, &lease.FakeLessor{}, StoreConfig{}) + s := NewStore(zaptest.NewLogger(t), b, &lease.FakeLessor{}, StoreConfig{}) defer cleanup(s, b, tmpPath) s.Put([]byte("foo"), []byte("bar0"), lease.NoLease) @@ -636,7 +636,7 @@ func TestKVHash(t *testing.T) { for i := 0; i < len(hashes); i++ { var err error b, tmpPath := betesting.NewDefaultTmpBackend(t) - kv := NewStore(zap.NewExample(), b, &lease.FakeLessor{}, StoreConfig{}) + kv := NewStore(zaptest.NewLogger(t), b, &lease.FakeLessor{}, StoreConfig{}) kv.Put([]byte("foo0"), []byte("bar0"), lease.NoLease) kv.Put([]byte("foo1"), []byte("bar0"), lease.NoLease) hashes[i], _, err = kv.Hash() @@ -674,7 +674,7 @@ func TestKVRestore(t *testing.T) { } for i, tt := range tests { b, tmpPath := betesting.NewDefaultTmpBackend(t) - s := NewStore(zap.NewExample(), b, &lease.FakeLessor{}, StoreConfig{}) + s := NewStore(zaptest.NewLogger(t), b, &lease.FakeLessor{}, StoreConfig{}) tt(s) var kvss [][]mvccpb.KeyValue for k := int64(0); k < 10; k++ { @@ -686,7 +686,7 @@ func TestKVRestore(t *testing.T) { s.Close() // ns should recover the the previous state from backend. - ns := NewStore(zap.NewExample(), b, &lease.FakeLessor{}, StoreConfig{}) + ns := NewStore(zaptest.NewLogger(t), b, &lease.FakeLessor{}, StoreConfig{}) if keysRestore := readGaugeInt(keysGauge); keysBefore != keysRestore { t.Errorf("#%d: got %d key count, expected %d", i, keysRestore, keysBefore) @@ -718,7 +718,7 @@ func readGaugeInt(g prometheus.Gauge) int { func TestKVSnapshot(t *testing.T) { b, tmpPath := betesting.NewDefaultTmpBackend(t) - s := NewStore(zap.NewExample(), b, &lease.FakeLessor{}, StoreConfig{}) + s := NewStore(zaptest.NewLogger(t), b, &lease.FakeLessor{}, StoreConfig{}) defer cleanup(s, b, tmpPath) wkvs := put3TestKVs(s) @@ -738,7 +738,7 @@ func TestKVSnapshot(t *testing.T) { } f.Close() - ns := NewStore(zap.NewExample(), b, &lease.FakeLessor{}, StoreConfig{}) + ns := NewStore(zaptest.NewLogger(t), b, &lease.FakeLessor{}, StoreConfig{}) defer ns.Close() r, err := ns.Range(context.TODO(), []byte("a"), []byte("z"), RangeOptions{}) if err != nil { @@ -754,7 +754,7 @@ func TestKVSnapshot(t *testing.T) { func TestWatchableKVWatch(t *testing.T) { b, tmpPath := betesting.NewDefaultTmpBackend(t) - s := WatchableKV(newWatchableStore(zap.NewExample(), b, &lease.FakeLessor{}, StoreConfig{})) + s := WatchableKV(newWatchableStore(zaptest.NewLogger(t), b, &lease.FakeLessor{}, StoreConfig{})) defer cleanup(s, b, tmpPath) w := s.NewWatchStream() diff --git a/server/storage/mvcc/kvstore_bench_test.go b/server/storage/mvcc/kvstore_bench_test.go index 8f4ff6ce963b..e8b74fdc116d 100644 --- a/server/storage/mvcc/kvstore_bench_test.go +++ b/server/storage/mvcc/kvstore_bench_test.go @@ -24,13 +24,12 @@ import ( "go.etcd.io/etcd/server/v3/lease" betesting "go.etcd.io/etcd/server/v3/storage/backend/testing" "go.etcd.io/etcd/server/v3/storage/schema" - - "go.uber.org/zap" + "go.uber.org/zap/zaptest" ) func BenchmarkStorePut(b *testing.B) { be, tmpPath := betesting.NewDefaultTmpBackend(b) - s := NewStore(zap.NewExample(), be, &lease.FakeLessor{}, StoreConfig{}) + s := NewStore(zaptest.NewLogger(b), be, &lease.FakeLessor{}, StoreConfig{}) defer cleanup(s, be, tmpPath) // arbitrary number of bytes @@ -49,7 +48,7 @@ func BenchmarkStoreRangeKey100(b *testing.B) { benchmarkStoreRange(b, 100) } func benchmarkStoreRange(b *testing.B, n int) { be, tmpPath := betesting.NewDefaultTmpBackend(b) - s := NewStore(zap.NewExample(), be, &lease.FakeLessor{}, StoreConfig{}) + s := NewStore(zaptest.NewLogger(b), be, &lease.FakeLessor{}, StoreConfig{}) defer cleanup(s, be, tmpPath) // 64 byte key/val @@ -98,7 +97,7 @@ func BenchmarkConsistentIndex(b *testing.B) { // BenchmarkStoreTxnPutUpdate is same as above, but instead updates single key func BenchmarkStorePutUpdate(b *testing.B) { be, tmpPath := betesting.NewDefaultTmpBackend(b) - s := NewStore(zap.NewExample(), be, &lease.FakeLessor{}, StoreConfig{}) + s := NewStore(zaptest.NewLogger(b), be, &lease.FakeLessor{}, StoreConfig{}) defer cleanup(s, be, tmpPath) // arbitrary number of bytes @@ -116,7 +115,7 @@ func BenchmarkStorePutUpdate(b *testing.B) { // some synchronization operations, such as mutex locking. func BenchmarkStoreTxnPut(b *testing.B) { be, tmpPath := betesting.NewDefaultTmpBackend(b) - s := NewStore(zap.NewExample(), be, &lease.FakeLessor{}, StoreConfig{}) + s := NewStore(zaptest.NewLogger(b), be, &lease.FakeLessor{}, StoreConfig{}) defer cleanup(s, be, tmpPath) // arbitrary number of bytes @@ -136,7 +135,7 @@ func BenchmarkStoreTxnPut(b *testing.B) { // benchmarkStoreRestore benchmarks the restore operation func benchmarkStoreRestore(revsPerKey int, b *testing.B) { be, tmpPath := betesting.NewDefaultTmpBackend(b) - s := NewStore(zap.NewExample(), be, &lease.FakeLessor{}, StoreConfig{}) + s := NewStore(zaptest.NewLogger(b), be, &lease.FakeLessor{}, StoreConfig{}) // use closure to capture 's' to pick up the reassignment defer func() { cleanup(s, be, tmpPath) }() @@ -156,7 +155,7 @@ func benchmarkStoreRestore(revsPerKey int, b *testing.B) { b.ReportAllocs() b.ResetTimer() - s = NewStore(zap.NewExample(), be, &lease.FakeLessor{}, StoreConfig{}) + s = NewStore(zaptest.NewLogger(b), be, &lease.FakeLessor{}, StoreConfig{}) } func BenchmarkStoreRestoreRevs1(b *testing.B) { diff --git a/server/storage/mvcc/kvstore_compaction_test.go b/server/storage/mvcc/kvstore_compaction_test.go index ccf6df9b9b1e..27b44a0a8dcf 100644 --- a/server/storage/mvcc/kvstore_compaction_test.go +++ b/server/storage/mvcc/kvstore_compaction_test.go @@ -25,7 +25,7 @@ import ( "go.etcd.io/etcd/server/v3/lease" betesting "go.etcd.io/etcd/server/v3/storage/backend/testing" "go.etcd.io/etcd/server/v3/storage/schema" - "go.uber.org/zap" + "go.uber.org/zap/zaptest" ) func TestScheduleCompaction(t *testing.T) { @@ -68,7 +68,7 @@ func TestScheduleCompaction(t *testing.T) { } for i, tt := range tests { b, tmpPath := betesting.NewDefaultTmpBackend(t) - s := NewStore(zap.NewExample(), b, &lease.FakeLessor{}, StoreConfig{}) + s := NewStore(zaptest.NewLogger(t), b, &lease.FakeLessor{}, StoreConfig{}) tx := s.b.BatchTx() tx.Lock() @@ -101,7 +101,7 @@ func TestScheduleCompaction(t *testing.T) { func TestCompactAllAndRestore(t *testing.T) { b, tmpPath := betesting.NewDefaultTmpBackend(t) - s0 := NewStore(zap.NewExample(), b, &lease.FakeLessor{}, StoreConfig{}) + s0 := NewStore(zaptest.NewLogger(t), b, &lease.FakeLessor{}, StoreConfig{}) defer os.Remove(tmpPath) s0.Put([]byte("foo"), []byte("bar"), lease.NoLease) @@ -127,7 +127,7 @@ func TestCompactAllAndRestore(t *testing.T) { t.Fatal(err) } - s1 := NewStore(zap.NewExample(), b, &lease.FakeLessor{}, StoreConfig{}) + s1 := NewStore(zaptest.NewLogger(t), b, &lease.FakeLessor{}, StoreConfig{}) if s1.Rev() != rev { t.Errorf("rev = %v, want %v", s1.Rev(), rev) } diff --git a/server/storage/mvcc/kvstore_test.go b/server/storage/mvcc/kvstore_test.go index c200c0d9273e..4f0dbce79682 100644 --- a/server/storage/mvcc/kvstore_test.go +++ b/server/storage/mvcc/kvstore_test.go @@ -38,13 +38,14 @@ import ( "go.etcd.io/etcd/server/v3/storage/backend" betesting "go.etcd.io/etcd/server/v3/storage/backend/testing" "go.etcd.io/etcd/server/v3/storage/schema" + "go.uber.org/zap/zaptest" "go.uber.org/zap" ) func TestStoreRev(t *testing.T) { b, _ := betesting.NewDefaultTmpBackend(t) - s := NewStore(zap.NewExample(), b, &lease.FakeLessor{}, StoreConfig{}) + s := NewStore(zaptest.NewLogger(t), b, &lease.FakeLessor{}, StoreConfig{}) defer s.Close() for i := 1; i <= 3; i++ { @@ -56,6 +57,7 @@ func TestStoreRev(t *testing.T) { } func TestStorePut(t *testing.T) { + lg := zaptest.NewLogger(t) kv := mvccpb.KeyValue{ Key: []byte("foo"), Value: []byte("bar"), @@ -84,7 +86,7 @@ func TestStorePut(t *testing.T) { nil, revision{2, 0}, - newTestKeyBytes(revision{2, 0}, false), + newTestKeyBytes(lg, revision{2, 0}, false), mvccpb.KeyValue{ Key: []byte("foo"), Value: []byte("bar"), @@ -98,10 +100,10 @@ func TestStorePut(t *testing.T) { { revision{1, 1}, indexGetResp{revision{2, 0}, revision{2, 0}, 1, nil}, - &rangeResp{[][]byte{newTestKeyBytes(revision{2, 1}, false)}, [][]byte{kvb}}, + &rangeResp{[][]byte{newTestKeyBytes(lg, revision{2, 1}, false)}, [][]byte{kvb}}, revision{2, 0}, - newTestKeyBytes(revision{2, 0}, false), + newTestKeyBytes(lg, revision{2, 0}, false), mvccpb.KeyValue{ Key: []byte("foo"), Value: []byte("bar"), @@ -115,10 +117,10 @@ func TestStorePut(t *testing.T) { { revision{2, 0}, indexGetResp{revision{2, 1}, revision{2, 0}, 2, nil}, - &rangeResp{[][]byte{newTestKeyBytes(revision{2, 1}, false)}, [][]byte{kvb}}, + &rangeResp{[][]byte{newTestKeyBytes(lg, revision{2, 1}, false)}, [][]byte{kvb}}, revision{3, 0}, - newTestKeyBytes(revision{3, 0}, false), + newTestKeyBytes(lg, revision{3, 0}, false), mvccpb.KeyValue{ Key: []byte("foo"), Value: []byte("bar"), @@ -131,7 +133,7 @@ func TestStorePut(t *testing.T) { }, } for i, tt := range tests { - s := newFakeStore() + s := newFakeStore(lg) b := s.b.(*fakeBackend) fi := s.kvindex.(*fakeIndex) @@ -177,7 +179,8 @@ func TestStorePut(t *testing.T) { } func TestStoreRange(t *testing.T) { - key := newTestKeyBytes(revision{2, 0}, false) + lg := zaptest.NewLogger(t) + key := newTestKeyBytes(lg, revision{2, 0}, false) kv := mvccpb.KeyValue{ Key: []byte("foo"), Value: []byte("bar"), @@ -207,7 +210,7 @@ func TestStoreRange(t *testing.T) { ro := RangeOptions{Limit: 1, Rev: 0, Count: false} for i, tt := range tests { - s := newFakeStore() + s := newFakeStore(lg) b := s.b.(*fakeBackend) fi := s.kvindex.(*fakeIndex) @@ -249,7 +252,8 @@ func TestStoreRange(t *testing.T) { } func TestStoreDeleteRange(t *testing.T) { - key := newTestKeyBytes(revision{2, 0}, false) + lg := zaptest.NewLogger(t) + key := newTestKeyBytes(lg, revision{2, 0}, false) kv := mvccpb.KeyValue{ Key: []byte("foo"), Value: []byte("bar"), @@ -277,14 +281,14 @@ func TestStoreDeleteRange(t *testing.T) { indexRangeResp{[][]byte{[]byte("foo")}, []revision{{2, 0}}}, rangeResp{[][]byte{key}, [][]byte{kvb}}, - newTestKeyBytes(revision{3, 0}, true), + newTestKeyBytes(lg, revision{3, 0}, true), revision{3, 0}, 2, revision{3, 0}, }, } for i, tt := range tests { - s := newFakeStore() + s := newFakeStore(lg) b := s.b.(*fakeBackend) fi := s.kvindex.(*fakeIndex) @@ -323,15 +327,16 @@ func TestStoreDeleteRange(t *testing.T) { } func TestStoreCompact(t *testing.T) { - s := newFakeStore() + lg := zaptest.NewLogger(t) + s := newFakeStore(lg) defer s.Close() b := s.b.(*fakeBackend) fi := s.kvindex.(*fakeIndex) s.currentRev = 3 fi.indexCompactRespc <- map[revision]struct{}{{1, 0}: {}} - key1 := newTestKeyBytes(revision{1, 0}, false) - key2 := newTestKeyBytes(revision{2, 0}, false) + key1 := newTestKeyBytes(lg, revision{1, 0}, false) + key2 := newTestKeyBytes(lg, revision{2, 0}, false) b.tx.rangeRespc <- rangeResp{[][]byte{key1, key2}, nil} s.Compact(traceutil.TODO(), 3) @@ -360,11 +365,12 @@ func TestStoreCompact(t *testing.T) { } func TestStoreRestore(t *testing.T) { - s := newFakeStore() + lg := zaptest.NewLogger(t) + s := newFakeStore(lg) b := s.b.(*fakeBackend) fi := s.kvindex.(*fakeIndex) - putkey := newTestKeyBytes(revision{3, 0}, false) + putkey := newTestKeyBytes(lg, revision{3, 0}, false) putkv := mvccpb.KeyValue{ Key: []byte("foo"), Value: []byte("bar"), @@ -376,7 +382,7 @@ func TestStoreRestore(t *testing.T) { if err != nil { t.Fatal(err) } - delkey := newTestKeyBytes(revision{5, 0}, true) + delkey := newTestKeyBytes(lg, revision{5, 0}, true) delkv := mvccpb.KeyValue{ Key: []byte("foo"), } @@ -427,7 +433,7 @@ func TestRestoreDelete(t *testing.T) { defer func() { restoreChunkKeys = oldChunk }() b, _ := betesting.NewDefaultTmpBackend(t) - s := NewStore(zap.NewExample(), b, &lease.FakeLessor{}, StoreConfig{}) + s := NewStore(zaptest.NewLogger(t), b, &lease.FakeLessor{}, StoreConfig{}) keys := make(map[string]struct{}) for i := 0; i < 20; i++ { @@ -452,7 +458,7 @@ func TestRestoreDelete(t *testing.T) { } s.Close() - s = NewStore(zap.NewExample(), b, &lease.FakeLessor{}, StoreConfig{}) + s = NewStore(zaptest.NewLogger(t), b, &lease.FakeLessor{}, StoreConfig{}) defer s.Close() for i := 0; i < 20; i++ { ks := fmt.Sprintf("foo-%d", i) @@ -474,7 +480,7 @@ func TestRestoreContinueUnfinishedCompaction(t *testing.T) { tests := []string{"recreate", "restore"} for _, test := range tests { b, _ := betesting.NewDefaultTmpBackend(t) - s0 := NewStore(zap.NewExample(), b, &lease.FakeLessor{}, StoreConfig{}) + s0 := NewStore(zaptest.NewLogger(t), b, &lease.FakeLessor{}, StoreConfig{}) s0.Put([]byte("foo"), []byte("bar"), lease.NoLease) s0.Put([]byte("foo"), []byte("bar1"), lease.NoLease) @@ -493,7 +499,7 @@ func TestRestoreContinueUnfinishedCompaction(t *testing.T) { var s *store switch test { case "recreate": - s = NewStore(zap.NewExample(), b, &lease.FakeLessor{}, StoreConfig{}) + s = NewStore(zaptest.NewLogger(t), b, &lease.FakeLessor{}, StoreConfig{}) case "restore": s0.Restore(b) s = s0 @@ -535,7 +541,7 @@ type hashKVResult struct { // TestHashKVWhenCompacting ensures that HashKV returns correct hash when compacting. func TestHashKVWhenCompacting(t *testing.T) { b, tmpPath := betesting.NewDefaultTmpBackend(t) - s := NewStore(zap.NewExample(), b, &lease.FakeLessor{}, StoreConfig{}) + s := NewStore(zaptest.NewLogger(t), b, &lease.FakeLessor{}, StoreConfig{}) defer s.Close() defer b.Close() defer os.Remove(tmpPath) @@ -605,7 +611,7 @@ func TestHashKVWhenCompacting(t *testing.T) { // correct hash value with latest revision. func TestHashKVZeroRevision(t *testing.T) { b, tmpPath := betesting.NewDefaultTmpBackend(t) - s := NewStore(zap.NewExample(), b, &lease.FakeLessor{}, StoreConfig{}) + s := NewStore(zaptest.NewLogger(t), b, &lease.FakeLessor{}, StoreConfig{}) defer os.Remove(tmpPath) rev := 10000 @@ -638,7 +644,7 @@ func TestTxnPut(t *testing.T) { vals := createBytesSlice(bytesN, sliceN) b, tmpPath := betesting.NewDefaultTmpBackend(t) - s := NewStore(zap.NewExample(), b, &lease.FakeLessor{}, StoreConfig{}) + s := NewStore(zaptest.NewLogger(t), b, &lease.FakeLessor{}, StoreConfig{}) defer cleanup(s, b, tmpPath) for i := 0; i < sliceN; i++ { @@ -654,7 +660,7 @@ func TestTxnPut(t *testing.T) { // TestConcurrentReadNotBlockingWrite ensures Read does not blocking Write after its creation func TestConcurrentReadNotBlockingWrite(t *testing.T) { b, tmpPath := betesting.NewDefaultTmpBackend(t) - s := NewStore(zap.NewExample(), b, &lease.FakeLessor{}, StoreConfig{}) + s := NewStore(zaptest.NewLogger(t), b, &lease.FakeLessor{}, StoreConfig{}) defer os.Remove(tmpPath) // write something to read later @@ -723,7 +729,7 @@ func TestConcurrentReadTxAndWrite(t *testing.T) { mu sync.Mutex // mu protects committedKVs ) b, tmpPath := betesting.NewDefaultTmpBackend(t) - s := NewStore(zap.NewExample(), b, &lease.FakeLessor{}, StoreConfig{}) + s := NewStore(zaptest.NewLogger(t), b, &lease.FakeLessor{}, StoreConfig{}) defer b.Close() defer s.Close() defer os.Remove(tmpPath) @@ -830,16 +836,16 @@ func newTestRevBytes(rev revision) []byte { return bytes } -func newTestKeyBytes(rev revision, tombstone bool) []byte { +func newTestKeyBytes(lg *zap.Logger, rev revision, tombstone bool) []byte { bytes := newRevBytes() revToBytes(rev, bytes) if tombstone { - bytes = appendMarkTombstone(zap.NewExample(), bytes) + bytes = appendMarkTombstone(lg, bytes) } return bytes } -func newFakeStore() *store { +func newFakeStore(lg *zap.Logger) *store { b := &fakeBackend{&fakeBatchTx{ Recorder: &testutil.RecorderBuffered{}, rangeRespc: make(chan rangeResp, 5)}} @@ -859,7 +865,7 @@ func newFakeStore() *store { compactMainRev: -1, fifoSched: schedule.NewFIFOScheduler(), stopc: make(chan struct{}), - lg: zap.NewExample(), + lg: lg, } s.ReadView, s.WriteView = &readView{s}, &writeView{s} return s diff --git a/server/storage/mvcc/watchable_store_bench_test.go b/server/storage/mvcc/watchable_store_bench_test.go index 20eb132ac519..2ada187e4bd2 100644 --- a/server/storage/mvcc/watchable_store_bench_test.go +++ b/server/storage/mvcc/watchable_store_bench_test.go @@ -22,13 +22,12 @@ import ( "go.etcd.io/etcd/pkg/v3/traceutil" "go.etcd.io/etcd/server/v3/lease" betesting "go.etcd.io/etcd/server/v3/storage/backend/testing" - - "go.uber.org/zap" + "go.uber.org/zap/zaptest" ) func BenchmarkWatchableStorePut(b *testing.B) { be, tmpPath := betesting.NewDefaultTmpBackend(b) - s := New(zap.NewExample(), be, &lease.FakeLessor{}, StoreConfig{}) + s := New(zaptest.NewLogger(b), be, &lease.FakeLessor{}, StoreConfig{}) defer cleanup(s, be, tmpPath) // arbitrary number of bytes @@ -48,7 +47,7 @@ func BenchmarkWatchableStorePut(b *testing.B) { // some synchronization operations, such as mutex locking. func BenchmarkWatchableStoreTxnPut(b *testing.B) { be, tmpPath := betesting.NewDefaultTmpBackend(b) - s := New(zap.NewExample(), be, &lease.FakeLessor{}, StoreConfig{}) + s := New(zaptest.NewLogger(b), be, &lease.FakeLessor{}, StoreConfig{}) defer cleanup(s, be, tmpPath) // arbitrary number of bytes @@ -79,7 +78,7 @@ func BenchmarkWatchableStoreWatchPutUnsync(b *testing.B) { func benchmarkWatchableStoreWatchPut(b *testing.B, synced bool) { be, tmpPath := betesting.NewDefaultTmpBackend(b) - s := newWatchableStore(zap.NewExample(), be, &lease.FakeLessor{}, StoreConfig{}) + s := newWatchableStore(zaptest.NewLogger(b), be, &lease.FakeLessor{}, StoreConfig{}) defer cleanup(s, be, tmpPath) k := []byte("testkey") @@ -122,7 +121,7 @@ func benchmarkWatchableStoreWatchPut(b *testing.B, synced bool) { // we should put to simulate the real-world use cases. func BenchmarkWatchableStoreUnsyncedCancel(b *testing.B) { be, tmpPath := betesting.NewDefaultTmpBackend(b) - s := NewStore(zap.NewExample(), be, &lease.FakeLessor{}, StoreConfig{}) + s := NewStore(zaptest.NewLogger(b), be, &lease.FakeLessor{}, StoreConfig{}) // manually create watchableStore instead of newWatchableStore // because newWatchableStore periodically calls syncWatchersLoop @@ -179,7 +178,7 @@ func BenchmarkWatchableStoreUnsyncedCancel(b *testing.B) { func BenchmarkWatchableStoreSyncedCancel(b *testing.B) { be, tmpPath := betesting.NewDefaultTmpBackend(b) - s := newWatchableStore(zap.NewExample(), be, &lease.FakeLessor{}, StoreConfig{}) + s := newWatchableStore(zaptest.NewLogger(b), be, &lease.FakeLessor{}, StoreConfig{}) defer func() { s.store.Close() diff --git a/server/storage/mvcc/watchable_store_test.go b/server/storage/mvcc/watchable_store_test.go index f3167270ce19..45b54818daa3 100644 --- a/server/storage/mvcc/watchable_store_test.go +++ b/server/storage/mvcc/watchable_store_test.go @@ -27,12 +27,12 @@ import ( "go.etcd.io/etcd/pkg/v3/traceutil" "go.etcd.io/etcd/server/v3/lease" betesting "go.etcd.io/etcd/server/v3/storage/backend/testing" - "go.uber.org/zap" + "go.uber.org/zap/zaptest" ) func TestWatch(t *testing.T) { b, tmpPath := betesting.NewDefaultTmpBackend(t) - s := newWatchableStore(zap.NewExample(), b, &lease.FakeLessor{}, StoreConfig{}) + s := newWatchableStore(zaptest.NewLogger(t), b, &lease.FakeLessor{}, StoreConfig{}) defer func() { b.Close() @@ -55,7 +55,7 @@ func TestWatch(t *testing.T) { func TestNewWatcherCancel(t *testing.T) { b, tmpPath := betesting.NewDefaultTmpBackend(t) - s := newWatchableStore(zap.NewExample(), b, &lease.FakeLessor{}, StoreConfig{}) + s := newWatchableStore(zaptest.NewLogger(t), b, &lease.FakeLessor{}, StoreConfig{}) defer func() { s.store.Close() @@ -87,7 +87,7 @@ func TestCancelUnsynced(t *testing.T) { // method to sync watchers in unsynced map. We want to keep watchers // in unsynced to test if syncWatchers works as expected. s := &watchableStore{ - store: NewStore(zap.NewExample(), b, &lease.FakeLessor{}, StoreConfig{}), + store: NewStore(zaptest.NewLogger(t), b, &lease.FakeLessor{}, StoreConfig{}), unsynced: newWatcherGroup(), // to make the test not crash from assigning to nil map. @@ -142,7 +142,7 @@ func TestSyncWatchers(t *testing.T) { b, tmpPath := betesting.NewDefaultTmpBackend(t) s := &watchableStore{ - store: NewStore(zap.NewExample(), b, &lease.FakeLessor{}, StoreConfig{}), + store: NewStore(zaptest.NewLogger(t), b, &lease.FakeLessor{}, StoreConfig{}), unsynced: newWatcherGroup(), synced: newWatcherGroup(), } @@ -225,7 +225,7 @@ func TestSyncWatchers(t *testing.T) { // TestWatchCompacted tests a watcher that watches on a compacted revision. func TestWatchCompacted(t *testing.T) { b, tmpPath := betesting.NewDefaultTmpBackend(t) - s := newWatchableStore(zap.NewExample(), b, &lease.FakeLessor{}, StoreConfig{}) + s := newWatchableStore(zaptest.NewLogger(t), b, &lease.FakeLessor{}, StoreConfig{}) defer func() { s.store.Close() @@ -262,7 +262,7 @@ func TestWatchCompacted(t *testing.T) { func TestWatchFutureRev(t *testing.T) { b, tmpPath := betesting.NewDefaultTmpBackend(t) - s := newWatchableStore(zap.NewExample(), b, &lease.FakeLessor{}, StoreConfig{}) + s := newWatchableStore(zaptest.NewLogger(t), b, &lease.FakeLessor{}, StoreConfig{}) defer func() { b.Close() @@ -304,7 +304,7 @@ func TestWatchRestore(t *testing.T) { test := func(delay time.Duration) func(t *testing.T) { return func(t *testing.T) { b, tmpPath := betesting.NewDefaultTmpBackend(t) - s := newWatchableStore(zap.NewExample(), b, &lease.FakeLessor{}, StoreConfig{}) + s := newWatchableStore(zaptest.NewLogger(t), b, &lease.FakeLessor{}, StoreConfig{}) defer cleanup(s, b, tmpPath) testKey := []byte("foo") @@ -312,7 +312,7 @@ func TestWatchRestore(t *testing.T) { rev := s.Put(testKey, testValue, lease.NoLease) newBackend, newPath := betesting.NewDefaultTmpBackend(t) - newStore := newWatchableStore(zap.NewExample(), newBackend, &lease.FakeLessor{}, StoreConfig{}) + newStore := newWatchableStore(zaptest.NewLogger(t), newBackend, &lease.FakeLessor{}, StoreConfig{}) defer cleanup(newStore, newBackend, newPath) w := newStore.NewWatchStream() @@ -350,11 +350,11 @@ func TestWatchRestore(t *testing.T) { // 5. choose the watcher from step 1, without panic func TestWatchRestoreSyncedWatcher(t *testing.T) { b1, b1Path := betesting.NewDefaultTmpBackend(t) - s1 := newWatchableStore(zap.NewExample(), b1, &lease.FakeLessor{}, StoreConfig{}) + s1 := newWatchableStore(zaptest.NewLogger(t), b1, &lease.FakeLessor{}, StoreConfig{}) defer cleanup(s1, b1, b1Path) b2, b2Path := betesting.NewDefaultTmpBackend(t) - s2 := newWatchableStore(zap.NewExample(), b2, &lease.FakeLessor{}, StoreConfig{}) + s2 := newWatchableStore(zaptest.NewLogger(t), b2, &lease.FakeLessor{}, StoreConfig{}) defer cleanup(s2, b2, b2Path) testKey, testValue := []byte("foo"), []byte("bar") @@ -401,7 +401,7 @@ func TestWatchRestoreSyncedWatcher(t *testing.T) { // TestWatchBatchUnsynced tests batching on unsynced watchers func TestWatchBatchUnsynced(t *testing.T) { b, tmpPath := betesting.NewDefaultTmpBackend(t) - s := newWatchableStore(zap.NewExample(), b, &lease.FakeLessor{}, StoreConfig{}) + s := newWatchableStore(zaptest.NewLogger(t), b, &lease.FakeLessor{}, StoreConfig{}) oldMaxRevs := watchBatchMaxRevs defer func() { @@ -535,7 +535,7 @@ func TestWatchVictims(t *testing.T) { oldChanBufLen, oldMaxWatchersPerSync := chanBufLen, maxWatchersPerSync b, tmpPath := betesting.NewDefaultTmpBackend(t) - s := newWatchableStore(zap.NewExample(), b, &lease.FakeLessor{}, StoreConfig{}) + s := newWatchableStore(zaptest.NewLogger(t), b, &lease.FakeLessor{}, StoreConfig{}) defer func() { b.Close() @@ -614,7 +614,7 @@ func TestWatchVictims(t *testing.T) { // canceling its watches. func TestStressWatchCancelClose(t *testing.T) { b, tmpPath := betesting.NewDefaultTmpBackend(t) - s := newWatchableStore(zap.NewExample(), b, &lease.FakeLessor{}, StoreConfig{}) + s := newWatchableStore(zaptest.NewLogger(t), b, &lease.FakeLessor{}, StoreConfig{}) defer func() { b.Close() diff --git a/server/storage/mvcc/watcher_bench_test.go b/server/storage/mvcc/watcher_bench_test.go index 049c0203b32a..5901ce55ea0b 100644 --- a/server/storage/mvcc/watcher_bench_test.go +++ b/server/storage/mvcc/watcher_bench_test.go @@ -20,13 +20,12 @@ import ( "go.etcd.io/etcd/server/v3/lease" betesting "go.etcd.io/etcd/server/v3/storage/backend/testing" - - "go.uber.org/zap" + "go.uber.org/zap/zaptest" ) func BenchmarkKVWatcherMemoryUsage(b *testing.B) { be, tmpPath := betesting.NewDefaultTmpBackend(b) - watchable := newWatchableStore(zap.NewExample(), be, &lease.FakeLessor{}, StoreConfig{}) + watchable := newWatchableStore(zaptest.NewLogger(b), be, &lease.FakeLessor{}, StoreConfig{}) defer cleanup(watchable, be, tmpPath) diff --git a/server/storage/mvcc/watcher_test.go b/server/storage/mvcc/watcher_test.go index ebf0181adc34..c0719d31fd20 100644 --- a/server/storage/mvcc/watcher_test.go +++ b/server/storage/mvcc/watcher_test.go @@ -25,14 +25,14 @@ import ( "go.etcd.io/etcd/api/v3/mvccpb" "go.etcd.io/etcd/server/v3/lease" betesting "go.etcd.io/etcd/server/v3/storage/backend/testing" - "go.uber.org/zap" + "go.uber.org/zap/zaptest" ) // TestWatcherWatchID tests that each watcher provides unique watchID, // and the watched event attaches the correct watchID. func TestWatcherWatchID(t *testing.T) { b, tmpPath := betesting.NewDefaultTmpBackend(t) - s := WatchableKV(newWatchableStore(zap.NewExample(), b, &lease.FakeLessor{}, StoreConfig{})) + s := WatchableKV(newWatchableStore(zaptest.NewLogger(t), b, &lease.FakeLessor{}, StoreConfig{})) defer cleanup(s, b, tmpPath) w := s.NewWatchStream() @@ -82,7 +82,7 @@ func TestWatcherWatchID(t *testing.T) { func TestWatcherRequestsCustomID(t *testing.T) { b, tmpPath := betesting.NewDefaultTmpBackend(t) - s := WatchableKV(newWatchableStore(zap.NewExample(), b, &lease.FakeLessor{}, StoreConfig{})) + s := WatchableKV(newWatchableStore(zaptest.NewLogger(t), b, &lease.FakeLessor{}, StoreConfig{})) defer cleanup(s, b, tmpPath) w := s.NewWatchStream() @@ -119,7 +119,7 @@ func TestWatcherRequestsCustomID(t *testing.T) { // and returns events with matching prefixes. func TestWatcherWatchPrefix(t *testing.T) { b, tmpPath := betesting.NewDefaultTmpBackend(t) - s := WatchableKV(newWatchableStore(zap.NewExample(), b, &lease.FakeLessor{}, StoreConfig{})) + s := WatchableKV(newWatchableStore(zaptest.NewLogger(t), b, &lease.FakeLessor{}, StoreConfig{})) defer cleanup(s, b, tmpPath) w := s.NewWatchStream() @@ -193,7 +193,7 @@ func TestWatcherWatchPrefix(t *testing.T) { // does not create watcher, which panics when canceling in range tree. func TestWatcherWatchWrongRange(t *testing.T) { b, tmpPath := betesting.NewDefaultTmpBackend(t) - s := WatchableKV(newWatchableStore(zap.NewExample(), b, &lease.FakeLessor{}, StoreConfig{})) + s := WatchableKV(newWatchableStore(zaptest.NewLogger(t), b, &lease.FakeLessor{}, StoreConfig{})) defer cleanup(s, b, tmpPath) w := s.NewWatchStream() @@ -213,7 +213,7 @@ func TestWatcherWatchWrongRange(t *testing.T) { func TestWatchDeleteRange(t *testing.T) { b, tmpPath := betesting.NewDefaultTmpBackend(t) - s := newWatchableStore(zap.NewExample(), b, &lease.FakeLessor{}, StoreConfig{}) + s := newWatchableStore(zaptest.NewLogger(t), b, &lease.FakeLessor{}, StoreConfig{}) defer func() { b.Close() @@ -253,7 +253,7 @@ func TestWatchDeleteRange(t *testing.T) { // with given id inside watchStream. func TestWatchStreamCancelWatcherByID(t *testing.T) { b, tmpPath := betesting.NewDefaultTmpBackend(t) - s := WatchableKV(newWatchableStore(zap.NewExample(), b, &lease.FakeLessor{}, StoreConfig{})) + s := WatchableKV(newWatchableStore(zaptest.NewLogger(t), b, &lease.FakeLessor{}, StoreConfig{})) defer cleanup(s, b, tmpPath) w := s.NewWatchStream() @@ -296,7 +296,7 @@ func TestWatcherRequestProgress(t *testing.T) { // method to sync watchers in unsynced map. We want to keep watchers // in unsynced to test if syncWatchers works as expected. s := &watchableStore{ - store: NewStore(zap.NewExample(), b, &lease.FakeLessor{}, StoreConfig{}), + store: NewStore(zaptest.NewLogger(t), b, &lease.FakeLessor{}, StoreConfig{}), unsynced: newWatcherGroup(), synced: newWatcherGroup(), } @@ -345,7 +345,7 @@ func TestWatcherRequestProgress(t *testing.T) { func TestWatcherWatchWithFilter(t *testing.T) { b, tmpPath := betesting.NewDefaultTmpBackend(t) - s := WatchableKV(newWatchableStore(zap.NewExample(), b, &lease.FakeLessor{}, StoreConfig{})) + s := WatchableKV(newWatchableStore(zaptest.NewLogger(t), b, &lease.FakeLessor{}, StoreConfig{})) defer cleanup(s, b, tmpPath) w := s.NewWatchStream() diff --git a/server/storage/wal/file_pipeline_test.go b/server/storage/wal/file_pipeline_test.go index 30ce5cc04acf..b79927146e0b 100644 --- a/server/storage/wal/file_pipeline_test.go +++ b/server/storage/wal/file_pipeline_test.go @@ -18,13 +18,13 @@ import ( "math" "testing" - "go.uber.org/zap" + "go.uber.org/zap/zaptest" ) func TestFilePipeline(t *testing.T) { tdir := t.TempDir() - fp := newFilePipeline(zap.NewExample(), tdir, SegmentSizeBytes) + fp := newFilePipeline(zaptest.NewLogger(t), tdir, SegmentSizeBytes) defer fp.Close() f, ferr := fp.Open() @@ -37,7 +37,7 @@ func TestFilePipeline(t *testing.T) { func TestFilePipelineFailPreallocate(t *testing.T) { tdir := t.TempDir() - fp := newFilePipeline(zap.NewExample(), tdir, math.MaxInt64) + fp := newFilePipeline(zaptest.NewLogger(t), tdir, math.MaxInt64) defer fp.Close() f, ferr := fp.Open() @@ -49,7 +49,7 @@ func TestFilePipelineFailPreallocate(t *testing.T) { func TestFilePipelineFailLockFile(t *testing.T) { tdir := t.TempDir() - fp := newFilePipeline(zap.NewExample(), tdir, math.MaxInt64) + fp := newFilePipeline(zaptest.NewLogger(t), tdir, math.MaxInt64) defer fp.Close() f, ferr := fp.Open() diff --git a/server/storage/wal/repair_test.go b/server/storage/wal/repair_test.go index e1c3e2a807d9..cf868a5056e3 100644 --- a/server/storage/wal/repair_test.go +++ b/server/storage/wal/repair_test.go @@ -22,8 +22,7 @@ import ( "go.etcd.io/etcd/raft/v3/raftpb" "go.etcd.io/etcd/server/v3/storage/wal/walpb" - - "go.uber.org/zap" + "go.uber.org/zap/zaptest" ) type corruptFunc func(string, int64) error @@ -31,7 +30,7 @@ type corruptFunc func(string, int64) error // TestRepairTruncate ensures a truncated file can be repaired func TestRepairTruncate(t *testing.T) { corruptf := func(p string, offset int64) error { - f, err := openLast(zap.NewExample(), p) + f, err := openLast(zaptest.NewLogger(t), p) if err != nil { return err } @@ -46,7 +45,7 @@ func testRepair(t *testing.T, ents [][]raftpb.Entry, corrupt corruptFunc, expect p := t.TempDir() // create WAL - w, err := Create(zap.NewExample(), p, nil) + w, err := Create(zaptest.NewLogger(t), p, nil) defer func() { if err = w.Close(); err != nil { t.Fatal(err) @@ -74,7 +73,7 @@ func testRepair(t *testing.T, ents [][]raftpb.Entry, corrupt corruptFunc, expect } // verify we broke the wal - w, err = Open(zap.NewExample(), p, walpb.Snapshot{}) + w, err = Open(zaptest.NewLogger(t), p, walpb.Snapshot{}) if err != nil { t.Fatal(err) } @@ -85,12 +84,12 @@ func testRepair(t *testing.T, ents [][]raftpb.Entry, corrupt corruptFunc, expect w.Close() // repair the wal - if ok := Repair(zap.NewExample(), p); !ok { + if ok := Repair(zaptest.NewLogger(t), p); !ok { t.Fatalf("'Repair' returned '%v', want 'true'", ok) } // read it back - w, err = Open(zap.NewExample(), p, walpb.Snapshot{}) + w, err = Open(zaptest.NewLogger(t), p, walpb.Snapshot{}) if err != nil { t.Fatal(err) } @@ -112,7 +111,7 @@ func testRepair(t *testing.T, ents [][]raftpb.Entry, corrupt corruptFunc, expect w.Close() // read back entries following repair, ensure it's all there - w, err = Open(zap.NewExample(), p, walpb.Snapshot{}) + w, err = Open(zaptest.NewLogger(t), p, walpb.Snapshot{}) if err != nil { t.Fatal(err) } @@ -136,7 +135,7 @@ func makeEnts(ents int) (ret [][]raftpb.Entry) { // that straddled two sectors. func TestRepairWriteTearLast(t *testing.T) { corruptf := func(p string, offset int64) error { - f, err := openLast(zap.NewExample(), p) + f, err := openLast(zaptest.NewLogger(t), p) if err != nil { return err } @@ -157,7 +156,7 @@ func TestRepairWriteTearLast(t *testing.T) { // in the middle of a record. func TestRepairWriteTearMiddle(t *testing.T) { corruptf := func(p string, offset int64) error { - f, err := openLast(zap.NewExample(), p) + f, err := openLast(zaptest.NewLogger(t), p) if err != nil { return err } @@ -181,7 +180,7 @@ func TestRepairWriteTearMiddle(t *testing.T) { func TestRepairFailDeleteDir(t *testing.T) { p := t.TempDir() - w, err := Create(zap.NewExample(), p, nil) + w, err := Create(zaptest.NewLogger(t), p, nil) if err != nil { t.Fatal(err) } @@ -203,7 +202,7 @@ func TestRepairFailDeleteDir(t *testing.T) { } w.Close() - f, err := openLast(zap.NewExample(), p) + f, err := openLast(zaptest.NewLogger(t), p) if err != nil { t.Fatal(err) } @@ -212,7 +211,7 @@ func TestRepairFailDeleteDir(t *testing.T) { } f.Close() - w, err = Open(zap.NewExample(), p, walpb.Snapshot{}) + w, err = Open(zaptest.NewLogger(t), p, walpb.Snapshot{}) if err != nil { t.Fatal(err) } @@ -223,7 +222,7 @@ func TestRepairFailDeleteDir(t *testing.T) { w.Close() os.RemoveAll(p) - if Repair(zap.NewExample(), p) { + if Repair(zaptest.NewLogger(t), p) { t.Fatal("expect 'Repair' fail on unexpected directory deletion") } } diff --git a/server/storage/wal/wal_bench_test.go b/server/storage/wal/wal_bench_test.go index ca7e98e1b406..14acf73b7922 100644 --- a/server/storage/wal/wal_bench_test.go +++ b/server/storage/wal/wal_bench_test.go @@ -17,9 +17,8 @@ package wal import ( "testing" - "go.uber.org/zap" - "go.etcd.io/etcd/raft/v3/raftpb" + "go.uber.org/zap/zaptest" ) func BenchmarkWrite100EntryWithoutBatch(b *testing.B) { benchmarkWriteEntry(b, 100, 0) } @@ -37,7 +36,7 @@ func BenchmarkWrite1000EntryBatch1000(b *testing.B) { benchmarkWriteEntry(b, func benchmarkWriteEntry(b *testing.B, size int, batch int) { p := b.TempDir() - w, err := Create(zap.NewExample(), p, []byte("somedata")) + w, err := Create(zaptest.NewLogger(b), p, []byte("somedata")) if err != nil { b.Fatalf("err = %v, want nil", err) } diff --git a/server/storage/wal/wal_test.go b/server/storage/wal/wal_test.go index 5a326476e9d8..16e552f9aa9f 100644 --- a/server/storage/wal/wal_test.go +++ b/server/storage/wal/wal_test.go @@ -32,8 +32,6 @@ import ( "go.etcd.io/etcd/raft/v3/raftpb" "go.etcd.io/etcd/server/v3/storage/wal/walpb" "go.uber.org/zap/zaptest" - - "go.uber.org/zap" ) var ( @@ -46,7 +44,7 @@ var ( func TestNew(t *testing.T) { p := t.TempDir() - w, err := Create(zap.NewExample(), p, []byte("somedata")) + w, err := Create(zaptest.NewLogger(t), p, []byte("somedata")) if err != nil { t.Fatalf("err = %v, want nil", err) } @@ -97,7 +95,7 @@ func TestCreateFailFromPollutedDir(t *testing.T) { p := t.TempDir() os.WriteFile(filepath.Join(p, "test.wal"), []byte("data"), os.ModeTemporary) - _, err := Create(zap.NewExample(), p, []byte("data")) + _, err := Create(zaptest.NewLogger(t), p, []byte("data")) if err != os.ErrExist { t.Fatalf("expected %v, got %v", os.ErrExist, err) } @@ -110,7 +108,7 @@ func TestWalCleanup(t *testing.T) { t.Fatal(err) } - logger := zap.NewExample() + logger := zaptest.NewLogger(t) w, err := Create(logger, p, []byte("")) if err != nil { t.Fatalf("err = %v, want nil", err) @@ -139,7 +137,7 @@ func TestCreateFailFromNoSpaceLeft(t *testing.T) { }() SegmentSizeBytes = math.MaxInt64 - _, err := Create(zap.NewExample(), p, []byte("data")) + _, err := Create(zaptest.NewLogger(t), p, []byte("data")) if err == nil { // no space left on device t.Fatalf("expected error 'no space left on device', got nil") } @@ -149,7 +147,7 @@ func TestNewForInitedDir(t *testing.T) { p := t.TempDir() os.Create(filepath.Join(p, walName(0, 0))) - if _, err := Create(zap.NewExample(), p, nil); err == nil || err != os.ErrExist { + if _, err := Create(zaptest.NewLogger(t), p, nil); err == nil || err != os.ErrExist { t.Errorf("err = %v, want %v", err, os.ErrExist) } } @@ -163,7 +161,7 @@ func TestOpenAtIndex(t *testing.T) { } f.Close() - w, err := Open(zap.NewExample(), dir, walpb.Snapshot{}) + w, err := Open(zaptest.NewLogger(t), dir, walpb.Snapshot{}) if err != nil { t.Fatalf("err = %v, want nil", err) } @@ -182,7 +180,7 @@ func TestOpenAtIndex(t *testing.T) { } f.Close() - w, err = Open(zap.NewExample(), dir, walpb.Snapshot{Index: 5}) + w, err = Open(zaptest.NewLogger(t), dir, walpb.Snapshot{Index: 5}) if err != nil { t.Fatalf("err = %v, want nil", err) } @@ -195,7 +193,7 @@ func TestOpenAtIndex(t *testing.T) { w.Close() emptydir := t.TempDir() - if _, err = Open(zap.NewExample(), emptydir, walpb.Snapshot{}); err != ErrFileNotFound { + if _, err = Open(zaptest.NewLogger(t), emptydir, walpb.Snapshot{}); err != ErrFileNotFound { t.Errorf("err = %v, want %v", err, ErrFileNotFound) } } @@ -256,7 +254,7 @@ func TestVerify(t *testing.T) { func TestCut(t *testing.T) { p := t.TempDir() - w, err := Create(zap.NewExample(), p, nil) + w, err := Create(zaptest.NewLogger(t), p, nil) if err != nil { t.Fatal(err) } @@ -314,7 +312,7 @@ func TestCut(t *testing.T) { func TestSaveWithCut(t *testing.T) { p := t.TempDir() - w, err := Create(zap.NewExample(), p, []byte("metadata")) + w, err := Create(zaptest.NewLogger(t), p, []byte("metadata")) if err != nil { t.Fatal(err) } @@ -342,7 +340,7 @@ func TestSaveWithCut(t *testing.T) { w.Close() - neww, err := Open(zap.NewExample(), p, walpb.Snapshot{}) + neww, err := Open(zaptest.NewLogger(t), p, walpb.Snapshot{}) if err != nil { t.Fatalf("err = %v, want nil", err) } @@ -373,7 +371,7 @@ func TestSaveWithCut(t *testing.T) { func TestRecover(t *testing.T) { p := t.TempDir() - w, err := Create(zap.NewExample(), p, []byte("metadata")) + w, err := Create(zaptest.NewLogger(t), p, []byte("metadata")) if err != nil { t.Fatal(err) } @@ -392,7 +390,7 @@ func TestRecover(t *testing.T) { } w.Close() - if w, err = Open(zap.NewExample(), p, walpb.Snapshot{}); err != nil { + if w, err = Open(zaptest.NewLogger(t), p, walpb.Snapshot{}); err != nil { t.Fatal(err) } metadata, state, entries, err := w.ReadAll() @@ -447,7 +445,7 @@ func TestSearchIndex(t *testing.T) { }, } for i, tt := range tests { - idx, ok := searchIndex(zap.NewExample(), tt.names, tt.index) + idx, ok := searchIndex(zaptest.NewLogger(t), tt.names, tt.index) if idx != tt.widx { t.Errorf("#%d: idx = %d, want %d", i, idx, tt.widx) } @@ -484,7 +482,7 @@ func TestScanWalName(t *testing.T) { func TestRecoverAfterCut(t *testing.T) { p := t.TempDir() - md, err := Create(zap.NewExample(), p, []byte("metadata")) + md, err := Create(zaptest.NewLogger(t), p, []byte("metadata")) if err != nil { t.Fatal(err) } @@ -507,7 +505,7 @@ func TestRecoverAfterCut(t *testing.T) { } for i := 0; i < 10; i++ { - w, err := Open(zap.NewExample(), p, walpb.Snapshot{Index: uint64(i), Term: 1}) + w, err := Open(zaptest.NewLogger(t), p, walpb.Snapshot{Index: uint64(i), Term: 1}) if err != nil { if i <= 4 { if err != ErrFileNotFound { @@ -538,7 +536,7 @@ func TestRecoverAfterCut(t *testing.T) { func TestOpenAtUncommittedIndex(t *testing.T) { p := t.TempDir() - w, err := Create(zap.NewExample(), p, nil) + w, err := Create(zaptest.NewLogger(t), p, nil) if err != nil { t.Fatal(err) } @@ -550,7 +548,7 @@ func TestOpenAtUncommittedIndex(t *testing.T) { } w.Close() - w, err = Open(zap.NewExample(), p, walpb.Snapshot{}) + w, err = Open(zaptest.NewLogger(t), p, walpb.Snapshot{}) if err != nil { t.Fatal(err) } @@ -568,7 +566,7 @@ func TestOpenAtUncommittedIndex(t *testing.T) { func TestOpenForRead(t *testing.T) { p := t.TempDir() // create WAL - w, err := Create(zap.NewExample(), p, nil) + w, err := Create(zaptest.NewLogger(t), p, nil) if err != nil { t.Fatal(err) } @@ -588,7 +586,7 @@ func TestOpenForRead(t *testing.T) { w.ReleaseLockTo(unlockIndex) // All are available for read - w2, err := OpenForRead(zap.NewExample(), p, walpb.Snapshot{}) + w2, err := OpenForRead(zaptest.NewLogger(t), p, walpb.Snapshot{}) if err != nil { t.Fatal(err) } @@ -605,7 +603,7 @@ func TestOpenForRead(t *testing.T) { func TestOpenWithMaxIndex(t *testing.T) { p := t.TempDir() // create WAL - w, err := Create(zap.NewExample(), p, nil) + w, err := Create(zaptest.NewLogger(t), p, nil) if err != nil { t.Fatal(err) } @@ -617,7 +615,7 @@ func TestOpenWithMaxIndex(t *testing.T) { } w.Close() - w, err = Open(zap.NewExample(), p, walpb.Snapshot{}) + w, err = Open(zaptest.NewLogger(t), p, walpb.Snapshot{}) if err != nil { t.Fatal(err) } @@ -644,7 +642,7 @@ func TestSaveEmpty(t *testing.T) { func TestReleaseLockTo(t *testing.T) { p := t.TempDir() // create WAL - w, err := Create(zap.NewExample(), p, nil) + w, err := Create(zaptest.NewLogger(t), p, nil) defer func() { if err = w.Close(); err != nil { t.Fatal(err) @@ -713,7 +711,7 @@ func TestTailWriteNoSlackSpace(t *testing.T) { p := t.TempDir() // create initial WAL - w, err := Create(zap.NewExample(), p, []byte("metadata")) + w, err := Create(zaptest.NewLogger(t), p, []byte("metadata")) if err != nil { t.Fatal(err) } @@ -735,7 +733,7 @@ func TestTailWriteNoSlackSpace(t *testing.T) { w.Close() // open, write more - w, err = Open(zap.NewExample(), p, walpb.Snapshot{}) + w, err = Open(zaptest.NewLogger(t), p, walpb.Snapshot{}) if err != nil { t.Fatal(err) } @@ -756,7 +754,7 @@ func TestTailWriteNoSlackSpace(t *testing.T) { w.Close() // confirm all writes - w, err = Open(zap.NewExample(), p, walpb.Snapshot{}) + w, err = Open(zaptest.NewLogger(t), p, walpb.Snapshot{}) if err != nil { t.Fatal(err) } @@ -784,7 +782,7 @@ func TestRestartCreateWal(t *testing.T) { t.Fatal(err) } - w, werr := Create(zap.NewExample(), p, []byte("abc")) + w, werr := Create(zaptest.NewLogger(t), p, []byte("abc")) if werr != nil { t.Fatal(werr) } @@ -793,7 +791,7 @@ func TestRestartCreateWal(t *testing.T) { t.Fatalf("got %q exists, expected it to not exist", tmpdir) } - if w, err = OpenForRead(zap.NewExample(), p, walpb.Snapshot{}); err != nil { + if w, err = OpenForRead(zaptest.NewLogger(t), p, walpb.Snapshot{}); err != nil { t.Fatal(err) } defer w.Close() @@ -810,7 +808,7 @@ func TestOpenOnTornWrite(t *testing.T) { overwriteEntries := 5 p := t.TempDir() - w, err := Create(zap.NewExample(), p, nil) + w, err := Create(zaptest.NewLogger(t), p, nil) defer func() { if err = w.Close(); err != nil && err != os.ErrInvalid { t.Fatal(err) @@ -852,7 +850,7 @@ func TestOpenOnTornWrite(t *testing.T) { } f.Close() - w, err = Open(zap.NewExample(), p, walpb.Snapshot{}) + w, err = Open(zaptest.NewLogger(t), p, walpb.Snapshot{}) if err != nil { t.Fatal(err) } @@ -873,7 +871,7 @@ func TestOpenOnTornWrite(t *testing.T) { w.Close() // read back the entries, confirm number of entries matches expectation - w, err = OpenForRead(zap.NewExample(), p, walpb.Snapshot{}) + w, err = OpenForRead(zaptest.NewLogger(t), p, walpb.Snapshot{}) if err != nil { t.Fatal(err) } @@ -902,7 +900,7 @@ func TestRenameFail(t *testing.T) { os.RemoveAll(tp) w := &WAL{ - lg: zap.NewExample(), + lg: zaptest.NewLogger(t), dir: p, } w2, werr := w.renameWAL(tp) @@ -916,7 +914,7 @@ func TestReadAllFail(t *testing.T) { dir := t.TempDir() // create initial WAL - f, err := Create(zap.NewExample(), dir, []byte("metadata")) + f, err := Create(zaptest.NewLogger(t), dir, []byte("metadata")) if err != nil { t.Fatal(err) } @@ -940,7 +938,7 @@ func TestValidSnapshotEntries(t *testing.T) { state2 := raftpb.HardState{Commit: 3, Term: 2} snap4 := walpb.Snapshot{Index: 4, Term: 2, ConfState: &confState} // will be orphaned since the last committed entry will be snap3 func() { - w, err := Create(zap.NewExample(), p, nil) + w, err := Create(zaptest.NewLogger(t), p, nil) if err != nil { t.Fatal(err) } @@ -966,7 +964,7 @@ func TestValidSnapshotEntries(t *testing.T) { t.Fatal(err) } }() - walSnaps, err := ValidSnapshotEntries(zap.NewExample(), p) + walSnaps, err := ValidSnapshotEntries(zaptest.NewLogger(t), p) if err != nil { t.Fatal(err) } @@ -992,7 +990,7 @@ func TestValidSnapshotEntriesAfterPurgeWal(t *testing.T) { snap3 := walpb.Snapshot{Index: 3, Term: 2, ConfState: &confState} state2 := raftpb.HardState{Commit: 3, Term: 2} func() { - w, err := Create(zap.NewExample(), p, nil) + w, err := Create(zaptest.NewLogger(t), p, nil) if err != nil { t.Fatal(err) } @@ -1023,7 +1021,7 @@ func TestValidSnapshotEntriesAfterPurgeWal(t *testing.T) { t.Fatal(err) } os.Remove(p + "/" + files[0]) - _, err = ValidSnapshotEntries(zap.NewExample(), p) + _, err = ValidSnapshotEntries(zaptest.NewLogger(t), p) if err != nil { t.Fatal(err) } diff --git a/tests/functional/tester/cluster_test.go b/tests/functional/tester/cluster_test.go index aa17e7e37583..97511928028a 100644 --- a/tests/functional/tester/cluster_test.go +++ b/tests/functional/tester/cluster_test.go @@ -20,8 +20,7 @@ import ( "testing" "go.etcd.io/etcd/tests/v3/functional/rpcpb" - - "go.uber.org/zap" + "go.uber.org/zap/zaptest" ) func Test_read(t *testing.T) { @@ -262,10 +261,7 @@ func Test_read(t *testing.T) { }, } - logger, err := zap.NewProduction() - if err != nil { - t.Fatal(err) - } + logger := zaptest.NewLogger(t) defer logger.Sync() cfg, err := read(logger, "../functional.yaml") diff --git a/tools/etcd-dump-logs/etcd-dump-log_test.go b/tools/etcd-dump-logs/etcd-dump-log_test.go index bef7e0648615..ca7f5c325552 100644 --- a/tools/etcd-dump-logs/etcd-dump-log_test.go +++ b/tools/etcd-dump-logs/etcd-dump-log_test.go @@ -29,7 +29,7 @@ import ( "go.etcd.io/etcd/pkg/v3/pbutil" "go.etcd.io/etcd/raft/v3/raftpb" "go.etcd.io/etcd/server/v3/storage/wal" - "go.uber.org/zap" + "go.uber.org/zap/zaptest" ) func TestEtcdDumpLogEntryType(t *testing.T) { @@ -57,7 +57,7 @@ func TestEtcdDumpLogEntryType(t *testing.T) { waldir := walDir(p) snapdir := snapDir(p) - w, err := wal.Create(zap.NewExample(), waldir, nil) + w, err := wal.Create(zaptest.NewLogger(t), waldir, nil) if err != nil { t.Fatal(err) } From f71196d1135575c461b624846bec96cc3c7f2e78 Mon Sep 17 00:00:00 2001 From: Danielle Lancashire Date: Thu, 31 Mar 2022 21:17:54 +0200 Subject: [PATCH 246/258] tests/common/lease: Wait for correct lease list response MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit We don't consistently reach the same etcd server during the lifetime of a test and in some cases, this means that this test will flake if an etcd server was slow to update its state and the test hits the outdated server. Here we switch to using an `Eventually` case which will wait upto a second for the expected result before failing - with a 10ms gap between invocations. ``` [tests(dani/leasefix)] $ gotestsum -- ./common -tags integration -count 100 -timeout 15m -run TestLeaseGrantAndList ✓ common (2m26.71s) DONE 1600 tests in 147.258s ``` --- tests/common/lease_test.go | 20 +++++++++++++++----- 1 file changed, 15 insertions(+), 5 deletions(-) diff --git a/tests/common/lease_test.go b/tests/common/lease_test.go index 34260c6c2870..2b239b2adfed 100644 --- a/tests/common/lease_test.go +++ b/tests/common/lease_test.go @@ -127,20 +127,30 @@ func TestLeaseGrantAndList(t *testing.T) { t.Logf("Created cluster and client") testutils.ExecuteWithTimeout(t, 10*time.Second, func() { createdLeases := []clientv3.LeaseID{} + lastRev := int64(0) for i := 0; i < nc.leaseCount; i++ { leaseResp, err := cc.Grant(10) t.Logf("Grant returned: resp:%s err:%v", leaseResp.String(), err) require.NoError(t, err) createdLeases = append(createdLeases, leaseResp.ID) + lastRev = leaseResp.GetRevision() } - resp, err := cc.LeaseList() - t.Logf("Lease list returned: resp:%s err:%v", resp.String(), err) - require.NoError(t, err) - require.Len(t, resp.Leases, nc.leaseCount) + // Because we're not guarunteed to talk to the same member, wait for + // listing to eventually return true, either by the result propagaing + // or by hitting an up to date member. + leases := []clientv3.LeaseStatus{} + require.Eventually(t, func() bool { + resp, err := cc.LeaseList() + if err != nil { + return false + } + leases = resp.Leases + return resp.GetRevision() >= lastRev + }, 2*time.Second, 10*time.Millisecond) returnedLeases := make([]clientv3.LeaseID, 0, nc.leaseCount) - for _, status := range resp.Leases { + for _, status := range leases { returnedLeases = append(returnedLeases, status.ID) } From 1d3517020b69596a6f1dfda2f67ad8abbb5ca9cc Mon Sep 17 00:00:00 2001 From: Marek Siarkowicz Date: Tue, 5 Apr 2022 14:32:22 +0200 Subject: [PATCH 247/258] server: Add verification of whether lock was called within out outside of apply --- scripts/test.sh | 1 + server/storage/backend/batch_tx.go | 12 ++++ server/storage/backend/verify.go | 56 +++++++++++++++++ server/storage/backend/verify_test.go | 91 +++++++++++++++++++++++++++ server/storage/mvcc/kvstore_test.go | 6 +- 5 files changed, 164 insertions(+), 2 deletions(-) create mode 100644 server/storage/backend/verify.go create mode 100644 server/storage/backend/verify_test.go diff --git a/scripts/test.sh b/scripts/test.sh index 9f5b38772801..cdd52e1ab6bd 100755 --- a/scripts/test.sh +++ b/scripts/test.sh @@ -41,6 +41,7 @@ set -o pipefail # e.g. add/update missing dependencies. Such divergences should be # detected and trigger a failure that needs explicit developer's action. export GOFLAGS=-mod=readonly +export ETCD_VERIFY=all source ./scripts/test_lib.sh source ./scripts/build.sh diff --git a/server/storage/backend/batch_tx.go b/server/storage/backend/batch_tx.go index b2b0ad7cbf02..a8e649199161 100644 --- a/server/storage/backend/batch_tx.go +++ b/server/storage/backend/batch_tx.go @@ -53,6 +53,8 @@ type BatchTx interface { Commit() // CommitAndStop commits the previous tx and does not create a new one. CommitAndStop() + LockInsideApply() + LockOutsideApply() } type batchTx struct { @@ -67,6 +69,16 @@ func (t *batchTx) Lock() { t.Mutex.Lock() } +func (t *batchTx) LockInsideApply() { + ValidateCalledInsideApply(t.backend.lg) + t.Lock() +} + +func (t *batchTx) LockOutsideApply() { + ValidateCalledOutSideApply(t.backend.lg) + t.Lock() +} + func (t *batchTx) Unlock() { if t.pending >= t.backend.batchLimit { t.commit(false) diff --git a/server/storage/backend/verify.go b/server/storage/backend/verify.go new file mode 100644 index 000000000000..2f3dc0221c60 --- /dev/null +++ b/server/storage/backend/verify.go @@ -0,0 +1,56 @@ +// Copyright 2022 The etcd Authors +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package backend + +import ( + "os" + "runtime/debug" + "strings" + + "go.uber.org/zap" +) + +const ( + ENV_VERIFY = "ETCD_VERIFY" + ENV_VERIFY_ALL_VALUE = "all" + ENV_VERIFY_LOCK = "lock" +) + +func ValidateCalledInsideApply(lg *zap.Logger) { + if !verifyLockEnabled() { + return + } + if !insideApply() { + lg.Panic("Called outside of APPLY!", zap.Stack("stacktrace")) + } +} + +func ValidateCalledOutSideApply(lg *zap.Logger) { + if !verifyLockEnabled() { + return + } + if insideApply() { + lg.Panic("Called inside of APPLY!", zap.Stack("stacktrace")) + } +} + +func verifyLockEnabled() bool { + return os.Getenv(ENV_VERIFY) == ENV_VERIFY_ALL_VALUE || os.Getenv(ENV_VERIFY) == ENV_VERIFY_LOCK +} + +func insideApply() bool { + stackTraceStr := string(debug.Stack()) + return strings.Contains(stackTraceStr, ".applyEntries") +} diff --git a/server/storage/backend/verify_test.go b/server/storage/backend/verify_test.go new file mode 100644 index 000000000000..08efb392104a --- /dev/null +++ b/server/storage/backend/verify_test.go @@ -0,0 +1,91 @@ +// Copyright 2022 The etcd Authors +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package backend_test + +import ( + "fmt" + "os" + "testing" + "time" + + "go.etcd.io/etcd/server/v3/storage/backend" + betesting "go.etcd.io/etcd/server/v3/storage/backend/testing" +) + +func TestLockVerify(t *testing.T) { + tcs := []struct { + insideApply bool + lock func(tx backend.BatchTx) + expectPanic bool + }{ + { + insideApply: true, + lock: lockInsideApply, + expectPanic: false, + }, + { + insideApply: false, + lock: lockInsideApply, + expectPanic: true, + }, + { + insideApply: false, + lock: lockOutsideApply, + expectPanic: false, + }, + { + insideApply: true, + lock: lockOutsideApply, + expectPanic: true, + }, + } + env := os.Getenv("ETCD_VERIFY") + os.Setenv("ETCD_VERIFY", "lock") + defer func() { + os.Setenv("ETCD_VERIFY", env) + }() + for i, tc := range tcs { + t.Run(fmt.Sprintf("%d", i), func(t *testing.T) { + + be, _ := betesting.NewTmpBackend(t, time.Hour, 10000) + + hasPaniced := handlePanic(func() { + if tc.insideApply { + applyEntries(be, tc.lock) + } else { + tc.lock(be.BatchTx()) + } + }) != nil + if hasPaniced != tc.expectPanic { + t.Errorf("%v != %v", hasPaniced, tc.expectPanic) + } + }) + } +} + +func handlePanic(f func()) (result interface{}) { + defer func() { + result = recover() + }() + f() + return result +} + +func applyEntries(be backend.Backend, f func(tx backend.BatchTx)) { + f(be.BatchTx()) +} + +func lockInsideApply(tx backend.BatchTx) { tx.LockInsideApply() } +func lockOutsideApply(tx backend.BatchTx) { tx.LockOutsideApply() } diff --git a/server/storage/mvcc/kvstore_test.go b/server/storage/mvcc/kvstore_test.go index 4f0dbce79682..31cb37655415 100644 --- a/server/storage/mvcc/kvstore_test.go +++ b/server/storage/mvcc/kvstore_test.go @@ -904,8 +904,10 @@ func (b *fakeBatchTx) UnsafeDelete(bucket backend.Bucket, key []byte) { func (b *fakeBatchTx) UnsafeForEach(bucket backend.Bucket, visitor func(k, v []byte) error) error { return nil } -func (b *fakeBatchTx) Commit() {} -func (b *fakeBatchTx) CommitAndStop() {} +func (b *fakeBatchTx) Commit() {} +func (b *fakeBatchTx) CommitAndStop() {} +func (b *fakeBatchTx) LockInsideApply() {} +func (b *fakeBatchTx) LockOutsideApply() {} type fakeBackend struct { tx *fakeBatchTx From 73fc8642478d3f24dd79aa9d6492ecc95c39428e Mon Sep 17 00:00:00 2001 From: Marek Siarkowicz Date: Tue, 5 Apr 2022 15:53:38 +0200 Subject: [PATCH 248/258] tests: Pass logger to backend --- etcdutl/etcdutl/backup_command.go | 2 +- etcdutl/etcdutl/defrag_command.go | 2 +- etcdutl/etcdutl/migrate_command.go | 19 ++++++++++--------- etcdutl/snapshot/v3_snapshot.go | 6 +++--- server/etcdserver/cindex/cindex_test.go | 3 ++- server/lease/lessor_test.go | 6 ++++-- server/storage/backend.go | 2 +- server/storage/backend/backend.go | 11 ++++------- server/storage/backend/backend_test.go | 5 +++-- server/storage/backend/hooks_test.go | 7 ++++--- server/storage/backend/testing/betesting.go | 4 ++-- server/storage/mvcc/store_test.go | 7 +++++-- server/storage/schema/auth_roles_test.go | 14 ++++++++------ server/storage/schema/auth_test.go | 14 ++++++++------ server/storage/schema/auth_users_test.go | 14 ++++++++------ server/storage/schema/lease_test.go | 4 +++- server/storage/schema/schema_test.go | 6 +++--- server/storage/schema/version_test.go | 4 +++- server/verify/verify.go | 2 +- tests/e2e/utl_migrate_test.go | 4 +++- .../integration/clientv3/maintenance_test.go | 5 +++-- tests/integration/v3_alarm_test.go | 9 +++++---- tools/benchmark/cmd/mvcc.go | 2 +- tools/etcd-dump-db/backend.go | 3 ++- 24 files changed, 88 insertions(+), 67 deletions(-) diff --git a/etcdutl/etcdutl/backup_command.go b/etcdutl/etcdutl/backup_command.go index ce9b50bd9aa3..49b6a93101d1 100644 --- a/etcdutl/etcdutl/backup_command.go +++ b/etcdutl/etcdutl/backup_command.go @@ -308,7 +308,7 @@ func saveDB(lg *zap.Logger, destDB, srcDB string, idx uint64, term uint64, desir } } - be := backend.NewDefaultBackend(destDB) + be := backend.NewDefaultBackend(lg, destDB) defer be.Close() ms := schema.NewMembershipBackend(lg, be) if err := ms.TrimClusterFromBackend(); err != nil { diff --git a/etcdutl/etcdutl/defrag_command.go b/etcdutl/etcdutl/defrag_command.go index fe4f8430d509..bc447d4ada8f 100644 --- a/etcdutl/etcdutl/defrag_command.go +++ b/etcdutl/etcdutl/defrag_command.go @@ -57,7 +57,7 @@ func DefragData(dataDir string) error { dbDir := datadir.ToBackendFileName(dataDir) go func() { defer close(bch) - cfg := backend.DefaultBackendConfig() + cfg := backend.DefaultBackendConfig(lg) cfg.Logger = lg cfg.Path = dbDir be = backend.New(cfg) diff --git a/etcdutl/etcdutl/migrate_command.go b/etcdutl/etcdutl/migrate_command.go index c3a02cb4a266..88f9e473c8a1 100644 --- a/etcdutl/etcdutl/migrate_command.go +++ b/etcdutl/etcdutl/migrate_command.go @@ -75,6 +75,7 @@ func (o *migrateOptions) AddFlags(cmd *cobra.Command) { func (o *migrateOptions) Config() (*migrateConfig, error) { c := &migrateConfig{ force: o.force, + lg: GetLogger(), } var err error dotCount := strings.Count(o.targetVersion, ".") @@ -90,10 +91,10 @@ func (o *migrateOptions) Config() (*migrateConfig, error) { } dbPath := datadir.ToBackendFileName(o.dataDir) - c.be = backend.NewDefaultBackend(dbPath) + c.be = backend.NewDefaultBackend(GetLogger(), dbPath) walPath := datadir.ToWalDir(o.dataDir) - w, err := wal.OpenForRead(GetLogger(), walPath, walpb.Snapshot{}) + w, err := wal.OpenForRead(c.lg, walPath, walpb.Snapshot{}) if err != nil { return nil, fmt.Errorf(`failed to open wal: %v`, err) } @@ -107,6 +108,7 @@ func (o *migrateOptions) Config() (*migrateConfig, error) { } type migrateConfig struct { + lg *zap.Logger be backend.Backend targetVersion *semver.Version walVersion schema.WALVersion @@ -115,24 +117,23 @@ type migrateConfig struct { func migrateCommandFunc(c *migrateConfig) error { defer c.be.Close() - lg := GetLogger() tx := c.be.BatchTx() - current, err := schema.DetectSchemaVersion(lg, tx) + current, err := schema.DetectSchemaVersion(c.lg, tx) if err != nil { - lg.Error("failed to detect storage version. Please make sure you are using data dir from etcd v3.5 and older") + c.lg.Error("failed to detect storage version. Please make sure you are using data dir from etcd v3.5 and older") return err } if current == *c.targetVersion { - lg.Info("storage version up-to-date", zap.String("storage-version", storageVersionToString(¤t))) + c.lg.Info("storage version up-to-date", zap.String("storage-version", storageVersionToString(¤t))) return nil } - err = schema.Migrate(lg, tx, c.walVersion, *c.targetVersion) + err = schema.Migrate(c.lg, tx, c.walVersion, *c.targetVersion) if err != nil { if !c.force { return err } - lg.Info("normal migrate failed, trying with force", zap.Error(err)) - migrateForce(lg, tx, c.targetVersion) + c.lg.Info("normal migrate failed, trying with force", zap.Error(err)) + migrateForce(c.lg, tx, c.targetVersion) } c.be.ForceCommit() return nil diff --git a/etcdutl/snapshot/v3_snapshot.go b/etcdutl/snapshot/v3_snapshot.go index 61d62385deb9..fcce5bf8282a 100644 --- a/etcdutl/snapshot/v3_snapshot.go +++ b/etcdutl/snapshot/v3_snapshot.go @@ -299,7 +299,7 @@ func (s *v3Manager) saveDB() error { return err } - be := backend.NewDefaultBackend(s.outDbPath()) + be := backend.NewDefaultBackend(s.lg, s.outDbPath()) defer be.Close() err = schema.NewMembershipBackend(s.lg, be).TrimMembershipFromBackend() @@ -397,7 +397,7 @@ func (s *v3Manager) saveWALAndSnap() (*raftpb.HardState, error) { // add members again to persist them to the store we create. st := v2store.New(etcdserver.StoreClusterPrefix, etcdserver.StoreKeysPrefix) s.cl.SetStore(st) - be := backend.NewDefaultBackend(s.outDbPath()) + be := backend.NewDefaultBackend(s.lg, s.outDbPath()) defer be.Close() s.cl.SetBackend(schema.NewMembershipBackend(s.lg, be)) for _, m := range s.cl.Members() { @@ -480,7 +480,7 @@ func (s *v3Manager) saveWALAndSnap() (*raftpb.HardState, error) { } func (s *v3Manager) updateCIndex(commit uint64, term uint64) error { - be := backend.NewDefaultBackend(s.outDbPath()) + be := backend.NewDefaultBackend(s.lg, s.outDbPath()) defer be.Close() cindex.UpdateConsistentIndex(be.BatchTx(), commit, term, false) diff --git a/server/etcdserver/cindex/cindex_test.go b/server/etcdserver/cindex/cindex_test.go index 9122c6e33728..026c5a624666 100644 --- a/server/etcdserver/cindex/cindex_test.go +++ b/server/etcdserver/cindex/cindex_test.go @@ -23,6 +23,7 @@ import ( "go.etcd.io/etcd/server/v3/storage/backend" betesting "go.etcd.io/etcd/server/v3/storage/backend/testing" "go.etcd.io/etcd/server/v3/storage/schema" + "go.uber.org/zap/zaptest" ) // TestConsistentIndex ensures that LoadConsistentIndex/Save/ConsistentIndex and backend.BatchTx can work well together. @@ -53,7 +54,7 @@ func TestConsistentIndex(t *testing.T) { be.ForceCommit() be.Close() - b := backend.NewDefaultBackend(tmpPath) + b := backend.NewDefaultBackend(zaptest.NewLogger(t), tmpPath) defer b.Close() ci.SetBackend(b) index = ci.ConsistentIndex() diff --git a/server/lease/lessor_test.go b/server/lease/lessor_test.go index 740294c50848..1879549f34b7 100644 --- a/server/lease/lessor_test.go +++ b/server/lease/lessor_test.go @@ -31,6 +31,7 @@ import ( "go.etcd.io/etcd/server/v3/storage/backend" "go.etcd.io/etcd/server/v3/storage/schema" "go.uber.org/zap" + "go.uber.org/zap/zaptest" ) const ( @@ -310,7 +311,7 @@ func TestLessorRenewExtendPileup(t *testing.T) { // simulate stop and recovery le.Stop() be.Close() - bcfg := backend.DefaultBackendConfig() + bcfg := backend.DefaultBackendConfig(lg) bcfg.Path = filepath.Join(dir, "be") be = backend.New(bcfg) defer be.Close() @@ -669,8 +670,9 @@ func (fd *fakeDeleter) DeleteRange(key, end []byte) (int64, int64) { } func NewTestBackend(t *testing.T) (string, backend.Backend) { + lg := zaptest.NewLogger(t) tmpPath := t.TempDir() - bcfg := backend.DefaultBackendConfig() + bcfg := backend.DefaultBackendConfig(lg) bcfg.Path = filepath.Join(tmpPath, "be") return tmpPath, backend.New(bcfg) } diff --git a/server/storage/backend.go b/server/storage/backend.go index abbbf889d7d2..b7b0eb2fc7f4 100644 --- a/server/storage/backend.go +++ b/server/storage/backend.go @@ -29,7 +29,7 @@ import ( ) func newBackend(cfg config.ServerConfig, hooks backend.Hooks) backend.Backend { - bcfg := backend.DefaultBackendConfig() + bcfg := backend.DefaultBackendConfig(cfg.Logger) bcfg.Path = cfg.BackendPath() bcfg.UnsafeNoFsync = cfg.UnsafeNoFsync if cfg.BackendBatchLimit != 0 { diff --git a/server/storage/backend/backend.go b/server/storage/backend/backend.go index 67cfab9dd3a8..a61f4ec3609b 100644 --- a/server/storage/backend/backend.go +++ b/server/storage/backend/backend.go @@ -144,11 +144,12 @@ type BackendConfig struct { Hooks Hooks } -func DefaultBackendConfig() BackendConfig { +func DefaultBackendConfig(lg *zap.Logger) BackendConfig { return BackendConfig{ BatchInterval: defaultBatchInterval, BatchLimit: defaultBatchLimit, MmapSize: initialMmapSize, + Logger: lg, } } @@ -156,17 +157,13 @@ func New(bcfg BackendConfig) Backend { return newBackend(bcfg) } -func NewDefaultBackend(path string) Backend { - bcfg := DefaultBackendConfig() +func NewDefaultBackend(lg *zap.Logger, path string) Backend { + bcfg := DefaultBackendConfig(lg) bcfg.Path = path return newBackend(bcfg) } func newBackend(bcfg BackendConfig) *backend { - if bcfg.Logger == nil { - bcfg.Logger = zap.NewNop() - } - bopts := &bolt.Options{} if boltOpenOptions != nil { *bopts = *boltOpenOptions diff --git a/server/storage/backend/backend_test.go b/server/storage/backend/backend_test.go index 0b3e4b629ed8..0b0b6b8ec9b1 100644 --- a/server/storage/backend/backend_test.go +++ b/server/storage/backend/backend_test.go @@ -26,6 +26,7 @@ import ( "go.etcd.io/etcd/server/v3/storage/backend" betesting "go.etcd.io/etcd/server/v3/storage/backend/testing" "go.etcd.io/etcd/server/v3/storage/schema" + "go.uber.org/zap/zaptest" ) func TestBackendClose(t *testing.T) { @@ -71,7 +72,7 @@ func TestBackendSnapshot(t *testing.T) { assert.NoError(t, f.Close()) // bootstrap new backend from the snapshot - bcfg := backend.DefaultBackendConfig() + bcfg := backend.DefaultBackendConfig(zaptest.NewLogger(t)) bcfg.Path, bcfg.BatchInterval, bcfg.BatchLimit = f.Name(), time.Hour, 10000 nb := backend.New(bcfg) defer betesting.Close(t, nb) @@ -122,7 +123,7 @@ func TestBackendBatchIntervalCommit(t *testing.T) { } func TestBackendDefrag(t *testing.T) { - bcfg := backend.DefaultBackendConfig() + bcfg := backend.DefaultBackendConfig(zaptest.NewLogger(t)) // Make sure we change BackendFreelistType // The goal is to verify that we restore config option after defrag. if bcfg.BackendFreelistType == bolt.FreelistMapType { diff --git a/server/storage/backend/hooks_test.go b/server/storage/backend/hooks_test.go index 5197ee2d71fe..766464484890 100644 --- a/server/storage/backend/hooks_test.go +++ b/server/storage/backend/hooks_test.go @@ -23,6 +23,7 @@ import ( "go.etcd.io/etcd/server/v3/storage/backend" betesting "go.etcd.io/etcd/server/v3/storage/backend/testing" "go.etcd.io/etcd/server/v3/storage/schema" + "go.uber.org/zap/zaptest" ) var ( @@ -31,7 +32,7 @@ var ( ) func TestBackendPreCommitHook(t *testing.T) { - be := newTestHooksBackend(t, backend.DefaultBackendConfig()) + be := newTestHooksBackend(t, backend.DefaultBackendConfig(zaptest.NewLogger(t))) tx := be.BatchTx() prepareBuckenAndKey(tx) @@ -48,7 +49,7 @@ func TestBackendPreCommitHook(t *testing.T) { } func TestBackendAutoCommitLimitHook(t *testing.T) { - cfg := backend.DefaultBackendConfig() + cfg := backend.DefaultBackendConfig(zaptest.NewLogger(t)) cfg.BatchLimit = 3 be := newTestHooksBackend(t, cfg) @@ -72,7 +73,7 @@ func TestBackendAutoCommitBatchIntervalHook(t *testing.T) { ctx, cancel := context.WithTimeout(context.Background(), time.Minute) defer cancel() - cfg := backend.DefaultBackendConfig() + cfg := backend.DefaultBackendConfig(zaptest.NewLogger(t)) cfg.BatchInterval = 10 * time.Millisecond be := newTestHooksBackend(t, cfg) tx := be.BatchTx() diff --git a/server/storage/backend/testing/betesting.go b/server/storage/backend/testing/betesting.go index c8ce79482f86..05e0249b2413 100644 --- a/server/storage/backend/testing/betesting.go +++ b/server/storage/backend/testing/betesting.go @@ -38,13 +38,13 @@ func NewTmpBackendFromCfg(t testing.TB, bcfg backend.BackendConfig) (backend.Bac // NewTmpBackend creates a backend implementation for testing. func NewTmpBackend(t testing.TB, batchInterval time.Duration, batchLimit int) (backend.Backend, string) { - bcfg := backend.DefaultBackendConfig() + bcfg := backend.DefaultBackendConfig(zaptest.NewLogger(t)) bcfg.BatchInterval, bcfg.BatchLimit = batchInterval, batchLimit return NewTmpBackendFromCfg(t, bcfg) } func NewDefaultTmpBackend(t testing.TB) (backend.Backend, string) { - return NewTmpBackendFromCfg(t, backend.DefaultBackendConfig()) + return NewTmpBackendFromCfg(t, backend.DefaultBackendConfig(zaptest.NewLogger(t))) } func Close(t testing.TB, b backend.Backend) { diff --git a/server/storage/mvcc/store_test.go b/server/storage/mvcc/store_test.go index 4d9db44359e8..dc6ac7373dcc 100644 --- a/server/storage/mvcc/store_test.go +++ b/server/storage/mvcc/store_test.go @@ -7,6 +7,7 @@ import ( "time" "github.com/stretchr/testify/assert" + "go.uber.org/zap/zaptest" "go.etcd.io/etcd/server/v3/storage/backend" betesting "go.etcd.io/etcd/server/v3/storage/backend/testing" @@ -33,6 +34,7 @@ func TestScheduledCompact(t *testing.T) { } for _, tc := range tcs { t.Run(fmt.Sprint(tc.value), func(t *testing.T) { + lg := zaptest.NewLogger(t) be, tmpPath := betesting.NewTmpBackend(t, time.Microsecond, 10) tx := be.BatchTx() if tx == nil { @@ -45,7 +47,7 @@ func TestScheduledCompact(t *testing.T) { be.ForceCommit() be.Close() - b := backend.NewDefaultBackend(tmpPath) + b := backend.NewDefaultBackend(lg, tmpPath) defer b.Close() v, found := UnsafeReadScheduledCompact(b.BatchTx()) assert.Equal(t, true, found) @@ -74,6 +76,7 @@ func TestFinishedCompact(t *testing.T) { } for _, tc := range tcs { t.Run(fmt.Sprint(tc.value), func(t *testing.T) { + lg := zaptest.NewLogger(t) be, tmpPath := betesting.NewTmpBackend(t, time.Microsecond, 10) tx := be.BatchTx() if tx == nil { @@ -86,7 +89,7 @@ func TestFinishedCompact(t *testing.T) { be.ForceCommit() be.Close() - b := backend.NewDefaultBackend(tmpPath) + b := backend.NewDefaultBackend(lg, tmpPath) defer b.Close() v, found := UnsafeReadFinishedCompact(b.BatchTx()) assert.Equal(t, true, found) diff --git a/server/storage/schema/auth_roles_test.go b/server/storage/schema/auth_roles_test.go index 5302aef2d8de..31c3ff605004 100644 --- a/server/storage/schema/auth_roles_test.go +++ b/server/storage/schema/auth_roles_test.go @@ -109,8 +109,9 @@ func TestGetAllRoles(t *testing.T) { } for _, tc := range tcs { t.Run(tc.name, func(t *testing.T) { + lg := zaptest.NewLogger(t) be, tmpPath := betesting.NewTmpBackend(t, time.Microsecond, 10) - abe := NewAuthBackend(zaptest.NewLogger(t), be) + abe := NewAuthBackend(lg, be) abe.CreateAuthBuckets() tx := abe.BatchTx() @@ -121,9 +122,9 @@ func TestGetAllRoles(t *testing.T) { abe.ForceCommit() be.Close() - be2 := backend.NewDefaultBackend(tmpPath) + be2 := backend.NewDefaultBackend(lg, tmpPath) defer be2.Close() - abe2 := NewAuthBackend(zaptest.NewLogger(t), be2) + abe2 := NewAuthBackend(lg, be2) users := abe2.GetAllRoles() assert.Equal(t, tc.want, users) @@ -205,8 +206,9 @@ func TestGetRole(t *testing.T) { } for _, tc := range tcs { t.Run(tc.name, func(t *testing.T) { + lg := zaptest.NewLogger(t) be, tmpPath := betesting.NewTmpBackend(t, time.Microsecond, 10) - abe := NewAuthBackend(zaptest.NewLogger(t), be) + abe := NewAuthBackend(lg, be) abe.CreateAuthBuckets() tx := abe.BatchTx() @@ -217,9 +219,9 @@ func TestGetRole(t *testing.T) { abe.ForceCommit() be.Close() - be2 := backend.NewDefaultBackend(tmpPath) + be2 := backend.NewDefaultBackend(lg, tmpPath) defer be2.Close() - abe2 := NewAuthBackend(zaptest.NewLogger(t), be2) + abe2 := NewAuthBackend(lg, be2) users := abe2.GetRole("role1") assert.Equal(t, tc.want, users) diff --git a/server/storage/schema/auth_test.go b/server/storage/schema/auth_test.go index 71d231d9083f..96174e50ffc6 100644 --- a/server/storage/schema/auth_test.go +++ b/server/storage/schema/auth_test.go @@ -52,8 +52,9 @@ func TestAuthEnabled(t *testing.T) { } for _, tc := range tcs { t.Run(tc.name, func(t *testing.T) { + lg := zaptest.NewLogger(t) be, tmpPath := betesting.NewTmpBackend(t, time.Microsecond, 10) - abe := NewAuthBackend(zaptest.NewLogger(t), be) + abe := NewAuthBackend(lg, be) tx := abe.BatchTx() abe.CreateAuthBuckets() @@ -65,9 +66,9 @@ func TestAuthEnabled(t *testing.T) { abe.ForceCommit() be.Close() - be2 := backend.NewDefaultBackend(tmpPath) + be2 := backend.NewDefaultBackend(lg, tmpPath) defer be2.Close() - abe2 := NewAuthBackend(zaptest.NewLogger(t), be2) + abe2 := NewAuthBackend(lg, be2) tx = abe2.BatchTx() tx.Lock() defer tx.Unlock() @@ -102,8 +103,9 @@ func TestAuthRevision(t *testing.T) { } for _, tc := range tcs { t.Run(tc.name, func(t *testing.T) { + lg := zaptest.NewLogger(t) be, tmpPath := betesting.NewTmpBackend(t, time.Microsecond, 10) - abe := NewAuthBackend(zaptest.NewLogger(t), be) + abe := NewAuthBackend(lg, be) abe.CreateAuthBuckets() if tc.setRevision != 0 { @@ -115,9 +117,9 @@ func TestAuthRevision(t *testing.T) { abe.ForceCommit() be.Close() - be2 := backend.NewDefaultBackend(tmpPath) + be2 := backend.NewDefaultBackend(lg, tmpPath) defer be2.Close() - abe2 := NewAuthBackend(zaptest.NewLogger(t), be2) + abe2 := NewAuthBackend(lg, be2) tx := abe2.BatchTx() tx.Lock() defer tx.Unlock() diff --git a/server/storage/schema/auth_users_test.go b/server/storage/schema/auth_users_test.go index 359dde5ac083..c25aef33639f 100644 --- a/server/storage/schema/auth_users_test.go +++ b/server/storage/schema/auth_users_test.go @@ -97,8 +97,9 @@ func TestGetAllUsers(t *testing.T) { } for _, tc := range tcs { t.Run(tc.name, func(t *testing.T) { + lg := zaptest.NewLogger(t) be, tmpPath := betesting.NewTmpBackend(t, time.Microsecond, 10) - abe := NewAuthBackend(zaptest.NewLogger(t), be) + abe := NewAuthBackend(lg, be) abe.CreateAuthBuckets() tx := abe.BatchTx() @@ -109,9 +110,9 @@ func TestGetAllUsers(t *testing.T) { abe.ForceCommit() be.Close() - be2 := backend.NewDefaultBackend(tmpPath) + be2 := backend.NewDefaultBackend(lg, tmpPath) defer be2.Close() - abe2 := NewAuthBackend(zaptest.NewLogger(t), be2) + abe2 := NewAuthBackend(lg, be2) users := abe2.GetAllUsers() assert.Equal(t, tc.want, users) @@ -181,8 +182,9 @@ func TestGetUser(t *testing.T) { } for _, tc := range tcs { t.Run(tc.name, func(t *testing.T) { + lg := zaptest.NewLogger(t) be, tmpPath := betesting.NewTmpBackend(t, time.Microsecond, 10) - abe := NewAuthBackend(zaptest.NewLogger(t), be) + abe := NewAuthBackend(lg, be) abe.CreateAuthBuckets() tx := abe.BatchTx() @@ -193,9 +195,9 @@ func TestGetUser(t *testing.T) { abe.ForceCommit() be.Close() - be2 := backend.NewDefaultBackend(tmpPath) + be2 := backend.NewDefaultBackend(lg, tmpPath) defer be2.Close() - abe2 := NewAuthBackend(zaptest.NewLogger(t), be2) + abe2 := NewAuthBackend(lg, be2) users := abe2.GetUser("alice") assert.Equal(t, tc.want, users) diff --git a/server/storage/schema/lease_test.go b/server/storage/schema/lease_test.go index 8ac4f163d853..6ec943a9a46e 100644 --- a/server/storage/schema/lease_test.go +++ b/server/storage/schema/lease_test.go @@ -23,6 +23,7 @@ import ( "go.etcd.io/etcd/server/v3/lease/leasepb" "go.etcd.io/etcd/server/v3/storage/backend" betesting "go.etcd.io/etcd/server/v3/storage/backend/testing" + "go.uber.org/zap/zaptest" ) func TestLeaseBackend(t *testing.T) { @@ -86,6 +87,7 @@ func TestLeaseBackend(t *testing.T) { for _, tc := range tcs { t.Run(tc.name, func(t *testing.T) { + lg := zaptest.NewLogger(t) be, tmpPath := betesting.NewTmpBackend(t, time.Microsecond, 10) tx := be.BatchTx() tx.Lock() @@ -96,7 +98,7 @@ func TestLeaseBackend(t *testing.T) { be.ForceCommit() be.Close() - be2 := backend.NewDefaultBackend(tmpPath) + be2 := backend.NewDefaultBackend(lg, tmpPath) defer be2.Close() leases := MustUnsafeGetAllLeases(be2.ReadTx()) diff --git a/server/storage/schema/schema_test.go b/server/storage/schema/schema_test.go index f0fb943b47bc..f3c0c4a7fe89 100644 --- a/server/storage/schema/schema_test.go +++ b/server/storage/schema/schema_test.go @@ -86,7 +86,7 @@ func TestValidate(t *testing.T) { lg := zap.NewNop() dataPath := setupBackendData(t, tc.version, tc.overrideKeys) - b := backend.NewDefaultBackend(dataPath) + b := backend.NewDefaultBackend(lg, dataPath) defer b.Close() err := Validate(lg, b.BatchTx()) if (err != nil) != tc.expectError { @@ -214,7 +214,7 @@ func TestMigrate(t *testing.T) { t.Fatal(err) } - b := backend.NewDefaultBackend(dataPath) + b := backend.NewDefaultBackend(lg, dataPath) defer b.Close() err = Migrate(lg, b.BatchTx(), walVersion, tc.targetVersion) @@ -258,7 +258,7 @@ func TestMigrateIsReversible(t *testing.T) { lg := zap.NewNop() dataPath := setupBackendData(t, tc.initialVersion, nil) - be := backend.NewDefaultBackend(dataPath) + be := backend.NewDefaultBackend(lg, dataPath) defer be.Close() tx := be.BatchTx() tx.Lock() diff --git a/server/storage/schema/version_test.go b/server/storage/schema/version_test.go index 60e7cf7760d0..bb5d43031c97 100644 --- a/server/storage/schema/version_test.go +++ b/server/storage/schema/version_test.go @@ -21,6 +21,7 @@ import ( "github.com/coreos/go-semver/semver" "github.com/stretchr/testify/assert" "go.etcd.io/bbolt" + "go.uber.org/zap/zaptest" "go.etcd.io/etcd/server/v3/storage/backend" "go.etcd.io/etcd/server/v3/storage/backend/testing" @@ -55,6 +56,7 @@ func TestVersion(t *testing.T) { } for _, tc := range tcs { t.Run(tc.version, func(t *testing.T) { + lg := zaptest.NewLogger(t) be, tmpPath := betesting.NewTmpBackend(t, time.Microsecond, 10) tx := be.BatchTx() if tx == nil { @@ -67,7 +69,7 @@ func TestVersion(t *testing.T) { be.ForceCommit() be.Close() - b := backend.NewDefaultBackend(tmpPath) + b := backend.NewDefaultBackend(lg, tmpPath) defer b.Close() v := UnsafeReadStorageVersion(b.BatchTx()) diff --git a/server/verify/verify.go b/server/verify/verify.go index f1de10b5da70..9402e5eb5ea6 100644 --- a/server/verify/verify.go +++ b/server/verify/verify.go @@ -69,7 +69,7 @@ func Verify(cfg Config) error { } }() - beConfig := backend.DefaultBackendConfig() + beConfig := backend.DefaultBackendConfig(lg) beConfig.Path = datadir.ToBackendFileName(cfg.DataDir) beConfig.Logger = cfg.Logger diff --git a/tests/e2e/utl_migrate_test.go b/tests/e2e/utl_migrate_test.go index 7623fc1b8ce8..9a7408665bbc 100644 --- a/tests/e2e/utl_migrate_test.go +++ b/tests/e2e/utl_migrate_test.go @@ -26,6 +26,7 @@ import ( "go.etcd.io/etcd/server/v3/storage/backend" "go.etcd.io/etcd/server/v3/storage/schema" "go.etcd.io/etcd/tests/v3/framework/e2e" + "go.uber.org/zap/zaptest" ) func TestEtctlutlMigrate(t *testing.T) { @@ -105,6 +106,7 @@ func TestEtctlutlMigrate(t *testing.T) { for _, tc := range tcs { t.Run(tc.name, func(t *testing.T) { e2e.BeforeTest(t) + lg := zaptest.NewLogger(t) if tc.binary != "" && !fileutil.Exist(tc.binary) { t.Skipf("%q does not exist", lastReleaseBinary) } @@ -154,7 +156,7 @@ func TestEtctlutlMigrate(t *testing.T) { } t.Log("etcdutl migrate...") - be := backend.NewDefaultBackend(dataDirPath + "/member/snap/db") + be := backend.NewDefaultBackend(lg, dataDirPath+"/member/snap/db") defer be.Close() ver := schema.ReadStorageVersion(be.ReadTx()) diff --git a/tests/integration/clientv3/maintenance_test.go b/tests/integration/clientv3/maintenance_test.go index 75b134413cce..f0e620e5dd42 100644 --- a/tests/integration/clientv3/maintenance_test.go +++ b/tests/integration/clientv3/maintenance_test.go @@ -190,6 +190,7 @@ func TestMaintenanceSnapshotErrorInflight(t *testing.T) { // will fail to read with corresponding context errors on inflight context cancel timeout. func testMaintenanceSnapshotErrorInflight(t *testing.T, snapshot func(context.Context, *clientv3.Client) (io.ReadCloser, error)) { integration2.BeforeTest(t) + lg := zaptest.NewLogger(t) clus := integration2.NewCluster(t, &integration2.ClusterConfig{Size: 1, UseBridge: true}) defer clus.Terminate(t) @@ -197,8 +198,8 @@ func testMaintenanceSnapshotErrorInflight(t *testing.T, snapshot func(context.Co // take about 1-second to read snapshot clus.Members[0].Stop(t) dpath := filepath.Join(clus.Members[0].DataDir, "member", "snap", "db") - b := backend.NewDefaultBackend(dpath) - s := mvcc.NewStore(zaptest.NewLogger(t), b, &lease.FakeLessor{}, mvcc.StoreConfig{CompactionBatchLimit: math.MaxInt32}) + b := backend.NewDefaultBackend(lg, dpath) + s := mvcc.NewStore(lg, b, &lease.FakeLessor{}, mvcc.StoreConfig{CompactionBatchLimit: math.MaxInt32}) rev := 100000 for i := 2; i <= rev; i++ { s.Put([]byte(fmt.Sprintf("%10d", i)), bytes.Repeat([]byte("a"), 1024), lease.NoLease) diff --git a/tests/integration/v3_alarm_test.go b/tests/integration/v3_alarm_test.go index 5b886d12654b..733b060f53a5 100644 --- a/tests/integration/v3_alarm_test.go +++ b/tests/integration/v3_alarm_test.go @@ -174,6 +174,7 @@ func TestV3AlarmDeactivate(t *testing.T) { func TestV3CorruptAlarm(t *testing.T) { integration.BeforeTest(t) + lg := zaptest.NewLogger(t) clus := integration.NewCluster(t, &integration.ClusterConfig{Size: 3, UseBridge: true}) defer clus.Terminate(t) @@ -192,8 +193,8 @@ func TestV3CorruptAlarm(t *testing.T) { // Corrupt member 0 by modifying backend offline. clus.Members[0].Stop(t) fp := filepath.Join(clus.Members[0].DataDir, "member", "snap", "db") - be := backend.NewDefaultBackend(fp) - s := mvcc.NewStore(zaptest.NewLogger(t), be, nil, mvcc.StoreConfig{}) + be := backend.NewDefaultBackend(lg, fp) + s := mvcc.NewStore(lg, be, nil, mvcc.StoreConfig{}) // NOTE: cluster_proxy mode with namespacing won't set 'k', but namespace/'k'. s.Put([]byte("abc"), []byte("def"), 0) s.Put([]byte("xyz"), []byte("123"), 0) @@ -258,6 +259,7 @@ func TestV3CorruptAlarm(t *testing.T) { func TestV3CorruptAlarmWithLeaseCorrupted(t *testing.T) { integration.BeforeTest(t) + lg := zaptest.NewLogger(t) clus := integration.NewCluster(t, &integration.ClusterConfig{ CorruptCheckTime: time.Second, Size: 3, @@ -299,9 +301,8 @@ func TestV3CorruptAlarmWithLeaseCorrupted(t *testing.T) { // Corrupt member 2 by modifying backend lease bucket offline. clus.Members[2].Stop(t) fp := filepath.Join(clus.Members[2].DataDir, "member", "snap", "db") - bcfg := backend.DefaultBackendConfig() + bcfg := backend.DefaultBackendConfig(lg) bcfg.Path = fp - bcfg.Logger = zaptest.NewLogger(t) be := backend.New(bcfg) olpb := leasepb.Lease{ID: int64(1), TTL: 60} diff --git a/tools/benchmark/cmd/mvcc.go b/tools/benchmark/cmd/mvcc.go index ebb134e0e0c2..1d51c523710d 100644 --- a/tools/benchmark/cmd/mvcc.go +++ b/tools/benchmark/cmd/mvcc.go @@ -35,7 +35,7 @@ var ( ) func initMVCC() { - bcfg := backend.DefaultBackendConfig() + bcfg := backend.DefaultBackendConfig(zap.NewNop()) bcfg.Path, bcfg.BatchInterval, bcfg.BatchLimit = "mvcc-bench", time.Duration(batchInterval)*time.Millisecond, batchLimit be := backend.New(bcfg) s = mvcc.NewStore(zap.NewExample(), be, &lease.FakeLessor{}, mvcc.StoreConfig{}) diff --git a/tools/etcd-dump-db/backend.go b/tools/etcd-dump-db/backend.go index 0be477b4ec11..6205d5597f82 100644 --- a/tools/etcd-dump-db/backend.go +++ b/tools/etcd-dump-db/backend.go @@ -21,6 +21,7 @@ import ( "go.etcd.io/etcd/api/v3/authpb" "go.etcd.io/etcd/server/v3/storage/schema" + "go.uber.org/zap" "go.etcd.io/etcd/api/v3/mvccpb" "go.etcd.io/etcd/server/v3/lease/leasepb" @@ -176,7 +177,7 @@ func iterateBucket(dbPath, bucket string, limit uint64, decode bool) (err error) } func getHash(dbPath string) (hash uint32, err error) { - b := backend.NewDefaultBackend(dbPath) + b := backend.NewDefaultBackend(zap.NewNop(), dbPath) return b.Hash(schema.DefaultIgnores) } From 5b84b30fce6c82ae48db8a7a801ae898b48bbb87 Mon Sep 17 00:00:00 2001 From: ls-2018 Date: Wed, 6 Apr 2022 17:38:46 +0800 Subject: [PATCH 249/258] fix unexpose todo Signed-off-by: ls-2018 --- server/lease/lessor.go | 7 +++---- server/lease/lessor_test.go | 12 ++++++------ 2 files changed, 9 insertions(+), 10 deletions(-) diff --git a/server/lease/lessor.go b/server/lease/lessor.go index 0a77fd669da4..cb6f0d6ec805 100644 --- a/server/lease/lessor.go +++ b/server/lease/lessor.go @@ -744,7 +744,7 @@ func (le *lessor) scheduleCheckpointIfNeeded(lease *Lease) { return } - if lease.RemainingTTL() > int64(le.checkpointInterval.Seconds()) { + if lease.getRemainingTTL() > int64(le.checkpointInterval.Seconds()) { if le.lg != nil { le.lg.Debug("Scheduling lease checkpoint", zap.Int64("leaseID", int64(lease.ID)), @@ -856,8 +856,7 @@ func (l *Lease) TTL() int64 { } // RemainingTTL returns the last checkpointed remaining TTL of the lease. -// TODO(jpbetz): do not expose this utility method -func (l *Lease) RemainingTTL() int64 { +func (l *Lease) getRemainingTTL() int64 { if l.remainingTTL > 0 { return l.remainingTTL } @@ -866,7 +865,7 @@ func (l *Lease) RemainingTTL() int64 { // refresh refreshes the expiry of the lease. func (l *Lease) refresh(extend time.Duration) { - newExpiry := time.Now().Add(extend + time.Duration(l.RemainingTTL())*time.Second) + newExpiry := time.Now().Add(extend + time.Duration(l.getRemainingTTL())*time.Second) l.expiryMu.Lock() defer l.expiryMu.Unlock() l.expiry = newExpiry diff --git a/server/lease/lessor_test.go b/server/lease/lessor_test.go index 1879549f34b7..58a36e612323 100644 --- a/server/lease/lessor_test.go +++ b/server/lease/lessor_test.go @@ -634,18 +634,18 @@ func TestLessorCheckpointPersistenceAfterRestart(t *testing.T) { if err != nil { t.Fatal(err) } - if l.RemainingTTL() != ttl { - t.Errorf("remainingTTL() = %d, expected: %d", l.RemainingTTL(), ttl) + if l.getRemainingTTL() != ttl { + t.Errorf("getRemainingTTL() = %d, expected: %d", l.getRemainingTTL(), ttl) } le.Checkpoint(2, checkpointTTL) - if l.RemainingTTL() != checkpointTTL { - t.Errorf("remainingTTL() = %d, expected: %d", l.RemainingTTL(), checkpointTTL) + if l.getRemainingTTL() != checkpointTTL { + t.Errorf("getRemainingTTL() = %d, expected: %d", l.getRemainingTTL(), checkpointTTL) } le.Stop() le2 := newLessor(lg, be, clusterLatest(), cfg) l = le2.Lookup(2) - if l.RemainingTTL() != tc.expectRemainingTTL { - t.Errorf("remainingTTL() = %d, expected: %d", l.RemainingTTL(), tc.expectRemainingTTL) + if l.getRemainingTTL() != tc.expectRemainingTTL { + t.Errorf("getRemainingTTL() = %d, expected: %d", l.getRemainingTTL(), tc.expectRemainingTTL) } }) } From f0f77fc14e3bd4d94a953b490e810a06ef36695a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Manuel=20R=C3=BCger?= Date: Wed, 6 Apr 2022 19:03:22 +0200 Subject: [PATCH 250/258] go.mod: Bump prometheus/client_golang to v1.12.1 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Manuel Rüger --- client/v3/go.mod | 14 +-- client/v3/go.sum | 275 +++++++++++++++++++++++++++++++++++++++++++++-- etcdctl/go.mod | 10 +- etcdctl/go.sum | 274 ++++++++++++++++++++++++++++++++++++++++++++-- etcdutl/go.mod | 10 +- etcdutl/go.sum | 275 +++++++++++++++++++++++++++++++++++++++++++++-- go.mod | 11 +- go.sum | 23 ++-- server/go.mod | 10 +- server/go.sum | 275 +++++++++++++++++++++++++++++++++++++++++++++-- tests/go.mod | 10 +- tests/go.sum | 275 +++++++++++++++++++++++++++++++++++++++++++++-- 12 files changed, 1378 insertions(+), 84 deletions(-) diff --git a/client/v3/go.mod b/client/v3/go.mod index f8b11edbd926..02acfa349a77 100644 --- a/client/v3/go.mod +++ b/client/v3/go.mod @@ -5,7 +5,7 @@ go 1.17 require ( github.com/dustin/go-humanize v1.0.0 github.com/grpc-ecosystem/go-grpc-prometheus v1.2.0 - github.com/prometheus/client_golang v1.11.0 + github.com/prometheus/client_golang v1.12.1 github.com/stretchr/testify v1.7.0 go.etcd.io/etcd/api/v3 v3.6.0-alpha.0 go.etcd.io/etcd/client/pkg/v3 v3.6.0-alpha.0 @@ -16,7 +16,7 @@ require ( require ( github.com/beorn7/perks v1.0.1 // indirect - github.com/cespare/xxhash/v2 v2.1.1 // indirect + github.com/cespare/xxhash/v2 v2.1.2 // indirect github.com/coreos/go-semver v0.3.0 // indirect github.com/coreos/go-systemd/v22 v22.3.2 // indirect github.com/davecgh/go-spew v1.1.1 // indirect @@ -25,13 +25,13 @@ require ( github.com/matttproud/golang_protobuf_extensions v1.0.1 // indirect github.com/pmezard/go-difflib v1.0.0 // indirect github.com/prometheus/client_model v0.2.0 // indirect - github.com/prometheus/common v0.26.0 // indirect - github.com/prometheus/procfs v0.6.0 // indirect + github.com/prometheus/common v0.32.1 // indirect + github.com/prometheus/procfs v0.7.3 // indirect go.uber.org/atomic v1.7.0 // indirect go.uber.org/multierr v1.6.0 // indirect - golang.org/x/net v0.0.0-20210405180319-a5a99cb37ef4 // indirect - golang.org/x/sys v0.0.0-20210603125802-9665404d3644 // indirect - golang.org/x/text v0.3.5 // indirect + golang.org/x/net v0.0.0-20210525063256-abc453219eb5 // indirect + golang.org/x/sys v0.0.0-20220114195835-da31bd327af9 // indirect + golang.org/x/text v0.3.6 // indirect google.golang.org/genproto v0.0.0-20211118181313-81c1377c94b1 // indirect google.golang.org/protobuf v1.27.1 // indirect gopkg.in/yaml.v2 v2.4.0 // indirect diff --git a/client/v3/go.sum b/client/v3/go.sum index fe36400df4b4..bab2b7f33c97 100644 --- a/client/v3/go.sum +++ b/client/v3/go.sum @@ -1,6 +1,38 @@ cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= cloud.google.com/go v0.34.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= +cloud.google.com/go v0.38.0/go.mod h1:990N+gfupTy94rShfmMCWGDn0LpTmnzTp2qbd1dvSRU= +cloud.google.com/go v0.44.1/go.mod h1:iSa0KzasP4Uvy3f1mN/7PiObzGgflwredwwASm/v6AU= +cloud.google.com/go v0.44.2/go.mod h1:60680Gw3Yr4ikxnPRS/oxxkBccT6SA1yMk63TGekxKY= +cloud.google.com/go v0.45.1/go.mod h1:RpBamKRgapWJb87xiFSdk4g1CME7QZg3uwTez+TSTjc= +cloud.google.com/go v0.46.3/go.mod h1:a6bKKbmY7er1mI7TEI4lsAkts/mkhTSZK8w33B4RAg0= +cloud.google.com/go v0.50.0/go.mod h1:r9sluTvynVuxRIOHXQEHMFffphuXHOMZMycpNR5e6To= +cloud.google.com/go v0.52.0/go.mod h1:pXajvRH/6o3+F9jDHZWQ5PbGhn+o8w9qiu/CffaVdO4= +cloud.google.com/go v0.53.0/go.mod h1:fp/UouUEsRkN6ryDKNW/Upv/JBKnv6WDthjR6+vze6M= +cloud.google.com/go v0.54.0/go.mod h1:1rq2OEkV3YMf6n/9ZvGWI3GWw0VoqH/1x2nd8Is/bPc= +cloud.google.com/go v0.56.0/go.mod h1:jr7tqZxxKOVYizybht9+26Z/gUq7tiRzu+ACVAMbKVk= +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.65.0/go.mod h1:O5N8zS7uWy9vkA9vayVHs65eM1ubvY4h553ofrNHObY= +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.4.0/go.mod h1:S8dzgnTigyfTmLBfrtrhyYhwRxG72rYxvftPBK2Dvzc= +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.8.0/go.mod h1:J5hqkt3O0uAFnINi6JXValWIb1v0goeZM77hZzJN/fQ= +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/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.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/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.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.10.0/go.mod h1:FLPqc6j+Ki4BU591ie1oL6qBQGu2Bl/tZ9ullr3+Kg0= +dmitri.shuralyov.com/gpu/mtl v0.0.0-20190408044501-666a987793e9/go.mod h1:H6x//7gZCb22OMCxBHrMx7a5I7Hp++hsVxbQ4BYO7hU= github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= +github.com/BurntSushi/xgb v0.0.0-20160522181843-27f122750802/go.mod h1:IVnqGOEym/WlBOVXweHU+Q+/VP0lqqI8lqeDx9IjBqo= github.com/OneOfOne/xxhash v1.2.2/go.mod h1:HSdplMjZKSmBqAxg5vPj2TmRDmfkzw+cTzAElWljhcU= github.com/alecthomas/template v0.0.0-20160405071501-a0175ee3bccc/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc= github.com/alecthomas/template v0.0.0-20190718012654-fb15b899a751/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc= @@ -15,8 +47,12 @@ github.com/beorn7/perks v1.0.1/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6r github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU= github.com/cespare/xxhash v1.1.0 h1:a6HrQnmkObjyL+Gs60czilIUGqrzKutQD6XZog3p+ko= github.com/cespare/xxhash v1.1.0/go.mod h1:XrSqR1VqqWfGrhpAt58auRo0WTKS1nRRg3ghfAqPWnc= -github.com/cespare/xxhash/v2 v2.1.1 h1:6MnRN8NT7+YBpUIWxHtefFZOKTAPgGjpQSxqLNn0+qY= github.com/cespare/xxhash/v2 v2.1.1/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= +github.com/cespare/xxhash/v2 v2.1.2 h1:YRXhKfTDauu4ajMg1TPgFO5jnlC2HCbmLXMcTG5cbYE= +github.com/cespare/xxhash/v2 v2.1.2/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= +github.com/chzyer/logex v1.1.10/go.mod h1:+Ywpsq7O8HXn0nuIou7OrIPyXbp3wmkHB+jjWRnGsAI= +github.com/chzyer/readline v0.0.0-20180603132655-2972be24d48e/go.mod h1:nSuG5e5PlCu98SY8svDHJxuZscDgtXS6KTTbou5AhLI= +github.com/chzyer/test v0.0.0-20180213035817-a1ea475d72b1/go.mod h1:Q3SI9o4m/ZMnBNeIyt5eFwwo7qiLfzFZmjNmxjkiQlU= github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw= github.com/cncf/udpa/go v0.0.0-20191209042840-269d4d468f6f/go.mod h1:M8M6+tZqaGXZJjfX53e64911xZQV5JYwmTeXPW+k8Sc= github.com/cncf/udpa/go v0.0.0-20201120205902-5459f2c99403/go.mod h1:WmhPx2Nbnhtbo57+VJT5O0JRkEi1Wbu0z5j0R8u5Hbk= @@ -39,6 +75,9 @@ github.com/envoyproxy/go-control-plane v0.9.9-0.20210512163311-63b5d3c536b0/go.m github.com/envoyproxy/go-control-plane v0.9.10-0.20210907150352-cf90f659a021/go.mod h1:AFq3mo9L8Lqqiid3OhADV3RfLJnjiw63cSpi+fDTRC0= github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c= github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04= +github.com/go-gl/glfw v0.0.0-20190409004039-e6da0acd62b1/go.mod h1:vR7hzQXu2zJy9AVAgeJqvqgH9Q5CA+iKCZ2gyEVpxRU= +github.com/go-gl/glfw/v3.3/glfw v0.0.0-20191125211704-12ad95a8df72/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8= +github.com/go-gl/glfw/v3.3/glfw v0.0.0-20200222043503-6f7a984d4dc4/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8= github.com/go-kit/kit v0.8.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as= github.com/go-kit/kit v0.9.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as= github.com/go-kit/log v0.1.0/go.mod h1:zbhenjAZHb184qTLMA9ZjW7ThYL0H2mk7Q6pNt4vbaY= @@ -51,11 +90,22 @@ github.com/gogo/protobuf v1.1.1/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7a github.com/gogo/protobuf v1.3.2 h1:Ov1cvc58UF3b5XjBnZv7+opcTcQFZebYjWzi34vdm4Q= github.com/gogo/protobuf v1.3.2/go.mod h1:P1XiOD3dCwIKUDQYPy72D8LYyHL2YPYrpS2s69NZV8Q= github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q= +github.com/golang/groupcache v0.0.0-20190702054246-869f871628b6/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= +github.com/golang/groupcache v0.0.0-20191227052852-215e87163ea7/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= +github.com/golang/groupcache v0.0.0-20200121045136-8c9f03a8e57e/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= github.com/golang/mock v1.1.1/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A= +github.com/golang/mock v1.2.0/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A= +github.com/golang/mock v1.3.1/go.mod h1:sBzyDLLjw3U8JLTeZvSv8jJB+tU5PVekmnlKIyFUx0Y= +github.com/golang/mock v1.4.0/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.4/go.mod h1:l3mdAwkq5BuhzHwde/uurv3sEJeZMXNpwsxVWU71h+4= github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= github.com/golang/protobuf v1.3.1/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= github.com/golang/protobuf v1.3.2/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= github.com/golang/protobuf v1.3.3/go.mod h1:vzj43D7+SQXF/4pzW/hwtAqwc6iTitCiVSaWz5lYuqw= +github.com/golang/protobuf v1.3.4/go.mod h1:vzj43D7+SQXF/4pzW/hwtAqwc6iTitCiVSaWz5lYuqw= +github.com/golang/protobuf v1.3.5/go.mod h1:6O5/vntMXwX2lRkT1hjjk0nAC1IDOTvTlVgjlRvqsdk= github.com/golang/protobuf v1.4.0-rc.1/go.mod h1:ceaxUfeHdC40wWswd/P6IGgMaK3YpKi5j83Wpe3EHw8= github.com/golang/protobuf v1.4.0-rc.1.0.20200221234624-67d41d38c208/go.mod h1:xKAWHe0F5eneWXFV3EuXVDTCmh+JuBKY0li0aMyXATA= github.com/golang/protobuf v1.4.0-rc.2/go.mod h1:LlEzMj4AhA7rCAGe4KMBDvJI+AwstrUpVNzEA03Pprs= @@ -67,23 +117,45 @@ github.com/golang/protobuf v1.4.3/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk= 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/google/btree v0.0.0-20180813153112-4030bb1f1f0c/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ= +github.com/google/btree v1.0.0/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ= github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M= github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= +github.com/google/go-cmp v0.4.1/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.4/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.5 h1:Khx7svrCpmxxtHBq5j2mp/xVjsi8hQMfNLvJFAlrGgU= github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= +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/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-20191218002539-d4f498aebedc/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= +github.com/google/pprof v0.0.0-20200212024743-f11f1df84d12/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-20200708004538-1a94d8640e99/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= +github.com/google/renameio v0.1.0/go.mod h1:KWCgfxg9yswjAJkECMjeO8J8rahYeXnNhOm40UhjYkI= github.com/google/uuid v1.1.2/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= +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/grpc-ecosystem/go-grpc-prometheus v1.2.0 h1:Ovs26xHkKqVztRpIrF/92BcuyuQ/YW4NSIpoGtfXNho= github.com/grpc-ecosystem/go-grpc-prometheus v1.2.0/go.mod h1:8NvIoxWQoOIhqOTXgfV/d3M/q6VIi02HzZEHgUlZvzk= github.com/grpc-ecosystem/grpc-gateway v1.16.0/go.mod h1:BDjrQk3hbvj6Nolgz8mAMFbcEtjT1g+wF4CSlocrBnw= +github.com/hashicorp/golang-lru v0.5.0/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8= +github.com/hashicorp/golang-lru v0.5.1/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8= +github.com/ianlancetaylor/demangle v0.0.0-20181102032728-5e5cf60278f6/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc= 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.10/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4= github.com/json-iterator/go v1.1.11/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4= +github.com/json-iterator/go v1.1.12/go.mod h1:e30LSqwooZae/UwlEbR2852Gd8hjQvJoHmT4TnhNGBo= +github.com/jstemmer/go-junit-report v0.0.0-20190106144839-af01ea7f8024/go.mod h1:6v2b51hI/fHJwM22ozAgKL4VKDeJcHhJFhtBdhmNjmU= +github.com/jstemmer/go-junit-report v0.9.1/go.mod h1:Brl9GWCQeLvo8nXZwPNNblvFj/XSXhF0NWZEnDohbsk= github.com/julienschmidt/httprouter v1.2.0/go.mod h1:SYymIcj16QtmaHHD7aYtjjsJG7VTCxuUUipMqKk8s4w= github.com/julienschmidt/httprouter v1.3.0/go.mod h1:JR6WtHb+2LUe8TCKY3cZOxFyyO8IZAc4RVcycCCAKdM= github.com/kisielk/errcheck v1.5.0/go.mod h1:pFxgyoBC7bSaBwPgfKdkLd5X25qrDl4LWUI2bnpBCr8= @@ -102,6 +174,7 @@ github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJ github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= github.com/modern-go/reflect2 v0.0.0-20180701023420-4b7aa43c6742/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0= github.com/modern-go/reflect2 v1.0.1/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0= +github.com/modern-go/reflect2 v1.0.2/go.mod h1:yWuevngMOJpCy52FWWMvUC8ws7m/LJsjYzDa0/r8luk= github.com/mwitkow/go-conntrack v0.0.0-20161129095857-cc309e4a2223/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U= github.com/mwitkow/go-conntrack v0.0.0-20190716064945-2f068394615f/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U= github.com/pkg/errors v0.8.0/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= @@ -113,8 +186,9 @@ github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZN github.com/prometheus/client_golang v0.9.1/go.mod h1:7SWBe2y4D6OKWSNQJUaRYU/AaXPKyh/dDVn+NZz0KFw= github.com/prometheus/client_golang v1.0.0/go.mod h1:db9x61etRT2tGnBNRi70OPL5FsnadC4Ky3P0J6CfImo= github.com/prometheus/client_golang v1.7.1/go.mod h1:PY5Wy2awLA44sXw4AOSfFBetzPP4j5+D6mVACh+pe2M= -github.com/prometheus/client_golang v1.11.0 h1:HNkLOAEQMIDv/K+04rukrLx6ch7msSRwf3/SASFAGtQ= github.com/prometheus/client_golang v1.11.0/go.mod h1:Z6t4BnS23TR94PD6BsDNk8yVqroYurpAkEiz0P2BEV0= +github.com/prometheus/client_golang v1.12.1 h1:ZiaPsmm9uiBeaSMRznKsCDNtPCS0T3JVDGF+06gjBzk= +github.com/prometheus/client_golang v1.12.1/go.mod h1:3Z9XVyYiZYEO+YQWt3RD2R3jrbd179Rt297l4aS6nDY= github.com/prometheus/client_model v0.0.0-20180712105110-5c3871d89910/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo= github.com/prometheus/client_model v0.0.0-20190129233127-fd36f4220a90/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= @@ -122,14 +196,17 @@ github.com/prometheus/client_model v0.2.0 h1:uq5h0d+GuxiXLJLNABMgp2qUWDPiLvgCzz2 github.com/prometheus/client_model v0.2.0/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= github.com/prometheus/common v0.4.1/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y86RQel1bk4= github.com/prometheus/common v0.10.0/go.mod h1:Tlit/dnDKsSWFlCLTWaA1cyBgKHSMdTB80sz/V91rCo= -github.com/prometheus/common v0.26.0 h1:iMAkS2TDoNWnKM+Kopnx/8tnEStIfpYA0ur0xQzzhMQ= github.com/prometheus/common v0.26.0/go.mod h1:M7rCNAaPfAosfx8veZJCuw84e35h3Cfd9VFqTh1DIvc= +github.com/prometheus/common v0.32.1 h1:hWIdL3N2HoUx3B8j3YN9mWor0qhY/NlEKZEaXxuIRh4= +github.com/prometheus/common v0.32.1/go.mod h1:vu+V0TpY+O6vW9J44gczi3Ap/oXXR10b+M/gUGO4Hls= github.com/prometheus/procfs v0.0.0-20181005140218-185b4288413d/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk= github.com/prometheus/procfs v0.0.2/go.mod h1:TjEm7ze935MbeOT/UhFTIMYKhuLP4wbCsTZCD3I8kEA= github.com/prometheus/procfs v0.1.3/go.mod h1:lV6e/gmhEcM9IjHGsFOCxxuZ+z1YqCvr4OA4YeYWdaU= -github.com/prometheus/procfs v0.6.0 h1:mxy4L2jP6qMonqmq+aTtOx1ifVWUgG/TAmntgbh3xv4= github.com/prometheus/procfs v0.6.0/go.mod h1:cz+aTbrPOrUb4q7XlbU9ygM+/jj0fzG6c1xBZuNvfVA= +github.com/prometheus/procfs v0.7.3 h1:4jVXhlkAyzOScmCkXBTOLRLTz8EeU+eyjrwB/EPq0VU= +github.com/prometheus/procfs v0.7.3/go.mod h1:cz+aTbrPOrUb4q7XlbU9ygM+/jj0fzG6c1xBZuNvfVA= github.com/rogpeppe/fastuuid v1.2.0/go.mod h1:jVj6XXZzXRy/MSR5jhDC/2q6DgLz+nrA6LYCDYWNEvQ= +github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4= github.com/sirupsen/logrus v1.2.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPxbbu5VWo= github.com/sirupsen/logrus v1.4.2/go.mod h1:tLMulIdttU9McNUspp0xgXVQah82FyeX6MwdIuYE2rE= github.com/sirupsen/logrus v1.6.0/go.mod h1:7uNnSEd1DgxDLC74fIahvMZmmYsHGZGEOFrfsX/uA88= @@ -142,8 +219,15 @@ github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81P github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA= github.com/stretchr/testify v1.7.0 h1:nwc3DEeHmmLAfoZucVR881uASk0Mfjw8xYJ99tb5CcY= github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= +github.com/yuin/goldmark v1.1.25/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= +github.com/yuin/goldmark v1.1.32/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= +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.2/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.opentelemetry.io/proto/otlp v0.7.0/go.mod h1:PqfVotwruBrMGOCsRd/89rSnXhoiJIqeYNgFYFoEGnI= go.uber.org/atomic v1.7.0 h1:ADUqmZGgLDDfbSL9ZmPxKTybcoEYHgpYfELNoN+7hsw= go.uber.org/atomic v1.7.0/go.mod h1:fEN4uk6kAWBTFdckzkM89CLk9XfWZrxpCo0nPH17wJc= @@ -153,12 +237,38 @@ go.uber.org/zap v1.17.0 h1:MTjgFu6ZLKvY6Pvaqk97GlxNBuMpV4Hy/3P6tRGlI2U= go.uber.org/zap v1.17.0/go.mod h1:MXVU+bhUf/A7Xi2HNOnopQOrmycQ5Ih87HtOu4q5SSo= golang.org/x/crypto v0.0.0-20180904163835-0709b304e793/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= +golang.org/x/crypto v0.0.0-20190510104115-cbcb75029529/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= +golang.org/x/crypto v0.0.0-20190605123033-f99c8df09eb5/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= +golang.org/x/exp v0.0.0-20190306152737-a1d7652674e8/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= +golang.org/x/exp v0.0.0-20190510132918-efd6b22b2522/go.mod h1:ZjyILWgesfNpC6sMxTJOJm9Kp84zZh5NQWvqDGG3Qr8= +golang.org/x/exp v0.0.0-20190829153037-c13cbed26979/go.mod h1:86+5VVa7VpoJ4kLfm080zCjGlMRFzhUhsZKEZO7MGek= +golang.org/x/exp v0.0.0-20191030013958-a1ab85dbe136/go.mod h1:JXzH8nQsPlswgeRAPE3MuO9GYsAcnJvJ4vnMwN/5qkY= +golang.org/x/exp v0.0.0-20191129062945-2f5052295587/go.mod h1:2RIsYlXP63K8oxa1u096TMicItID8zy7Y6sNkU49FU4= +golang.org/x/exp v0.0.0-20191227195350-da58074b4299/go.mod h1:2RIsYlXP63K8oxa1u096TMicItID8zy7Y6sNkU49FU4= +golang.org/x/exp v0.0.0-20200119233911-0405dc783f0a/go.mod h1:2RIsYlXP63K8oxa1u096TMicItID8zy7Y6sNkU49FU4= +golang.org/x/exp v0.0.0-20200207192155-f17229e696bd/go.mod h1:J/WKrq2StrnmMY6+EHIKF9dgMWnmCNThgcyBT1FY9mM= +golang.org/x/exp v0.0.0-20200224162631-6cc2880d07d6/go.mod h1:3jZMyOhIsHpP37uCMkUooju7aAi5cS1Q23tOzKc+0MU= +golang.org/x/image v0.0.0-20190227222117-0694c2d4d067/go.mod h1:kZ7UVZpmo3dzQBMxlp+ypCbDeSB+sBbTgSJuh5dn5js= +golang.org/x/image v0.0.0-20190802002840-cff245a6509b/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0= golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE= golang.org/x/lint v0.0.0-20190227174305-5b3e6a55c961/go.mod h1:wehouNa3lNwaWXcvxsM5YxQ5yQlVC4a0KAMCusXpPoU= +golang.org/x/lint v0.0.0-20190301231843-5614ed5bae6f/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE= golang.org/x/lint v0.0.0-20190313153728-d0100b6bd8b3/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= +golang.org/x/lint v0.0.0-20190409202823-959b441ac422/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= +golang.org/x/lint v0.0.0-20190909230951-414d861bb4ac/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= +golang.org/x/lint v0.0.0-20190930215403-16217165b5de/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= +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-20200302205851-738671d3881b/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-20190719004257-d2bd2a29d028/go.mod h1:E/iHnbuqvinMTCcRqshq8CkpyQDoeVncDDYHnLhea+o= +golang.org/x/mod v0.0.0-20190513183733-4bf6d317e70e/go.mod h1:mXi4GBBbnImb6dmsKGUJ2LatrhH/nqhxcFungHvyanc= +golang.org/x/mod v0.1.0/go.mod h1:0QHyrYULN0/3qlju5TqG8bIK38QM8yzMo5ekMj3DlcY= +golang.org/x/mod v0.1.1-0.20191105210325-c90efee705ee/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.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= @@ -168,73 +278,213 @@ golang.org/x/net v0.0.0-20190108225652-1e06a53dbb7e/go.mod h1:mL1N/T3taQHkDXs73r golang.org/x/net v0.0.0-20190213061140-3a22650c66bd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= +golang.org/x/net v0.0.0-20190501004415-9ce7a6920f09/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= +golang.org/x/net v0.0.0-20190503192946-f4e77d36d62c/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= +golang.org/x/net v0.0.0-20190603091049-60506f45cf65/go.mod h1:HSz+uSET+XFnRR8LxR5pz3Of3rY3CfYBVs4xY44aLks= golang.org/x/net v0.0.0-20190613194153-d28f0bde5980/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20190628185345-da137c7871d7/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20190724013045-ca1201d0de80/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20191209160850-c0dbc17a3553/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20200114155413-6afb5195e5aa/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20200202094626-16171245cfb2/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20200222125558-5a598a2470a0/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20200226121028-0de0cce0169b/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20200301022130-244492dfa37a/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20200324143707-d3edc9973b7e/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= +golang.org/x/net v0.0.0-20200501053045-e0ff5e5a1de5/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= +golang.org/x/net v0.0.0-20200506145744-7e3656a0809f/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= +golang.org/x/net v0.0.0-20200513185701-a91f0712d120/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= +golang.org/x/net v0.0.0-20200520182314-0ba52f642ac2/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= golang.org/x/net v0.0.0-20200625001655-4c5254603344/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-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= -golang.org/x/net v0.0.0-20210405180319-a5a99cb37ef4 h1:4nGaVu0QrbjT/AK2PRLuQfQuh6DJve+pELhqTdAj3x0= golang.org/x/net v0.0.0-20210405180319-a5a99cb37ef4/go.mod h1:p54w0d4576C0XHj96bSt6lcn1PtDYWL6XObtHCRCNQM= +golang.org/x/net v0.0.0-20210525063256-abc453219eb5 h1:wjuX4b5yYQnEQHzd+CBcrcC6OVR2J1CN6mUy0oSxIPo= +golang.org/x/net v0.0.0-20210525063256-abc453219eb5/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= 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-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-20200107190931-bf48bf16ab8d/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= +golang.org/x/oauth2 v0.0.0-20210514164344-f6687ab2804c/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= 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-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20190227155943-e225da77a7e6/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20200317015054-43a5402ce75a/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20200625203802-6e8e738ad208/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/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-20181116152217-5ac8a444bdc5/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20190312061237-fead79001313/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190422165155-953cdadca894/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190502145724-3ef323f4f1fd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190507160741-ecd444e8653b/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190606165138-5da285871e9c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190624142023-c5567b49c5d0/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190726091711-fc99dfbffb4e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20191001151750-bb3f8db39f24/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20191204072324-ce4227a45e2e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20191228213918-04cbcbbfeed8/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200106162015-b016eb3dc98e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200113162924-86b910548bc1/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200122134326-e047566fdf82/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200202164722-d101bd2416d5/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200212091648-12a6c2dcc1e4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200223170610-d5e6a3e2c0ae/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200302150141-5c8b2ff67527/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200331124033-c3d80250170d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200501052902-10377860bb8e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200511232937-7e40ca221e25/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200515095857-1151b9dac4a9/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200523222454-059865788121/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-20200803210538-64077c9b5642/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-20210124154548-22da62e12c0c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210330210617-4fbd30eecc44/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210423082822-04245dca01da/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-20210603081109-ebe580a85c40/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20210603125802-9665404d3644 h1:CA1DEQ4NdKphKeL70tvsWNdT5oFh1lOjihRcEDROi0I= golang.org/x/sys v0.0.0-20210603125802-9665404d3644/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20220114195835-da31bd327af9 h1:XfKQ4OlFl8okEOr5UvAqFRVj8pY/4yfcXrddB8qAbU0= +golang.org/x/sys v0.0.0-20220114195835-da31bd327af9/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= +golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= +golang.org/x/text v0.3.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.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= -golang.org/x/text v0.3.5 h1:i6eZZ+zk0SOf0xgBpEpPD18qWcJda6q1sxt3S0kzyUQ= golang.org/x/text v0.3.5/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= +golang.org/x/text v0.3.6 h1:aRYxNxv6iGQlyVaZmk6ZgYEDa+Jg18DxebPSrd6bg1M= +golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= +golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= +golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= +golang.org/x/time v0.0.0-20191024005414-555d28b269f0/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-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-20190311212946-11955173bddd/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= +golang.org/x/tools v0.0.0-20190312151545-0bb0c0a6e846/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= +golang.org/x/tools v0.0.0-20190312170243-e65039ee4138/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= +golang.org/x/tools v0.0.0-20190425150028-36563e24a262/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q= +golang.org/x/tools v0.0.0-20190506145303-2d16b83fe98c/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q= golang.org/x/tools v0.0.0-20190524140312-2c0ae7006135/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q= +golang.org/x/tools v0.0.0-20190606124116-d0a3d012864b/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc= +golang.org/x/tools v0.0.0-20190621195816-6e04913cbbac/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc= +golang.org/x/tools v0.0.0-20190628153133-6cdbf07be9d0/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc= +golang.org/x/tools v0.0.0-20190816200558-6889da9d5479/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-20190911174233-4f2ddba30aff/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-20191012152004-8de300cfc20a/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-20191113191852-77e3bb0ad9e7/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-20191115202509-3a792d9c32b2/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-20191125144606-a911d9008d1f/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-20191130070609-6e064ea0cf2d/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-20191216173652-a0e659d51361/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= +golang.org/x/tools v0.0.0-20191227053925-7b8e75db28f4/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= +golang.org/x/tools v0.0.0-20200117161641-43d50277825c/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= +golang.org/x/tools v0.0.0-20200122220014-bf1340f18c4a/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= +golang.org/x/tools v0.0.0-20200130002326-2f3ba24bd6e7/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= +golang.org/x/tools v0.0.0-20200204074204-1cc6d1ef6c74/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= +golang.org/x/tools v0.0.0-20200207183749-b753a1ba74fa/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= +golang.org/x/tools v0.0.0-20200212150539-ea181f53ac56/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= +golang.org/x/tools v0.0.0-20200224181240-023911ca70b2/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= +golang.org/x/tools v0.0.0-20200227222343-706bc42d1f0d/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= +golang.org/x/tools v0.0.0-20200304193943-95d2e580d8eb/go.mod h1:o4KQGtdN14AW+yjsvvwRTJJuXz8XRtIHtEnmAXLyFUw= +golang.org/x/tools v0.0.0-20200312045724-11d5b4c81c7d/go.mod h1:o4KQGtdN14AW+yjsvvwRTJJuXz8XRtIHtEnmAXLyFUw= +golang.org/x/tools v0.0.0-20200331025713-a30bf2db82d4/go.mod h1:Sl4aGygMT6LrqrWclx+PTx3U+LnKx/seiNR+3G19Ar8= +golang.org/x/tools v0.0.0-20200501065659-ab2804fb9c9d/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= +golang.org/x/tools v0.0.0-20200512131952-2bc93b1c0c88/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= +golang.org/x/tools v0.0.0-20200515010526-7d3b6ebf133d/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= +golang.org/x/tools v0.0.0-20200618134242-20370b0cb4b2/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= golang.org/x/tools v0.0.0-20200619180055-7c47624df98f/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= +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-20200825202427-b303f430e36d/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA= golang.org/x/tools v0.0.0-20210106214847-113979e3529a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= 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-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1 h1:go1bK/D/BFZV2I8cIQd1NKEZ+0owSTG1fDTci4IqFcE= golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +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.8.0/go.mod h1:o4eAsZoiT+ibD93RtjEohWalFOjRDx6CVaqeizhEnKg= +google.golang.org/api v0.9.0/go.mod h1:o4eAsZoiT+ibD93RtjEohWalFOjRDx6CVaqeizhEnKg= +google.golang.org/api v0.13.0/go.mod h1:iLdEw5Ide6rF15KTC1Kkl0iskquN2gFfn9o9XIsbkAI= +google.golang.org/api v0.14.0/go.mod h1:iLdEw5Ide6rF15KTC1Kkl0iskquN2gFfn9o9XIsbkAI= +google.golang.org/api v0.15.0/go.mod h1:iLdEw5Ide6rF15KTC1Kkl0iskquN2gFfn9o9XIsbkAI= +google.golang.org/api v0.17.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE= +google.golang.org/api v0.18.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE= +google.golang.org/api v0.19.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE= +google.golang.org/api v0.20.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE= +google.golang.org/api v0.22.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE= +google.golang.org/api v0.24.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.30.0/go.mod h1:QGmEvQ87FHZNiUVJkT14jQNYJ4ZJjdRF23ZXz5138Fc= 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.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.5/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc= +google.golang.org/appengine v1.6.6/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-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-20190425155659-357c62f0e4bb/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= +google.golang.org/genproto v0.0.0-20190502173448-54afdca5d873/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= +google.golang.org/genproto v0.0.0-20190801165951-fa694d86fc64/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc= google.golang.org/genproto v0.0.0-20190819201941-24fa4b261c55/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc= +google.golang.org/genproto v0.0.0-20190911173649-1774047e7e51/go.mod h1:IbNlFCBrqXvoKpeg0TB2l7cyZUmoaFKYIwrEpbDKLA8= +google.golang.org/genproto v0.0.0-20191108220845-16a3f7862a1a/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= +google.golang.org/genproto v0.0.0-20191115194625-c23dd37a84c9/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= +google.golang.org/genproto v0.0.0-20191216164720-4f79533eabd1/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= +google.golang.org/genproto v0.0.0-20191230161307-f3c370f40bfb/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= +google.golang.org/genproto v0.0.0-20200115191322-ca5a22157cba/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= +google.golang.org/genproto v0.0.0-20200122232147-0452cf42e150/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= +google.golang.org/genproto v0.0.0-20200204135345-fa8e72b47b90/go.mod h1:GmwEX6Z4W5gMy59cAlVYjN9JhxgbQH6Gn+gFDQe2lzA= +google.golang.org/genproto v0.0.0-20200212174721-66ed5ce911ce/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= +google.golang.org/genproto v0.0.0-20200224152610-e50cd9704f63/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= +google.golang.org/genproto v0.0.0-20200228133532-8c2c7df3a383/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= +google.golang.org/genproto v0.0.0-20200305110556-506484158171/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= +google.golang.org/genproto v0.0.0-20200312145019-da6875a35672/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= +google.golang.org/genproto v0.0.0-20200331122359-1ee6d9798940/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= +google.golang.org/genproto v0.0.0-20200430143042-b979b6f78d84/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= +google.golang.org/genproto v0.0.0-20200511104702-f5ebc3bea380/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= google.golang.org/genproto v0.0.0-20200513103714-09dca8ec2884/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= +google.golang.org/genproto v0.0.0-20200515170657-fc4c6c6a6587/go.mod h1:YsZOwe1myG/8QRHRsmBRE1LrgQY60beZKjly0O1fX9U= google.golang.org/genproto v0.0.0-20200526211855-cb27e3aa2013/go.mod h1:NbSheEEYHJ7i3ixzK3sjbqSGDJWnxyFXZblF3eUsNvo= +google.golang.org/genproto v0.0.0-20200618031413-b414f8b61790/go.mod h1:jDfRM7FcilCzHH/e9qn6dsT145K34l5v+OpcnNgKAAA= +google.golang.org/genproto v0.0.0-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-20200825200019-8632dd797987/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= google.golang.org/genproto v0.0.0-20211118181313-81c1377c94b1 h1:b9mVrqYfq3P4bCdaLg1qtBnPzUYgglsIdjZkL/fQVOE= google.golang.org/genproto v0.0.0-20211118181313-81c1377c94b1/go.mod h1:5CzLGKJ67TSI2B9POpiiyGha0AjJvZIUgRMt1dSmuhc= 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.21.1/go.mod h1:oYelfM1adQP15Ek0mdvEgi9Df8B9CZIaU1084ijfRaM= google.golang.org/grpc v1.23.0/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg= google.golang.org/grpc v1.25.1/go.mod h1:c3i+UQWmh7LiEpx4sFZnkU36qjEYZ0imhYfXVyQciAY= +google.golang.org/grpc v1.26.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk= google.golang.org/grpc v1.27.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk= +google.golang.org/grpc v1.27.1/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk= +google.golang.org/grpc v1.28.0/go.mod h1:rpkK4SK4GF4Ach/+MFLZUBavHOvF2JJB5uozKKal+60= +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.31.0/go.mod h1:N36X2cJ7JwdamYAgDz+s+rVMFjt3numwzf/HckM8pak= google.golang.org/grpc v1.33.1/go.mod h1:fr5YgcSWrqhRRxogOsw7RzIpsmvOZ6IcH4kBYTpR3n0= google.golang.org/grpc v1.36.0/go.mod h1:qjiiYl8FncCW8feJPdyg3v6XW24KsRHe+dy9BAGRRjU= google.golang.org/grpc v1.40.0/go.mod h1:ogyxbiOoUXAkP+4+xa6PZSE9DZgIHtSpzjDTB9KAK34= @@ -248,6 +498,7 @@ google.golang.org/protobuf v1.21.0/go.mod h1:47Nbq4nVaFHyn7ilMalzfO3qCViNmqZ2kzi google.golang.org/protobuf v1.22.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= google.golang.org/protobuf v1.23.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= google.golang.org/protobuf v1.23.1-0.20200526195155-81db48ad09cc/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= +google.golang.org/protobuf v1.24.0/go.mod h1:r/3tXBNzIEhYS9I1OUVjXDlt8tc493IdKGjtUeSXeh4= google.golang.org/protobuf v1.25.0/go.mod h1:9JNX74DMeImyA3h4bdi1ymwjUzf21/xIlbajtzgsN7c= google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw= google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc= @@ -255,8 +506,10 @@ google.golang.org/protobuf v1.27.1 h1:SnqbnDw1V7RiZcXPx5MEeqPv2s79L9i7BJUlG/+Rur google.golang.org/protobuf v1.27.1/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc= gopkg.in/alecthomas/kingpin.v2 v2.2.6/go.mod h1:FMv+mEhP44yOT+4EoQTLFTRgOQ1FBLkstjWtayDeSgw= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15 h1:YR8cESwS4TdDjEe65xsg0ogRM/Nc3DYOhEAlW+xobZo= gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/errgo.v2 v2.1.0/go.mod h1:hNsd1EY+bozCKY1Ytp96fpM3vjJbqLJn88ws8XvfDNI= gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.2.3/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= @@ -270,6 +523,14 @@ gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b h1:h8qDotaEPuJATrMmW04NCwg7v22aHH28wwpauUhK9Oo= gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= +honnef.co/go/tools v0.0.0-20190106161140-3f1c8253044a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= +honnef.co/go/tools v0.0.0-20190418001031-e561f6794a2a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= honnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= +honnef.co/go/tools v0.0.1-2019.2.3/go.mod h1:a3bituU0lyd329TUQxRnasdCoJDkEUEAqEt0JzvZhAg= +honnef.co/go/tools v0.0.1-2020.1.3/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9vFzvIQ3k= +honnef.co/go/tools v0.0.1-2020.1.4/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9vFzvIQ3k= +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/sampler v1.3.0/go.mod h1:T1hPZKmBbMNahiBKFy5HrXp6adAjACjK9JXDnKaTXpA= sigs.k8s.io/yaml v1.2.0 h1:kr/MCeFWJWTwyaHoR9c8EjH9OumOmoF9YGiZd7lFm/Q= sigs.k8s.io/yaml v1.2.0/go.mod h1:yfXDCHCao9+ENCvLSE62v9VSji2MKu5jeNfTrofGhJc= diff --git a/etcdctl/go.mod b/etcdctl/go.mod index 741e07929bd3..ae0e5d11ca3a 100644 --- a/etcdctl/go.mod +++ b/etcdctl/go.mod @@ -23,7 +23,7 @@ require ( require ( github.com/beorn7/perks v1.0.1 // indirect - github.com/cespare/xxhash/v2 v2.1.1 // indirect + github.com/cespare/xxhash/v2 v2.1.2 // indirect github.com/coreos/go-semver v0.3.0 // indirect github.com/coreos/go-systemd/v22 v22.3.2 // indirect github.com/cpuguy83/go-md2man/v2 v2.0.1 // indirect @@ -37,10 +37,10 @@ require ( github.com/mattn/go-colorable v0.1.12 // indirect github.com/mattn/go-runewidth v0.0.9 // indirect github.com/matttproud/golang_protobuf_extensions v1.0.1 // indirect - github.com/prometheus/client_golang v1.11.0 // indirect + github.com/prometheus/client_golang v1.12.1 // indirect github.com/prometheus/client_model v0.2.0 // indirect - github.com/prometheus/common v0.26.0 // indirect - github.com/prometheus/procfs v0.6.0 // indirect + github.com/prometheus/common v0.32.1 // indirect + github.com/prometheus/procfs v0.7.3 // indirect github.com/russross/blackfriday/v2 v2.1.0 // indirect github.com/xiang90/probing v0.0.0-20190116061207-43a291ad63a2 // indirect go.etcd.io/bbolt v1.3.6 // indirect @@ -53,7 +53,7 @@ require ( go.uber.org/multierr v1.7.0 // indirect golang.org/x/crypto v0.0.0-20210513164829-c07d793c2f9a // indirect golang.org/x/net v0.0.0-20220105145211-5b0dc2dfae98 // indirect - golang.org/x/sys v0.0.0-20211123173158-ef496fb156ab // indirect + golang.org/x/sys v0.0.0-20220114195835-da31bd327af9 // indirect golang.org/x/text v0.3.7 // indirect google.golang.org/genproto v0.0.0-20211118181313-81c1377c94b1 // indirect google.golang.org/protobuf v1.27.1 // indirect diff --git a/etcdctl/go.sum b/etcdctl/go.sum index 362c5247e267..e936f2424936 100644 --- a/etcdctl/go.sum +++ b/etcdctl/go.sum @@ -1,7 +1,39 @@ cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= -cloud.google.com/go v0.34.0 h1:eOI3/cP2VTU6uZLDYAoic+eyzzB9YyGmJ7eIjl8rOPg= cloud.google.com/go v0.34.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= +cloud.google.com/go v0.38.0/go.mod h1:990N+gfupTy94rShfmMCWGDn0LpTmnzTp2qbd1dvSRU= +cloud.google.com/go v0.44.1/go.mod h1:iSa0KzasP4Uvy3f1mN/7PiObzGgflwredwwASm/v6AU= +cloud.google.com/go v0.44.2/go.mod h1:60680Gw3Yr4ikxnPRS/oxxkBccT6SA1yMk63TGekxKY= +cloud.google.com/go v0.45.1/go.mod h1:RpBamKRgapWJb87xiFSdk4g1CME7QZg3uwTez+TSTjc= +cloud.google.com/go v0.46.3/go.mod h1:a6bKKbmY7er1mI7TEI4lsAkts/mkhTSZK8w33B4RAg0= +cloud.google.com/go v0.50.0/go.mod h1:r9sluTvynVuxRIOHXQEHMFffphuXHOMZMycpNR5e6To= +cloud.google.com/go v0.52.0/go.mod h1:pXajvRH/6o3+F9jDHZWQ5PbGhn+o8w9qiu/CffaVdO4= +cloud.google.com/go v0.53.0/go.mod h1:fp/UouUEsRkN6ryDKNW/Upv/JBKnv6WDthjR6+vze6M= +cloud.google.com/go v0.54.0/go.mod h1:1rq2OEkV3YMf6n/9ZvGWI3GWw0VoqH/1x2nd8Is/bPc= +cloud.google.com/go v0.56.0/go.mod h1:jr7tqZxxKOVYizybht9+26Z/gUq7tiRzu+ACVAMbKVk= +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.65.0 h1:Dg9iHVQfrhq82rUNu9ZxUDrJLaxFUe/HlCVaLyRruq8= +cloud.google.com/go v0.65.0/go.mod h1:O5N8zS7uWy9vkA9vayVHs65eM1ubvY4h553ofrNHObY= +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.4.0/go.mod h1:S8dzgnTigyfTmLBfrtrhyYhwRxG72rYxvftPBK2Dvzc= +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.8.0/go.mod h1:J5hqkt3O0uAFnINi6JXValWIb1v0goeZM77hZzJN/fQ= +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/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.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/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.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.10.0/go.mod h1:FLPqc6j+Ki4BU591ie1oL6qBQGu2Bl/tZ9ullr3+Kg0= +dmitri.shuralyov.com/gpu/mtl v0.0.0-20190408044501-666a987793e9/go.mod h1:H6x//7gZCb22OMCxBHrMx7a5I7Hp++hsVxbQ4BYO7hU= github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= +github.com/BurntSushi/xgb v0.0.0-20160522181843-27f122750802/go.mod h1:IVnqGOEym/WlBOVXweHU+Q+/VP0lqqI8lqeDx9IjBqo= github.com/OneOfOne/xxhash v1.2.2/go.mod h1:HSdplMjZKSmBqAxg5vPj2TmRDmfkzw+cTzAElWljhcU= github.com/alecthomas/template v0.0.0-20160405071501-a0175ee3bccc/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc= github.com/alecthomas/template v0.0.0-20190718012654-fb15b899a751/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc= @@ -22,8 +54,12 @@ github.com/certifi/gocertifi v0.0.0-20200922220541-2c3bb06c6054 h1:uH66TXeswKn5P github.com/certifi/gocertifi v0.0.0-20200922220541-2c3bb06c6054/go.mod h1:sGbDF6GwGcLpkNXPUTkMRoywsNa/ol15pxFe6ERfguA= github.com/cespare/xxhash v1.1.0 h1:a6HrQnmkObjyL+Gs60czilIUGqrzKutQD6XZog3p+ko= github.com/cespare/xxhash v1.1.0/go.mod h1:XrSqR1VqqWfGrhpAt58auRo0WTKS1nRRg3ghfAqPWnc= -github.com/cespare/xxhash/v2 v2.1.1 h1:6MnRN8NT7+YBpUIWxHtefFZOKTAPgGjpQSxqLNn0+qY= github.com/cespare/xxhash/v2 v2.1.1/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= +github.com/cespare/xxhash/v2 v2.1.2 h1:YRXhKfTDauu4ajMg1TPgFO5jnlC2HCbmLXMcTG5cbYE= +github.com/cespare/xxhash/v2 v2.1.2/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= +github.com/chzyer/logex v1.1.10/go.mod h1:+Ywpsq7O8HXn0nuIou7OrIPyXbp3wmkHB+jjWRnGsAI= +github.com/chzyer/readline v0.0.0-20180603132655-2972be24d48e/go.mod h1:nSuG5e5PlCu98SY8svDHJxuZscDgtXS6KTTbou5AhLI= +github.com/chzyer/test v0.0.0-20180213035817-a1ea475d72b1/go.mod h1:Q3SI9o4m/ZMnBNeIyt5eFwwo7qiLfzFZmjNmxjkiQlU= github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw= github.com/cncf/udpa/go v0.0.0-20191209042840-269d4d468f6f/go.mod h1:M8M6+tZqaGXZJjfX53e64911xZQV5JYwmTeXPW+k8Sc= github.com/cncf/udpa/go v0.0.0-20201120205902-5459f2c99403/go.mod h1:WmhPx2Nbnhtbo57+VJT5O0JRkEi1Wbu0z5j0R8u5Hbk= @@ -62,6 +98,9 @@ github.com/fatih/color v1.13.0/go.mod h1:kLAiJbzzSOZDVNGyDpeOxJ47H46qBXwg5ILebYF github.com/getsentry/raven-go v0.2.0 h1:no+xWJRb5ZI7eE8TWgIq1jLulQiIoLG0IfYxv5JYMGs= github.com/getsentry/raven-go v0.2.0/go.mod h1:KungGk8q33+aIAZUIVWZDr2OfAEBsO49PX4NzFV5kcQ= github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04= +github.com/go-gl/glfw v0.0.0-20190409004039-e6da0acd62b1/go.mod h1:vR7hzQXu2zJy9AVAgeJqvqgH9Q5CA+iKCZ2gyEVpxRU= +github.com/go-gl/glfw/v3.3/glfw v0.0.0-20191125211704-12ad95a8df72/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8= +github.com/go-gl/glfw/v3.3/glfw v0.0.0-20200222043503-6f7a984d4dc4/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8= github.com/go-kit/kit v0.8.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as= github.com/go-kit/kit v0.9.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as= github.com/go-kit/log v0.1.0/go.mod h1:zbhenjAZHb184qTLMA9ZjW7ThYL0H2mk7Q6pNt4vbaY= @@ -77,12 +116,23 @@ github.com/gogo/protobuf v1.3.2/go.mod h1:P1XiOD3dCwIKUDQYPy72D8LYyHL2YPYrpS2s69 github.com/golang-jwt/jwt v3.2.2+incompatible h1:IfV12K8xAKAnZqdXVzCZ+TOjboZ2keLg81eXfW3O+oY= github.com/golang-jwt/jwt v3.2.2+incompatible/go.mod h1:8pz2t5EyA70fFQQSrl6XZXzqecmYZeUEB8OUGHkxJ+I= github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q= +github.com/golang/groupcache v0.0.0-20190702054246-869f871628b6/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= +github.com/golang/groupcache v0.0.0-20191227052852-215e87163ea7/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= +github.com/golang/groupcache v0.0.0-20200121045136-8c9f03a8e57e/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= github.com/golang/mock v1.1.1/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A= +github.com/golang/mock v1.2.0/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A= +github.com/golang/mock v1.3.1/go.mod h1:sBzyDLLjw3U8JLTeZvSv8jJB+tU5PVekmnlKIyFUx0Y= +github.com/golang/mock v1.4.0/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.4/go.mod h1:l3mdAwkq5BuhzHwde/uurv3sEJeZMXNpwsxVWU71h+4= github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= github.com/golang/protobuf v1.3.1/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= github.com/golang/protobuf v1.3.2/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= github.com/golang/protobuf v1.3.3/go.mod h1:vzj43D7+SQXF/4pzW/hwtAqwc6iTitCiVSaWz5lYuqw= +github.com/golang/protobuf v1.3.4/go.mod h1:vzj43D7+SQXF/4pzW/hwtAqwc6iTitCiVSaWz5lYuqw= +github.com/golang/protobuf v1.3.5/go.mod h1:6O5/vntMXwX2lRkT1hjjk0nAC1IDOTvTlVgjlRvqsdk= github.com/golang/protobuf v1.4.0-rc.1/go.mod h1:ceaxUfeHdC40wWswd/P6IGgMaK3YpKi5j83Wpe3EHw8= github.com/golang/protobuf v1.4.0-rc.1.0.20200221234624-67d41d38c208/go.mod h1:xKAWHe0F5eneWXFV3EuXVDTCmh+JuBKY0li0aMyXATA= github.com/golang/protobuf v1.4.0-rc.2/go.mod h1:LlEzMj4AhA7rCAGe4KMBDvJI+AwstrUpVNzEA03Pprs= @@ -94,24 +144,43 @@ github.com/golang/protobuf v1.4.3/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk= 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/google/btree v0.0.0-20180813153112-4030bb1f1f0c/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ= +github.com/google/btree v1.0.0/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ= github.com/google/btree v1.0.1 h1:gK4Kx5IaGY9CD5sPJ36FHiBJ6ZXl0kilRiiCj+jdYp4= github.com/google/btree v1.0.1/go.mod h1:xXMiIv4Fb/0kKde4SpL7qlzvu5cMJDRkFDxJfI9uaxA= github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M= github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= +github.com/google/go-cmp v0.4.1/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.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.6 h1:BKbKCqvP6I+rmFHt06ZmyQtvB8xAkWdhFyr0ZUNZcxQ= github.com/google/go-cmp v0.5.6/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= +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/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-20191218002539-d4f498aebedc/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= +github.com/google/pprof v0.0.0-20200212024743-f11f1df84d12/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-20200708004538-1a94d8640e99/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= +github.com/google/renameio v0.1.0/go.mod h1:KWCgfxg9yswjAJkECMjeO8J8rahYeXnNhOm40UhjYkI= github.com/google/uuid v1.1.2/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= +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/gorilla/websocket v1.4.2/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE= github.com/grpc-ecosystem/go-grpc-middleware v1.3.0/go.mod h1:z0ButlSOZa5vEBq9m2m2hlwIgKw+rp3sdCBRoJY+30Y= github.com/grpc-ecosystem/go-grpc-prometheus v1.2.0 h1:Ovs26xHkKqVztRpIrF/92BcuyuQ/YW4NSIpoGtfXNho= github.com/grpc-ecosystem/go-grpc-prometheus v1.2.0/go.mod h1:8NvIoxWQoOIhqOTXgfV/d3M/q6VIi02HzZEHgUlZvzk= github.com/grpc-ecosystem/grpc-gateway v1.16.0/go.mod h1:BDjrQk3hbvj6Nolgz8mAMFbcEtjT1g+wF4CSlocrBnw= +github.com/hashicorp/golang-lru v0.5.0/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8= +github.com/hashicorp/golang-lru v0.5.1/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8= +github.com/ianlancetaylor/demangle v0.0.0-20181102032728-5e5cf60278f6/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc= github.com/inconshreveable/mousetrap v1.0.0 h1:Z8tu5sraLXCXIcARxBp/8cbvlwVa7Z1NHg9XEKhtSvM= github.com/inconshreveable/mousetrap v1.0.0/go.mod h1:PxqpIevigyE2G7u3NXJIT2ANytuPF1OarO4DADm73n8= github.com/jonboulle/clockwork v0.2.2 h1:UOGuzwb1PwsrDAObMuhUnj0p5ULPj8V/xJ7Kx9qUBdQ= @@ -120,6 +189,9 @@ github.com/jpillora/backoff v1.0.0/go.mod h1:J/6gKK9jxlEcS3zixgDgUAsiuZ7yrSoa/FX github.com/json-iterator/go v1.1.6/go.mod h1:+SdeFBvtyEkXs7REEP0seUULqWtbJapLOCVDaaPEHmU= github.com/json-iterator/go v1.1.10/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4= github.com/json-iterator/go v1.1.11/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4= +github.com/json-iterator/go v1.1.12/go.mod h1:e30LSqwooZae/UwlEbR2852Gd8hjQvJoHmT4TnhNGBo= +github.com/jstemmer/go-junit-report v0.0.0-20190106144839-af01ea7f8024/go.mod h1:6v2b51hI/fHJwM22ozAgKL4VKDeJcHhJFhtBdhmNjmU= +github.com/jstemmer/go-junit-report v0.9.1/go.mod h1:Brl9GWCQeLvo8nXZwPNNblvFj/XSXhF0NWZEnDohbsk= github.com/julienschmidt/httprouter v1.2.0/go.mod h1:SYymIcj16QtmaHHD7aYtjjsJG7VTCxuUUipMqKk8s4w= github.com/julienschmidt/httprouter v1.3.0/go.mod h1:JR6WtHb+2LUe8TCKY3cZOxFyyO8IZAc4RVcycCCAKdM= github.com/kisielk/errcheck v1.2.0/go.mod h1:/BMXB+zMLi60iA8Vv6Ksmxu/1UDYcXs4uQLJ+jE2L00= @@ -146,6 +218,7 @@ github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJ github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= github.com/modern-go/reflect2 v0.0.0-20180701023420-4b7aa43c6742/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0= github.com/modern-go/reflect2 v1.0.1/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0= +github.com/modern-go/reflect2 v1.0.2/go.mod h1:yWuevngMOJpCy52FWWMvUC8ws7m/LJsjYzDa0/r8luk= github.com/mwitkow/go-conntrack v0.0.0-20161129095857-cc309e4a2223/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U= github.com/mwitkow/go-conntrack v0.0.0-20190716064945-2f068394615f/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U= github.com/olekukonko/tablewriter v0.0.5 h1:P2Ga83D34wi1o9J6Wh1mRuqd4mF/x/lgBS7N7AbDhec= @@ -160,8 +233,9 @@ github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZN github.com/prometheus/client_golang v0.9.1/go.mod h1:7SWBe2y4D6OKWSNQJUaRYU/AaXPKyh/dDVn+NZz0KFw= github.com/prometheus/client_golang v1.0.0/go.mod h1:db9x61etRT2tGnBNRi70OPL5FsnadC4Ky3P0J6CfImo= github.com/prometheus/client_golang v1.7.1/go.mod h1:PY5Wy2awLA44sXw4AOSfFBetzPP4j5+D6mVACh+pe2M= -github.com/prometheus/client_golang v1.11.0 h1:HNkLOAEQMIDv/K+04rukrLx6ch7msSRwf3/SASFAGtQ= github.com/prometheus/client_golang v1.11.0/go.mod h1:Z6t4BnS23TR94PD6BsDNk8yVqroYurpAkEiz0P2BEV0= +github.com/prometheus/client_golang v1.12.1 h1:ZiaPsmm9uiBeaSMRznKsCDNtPCS0T3JVDGF+06gjBzk= +github.com/prometheus/client_golang v1.12.1/go.mod h1:3Z9XVyYiZYEO+YQWt3RD2R3jrbd179Rt297l4aS6nDY= github.com/prometheus/client_model v0.0.0-20180712105110-5c3871d89910/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo= github.com/prometheus/client_model v0.0.0-20190129233127-fd36f4220a90/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= @@ -169,14 +243,17 @@ github.com/prometheus/client_model v0.2.0 h1:uq5h0d+GuxiXLJLNABMgp2qUWDPiLvgCzz2 github.com/prometheus/client_model v0.2.0/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= github.com/prometheus/common v0.4.1/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y86RQel1bk4= github.com/prometheus/common v0.10.0/go.mod h1:Tlit/dnDKsSWFlCLTWaA1cyBgKHSMdTB80sz/V91rCo= -github.com/prometheus/common v0.26.0 h1:iMAkS2TDoNWnKM+Kopnx/8tnEStIfpYA0ur0xQzzhMQ= github.com/prometheus/common v0.26.0/go.mod h1:M7rCNAaPfAosfx8veZJCuw84e35h3Cfd9VFqTh1DIvc= +github.com/prometheus/common v0.32.1 h1:hWIdL3N2HoUx3B8j3YN9mWor0qhY/NlEKZEaXxuIRh4= +github.com/prometheus/common v0.32.1/go.mod h1:vu+V0TpY+O6vW9J44gczi3Ap/oXXR10b+M/gUGO4Hls= github.com/prometheus/procfs v0.0.0-20181005140218-185b4288413d/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk= github.com/prometheus/procfs v0.0.2/go.mod h1:TjEm7ze935MbeOT/UhFTIMYKhuLP4wbCsTZCD3I8kEA= github.com/prometheus/procfs v0.1.3/go.mod h1:lV6e/gmhEcM9IjHGsFOCxxuZ+z1YqCvr4OA4YeYWdaU= -github.com/prometheus/procfs v0.6.0 h1:mxy4L2jP6qMonqmq+aTtOx1ifVWUgG/TAmntgbh3xv4= github.com/prometheus/procfs v0.6.0/go.mod h1:cz+aTbrPOrUb4q7XlbU9ygM+/jj0fzG6c1xBZuNvfVA= +github.com/prometheus/procfs v0.7.3 h1:4jVXhlkAyzOScmCkXBTOLRLTz8EeU+eyjrwB/EPq0VU= +github.com/prometheus/procfs v0.7.3/go.mod h1:cz+aTbrPOrUb4q7XlbU9ygM+/jj0fzG6c1xBZuNvfVA= github.com/rogpeppe/fastuuid v1.2.0/go.mod h1:jVj6XXZzXRy/MSR5jhDC/2q6DgLz+nrA6LYCDYWNEvQ= +github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4= github.com/russross/blackfriday/v2 v2.0.1/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= github.com/russross/blackfriday/v2 v2.1.0 h1:JIOH55/0cWyOuilr9/qlrm0BSXldqnqwMsf35Ld67mk= github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= @@ -204,10 +281,17 @@ github.com/urfave/cli v1.22.4 h1:u7tSpNPPswAFymm8IehJhy4uJMlUuU/GmqSkvJ1InXA= github.com/urfave/cli v1.22.4/go.mod h1:Gos4lmkARVdJ6EkW0WaNv/tZAAMe9V7XWyB60NtXRu0= github.com/xiang90/probing v0.0.0-20190116061207-43a291ad63a2 h1:eY9dn8+vbi4tKz5Qo6v2eYzo7kUS51QINcR5jNpbZS8= github.com/xiang90/probing v0.0.0-20190116061207-43a291ad63a2/go.mod h1:UETIi67q53MR2AWcXfiuqkDkRtnGDLqkBTpCHuJHxtU= +github.com/yuin/goldmark v1.1.25/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= +github.com/yuin/goldmark v1.1.32/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= go.etcd.io/bbolt v1.3.6 h1:/ecaJf0sk1l4l6V4awd65v2C3ILy7MSj+s/x1ADCIMU= go.etcd.io/bbolt v1.3.6/go.mod h1:qXsaaIqmgQH0T+OPdb99Bf+PKfBBQVAdyD6TY9G8XM4= +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.2/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.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.26.1 h1:puWrOArBwWlr5dq6vyZ6fKykHyS8JgMIVhTBA8XsGuU= go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.26.1/go.mod h1:4wsfAAW5N9wUHM0QTmZS8z7fvYZ1rv3m+sVeSpf8NhU= go.opentelemetry.io/otel v1.1.0/go.mod h1:7cww0OW51jQ8IaZChIEdqLwgh+44+7uiTdWsAL0wQpA= @@ -235,14 +319,40 @@ go.uber.org/zap v1.17.0 h1:MTjgFu6ZLKvY6Pvaqk97GlxNBuMpV4Hy/3P6tRGlI2U= go.uber.org/zap v1.17.0/go.mod h1:MXVU+bhUf/A7Xi2HNOnopQOrmycQ5Ih87HtOu4q5SSo= golang.org/x/crypto v0.0.0-20180904163835-0709b304e793/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= +golang.org/x/crypto v0.0.0-20190510104115-cbcb75029529/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= +golang.org/x/crypto v0.0.0-20190605123033-f99c8df09eb5/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= golang.org/x/crypto v0.0.0-20210513164829-c07d793c2f9a h1:kr2P4QFmQr29mSLA43kwrOcgcReGTfbE9N577tCTuBc= golang.org/x/crypto v0.0.0-20210513164829-c07d793c2f9a/go.mod h1:P+XmwS30IXTQdn5tA2iutPOUgjI07+tq3H3K9MVA1s8= golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= +golang.org/x/exp v0.0.0-20190306152737-a1d7652674e8/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= +golang.org/x/exp v0.0.0-20190510132918-efd6b22b2522/go.mod h1:ZjyILWgesfNpC6sMxTJOJm9Kp84zZh5NQWvqDGG3Qr8= +golang.org/x/exp v0.0.0-20190829153037-c13cbed26979/go.mod h1:86+5VVa7VpoJ4kLfm080zCjGlMRFzhUhsZKEZO7MGek= +golang.org/x/exp v0.0.0-20191030013958-a1ab85dbe136/go.mod h1:JXzH8nQsPlswgeRAPE3MuO9GYsAcnJvJ4vnMwN/5qkY= +golang.org/x/exp v0.0.0-20191129062945-2f5052295587/go.mod h1:2RIsYlXP63K8oxa1u096TMicItID8zy7Y6sNkU49FU4= +golang.org/x/exp v0.0.0-20191227195350-da58074b4299/go.mod h1:2RIsYlXP63K8oxa1u096TMicItID8zy7Y6sNkU49FU4= +golang.org/x/exp v0.0.0-20200119233911-0405dc783f0a/go.mod h1:2RIsYlXP63K8oxa1u096TMicItID8zy7Y6sNkU49FU4= +golang.org/x/exp v0.0.0-20200207192155-f17229e696bd/go.mod h1:J/WKrq2StrnmMY6+EHIKF9dgMWnmCNThgcyBT1FY9mM= +golang.org/x/exp v0.0.0-20200224162631-6cc2880d07d6/go.mod h1:3jZMyOhIsHpP37uCMkUooju7aAi5cS1Q23tOzKc+0MU= +golang.org/x/image v0.0.0-20190227222117-0694c2d4d067/go.mod h1:kZ7UVZpmo3dzQBMxlp+ypCbDeSB+sBbTgSJuh5dn5js= +golang.org/x/image v0.0.0-20190802002840-cff245a6509b/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0= golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE= golang.org/x/lint v0.0.0-20190227174305-5b3e6a55c961/go.mod h1:wehouNa3lNwaWXcvxsM5YxQ5yQlVC4a0KAMCusXpPoU= +golang.org/x/lint v0.0.0-20190301231843-5614ed5bae6f/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE= golang.org/x/lint v0.0.0-20190313153728-d0100b6bd8b3/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= +golang.org/x/lint v0.0.0-20190409202823-959b441ac422/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= +golang.org/x/lint v0.0.0-20190909230951-414d861bb4ac/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= +golang.org/x/lint v0.0.0-20190930215403-16217165b5de/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= +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-20200302205851-738671d3881b/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-20190719004257-d2bd2a29d028/go.mod h1:E/iHnbuqvinMTCcRqshq8CkpyQDoeVncDDYHnLhea+o= +golang.org/x/mod v0.0.0-20190513183733-4bf6d317e70e/go.mod h1:mXi4GBBbnImb6dmsKGUJ2LatrhH/nqhxcFungHvyanc= +golang.org/x/mod v0.1.0/go.mod h1:0QHyrYULN0/3qlju5TqG8bIK38QM8yzMo5ekMj3DlcY= +golang.org/x/mod v0.1.1-0.20191105210325-c90efee705ee/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.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= @@ -252,41 +362,84 @@ golang.org/x/net v0.0.0-20190108225652-1e06a53dbb7e/go.mod h1:mL1N/T3taQHkDXs73r golang.org/x/net v0.0.0-20190213061140-3a22650c66bd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= +golang.org/x/net v0.0.0-20190501004415-9ce7a6920f09/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= +golang.org/x/net v0.0.0-20190503192946-f4e77d36d62c/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= +golang.org/x/net v0.0.0-20190603091049-60506f45cf65/go.mod h1:HSz+uSET+XFnRR8LxR5pz3Of3rY3CfYBVs4xY44aLks= golang.org/x/net v0.0.0-20190613194153-d28f0bde5980/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20190628185345-da137c7871d7/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20190724013045-ca1201d0de80/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20191209160850-c0dbc17a3553/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20200114155413-6afb5195e5aa/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20200202094626-16171245cfb2/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20200222125558-5a598a2470a0/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20200226121028-0de0cce0169b/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20200301022130-244492dfa37a/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20200324143707-d3edc9973b7e/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= +golang.org/x/net v0.0.0-20200501053045-e0ff5e5a1de5/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= +golang.org/x/net v0.0.0-20200506145744-7e3656a0809f/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= +golang.org/x/net v0.0.0-20200513185701-a91f0712d120/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= +golang.org/x/net v0.0.0-20200520182314-0ba52f642ac2/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= golang.org/x/net v0.0.0-20200625001655-4c5254603344/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-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= golang.org/x/net v0.0.0-20201202161906-c7110b5ffcbb/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= golang.org/x/net v0.0.0-20210405180319-a5a99cb37ef4/go.mod h1:p54w0d4576C0XHj96bSt6lcn1PtDYWL6XObtHCRCNQM= +golang.org/x/net v0.0.0-20210525063256-abc453219eb5/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= golang.org/x/net v0.0.0-20220105145211-5b0dc2dfae98 h1:+6WJMRLHlD7X7frgp7TUZ36RnQzSf9wVVTNakEp+nqY= golang.org/x/net v0.0.0-20220105145211-5b0dc2dfae98/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= 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-20200107190931-bf48bf16ab8d h1:TzXSXBo42m9gQenoE3b9BGiEpg5IG2JkU5FkPIawgtw= +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-20200107190931-bf48bf16ab8d/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= +golang.org/x/oauth2 v0.0.0-20210514164344-f6687ab2804c h1:pkQiBZBvdos9qq4wBAHqlzuZHEXo07pqV06ef90u1WI= +golang.org/x/oauth2 v0.0.0-20210514164344-f6687ab2804c/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= 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-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20190227155943-e225da77a7e6/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20200317015054-43a5402ce75a/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20200625203802-6e8e738ad208/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/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-20181116152217-5ac8a444bdc5/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20190312061237-fead79001313/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190422165155-953cdadca894/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190502145724-3ef323f4f1fd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190507160741-ecd444e8653b/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190606165138-5da285871e9c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190624142023-c5567b49c5d0/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190726091711-fc99dfbffb4e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20191001151750-bb3f8db39f24/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20191026070338-33540a1f6037/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20191204072324-ce4227a45e2e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20191228213918-04cbcbbfeed8/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200106162015-b016eb3dc98e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200113162924-86b910548bc1/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200116001909-b77594299b42/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200122134326-e047566fdf82/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200202164722-d101bd2416d5/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200212091648-12a6c2dcc1e4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200223170610-d5e6a3e2c0ae/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200302150141-5c8b2ff67527/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200331124033-c3d80250170d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200501052902-10377860bb8e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200511232937-7e40ca221e25/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200515095857-1151b9dac4a9/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200523222454-059865788121/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-20200803210538-64077c9b5642/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200923182605-d9f96fdee20d/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= @@ -299,16 +452,21 @@ golang.org/x/sys v0.0.0-20210603081109-ebe580a85c40/go.mod h1:oPkhp1MJrh7nUepCBc golang.org/x/sys v0.0.0-20210603125802-9665404d3644/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20210630005230-0f9fa26af87c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20210927094055-39ccf1dd6fa6/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20211123173158-ef496fb156ab h1:rfJ1bsoJQQIAoAxTxB7bme+vHrNkRw8CqfsYh9w54cw= -golang.org/x/sys v0.0.0-20211123173158-ef496fb156ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20220114195835-da31bd327af9 h1:XfKQ4OlFl8okEOr5UvAqFRVj8pY/4yfcXrddB8qAbU0= +golang.org/x/sys v0.0.0-20220114195835-da31bd327af9/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= +golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= +golang.org/x/text v0.3.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.3/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.7 h1:olpwvP2KacW1ZWvsR7uQhoyTYvKAupfQrRGBFM352Gk= golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ= +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-20191024005414-555d28b269f0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.0.0-20210220033141-f8bda1e9f3ba h1:O8mE0/t419eoIwhTFpKVkHiTs/Igowgfkj25AcZrtiE= golang.org/x/time v0.0.0-20210220033141-f8bda1e9f3ba/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= @@ -316,30 +474,117 @@ golang.org/x/tools v0.0.0-20181030221726-6c7e314b6563/go.mod h1:n7NCudcB/nEzxVGm 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-20190311212946-11955173bddd/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= +golang.org/x/tools v0.0.0-20190312151545-0bb0c0a6e846/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= +golang.org/x/tools v0.0.0-20190312170243-e65039ee4138/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= +golang.org/x/tools v0.0.0-20190425150028-36563e24a262/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q= +golang.org/x/tools v0.0.0-20190506145303-2d16b83fe98c/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q= golang.org/x/tools v0.0.0-20190524140312-2c0ae7006135/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q= +golang.org/x/tools v0.0.0-20190606124116-d0a3d012864b/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc= +golang.org/x/tools v0.0.0-20190621195816-6e04913cbbac/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc= +golang.org/x/tools v0.0.0-20190628153133-6cdbf07be9d0/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc= +golang.org/x/tools v0.0.0-20190816200558-6889da9d5479/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-20190911174233-4f2ddba30aff/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-20191012152004-8de300cfc20a/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-20191113191852-77e3bb0ad9e7/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-20191115202509-3a792d9c32b2/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-20191125144606-a911d9008d1f/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-20191130070609-6e064ea0cf2d/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-20191216173652-a0e659d51361/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= +golang.org/x/tools v0.0.0-20191227053925-7b8e75db28f4/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= +golang.org/x/tools v0.0.0-20200117161641-43d50277825c/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= +golang.org/x/tools v0.0.0-20200122220014-bf1340f18c4a/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= +golang.org/x/tools v0.0.0-20200130002326-2f3ba24bd6e7/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= +golang.org/x/tools v0.0.0-20200204074204-1cc6d1ef6c74/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= +golang.org/x/tools v0.0.0-20200207183749-b753a1ba74fa/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= +golang.org/x/tools v0.0.0-20200212150539-ea181f53ac56/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= +golang.org/x/tools v0.0.0-20200224181240-023911ca70b2/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= +golang.org/x/tools v0.0.0-20200227222343-706bc42d1f0d/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= +golang.org/x/tools v0.0.0-20200304193943-95d2e580d8eb/go.mod h1:o4KQGtdN14AW+yjsvvwRTJJuXz8XRtIHtEnmAXLyFUw= +golang.org/x/tools v0.0.0-20200312045724-11d5b4c81c7d/go.mod h1:o4KQGtdN14AW+yjsvvwRTJJuXz8XRtIHtEnmAXLyFUw= +golang.org/x/tools v0.0.0-20200331025713-a30bf2db82d4/go.mod h1:Sl4aGygMT6LrqrWclx+PTx3U+LnKx/seiNR+3G19Ar8= +golang.org/x/tools v0.0.0-20200501065659-ab2804fb9c9d/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= +golang.org/x/tools v0.0.0-20200512131952-2bc93b1c0c88/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= +golang.org/x/tools v0.0.0-20200515010526-7d3b6ebf133d/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= +golang.org/x/tools v0.0.0-20200618134242-20370b0cb4b2/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= golang.org/x/tools v0.0.0-20200619180055-7c47624df98f/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= +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-20200825202427-b303f430e36d/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA= golang.org/x/tools v0.0.0-20210106214847-113979e3529a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= 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-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1 h1:go1bK/D/BFZV2I8cIQd1NKEZ+0owSTG1fDTci4IqFcE= golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +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.8.0/go.mod h1:o4eAsZoiT+ibD93RtjEohWalFOjRDx6CVaqeizhEnKg= +google.golang.org/api v0.9.0/go.mod h1:o4eAsZoiT+ibD93RtjEohWalFOjRDx6CVaqeizhEnKg= +google.golang.org/api v0.13.0/go.mod h1:iLdEw5Ide6rF15KTC1Kkl0iskquN2gFfn9o9XIsbkAI= +google.golang.org/api v0.14.0/go.mod h1:iLdEw5Ide6rF15KTC1Kkl0iskquN2gFfn9o9XIsbkAI= +google.golang.org/api v0.15.0/go.mod h1:iLdEw5Ide6rF15KTC1Kkl0iskquN2gFfn9o9XIsbkAI= +google.golang.org/api v0.17.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE= +google.golang.org/api v0.18.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE= +google.golang.org/api v0.19.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE= +google.golang.org/api v0.20.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE= +google.golang.org/api v0.22.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE= +google.golang.org/api v0.24.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.30.0/go.mod h1:QGmEvQ87FHZNiUVJkT14jQNYJ4ZJjdRF23ZXz5138Fc= google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM= -google.golang.org/appengine v1.4.0 h1:/wp5JvzpHIxhs/dumFmF7BXTf3Z+dd4uXta4kVyO508= 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.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.6 h1:lMO5rYAqUxkmaj76jAkRUvt5JZgFymx/+Q5Mzfivuhc= +google.golang.org/appengine v1.6.6/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-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-20190425155659-357c62f0e4bb/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= +google.golang.org/genproto v0.0.0-20190502173448-54afdca5d873/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= +google.golang.org/genproto v0.0.0-20190801165951-fa694d86fc64/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc= google.golang.org/genproto v0.0.0-20190819201941-24fa4b261c55/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc= +google.golang.org/genproto v0.0.0-20190911173649-1774047e7e51/go.mod h1:IbNlFCBrqXvoKpeg0TB2l7cyZUmoaFKYIwrEpbDKLA8= +google.golang.org/genproto v0.0.0-20191108220845-16a3f7862a1a/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= +google.golang.org/genproto v0.0.0-20191115194625-c23dd37a84c9/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= +google.golang.org/genproto v0.0.0-20191216164720-4f79533eabd1/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= +google.golang.org/genproto v0.0.0-20191230161307-f3c370f40bfb/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= +google.golang.org/genproto v0.0.0-20200115191322-ca5a22157cba/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= +google.golang.org/genproto v0.0.0-20200122232147-0452cf42e150/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= +google.golang.org/genproto v0.0.0-20200204135345-fa8e72b47b90/go.mod h1:GmwEX6Z4W5gMy59cAlVYjN9JhxgbQH6Gn+gFDQe2lzA= +google.golang.org/genproto v0.0.0-20200212174721-66ed5ce911ce/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= +google.golang.org/genproto v0.0.0-20200224152610-e50cd9704f63/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= +google.golang.org/genproto v0.0.0-20200228133532-8c2c7df3a383/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= +google.golang.org/genproto v0.0.0-20200305110556-506484158171/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= +google.golang.org/genproto v0.0.0-20200312145019-da6875a35672/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= +google.golang.org/genproto v0.0.0-20200331122359-1ee6d9798940/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= google.golang.org/genproto v0.0.0-20200423170343-7949de9c1215/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= +google.golang.org/genproto v0.0.0-20200430143042-b979b6f78d84/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= +google.golang.org/genproto v0.0.0-20200511104702-f5ebc3bea380/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= google.golang.org/genproto v0.0.0-20200513103714-09dca8ec2884/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= +google.golang.org/genproto v0.0.0-20200515170657-fc4c6c6a6587/go.mod h1:YsZOwe1myG/8QRHRsmBRE1LrgQY60beZKjly0O1fX9U= google.golang.org/genproto v0.0.0-20200526211855-cb27e3aa2013/go.mod h1:NbSheEEYHJ7i3ixzK3sjbqSGDJWnxyFXZblF3eUsNvo= +google.golang.org/genproto v0.0.0-20200618031413-b414f8b61790/go.mod h1:jDfRM7FcilCzHH/e9qn6dsT145K34l5v+OpcnNgKAAA= +google.golang.org/genproto v0.0.0-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-20200825200019-8632dd797987/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= google.golang.org/genproto v0.0.0-20211118181313-81c1377c94b1 h1:b9mVrqYfq3P4bCdaLg1qtBnPzUYgglsIdjZkL/fQVOE= google.golang.org/genproto v0.0.0-20211118181313-81c1377c94b1/go.mod h1:5CzLGKJ67TSI2B9POpiiyGha0AjJvZIUgRMt1dSmuhc= 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.21.1/go.mod h1:oYelfM1adQP15Ek0mdvEgi9Df8B9CZIaU1084ijfRaM= google.golang.org/grpc v1.23.0/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg= google.golang.org/grpc v1.25.1/go.mod h1:c3i+UQWmh7LiEpx4sFZnkU36qjEYZ0imhYfXVyQciAY= +google.golang.org/grpc v1.26.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk= google.golang.org/grpc v1.27.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk= +google.golang.org/grpc v1.27.1/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk= +google.golang.org/grpc v1.28.0/go.mod h1:rpkK4SK4GF4Ach/+MFLZUBavHOvF2JJB5uozKKal+60= 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.31.0/go.mod h1:N36X2cJ7JwdamYAgDz+s+rVMFjt3numwzf/HckM8pak= google.golang.org/grpc v1.33.1/go.mod h1:fr5YgcSWrqhRRxogOsw7RzIpsmvOZ6IcH4kBYTpR3n0= google.golang.org/grpc v1.36.0/go.mod h1:qjiiYl8FncCW8feJPdyg3v6XW24KsRHe+dy9BAGRRjU= google.golang.org/grpc v1.37.1/go.mod h1:NREThFqKR1f3iQ6oBuvc5LadQuXVGo9rkm5ZGrQdJfM= @@ -354,6 +599,7 @@ google.golang.org/protobuf v1.21.0/go.mod h1:47Nbq4nVaFHyn7ilMalzfO3qCViNmqZ2kzi google.golang.org/protobuf v1.22.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= google.golang.org/protobuf v1.23.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= google.golang.org/protobuf v1.23.1-0.20200526195155-81db48ad09cc/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= +google.golang.org/protobuf v1.24.0/go.mod h1:r/3tXBNzIEhYS9I1OUVjXDlt8tc493IdKGjtUeSXeh4= google.golang.org/protobuf v1.25.0/go.mod h1:9JNX74DMeImyA3h4bdi1ymwjUzf21/xIlbajtzgsN7c= google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw= google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc= @@ -361,9 +607,11 @@ google.golang.org/protobuf v1.27.1 h1:SnqbnDw1V7RiZcXPx5MEeqPv2s79L9i7BJUlG/+Rur google.golang.org/protobuf v1.27.1/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc= gopkg.in/alecthomas/kingpin.v2 v2.2.6/go.mod h1:FMv+mEhP44yOT+4EoQTLFTRgOQ1FBLkstjWtayDeSgw= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/cheggaaa/pb.v1 v1.0.28 h1:n1tBJnnK2r7g9OW2btFH91V92STTUevLXYFb8gy9EMk= gopkg.in/cheggaaa/pb.v1 v1.0.28/go.mod h1:V/YB90LKu/1FcN3WVnfiiE5oMCibMjukxqG/qStrOgw= +gopkg.in/errgo.v2 v2.1.0/go.mod h1:hNsd1EY+bozCKY1Ytp96fpM3vjJbqLJn88ws8XvfDNI= gopkg.in/natefinch/lumberjack.v2 v2.0.0/go.mod h1:l0ndWWf7gzL7RNwBG7wST/UCcT4T24xpD6X8LsfU/+k= gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= @@ -378,7 +626,15 @@ gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b h1:h8qDotaEPuJATrMmW04NCwg7v22aHH28wwpauUhK9Oo= gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= +honnef.co/go/tools v0.0.0-20190106161140-3f1c8253044a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= +honnef.co/go/tools v0.0.0-20190418001031-e561f6794a2a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= honnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= +honnef.co/go/tools v0.0.1-2019.2.3/go.mod h1:a3bituU0lyd329TUQxRnasdCoJDkEUEAqEt0JzvZhAg= +honnef.co/go/tools v0.0.1-2020.1.3/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9vFzvIQ3k= +honnef.co/go/tools v0.0.1-2020.1.4/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9vFzvIQ3k= +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/sampler v1.3.0/go.mod h1:T1hPZKmBbMNahiBKFy5HrXp6adAjACjK9JXDnKaTXpA= sigs.k8s.io/json v0.0.0-20211020170558-c049b76a60c6 h1:fD1pz4yfdADVNfFmcP2aBEtudwUQ1AlLnRBALr33v3s= sigs.k8s.io/json v0.0.0-20211020170558-c049b76a60c6/go.mod h1:p4QtZmO4uMYipTQNzagwnNoseA6OxSUutVw05NhYDRs= sigs.k8s.io/yaml v1.2.0/go.mod h1:yfXDCHCao9+ENCvLSE62v9VSji2MKu5jeNfTrofGhJc= diff --git a/etcdutl/go.mod b/etcdutl/go.mod index 82f39a6ad0a1..8b594fabdd81 100644 --- a/etcdutl/go.mod +++ b/etcdutl/go.mod @@ -37,7 +37,7 @@ require ( require ( github.com/beorn7/perks v1.0.1 // indirect - github.com/cespare/xxhash/v2 v2.1.1 // indirect + github.com/cespare/xxhash/v2 v2.1.2 // indirect github.com/coreos/go-systemd/v22 v22.3.2 // indirect github.com/gogo/protobuf v1.3.2 // indirect github.com/golang-jwt/jwt v3.2.2+incompatible // indirect @@ -47,10 +47,10 @@ require ( github.com/jonboulle/clockwork v0.2.2 // indirect github.com/mattn/go-runewidth v0.0.9 // indirect github.com/matttproud/golang_protobuf_extensions v1.0.1 // indirect - github.com/prometheus/client_golang v1.11.0 // indirect + github.com/prometheus/client_golang v1.12.1 // indirect github.com/prometheus/client_model v0.2.0 // indirect - github.com/prometheus/common v0.26.0 // indirect - github.com/prometheus/procfs v0.6.0 // indirect + github.com/prometheus/common v0.32.1 // indirect + github.com/prometheus/procfs v0.7.3 // indirect github.com/spf13/pflag v1.0.5 // indirect github.com/xiang90/probing v0.0.0-20190116061207-43a291ad63a2 // indirect go.etcd.io/etcd/client/v2 v2.306.0-alpha.0 // indirect @@ -61,7 +61,7 @@ require ( go.uber.org/multierr v1.7.0 // indirect golang.org/x/crypto v0.0.0-20210513164829-c07d793c2f9a // indirect golang.org/x/net v0.0.0-20220105145211-5b0dc2dfae98 // indirect - golang.org/x/sys v0.0.0-20211123173158-ef496fb156ab // indirect + golang.org/x/sys v0.0.0-20220114195835-da31bd327af9 // indirect golang.org/x/text v0.3.7 // indirect golang.org/x/time v0.0.0-20210220033141-f8bda1e9f3ba // indirect google.golang.org/genproto v0.0.0-20211118181313-81c1377c94b1 // indirect diff --git a/etcdutl/go.sum b/etcdutl/go.sum index 673bd9eef83e..51d97bf73a24 100644 --- a/etcdutl/go.sum +++ b/etcdutl/go.sum @@ -1,7 +1,39 @@ cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= -cloud.google.com/go v0.34.0 h1:eOI3/cP2VTU6uZLDYAoic+eyzzB9YyGmJ7eIjl8rOPg= cloud.google.com/go v0.34.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= +cloud.google.com/go v0.38.0/go.mod h1:990N+gfupTy94rShfmMCWGDn0LpTmnzTp2qbd1dvSRU= +cloud.google.com/go v0.44.1/go.mod h1:iSa0KzasP4Uvy3f1mN/7PiObzGgflwredwwASm/v6AU= +cloud.google.com/go v0.44.2/go.mod h1:60680Gw3Yr4ikxnPRS/oxxkBccT6SA1yMk63TGekxKY= +cloud.google.com/go v0.45.1/go.mod h1:RpBamKRgapWJb87xiFSdk4g1CME7QZg3uwTez+TSTjc= +cloud.google.com/go v0.46.3/go.mod h1:a6bKKbmY7er1mI7TEI4lsAkts/mkhTSZK8w33B4RAg0= +cloud.google.com/go v0.50.0/go.mod h1:r9sluTvynVuxRIOHXQEHMFffphuXHOMZMycpNR5e6To= +cloud.google.com/go v0.52.0/go.mod h1:pXajvRH/6o3+F9jDHZWQ5PbGhn+o8w9qiu/CffaVdO4= +cloud.google.com/go v0.53.0/go.mod h1:fp/UouUEsRkN6ryDKNW/Upv/JBKnv6WDthjR6+vze6M= +cloud.google.com/go v0.54.0/go.mod h1:1rq2OEkV3YMf6n/9ZvGWI3GWw0VoqH/1x2nd8Is/bPc= +cloud.google.com/go v0.56.0/go.mod h1:jr7tqZxxKOVYizybht9+26Z/gUq7tiRzu+ACVAMbKVk= +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.65.0 h1:Dg9iHVQfrhq82rUNu9ZxUDrJLaxFUe/HlCVaLyRruq8= +cloud.google.com/go v0.65.0/go.mod h1:O5N8zS7uWy9vkA9vayVHs65eM1ubvY4h553ofrNHObY= +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.4.0/go.mod h1:S8dzgnTigyfTmLBfrtrhyYhwRxG72rYxvftPBK2Dvzc= +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.8.0/go.mod h1:J5hqkt3O0uAFnINi6JXValWIb1v0goeZM77hZzJN/fQ= +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/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.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/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.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.10.0/go.mod h1:FLPqc6j+Ki4BU591ie1oL6qBQGu2Bl/tZ9ullr3+Kg0= +dmitri.shuralyov.com/gpu/mtl v0.0.0-20190408044501-666a987793e9/go.mod h1:H6x//7gZCb22OMCxBHrMx7a5I7Hp++hsVxbQ4BYO7hU= github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= +github.com/BurntSushi/xgb v0.0.0-20160522181843-27f122750802/go.mod h1:IVnqGOEym/WlBOVXweHU+Q+/VP0lqqI8lqeDx9IjBqo= github.com/OneOfOne/xxhash v1.2.2/go.mod h1:HSdplMjZKSmBqAxg5vPj2TmRDmfkzw+cTzAElWljhcU= github.com/alecthomas/template v0.0.0-20160405071501-a0175ee3bccc/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc= github.com/alecthomas/template v0.0.0-20190718012654-fb15b899a751/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc= @@ -20,8 +52,12 @@ github.com/certifi/gocertifi v0.0.0-20200922220541-2c3bb06c6054 h1:uH66TXeswKn5P github.com/certifi/gocertifi v0.0.0-20200922220541-2c3bb06c6054/go.mod h1:sGbDF6GwGcLpkNXPUTkMRoywsNa/ol15pxFe6ERfguA= github.com/cespare/xxhash v1.1.0 h1:a6HrQnmkObjyL+Gs60czilIUGqrzKutQD6XZog3p+ko= github.com/cespare/xxhash v1.1.0/go.mod h1:XrSqR1VqqWfGrhpAt58auRo0WTKS1nRRg3ghfAqPWnc= -github.com/cespare/xxhash/v2 v2.1.1 h1:6MnRN8NT7+YBpUIWxHtefFZOKTAPgGjpQSxqLNn0+qY= github.com/cespare/xxhash/v2 v2.1.1/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= +github.com/cespare/xxhash/v2 v2.1.2 h1:YRXhKfTDauu4ajMg1TPgFO5jnlC2HCbmLXMcTG5cbYE= +github.com/cespare/xxhash/v2 v2.1.2/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= +github.com/chzyer/logex v1.1.10/go.mod h1:+Ywpsq7O8HXn0nuIou7OrIPyXbp3wmkHB+jjWRnGsAI= +github.com/chzyer/readline v0.0.0-20180603132655-2972be24d48e/go.mod h1:nSuG5e5PlCu98SY8svDHJxuZscDgtXS6KTTbou5AhLI= +github.com/chzyer/test v0.0.0-20180213035817-a1ea475d72b1/go.mod h1:Q3SI9o4m/ZMnBNeIyt5eFwwo7qiLfzFZmjNmxjkiQlU= github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw= github.com/cncf/udpa/go v0.0.0-20191209042840-269d4d468f6f/go.mod h1:M8M6+tZqaGXZJjfX53e64911xZQV5JYwmTeXPW+k8Sc= github.com/cncf/udpa/go v0.0.0-20201120205902-5459f2c99403/go.mod h1:WmhPx2Nbnhtbo57+VJT5O0JRkEi1Wbu0z5j0R8u5Hbk= @@ -56,6 +92,9 @@ github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7 github.com/getsentry/raven-go v0.2.0 h1:no+xWJRb5ZI7eE8TWgIq1jLulQiIoLG0IfYxv5JYMGs= github.com/getsentry/raven-go v0.2.0/go.mod h1:KungGk8q33+aIAZUIVWZDr2OfAEBsO49PX4NzFV5kcQ= github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04= +github.com/go-gl/glfw v0.0.0-20190409004039-e6da0acd62b1/go.mod h1:vR7hzQXu2zJy9AVAgeJqvqgH9Q5CA+iKCZ2gyEVpxRU= +github.com/go-gl/glfw/v3.3/glfw v0.0.0-20191125211704-12ad95a8df72/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8= +github.com/go-gl/glfw/v3.3/glfw v0.0.0-20200222043503-6f7a984d4dc4/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8= github.com/go-kit/kit v0.8.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as= github.com/go-kit/kit v0.9.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as= github.com/go-kit/log v0.1.0/go.mod h1:zbhenjAZHb184qTLMA9ZjW7ThYL0H2mk7Q6pNt4vbaY= @@ -71,12 +110,23 @@ github.com/gogo/protobuf v1.3.2/go.mod h1:P1XiOD3dCwIKUDQYPy72D8LYyHL2YPYrpS2s69 github.com/golang-jwt/jwt v3.2.2+incompatible h1:IfV12K8xAKAnZqdXVzCZ+TOjboZ2keLg81eXfW3O+oY= github.com/golang-jwt/jwt v3.2.2+incompatible/go.mod h1:8pz2t5EyA70fFQQSrl6XZXzqecmYZeUEB8OUGHkxJ+I= github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q= +github.com/golang/groupcache v0.0.0-20190702054246-869f871628b6/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= +github.com/golang/groupcache v0.0.0-20191227052852-215e87163ea7/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= +github.com/golang/groupcache v0.0.0-20200121045136-8c9f03a8e57e/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= github.com/golang/mock v1.1.1/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A= +github.com/golang/mock v1.2.0/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A= +github.com/golang/mock v1.3.1/go.mod h1:sBzyDLLjw3U8JLTeZvSv8jJB+tU5PVekmnlKIyFUx0Y= +github.com/golang/mock v1.4.0/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.4/go.mod h1:l3mdAwkq5BuhzHwde/uurv3sEJeZMXNpwsxVWU71h+4= github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= github.com/golang/protobuf v1.3.1/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= github.com/golang/protobuf v1.3.2/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= github.com/golang/protobuf v1.3.3/go.mod h1:vzj43D7+SQXF/4pzW/hwtAqwc6iTitCiVSaWz5lYuqw= +github.com/golang/protobuf v1.3.4/go.mod h1:vzj43D7+SQXF/4pzW/hwtAqwc6iTitCiVSaWz5lYuqw= +github.com/golang/protobuf v1.3.5/go.mod h1:6O5/vntMXwX2lRkT1hjjk0nAC1IDOTvTlVgjlRvqsdk= github.com/golang/protobuf v1.4.0-rc.1/go.mod h1:ceaxUfeHdC40wWswd/P6IGgMaK3YpKi5j83Wpe3EHw8= github.com/golang/protobuf v1.4.0-rc.1.0.20200221234624-67d41d38c208/go.mod h1:xKAWHe0F5eneWXFV3EuXVDTCmh+JuBKY0li0aMyXATA= github.com/golang/protobuf v1.4.0-rc.2/go.mod h1:LlEzMj4AhA7rCAGe4KMBDvJI+AwstrUpVNzEA03Pprs= @@ -88,24 +138,43 @@ github.com/golang/protobuf v1.4.3/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk= 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/google/btree v0.0.0-20180813153112-4030bb1f1f0c/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ= +github.com/google/btree v1.0.0/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ= github.com/google/btree v1.0.1 h1:gK4Kx5IaGY9CD5sPJ36FHiBJ6ZXl0kilRiiCj+jdYp4= github.com/google/btree v1.0.1/go.mod h1:xXMiIv4Fb/0kKde4SpL7qlzvu5cMJDRkFDxJfI9uaxA= github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M= github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= +github.com/google/go-cmp v0.4.1/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.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.6 h1:BKbKCqvP6I+rmFHt06ZmyQtvB8xAkWdhFyr0ZUNZcxQ= github.com/google/go-cmp v0.5.6/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= +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/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-20191218002539-d4f498aebedc/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= +github.com/google/pprof v0.0.0-20200212024743-f11f1df84d12/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-20200708004538-1a94d8640e99/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= +github.com/google/renameio v0.1.0/go.mod h1:KWCgfxg9yswjAJkECMjeO8J8rahYeXnNhOm40UhjYkI= github.com/google/uuid v1.1.2/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= +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/gorilla/websocket v1.4.2/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE= github.com/grpc-ecosystem/go-grpc-middleware v1.3.0/go.mod h1:z0ButlSOZa5vEBq9m2m2hlwIgKw+rp3sdCBRoJY+30Y= github.com/grpc-ecosystem/go-grpc-prometheus v1.2.0 h1:Ovs26xHkKqVztRpIrF/92BcuyuQ/YW4NSIpoGtfXNho= github.com/grpc-ecosystem/go-grpc-prometheus v1.2.0/go.mod h1:8NvIoxWQoOIhqOTXgfV/d3M/q6VIi02HzZEHgUlZvzk= github.com/grpc-ecosystem/grpc-gateway v1.16.0/go.mod h1:BDjrQk3hbvj6Nolgz8mAMFbcEtjT1g+wF4CSlocrBnw= +github.com/hashicorp/golang-lru v0.5.0/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8= +github.com/hashicorp/golang-lru v0.5.1/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8= +github.com/ianlancetaylor/demangle v0.0.0-20181102032728-5e5cf60278f6/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc= github.com/inconshreveable/mousetrap v1.0.0 h1:Z8tu5sraLXCXIcARxBp/8cbvlwVa7Z1NHg9XEKhtSvM= github.com/inconshreveable/mousetrap v1.0.0/go.mod h1:PxqpIevigyE2G7u3NXJIT2ANytuPF1OarO4DADm73n8= github.com/jonboulle/clockwork v0.2.2 h1:UOGuzwb1PwsrDAObMuhUnj0p5ULPj8V/xJ7Kx9qUBdQ= @@ -114,6 +183,9 @@ github.com/jpillora/backoff v1.0.0/go.mod h1:J/6gKK9jxlEcS3zixgDgUAsiuZ7yrSoa/FX github.com/json-iterator/go v1.1.6/go.mod h1:+SdeFBvtyEkXs7REEP0seUULqWtbJapLOCVDaaPEHmU= github.com/json-iterator/go v1.1.10/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4= github.com/json-iterator/go v1.1.11/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4= +github.com/json-iterator/go v1.1.12/go.mod h1:e30LSqwooZae/UwlEbR2852Gd8hjQvJoHmT4TnhNGBo= +github.com/jstemmer/go-junit-report v0.0.0-20190106144839-af01ea7f8024/go.mod h1:6v2b51hI/fHJwM22ozAgKL4VKDeJcHhJFhtBdhmNjmU= +github.com/jstemmer/go-junit-report v0.9.1/go.mod h1:Brl9GWCQeLvo8nXZwPNNblvFj/XSXhF0NWZEnDohbsk= github.com/julienschmidt/httprouter v1.2.0/go.mod h1:SYymIcj16QtmaHHD7aYtjjsJG7VTCxuUUipMqKk8s4w= github.com/julienschmidt/httprouter v1.3.0/go.mod h1:JR6WtHb+2LUe8TCKY3cZOxFyyO8IZAc4RVcycCCAKdM= github.com/kisielk/errcheck v1.2.0/go.mod h1:/BMXB+zMLi60iA8Vv6Ksmxu/1UDYcXs4uQLJ+jE2L00= @@ -134,6 +206,7 @@ github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJ github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= github.com/modern-go/reflect2 v0.0.0-20180701023420-4b7aa43c6742/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0= github.com/modern-go/reflect2 v1.0.1/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0= +github.com/modern-go/reflect2 v1.0.2/go.mod h1:yWuevngMOJpCy52FWWMvUC8ws7m/LJsjYzDa0/r8luk= github.com/mwitkow/go-conntrack v0.0.0-20161129095857-cc309e4a2223/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U= github.com/mwitkow/go-conntrack v0.0.0-20190716064945-2f068394615f/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U= github.com/olekukonko/tablewriter v0.0.5 h1:P2Ga83D34wi1o9J6Wh1mRuqd4mF/x/lgBS7N7AbDhec= @@ -148,8 +221,9 @@ github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZN github.com/prometheus/client_golang v0.9.1/go.mod h1:7SWBe2y4D6OKWSNQJUaRYU/AaXPKyh/dDVn+NZz0KFw= github.com/prometheus/client_golang v1.0.0/go.mod h1:db9x61etRT2tGnBNRi70OPL5FsnadC4Ky3P0J6CfImo= github.com/prometheus/client_golang v1.7.1/go.mod h1:PY5Wy2awLA44sXw4AOSfFBetzPP4j5+D6mVACh+pe2M= -github.com/prometheus/client_golang v1.11.0 h1:HNkLOAEQMIDv/K+04rukrLx6ch7msSRwf3/SASFAGtQ= github.com/prometheus/client_golang v1.11.0/go.mod h1:Z6t4BnS23TR94PD6BsDNk8yVqroYurpAkEiz0P2BEV0= +github.com/prometheus/client_golang v1.12.1 h1:ZiaPsmm9uiBeaSMRznKsCDNtPCS0T3JVDGF+06gjBzk= +github.com/prometheus/client_golang v1.12.1/go.mod h1:3Z9XVyYiZYEO+YQWt3RD2R3jrbd179Rt297l4aS6nDY= github.com/prometheus/client_model v0.0.0-20180712105110-5c3871d89910/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo= github.com/prometheus/client_model v0.0.0-20190129233127-fd36f4220a90/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= @@ -157,14 +231,17 @@ github.com/prometheus/client_model v0.2.0 h1:uq5h0d+GuxiXLJLNABMgp2qUWDPiLvgCzz2 github.com/prometheus/client_model v0.2.0/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= github.com/prometheus/common v0.4.1/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y86RQel1bk4= github.com/prometheus/common v0.10.0/go.mod h1:Tlit/dnDKsSWFlCLTWaA1cyBgKHSMdTB80sz/V91rCo= -github.com/prometheus/common v0.26.0 h1:iMAkS2TDoNWnKM+Kopnx/8tnEStIfpYA0ur0xQzzhMQ= github.com/prometheus/common v0.26.0/go.mod h1:M7rCNAaPfAosfx8veZJCuw84e35h3Cfd9VFqTh1DIvc= +github.com/prometheus/common v0.32.1 h1:hWIdL3N2HoUx3B8j3YN9mWor0qhY/NlEKZEaXxuIRh4= +github.com/prometheus/common v0.32.1/go.mod h1:vu+V0TpY+O6vW9J44gczi3Ap/oXXR10b+M/gUGO4Hls= github.com/prometheus/procfs v0.0.0-20181005140218-185b4288413d/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk= github.com/prometheus/procfs v0.0.2/go.mod h1:TjEm7ze935MbeOT/UhFTIMYKhuLP4wbCsTZCD3I8kEA= github.com/prometheus/procfs v0.1.3/go.mod h1:lV6e/gmhEcM9IjHGsFOCxxuZ+z1YqCvr4OA4YeYWdaU= -github.com/prometheus/procfs v0.6.0 h1:mxy4L2jP6qMonqmq+aTtOx1ifVWUgG/TAmntgbh3xv4= github.com/prometheus/procfs v0.6.0/go.mod h1:cz+aTbrPOrUb4q7XlbU9ygM+/jj0fzG6c1xBZuNvfVA= +github.com/prometheus/procfs v0.7.3 h1:4jVXhlkAyzOScmCkXBTOLRLTz8EeU+eyjrwB/EPq0VU= +github.com/prometheus/procfs v0.7.3/go.mod h1:cz+aTbrPOrUb4q7XlbU9ygM+/jj0fzG6c1xBZuNvfVA= github.com/rogpeppe/fastuuid v1.2.0/go.mod h1:jVj6XXZzXRy/MSR5jhDC/2q6DgLz+nrA6LYCDYWNEvQ= +github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4= github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= github.com/sirupsen/logrus v1.2.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPxbbu5VWo= github.com/sirupsen/logrus v1.4.2/go.mod h1:tLMulIdttU9McNUspp0xgXVQah82FyeX6MwdIuYE2rE= @@ -187,10 +264,17 @@ github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/ github.com/tmc/grpc-websocket-proxy v0.0.0-20201229170055-e5319fda7802/go.mod h1:ncp9v5uamzpCO7NfCPTXjqaC+bZgJeR0sMTm6dMHP7U= github.com/xiang90/probing v0.0.0-20190116061207-43a291ad63a2 h1:eY9dn8+vbi4tKz5Qo6v2eYzo7kUS51QINcR5jNpbZS8= github.com/xiang90/probing v0.0.0-20190116061207-43a291ad63a2/go.mod h1:UETIi67q53MR2AWcXfiuqkDkRtnGDLqkBTpCHuJHxtU= +github.com/yuin/goldmark v1.1.25/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= +github.com/yuin/goldmark v1.1.32/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= go.etcd.io/bbolt v1.3.6 h1:/ecaJf0sk1l4l6V4awd65v2C3ILy7MSj+s/x1ADCIMU= go.etcd.io/bbolt v1.3.6/go.mod h1:qXsaaIqmgQH0T+OPdb99Bf+PKfBBQVAdyD6TY9G8XM4= +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.2/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.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.26.1 h1:puWrOArBwWlr5dq6vyZ6fKykHyS8JgMIVhTBA8XsGuU= go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.26.1/go.mod h1:4wsfAAW5N9wUHM0QTmZS8z7fvYZ1rv3m+sVeSpf8NhU= go.opentelemetry.io/otel v1.1.0/go.mod h1:7cww0OW51jQ8IaZChIEdqLwgh+44+7uiTdWsAL0wQpA= @@ -218,14 +302,40 @@ go.uber.org/zap v1.17.0 h1:MTjgFu6ZLKvY6Pvaqk97GlxNBuMpV4Hy/3P6tRGlI2U= go.uber.org/zap v1.17.0/go.mod h1:MXVU+bhUf/A7Xi2HNOnopQOrmycQ5Ih87HtOu4q5SSo= golang.org/x/crypto v0.0.0-20180904163835-0709b304e793/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= +golang.org/x/crypto v0.0.0-20190510104115-cbcb75029529/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= +golang.org/x/crypto v0.0.0-20190605123033-f99c8df09eb5/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= golang.org/x/crypto v0.0.0-20210513164829-c07d793c2f9a h1:kr2P4QFmQr29mSLA43kwrOcgcReGTfbE9N577tCTuBc= golang.org/x/crypto v0.0.0-20210513164829-c07d793c2f9a/go.mod h1:P+XmwS30IXTQdn5tA2iutPOUgjI07+tq3H3K9MVA1s8= golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= +golang.org/x/exp v0.0.0-20190306152737-a1d7652674e8/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= +golang.org/x/exp v0.0.0-20190510132918-efd6b22b2522/go.mod h1:ZjyILWgesfNpC6sMxTJOJm9Kp84zZh5NQWvqDGG3Qr8= +golang.org/x/exp v0.0.0-20190829153037-c13cbed26979/go.mod h1:86+5VVa7VpoJ4kLfm080zCjGlMRFzhUhsZKEZO7MGek= +golang.org/x/exp v0.0.0-20191030013958-a1ab85dbe136/go.mod h1:JXzH8nQsPlswgeRAPE3MuO9GYsAcnJvJ4vnMwN/5qkY= +golang.org/x/exp v0.0.0-20191129062945-2f5052295587/go.mod h1:2RIsYlXP63K8oxa1u096TMicItID8zy7Y6sNkU49FU4= +golang.org/x/exp v0.0.0-20191227195350-da58074b4299/go.mod h1:2RIsYlXP63K8oxa1u096TMicItID8zy7Y6sNkU49FU4= +golang.org/x/exp v0.0.0-20200119233911-0405dc783f0a/go.mod h1:2RIsYlXP63K8oxa1u096TMicItID8zy7Y6sNkU49FU4= +golang.org/x/exp v0.0.0-20200207192155-f17229e696bd/go.mod h1:J/WKrq2StrnmMY6+EHIKF9dgMWnmCNThgcyBT1FY9mM= +golang.org/x/exp v0.0.0-20200224162631-6cc2880d07d6/go.mod h1:3jZMyOhIsHpP37uCMkUooju7aAi5cS1Q23tOzKc+0MU= +golang.org/x/image v0.0.0-20190227222117-0694c2d4d067/go.mod h1:kZ7UVZpmo3dzQBMxlp+ypCbDeSB+sBbTgSJuh5dn5js= +golang.org/x/image v0.0.0-20190802002840-cff245a6509b/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0= golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE= golang.org/x/lint v0.0.0-20190227174305-5b3e6a55c961/go.mod h1:wehouNa3lNwaWXcvxsM5YxQ5yQlVC4a0KAMCusXpPoU= +golang.org/x/lint v0.0.0-20190301231843-5614ed5bae6f/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE= golang.org/x/lint v0.0.0-20190313153728-d0100b6bd8b3/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= +golang.org/x/lint v0.0.0-20190409202823-959b441ac422/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= +golang.org/x/lint v0.0.0-20190909230951-414d861bb4ac/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= +golang.org/x/lint v0.0.0-20190930215403-16217165b5de/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= +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-20200302205851-738671d3881b/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-20190719004257-d2bd2a29d028/go.mod h1:E/iHnbuqvinMTCcRqshq8CkpyQDoeVncDDYHnLhea+o= +golang.org/x/mod v0.0.0-20190513183733-4bf6d317e70e/go.mod h1:mXi4GBBbnImb6dmsKGUJ2LatrhH/nqhxcFungHvyanc= +golang.org/x/mod v0.1.0/go.mod h1:0QHyrYULN0/3qlju5TqG8bIK38QM8yzMo5ekMj3DlcY= +golang.org/x/mod v0.1.1-0.20191105210325-c90efee705ee/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.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= @@ -235,39 +345,83 @@ golang.org/x/net v0.0.0-20190108225652-1e06a53dbb7e/go.mod h1:mL1N/T3taQHkDXs73r golang.org/x/net v0.0.0-20190213061140-3a22650c66bd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= +golang.org/x/net v0.0.0-20190501004415-9ce7a6920f09/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= +golang.org/x/net v0.0.0-20190503192946-f4e77d36d62c/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= +golang.org/x/net v0.0.0-20190603091049-60506f45cf65/go.mod h1:HSz+uSET+XFnRR8LxR5pz3Of3rY3CfYBVs4xY44aLks= golang.org/x/net v0.0.0-20190613194153-d28f0bde5980/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20190628185345-da137c7871d7/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20190724013045-ca1201d0de80/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20191209160850-c0dbc17a3553/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20200114155413-6afb5195e5aa/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20200202094626-16171245cfb2/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20200222125558-5a598a2470a0/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20200226121028-0de0cce0169b/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20200301022130-244492dfa37a/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20200324143707-d3edc9973b7e/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= +golang.org/x/net v0.0.0-20200501053045-e0ff5e5a1de5/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= +golang.org/x/net v0.0.0-20200506145744-7e3656a0809f/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= +golang.org/x/net v0.0.0-20200513185701-a91f0712d120/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= +golang.org/x/net v0.0.0-20200520182314-0ba52f642ac2/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= golang.org/x/net v0.0.0-20200625001655-4c5254603344/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-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= golang.org/x/net v0.0.0-20201202161906-c7110b5ffcbb/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= golang.org/x/net v0.0.0-20210405180319-a5a99cb37ef4/go.mod h1:p54w0d4576C0XHj96bSt6lcn1PtDYWL6XObtHCRCNQM= +golang.org/x/net v0.0.0-20210525063256-abc453219eb5/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= golang.org/x/net v0.0.0-20220105145211-5b0dc2dfae98 h1:+6WJMRLHlD7X7frgp7TUZ36RnQzSf9wVVTNakEp+nqY= golang.org/x/net v0.0.0-20220105145211-5b0dc2dfae98/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= 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-20200107190931-bf48bf16ab8d h1:TzXSXBo42m9gQenoE3b9BGiEpg5IG2JkU5FkPIawgtw= +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-20200107190931-bf48bf16ab8d/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= +golang.org/x/oauth2 v0.0.0-20210514164344-f6687ab2804c h1:pkQiBZBvdos9qq4wBAHqlzuZHEXo07pqV06ef90u1WI= +golang.org/x/oauth2 v0.0.0-20210514164344-f6687ab2804c/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= 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-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20190227155943-e225da77a7e6/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20200317015054-43a5402ce75a/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20200625203802-6e8e738ad208/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/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-20181116152217-5ac8a444bdc5/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20190312061237-fead79001313/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190422165155-953cdadca894/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190502145724-3ef323f4f1fd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190507160741-ecd444e8653b/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190606165138-5da285871e9c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190624142023-c5567b49c5d0/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190726091711-fc99dfbffb4e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20191001151750-bb3f8db39f24/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20191026070338-33540a1f6037/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20191204072324-ce4227a45e2e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20191228213918-04cbcbbfeed8/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200106162015-b016eb3dc98e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200113162924-86b910548bc1/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200122134326-e047566fdf82/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200202164722-d101bd2416d5/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200212091648-12a6c2dcc1e4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200223170610-d5e6a3e2c0ae/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200302150141-5c8b2ff67527/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200331124033-c3d80250170d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200501052902-10377860bb8e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200511232937-7e40ca221e25/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200515095857-1151b9dac4a9/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200523222454-059865788121/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-20200803210538-64077c9b5642/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200923182605-d9f96fdee20d/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= @@ -278,16 +432,21 @@ golang.org/x/sys v0.0.0-20210423185535-09eb48e85fd7/go.mod h1:h1NjWce9XRLGQEsW7w golang.org/x/sys v0.0.0-20210510120138-977fb7262007/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-20211123173158-ef496fb156ab h1:rfJ1bsoJQQIAoAxTxB7bme+vHrNkRw8CqfsYh9w54cw= -golang.org/x/sys v0.0.0-20211123173158-ef496fb156ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20220114195835-da31bd327af9 h1:XfKQ4OlFl8okEOr5UvAqFRVj8pY/4yfcXrddB8qAbU0= +golang.org/x/sys v0.0.0-20220114195835-da31bd327af9/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= +golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= +golang.org/x/text v0.3.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.3/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.7 h1:olpwvP2KacW1ZWvsR7uQhoyTYvKAupfQrRGBFM352Gk= golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ= +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-20191024005414-555d28b269f0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.0.0-20210220033141-f8bda1e9f3ba h1:O8mE0/t419eoIwhTFpKVkHiTs/Igowgfkj25AcZrtiE= golang.org/x/time v0.0.0-20210220033141-f8bda1e9f3ba/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= @@ -295,30 +454,117 @@ golang.org/x/tools v0.0.0-20181030221726-6c7e314b6563/go.mod h1:n7NCudcB/nEzxVGm 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-20190311212946-11955173bddd/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= +golang.org/x/tools v0.0.0-20190312151545-0bb0c0a6e846/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= +golang.org/x/tools v0.0.0-20190312170243-e65039ee4138/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= +golang.org/x/tools v0.0.0-20190425150028-36563e24a262/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q= +golang.org/x/tools v0.0.0-20190506145303-2d16b83fe98c/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q= golang.org/x/tools v0.0.0-20190524140312-2c0ae7006135/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q= +golang.org/x/tools v0.0.0-20190606124116-d0a3d012864b/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc= +golang.org/x/tools v0.0.0-20190621195816-6e04913cbbac/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc= +golang.org/x/tools v0.0.0-20190628153133-6cdbf07be9d0/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc= +golang.org/x/tools v0.0.0-20190816200558-6889da9d5479/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-20190911174233-4f2ddba30aff/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-20191012152004-8de300cfc20a/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-20191113191852-77e3bb0ad9e7/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-20191115202509-3a792d9c32b2/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-20191125144606-a911d9008d1f/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-20191130070609-6e064ea0cf2d/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-20191216173652-a0e659d51361/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= +golang.org/x/tools v0.0.0-20191227053925-7b8e75db28f4/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= +golang.org/x/tools v0.0.0-20200117161641-43d50277825c/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= +golang.org/x/tools v0.0.0-20200122220014-bf1340f18c4a/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= +golang.org/x/tools v0.0.0-20200130002326-2f3ba24bd6e7/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= +golang.org/x/tools v0.0.0-20200204074204-1cc6d1ef6c74/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= +golang.org/x/tools v0.0.0-20200207183749-b753a1ba74fa/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= +golang.org/x/tools v0.0.0-20200212150539-ea181f53ac56/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= +golang.org/x/tools v0.0.0-20200224181240-023911ca70b2/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= +golang.org/x/tools v0.0.0-20200227222343-706bc42d1f0d/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= +golang.org/x/tools v0.0.0-20200304193943-95d2e580d8eb/go.mod h1:o4KQGtdN14AW+yjsvvwRTJJuXz8XRtIHtEnmAXLyFUw= +golang.org/x/tools v0.0.0-20200312045724-11d5b4c81c7d/go.mod h1:o4KQGtdN14AW+yjsvvwRTJJuXz8XRtIHtEnmAXLyFUw= +golang.org/x/tools v0.0.0-20200331025713-a30bf2db82d4/go.mod h1:Sl4aGygMT6LrqrWclx+PTx3U+LnKx/seiNR+3G19Ar8= +golang.org/x/tools v0.0.0-20200501065659-ab2804fb9c9d/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= +golang.org/x/tools v0.0.0-20200512131952-2bc93b1c0c88/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= +golang.org/x/tools v0.0.0-20200515010526-7d3b6ebf133d/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= +golang.org/x/tools v0.0.0-20200618134242-20370b0cb4b2/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= golang.org/x/tools v0.0.0-20200619180055-7c47624df98f/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= +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-20200825202427-b303f430e36d/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA= golang.org/x/tools v0.0.0-20210106214847-113979e3529a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= 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-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1 h1:go1bK/D/BFZV2I8cIQd1NKEZ+0owSTG1fDTci4IqFcE= golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +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.8.0/go.mod h1:o4eAsZoiT+ibD93RtjEohWalFOjRDx6CVaqeizhEnKg= +google.golang.org/api v0.9.0/go.mod h1:o4eAsZoiT+ibD93RtjEohWalFOjRDx6CVaqeizhEnKg= +google.golang.org/api v0.13.0/go.mod h1:iLdEw5Ide6rF15KTC1Kkl0iskquN2gFfn9o9XIsbkAI= +google.golang.org/api v0.14.0/go.mod h1:iLdEw5Ide6rF15KTC1Kkl0iskquN2gFfn9o9XIsbkAI= +google.golang.org/api v0.15.0/go.mod h1:iLdEw5Ide6rF15KTC1Kkl0iskquN2gFfn9o9XIsbkAI= +google.golang.org/api v0.17.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE= +google.golang.org/api v0.18.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE= +google.golang.org/api v0.19.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE= +google.golang.org/api v0.20.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE= +google.golang.org/api v0.22.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE= +google.golang.org/api v0.24.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.30.0/go.mod h1:QGmEvQ87FHZNiUVJkT14jQNYJ4ZJjdRF23ZXz5138Fc= google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM= -google.golang.org/appengine v1.4.0 h1:/wp5JvzpHIxhs/dumFmF7BXTf3Z+dd4uXta4kVyO508= 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.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.6 h1:lMO5rYAqUxkmaj76jAkRUvt5JZgFymx/+Q5Mzfivuhc= +google.golang.org/appengine v1.6.6/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-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-20190425155659-357c62f0e4bb/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= +google.golang.org/genproto v0.0.0-20190502173448-54afdca5d873/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= +google.golang.org/genproto v0.0.0-20190801165951-fa694d86fc64/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc= google.golang.org/genproto v0.0.0-20190819201941-24fa4b261c55/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc= +google.golang.org/genproto v0.0.0-20190911173649-1774047e7e51/go.mod h1:IbNlFCBrqXvoKpeg0TB2l7cyZUmoaFKYIwrEpbDKLA8= +google.golang.org/genproto v0.0.0-20191108220845-16a3f7862a1a/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= +google.golang.org/genproto v0.0.0-20191115194625-c23dd37a84c9/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= +google.golang.org/genproto v0.0.0-20191216164720-4f79533eabd1/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= +google.golang.org/genproto v0.0.0-20191230161307-f3c370f40bfb/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= +google.golang.org/genproto v0.0.0-20200115191322-ca5a22157cba/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= +google.golang.org/genproto v0.0.0-20200122232147-0452cf42e150/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= +google.golang.org/genproto v0.0.0-20200204135345-fa8e72b47b90/go.mod h1:GmwEX6Z4W5gMy59cAlVYjN9JhxgbQH6Gn+gFDQe2lzA= +google.golang.org/genproto v0.0.0-20200212174721-66ed5ce911ce/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= +google.golang.org/genproto v0.0.0-20200224152610-e50cd9704f63/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= +google.golang.org/genproto v0.0.0-20200228133532-8c2c7df3a383/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= +google.golang.org/genproto v0.0.0-20200305110556-506484158171/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= +google.golang.org/genproto v0.0.0-20200312145019-da6875a35672/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= +google.golang.org/genproto v0.0.0-20200331122359-1ee6d9798940/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= google.golang.org/genproto v0.0.0-20200423170343-7949de9c1215/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= +google.golang.org/genproto v0.0.0-20200430143042-b979b6f78d84/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= +google.golang.org/genproto v0.0.0-20200511104702-f5ebc3bea380/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= google.golang.org/genproto v0.0.0-20200513103714-09dca8ec2884/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= +google.golang.org/genproto v0.0.0-20200515170657-fc4c6c6a6587/go.mod h1:YsZOwe1myG/8QRHRsmBRE1LrgQY60beZKjly0O1fX9U= google.golang.org/genproto v0.0.0-20200526211855-cb27e3aa2013/go.mod h1:NbSheEEYHJ7i3ixzK3sjbqSGDJWnxyFXZblF3eUsNvo= +google.golang.org/genproto v0.0.0-20200618031413-b414f8b61790/go.mod h1:jDfRM7FcilCzHH/e9qn6dsT145K34l5v+OpcnNgKAAA= +google.golang.org/genproto v0.0.0-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-20200825200019-8632dd797987/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= google.golang.org/genproto v0.0.0-20211118181313-81c1377c94b1 h1:b9mVrqYfq3P4bCdaLg1qtBnPzUYgglsIdjZkL/fQVOE= google.golang.org/genproto v0.0.0-20211118181313-81c1377c94b1/go.mod h1:5CzLGKJ67TSI2B9POpiiyGha0AjJvZIUgRMt1dSmuhc= 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.21.1/go.mod h1:oYelfM1adQP15Ek0mdvEgi9Df8B9CZIaU1084ijfRaM= google.golang.org/grpc v1.23.0/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg= google.golang.org/grpc v1.25.1/go.mod h1:c3i+UQWmh7LiEpx4sFZnkU36qjEYZ0imhYfXVyQciAY= +google.golang.org/grpc v1.26.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk= google.golang.org/grpc v1.27.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk= +google.golang.org/grpc v1.27.1/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk= +google.golang.org/grpc v1.28.0/go.mod h1:rpkK4SK4GF4Ach/+MFLZUBavHOvF2JJB5uozKKal+60= 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.31.0/go.mod h1:N36X2cJ7JwdamYAgDz+s+rVMFjt3numwzf/HckM8pak= google.golang.org/grpc v1.33.1/go.mod h1:fr5YgcSWrqhRRxogOsw7RzIpsmvOZ6IcH4kBYTpR3n0= google.golang.org/grpc v1.36.0/go.mod h1:qjiiYl8FncCW8feJPdyg3v6XW24KsRHe+dy9BAGRRjU= google.golang.org/grpc v1.37.1/go.mod h1:NREThFqKR1f3iQ6oBuvc5LadQuXVGo9rkm5ZGrQdJfM= @@ -333,6 +579,7 @@ google.golang.org/protobuf v1.21.0/go.mod h1:47Nbq4nVaFHyn7ilMalzfO3qCViNmqZ2kzi google.golang.org/protobuf v1.22.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= google.golang.org/protobuf v1.23.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= google.golang.org/protobuf v1.23.1-0.20200526195155-81db48ad09cc/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= +google.golang.org/protobuf v1.24.0/go.mod h1:r/3tXBNzIEhYS9I1OUVjXDlt8tc493IdKGjtUeSXeh4= google.golang.org/protobuf v1.25.0/go.mod h1:9JNX74DMeImyA3h4bdi1ymwjUzf21/xIlbajtzgsN7c= google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw= google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc= @@ -340,7 +587,9 @@ google.golang.org/protobuf v1.27.1 h1:SnqbnDw1V7RiZcXPx5MEeqPv2s79L9i7BJUlG/+Rur google.golang.org/protobuf v1.27.1/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc= gopkg.in/alecthomas/kingpin.v2 v2.2.6/go.mod h1:FMv+mEhP44yOT+4EoQTLFTRgOQ1FBLkstjWtayDeSgw= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/errgo.v2 v2.1.0/go.mod h1:hNsd1EY+bozCKY1Ytp96fpM3vjJbqLJn88ws8XvfDNI= gopkg.in/natefinch/lumberjack.v2 v2.0.0/go.mod h1:l0ndWWf7gzL7RNwBG7wST/UCcT4T24xpD6X8LsfU/+k= gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= @@ -355,7 +604,15 @@ gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b h1:h8qDotaEPuJATrMmW04NCwg7v22aHH28wwpauUhK9Oo= gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= +honnef.co/go/tools v0.0.0-20190106161140-3f1c8253044a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= +honnef.co/go/tools v0.0.0-20190418001031-e561f6794a2a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= honnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= +honnef.co/go/tools v0.0.1-2019.2.3/go.mod h1:a3bituU0lyd329TUQxRnasdCoJDkEUEAqEt0JzvZhAg= +honnef.co/go/tools v0.0.1-2020.1.3/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9vFzvIQ3k= +honnef.co/go/tools v0.0.1-2020.1.4/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9vFzvIQ3k= +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/sampler v1.3.0/go.mod h1:T1hPZKmBbMNahiBKFy5HrXp6adAjACjK9JXDnKaTXpA= sigs.k8s.io/json v0.0.0-20211020170558-c049b76a60c6 h1:fD1pz4yfdADVNfFmcP2aBEtudwUQ1AlLnRBALr33v3s= sigs.k8s.io/json v0.0.0-20211020170558-c049b76a60c6/go.mod h1:p4QtZmO4uMYipTQNzagwnNoseA6OxSUutVw05NhYDRs= sigs.k8s.io/yaml v1.2.0/go.mod h1:yfXDCHCao9+ENCvLSE62v9VSji2MKu5jeNfTrofGhJc= diff --git a/go.mod b/go.mod index 1d74e65a0d92..cc2ec5f2d501 100644 --- a/go.mod +++ b/go.mod @@ -42,7 +42,7 @@ require ( cloud.google.com/go v0.81.0 // indirect github.com/beorn7/perks v1.0.1 // indirect github.com/cenkalti/backoff/v4 v4.1.1 // indirect - github.com/cespare/xxhash/v2 v2.1.1 // indirect + github.com/cespare/xxhash/v2 v2.1.2 // indirect github.com/coreos/go-systemd/v22 v22.3.2 // indirect github.com/davecgh/go-spew v1.1.1 // indirect github.com/gogo/protobuf v1.3.2 // indirect @@ -62,10 +62,10 @@ require ( github.com/matttproud/golang_protobuf_extensions v1.0.1 // indirect github.com/olekukonko/tablewriter v0.0.5 // indirect github.com/pmezard/go-difflib v1.0.0 // indirect - github.com/prometheus/client_golang v1.11.0 // indirect + github.com/prometheus/client_golang v1.12.1 // indirect github.com/prometheus/client_model v0.2.0 // indirect - github.com/prometheus/common v0.26.0 // indirect - github.com/prometheus/procfs v0.6.0 // indirect + github.com/prometheus/common v0.32.1 // indirect + github.com/prometheus/procfs v0.7.3 // indirect github.com/sirupsen/logrus v1.8.1 // indirect github.com/soheilhy/cmux v0.1.5 // indirect github.com/spf13/pflag v1.0.5 // indirect @@ -83,8 +83,7 @@ require ( go.uber.org/multierr v1.7.0 // indirect golang.org/x/crypto v0.0.0-20210513164829-c07d793c2f9a // indirect golang.org/x/net v0.0.0-20220105145211-5b0dc2dfae98 // indirect - golang.org/x/oauth2 v0.0.0-20210402161424-2e8d93401602 // indirect - golang.org/x/sys v0.0.0-20211123173158-ef496fb156ab // indirect + golang.org/x/sys v0.0.0-20220114195835-da31bd327af9 // indirect golang.org/x/text v0.3.7 // indirect golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1 // indirect google.golang.org/appengine v1.6.7 // indirect diff --git a/go.sum b/go.sum index 7237b981a87f..1811cec82d13 100644 --- a/go.sum +++ b/go.sum @@ -61,8 +61,9 @@ github.com/certifi/gocertifi v0.0.0-20200922220541-2c3bb06c6054 h1:uH66TXeswKn5P github.com/certifi/gocertifi v0.0.0-20200922220541-2c3bb06c6054/go.mod h1:sGbDF6GwGcLpkNXPUTkMRoywsNa/ol15pxFe6ERfguA= github.com/cespare/xxhash v1.1.0 h1:a6HrQnmkObjyL+Gs60czilIUGqrzKutQD6XZog3p+ko= github.com/cespare/xxhash v1.1.0/go.mod h1:XrSqR1VqqWfGrhpAt58auRo0WTKS1nRRg3ghfAqPWnc= -github.com/cespare/xxhash/v2 v2.1.1 h1:6MnRN8NT7+YBpUIWxHtefFZOKTAPgGjpQSxqLNn0+qY= github.com/cespare/xxhash/v2 v2.1.1/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= +github.com/cespare/xxhash/v2 v2.1.2 h1:YRXhKfTDauu4ajMg1TPgFO5jnlC2HCbmLXMcTG5cbYE= +github.com/cespare/xxhash/v2 v2.1.2/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= github.com/chzyer/logex v1.1.10/go.mod h1:+Ywpsq7O8HXn0nuIou7OrIPyXbp3wmkHB+jjWRnGsAI= github.com/chzyer/readline v0.0.0-20180603132655-2972be24d48e/go.mod h1:nSuG5e5PlCu98SY8svDHJxuZscDgtXS6KTTbou5AhLI= github.com/chzyer/test v0.0.0-20180213035817-a1ea475d72b1/go.mod h1:Q3SI9o4m/ZMnBNeIyt5eFwwo7qiLfzFZmjNmxjkiQlU= @@ -210,6 +211,7 @@ github.com/jpillora/backoff v1.0.0/go.mod h1:J/6gKK9jxlEcS3zixgDgUAsiuZ7yrSoa/FX github.com/json-iterator/go v1.1.6/go.mod h1:+SdeFBvtyEkXs7REEP0seUULqWtbJapLOCVDaaPEHmU= github.com/json-iterator/go v1.1.10/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4= github.com/json-iterator/go v1.1.11/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4= +github.com/json-iterator/go v1.1.12/go.mod h1:e30LSqwooZae/UwlEbR2852Gd8hjQvJoHmT4TnhNGBo= github.com/jstemmer/go-junit-report v0.0.0-20190106144839-af01ea7f8024/go.mod h1:6v2b51hI/fHJwM22ozAgKL4VKDeJcHhJFhtBdhmNjmU= github.com/jstemmer/go-junit-report v0.9.1/go.mod h1:Brl9GWCQeLvo8nXZwPNNblvFj/XSXhF0NWZEnDohbsk= github.com/julienschmidt/httprouter v1.2.0/go.mod h1:SYymIcj16QtmaHHD7aYtjjsJG7VTCxuUUipMqKk8s4w= @@ -240,6 +242,7 @@ github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJ github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= github.com/modern-go/reflect2 v0.0.0-20180701023420-4b7aa43c6742/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0= github.com/modern-go/reflect2 v1.0.1/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0= +github.com/modern-go/reflect2 v1.0.2/go.mod h1:yWuevngMOJpCy52FWWMvUC8ws7m/LJsjYzDa0/r8luk= github.com/mwitkow/go-conntrack v0.0.0-20161129095857-cc309e4a2223/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U= github.com/mwitkow/go-conntrack v0.0.0-20190716064945-2f068394615f/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U= github.com/olekukonko/tablewriter v0.0.5 h1:P2Ga83D34wi1o9J6Wh1mRuqd4mF/x/lgBS7N7AbDhec= @@ -254,8 +257,9 @@ github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZN github.com/prometheus/client_golang v0.9.1/go.mod h1:7SWBe2y4D6OKWSNQJUaRYU/AaXPKyh/dDVn+NZz0KFw= github.com/prometheus/client_golang v1.0.0/go.mod h1:db9x61etRT2tGnBNRi70OPL5FsnadC4Ky3P0J6CfImo= github.com/prometheus/client_golang v1.7.1/go.mod h1:PY5Wy2awLA44sXw4AOSfFBetzPP4j5+D6mVACh+pe2M= -github.com/prometheus/client_golang v1.11.0 h1:HNkLOAEQMIDv/K+04rukrLx6ch7msSRwf3/SASFAGtQ= github.com/prometheus/client_golang v1.11.0/go.mod h1:Z6t4BnS23TR94PD6BsDNk8yVqroYurpAkEiz0P2BEV0= +github.com/prometheus/client_golang v1.12.1 h1:ZiaPsmm9uiBeaSMRznKsCDNtPCS0T3JVDGF+06gjBzk= +github.com/prometheus/client_golang v1.12.1/go.mod h1:3Z9XVyYiZYEO+YQWt3RD2R3jrbd179Rt297l4aS6nDY= github.com/prometheus/client_model v0.0.0-20180712105110-5c3871d89910/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo= github.com/prometheus/client_model v0.0.0-20190129233127-fd36f4220a90/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= @@ -263,13 +267,15 @@ github.com/prometheus/client_model v0.2.0 h1:uq5h0d+GuxiXLJLNABMgp2qUWDPiLvgCzz2 github.com/prometheus/client_model v0.2.0/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= github.com/prometheus/common v0.4.1/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y86RQel1bk4= github.com/prometheus/common v0.10.0/go.mod h1:Tlit/dnDKsSWFlCLTWaA1cyBgKHSMdTB80sz/V91rCo= -github.com/prometheus/common v0.26.0 h1:iMAkS2TDoNWnKM+Kopnx/8tnEStIfpYA0ur0xQzzhMQ= github.com/prometheus/common v0.26.0/go.mod h1:M7rCNAaPfAosfx8veZJCuw84e35h3Cfd9VFqTh1DIvc= +github.com/prometheus/common v0.32.1 h1:hWIdL3N2HoUx3B8j3YN9mWor0qhY/NlEKZEaXxuIRh4= +github.com/prometheus/common v0.32.1/go.mod h1:vu+V0TpY+O6vW9J44gczi3Ap/oXXR10b+M/gUGO4Hls= github.com/prometheus/procfs v0.0.0-20181005140218-185b4288413d/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk= github.com/prometheus/procfs v0.0.2/go.mod h1:TjEm7ze935MbeOT/UhFTIMYKhuLP4wbCsTZCD3I8kEA= github.com/prometheus/procfs v0.1.3/go.mod h1:lV6e/gmhEcM9IjHGsFOCxxuZ+z1YqCvr4OA4YeYWdaU= -github.com/prometheus/procfs v0.6.0 h1:mxy4L2jP6qMonqmq+aTtOx1ifVWUgG/TAmntgbh3xv4= github.com/prometheus/procfs v0.6.0/go.mod h1:cz+aTbrPOrUb4q7XlbU9ygM+/jj0fzG6c1xBZuNvfVA= +github.com/prometheus/procfs v0.7.3 h1:4jVXhlkAyzOScmCkXBTOLRLTz8EeU+eyjrwB/EPq0VU= +github.com/prometheus/procfs v0.7.3/go.mod h1:cz+aTbrPOrUb4q7XlbU9ygM+/jj0fzG6c1xBZuNvfVA= github.com/rogpeppe/fastuuid v1.2.0/go.mod h1:jVj6XXZzXRy/MSR5jhDC/2q6DgLz+nrA6LYCDYWNEvQ= github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4= github.com/russross/blackfriday/v2 v2.0.1/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= @@ -421,6 +427,7 @@ golang.org/x/net v0.0.0-20210119194325-5f4716e94777/go.mod h1:m0MpNAwzfU5UDzcl9v 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-20210525063256-abc453219eb5/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= golang.org/x/net v0.0.0-20220105145211-5b0dc2dfae98 h1:+6WJMRLHlD7X7frgp7TUZ36RnQzSf9wVVTNakEp+nqY= golang.org/x/net v0.0.0-20220105145211-5b0dc2dfae98/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= @@ -434,8 +441,8 @@ golang.org/x/oauth2 v0.0.0-20201208152858-08078c50e5b5/go.mod h1:KelEdhl1UZF7XfJ 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-20210402161424-2e8d93401602 h1:0Ja1LBD+yisY6RWM/BH7TJVXWsSjs2VwBSmvSX4HdBc= -golang.org/x/oauth2 v0.0.0-20210402161424-2e8d93401602/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= +golang.org/x/oauth2 v0.0.0-20210514164344-f6687ab2804c h1:pkQiBZBvdos9qq4wBAHqlzuZHEXo07pqV06ef90u1WI= +golang.org/x/oauth2 v0.0.0-20210514164344-f6687ab2804c/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= 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-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= @@ -501,8 +508,8 @@ golang.org/x/sys v0.0.0-20210603081109-ebe580a85c40/go.mod h1:oPkhp1MJrh7nUepCBc golang.org/x/sys v0.0.0-20210603125802-9665404d3644/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20210630005230-0f9fa26af87c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20210927094055-39ccf1dd6fa6/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20211123173158-ef496fb156ab h1:rfJ1bsoJQQIAoAxTxB7bme+vHrNkRw8CqfsYh9w54cw= -golang.org/x/sys v0.0.0-20211123173158-ef496fb156ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20220114195835-da31bd327af9 h1:XfKQ4OlFl8okEOr5UvAqFRVj8pY/4yfcXrddB8qAbU0= +golang.org/x/sys v0.0.0-20220114195835-da31bd327af9/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= diff --git a/server/go.mod b/server/go.mod index 241c4d9e7782..068e11072da3 100644 --- a/server/go.mod +++ b/server/go.mod @@ -15,7 +15,7 @@ require ( github.com/grpc-ecosystem/go-grpc-prometheus v1.2.0 github.com/grpc-ecosystem/grpc-gateway v1.16.0 github.com/jonboulle/clockwork v0.2.2 - github.com/prometheus/client_golang v1.11.0 + github.com/prometheus/client_golang v1.12.1 github.com/prometheus/client_model v0.2.0 github.com/soheilhy/cmux v0.1.5 github.com/spf13/cobra v1.4.0 @@ -48,22 +48,22 @@ require ( require ( github.com/beorn7/perks v1.0.1 // indirect github.com/cenkalti/backoff/v4 v4.1.1 // indirect - github.com/cespare/xxhash/v2 v2.1.1 // indirect + github.com/cespare/xxhash/v2 v2.1.2 // indirect github.com/davecgh/go-spew v1.1.1 // indirect github.com/gorilla/websocket v1.4.2 // indirect github.com/inconshreveable/mousetrap v1.0.0 // indirect github.com/kr/text v0.2.0 // indirect github.com/matttproud/golang_protobuf_extensions v1.0.1 // indirect github.com/pmezard/go-difflib v1.0.0 // indirect - github.com/prometheus/common v0.26.0 // indirect - github.com/prometheus/procfs v0.6.0 // indirect + github.com/prometheus/common v0.32.1 // indirect + github.com/prometheus/procfs v0.7.3 // indirect github.com/sirupsen/logrus v1.8.1 // indirect github.com/spf13/pflag v1.0.5 // indirect go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.1.0 // indirect go.opentelemetry.io/otel/trace v1.2.0 // indirect go.opentelemetry.io/proto/otlp v0.10.0 // indirect go.uber.org/atomic v1.7.0 // indirect - golang.org/x/sys v0.0.0-20211123173158-ef496fb156ab // indirect + golang.org/x/sys v0.0.0-20220114195835-da31bd327af9 // indirect golang.org/x/text v0.3.7 // indirect gopkg.in/yaml.v2 v2.4.0 // indirect gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b // indirect diff --git a/server/go.sum b/server/go.sum index 33dc67b849df..3718af092724 100644 --- a/server/go.sum +++ b/server/go.sum @@ -1,8 +1,40 @@ cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= -cloud.google.com/go v0.34.0 h1:eOI3/cP2VTU6uZLDYAoic+eyzzB9YyGmJ7eIjl8rOPg= cloud.google.com/go v0.34.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= +cloud.google.com/go v0.38.0/go.mod h1:990N+gfupTy94rShfmMCWGDn0LpTmnzTp2qbd1dvSRU= +cloud.google.com/go v0.44.1/go.mod h1:iSa0KzasP4Uvy3f1mN/7PiObzGgflwredwwASm/v6AU= +cloud.google.com/go v0.44.2/go.mod h1:60680Gw3Yr4ikxnPRS/oxxkBccT6SA1yMk63TGekxKY= +cloud.google.com/go v0.45.1/go.mod h1:RpBamKRgapWJb87xiFSdk4g1CME7QZg3uwTez+TSTjc= +cloud.google.com/go v0.46.3/go.mod h1:a6bKKbmY7er1mI7TEI4lsAkts/mkhTSZK8w33B4RAg0= +cloud.google.com/go v0.50.0/go.mod h1:r9sluTvynVuxRIOHXQEHMFffphuXHOMZMycpNR5e6To= +cloud.google.com/go v0.52.0/go.mod h1:pXajvRH/6o3+F9jDHZWQ5PbGhn+o8w9qiu/CffaVdO4= +cloud.google.com/go v0.53.0/go.mod h1:fp/UouUEsRkN6ryDKNW/Upv/JBKnv6WDthjR6+vze6M= +cloud.google.com/go v0.54.0/go.mod h1:1rq2OEkV3YMf6n/9ZvGWI3GWw0VoqH/1x2nd8Is/bPc= +cloud.google.com/go v0.56.0/go.mod h1:jr7tqZxxKOVYizybht9+26Z/gUq7tiRzu+ACVAMbKVk= +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.65.0 h1:Dg9iHVQfrhq82rUNu9ZxUDrJLaxFUe/HlCVaLyRruq8= +cloud.google.com/go v0.65.0/go.mod h1:O5N8zS7uWy9vkA9vayVHs65eM1ubvY4h553ofrNHObY= +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.4.0/go.mod h1:S8dzgnTigyfTmLBfrtrhyYhwRxG72rYxvftPBK2Dvzc= +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.8.0/go.mod h1:J5hqkt3O0uAFnINi6JXValWIb1v0goeZM77hZzJN/fQ= +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/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.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/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.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.10.0/go.mod h1:FLPqc6j+Ki4BU591ie1oL6qBQGu2Bl/tZ9ullr3+Kg0= +dmitri.shuralyov.com/gpu/mtl v0.0.0-20190408044501-666a987793e9/go.mod h1:H6x//7gZCb22OMCxBHrMx7a5I7Hp++hsVxbQ4BYO7hU= github.com/BurntSushi/toml v0.3.1 h1:WXkYYl6Yr3qBf1K79EBnL4mak0OimBfB0XUf9Vl28OQ= github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= +github.com/BurntSushi/xgb v0.0.0-20160522181843-27f122750802/go.mod h1:IVnqGOEym/WlBOVXweHU+Q+/VP0lqqI8lqeDx9IjBqo= github.com/OneOfOne/xxhash v1.2.2/go.mod h1:HSdplMjZKSmBqAxg5vPj2TmRDmfkzw+cTzAElWljhcU= github.com/alecthomas/template v0.0.0-20160405071501-a0175ee3bccc/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc= github.com/alecthomas/template v0.0.0-20190718012654-fb15b899a751/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc= @@ -22,8 +54,12 @@ github.com/certifi/gocertifi v0.0.0-20200922220541-2c3bb06c6054 h1:uH66TXeswKn5P github.com/certifi/gocertifi v0.0.0-20200922220541-2c3bb06c6054/go.mod h1:sGbDF6GwGcLpkNXPUTkMRoywsNa/ol15pxFe6ERfguA= github.com/cespare/xxhash v1.1.0 h1:a6HrQnmkObjyL+Gs60czilIUGqrzKutQD6XZog3p+ko= github.com/cespare/xxhash v1.1.0/go.mod h1:XrSqR1VqqWfGrhpAt58auRo0WTKS1nRRg3ghfAqPWnc= -github.com/cespare/xxhash/v2 v2.1.1 h1:6MnRN8NT7+YBpUIWxHtefFZOKTAPgGjpQSxqLNn0+qY= github.com/cespare/xxhash/v2 v2.1.1/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= +github.com/cespare/xxhash/v2 v2.1.2 h1:YRXhKfTDauu4ajMg1TPgFO5jnlC2HCbmLXMcTG5cbYE= +github.com/cespare/xxhash/v2 v2.1.2/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= +github.com/chzyer/logex v1.1.10/go.mod h1:+Ywpsq7O8HXn0nuIou7OrIPyXbp3wmkHB+jjWRnGsAI= +github.com/chzyer/readline v0.0.0-20180603132655-2972be24d48e/go.mod h1:nSuG5e5PlCu98SY8svDHJxuZscDgtXS6KTTbou5AhLI= +github.com/chzyer/test v0.0.0-20180213035817-a1ea475d72b1/go.mod h1:Q3SI9o4m/ZMnBNeIyt5eFwwo7qiLfzFZmjNmxjkiQlU= github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw= github.com/cncf/udpa/go v0.0.0-20191209042840-269d4d468f6f/go.mod h1:M8M6+tZqaGXZJjfX53e64911xZQV5JYwmTeXPW+k8Sc= github.com/cncf/udpa/go v0.0.0-20201120205902-5459f2c99403/go.mod h1:WmhPx2Nbnhtbo57+VJT5O0JRkEi1Wbu0z5j0R8u5Hbk= @@ -58,6 +94,9 @@ github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7 github.com/getsentry/raven-go v0.2.0 h1:no+xWJRb5ZI7eE8TWgIq1jLulQiIoLG0IfYxv5JYMGs= github.com/getsentry/raven-go v0.2.0/go.mod h1:KungGk8q33+aIAZUIVWZDr2OfAEBsO49PX4NzFV5kcQ= github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04= +github.com/go-gl/glfw v0.0.0-20190409004039-e6da0acd62b1/go.mod h1:vR7hzQXu2zJy9AVAgeJqvqgH9Q5CA+iKCZ2gyEVpxRU= +github.com/go-gl/glfw/v3.3/glfw v0.0.0-20191125211704-12ad95a8df72/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8= +github.com/go-gl/glfw/v3.3/glfw v0.0.0-20200222043503-6f7a984d4dc4/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8= github.com/go-kit/kit v0.8.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as= github.com/go-kit/kit v0.9.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as= github.com/go-kit/log v0.1.0/go.mod h1:zbhenjAZHb184qTLMA9ZjW7ThYL0H2mk7Q6pNt4vbaY= @@ -73,13 +112,24 @@ github.com/gogo/protobuf v1.3.2/go.mod h1:P1XiOD3dCwIKUDQYPy72D8LYyHL2YPYrpS2s69 github.com/golang-jwt/jwt v3.2.2+incompatible h1:IfV12K8xAKAnZqdXVzCZ+TOjboZ2keLg81eXfW3O+oY= github.com/golang-jwt/jwt v3.2.2+incompatible/go.mod h1:8pz2t5EyA70fFQQSrl6XZXzqecmYZeUEB8OUGHkxJ+I= github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q= +github.com/golang/groupcache v0.0.0-20190702054246-869f871628b6/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= +github.com/golang/groupcache v0.0.0-20191227052852-215e87163ea7/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= +github.com/golang/groupcache v0.0.0-20200121045136-8c9f03a8e57e/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da h1:oI5xCqsCo564l8iNU+DwB5epxmsaqB+rhGL0m5jtYqE= github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= github.com/golang/mock v1.1.1/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A= +github.com/golang/mock v1.2.0/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A= +github.com/golang/mock v1.3.1/go.mod h1:sBzyDLLjw3U8JLTeZvSv8jJB+tU5PVekmnlKIyFUx0Y= +github.com/golang/mock v1.4.0/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.4/go.mod h1:l3mdAwkq5BuhzHwde/uurv3sEJeZMXNpwsxVWU71h+4= github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= github.com/golang/protobuf v1.3.1/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= github.com/golang/protobuf v1.3.2/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= github.com/golang/protobuf v1.3.3/go.mod h1:vzj43D7+SQXF/4pzW/hwtAqwc6iTitCiVSaWz5lYuqw= +github.com/golang/protobuf v1.3.4/go.mod h1:vzj43D7+SQXF/4pzW/hwtAqwc6iTitCiVSaWz5lYuqw= +github.com/golang/protobuf v1.3.5/go.mod h1:6O5/vntMXwX2lRkT1hjjk0nAC1IDOTvTlVgjlRvqsdk= github.com/golang/protobuf v1.4.0-rc.1/go.mod h1:ceaxUfeHdC40wWswd/P6IGgMaK3YpKi5j83Wpe3EHw8= github.com/golang/protobuf v1.4.0-rc.1.0.20200221234624-67d41d38c208/go.mod h1:xKAWHe0F5eneWXFV3EuXVDTCmh+JuBKY0li0aMyXATA= github.com/golang/protobuf v1.4.0-rc.2/go.mod h1:LlEzMj4AhA7rCAGe4KMBDvJI+AwstrUpVNzEA03Pprs= @@ -91,19 +141,35 @@ github.com/golang/protobuf v1.4.3/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk= 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/google/btree v0.0.0-20180813153112-4030bb1f1f0c/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ= +github.com/google/btree v1.0.0/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ= github.com/google/btree v1.0.1 h1:gK4Kx5IaGY9CD5sPJ36FHiBJ6ZXl0kilRiiCj+jdYp4= github.com/google/btree v1.0.1/go.mod h1:xXMiIv4Fb/0kKde4SpL7qlzvu5cMJDRkFDxJfI9uaxA= github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M= github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= +github.com/google/go-cmp v0.4.1/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.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.6 h1:BKbKCqvP6I+rmFHt06ZmyQtvB8xAkWdhFyr0ZUNZcxQ= github.com/google/go-cmp v0.5.6/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= +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/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-20191218002539-d4f498aebedc/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= +github.com/google/pprof v0.0.0-20200212024743-f11f1df84d12/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-20200708004538-1a94d8640e99/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= +github.com/google/renameio v0.1.0/go.mod h1:KWCgfxg9yswjAJkECMjeO8J8rahYeXnNhOm40UhjYkI= github.com/google/uuid v1.1.2/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= +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/gorilla/websocket v1.4.2 h1:+/TMaTYc4QFitKJxsQ7Yye35DkWvkdLcvGKqM+x0Ufc= github.com/gorilla/websocket v1.4.2/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE= github.com/grpc-ecosystem/go-grpc-middleware v1.3.0 h1:+9834+KizmvFV7pXQGSXQTsaWhq2GjuNUt0aUU0YBYw= @@ -112,6 +178,9 @@ github.com/grpc-ecosystem/go-grpc-prometheus v1.2.0 h1:Ovs26xHkKqVztRpIrF/92Bcuy github.com/grpc-ecosystem/go-grpc-prometheus v1.2.0/go.mod h1:8NvIoxWQoOIhqOTXgfV/d3M/q6VIi02HzZEHgUlZvzk= github.com/grpc-ecosystem/grpc-gateway v1.16.0 h1:gmcG1KaJ57LophUzW0Hy8NmPhnMZb4M0+kPpLofRdBo= github.com/grpc-ecosystem/grpc-gateway v1.16.0/go.mod h1:BDjrQk3hbvj6Nolgz8mAMFbcEtjT1g+wF4CSlocrBnw= +github.com/hashicorp/golang-lru v0.5.0/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8= +github.com/hashicorp/golang-lru v0.5.1/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8= +github.com/ianlancetaylor/demangle v0.0.0-20181102032728-5e5cf60278f6/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc= github.com/inconshreveable/mousetrap v1.0.0 h1:Z8tu5sraLXCXIcARxBp/8cbvlwVa7Z1NHg9XEKhtSvM= github.com/inconshreveable/mousetrap v1.0.0/go.mod h1:PxqpIevigyE2G7u3NXJIT2ANytuPF1OarO4DADm73n8= github.com/jonboulle/clockwork v0.2.2 h1:UOGuzwb1PwsrDAObMuhUnj0p5ULPj8V/xJ7Kx9qUBdQ= @@ -120,6 +189,9 @@ github.com/jpillora/backoff v1.0.0/go.mod h1:J/6gKK9jxlEcS3zixgDgUAsiuZ7yrSoa/FX github.com/json-iterator/go v1.1.6/go.mod h1:+SdeFBvtyEkXs7REEP0seUULqWtbJapLOCVDaaPEHmU= github.com/json-iterator/go v1.1.10/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4= github.com/json-iterator/go v1.1.11/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4= +github.com/json-iterator/go v1.1.12/go.mod h1:e30LSqwooZae/UwlEbR2852Gd8hjQvJoHmT4TnhNGBo= +github.com/jstemmer/go-junit-report v0.0.0-20190106144839-af01ea7f8024/go.mod h1:6v2b51hI/fHJwM22ozAgKL4VKDeJcHhJFhtBdhmNjmU= +github.com/jstemmer/go-junit-report v0.9.1/go.mod h1:Brl9GWCQeLvo8nXZwPNNblvFj/XSXhF0NWZEnDohbsk= github.com/julienschmidt/httprouter v1.2.0/go.mod h1:SYymIcj16QtmaHHD7aYtjjsJG7VTCxuUUipMqKk8s4w= github.com/julienschmidt/httprouter v1.3.0/go.mod h1:JR6WtHb+2LUe8TCKY3cZOxFyyO8IZAc4RVcycCCAKdM= github.com/kisielk/errcheck v1.2.0/go.mod h1:/BMXB+zMLi60iA8Vv6Ksmxu/1UDYcXs4uQLJ+jE2L00= @@ -140,6 +212,7 @@ github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJ github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= github.com/modern-go/reflect2 v0.0.0-20180701023420-4b7aa43c6742/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0= github.com/modern-go/reflect2 v1.0.1/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0= +github.com/modern-go/reflect2 v1.0.2/go.mod h1:yWuevngMOJpCy52FWWMvUC8ws7m/LJsjYzDa0/r8luk= github.com/mwitkow/go-conntrack v0.0.0-20161129095857-cc309e4a2223/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U= github.com/mwitkow/go-conntrack v0.0.0-20190716064945-2f068394615f/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U= github.com/opentracing/opentracing-go v1.1.0/go.mod h1:UkNAQd3GIcIGf0SeVgPpRdFStlNbqXla1AfSYxPUl2o= @@ -152,8 +225,9 @@ github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZN github.com/prometheus/client_golang v0.9.1/go.mod h1:7SWBe2y4D6OKWSNQJUaRYU/AaXPKyh/dDVn+NZz0KFw= github.com/prometheus/client_golang v1.0.0/go.mod h1:db9x61etRT2tGnBNRi70OPL5FsnadC4Ky3P0J6CfImo= github.com/prometheus/client_golang v1.7.1/go.mod h1:PY5Wy2awLA44sXw4AOSfFBetzPP4j5+D6mVACh+pe2M= -github.com/prometheus/client_golang v1.11.0 h1:HNkLOAEQMIDv/K+04rukrLx6ch7msSRwf3/SASFAGtQ= github.com/prometheus/client_golang v1.11.0/go.mod h1:Z6t4BnS23TR94PD6BsDNk8yVqroYurpAkEiz0P2BEV0= +github.com/prometheus/client_golang v1.12.1 h1:ZiaPsmm9uiBeaSMRznKsCDNtPCS0T3JVDGF+06gjBzk= +github.com/prometheus/client_golang v1.12.1/go.mod h1:3Z9XVyYiZYEO+YQWt3RD2R3jrbd179Rt297l4aS6nDY= github.com/prometheus/client_model v0.0.0-20180712105110-5c3871d89910/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo= github.com/prometheus/client_model v0.0.0-20190129233127-fd36f4220a90/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= @@ -161,14 +235,17 @@ github.com/prometheus/client_model v0.2.0 h1:uq5h0d+GuxiXLJLNABMgp2qUWDPiLvgCzz2 github.com/prometheus/client_model v0.2.0/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= github.com/prometheus/common v0.4.1/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y86RQel1bk4= github.com/prometheus/common v0.10.0/go.mod h1:Tlit/dnDKsSWFlCLTWaA1cyBgKHSMdTB80sz/V91rCo= -github.com/prometheus/common v0.26.0 h1:iMAkS2TDoNWnKM+Kopnx/8tnEStIfpYA0ur0xQzzhMQ= github.com/prometheus/common v0.26.0/go.mod h1:M7rCNAaPfAosfx8veZJCuw84e35h3Cfd9VFqTh1DIvc= +github.com/prometheus/common v0.32.1 h1:hWIdL3N2HoUx3B8j3YN9mWor0qhY/NlEKZEaXxuIRh4= +github.com/prometheus/common v0.32.1/go.mod h1:vu+V0TpY+O6vW9J44gczi3Ap/oXXR10b+M/gUGO4Hls= github.com/prometheus/procfs v0.0.0-20181005140218-185b4288413d/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk= github.com/prometheus/procfs v0.0.2/go.mod h1:TjEm7ze935MbeOT/UhFTIMYKhuLP4wbCsTZCD3I8kEA= github.com/prometheus/procfs v0.1.3/go.mod h1:lV6e/gmhEcM9IjHGsFOCxxuZ+z1YqCvr4OA4YeYWdaU= -github.com/prometheus/procfs v0.6.0 h1:mxy4L2jP6qMonqmq+aTtOx1ifVWUgG/TAmntgbh3xv4= github.com/prometheus/procfs v0.6.0/go.mod h1:cz+aTbrPOrUb4q7XlbU9ygM+/jj0fzG6c1xBZuNvfVA= +github.com/prometheus/procfs v0.7.3 h1:4jVXhlkAyzOScmCkXBTOLRLTz8EeU+eyjrwB/EPq0VU= +github.com/prometheus/procfs v0.7.3/go.mod h1:cz+aTbrPOrUb4q7XlbU9ygM+/jj0fzG6c1xBZuNvfVA= github.com/rogpeppe/fastuuid v1.2.0/go.mod h1:jVj6XXZzXRy/MSR5jhDC/2q6DgLz+nrA6LYCDYWNEvQ= +github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4= github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= github.com/sirupsen/logrus v1.2.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPxbbu5VWo= github.com/sirupsen/logrus v1.4.2/go.mod h1:tLMulIdttU9McNUspp0xgXVQah82FyeX6MwdIuYE2rE= @@ -194,10 +271,17 @@ github.com/tmc/grpc-websocket-proxy v0.0.0-20201229170055-e5319fda7802 h1:uruHq4 github.com/tmc/grpc-websocket-proxy v0.0.0-20201229170055-e5319fda7802/go.mod h1:ncp9v5uamzpCO7NfCPTXjqaC+bZgJeR0sMTm6dMHP7U= github.com/xiang90/probing v0.0.0-20190116061207-43a291ad63a2 h1:eY9dn8+vbi4tKz5Qo6v2eYzo7kUS51QINcR5jNpbZS8= github.com/xiang90/probing v0.0.0-20190116061207-43a291ad63a2/go.mod h1:UETIi67q53MR2AWcXfiuqkDkRtnGDLqkBTpCHuJHxtU= +github.com/yuin/goldmark v1.1.25/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= +github.com/yuin/goldmark v1.1.32/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= go.etcd.io/bbolt v1.3.6 h1:/ecaJf0sk1l4l6V4awd65v2C3ILy7MSj+s/x1ADCIMU= go.etcd.io/bbolt v1.3.6/go.mod h1:qXsaaIqmgQH0T+OPdb99Bf+PKfBBQVAdyD6TY9G8XM4= +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.2/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.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.26.1 h1:puWrOArBwWlr5dq6vyZ6fKykHyS8JgMIVhTBA8XsGuU= go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.26.1/go.mod h1:4wsfAAW5N9wUHM0QTmZS8z7fvYZ1rv3m+sVeSpf8NhU= go.opentelemetry.io/otel v1.1.0/go.mod h1:7cww0OW51jQ8IaZChIEdqLwgh+44+7uiTdWsAL0wQpA= @@ -229,14 +313,40 @@ go.uber.org/zap v1.17.0 h1:MTjgFu6ZLKvY6Pvaqk97GlxNBuMpV4Hy/3P6tRGlI2U= go.uber.org/zap v1.17.0/go.mod h1:MXVU+bhUf/A7Xi2HNOnopQOrmycQ5Ih87HtOu4q5SSo= golang.org/x/crypto v0.0.0-20180904163835-0709b304e793/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= +golang.org/x/crypto v0.0.0-20190510104115-cbcb75029529/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= +golang.org/x/crypto v0.0.0-20190605123033-f99c8df09eb5/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= golang.org/x/crypto v0.0.0-20210513164829-c07d793c2f9a h1:kr2P4QFmQr29mSLA43kwrOcgcReGTfbE9N577tCTuBc= golang.org/x/crypto v0.0.0-20210513164829-c07d793c2f9a/go.mod h1:P+XmwS30IXTQdn5tA2iutPOUgjI07+tq3H3K9MVA1s8= golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= +golang.org/x/exp v0.0.0-20190306152737-a1d7652674e8/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= +golang.org/x/exp v0.0.0-20190510132918-efd6b22b2522/go.mod h1:ZjyILWgesfNpC6sMxTJOJm9Kp84zZh5NQWvqDGG3Qr8= +golang.org/x/exp v0.0.0-20190829153037-c13cbed26979/go.mod h1:86+5VVa7VpoJ4kLfm080zCjGlMRFzhUhsZKEZO7MGek= +golang.org/x/exp v0.0.0-20191030013958-a1ab85dbe136/go.mod h1:JXzH8nQsPlswgeRAPE3MuO9GYsAcnJvJ4vnMwN/5qkY= +golang.org/x/exp v0.0.0-20191129062945-2f5052295587/go.mod h1:2RIsYlXP63K8oxa1u096TMicItID8zy7Y6sNkU49FU4= +golang.org/x/exp v0.0.0-20191227195350-da58074b4299/go.mod h1:2RIsYlXP63K8oxa1u096TMicItID8zy7Y6sNkU49FU4= +golang.org/x/exp v0.0.0-20200119233911-0405dc783f0a/go.mod h1:2RIsYlXP63K8oxa1u096TMicItID8zy7Y6sNkU49FU4= +golang.org/x/exp v0.0.0-20200207192155-f17229e696bd/go.mod h1:J/WKrq2StrnmMY6+EHIKF9dgMWnmCNThgcyBT1FY9mM= +golang.org/x/exp v0.0.0-20200224162631-6cc2880d07d6/go.mod h1:3jZMyOhIsHpP37uCMkUooju7aAi5cS1Q23tOzKc+0MU= +golang.org/x/image v0.0.0-20190227222117-0694c2d4d067/go.mod h1:kZ7UVZpmo3dzQBMxlp+ypCbDeSB+sBbTgSJuh5dn5js= +golang.org/x/image v0.0.0-20190802002840-cff245a6509b/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0= golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE= golang.org/x/lint v0.0.0-20190227174305-5b3e6a55c961/go.mod h1:wehouNa3lNwaWXcvxsM5YxQ5yQlVC4a0KAMCusXpPoU= +golang.org/x/lint v0.0.0-20190301231843-5614ed5bae6f/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE= golang.org/x/lint v0.0.0-20190313153728-d0100b6bd8b3/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= +golang.org/x/lint v0.0.0-20190409202823-959b441ac422/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= +golang.org/x/lint v0.0.0-20190909230951-414d861bb4ac/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= +golang.org/x/lint v0.0.0-20190930215403-16217165b5de/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= +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-20200302205851-738671d3881b/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-20190719004257-d2bd2a29d028/go.mod h1:E/iHnbuqvinMTCcRqshq8CkpyQDoeVncDDYHnLhea+o= +golang.org/x/mod v0.0.0-20190513183733-4bf6d317e70e/go.mod h1:mXi4GBBbnImb6dmsKGUJ2LatrhH/nqhxcFungHvyanc= +golang.org/x/mod v0.1.0/go.mod h1:0QHyrYULN0/3qlju5TqG8bIK38QM8yzMo5ekMj3DlcY= +golang.org/x/mod v0.1.1-0.20191105210325-c90efee705ee/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.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= @@ -246,39 +356,83 @@ golang.org/x/net v0.0.0-20190108225652-1e06a53dbb7e/go.mod h1:mL1N/T3taQHkDXs73r golang.org/x/net v0.0.0-20190213061140-3a22650c66bd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= +golang.org/x/net v0.0.0-20190501004415-9ce7a6920f09/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= +golang.org/x/net v0.0.0-20190503192946-f4e77d36d62c/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= +golang.org/x/net v0.0.0-20190603091049-60506f45cf65/go.mod h1:HSz+uSET+XFnRR8LxR5pz3Of3rY3CfYBVs4xY44aLks= golang.org/x/net v0.0.0-20190613194153-d28f0bde5980/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20190628185345-da137c7871d7/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20190724013045-ca1201d0de80/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20191209160850-c0dbc17a3553/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20200114155413-6afb5195e5aa/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20200202094626-16171245cfb2/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20200222125558-5a598a2470a0/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20200226121028-0de0cce0169b/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20200301022130-244492dfa37a/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20200324143707-d3edc9973b7e/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= +golang.org/x/net v0.0.0-20200501053045-e0ff5e5a1de5/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= +golang.org/x/net v0.0.0-20200506145744-7e3656a0809f/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= +golang.org/x/net v0.0.0-20200513185701-a91f0712d120/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= +golang.org/x/net v0.0.0-20200520182314-0ba52f642ac2/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= golang.org/x/net v0.0.0-20200625001655-4c5254603344/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-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= golang.org/x/net v0.0.0-20201202161906-c7110b5ffcbb/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= golang.org/x/net v0.0.0-20210405180319-a5a99cb37ef4/go.mod h1:p54w0d4576C0XHj96bSt6lcn1PtDYWL6XObtHCRCNQM= +golang.org/x/net v0.0.0-20210525063256-abc453219eb5/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= golang.org/x/net v0.0.0-20220105145211-5b0dc2dfae98 h1:+6WJMRLHlD7X7frgp7TUZ36RnQzSf9wVVTNakEp+nqY= golang.org/x/net v0.0.0-20220105145211-5b0dc2dfae98/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= 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-20200107190931-bf48bf16ab8d h1:TzXSXBo42m9gQenoE3b9BGiEpg5IG2JkU5FkPIawgtw= +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-20200107190931-bf48bf16ab8d/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= +golang.org/x/oauth2 v0.0.0-20210514164344-f6687ab2804c h1:pkQiBZBvdos9qq4wBAHqlzuZHEXo07pqV06ef90u1WI= +golang.org/x/oauth2 v0.0.0-20210514164344-f6687ab2804c/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= 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-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20190227155943-e225da77a7e6/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20200317015054-43a5402ce75a/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20200625203802-6e8e738ad208/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/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-20181116152217-5ac8a444bdc5/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20190312061237-fead79001313/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190422165155-953cdadca894/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190502145724-3ef323f4f1fd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190507160741-ecd444e8653b/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190606165138-5da285871e9c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190624142023-c5567b49c5d0/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190726091711-fc99dfbffb4e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20191001151750-bb3f8db39f24/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20191026070338-33540a1f6037/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20191204072324-ce4227a45e2e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20191228213918-04cbcbbfeed8/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200106162015-b016eb3dc98e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200113162924-86b910548bc1/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200122134326-e047566fdf82/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200202164722-d101bd2416d5/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200212091648-12a6c2dcc1e4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200223170610-d5e6a3e2c0ae/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200302150141-5c8b2ff67527/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200331124033-c3d80250170d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200501052902-10377860bb8e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200511232937-7e40ca221e25/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200515095857-1151b9dac4a9/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200523222454-059865788121/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-20200803210538-64077c9b5642/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200923182605-d9f96fdee20d/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= @@ -289,16 +443,21 @@ golang.org/x/sys v0.0.0-20210423185535-09eb48e85fd7/go.mod h1:h1NjWce9XRLGQEsW7w golang.org/x/sys v0.0.0-20210510120138-977fb7262007/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-20211123173158-ef496fb156ab h1:rfJ1bsoJQQIAoAxTxB7bme+vHrNkRw8CqfsYh9w54cw= -golang.org/x/sys v0.0.0-20211123173158-ef496fb156ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20220114195835-da31bd327af9 h1:XfKQ4OlFl8okEOr5UvAqFRVj8pY/4yfcXrddB8qAbU0= +golang.org/x/sys v0.0.0-20220114195835-da31bd327af9/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= +golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= +golang.org/x/text v0.3.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.3/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.7 h1:olpwvP2KacW1ZWvsR7uQhoyTYvKAupfQrRGBFM352Gk= golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ= +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-20191024005414-555d28b269f0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.0.0-20210220033141-f8bda1e9f3ba h1:O8mE0/t419eoIwhTFpKVkHiTs/Igowgfkj25AcZrtiE= golang.org/x/time v0.0.0-20210220033141-f8bda1e9f3ba/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= @@ -306,30 +465,117 @@ golang.org/x/tools v0.0.0-20181030221726-6c7e314b6563/go.mod h1:n7NCudcB/nEzxVGm 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-20190311212946-11955173bddd/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= +golang.org/x/tools v0.0.0-20190312151545-0bb0c0a6e846/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= +golang.org/x/tools v0.0.0-20190312170243-e65039ee4138/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= +golang.org/x/tools v0.0.0-20190425150028-36563e24a262/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q= +golang.org/x/tools v0.0.0-20190506145303-2d16b83fe98c/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q= golang.org/x/tools v0.0.0-20190524140312-2c0ae7006135/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q= +golang.org/x/tools v0.0.0-20190606124116-d0a3d012864b/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc= +golang.org/x/tools v0.0.0-20190621195816-6e04913cbbac/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc= +golang.org/x/tools v0.0.0-20190628153133-6cdbf07be9d0/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc= +golang.org/x/tools v0.0.0-20190816200558-6889da9d5479/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-20190911174233-4f2ddba30aff/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-20191012152004-8de300cfc20a/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-20191113191852-77e3bb0ad9e7/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-20191115202509-3a792d9c32b2/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-20191125144606-a911d9008d1f/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-20191130070609-6e064ea0cf2d/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-20191216173652-a0e659d51361/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= +golang.org/x/tools v0.0.0-20191227053925-7b8e75db28f4/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= +golang.org/x/tools v0.0.0-20200117161641-43d50277825c/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= +golang.org/x/tools v0.0.0-20200122220014-bf1340f18c4a/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= +golang.org/x/tools v0.0.0-20200130002326-2f3ba24bd6e7/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= +golang.org/x/tools v0.0.0-20200204074204-1cc6d1ef6c74/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= +golang.org/x/tools v0.0.0-20200207183749-b753a1ba74fa/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= +golang.org/x/tools v0.0.0-20200212150539-ea181f53ac56/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= +golang.org/x/tools v0.0.0-20200224181240-023911ca70b2/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= +golang.org/x/tools v0.0.0-20200227222343-706bc42d1f0d/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= +golang.org/x/tools v0.0.0-20200304193943-95d2e580d8eb/go.mod h1:o4KQGtdN14AW+yjsvvwRTJJuXz8XRtIHtEnmAXLyFUw= +golang.org/x/tools v0.0.0-20200312045724-11d5b4c81c7d/go.mod h1:o4KQGtdN14AW+yjsvvwRTJJuXz8XRtIHtEnmAXLyFUw= +golang.org/x/tools v0.0.0-20200331025713-a30bf2db82d4/go.mod h1:Sl4aGygMT6LrqrWclx+PTx3U+LnKx/seiNR+3G19Ar8= +golang.org/x/tools v0.0.0-20200501065659-ab2804fb9c9d/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= +golang.org/x/tools v0.0.0-20200512131952-2bc93b1c0c88/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= +golang.org/x/tools v0.0.0-20200515010526-7d3b6ebf133d/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= +golang.org/x/tools v0.0.0-20200618134242-20370b0cb4b2/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= golang.org/x/tools v0.0.0-20200619180055-7c47624df98f/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= +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-20200825202427-b303f430e36d/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA= golang.org/x/tools v0.0.0-20210106214847-113979e3529a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= 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-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1 h1:go1bK/D/BFZV2I8cIQd1NKEZ+0owSTG1fDTci4IqFcE= golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +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.8.0/go.mod h1:o4eAsZoiT+ibD93RtjEohWalFOjRDx6CVaqeizhEnKg= +google.golang.org/api v0.9.0/go.mod h1:o4eAsZoiT+ibD93RtjEohWalFOjRDx6CVaqeizhEnKg= +google.golang.org/api v0.13.0/go.mod h1:iLdEw5Ide6rF15KTC1Kkl0iskquN2gFfn9o9XIsbkAI= +google.golang.org/api v0.14.0/go.mod h1:iLdEw5Ide6rF15KTC1Kkl0iskquN2gFfn9o9XIsbkAI= +google.golang.org/api v0.15.0/go.mod h1:iLdEw5Ide6rF15KTC1Kkl0iskquN2gFfn9o9XIsbkAI= +google.golang.org/api v0.17.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE= +google.golang.org/api v0.18.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE= +google.golang.org/api v0.19.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE= +google.golang.org/api v0.20.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE= +google.golang.org/api v0.22.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE= +google.golang.org/api v0.24.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.30.0/go.mod h1:QGmEvQ87FHZNiUVJkT14jQNYJ4ZJjdRF23ZXz5138Fc= google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM= -google.golang.org/appengine v1.4.0 h1:/wp5JvzpHIxhs/dumFmF7BXTf3Z+dd4uXta4kVyO508= 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.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.6 h1:lMO5rYAqUxkmaj76jAkRUvt5JZgFymx/+Q5Mzfivuhc= +google.golang.org/appengine v1.6.6/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-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-20190425155659-357c62f0e4bb/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= +google.golang.org/genproto v0.0.0-20190502173448-54afdca5d873/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= +google.golang.org/genproto v0.0.0-20190801165951-fa694d86fc64/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc= google.golang.org/genproto v0.0.0-20190819201941-24fa4b261c55/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc= +google.golang.org/genproto v0.0.0-20190911173649-1774047e7e51/go.mod h1:IbNlFCBrqXvoKpeg0TB2l7cyZUmoaFKYIwrEpbDKLA8= +google.golang.org/genproto v0.0.0-20191108220845-16a3f7862a1a/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= +google.golang.org/genproto v0.0.0-20191115194625-c23dd37a84c9/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= +google.golang.org/genproto v0.0.0-20191216164720-4f79533eabd1/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= +google.golang.org/genproto v0.0.0-20191230161307-f3c370f40bfb/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= +google.golang.org/genproto v0.0.0-20200115191322-ca5a22157cba/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= +google.golang.org/genproto v0.0.0-20200122232147-0452cf42e150/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= +google.golang.org/genproto v0.0.0-20200204135345-fa8e72b47b90/go.mod h1:GmwEX6Z4W5gMy59cAlVYjN9JhxgbQH6Gn+gFDQe2lzA= +google.golang.org/genproto v0.0.0-20200212174721-66ed5ce911ce/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= +google.golang.org/genproto v0.0.0-20200224152610-e50cd9704f63/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= +google.golang.org/genproto v0.0.0-20200228133532-8c2c7df3a383/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= +google.golang.org/genproto v0.0.0-20200305110556-506484158171/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= +google.golang.org/genproto v0.0.0-20200312145019-da6875a35672/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= +google.golang.org/genproto v0.0.0-20200331122359-1ee6d9798940/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= google.golang.org/genproto v0.0.0-20200423170343-7949de9c1215/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= +google.golang.org/genproto v0.0.0-20200430143042-b979b6f78d84/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= +google.golang.org/genproto v0.0.0-20200511104702-f5ebc3bea380/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= google.golang.org/genproto v0.0.0-20200513103714-09dca8ec2884/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= +google.golang.org/genproto v0.0.0-20200515170657-fc4c6c6a6587/go.mod h1:YsZOwe1myG/8QRHRsmBRE1LrgQY60beZKjly0O1fX9U= google.golang.org/genproto v0.0.0-20200526211855-cb27e3aa2013/go.mod h1:NbSheEEYHJ7i3ixzK3sjbqSGDJWnxyFXZblF3eUsNvo= +google.golang.org/genproto v0.0.0-20200618031413-b414f8b61790/go.mod h1:jDfRM7FcilCzHH/e9qn6dsT145K34l5v+OpcnNgKAAA= +google.golang.org/genproto v0.0.0-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-20200825200019-8632dd797987/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= google.golang.org/genproto v0.0.0-20211118181313-81c1377c94b1 h1:b9mVrqYfq3P4bCdaLg1qtBnPzUYgglsIdjZkL/fQVOE= google.golang.org/genproto v0.0.0-20211118181313-81c1377c94b1/go.mod h1:5CzLGKJ67TSI2B9POpiiyGha0AjJvZIUgRMt1dSmuhc= 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.21.1/go.mod h1:oYelfM1adQP15Ek0mdvEgi9Df8B9CZIaU1084ijfRaM= google.golang.org/grpc v1.23.0/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg= google.golang.org/grpc v1.25.1/go.mod h1:c3i+UQWmh7LiEpx4sFZnkU36qjEYZ0imhYfXVyQciAY= +google.golang.org/grpc v1.26.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk= google.golang.org/grpc v1.27.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk= +google.golang.org/grpc v1.27.1/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk= +google.golang.org/grpc v1.28.0/go.mod h1:rpkK4SK4GF4Ach/+MFLZUBavHOvF2JJB5uozKKal+60= 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.31.0/go.mod h1:N36X2cJ7JwdamYAgDz+s+rVMFjt3numwzf/HckM8pak= google.golang.org/grpc v1.33.1/go.mod h1:fr5YgcSWrqhRRxogOsw7RzIpsmvOZ6IcH4kBYTpR3n0= google.golang.org/grpc v1.36.0/go.mod h1:qjiiYl8FncCW8feJPdyg3v6XW24KsRHe+dy9BAGRRjU= google.golang.org/grpc v1.37.1/go.mod h1:NREThFqKR1f3iQ6oBuvc5LadQuXVGo9rkm5ZGrQdJfM= @@ -344,6 +590,7 @@ google.golang.org/protobuf v1.21.0/go.mod h1:47Nbq4nVaFHyn7ilMalzfO3qCViNmqZ2kzi google.golang.org/protobuf v1.22.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= google.golang.org/protobuf v1.23.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= google.golang.org/protobuf v1.23.1-0.20200526195155-81db48ad09cc/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= +google.golang.org/protobuf v1.24.0/go.mod h1:r/3tXBNzIEhYS9I1OUVjXDlt8tc493IdKGjtUeSXeh4= google.golang.org/protobuf v1.25.0/go.mod h1:9JNX74DMeImyA3h4bdi1ymwjUzf21/xIlbajtzgsN7c= google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw= google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc= @@ -351,8 +598,10 @@ google.golang.org/protobuf v1.27.1 h1:SnqbnDw1V7RiZcXPx5MEeqPv2s79L9i7BJUlG/+Rur google.golang.org/protobuf v1.27.1/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc= gopkg.in/alecthomas/kingpin.v2 v2.2.6/go.mod h1:FMv+mEhP44yOT+4EoQTLFTRgOQ1FBLkstjWtayDeSgw= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15 h1:YR8cESwS4TdDjEe65xsg0ogRM/Nc3DYOhEAlW+xobZo= gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/errgo.v2 v2.1.0/go.mod h1:hNsd1EY+bozCKY1Ytp96fpM3vjJbqLJn88ws8XvfDNI= gopkg.in/natefinch/lumberjack.v2 v2.0.0 h1:1Lc07Kr7qY4U2YPouBjpCLxpiyxIVoxqXgkXLknAOE8= gopkg.in/natefinch/lumberjack.v2 v2.0.0/go.mod h1:l0ndWWf7gzL7RNwBG7wST/UCcT4T24xpD6X8LsfU/+k= gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= @@ -368,7 +617,15 @@ gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b h1:h8qDotaEPuJATrMmW04NCwg7v22aHH28wwpauUhK9Oo= gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= +honnef.co/go/tools v0.0.0-20190106161140-3f1c8253044a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= +honnef.co/go/tools v0.0.0-20190418001031-e561f6794a2a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= honnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= +honnef.co/go/tools v0.0.1-2019.2.3/go.mod h1:a3bituU0lyd329TUQxRnasdCoJDkEUEAqEt0JzvZhAg= +honnef.co/go/tools v0.0.1-2020.1.3/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9vFzvIQ3k= +honnef.co/go/tools v0.0.1-2020.1.4/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9vFzvIQ3k= +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/sampler v1.3.0/go.mod h1:T1hPZKmBbMNahiBKFy5HrXp6adAjACjK9JXDnKaTXpA= sigs.k8s.io/json v0.0.0-20211020170558-c049b76a60c6 h1:fD1pz4yfdADVNfFmcP2aBEtudwUQ1AlLnRBALr33v3s= sigs.k8s.io/json v0.0.0-20211020170558-c049b76a60c6/go.mod h1:p4QtZmO4uMYipTQNzagwnNoseA6OxSUutVw05NhYDRs= sigs.k8s.io/yaml v1.2.0 h1:kr/MCeFWJWTwyaHoR9c8EjH9OumOmoF9YGiZd7lFm/Q= diff --git a/tests/go.mod b/tests/go.mod index 6ddea1a12740..9952630ec00d 100644 --- a/tests/go.mod +++ b/tests/go.mod @@ -23,7 +23,7 @@ require ( github.com/grpc-ecosystem/go-grpc-middleware v1.3.0 github.com/grpc-ecosystem/go-grpc-prometheus v1.2.0 github.com/grpc-ecosystem/grpc-gateway v1.16.0 - github.com/prometheus/client_golang v1.11.0 + github.com/prometheus/client_golang v1.12.1 github.com/soheilhy/cmux v0.1.5 github.com/spf13/cobra v1.4.0 github.com/spf13/pflag v1.0.5 @@ -48,7 +48,7 @@ require ( require ( github.com/beorn7/perks v1.0.1 // indirect github.com/cenkalti/backoff/v4 v4.1.1 // indirect - github.com/cespare/xxhash/v2 v2.1.1 // indirect + github.com/cespare/xxhash/v2 v2.1.2 // indirect github.com/coreos/go-systemd/v22 v22.3.2 // indirect github.com/creack/pty v1.1.11 // indirect github.com/davecgh/go-spew v1.1.1 // indirect @@ -61,8 +61,8 @@ require ( github.com/matttproud/golang_protobuf_extensions v1.0.1 // indirect github.com/pmezard/go-difflib v1.0.0 // indirect github.com/prometheus/client_model v0.2.0 // indirect - github.com/prometheus/common v0.26.0 // indirect - github.com/prometheus/procfs v0.6.0 // indirect + github.com/prometheus/common v0.32.1 // indirect + github.com/prometheus/procfs v0.7.3 // indirect github.com/sirupsen/logrus v1.8.1 // indirect github.com/tmc/grpc-websocket-proxy v0.0.0-20201229170055-e5319fda7802 // indirect github.com/xiang90/probing v0.0.0-20190116061207-43a291ad63a2 // indirect @@ -76,7 +76,7 @@ require ( go.uber.org/atomic v1.7.0 // indirect go.uber.org/multierr v1.7.0 // indirect golang.org/x/net v0.0.0-20220105145211-5b0dc2dfae98 // indirect - golang.org/x/sys v0.0.0-20211123173158-ef496fb156ab // indirect + golang.org/x/sys v0.0.0-20220114195835-da31bd327af9 // indirect golang.org/x/text v0.3.7 // indirect golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1 // indirect google.golang.org/genproto v0.0.0-20211118181313-81c1377c94b1 // indirect diff --git a/tests/go.sum b/tests/go.sum index e86ba267986c..3e71228c5633 100644 --- a/tests/go.sum +++ b/tests/go.sum @@ -1,8 +1,40 @@ cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= -cloud.google.com/go v0.34.0 h1:eOI3/cP2VTU6uZLDYAoic+eyzzB9YyGmJ7eIjl8rOPg= cloud.google.com/go v0.34.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= +cloud.google.com/go v0.38.0/go.mod h1:990N+gfupTy94rShfmMCWGDn0LpTmnzTp2qbd1dvSRU= +cloud.google.com/go v0.44.1/go.mod h1:iSa0KzasP4Uvy3f1mN/7PiObzGgflwredwwASm/v6AU= +cloud.google.com/go v0.44.2/go.mod h1:60680Gw3Yr4ikxnPRS/oxxkBccT6SA1yMk63TGekxKY= +cloud.google.com/go v0.45.1/go.mod h1:RpBamKRgapWJb87xiFSdk4g1CME7QZg3uwTez+TSTjc= +cloud.google.com/go v0.46.3/go.mod h1:a6bKKbmY7er1mI7TEI4lsAkts/mkhTSZK8w33B4RAg0= +cloud.google.com/go v0.50.0/go.mod h1:r9sluTvynVuxRIOHXQEHMFffphuXHOMZMycpNR5e6To= +cloud.google.com/go v0.52.0/go.mod h1:pXajvRH/6o3+F9jDHZWQ5PbGhn+o8w9qiu/CffaVdO4= +cloud.google.com/go v0.53.0/go.mod h1:fp/UouUEsRkN6ryDKNW/Upv/JBKnv6WDthjR6+vze6M= +cloud.google.com/go v0.54.0/go.mod h1:1rq2OEkV3YMf6n/9ZvGWI3GWw0VoqH/1x2nd8Is/bPc= +cloud.google.com/go v0.56.0/go.mod h1:jr7tqZxxKOVYizybht9+26Z/gUq7tiRzu+ACVAMbKVk= +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.65.0 h1:Dg9iHVQfrhq82rUNu9ZxUDrJLaxFUe/HlCVaLyRruq8= +cloud.google.com/go v0.65.0/go.mod h1:O5N8zS7uWy9vkA9vayVHs65eM1ubvY4h553ofrNHObY= +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.4.0/go.mod h1:S8dzgnTigyfTmLBfrtrhyYhwRxG72rYxvftPBK2Dvzc= +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.8.0/go.mod h1:J5hqkt3O0uAFnINi6JXValWIb1v0goeZM77hZzJN/fQ= +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/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.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/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.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.10.0/go.mod h1:FLPqc6j+Ki4BU591ie1oL6qBQGu2Bl/tZ9ullr3+Kg0= +dmitri.shuralyov.com/gpu/mtl v0.0.0-20190408044501-666a987793e9/go.mod h1:H6x//7gZCb22OMCxBHrMx7a5I7Hp++hsVxbQ4BYO7hU= github.com/BurntSushi/toml v0.3.1 h1:WXkYYl6Yr3qBf1K79EBnL4mak0OimBfB0XUf9Vl28OQ= github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= +github.com/BurntSushi/xgb v0.0.0-20160522181843-27f122750802/go.mod h1:IVnqGOEym/WlBOVXweHU+Q+/VP0lqqI8lqeDx9IjBqo= github.com/OneOfOne/xxhash v1.2.2/go.mod h1:HSdplMjZKSmBqAxg5vPj2TmRDmfkzw+cTzAElWljhcU= github.com/alecthomas/template v0.0.0-20160405071501-a0175ee3bccc/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc= github.com/alecthomas/template v0.0.0-20190718012654-fb15b899a751/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc= @@ -22,8 +54,12 @@ github.com/certifi/gocertifi v0.0.0-20200922220541-2c3bb06c6054 h1:uH66TXeswKn5P github.com/certifi/gocertifi v0.0.0-20200922220541-2c3bb06c6054/go.mod h1:sGbDF6GwGcLpkNXPUTkMRoywsNa/ol15pxFe6ERfguA= github.com/cespare/xxhash v1.1.0 h1:a6HrQnmkObjyL+Gs60czilIUGqrzKutQD6XZog3p+ko= github.com/cespare/xxhash v1.1.0/go.mod h1:XrSqR1VqqWfGrhpAt58auRo0WTKS1nRRg3ghfAqPWnc= -github.com/cespare/xxhash/v2 v2.1.1 h1:6MnRN8NT7+YBpUIWxHtefFZOKTAPgGjpQSxqLNn0+qY= github.com/cespare/xxhash/v2 v2.1.1/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= +github.com/cespare/xxhash/v2 v2.1.2 h1:YRXhKfTDauu4ajMg1TPgFO5jnlC2HCbmLXMcTG5cbYE= +github.com/cespare/xxhash/v2 v2.1.2/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= +github.com/chzyer/logex v1.1.10/go.mod h1:+Ywpsq7O8HXn0nuIou7OrIPyXbp3wmkHB+jjWRnGsAI= +github.com/chzyer/readline v0.0.0-20180603132655-2972be24d48e/go.mod h1:nSuG5e5PlCu98SY8svDHJxuZscDgtXS6KTTbou5AhLI= +github.com/chzyer/test v0.0.0-20180213035817-a1ea475d72b1/go.mod h1:Q3SI9o4m/ZMnBNeIyt5eFwwo7qiLfzFZmjNmxjkiQlU= github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw= github.com/cncf/udpa/go v0.0.0-20191209042840-269d4d468f6f/go.mod h1:M8M6+tZqaGXZJjfX53e64911xZQV5JYwmTeXPW+k8Sc= github.com/cncf/udpa/go v0.0.0-20201120205902-5459f2c99403/go.mod h1:WmhPx2Nbnhtbo57+VJT5O0JRkEi1Wbu0z5j0R8u5Hbk= @@ -59,6 +95,9 @@ github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7 github.com/getsentry/raven-go v0.2.0 h1:no+xWJRb5ZI7eE8TWgIq1jLulQiIoLG0IfYxv5JYMGs= github.com/getsentry/raven-go v0.2.0/go.mod h1:KungGk8q33+aIAZUIVWZDr2OfAEBsO49PX4NzFV5kcQ= github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04= +github.com/go-gl/glfw v0.0.0-20190409004039-e6da0acd62b1/go.mod h1:vR7hzQXu2zJy9AVAgeJqvqgH9Q5CA+iKCZ2gyEVpxRU= +github.com/go-gl/glfw/v3.3/glfw v0.0.0-20191125211704-12ad95a8df72/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8= +github.com/go-gl/glfw/v3.3/glfw v0.0.0-20200222043503-6f7a984d4dc4/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8= github.com/go-kit/kit v0.8.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as= github.com/go-kit/kit v0.9.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as= github.com/go-kit/log v0.1.0/go.mod h1:zbhenjAZHb184qTLMA9ZjW7ThYL0H2mk7Q6pNt4vbaY= @@ -74,13 +113,24 @@ github.com/gogo/protobuf v1.3.2/go.mod h1:P1XiOD3dCwIKUDQYPy72D8LYyHL2YPYrpS2s69 github.com/golang-jwt/jwt v3.2.2+incompatible h1:IfV12K8xAKAnZqdXVzCZ+TOjboZ2keLg81eXfW3O+oY= github.com/golang-jwt/jwt v3.2.2+incompatible/go.mod h1:8pz2t5EyA70fFQQSrl6XZXzqecmYZeUEB8OUGHkxJ+I= github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q= +github.com/golang/groupcache v0.0.0-20190702054246-869f871628b6/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= +github.com/golang/groupcache v0.0.0-20191227052852-215e87163ea7/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= +github.com/golang/groupcache v0.0.0-20200121045136-8c9f03a8e57e/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da h1:oI5xCqsCo564l8iNU+DwB5epxmsaqB+rhGL0m5jtYqE= github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= github.com/golang/mock v1.1.1/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A= +github.com/golang/mock v1.2.0/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A= +github.com/golang/mock v1.3.1/go.mod h1:sBzyDLLjw3U8JLTeZvSv8jJB+tU5PVekmnlKIyFUx0Y= +github.com/golang/mock v1.4.0/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.4/go.mod h1:l3mdAwkq5BuhzHwde/uurv3sEJeZMXNpwsxVWU71h+4= github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= github.com/golang/protobuf v1.3.1/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= github.com/golang/protobuf v1.3.2/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= github.com/golang/protobuf v1.3.3/go.mod h1:vzj43D7+SQXF/4pzW/hwtAqwc6iTitCiVSaWz5lYuqw= +github.com/golang/protobuf v1.3.4/go.mod h1:vzj43D7+SQXF/4pzW/hwtAqwc6iTitCiVSaWz5lYuqw= +github.com/golang/protobuf v1.3.5/go.mod h1:6O5/vntMXwX2lRkT1hjjk0nAC1IDOTvTlVgjlRvqsdk= github.com/golang/protobuf v1.4.0-rc.1/go.mod h1:ceaxUfeHdC40wWswd/P6IGgMaK3YpKi5j83Wpe3EHw8= github.com/golang/protobuf v1.4.0-rc.1.0.20200221234624-67d41d38c208/go.mod h1:xKAWHe0F5eneWXFV3EuXVDTCmh+JuBKY0li0aMyXATA= github.com/golang/protobuf v1.4.0-rc.2/go.mod h1:LlEzMj4AhA7rCAGe4KMBDvJI+AwstrUpVNzEA03Pprs= @@ -92,19 +142,35 @@ github.com/golang/protobuf v1.4.3/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk= 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/google/btree v0.0.0-20180813153112-4030bb1f1f0c/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ= +github.com/google/btree v1.0.0/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ= github.com/google/btree v1.0.1 h1:gK4Kx5IaGY9CD5sPJ36FHiBJ6ZXl0kilRiiCj+jdYp4= github.com/google/btree v1.0.1/go.mod h1:xXMiIv4Fb/0kKde4SpL7qlzvu5cMJDRkFDxJfI9uaxA= github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M= github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= +github.com/google/go-cmp v0.4.1/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.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.6 h1:BKbKCqvP6I+rmFHt06ZmyQtvB8xAkWdhFyr0ZUNZcxQ= github.com/google/go-cmp v0.5.6/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= +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/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-20191218002539-d4f498aebedc/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= +github.com/google/pprof v0.0.0-20200212024743-f11f1df84d12/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-20200708004538-1a94d8640e99/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= +github.com/google/renameio v0.1.0/go.mod h1:KWCgfxg9yswjAJkECMjeO8J8rahYeXnNhOm40UhjYkI= github.com/google/uuid v1.1.2/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= +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/gorilla/websocket v1.4.2 h1:+/TMaTYc4QFitKJxsQ7Yye35DkWvkdLcvGKqM+x0Ufc= github.com/gorilla/websocket v1.4.2/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE= github.com/grpc-ecosystem/go-grpc-middleware v1.3.0 h1:+9834+KizmvFV7pXQGSXQTsaWhq2GjuNUt0aUU0YBYw= @@ -113,6 +179,9 @@ github.com/grpc-ecosystem/go-grpc-prometheus v1.2.0 h1:Ovs26xHkKqVztRpIrF/92Bcuy github.com/grpc-ecosystem/go-grpc-prometheus v1.2.0/go.mod h1:8NvIoxWQoOIhqOTXgfV/d3M/q6VIi02HzZEHgUlZvzk= github.com/grpc-ecosystem/grpc-gateway v1.16.0 h1:gmcG1KaJ57LophUzW0Hy8NmPhnMZb4M0+kPpLofRdBo= github.com/grpc-ecosystem/grpc-gateway v1.16.0/go.mod h1:BDjrQk3hbvj6Nolgz8mAMFbcEtjT1g+wF4CSlocrBnw= +github.com/hashicorp/golang-lru v0.5.0/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8= +github.com/hashicorp/golang-lru v0.5.1/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8= +github.com/ianlancetaylor/demangle v0.0.0-20181102032728-5e5cf60278f6/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc= github.com/inconshreveable/mousetrap v1.0.0 h1:Z8tu5sraLXCXIcARxBp/8cbvlwVa7Z1NHg9XEKhtSvM= github.com/inconshreveable/mousetrap v1.0.0/go.mod h1:PxqpIevigyE2G7u3NXJIT2ANytuPF1OarO4DADm73n8= github.com/jonboulle/clockwork v0.2.2 h1:UOGuzwb1PwsrDAObMuhUnj0p5ULPj8V/xJ7Kx9qUBdQ= @@ -121,6 +190,9 @@ github.com/jpillora/backoff v1.0.0/go.mod h1:J/6gKK9jxlEcS3zixgDgUAsiuZ7yrSoa/FX github.com/json-iterator/go v1.1.6/go.mod h1:+SdeFBvtyEkXs7REEP0seUULqWtbJapLOCVDaaPEHmU= github.com/json-iterator/go v1.1.10/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4= github.com/json-iterator/go v1.1.11/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4= +github.com/json-iterator/go v1.1.12/go.mod h1:e30LSqwooZae/UwlEbR2852Gd8hjQvJoHmT4TnhNGBo= +github.com/jstemmer/go-junit-report v0.0.0-20190106144839-af01ea7f8024/go.mod h1:6v2b51hI/fHJwM22ozAgKL4VKDeJcHhJFhtBdhmNjmU= +github.com/jstemmer/go-junit-report v0.9.1/go.mod h1:Brl9GWCQeLvo8nXZwPNNblvFj/XSXhF0NWZEnDohbsk= github.com/julienschmidt/httprouter v1.2.0/go.mod h1:SYymIcj16QtmaHHD7aYtjjsJG7VTCxuUUipMqKk8s4w= github.com/julienschmidt/httprouter v1.3.0/go.mod h1:JR6WtHb+2LUe8TCKY3cZOxFyyO8IZAc4RVcycCCAKdM= github.com/kisielk/errcheck v1.2.0/go.mod h1:/BMXB+zMLi60iA8Vv6Ksmxu/1UDYcXs4uQLJ+jE2L00= @@ -142,6 +214,7 @@ github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJ github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= github.com/modern-go/reflect2 v0.0.0-20180701023420-4b7aa43c6742/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0= github.com/modern-go/reflect2 v1.0.1/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0= +github.com/modern-go/reflect2 v1.0.2/go.mod h1:yWuevngMOJpCy52FWWMvUC8ws7m/LJsjYzDa0/r8luk= github.com/mwitkow/go-conntrack v0.0.0-20161129095857-cc309e4a2223/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U= github.com/mwitkow/go-conntrack v0.0.0-20190716064945-2f068394615f/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U= github.com/olekukonko/tablewriter v0.0.5/go.mod h1:hPp6KlRPjbx+hW8ykQs1w3UBbZlj6HuIJcUGPhkA7kY= @@ -155,8 +228,9 @@ github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZN github.com/prometheus/client_golang v0.9.1/go.mod h1:7SWBe2y4D6OKWSNQJUaRYU/AaXPKyh/dDVn+NZz0KFw= github.com/prometheus/client_golang v1.0.0/go.mod h1:db9x61etRT2tGnBNRi70OPL5FsnadC4Ky3P0J6CfImo= github.com/prometheus/client_golang v1.7.1/go.mod h1:PY5Wy2awLA44sXw4AOSfFBetzPP4j5+D6mVACh+pe2M= -github.com/prometheus/client_golang v1.11.0 h1:HNkLOAEQMIDv/K+04rukrLx6ch7msSRwf3/SASFAGtQ= github.com/prometheus/client_golang v1.11.0/go.mod h1:Z6t4BnS23TR94PD6BsDNk8yVqroYurpAkEiz0P2BEV0= +github.com/prometheus/client_golang v1.12.1 h1:ZiaPsmm9uiBeaSMRznKsCDNtPCS0T3JVDGF+06gjBzk= +github.com/prometheus/client_golang v1.12.1/go.mod h1:3Z9XVyYiZYEO+YQWt3RD2R3jrbd179Rt297l4aS6nDY= github.com/prometheus/client_model v0.0.0-20180712105110-5c3871d89910/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo= github.com/prometheus/client_model v0.0.0-20190129233127-fd36f4220a90/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= @@ -164,14 +238,17 @@ github.com/prometheus/client_model v0.2.0 h1:uq5h0d+GuxiXLJLNABMgp2qUWDPiLvgCzz2 github.com/prometheus/client_model v0.2.0/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= github.com/prometheus/common v0.4.1/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y86RQel1bk4= github.com/prometheus/common v0.10.0/go.mod h1:Tlit/dnDKsSWFlCLTWaA1cyBgKHSMdTB80sz/V91rCo= -github.com/prometheus/common v0.26.0 h1:iMAkS2TDoNWnKM+Kopnx/8tnEStIfpYA0ur0xQzzhMQ= github.com/prometheus/common v0.26.0/go.mod h1:M7rCNAaPfAosfx8veZJCuw84e35h3Cfd9VFqTh1DIvc= +github.com/prometheus/common v0.32.1 h1:hWIdL3N2HoUx3B8j3YN9mWor0qhY/NlEKZEaXxuIRh4= +github.com/prometheus/common v0.32.1/go.mod h1:vu+V0TpY+O6vW9J44gczi3Ap/oXXR10b+M/gUGO4Hls= github.com/prometheus/procfs v0.0.0-20181005140218-185b4288413d/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk= github.com/prometheus/procfs v0.0.2/go.mod h1:TjEm7ze935MbeOT/UhFTIMYKhuLP4wbCsTZCD3I8kEA= github.com/prometheus/procfs v0.1.3/go.mod h1:lV6e/gmhEcM9IjHGsFOCxxuZ+z1YqCvr4OA4YeYWdaU= -github.com/prometheus/procfs v0.6.0 h1:mxy4L2jP6qMonqmq+aTtOx1ifVWUgG/TAmntgbh3xv4= github.com/prometheus/procfs v0.6.0/go.mod h1:cz+aTbrPOrUb4q7XlbU9ygM+/jj0fzG6c1xBZuNvfVA= +github.com/prometheus/procfs v0.7.3 h1:4jVXhlkAyzOScmCkXBTOLRLTz8EeU+eyjrwB/EPq0VU= +github.com/prometheus/procfs v0.7.3/go.mod h1:cz+aTbrPOrUb4q7XlbU9ygM+/jj0fzG6c1xBZuNvfVA= github.com/rogpeppe/fastuuid v1.2.0/go.mod h1:jVj6XXZzXRy/MSR5jhDC/2q6DgLz+nrA6LYCDYWNEvQ= +github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4= github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= github.com/sirupsen/logrus v1.2.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPxbbu5VWo= github.com/sirupsen/logrus v1.4.2/go.mod h1:tLMulIdttU9McNUspp0xgXVQah82FyeX6MwdIuYE2rE= @@ -197,10 +274,17 @@ github.com/tmc/grpc-websocket-proxy v0.0.0-20201229170055-e5319fda7802 h1:uruHq4 github.com/tmc/grpc-websocket-proxy v0.0.0-20201229170055-e5319fda7802/go.mod h1:ncp9v5uamzpCO7NfCPTXjqaC+bZgJeR0sMTm6dMHP7U= github.com/xiang90/probing v0.0.0-20190116061207-43a291ad63a2 h1:eY9dn8+vbi4tKz5Qo6v2eYzo7kUS51QINcR5jNpbZS8= github.com/xiang90/probing v0.0.0-20190116061207-43a291ad63a2/go.mod h1:UETIi67q53MR2AWcXfiuqkDkRtnGDLqkBTpCHuJHxtU= +github.com/yuin/goldmark v1.1.25/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= +github.com/yuin/goldmark v1.1.32/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= go.etcd.io/bbolt v1.3.6 h1:/ecaJf0sk1l4l6V4awd65v2C3ILy7MSj+s/x1ADCIMU= go.etcd.io/bbolt v1.3.6/go.mod h1:qXsaaIqmgQH0T+OPdb99Bf+PKfBBQVAdyD6TY9G8XM4= +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.2/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.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.26.1 h1:puWrOArBwWlr5dq6vyZ6fKykHyS8JgMIVhTBA8XsGuU= go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.26.1/go.mod h1:4wsfAAW5N9wUHM0QTmZS8z7fvYZ1rv3m+sVeSpf8NhU= go.opentelemetry.io/otel v1.1.0/go.mod h1:7cww0OW51jQ8IaZChIEdqLwgh+44+7uiTdWsAL0wQpA= @@ -232,14 +316,40 @@ go.uber.org/zap v1.17.0 h1:MTjgFu6ZLKvY6Pvaqk97GlxNBuMpV4Hy/3P6tRGlI2U= go.uber.org/zap v1.17.0/go.mod h1:MXVU+bhUf/A7Xi2HNOnopQOrmycQ5Ih87HtOu4q5SSo= golang.org/x/crypto v0.0.0-20180904163835-0709b304e793/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= +golang.org/x/crypto v0.0.0-20190510104115-cbcb75029529/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= +golang.org/x/crypto v0.0.0-20190605123033-f99c8df09eb5/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= golang.org/x/crypto v0.0.0-20210513164829-c07d793c2f9a h1:kr2P4QFmQr29mSLA43kwrOcgcReGTfbE9N577tCTuBc= golang.org/x/crypto v0.0.0-20210513164829-c07d793c2f9a/go.mod h1:P+XmwS30IXTQdn5tA2iutPOUgjI07+tq3H3K9MVA1s8= golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= +golang.org/x/exp v0.0.0-20190306152737-a1d7652674e8/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= +golang.org/x/exp v0.0.0-20190510132918-efd6b22b2522/go.mod h1:ZjyILWgesfNpC6sMxTJOJm9Kp84zZh5NQWvqDGG3Qr8= +golang.org/x/exp v0.0.0-20190829153037-c13cbed26979/go.mod h1:86+5VVa7VpoJ4kLfm080zCjGlMRFzhUhsZKEZO7MGek= +golang.org/x/exp v0.0.0-20191030013958-a1ab85dbe136/go.mod h1:JXzH8nQsPlswgeRAPE3MuO9GYsAcnJvJ4vnMwN/5qkY= +golang.org/x/exp v0.0.0-20191129062945-2f5052295587/go.mod h1:2RIsYlXP63K8oxa1u096TMicItID8zy7Y6sNkU49FU4= +golang.org/x/exp v0.0.0-20191227195350-da58074b4299/go.mod h1:2RIsYlXP63K8oxa1u096TMicItID8zy7Y6sNkU49FU4= +golang.org/x/exp v0.0.0-20200119233911-0405dc783f0a/go.mod h1:2RIsYlXP63K8oxa1u096TMicItID8zy7Y6sNkU49FU4= +golang.org/x/exp v0.0.0-20200207192155-f17229e696bd/go.mod h1:J/WKrq2StrnmMY6+EHIKF9dgMWnmCNThgcyBT1FY9mM= +golang.org/x/exp v0.0.0-20200224162631-6cc2880d07d6/go.mod h1:3jZMyOhIsHpP37uCMkUooju7aAi5cS1Q23tOzKc+0MU= +golang.org/x/image v0.0.0-20190227222117-0694c2d4d067/go.mod h1:kZ7UVZpmo3dzQBMxlp+ypCbDeSB+sBbTgSJuh5dn5js= +golang.org/x/image v0.0.0-20190802002840-cff245a6509b/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0= golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE= golang.org/x/lint v0.0.0-20190227174305-5b3e6a55c961/go.mod h1:wehouNa3lNwaWXcvxsM5YxQ5yQlVC4a0KAMCusXpPoU= +golang.org/x/lint v0.0.0-20190301231843-5614ed5bae6f/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE= golang.org/x/lint v0.0.0-20190313153728-d0100b6bd8b3/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= +golang.org/x/lint v0.0.0-20190409202823-959b441ac422/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= +golang.org/x/lint v0.0.0-20190909230951-414d861bb4ac/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= +golang.org/x/lint v0.0.0-20190930215403-16217165b5de/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= +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-20200302205851-738671d3881b/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-20190719004257-d2bd2a29d028/go.mod h1:E/iHnbuqvinMTCcRqshq8CkpyQDoeVncDDYHnLhea+o= +golang.org/x/mod v0.0.0-20190513183733-4bf6d317e70e/go.mod h1:mXi4GBBbnImb6dmsKGUJ2LatrhH/nqhxcFungHvyanc= +golang.org/x/mod v0.1.0/go.mod h1:0QHyrYULN0/3qlju5TqG8bIK38QM8yzMo5ekMj3DlcY= +golang.org/x/mod v0.1.1-0.20191105210325-c90efee705ee/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.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= @@ -249,26 +359,49 @@ golang.org/x/net v0.0.0-20190108225652-1e06a53dbb7e/go.mod h1:mL1N/T3taQHkDXs73r golang.org/x/net v0.0.0-20190213061140-3a22650c66bd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= +golang.org/x/net v0.0.0-20190501004415-9ce7a6920f09/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= +golang.org/x/net v0.0.0-20190503192946-f4e77d36d62c/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= +golang.org/x/net v0.0.0-20190603091049-60506f45cf65/go.mod h1:HSz+uSET+XFnRR8LxR5pz3Of3rY3CfYBVs4xY44aLks= golang.org/x/net v0.0.0-20190613194153-d28f0bde5980/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20190628185345-da137c7871d7/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20190724013045-ca1201d0de80/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20191209160850-c0dbc17a3553/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20200114155413-6afb5195e5aa/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20200202094626-16171245cfb2/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20200222125558-5a598a2470a0/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20200226121028-0de0cce0169b/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20200301022130-244492dfa37a/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20200324143707-d3edc9973b7e/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= +golang.org/x/net v0.0.0-20200501053045-e0ff5e5a1de5/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= +golang.org/x/net v0.0.0-20200506145744-7e3656a0809f/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= +golang.org/x/net v0.0.0-20200513185701-a91f0712d120/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= +golang.org/x/net v0.0.0-20200520182314-0ba52f642ac2/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= golang.org/x/net v0.0.0-20200625001655-4c5254603344/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-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= golang.org/x/net v0.0.0-20201202161906-c7110b5ffcbb/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= golang.org/x/net v0.0.0-20210405180319-a5a99cb37ef4/go.mod h1:p54w0d4576C0XHj96bSt6lcn1PtDYWL6XObtHCRCNQM= +golang.org/x/net v0.0.0-20210525063256-abc453219eb5/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= golang.org/x/net v0.0.0-20220105145211-5b0dc2dfae98 h1:+6WJMRLHlD7X7frgp7TUZ36RnQzSf9wVVTNakEp+nqY= golang.org/x/net v0.0.0-20220105145211-5b0dc2dfae98/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= 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-20200107190931-bf48bf16ab8d h1:TzXSXBo42m9gQenoE3b9BGiEpg5IG2JkU5FkPIawgtw= +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-20200107190931-bf48bf16ab8d/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= +golang.org/x/oauth2 v0.0.0-20210514164344-f6687ab2804c h1:pkQiBZBvdos9qq4wBAHqlzuZHEXo07pqV06ef90u1WI= +golang.org/x/oauth2 v0.0.0-20210514164344-f6687ab2804c/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= 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-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20190227155943-e225da77a7e6/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20200317015054-43a5402ce75a/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20200625203802-6e8e738ad208/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-20210220032951-036812b2e83c h1:5KslGYwFpkhGh+Q16bwMP3cOontH8FOep7tGV86Y7SQ= @@ -277,13 +410,34 @@ golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5h golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20181116152217-5ac8a444bdc5/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20190312061237-fead79001313/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190422165155-953cdadca894/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190502145724-3ef323f4f1fd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190507160741-ecd444e8653b/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190606165138-5da285871e9c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190624142023-c5567b49c5d0/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190726091711-fc99dfbffb4e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20191001151750-bb3f8db39f24/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20191026070338-33540a1f6037/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20191204072324-ce4227a45e2e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20191228213918-04cbcbbfeed8/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200106162015-b016eb3dc98e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200113162924-86b910548bc1/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200122134326-e047566fdf82/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200202164722-d101bd2416d5/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200212091648-12a6c2dcc1e4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200223170610-d5e6a3e2c0ae/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200302150141-5c8b2ff67527/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200331124033-c3d80250170d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200501052902-10377860bb8e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200511232937-7e40ca221e25/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200515095857-1151b9dac4a9/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200523222454-059865788121/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-20200803210538-64077c9b5642/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200923182605-d9f96fdee20d/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= @@ -294,16 +448,21 @@ golang.org/x/sys v0.0.0-20210423185535-09eb48e85fd7/go.mod h1:h1NjWce9XRLGQEsW7w golang.org/x/sys v0.0.0-20210510120138-977fb7262007/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-20211123173158-ef496fb156ab h1:rfJ1bsoJQQIAoAxTxB7bme+vHrNkRw8CqfsYh9w54cw= -golang.org/x/sys v0.0.0-20211123173158-ef496fb156ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20220114195835-da31bd327af9 h1:XfKQ4OlFl8okEOr5UvAqFRVj8pY/4yfcXrddB8qAbU0= +golang.org/x/sys v0.0.0-20220114195835-da31bd327af9/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= +golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= +golang.org/x/text v0.3.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.3/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.7 h1:olpwvP2KacW1ZWvsR7uQhoyTYvKAupfQrRGBFM352Gk= golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ= +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-20191024005414-555d28b269f0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.0.0-20210220033141-f8bda1e9f3ba h1:O8mE0/t419eoIwhTFpKVkHiTs/Igowgfkj25AcZrtiE= golang.org/x/time v0.0.0-20210220033141-f8bda1e9f3ba/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= @@ -311,30 +470,117 @@ golang.org/x/tools v0.0.0-20181030221726-6c7e314b6563/go.mod h1:n7NCudcB/nEzxVGm 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-20190311212946-11955173bddd/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= +golang.org/x/tools v0.0.0-20190312151545-0bb0c0a6e846/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= +golang.org/x/tools v0.0.0-20190312170243-e65039ee4138/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= +golang.org/x/tools v0.0.0-20190425150028-36563e24a262/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q= +golang.org/x/tools v0.0.0-20190506145303-2d16b83fe98c/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q= golang.org/x/tools v0.0.0-20190524140312-2c0ae7006135/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q= +golang.org/x/tools v0.0.0-20190606124116-d0a3d012864b/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc= +golang.org/x/tools v0.0.0-20190621195816-6e04913cbbac/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc= +golang.org/x/tools v0.0.0-20190628153133-6cdbf07be9d0/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc= +golang.org/x/tools v0.0.0-20190816200558-6889da9d5479/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-20190911174233-4f2ddba30aff/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-20191012152004-8de300cfc20a/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-20191113191852-77e3bb0ad9e7/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-20191115202509-3a792d9c32b2/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-20191125144606-a911d9008d1f/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-20191130070609-6e064ea0cf2d/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-20191216173652-a0e659d51361/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= +golang.org/x/tools v0.0.0-20191227053925-7b8e75db28f4/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= +golang.org/x/tools v0.0.0-20200117161641-43d50277825c/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= +golang.org/x/tools v0.0.0-20200122220014-bf1340f18c4a/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= +golang.org/x/tools v0.0.0-20200130002326-2f3ba24bd6e7/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= +golang.org/x/tools v0.0.0-20200204074204-1cc6d1ef6c74/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= +golang.org/x/tools v0.0.0-20200207183749-b753a1ba74fa/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= +golang.org/x/tools v0.0.0-20200212150539-ea181f53ac56/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= +golang.org/x/tools v0.0.0-20200224181240-023911ca70b2/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= +golang.org/x/tools v0.0.0-20200227222343-706bc42d1f0d/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= +golang.org/x/tools v0.0.0-20200304193943-95d2e580d8eb/go.mod h1:o4KQGtdN14AW+yjsvvwRTJJuXz8XRtIHtEnmAXLyFUw= +golang.org/x/tools v0.0.0-20200312045724-11d5b4c81c7d/go.mod h1:o4KQGtdN14AW+yjsvvwRTJJuXz8XRtIHtEnmAXLyFUw= +golang.org/x/tools v0.0.0-20200331025713-a30bf2db82d4/go.mod h1:Sl4aGygMT6LrqrWclx+PTx3U+LnKx/seiNR+3G19Ar8= +golang.org/x/tools v0.0.0-20200501065659-ab2804fb9c9d/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= +golang.org/x/tools v0.0.0-20200512131952-2bc93b1c0c88/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= +golang.org/x/tools v0.0.0-20200515010526-7d3b6ebf133d/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= +golang.org/x/tools v0.0.0-20200618134242-20370b0cb4b2/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= golang.org/x/tools v0.0.0-20200619180055-7c47624df98f/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= +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-20200825202427-b303f430e36d/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA= golang.org/x/tools v0.0.0-20210106214847-113979e3529a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= 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-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1 h1:go1bK/D/BFZV2I8cIQd1NKEZ+0owSTG1fDTci4IqFcE= golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +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.8.0/go.mod h1:o4eAsZoiT+ibD93RtjEohWalFOjRDx6CVaqeizhEnKg= +google.golang.org/api v0.9.0/go.mod h1:o4eAsZoiT+ibD93RtjEohWalFOjRDx6CVaqeizhEnKg= +google.golang.org/api v0.13.0/go.mod h1:iLdEw5Ide6rF15KTC1Kkl0iskquN2gFfn9o9XIsbkAI= +google.golang.org/api v0.14.0/go.mod h1:iLdEw5Ide6rF15KTC1Kkl0iskquN2gFfn9o9XIsbkAI= +google.golang.org/api v0.15.0/go.mod h1:iLdEw5Ide6rF15KTC1Kkl0iskquN2gFfn9o9XIsbkAI= +google.golang.org/api v0.17.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE= +google.golang.org/api v0.18.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE= +google.golang.org/api v0.19.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE= +google.golang.org/api v0.20.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE= +google.golang.org/api v0.22.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE= +google.golang.org/api v0.24.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.30.0/go.mod h1:QGmEvQ87FHZNiUVJkT14jQNYJ4ZJjdRF23ZXz5138Fc= google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM= -google.golang.org/appengine v1.4.0 h1:/wp5JvzpHIxhs/dumFmF7BXTf3Z+dd4uXta4kVyO508= 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.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.6 h1:lMO5rYAqUxkmaj76jAkRUvt5JZgFymx/+Q5Mzfivuhc= +google.golang.org/appengine v1.6.6/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-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-20190425155659-357c62f0e4bb/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= +google.golang.org/genproto v0.0.0-20190502173448-54afdca5d873/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= +google.golang.org/genproto v0.0.0-20190801165951-fa694d86fc64/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc= google.golang.org/genproto v0.0.0-20190819201941-24fa4b261c55/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc= +google.golang.org/genproto v0.0.0-20190911173649-1774047e7e51/go.mod h1:IbNlFCBrqXvoKpeg0TB2l7cyZUmoaFKYIwrEpbDKLA8= +google.golang.org/genproto v0.0.0-20191108220845-16a3f7862a1a/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= +google.golang.org/genproto v0.0.0-20191115194625-c23dd37a84c9/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= +google.golang.org/genproto v0.0.0-20191216164720-4f79533eabd1/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= +google.golang.org/genproto v0.0.0-20191230161307-f3c370f40bfb/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= +google.golang.org/genproto v0.0.0-20200115191322-ca5a22157cba/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= +google.golang.org/genproto v0.0.0-20200122232147-0452cf42e150/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= +google.golang.org/genproto v0.0.0-20200204135345-fa8e72b47b90/go.mod h1:GmwEX6Z4W5gMy59cAlVYjN9JhxgbQH6Gn+gFDQe2lzA= +google.golang.org/genproto v0.0.0-20200212174721-66ed5ce911ce/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= +google.golang.org/genproto v0.0.0-20200224152610-e50cd9704f63/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= +google.golang.org/genproto v0.0.0-20200228133532-8c2c7df3a383/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= +google.golang.org/genproto v0.0.0-20200305110556-506484158171/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= +google.golang.org/genproto v0.0.0-20200312145019-da6875a35672/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= +google.golang.org/genproto v0.0.0-20200331122359-1ee6d9798940/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= google.golang.org/genproto v0.0.0-20200423170343-7949de9c1215/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= +google.golang.org/genproto v0.0.0-20200430143042-b979b6f78d84/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= +google.golang.org/genproto v0.0.0-20200511104702-f5ebc3bea380/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= google.golang.org/genproto v0.0.0-20200513103714-09dca8ec2884/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= +google.golang.org/genproto v0.0.0-20200515170657-fc4c6c6a6587/go.mod h1:YsZOwe1myG/8QRHRsmBRE1LrgQY60beZKjly0O1fX9U= google.golang.org/genproto v0.0.0-20200526211855-cb27e3aa2013/go.mod h1:NbSheEEYHJ7i3ixzK3sjbqSGDJWnxyFXZblF3eUsNvo= +google.golang.org/genproto v0.0.0-20200618031413-b414f8b61790/go.mod h1:jDfRM7FcilCzHH/e9qn6dsT145K34l5v+OpcnNgKAAA= +google.golang.org/genproto v0.0.0-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-20200825200019-8632dd797987/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= google.golang.org/genproto v0.0.0-20211118181313-81c1377c94b1 h1:b9mVrqYfq3P4bCdaLg1qtBnPzUYgglsIdjZkL/fQVOE= google.golang.org/genproto v0.0.0-20211118181313-81c1377c94b1/go.mod h1:5CzLGKJ67TSI2B9POpiiyGha0AjJvZIUgRMt1dSmuhc= 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.21.1/go.mod h1:oYelfM1adQP15Ek0mdvEgi9Df8B9CZIaU1084ijfRaM= google.golang.org/grpc v1.23.0/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg= google.golang.org/grpc v1.25.1/go.mod h1:c3i+UQWmh7LiEpx4sFZnkU36qjEYZ0imhYfXVyQciAY= +google.golang.org/grpc v1.26.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk= google.golang.org/grpc v1.27.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk= +google.golang.org/grpc v1.27.1/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk= +google.golang.org/grpc v1.28.0/go.mod h1:rpkK4SK4GF4Ach/+MFLZUBavHOvF2JJB5uozKKal+60= 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.31.0/go.mod h1:N36X2cJ7JwdamYAgDz+s+rVMFjt3numwzf/HckM8pak= google.golang.org/grpc v1.33.1/go.mod h1:fr5YgcSWrqhRRxogOsw7RzIpsmvOZ6IcH4kBYTpR3n0= google.golang.org/grpc v1.36.0/go.mod h1:qjiiYl8FncCW8feJPdyg3v6XW24KsRHe+dy9BAGRRjU= google.golang.org/grpc v1.37.1/go.mod h1:NREThFqKR1f3iQ6oBuvc5LadQuXVGo9rkm5ZGrQdJfM= @@ -349,6 +595,7 @@ google.golang.org/protobuf v1.21.0/go.mod h1:47Nbq4nVaFHyn7ilMalzfO3qCViNmqZ2kzi google.golang.org/protobuf v1.22.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= google.golang.org/protobuf v1.23.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= google.golang.org/protobuf v1.23.1-0.20200526195155-81db48ad09cc/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= +google.golang.org/protobuf v1.24.0/go.mod h1:r/3tXBNzIEhYS9I1OUVjXDlt8tc493IdKGjtUeSXeh4= google.golang.org/protobuf v1.25.0/go.mod h1:9JNX74DMeImyA3h4bdi1ymwjUzf21/xIlbajtzgsN7c= google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw= google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc= @@ -356,8 +603,10 @@ google.golang.org/protobuf v1.27.1 h1:SnqbnDw1V7RiZcXPx5MEeqPv2s79L9i7BJUlG/+Rur google.golang.org/protobuf v1.27.1/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc= gopkg.in/alecthomas/kingpin.v2 v2.2.6/go.mod h1:FMv+mEhP44yOT+4EoQTLFTRgOQ1FBLkstjWtayDeSgw= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15 h1:YR8cESwS4TdDjEe65xsg0ogRM/Nc3DYOhEAlW+xobZo= gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/errgo.v2 v2.1.0/go.mod h1:hNsd1EY+bozCKY1Ytp96fpM3vjJbqLJn88ws8XvfDNI= gopkg.in/natefinch/lumberjack.v2 v2.0.0 h1:1Lc07Kr7qY4U2YPouBjpCLxpiyxIVoxqXgkXLknAOE8= gopkg.in/natefinch/lumberjack.v2 v2.0.0/go.mod h1:l0ndWWf7gzL7RNwBG7wST/UCcT4T24xpD6X8LsfU/+k= gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= @@ -373,7 +622,15 @@ gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b h1:h8qDotaEPuJATrMmW04NCwg7v22aHH28wwpauUhK9Oo= gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= +honnef.co/go/tools v0.0.0-20190106161140-3f1c8253044a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= +honnef.co/go/tools v0.0.0-20190418001031-e561f6794a2a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= honnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= +honnef.co/go/tools v0.0.1-2019.2.3/go.mod h1:a3bituU0lyd329TUQxRnasdCoJDkEUEAqEt0JzvZhAg= +honnef.co/go/tools v0.0.1-2020.1.3/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9vFzvIQ3k= +honnef.co/go/tools v0.0.1-2020.1.4/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9vFzvIQ3k= +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/sampler v1.3.0/go.mod h1:T1hPZKmBbMNahiBKFy5HrXp6adAjACjK9JXDnKaTXpA= sigs.k8s.io/json v0.0.0-20211020170558-c049b76a60c6 h1:fD1pz4yfdADVNfFmcP2aBEtudwUQ1AlLnRBALr33v3s= sigs.k8s.io/json v0.0.0-20211020170558-c049b76a60c6/go.mod h1:p4QtZmO4uMYipTQNzagwnNoseA6OxSUutVw05NhYDRs= sigs.k8s.io/yaml v1.2.0 h1:kr/MCeFWJWTwyaHoR9c8EjH9OumOmoF9YGiZd7lFm/Q= From bfd5170f66812b43775b95e11ccb742d61cff466 Mon Sep 17 00:00:00 2001 From: ahrtr Date: Wed, 30 Mar 2022 15:26:31 +0800 Subject: [PATCH 251/258] add a txPostLockHook into the backend Previously the SetConsistentIndex() is called during the apply workflow, but it's outside the db transaction. If a commit happens between SetConsistentIndex and the following apply workflow, and etcd crashes for whatever reason right after the commit, then etcd commits an incomplete transaction to db. Eventually etcd runs into the data inconsistency issue. In this commit, we move the SetConsistentIndex into a txPostLockHook, so it will be executed inside the transaction lock. --- etcdutl/etcdutl/migrate_command.go | 4 +-- server/etcdserver/adapters.go | 8 +++--- server/etcdserver/cindex/cindex.go | 23 ++++++++++++++--- server/etcdserver/server.go | 31 ++++++++++++++++++++--- server/etcdserver/server_test.go | 7 ++--- server/lease/lessor.go | 2 +- server/storage/backend.go | 2 +- server/storage/backend/backend.go | 16 +++++++++++- server/storage/backend/batch_tx.go | 16 +++++++++--- server/storage/mvcc/kvstore.go | 4 +-- server/storage/mvcc/kvstore_compaction.go | 2 +- server/storage/mvcc/kvstore_test.go | 2 ++ server/storage/schema/alarm.go | 2 +- server/storage/schema/auth.go | 2 +- server/storage/schema/cindex.go | 6 ++--- server/storage/schema/membership.go | 6 ++--- server/storage/schema/migration.go | 4 +-- server/storage/schema/schema.go | 8 +++--- server/verify/verify.go | 3 +-- 19 files changed, 104 insertions(+), 44 deletions(-) diff --git a/etcdutl/etcdutl/migrate_command.go b/etcdutl/etcdutl/migrate_command.go index 88f9e473c8a1..195576e313a9 100644 --- a/etcdutl/etcdutl/migrate_command.go +++ b/etcdutl/etcdutl/migrate_command.go @@ -118,7 +118,7 @@ type migrateConfig struct { func migrateCommandFunc(c *migrateConfig) error { defer c.be.Close() tx := c.be.BatchTx() - current, err := schema.DetectSchemaVersion(c.lg, tx) + current, err := schema.DetectSchemaVersion(c.lg, c.be.ReadTx()) if err != nil { c.lg.Error("failed to detect storage version. Please make sure you are using data dir from etcd v3.5 and older") return err @@ -140,7 +140,7 @@ func migrateCommandFunc(c *migrateConfig) error { } func migrateForce(lg *zap.Logger, tx backend.BatchTx, target *semver.Version) { - tx.Lock() + tx.LockWithoutHook() defer tx.Unlock() // Storage version is only supported since v3.6 if target.LessThan(schema.V3_6) { diff --git a/server/etcdserver/adapters.go b/server/etcdserver/adapters.go index 9511bc6a6acf..5f1bcfef119d 100644 --- a/server/etcdserver/adapters.go +++ b/server/etcdserver/adapters.go @@ -78,9 +78,9 @@ func (s *serverVersionAdapter) GetStorageVersion() *semver.Version { s.bemu.RLock() defer s.bemu.RUnlock() - tx := s.be.BatchTx() - tx.Lock() - defer tx.Unlock() + tx := s.be.ReadTx() + tx.RLock() + defer tx.RUnlock() v, err := schema.UnsafeDetectSchemaVersion(s.lg, tx) if err != nil { return nil @@ -94,7 +94,7 @@ func (s *serverVersionAdapter) UpdateStorageVersion(target semver.Version) error defer s.bemu.RUnlock() tx := s.be.BatchTx() - tx.Lock() + tx.LockWithoutHook() defer tx.Unlock() return schema.UnsafeMigrate(s.lg, tx, s.r.storage, target) } diff --git a/server/etcdserver/cindex/cindex.go b/server/etcdserver/cindex/cindex.go index 24dad66031dd..7ec1b1212838 100644 --- a/server/etcdserver/cindex/cindex.go +++ b/server/etcdserver/cindex/cindex.go @@ -23,6 +23,7 @@ import ( ) type Backend interface { + ReadTx() backend.ReadTx BatchTx() backend.BatchTx } @@ -32,6 +33,9 @@ type ConsistentIndexer interface { // ConsistentIndex returns the consistent index of current executing entry. ConsistentIndex() uint64 + // UnsafeConsistentIndex is similar to ConsistentIndex, but it doesn't lock the transaction. + UnsafeConsistentIndex() uint64 + // SetConsistentIndex set the consistent index of current executing entry. SetConsistentIndex(v uint64, term uint64) @@ -73,7 +77,19 @@ func (ci *consistentIndex) ConsistentIndex() uint64 { ci.mutex.Lock() defer ci.mutex.Unlock() - v, term := schema.ReadConsistentIndex(ci.be.BatchTx()) + v, term := schema.ReadConsistentIndex(ci.be.ReadTx()) + ci.SetConsistentIndex(v, term) + return v +} + +// UnsafeConsistentIndex is similar to ConsistentIndex, +// but it shouldn't lock the transaction. +func (ci *consistentIndex) UnsafeConsistentIndex() uint64 { + if index := atomic.LoadUint64(&ci.consistentIndex); index > 0 { + return index + } + + v, term := schema.UnsafeReadConsistentIndex(ci.be.BatchTx()) ci.SetConsistentIndex(v, term) return v } @@ -106,7 +122,8 @@ type fakeConsistentIndex struct { term uint64 } -func (f *fakeConsistentIndex) ConsistentIndex() uint64 { return f.index } +func (f *fakeConsistentIndex) ConsistentIndex() uint64 { return f.index } +func (f *fakeConsistentIndex) UnsafeConsistentIndex() uint64 { return f.index } func (f *fakeConsistentIndex) SetConsistentIndex(index uint64, term uint64) { atomic.StoreUint64(&f.index, index) @@ -117,7 +134,7 @@ func (f *fakeConsistentIndex) UnsafeSave(_ backend.BatchTx) {} func (f *fakeConsistentIndex) SetBackend(_ Backend) {} func UpdateConsistentIndex(tx backend.BatchTx, index uint64, term uint64, onlyGrow bool) { - tx.Lock() + tx.LockWithoutHook() defer tx.Unlock() schema.UnsafeUpdateConsistentIndex(tx, index, term, onlyGrow) } diff --git a/server/etcdserver/server.go b/server/etcdserver/server.go index f5632318eab6..b22f680bb46f 100644 --- a/server/etcdserver/server.go +++ b/server/etcdserver/server.go @@ -207,8 +207,10 @@ type EtcdServer struct { term uint64 // must use atomic operations to access; keep 64-bit aligned. lead uint64 // must use atomic operations to access; keep 64-bit aligned. - consistIndex cindex.ConsistentIndexer // consistIndex is used to get/set/save consistentIndex - r raftNode // uses 64-bit atomics; keep 64-bit aligned. + consistentIdx uint64 // must use atomic operations to access; keep 64-bit aligned. + consistentTerm uint64 // must use atomic operations to access; keep 64-bit aligned. + consistIndex cindex.ConsistentIndexer // consistIndex is used to get/set/save consistentIndex + r raftNode // uses 64-bit atomics; keep 64-bit aligned. readych chan struct{} Cfg config.ServerConfig @@ -341,6 +343,7 @@ func NewServer(cfg config.ServerConfig) (srv *EtcdServer, err error) { srv.applyV2 = NewApplierV2(cfg.Logger, srv.v2store, srv.cluster) srv.be = b.storage.backend.be + srv.be.SetTxPostLockHook(srv.getTxPostLockHook()) srv.beHooks = b.storage.backend.beHooks minTTL := time.Duration((3*cfg.ElectionTicks)/2) * heartbeat @@ -978,6 +981,8 @@ func (s *EtcdServer) applySnapshot(ep *etcdProgress, apply *apply) { } s.consistIndex.SetBackend(newbe) + newbe.SetTxPostLockHook(s.getTxPostLockHook()) + lg.Info("restored mvcc store", zap.Uint64("consistent-index", s.consistIndex.ConsistentIndex())) // Closing old backend might block until all the txns @@ -1547,6 +1552,15 @@ func (s *EtcdServer) getTerm() uint64 { return atomic.LoadUint64(&s.term) } +func (s *EtcdServer) setConsistentIndexAndTerm(cIdx, cTerm uint64) { + atomic.StoreUint64(&s.consistentIdx, cIdx) + atomic.StoreUint64(&s.consistentTerm, cTerm) +} + +func (s *EtcdServer) getConsistentIndexAndTerm() (uint64, uint64) { + return atomic.LoadUint64(&s.consistentIdx), atomic.LoadUint64(&s.consistentTerm) +} + func (s *EtcdServer) setLead(v uint64) { atomic.StoreUint64(&s.lead, v) } @@ -1771,7 +1785,7 @@ func (s *EtcdServer) apply( // set the consistent index of current executing entry if e.Index > s.consistIndex.ConsistentIndex() { - s.consistIndex.SetConsistentIndex(e.Index, e.Term) + s.setConsistentIndexAndTerm(e.Index, e.Term) shouldApplyV3 = membership.ApplyBoth } @@ -1801,7 +1815,7 @@ func (s *EtcdServer) applyEntryNormal(e *raftpb.Entry) { index := s.consistIndex.ConsistentIndex() if e.Index > index { // set the consistent index of current executing entry - s.consistIndex.SetConsistentIndex(e.Index, e.Term) + s.setConsistentIndexAndTerm(e.Index, e.Term) shouldApplyV3 = membership.ApplyBoth } s.lg.Debug("apply entry normal", @@ -2296,3 +2310,12 @@ func (s *EtcdServer) raftStatus() raft.Status { func (s *EtcdServer) Version() *serverversion.Manager { return serverversion.NewManager(s.Logger(), NewServerVersionAdapter(s)) } + +func (s *EtcdServer) getTxPostLockHook() func() { + return func() { + cIdx, term := s.getConsistentIndexAndTerm() + if cIdx > s.consistIndex.UnsafeConsistentIndex() { + s.consistIndex.SetConsistentIndex(cIdx, term) + } + } +} diff --git a/server/etcdserver/server_test.go b/server/etcdserver/server_test.go index cb4386976d92..706c7854952c 100644 --- a/server/etcdserver/server_test.go +++ b/server/etcdserver/server_test.go @@ -687,9 +687,7 @@ func TestApplyConfigChangeUpdatesConsistIndex(t *testing.T) { _, appliedi, _ := srv.apply(ents, &raftpb.ConfState{}) consistIndex := srv.consistIndex.ConsistentIndex() - if consistIndex != appliedi { - t.Fatalf("consistIndex = %v, want %v", consistIndex, appliedi) - } + assert.Equal(t, uint64(2), appliedi) t.Run("verify-backend", func(t *testing.T) { tx := be.BatchTx() @@ -698,9 +696,8 @@ func TestApplyConfigChangeUpdatesConsistIndex(t *testing.T) { srv.beHooks.OnPreCommitUnsafe(tx) assert.Equal(t, raftpb.ConfState{Voters: []uint64{2}}, *schema.UnsafeConfStateFromBackend(lg, tx)) }) - rindex, rterm := schema.ReadConsistentIndex(be.BatchTx()) + rindex, _ := schema.ReadConsistentIndex(be.ReadTx()) assert.Equal(t, consistIndex, rindex) - assert.Equal(t, uint64(4), rterm) } func realisticRaftNode(lg *zap.Logger) *raftNode { diff --git a/server/lease/lessor.go b/server/lease/lessor.go index cb6f0d6ec805..4af816c76bb1 100644 --- a/server/lease/lessor.go +++ b/server/lease/lessor.go @@ -797,7 +797,7 @@ func (le *lessor) findDueScheduledCheckpoints(checkpointLimit int) []*pb.LeaseCh func (le *lessor) initAndRecover() { tx := le.b.BatchTx() - tx.Lock() + tx.LockWithoutHook() schema.UnsafeCreateLeaseBucket(tx) lpbs := schema.MustUnsafeGetAllLeases(tx) tx.Unlock() diff --git a/server/storage/backend.go b/server/storage/backend.go index b7b0eb2fc7f4..b1101cfa6fcf 100644 --- a/server/storage/backend.go +++ b/server/storage/backend.go @@ -99,7 +99,7 @@ func OpenBackend(cfg config.ServerConfig, hooks backend.Hooks) backend.Backend { func RecoverSnapshotBackend(cfg config.ServerConfig, oldbe backend.Backend, snapshot raftpb.Snapshot, beExist bool, hooks *BackendHooks) (backend.Backend, error) { consistentIndex := uint64(0) if beExist { - consistentIndex, _ = schema.ReadConsistentIndex(oldbe.BatchTx()) + consistentIndex, _ = schema.ReadConsistentIndex(oldbe.ReadTx()) } if snapshot.Metadata.Index <= consistentIndex { return oldbe, nil diff --git a/server/storage/backend/backend.go b/server/storage/backend/backend.go index a61f4ec3609b..f949f282b708 100644 --- a/server/storage/backend/backend.go +++ b/server/storage/backend/backend.go @@ -67,6 +67,9 @@ type Backend interface { Defrag() error ForceCommit() Close() error + + // SetTxPostLockHook sets a txPostLockHook. + SetTxPostLockHook(func()) } type Snapshot interface { @@ -119,6 +122,9 @@ type backend struct { hooks Hooks + // txPostLockHook is called each time right after locking the tx. + txPostLockHook func() + lg *zap.Logger } @@ -227,6 +233,14 @@ func (b *backend) BatchTx() BatchTx { return b.batchTx } +func (b *backend) SetTxPostLockHook(hook func()) { + // It needs to lock the batchTx, because the periodic commit + // may be accessing the txPostLockHook at the moment. + b.batchTx.LockWithoutHook() + defer b.batchTx.Unlock() + b.txPostLockHook = hook +} + func (b *backend) ReadTx() ReadTx { return b.readTx } // ConcurrentReadTx creates and returns a new ReadTx, which: @@ -438,7 +452,7 @@ func (b *backend) defrag() error { // TODO: make this non-blocking? // lock batchTx to ensure nobody is using previous tx, and then // close previous ongoing tx. - b.batchTx.Lock() + b.batchTx.LockWithoutHook() defer b.batchTx.Unlock() // lock database after lock tx to avoid deadlock. diff --git a/server/storage/backend/batch_tx.go b/server/storage/backend/batch_tx.go index a8e649199161..a27266bb22a0 100644 --- a/server/storage/backend/batch_tx.go +++ b/server/storage/backend/batch_tx.go @@ -55,6 +55,7 @@ type BatchTx interface { CommitAndStop() LockInsideApply() LockOutsideApply() + } type batchTx struct { @@ -66,6 +67,13 @@ type batchTx struct { } func (t *batchTx) Lock() { + t.LockWithoutHook() + if t.backend.txPostLockHook != nil { + t.backend.txPostLockHook() + } +} + +func (t *batchTx) LockWithoutHook() { t.Mutex.Lock() } @@ -226,14 +234,14 @@ func unsafeForEach(tx *bolt.Tx, bucket Bucket, visitor func(k, v []byte) error) // Commit commits a previous tx and begins a new writable one. func (t *batchTx) Commit() { - t.Lock() + t.LockWithoutHook() t.commit(false) t.Unlock() } // CommitAndStop commits the previous tx and does not create a new one. func (t *batchTx) CommitAndStop() { - t.Lock() + t.LockWithoutHook() t.commit(true) t.Unlock() } @@ -303,13 +311,13 @@ func (t *batchTxBuffered) Unlock() { } func (t *batchTxBuffered) Commit() { - t.Lock() + t.LockWithoutHook() t.commit(false) t.Unlock() } func (t *batchTxBuffered) CommitAndStop() { - t.Lock() + t.LockWithoutHook() t.commit(true) t.Unlock() } diff --git a/server/storage/mvcc/kvstore.go b/server/storage/mvcc/kvstore.go index 846f83cde18d..9b79c090afc9 100644 --- a/server/storage/mvcc/kvstore.go +++ b/server/storage/mvcc/kvstore.go @@ -121,7 +121,7 @@ func NewStore(lg *zap.Logger, b backend.Backend, le lease.Lessor, cfg StoreConfi } tx := s.b.BatchTx() - tx.Lock() + tx.LockWithoutHook() tx.UnsafeCreateBucket(schema.Key) schema.UnsafeCreateMetaBucket(tx) tx.Unlock() @@ -331,7 +331,7 @@ func (s *store) restore() error { // restore index tx := s.b.BatchTx() - tx.Lock() + tx.LockWithoutHook() finishedCompact, found := UnsafeReadFinishedCompact(tx) if found { diff --git a/server/storage/mvcc/kvstore_compaction.go b/server/storage/mvcc/kvstore_compaction.go index ba944008216b..941f056a9219 100644 --- a/server/storage/mvcc/kvstore_compaction.go +++ b/server/storage/mvcc/kvstore_compaction.go @@ -42,7 +42,7 @@ func (s *store) scheduleCompaction(compactMainRev int64, keep map[revision]struc start := time.Now() tx := s.b.BatchTx() - tx.Lock() + tx.LockWithoutHook() keys, _ := tx.UnsafeRange(schema.Key, last, end, int64(batchNum)) for _, key := range keys { rev = bytesToRev(key) diff --git a/server/storage/mvcc/kvstore_test.go b/server/storage/mvcc/kvstore_test.go index 31cb37655415..4a51e9c406bf 100644 --- a/server/storage/mvcc/kvstore_test.go +++ b/server/storage/mvcc/kvstore_test.go @@ -881,6 +881,7 @@ type fakeBatchTx struct { rangeRespc chan rangeResp } +func (b *fakeBatchTx) LockWithoutHook() {} func (b *fakeBatchTx) Lock() {} func (b *fakeBatchTx) Unlock() {} func (b *fakeBatchTx) RLock() {} @@ -924,6 +925,7 @@ func (b *fakeBackend) Snapshot() backend.Snapshot func (b *fakeBackend) ForceCommit() {} func (b *fakeBackend) Defrag() error { return nil } func (b *fakeBackend) Close() error { return nil } +func (b *fakeBackend) SetTxPostLockHook(func()) {} type indexGetResp struct { rev revision diff --git a/server/storage/schema/alarm.go b/server/storage/schema/alarm.go index 605bb3a0bfd0..09a49994da46 100644 --- a/server/storage/schema/alarm.go +++ b/server/storage/schema/alarm.go @@ -34,7 +34,7 @@ func NewAlarmBackend(lg *zap.Logger, be backend.Backend) *alarmBackend { func (s *alarmBackend) CreateAlarmBucket() { tx := s.be.BatchTx() - tx.Lock() + tx.LockWithoutHook() defer tx.Unlock() tx.UnsafeCreateBucket(Alarm) } diff --git a/server/storage/schema/auth.go b/server/storage/schema/auth.go index 93ef34c371ef..fc334a8bcf91 100644 --- a/server/storage/schema/auth.go +++ b/server/storage/schema/auth.go @@ -49,7 +49,7 @@ func NewAuthBackend(lg *zap.Logger, be backend.Backend) *authBackend { func (abe *authBackend) CreateAuthBuckets() { tx := abe.be.BatchTx() - tx.Lock() + tx.LockWithoutHook() defer tx.Unlock() tx.UnsafeCreateBucket(Auth) tx.UnsafeCreateBucket(AuthUsers) diff --git a/server/storage/schema/cindex.go b/server/storage/schema/cindex.go index d7b06b9cef78..38eea6f9179f 100644 --- a/server/storage/schema/cindex.go +++ b/server/storage/schema/cindex.go @@ -26,7 +26,7 @@ func UnsafeCreateMetaBucket(tx backend.BatchTx) { // CreateMetaBucket creates the `meta` bucket (if it does not exists yet). func CreateMetaBucket(tx backend.BatchTx) { - tx.Lock() + tx.LockWithoutHook() defer tx.Unlock() tx.UnsafeCreateBucket(Meta) } @@ -51,8 +51,8 @@ func UnsafeReadConsistentIndex(tx backend.ReadTx) (uint64, uint64) { // ReadConsistentIndex loads consistent index and term from given transaction. // returns 0 if the data are not found. func ReadConsistentIndex(tx backend.ReadTx) (uint64, uint64) { - tx.Lock() - defer tx.Unlock() + tx.RLock() + defer tx.RUnlock() return UnsafeReadConsistentIndex(tx) } diff --git a/server/storage/schema/membership.go b/server/storage/schema/membership.go index 844b50a85a4f..153699e694aa 100644 --- a/server/storage/schema/membership.go +++ b/server/storage/schema/membership.go @@ -61,7 +61,7 @@ func (s *membershipBackend) MustSaveMemberToBackend(m *membership.Member) { // from the v3 backend. func (s *membershipBackend) TrimClusterFromBackend() error { tx := s.be.BatchTx() - tx.Lock() + tx.LockWithoutHook() defer tx.Unlock() tx.UnsafeDeleteBucket(Cluster) return nil @@ -121,7 +121,7 @@ func (s *membershipBackend) readMembersFromBackend() (map[types.ID]*membership.M func (s *membershipBackend) TrimMembershipFromBackend() error { s.lg.Info("Trimming membership information from the backend...") tx := s.be.BatchTx() - tx.Lock() + tx.LockWithoutHook() defer tx.Unlock() err := tx.UnsafeForEach(Members, func(k, v []byte) error { tx.UnsafeDelete(Members, k) @@ -167,7 +167,7 @@ func (s *membershipBackend) MustSaveDowngradeToBackend(downgrade *version.Downgr func (s *membershipBackend) MustCreateBackendBuckets() { tx := s.be.BatchTx() - tx.Lock() + tx.LockWithoutHook() defer tx.Unlock() tx.UnsafeCreateBucket(Members) tx.UnsafeCreateBucket(MembersRemoved) diff --git a/server/storage/schema/migration.go b/server/storage/schema/migration.go index 47734b4b851a..e1e44dab5f90 100644 --- a/server/storage/schema/migration.go +++ b/server/storage/schema/migration.go @@ -49,7 +49,7 @@ func newPlan(lg *zap.Logger, current semver.Version, target semver.Version) (pla } func (p migrationPlan) Execute(lg *zap.Logger, tx backend.BatchTx) error { - tx.Lock() + tx.LockWithoutHook() defer tx.Unlock() return p.unsafeExecute(lg, tx) } @@ -90,7 +90,7 @@ func newMigrationStep(v semver.Version, isUpgrade bool, changes []schemaChange) // execute runs actions required to migrate etcd storage between two minor versions. func (s migrationStep) execute(lg *zap.Logger, tx backend.BatchTx) error { - tx.Lock() + tx.LockWithoutHook() defer tx.Unlock() return s.unsafeExecute(lg, tx) } diff --git a/server/storage/schema/schema.go b/server/storage/schema/schema.go index 850b55d5bd56..2b4c15f29c84 100644 --- a/server/storage/schema/schema.go +++ b/server/storage/schema/schema.go @@ -31,7 +31,7 @@ var ( // Validate checks provided backend to confirm that schema used is supported. func Validate(lg *zap.Logger, tx backend.BatchTx) error { - tx.Lock() + tx.LockWithoutHook() defer tx.Unlock() return unsafeValidate(lg, tx) } @@ -60,7 +60,7 @@ type WALVersion interface { // Migrate updates storage schema to provided target version. // Downgrading requires that provided WAL doesn't contain unsupported entries. func Migrate(lg *zap.Logger, tx backend.BatchTx, w WALVersion, target semver.Version) error { - tx.Lock() + tx.LockWithoutHook() defer tx.Unlock() return UnsafeMigrate(lg, tx, w, target) } @@ -89,8 +89,8 @@ func UnsafeMigrate(lg *zap.Logger, tx backend.BatchTx, w WALVersion, target semv // * v3.5 will return it's version if it includes all storage fields added in v3.5 (might require a snapshot). // * v3.4 and older is not supported and will return error. func DetectSchemaVersion(lg *zap.Logger, tx backend.ReadTx) (v semver.Version, err error) { - tx.Lock() - defer tx.Unlock() + tx.RLock() + defer tx.RUnlock() return UnsafeDetectSchemaVersion(lg, tx) } diff --git a/server/verify/verify.go b/server/verify/verify.go index 9402e5eb5ea6..2b73fbc07b20 100644 --- a/server/verify/verify.go +++ b/server/verify/verify.go @@ -108,8 +108,7 @@ func MustVerifyIfEnabled(cfg Config) { } func validateConsistentIndex(cfg Config, hardstate *raftpb.HardState, snapshot *walpb.Snapshot, be backend.Backend) error { - tx := be.BatchTx() - index, term := schema.ReadConsistentIndex(tx) + index, term := schema.ReadConsistentIndex(be.ReadTx()) if cfg.ExactIndex && index != hardstate.Commit { return fmt.Errorf("backend.ConsistentIndex (%v) expected == WAL.HardState.commit (%v)", index, hardstate.Commit) } From a4c5da844d732e9308646c117adc45b654608427 Mon Sep 17 00:00:00 2001 From: ahrtr Date: Thu, 31 Mar 2022 17:06:48 +0800 Subject: [PATCH 252/258] added detailed comment to explain the difference between Lock and LockWithoutHook --- server/storage/backend/batch_tx.go | 1 - 1 file changed, 1 deletion(-) diff --git a/server/storage/backend/batch_tx.go b/server/storage/backend/batch_tx.go index a27266bb22a0..8628d9aaa15b 100644 --- a/server/storage/backend/batch_tx.go +++ b/server/storage/backend/batch_tx.go @@ -55,7 +55,6 @@ type BatchTx interface { CommitAndStop() LockInsideApply() LockOutsideApply() - } type batchTx struct { From 7ac995cdde6ae56beba93b040fe231dfca03c38d Mon Sep 17 00:00:00 2001 From: ahrtr Date: Sat, 2 Apr 2022 06:02:22 +0800 Subject: [PATCH 253/258] enhanced authBackend to support authReadTx --- server/auth/range_perm_cache.go | 4 +- server/auth/store.go | 12 ++++-- server/auth/store_mock_test.go | 4 ++ server/etcdserver/cindex/cindex.go | 2 +- server/etcdserver/server.go | 5 ++- server/storage/schema/auth.go | 38 +++++++++++++++--- server/storage/schema/auth_roles.go | 60 +++++++++++++++++------------ server/storage/schema/auth_users.go | 50 ++++++++++++++---------- 8 files changed, 118 insertions(+), 57 deletions(-) diff --git a/server/auth/range_perm_cache.go b/server/auth/range_perm_cache.go index bae07ef52428..2ebe5439b588 100644 --- a/server/auth/range_perm_cache.go +++ b/server/auth/range_perm_cache.go @@ -20,7 +20,7 @@ import ( "go.uber.org/zap" ) -func getMergedPerms(tx AuthBatchTx, userName string) *unifiedRangePermissions { +func getMergedPerms(tx AuthReadTx, userName string) *unifiedRangePermissions { user := tx.UnsafeGetUser(userName) if user == nil { return nil @@ -103,7 +103,7 @@ func checkKeyPoint(lg *zap.Logger, cachedPerms *unifiedRangePermissions, key []b return false } -func (as *authStore) isRangeOpPermitted(tx AuthBatchTx, userName string, key, rangeEnd []byte, permtyp authpb.Permission_Type) bool { +func (as *authStore) isRangeOpPermitted(tx AuthReadTx, userName string, key, rangeEnd []byte, permtyp authpb.Permission_Type) bool { // assumption: tx is Lock()ed _, ok := as.rangePermCache[userName] if !ok { diff --git a/server/auth/store.go b/server/auth/store.go index 408b235babd7..762caecd780e 100644 --- a/server/auth/store.go +++ b/server/auth/store.go @@ -196,6 +196,7 @@ type TokenProvider interface { type AuthBackend interface { CreateAuthBuckets() ForceCommit() + ReadTx() AuthReadTx BatchTx() AuthBatchTx GetUser(string) *authpb.User @@ -345,7 +346,7 @@ func (as *authStore) CheckPassword(username, password string) (uint64, error) { // CompareHashAndPassword is very expensive, so we use closures // to avoid putting it in the critical section of the tx lock. revision, err := func() (uint64, error) { - tx := as.be.BatchTx() + tx := as.be.ReadTx() tx.Lock() defer tx.Unlock() @@ -855,7 +856,7 @@ func (as *authStore) isOpPermitted(userName string, revision uint64, key, rangeE return ErrAuthOldRevision } - tx := as.be.BatchTx() + tx := as.be.ReadTx() tx.Lock() defer tx.Unlock() @@ -897,7 +898,10 @@ func (as *authStore) IsAdminPermitted(authInfo *AuthInfo) error { return ErrUserEmpty } - u := as.be.GetUser(authInfo.Username) + tx := as.be.ReadTx() + tx.Lock() + defer tx.Unlock() + u := tx.UnsafeGetUser(authInfo.Username) if u == nil { return ErrUserNotFound @@ -935,6 +939,8 @@ func NewAuthStore(lg *zap.Logger, be AuthBackend, tp TokenProvider, bcryptCost i be.CreateAuthBuckets() tx := be.BatchTx() + // We should call LockWithoutHook here, but the txPostLockHoos isn't set + // to EtcdServer yet, so it's OK. tx.Lock() enabled := tx.UnsafeReadAuthEnabled() as := &authStore{ diff --git a/server/auth/store_mock_test.go b/server/auth/store_mock_test.go index d49f8dd333f2..39c3f6d139a2 100644 --- a/server/auth/store_mock_test.go +++ b/server/auth/store_mock_test.go @@ -36,6 +36,10 @@ func (b *backendMock) CreateAuthBuckets() { func (b *backendMock) ForceCommit() { } +func (b *backendMock) ReadTx() AuthReadTx { + return &txMock{be: b} +} + func (b *backendMock) BatchTx() AuthBatchTx { return &txMock{be: b} } diff --git a/server/etcdserver/cindex/cindex.go b/server/etcdserver/cindex/cindex.go index 7ec1b1212838..6367967f8758 100644 --- a/server/etcdserver/cindex/cindex.go +++ b/server/etcdserver/cindex/cindex.go @@ -89,7 +89,7 @@ func (ci *consistentIndex) UnsafeConsistentIndex() uint64 { return index } - v, term := schema.UnsafeReadConsistentIndex(ci.be.BatchTx()) + v, term := schema.UnsafeReadConsistentIndex(ci.be.ReadTx()) ci.SetConsistentIndex(v, term) return v } diff --git a/server/etcdserver/server.go b/server/etcdserver/server.go index b22f680bb46f..6a89f4592f87 100644 --- a/server/etcdserver/server.go +++ b/server/etcdserver/server.go @@ -343,7 +343,6 @@ func NewServer(cfg config.ServerConfig) (srv *EtcdServer, err error) { srv.applyV2 = NewApplierV2(cfg.Logger, srv.v2store, srv.cluster) srv.be = b.storage.backend.be - srv.be.SetTxPostLockHook(srv.getTxPostLockHook()) srv.beHooks = b.storage.backend.beHooks minTTL := time.Duration((3*cfg.ElectionTicks)/2) * heartbeat @@ -404,6 +403,10 @@ func NewServer(cfg config.ServerConfig) (srv *EtcdServer, err error) { }) } + // Set the hook after EtcdServer finishes the initialization to avoid + // the hook being called during the initialization process. + srv.be.SetTxPostLockHook(srv.getTxPostLockHook()) + // TODO: move transport initialization near the definition of remote tr := &rafthttp.Transport{ Logger: cfg.Logger, diff --git a/server/storage/schema/auth.go b/server/storage/schema/auth.go index fc334a8bcf91..3956ca782f9d 100644 --- a/server/storage/schema/auth.go +++ b/server/storage/schema/auth.go @@ -60,15 +60,25 @@ func (abe *authBackend) ForceCommit() { abe.be.ForceCommit() } +func (abe *authBackend) ReadTx() auth.AuthReadTx { + return &authReadTx{tx: abe.be.ReadTx(), lg: abe.lg} +} + func (abe *authBackend) BatchTx() auth.AuthBatchTx { return &authBatchTx{tx: abe.be.BatchTx(), lg: abe.lg} } +type authReadTx struct { + tx backend.ReadTx + lg *zap.Logger +} + type authBatchTx struct { tx backend.BatchTx lg *zap.Logger } +var _ auth.AuthReadTx = (*authReadTx)(nil) var _ auth.AuthBatchTx = (*authBatchTx)(nil) func (atx *authBatchTx) UnsafeSaveAuthEnabled(enabled bool) { @@ -86,6 +96,24 @@ func (atx *authBatchTx) UnsafeSaveAuthRevision(rev uint64) { } func (atx *authBatchTx) UnsafeReadAuthEnabled() bool { + arx := &authReadTx{tx: atx.tx, lg: atx.lg} + return arx.UnsafeReadAuthEnabled() +} + +func (atx *authBatchTx) UnsafeReadAuthRevision() uint64 { + arx := &authReadTx{tx: atx.tx, lg: atx.lg} + return arx.UnsafeReadAuthRevision() +} + +func (atx *authBatchTx) Lock() { + atx.tx.Lock() +} + +func (atx *authBatchTx) Unlock() { + atx.tx.Unlock() +} + +func (atx *authReadTx) UnsafeReadAuthEnabled() bool { _, vs := atx.tx.UnsafeRange(Auth, AuthEnabledKeyName, nil, 0) if len(vs) == 1 { if bytes.Equal(vs[0], authEnabled) { @@ -95,7 +123,7 @@ func (atx *authBatchTx) UnsafeReadAuthEnabled() bool { return false } -func (atx *authBatchTx) UnsafeReadAuthRevision() uint64 { +func (atx *authReadTx) UnsafeReadAuthRevision() uint64 { _, vs := atx.tx.UnsafeRange(Auth, AuthRevisionKeyName, nil, 0) if len(vs) != 1 { // this can happen in the initialization phase @@ -104,10 +132,10 @@ func (atx *authBatchTx) UnsafeReadAuthRevision() uint64 { return binary.BigEndian.Uint64(vs[0]) } -func (atx *authBatchTx) Lock() { - atx.tx.Lock() +func (atx *authReadTx) Lock() { + atx.tx.RLock() } -func (atx *authBatchTx) Unlock() { - atx.tx.Unlock() +func (atx *authReadTx) Unlock() { + atx.tx.RUnlock() } diff --git a/server/storage/schema/auth_roles.go b/server/storage/schema/auth_roles.go index 541e37b71910..dfda7ce5b7bc 100644 --- a/server/storage/schema/auth_roles.go +++ b/server/storage/schema/auth_roles.go @@ -32,6 +32,40 @@ func (abe *authBackend) GetRole(roleName string) *authpb.Role { } func (atx *authBatchTx) UnsafeGetRole(roleName string) *authpb.Role { + arx := &authReadTx{tx: atx.tx, lg: atx.lg} + return arx.UnsafeGetRole(roleName) +} + +func (abe *authBackend) GetAllRoles() []*authpb.Role { + tx := abe.BatchTx() + tx.Lock() + defer tx.Unlock() + return tx.UnsafeGetAllRoles() +} + +func (atx *authBatchTx) UnsafeGetAllRoles() []*authpb.Role { + arx := &authReadTx{tx: atx.tx, lg: atx.lg} + return arx.UnsafeGetAllRoles() +} + +func (atx *authBatchTx) UnsafePutRole(role *authpb.Role) { + b, err := role.Marshal() + if err != nil { + atx.lg.Panic( + "failed to marshal 'authpb.Role'", + zap.String("role-name", string(role.Name)), + zap.Error(err), + ) + } + + atx.tx.UnsafePut(AuthRoles, role.Name, b) +} + +func (atx *authBatchTx) UnsafeDeleteRole(rolename string) { + atx.tx.UnsafeDelete(AuthRoles, []byte(rolename)) +} + +func (atx *authReadTx) UnsafeGetRole(roleName string) *authpb.Role { _, vs := atx.tx.UnsafeRange(AuthRoles, []byte(roleName), nil, 0) if len(vs) == 0 { return nil @@ -45,14 +79,7 @@ func (atx *authBatchTx) UnsafeGetRole(roleName string) *authpb.Role { return role } -func (abe *authBackend) GetAllRoles() []*authpb.Role { - tx := abe.BatchTx() - tx.Lock() - defer tx.Unlock() - return tx.UnsafeGetAllRoles() -} - -func (atx *authBatchTx) UnsafeGetAllRoles() []*authpb.Role { +func (atx *authReadTx) UnsafeGetAllRoles() []*authpb.Role { _, vs := atx.tx.UnsafeRange(AuthRoles, []byte{0}, []byte{0xff}, -1) if len(vs) == 0 { return nil @@ -69,20 +96,3 @@ func (atx *authBatchTx) UnsafeGetAllRoles() []*authpb.Role { } return roles } - -func (atx *authBatchTx) UnsafePutRole(role *authpb.Role) { - b, err := role.Marshal() - if err != nil { - atx.lg.Panic( - "failed to marshal 'authpb.Role'", - zap.String("role-name", string(role.Name)), - zap.Error(err), - ) - } - - atx.tx.UnsafePut(AuthRoles, role.Name, b) -} - -func (atx *authBatchTx) UnsafeDeleteRole(rolename string) { - atx.tx.UnsafeDelete(AuthRoles, []byte(rolename)) -} diff --git a/server/storage/schema/auth_users.go b/server/storage/schema/auth_users.go index f385afa51225..c3e7a92ff394 100644 --- a/server/storage/schema/auth_users.go +++ b/server/storage/schema/auth_users.go @@ -27,6 +27,35 @@ func (abe *authBackend) GetUser(username string) *authpb.User { } func (atx *authBatchTx) UnsafeGetUser(username string) *authpb.User { + arx := &authReadTx{tx: atx.tx, lg: atx.lg} + return arx.UnsafeGetUser(username) +} + +func (abe *authBackend) GetAllUsers() []*authpb.User { + tx := abe.BatchTx() + tx.Lock() + defer tx.Unlock() + return tx.UnsafeGetAllUsers() +} + +func (atx *authBatchTx) UnsafeGetAllUsers() []*authpb.User { + arx := &authReadTx{tx: atx.tx, lg: atx.lg} + return arx.UnsafeGetAllUsers() +} + +func (atx *authBatchTx) UnsafePutUser(user *authpb.User) { + b, err := user.Marshal() + if err != nil { + atx.lg.Panic("failed to unmarshal 'authpb.User'", zap.Error(err)) + } + atx.tx.UnsafePut(AuthUsers, user.Name, b) +} + +func (atx *authBatchTx) UnsafeDeleteUser(username string) { + atx.tx.UnsafeDelete(AuthUsers, []byte(username)) +} + +func (atx *authReadTx) UnsafeGetUser(username string) *authpb.User { _, vs := atx.tx.UnsafeRange(AuthUsers, []byte(username), nil, 0) if len(vs) == 0 { return nil @@ -44,14 +73,7 @@ func (atx *authBatchTx) UnsafeGetUser(username string) *authpb.User { return user } -func (abe *authBackend) GetAllUsers() []*authpb.User { - tx := abe.BatchTx() - tx.Lock() - defer tx.Unlock() - return tx.UnsafeGetAllUsers() -} - -func (atx *authBatchTx) UnsafeGetAllUsers() []*authpb.User { +func (atx *authReadTx) UnsafeGetAllUsers() []*authpb.User { _, vs := atx.tx.UnsafeRange(AuthUsers, []byte{0}, []byte{0xff}, -1) if len(vs) == 0 { return nil @@ -68,15 +90,3 @@ func (atx *authBatchTx) UnsafeGetAllUsers() []*authpb.User { } return users } - -func (atx *authBatchTx) UnsafePutUser(user *authpb.User) { - b, err := user.Marshal() - if err != nil { - atx.lg.Panic("failed to unmarshal 'authpb.User'", zap.Error(err)) - } - atx.tx.UnsafePut(AuthUsers, user.Name, b) -} - -func (atx *authBatchTx) UnsafeDeleteUser(username string) { - atx.tx.UnsafeDelete(AuthUsers, []byte(username)) -} From 47038593e9eba0993156a6ddef2e1500758685a1 Mon Sep 17 00:00:00 2001 From: ahrtr Date: Mon, 4 Apr 2022 19:56:38 +0800 Subject: [PATCH 254/258] set the consistent_index directly when applyV3 isn't performed --- server/etcdserver/server.go | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/server/etcdserver/server.go b/server/etcdserver/server.go index 6a89f4592f87..612454227d6f 100644 --- a/server/etcdserver/server.go +++ b/server/etcdserver/server.go @@ -1815,6 +1815,14 @@ func (s *EtcdServer) apply( // applyEntryNormal applies an EntryNormal type raftpb request to the EtcdServer func (s *EtcdServer) applyEntryNormal(e *raftpb.Entry) { shouldApplyV3 := membership.ApplyV2storeOnly + applyV3Performed := false + defer func() { + // The txPostLock callback will not get called in this case, + // so we should set the consistent index directly. + if s.consistIndex != nil && !applyV3Performed && membership.ApplyBoth == shouldApplyV3 { + s.consistIndex.SetConsistentIndex(e.Index, e.Term) + } + }() index := s.consistIndex.ConsistentIndex() if e.Index > index { // set the consistent index of current executing entry @@ -1870,6 +1878,7 @@ func (s *EtcdServer) applyEntryNormal(e *raftpb.Entry) { if !needResult && raftReq.Txn != nil { removeNeedlessRangeReqs(raftReq.Txn) } + applyV3Performed = true ar = s.applyV3.Apply(&raftReq, shouldApplyV3) } @@ -1912,6 +1921,12 @@ func (s *EtcdServer) applyConfChange(cc raftpb.ConfChange, confState *raftpb.Con if err := s.cluster.ValidateConfigurationChange(cc); err != nil { cc.NodeID = raft.None s.r.ApplyConfChange(cc) + + // The txPostLock callback will not get called in this case, + // so we should set the consistent index directly. + if s.consistIndex != nil && membership.ApplyBoth == shouldApplyV3 { + s.consistIndex.SetConsistentIndex(s.consistentIdx, s.consistentTerm) + } return false, err } From e155e50886316b8ff6c0d3e6362406ca2fb11a7d Mon Sep 17 00:00:00 2001 From: ahrtr Date: Wed, 6 Apr 2022 05:07:07 +0800 Subject: [PATCH 255/258] rename LockWithoutHook to LockOutsideApply and add LockInsideApply --- etcdutl/etcdutl/backup_command.go | 2 +- etcdutl/etcdutl/migrate_command.go | 2 +- server/auth/store.go | 4 +-- server/etcdserver/adapters.go | 2 +- server/etcdserver/bootstrap.go | 2 +- server/etcdserver/cindex/cindex.go | 4 +-- server/etcdserver/server.go | 4 +-- server/lease/lessor.go | 4 +-- server/storage/backend/backend.go | 10 +++---- server/storage/backend/batch_tx.go | 30 ++++++++++++-------- server/storage/backend/hooks_test.go | 2 -- server/storage/backend/verify.go | 14 ++++++++++ server/storage/backend/verify_test.go | 34 ++++++++++++++++++----- server/storage/mvcc/kvstore.go | 4 +-- server/storage/mvcc/kvstore_compaction.go | 2 +- server/storage/mvcc/kvstore_test.go | 11 ++++---- server/storage/mvcc/kvstore_txn.go | 2 +- server/storage/mvcc/store.go | 4 +-- server/storage/schema/alarm.go | 6 ++-- server/storage/schema/auth.go | 4 +-- server/storage/schema/cindex.go | 2 +- server/storage/schema/membership.go | 14 +++++----- server/storage/schema/migration.go | 4 +-- server/storage/schema/schema.go | 8 +++--- server/storage/schema/schema_test.go | 2 +- 25 files changed, 106 insertions(+), 71 deletions(-) diff --git a/etcdutl/etcdutl/backup_command.go b/etcdutl/etcdutl/backup_command.go index 49b6a93101d1..e0d53fc1b1f8 100644 --- a/etcdutl/etcdutl/backup_command.go +++ b/etcdutl/etcdutl/backup_command.go @@ -322,7 +322,7 @@ func saveDB(lg *zap.Logger, destDB, srcDB string, idx uint64, term uint64, desir if !v3 { tx := be.BatchTx() - tx.Lock() + tx.LockOutsideApply() defer tx.Unlock() schema.UnsafeCreateMetaBucket(tx) schema.UnsafeUpdateConsistentIndex(tx, idx, term, false) diff --git a/etcdutl/etcdutl/migrate_command.go b/etcdutl/etcdutl/migrate_command.go index 195576e313a9..87b10664ff4c 100644 --- a/etcdutl/etcdutl/migrate_command.go +++ b/etcdutl/etcdutl/migrate_command.go @@ -140,7 +140,7 @@ func migrateCommandFunc(c *migrateConfig) error { } func migrateForce(lg *zap.Logger, tx backend.BatchTx, target *semver.Version) { - tx.LockWithoutHook() + tx.LockOutsideApply() defer tx.Unlock() // Storage version is only supported since v3.6 if target.LessThan(schema.V3_6) { diff --git a/server/auth/store.go b/server/auth/store.go index 762caecd780e..2d978a011416 100644 --- a/server/auth/store.go +++ b/server/auth/store.go @@ -374,7 +374,7 @@ func (as *authStore) CheckPassword(username, password string) (uint64, error) { func (as *authStore) Recover(be AuthBackend) { as.be = be - tx := be.BatchTx() + tx := be.ReadTx() tx.Lock() enabled := tx.UnsafeReadAuthEnabled() @@ -939,7 +939,7 @@ func NewAuthStore(lg *zap.Logger, be AuthBackend, tp TokenProvider, bcryptCost i be.CreateAuthBuckets() tx := be.BatchTx() - // We should call LockWithoutHook here, but the txPostLockHoos isn't set + // We should call LockOutsideApply here, but the txPostLockHoos isn't set // to EtcdServer yet, so it's OK. tx.Lock() enabled := tx.UnsafeReadAuthEnabled() diff --git a/server/etcdserver/adapters.go b/server/etcdserver/adapters.go index 5f1bcfef119d..d875cf14efea 100644 --- a/server/etcdserver/adapters.go +++ b/server/etcdserver/adapters.go @@ -94,7 +94,7 @@ func (s *serverVersionAdapter) UpdateStorageVersion(target semver.Version) error defer s.bemu.RUnlock() tx := s.be.BatchTx() - tx.LockWithoutHook() + tx.LockOutsideApply() defer tx.Unlock() return schema.UnsafeMigrate(s.lg, tx, s.r.storage, target) } diff --git a/server/etcdserver/bootstrap.go b/server/etcdserver/bootstrap.go index 857e7afa6ad9..43605be5e620 100644 --- a/server/etcdserver/bootstrap.go +++ b/server/etcdserver/bootstrap.go @@ -231,7 +231,7 @@ func bootstrapBackend(cfg config.ServerConfig, haveWAL bool, st v2store.Store, s } } if beExist { - err = schema.Validate(cfg.Logger, be.BatchTx()) + err = schema.Validate(cfg.Logger, be.ReadTx()) if err != nil { cfg.Logger.Error("Failed to validate schema", zap.Error(err)) return nil, err diff --git a/server/etcdserver/cindex/cindex.go b/server/etcdserver/cindex/cindex.go index 6367967f8758..91046cd0370c 100644 --- a/server/etcdserver/cindex/cindex.go +++ b/server/etcdserver/cindex/cindex.go @@ -82,8 +82,6 @@ func (ci *consistentIndex) ConsistentIndex() uint64 { return v } -// UnsafeConsistentIndex is similar to ConsistentIndex, -// but it shouldn't lock the transaction. func (ci *consistentIndex) UnsafeConsistentIndex() uint64 { if index := atomic.LoadUint64(&ci.consistentIndex); index > 0 { return index @@ -134,7 +132,7 @@ func (f *fakeConsistentIndex) UnsafeSave(_ backend.BatchTx) {} func (f *fakeConsistentIndex) SetBackend(_ Backend) {} func UpdateConsistentIndex(tx backend.BatchTx, index uint64, term uint64, onlyGrow bool) { - tx.LockWithoutHook() + tx.LockOutsideApply() defer tx.Unlock() schema.UnsafeUpdateConsistentIndex(tx, index, term, onlyGrow) } diff --git a/server/etcdserver/server.go b/server/etcdserver/server.go index 612454227d6f..015bcaf6f0a9 100644 --- a/server/etcdserver/server.go +++ b/server/etcdserver/server.go @@ -405,7 +405,7 @@ func NewServer(cfg config.ServerConfig) (srv *EtcdServer, err error) { // Set the hook after EtcdServer finishes the initialization to avoid // the hook being called during the initialization process. - srv.be.SetTxPostLockHook(srv.getTxPostLockHook()) + srv.be.SetTxPostLockInsideApplyHook(srv.getTxPostLockHook()) // TODO: move transport initialization near the definition of remote tr := &rafthttp.Transport{ @@ -984,7 +984,7 @@ func (s *EtcdServer) applySnapshot(ep *etcdProgress, apply *apply) { } s.consistIndex.SetBackend(newbe) - newbe.SetTxPostLockHook(s.getTxPostLockHook()) + newbe.SetTxPostLockInsideApplyHook(s.getTxPostLockHook()) lg.Info("restored mvcc store", zap.Uint64("consistent-index", s.consistIndex.ConsistentIndex())) diff --git a/server/lease/lessor.go b/server/lease/lessor.go index 4af816c76bb1..931cb3d090d2 100644 --- a/server/lease/lessor.go +++ b/server/lease/lessor.go @@ -797,7 +797,7 @@ func (le *lessor) findDueScheduledCheckpoints(checkpointLimit int) []*pb.LeaseCh func (le *lessor) initAndRecover() { tx := le.b.BatchTx() - tx.LockWithoutHook() + tx.LockOutsideApply() schema.UnsafeCreateLeaseBucket(tx) lpbs := schema.MustUnsafeGetAllLeases(tx) tx.Unlock() @@ -845,7 +845,7 @@ func (l *Lease) expired() bool { func (l *Lease) persistTo(b backend.Backend) { lpb := leasepb.Lease{ID: int64(l.ID), TTL: l.ttl, RemainingTTL: l.remainingTTL} tx := b.BatchTx() - tx.Lock() + tx.LockInsideApply() defer tx.Unlock() schema.MustUnsafePutLease(tx, &lpb) } diff --git a/server/storage/backend/backend.go b/server/storage/backend/backend.go index f949f282b708..ebb99ee2c342 100644 --- a/server/storage/backend/backend.go +++ b/server/storage/backend/backend.go @@ -68,8 +68,8 @@ type Backend interface { ForceCommit() Close() error - // SetTxPostLockHook sets a txPostLockHook. - SetTxPostLockHook(func()) + // SetTxPostLockInsideApplyHook sets a txPostLockHook. + SetTxPostLockInsideApplyHook(func()) } type Snapshot interface { @@ -233,10 +233,10 @@ func (b *backend) BatchTx() BatchTx { return b.batchTx } -func (b *backend) SetTxPostLockHook(hook func()) { +func (b *backend) SetTxPostLockInsideApplyHook(hook func()) { // It needs to lock the batchTx, because the periodic commit // may be accessing the txPostLockHook at the moment. - b.batchTx.LockWithoutHook() + b.batchTx.lock() defer b.batchTx.Unlock() b.txPostLockHook = hook } @@ -452,7 +452,7 @@ func (b *backend) defrag() error { // TODO: make this non-blocking? // lock batchTx to ensure nobody is using previous tx, and then // close previous ongoing tx. - b.batchTx.LockWithoutHook() + b.batchTx.LockOutsideApply() defer b.batchTx.Unlock() // lock database after lock tx to avoid deadlock. diff --git a/server/storage/backend/batch_tx.go b/server/storage/backend/batch_tx.go index 8628d9aaa15b..7eca835fd221 100644 --- a/server/storage/backend/batch_tx.go +++ b/server/storage/backend/batch_tx.go @@ -65,25 +65,31 @@ type batchTx struct { pending int } +// Lock is supposed to be called only by the unit test. func (t *batchTx) Lock() { - t.LockWithoutHook() - if t.backend.txPostLockHook != nil { - t.backend.txPostLockHook() - } + ValidateCalledInsideUnittest(t.backend.lg) + t.lock() } -func (t *batchTx) LockWithoutHook() { +func (t *batchTx) lock() { t.Mutex.Lock() } func (t *batchTx) LockInsideApply() { - ValidateCalledInsideApply(t.backend.lg) - t.Lock() + t.lock() + if t.backend.txPostLockHook != nil { + // The callers of some methods (i.e., (*RaftCluster).AddMember) + // can be coming from both InsideApply and OutsideApply, but the + // callers from OutsideApply will have a nil txPostLockHook. So we + // should check the txPostLockHook before validating the callstack. + ValidateCalledInsideApply(t.backend.lg) + t.backend.txPostLockHook() + } } func (t *batchTx) LockOutsideApply() { ValidateCalledOutSideApply(t.backend.lg) - t.Lock() + t.lock() } func (t *batchTx) Unlock() { @@ -233,14 +239,14 @@ func unsafeForEach(tx *bolt.Tx, bucket Bucket, visitor func(k, v []byte) error) // Commit commits a previous tx and begins a new writable one. func (t *batchTx) Commit() { - t.LockWithoutHook() + t.lock() t.commit(false) t.Unlock() } // CommitAndStop commits the previous tx and does not create a new one. func (t *batchTx) CommitAndStop() { - t.LockWithoutHook() + t.lock() t.commit(true) t.Unlock() } @@ -310,13 +316,13 @@ func (t *batchTxBuffered) Unlock() { } func (t *batchTxBuffered) Commit() { - t.LockWithoutHook() + t.lock() t.commit(false) t.Unlock() } func (t *batchTxBuffered) CommitAndStop() { - t.LockWithoutHook() + t.lock() t.commit(true) t.Unlock() } diff --git a/server/storage/backend/hooks_test.go b/server/storage/backend/hooks_test.go index 766464484890..b77efbba492d 100644 --- a/server/storage/backend/hooks_test.go +++ b/server/storage/backend/hooks_test.go @@ -41,8 +41,6 @@ func TestBackendPreCommitHook(t *testing.T) { // Empty commit. tx.Commit() - write(tx, []byte("foo"), []byte("bar")) - assert.Equal(t, ">cc", getCommitsKey(t, be), "expected 2 explict commits") tx.Commit() assert.Equal(t, ">ccc", getCommitsKey(t, be), "expected 3 explict commits") diff --git a/server/storage/backend/verify.go b/server/storage/backend/verify.go index 2f3dc0221c60..a6a0b8675ec5 100644 --- a/server/storage/backend/verify.go +++ b/server/storage/backend/verify.go @@ -46,6 +46,15 @@ func ValidateCalledOutSideApply(lg *zap.Logger) { } } +func ValidateCalledInsideUnittest(lg *zap.Logger) { + if !verifyLockEnabled() { + return + } + if !insideUnittest() { + lg.Fatal("Lock called outside of unit test!", zap.Stack("stacktrace")) + } +} + func verifyLockEnabled() bool { return os.Getenv(ENV_VERIFY) == ENV_VERIFY_ALL_VALUE || os.Getenv(ENV_VERIFY) == ENV_VERIFY_LOCK } @@ -54,3 +63,8 @@ func insideApply() bool { stackTraceStr := string(debug.Stack()) return strings.Contains(stackTraceStr, ".applyEntries") } + +func insideUnittest() bool { + stackTraceStr := string(debug.Stack()) + return strings.Contains(stackTraceStr, "_test.go") && !strings.Contains(stackTraceStr, "tests/") +} diff --git a/server/storage/backend/verify_test.go b/server/storage/backend/verify_test.go index 08efb392104a..2345f46b55f3 100644 --- a/server/storage/backend/verify_test.go +++ b/server/storage/backend/verify_test.go @@ -15,7 +15,6 @@ package backend_test import ( - "fmt" "os" "testing" "time" @@ -26,40 +25,60 @@ import ( func TestLockVerify(t *testing.T) { tcs := []struct { - insideApply bool - lock func(tx backend.BatchTx) - expectPanic bool + name string + insideApply bool + lock func(tx backend.BatchTx) + txPostLockHook func() + expectPanic bool }{ { + name: "call lockInsideApply from inside apply", insideApply: true, lock: lockInsideApply, expectPanic: false, }, { + name: "call lockInsideApply from outside apply (without txPostLockHook)", insideApply: false, lock: lockInsideApply, - expectPanic: true, + expectPanic: false, + }, + { + name: "call lockInsideApply from outside apply (with txPostLockHook)", + insideApply: false, + lock: lockInsideApply, + txPostLockHook: func() {}, + expectPanic: true, }, { + name: "call lockOutsideApply from outside apply", insideApply: false, lock: lockOutsideApply, expectPanic: false, }, { + name: "call lockOutsideApply from inside apply", insideApply: true, lock: lockOutsideApply, expectPanic: true, }, + { + name: "call Lock from unit test", + insideApply: false, + lock: lockFromUT, + expectPanic: false, + }, } env := os.Getenv("ETCD_VERIFY") os.Setenv("ETCD_VERIFY", "lock") defer func() { os.Setenv("ETCD_VERIFY", env) }() - for i, tc := range tcs { - t.Run(fmt.Sprintf("%d", i), func(t *testing.T) { + for _, tc := range tcs { + t.Run(tc.name, func(t *testing.T) { be, _ := betesting.NewTmpBackend(t, time.Hour, 10000) + be.SetTxPostLockInsideApplyHook(tc.txPostLockHook) hasPaniced := handlePanic(func() { if tc.insideApply { @@ -89,3 +108,4 @@ func applyEntries(be backend.Backend, f func(tx backend.BatchTx)) { func lockInsideApply(tx backend.BatchTx) { tx.LockInsideApply() } func lockOutsideApply(tx backend.BatchTx) { tx.LockOutsideApply() } +func lockFromUT(tx backend.BatchTx) { tx.Lock() } diff --git a/server/storage/mvcc/kvstore.go b/server/storage/mvcc/kvstore.go index 9b79c090afc9..074f1bea61be 100644 --- a/server/storage/mvcc/kvstore.go +++ b/server/storage/mvcc/kvstore.go @@ -121,7 +121,7 @@ func NewStore(lg *zap.Logger, b backend.Backend, le lease.Lessor, cfg StoreConfi } tx := s.b.BatchTx() - tx.LockWithoutHook() + tx.LockOutsideApply() tx.UnsafeCreateBucket(schema.Key) schema.UnsafeCreateMetaBucket(tx) tx.Unlock() @@ -331,7 +331,7 @@ func (s *store) restore() error { // restore index tx := s.b.BatchTx() - tx.LockWithoutHook() + tx.LockOutsideApply() finishedCompact, found := UnsafeReadFinishedCompact(tx) if found { diff --git a/server/storage/mvcc/kvstore_compaction.go b/server/storage/mvcc/kvstore_compaction.go index 941f056a9219..849f73b9576d 100644 --- a/server/storage/mvcc/kvstore_compaction.go +++ b/server/storage/mvcc/kvstore_compaction.go @@ -42,7 +42,7 @@ func (s *store) scheduleCompaction(compactMainRev int64, keep map[revision]struc start := time.Now() tx := s.b.BatchTx() - tx.LockWithoutHook() + tx.LockOutsideApply() keys, _ := tx.UnsafeRange(schema.Key, last, end, int64(batchNum)) for _, key := range keys { rev = bytesToRev(key) diff --git a/server/storage/mvcc/kvstore_test.go b/server/storage/mvcc/kvstore_test.go index 4a51e9c406bf..2779f10b7bfc 100644 --- a/server/storage/mvcc/kvstore_test.go +++ b/server/storage/mvcc/kvstore_test.go @@ -881,7 +881,8 @@ type fakeBatchTx struct { rangeRespc chan rangeResp } -func (b *fakeBatchTx) LockWithoutHook() {} +func (b *fakeBatchTx) LockInsideApply() {} +func (b *fakeBatchTx) LockOutsideApply() {} func (b *fakeBatchTx) Lock() {} func (b *fakeBatchTx) Unlock() {} func (b *fakeBatchTx) RLock() {} @@ -905,10 +906,8 @@ func (b *fakeBatchTx) UnsafeDelete(bucket backend.Bucket, key []byte) { func (b *fakeBatchTx) UnsafeForEach(bucket backend.Bucket, visitor func(k, v []byte) error) error { return nil } -func (b *fakeBatchTx) Commit() {} -func (b *fakeBatchTx) CommitAndStop() {} -func (b *fakeBatchTx) LockInsideApply() {} -func (b *fakeBatchTx) LockOutsideApply() {} +func (b *fakeBatchTx) Commit() {} +func (b *fakeBatchTx) CommitAndStop() {} type fakeBackend struct { tx *fakeBatchTx @@ -925,7 +924,7 @@ func (b *fakeBackend) Snapshot() backend.Snapshot func (b *fakeBackend) ForceCommit() {} func (b *fakeBackend) Defrag() error { return nil } func (b *fakeBackend) Close() error { return nil } -func (b *fakeBackend) SetTxPostLockHook(func()) {} +func (b *fakeBackend) SetTxPostLockInsideApplyHook(func()) {} type indexGetResp struct { rev revision diff --git a/server/storage/mvcc/kvstore_txn.go b/server/storage/mvcc/kvstore_txn.go index fb7a9ca1fa5c..604fac78cb3e 100644 --- a/server/storage/mvcc/kvstore_txn.go +++ b/server/storage/mvcc/kvstore_txn.go @@ -133,7 +133,7 @@ type storeTxnWrite struct { func (s *store) Write(trace *traceutil.Trace) TxnWrite { s.mu.RLock() tx := s.b.BatchTx() - tx.Lock() + tx.LockInsideApply() tw := &storeTxnWrite{ storeTxnRead: storeTxnRead{s, tx, 0, 0, trace}, tx: tx, diff --git a/server/storage/mvcc/store.go b/server/storage/mvcc/store.go index e530c82f4ece..a002ada71777 100644 --- a/server/storage/mvcc/store.go +++ b/server/storage/mvcc/store.go @@ -36,7 +36,7 @@ func UnsafeReadScheduledCompact(tx backend.ReadTx) (scheduledComact int64, found } func SetScheduledCompact(tx backend.BatchTx, value int64) { - tx.Lock() + tx.LockInsideApply() defer tx.Unlock() UnsafeSetScheduledCompact(tx, value) } @@ -48,7 +48,7 @@ func UnsafeSetScheduledCompact(tx backend.BatchTx, value int64) { } func SetFinishedCompact(tx backend.BatchTx, value int64) { - tx.Lock() + tx.LockInsideApply() defer tx.Unlock() UnsafeSetFinishedCompact(tx, value) } diff --git a/server/storage/schema/alarm.go b/server/storage/schema/alarm.go index 09a49994da46..825a8dbe0bfd 100644 --- a/server/storage/schema/alarm.go +++ b/server/storage/schema/alarm.go @@ -34,14 +34,14 @@ func NewAlarmBackend(lg *zap.Logger, be backend.Backend) *alarmBackend { func (s *alarmBackend) CreateAlarmBucket() { tx := s.be.BatchTx() - tx.LockWithoutHook() + tx.LockOutsideApply() defer tx.Unlock() tx.UnsafeCreateBucket(Alarm) } func (s *alarmBackend) MustPutAlarm(alarm *etcdserverpb.AlarmMember) { tx := s.be.BatchTx() - tx.Lock() + tx.LockInsideApply() defer tx.Unlock() s.mustUnsafePutAlarm(tx, alarm) } @@ -57,7 +57,7 @@ func (s *alarmBackend) mustUnsafePutAlarm(tx backend.BatchTx, alarm *etcdserverp func (s *alarmBackend) MustDeleteAlarm(alarm *etcdserverpb.AlarmMember) { tx := s.be.BatchTx() - tx.Lock() + tx.LockInsideApply() defer tx.Unlock() s.mustUnsafeDeleteAlarm(tx, alarm) } diff --git a/server/storage/schema/auth.go b/server/storage/schema/auth.go index 3956ca782f9d..aa695bb1d462 100644 --- a/server/storage/schema/auth.go +++ b/server/storage/schema/auth.go @@ -49,7 +49,7 @@ func NewAuthBackend(lg *zap.Logger, be backend.Backend) *authBackend { func (abe *authBackend) CreateAuthBuckets() { tx := abe.be.BatchTx() - tx.LockWithoutHook() + tx.LockOutsideApply() defer tx.Unlock() tx.UnsafeCreateBucket(Auth) tx.UnsafeCreateBucket(AuthUsers) @@ -106,7 +106,7 @@ func (atx *authBatchTx) UnsafeReadAuthRevision() uint64 { } func (atx *authBatchTx) Lock() { - atx.tx.Lock() + atx.tx.LockInsideApply() } func (atx *authBatchTx) Unlock() { diff --git a/server/storage/schema/cindex.go b/server/storage/schema/cindex.go index 38eea6f9179f..7d215bac6547 100644 --- a/server/storage/schema/cindex.go +++ b/server/storage/schema/cindex.go @@ -26,7 +26,7 @@ func UnsafeCreateMetaBucket(tx backend.BatchTx) { // CreateMetaBucket creates the `meta` bucket (if it does not exists yet). func CreateMetaBucket(tx backend.BatchTx) { - tx.LockWithoutHook() + tx.LockOutsideApply() defer tx.Unlock() tx.UnsafeCreateBucket(Meta) } diff --git a/server/storage/schema/membership.go b/server/storage/schema/membership.go index 153699e694aa..a42353c41686 100644 --- a/server/storage/schema/membership.go +++ b/server/storage/schema/membership.go @@ -52,7 +52,7 @@ func (s *membershipBackend) MustSaveMemberToBackend(m *membership.Member) { } tx := s.be.BatchTx() - tx.Lock() + tx.LockInsideApply() defer tx.Unlock() tx.UnsafePut(Members, mkey, mvalue) } @@ -61,7 +61,7 @@ func (s *membershipBackend) MustSaveMemberToBackend(m *membership.Member) { // from the v3 backend. func (s *membershipBackend) TrimClusterFromBackend() error { tx := s.be.BatchTx() - tx.LockWithoutHook() + tx.LockOutsideApply() defer tx.Unlock() tx.UnsafeDeleteBucket(Cluster) return nil @@ -71,7 +71,7 @@ func (s *membershipBackend) MustDeleteMemberFromBackend(id types.ID) { mkey := BackendMemberKey(id) tx := s.be.BatchTx() - tx.Lock() + tx.LockInsideApply() defer tx.Unlock() tx.UnsafeDelete(Members, mkey) tx.UnsafePut(MembersRemoved, mkey, []byte("removed")) @@ -121,7 +121,7 @@ func (s *membershipBackend) readMembersFromBackend() (map[types.ID]*membership.M func (s *membershipBackend) TrimMembershipFromBackend() error { s.lg.Info("Trimming membership information from the backend...") tx := s.be.BatchTx() - tx.LockWithoutHook() + tx.LockOutsideApply() defer tx.Unlock() err := tx.UnsafeForEach(Members, func(k, v []byte) error { tx.UnsafeDelete(Members, k) @@ -146,7 +146,7 @@ func (s *membershipBackend) MustSaveClusterVersionToBackend(ver *semver.Version) ckey := ClusterClusterVersionKeyName tx := s.be.BatchTx() - tx.Lock() + tx.LockInsideApply() defer tx.Unlock() tx.UnsafePut(Cluster, ckey, []byte(ver.String())) } @@ -160,14 +160,14 @@ func (s *membershipBackend) MustSaveDowngradeToBackend(downgrade *version.Downgr s.lg.Panic("failed to marshal downgrade information", zap.Error(err)) } tx := s.be.BatchTx() - tx.Lock() + tx.LockInsideApply() defer tx.Unlock() tx.UnsafePut(Cluster, dkey, dvalue) } func (s *membershipBackend) MustCreateBackendBuckets() { tx := s.be.BatchTx() - tx.LockWithoutHook() + tx.LockOutsideApply() defer tx.Unlock() tx.UnsafeCreateBucket(Members) tx.UnsafeCreateBucket(MembersRemoved) diff --git a/server/storage/schema/migration.go b/server/storage/schema/migration.go index e1e44dab5f90..61ea51bf2730 100644 --- a/server/storage/schema/migration.go +++ b/server/storage/schema/migration.go @@ -49,7 +49,7 @@ func newPlan(lg *zap.Logger, current semver.Version, target semver.Version) (pla } func (p migrationPlan) Execute(lg *zap.Logger, tx backend.BatchTx) error { - tx.LockWithoutHook() + tx.LockOutsideApply() defer tx.Unlock() return p.unsafeExecute(lg, tx) } @@ -90,7 +90,7 @@ func newMigrationStep(v semver.Version, isUpgrade bool, changes []schemaChange) // execute runs actions required to migrate etcd storage between two minor versions. func (s migrationStep) execute(lg *zap.Logger, tx backend.BatchTx) error { - tx.LockWithoutHook() + tx.LockOutsideApply() defer tx.Unlock() return s.unsafeExecute(lg, tx) } diff --git a/server/storage/schema/schema.go b/server/storage/schema/schema.go index 2b4c15f29c84..68bb212d71eb 100644 --- a/server/storage/schema/schema.go +++ b/server/storage/schema/schema.go @@ -30,13 +30,13 @@ var ( ) // Validate checks provided backend to confirm that schema used is supported. -func Validate(lg *zap.Logger, tx backend.BatchTx) error { - tx.LockWithoutHook() +func Validate(lg *zap.Logger, tx backend.ReadTx) error { + tx.Lock() defer tx.Unlock() return unsafeValidate(lg, tx) } -func unsafeValidate(lg *zap.Logger, tx backend.BatchTx) error { +func unsafeValidate(lg *zap.Logger, tx backend.ReadTx) error { current, err := UnsafeDetectSchemaVersion(lg, tx) if err != nil { // v3.5 requires a wal snapshot to persist its fields, so we can assign it a schema version. @@ -60,7 +60,7 @@ type WALVersion interface { // Migrate updates storage schema to provided target version. // Downgrading requires that provided WAL doesn't contain unsupported entries. func Migrate(lg *zap.Logger, tx backend.BatchTx, w WALVersion, target semver.Version) error { - tx.LockWithoutHook() + tx.LockOutsideApply() defer tx.Unlock() return UnsafeMigrate(lg, tx, w, target) } diff --git a/server/storage/schema/schema_test.go b/server/storage/schema/schema_test.go index f3c0c4a7fe89..8dbd337b2e5b 100644 --- a/server/storage/schema/schema_test.go +++ b/server/storage/schema/schema_test.go @@ -88,7 +88,7 @@ func TestValidate(t *testing.T) { b := backend.NewDefaultBackend(lg, dataPath) defer b.Close() - err := Validate(lg, b.BatchTx()) + err := Validate(lg, b.ReadTx()) if (err != nil) != tc.expectError { t.Errorf("Validate(lg, tx) = %+v, expected error: %v", err, tc.expectError) } From 4033f5c2b9b57cd341d1b3522abb03bedbeb9a07 Mon Sep 17 00:00:00 2001 From: ahrtr Date: Thu, 7 Apr 2022 06:11:34 +0800 Subject: [PATCH 256/258] move the consistentIdx and consistentTerm from Etcdserver to cindex package Removed the fields consistentIdx and consistentTerm from struct EtcdServer, and added applyingIndex and applyingTerm into struct consistentIndex in package cindex. We may remove the two fields completely if we decide to remove the OnPreCommitUnsafe, and it will depend on the performance test result. --- server/etcdserver/cindex/cindex.go | 43 +++++++++++++++++++++++++-- server/etcdserver/server.go | 34 ++++++++------------- server/storage/backend/backend.go | 10 +++---- server/storage/backend/batch_tx.go | 9 +++--- server/storage/backend/verify_test.go | 24 +++++++-------- 5 files changed, 75 insertions(+), 45 deletions(-) diff --git a/server/etcdserver/cindex/cindex.go b/server/etcdserver/cindex/cindex.go index 91046cd0370c..de64c1c11886 100644 --- a/server/etcdserver/cindex/cindex.go +++ b/server/etcdserver/cindex/cindex.go @@ -33,12 +33,18 @@ type ConsistentIndexer interface { // ConsistentIndex returns the consistent index of current executing entry. ConsistentIndex() uint64 + // ConsistentApplyingIndex returns the consistent applying index of current executing entry. + ConsistentApplyingIndex() (uint64, uint64) + // UnsafeConsistentIndex is similar to ConsistentIndex, but it doesn't lock the transaction. UnsafeConsistentIndex() uint64 // SetConsistentIndex set the consistent index of current executing entry. SetConsistentIndex(v uint64, term uint64) + // SetConsistentApplyingIndex set the consistent applying index of current executing entry. + SetConsistentApplyingIndex(v uint64, term uint64) + // UnsafeSave must be called holding the lock on the tx. // It saves consistentIndex to the underlying stable storage. UnsafeSave(tx backend.BatchTx) @@ -58,6 +64,19 @@ type consistentIndex struct { // The value is being persisted in the backend since v3.5. term uint64 + // applyingIndex and applyingTerm are just temporary cache of the raftpb.Entry.Index + // and raftpb.Entry.Term, and they are not ready to be persisted yet. They will be + // saved to consistentIndex and term above in the txPostLockInsideApplyHook. + // + // TODO(ahrtr): try to remove the OnPreCommitUnsafe, and compare the + // performance difference. Afterwards we can make a decision on whether + // or not we should remove OnPreCommitUnsafe. If it is true, then we + // can remove applyingIndex and applyingTerm, and save the e.Index and + // e.Term to consistentIndex and term directly in applyEntries, and + // persist them into db in the txPostLockInsideApplyHook. + applyingIndex uint64 + applyingTerm uint64 + // be is used for initial read consistentIndex be Backend // mutex is protecting be. @@ -111,6 +130,15 @@ func (ci *consistentIndex) SetBackend(be Backend) { ci.SetConsistentIndex(0, 0) } +func (ci *consistentIndex) ConsistentApplyingIndex() (uint64, uint64) { + return atomic.LoadUint64(&ci.applyingIndex), atomic.LoadUint64(&ci.applyingTerm) +} + +func (ci *consistentIndex) SetConsistentApplyingIndex(v uint64, term uint64) { + atomic.StoreUint64(&ci.applyingIndex, v) + atomic.StoreUint64(&ci.applyingTerm, term) +} + func NewFakeConsistentIndex(index uint64) ConsistentIndexer { return &fakeConsistentIndex{index: index} } @@ -120,13 +148,24 @@ type fakeConsistentIndex struct { term uint64 } -func (f *fakeConsistentIndex) ConsistentIndex() uint64 { return f.index } -func (f *fakeConsistentIndex) UnsafeConsistentIndex() uint64 { return f.index } +func (f *fakeConsistentIndex) ConsistentIndex() uint64 { + return atomic.LoadUint64(&f.index) +} +func (f *fakeConsistentIndex) ConsistentApplyingIndex() (uint64, uint64) { + return atomic.LoadUint64(&f.index), atomic.LoadUint64(&f.term) +} +func (f *fakeConsistentIndex) UnsafeConsistentIndex() uint64 { + return atomic.LoadUint64(&f.index) +} func (f *fakeConsistentIndex) SetConsistentIndex(index uint64, term uint64) { atomic.StoreUint64(&f.index, index) atomic.StoreUint64(&f.term, term) } +func (f *fakeConsistentIndex) SetConsistentApplyingIndex(index uint64, term uint64) { + atomic.StoreUint64(&f.index, index) + atomic.StoreUint64(&f.term, term) +} func (f *fakeConsistentIndex) UnsafeSave(_ backend.BatchTx) {} func (f *fakeConsistentIndex) SetBackend(_ Backend) {} diff --git a/server/etcdserver/server.go b/server/etcdserver/server.go index 015bcaf6f0a9..a3d0c9376f11 100644 --- a/server/etcdserver/server.go +++ b/server/etcdserver/server.go @@ -207,10 +207,8 @@ type EtcdServer struct { term uint64 // must use atomic operations to access; keep 64-bit aligned. lead uint64 // must use atomic operations to access; keep 64-bit aligned. - consistentIdx uint64 // must use atomic operations to access; keep 64-bit aligned. - consistentTerm uint64 // must use atomic operations to access; keep 64-bit aligned. - consistIndex cindex.ConsistentIndexer // consistIndex is used to get/set/save consistentIndex - r raftNode // uses 64-bit atomics; keep 64-bit aligned. + consistIndex cindex.ConsistentIndexer // consistIndex is used to get/set/save consistentIndex + r raftNode // uses 64-bit atomics; keep 64-bit aligned. readych chan struct{} Cfg config.ServerConfig @@ -405,7 +403,7 @@ func NewServer(cfg config.ServerConfig) (srv *EtcdServer, err error) { // Set the hook after EtcdServer finishes the initialization to avoid // the hook being called during the initialization process. - srv.be.SetTxPostLockInsideApplyHook(srv.getTxPostLockHook()) + srv.be.SetTxPostLockInsideApplyHook(srv.getTxPostLockInsideApplyHook()) // TODO: move transport initialization near the definition of remote tr := &rafthttp.Transport{ @@ -984,7 +982,7 @@ func (s *EtcdServer) applySnapshot(ep *etcdProgress, apply *apply) { } s.consistIndex.SetBackend(newbe) - newbe.SetTxPostLockInsideApplyHook(s.getTxPostLockHook()) + newbe.SetTxPostLockInsideApplyHook(s.getTxPostLockInsideApplyHook()) lg.Info("restored mvcc store", zap.Uint64("consistent-index", s.consistIndex.ConsistentIndex())) @@ -1555,15 +1553,6 @@ func (s *EtcdServer) getTerm() uint64 { return atomic.LoadUint64(&s.term) } -func (s *EtcdServer) setConsistentIndexAndTerm(cIdx, cTerm uint64) { - atomic.StoreUint64(&s.consistentIdx, cIdx) - atomic.StoreUint64(&s.consistentTerm, cTerm) -} - -func (s *EtcdServer) getConsistentIndexAndTerm() (uint64, uint64) { - return atomic.LoadUint64(&s.consistentIdx), atomic.LoadUint64(&s.consistentTerm) -} - func (s *EtcdServer) setLead(v uint64) { atomic.StoreUint64(&s.lead, v) } @@ -1788,7 +1777,7 @@ func (s *EtcdServer) apply( // set the consistent index of current executing entry if e.Index > s.consistIndex.ConsistentIndex() { - s.setConsistentIndexAndTerm(e.Index, e.Term) + s.consistIndex.SetConsistentApplyingIndex(e.Index, e.Term) shouldApplyV3 = membership.ApplyBoth } @@ -1826,7 +1815,7 @@ func (s *EtcdServer) applyEntryNormal(e *raftpb.Entry) { index := s.consistIndex.ConsistentIndex() if e.Index > index { // set the consistent index of current executing entry - s.setConsistentIndexAndTerm(e.Index, e.Term) + s.consistIndex.SetConsistentApplyingIndex(e.Index, e.Term) shouldApplyV3 = membership.ApplyBoth } s.lg.Debug("apply entry normal", @@ -1925,7 +1914,8 @@ func (s *EtcdServer) applyConfChange(cc raftpb.ConfChange, confState *raftpb.Con // The txPostLock callback will not get called in this case, // so we should set the consistent index directly. if s.consistIndex != nil && membership.ApplyBoth == shouldApplyV3 { - s.consistIndex.SetConsistentIndex(s.consistentIdx, s.consistentTerm) + applyingIndex, applyingTerm := s.consistIndex.ConsistentApplyingIndex() + s.consistIndex.SetConsistentIndex(applyingIndex, applyingTerm) } return false, err } @@ -2329,11 +2319,11 @@ func (s *EtcdServer) Version() *serverversion.Manager { return serverversion.NewManager(s.Logger(), NewServerVersionAdapter(s)) } -func (s *EtcdServer) getTxPostLockHook() func() { +func (s *EtcdServer) getTxPostLockInsideApplyHook() func() { return func() { - cIdx, term := s.getConsistentIndexAndTerm() - if cIdx > s.consistIndex.UnsafeConsistentIndex() { - s.consistIndex.SetConsistentIndex(cIdx, term) + applyingIdx, applyingTerm := s.consistIndex.ConsistentApplyingIndex() + if applyingIdx > s.consistIndex.UnsafeConsistentIndex() { + s.consistIndex.SetConsistentIndex(applyingIdx, applyingTerm) } } } diff --git a/server/storage/backend/backend.go b/server/storage/backend/backend.go index ebb99ee2c342..f30d79062c8c 100644 --- a/server/storage/backend/backend.go +++ b/server/storage/backend/backend.go @@ -68,7 +68,7 @@ type Backend interface { ForceCommit() Close() error - // SetTxPostLockInsideApplyHook sets a txPostLockHook. + // SetTxPostLockInsideApplyHook sets a txPostLockInsideApplyHook. SetTxPostLockInsideApplyHook(func()) } @@ -122,8 +122,8 @@ type backend struct { hooks Hooks - // txPostLockHook is called each time right after locking the tx. - txPostLockHook func() + // txPostLockInsideApplyHook is called each time right after locking the tx. + txPostLockInsideApplyHook func() lg *zap.Logger } @@ -235,10 +235,10 @@ func (b *backend) BatchTx() BatchTx { func (b *backend) SetTxPostLockInsideApplyHook(hook func()) { // It needs to lock the batchTx, because the periodic commit - // may be accessing the txPostLockHook at the moment. + // may be accessing the txPostLockInsideApplyHook at the moment. b.batchTx.lock() defer b.batchTx.Unlock() - b.txPostLockHook = hook + b.txPostLockInsideApplyHook = hook } func (b *backend) ReadTx() ReadTx { return b.readTx } diff --git a/server/storage/backend/batch_tx.go b/server/storage/backend/batch_tx.go index 7eca835fd221..c8fa55954f64 100644 --- a/server/storage/backend/batch_tx.go +++ b/server/storage/backend/batch_tx.go @@ -77,13 +77,14 @@ func (t *batchTx) lock() { func (t *batchTx) LockInsideApply() { t.lock() - if t.backend.txPostLockHook != nil { + if t.backend.txPostLockInsideApplyHook != nil { // The callers of some methods (i.e., (*RaftCluster).AddMember) // can be coming from both InsideApply and OutsideApply, but the - // callers from OutsideApply will have a nil txPostLockHook. So we - // should check the txPostLockHook before validating the callstack. + // callers from OutsideApply will have a nil txPostLockInsideApplyHook. + // So we should check the txPostLockInsideApplyHook before validating + // the callstack. ValidateCalledInsideApply(t.backend.lg) - t.backend.txPostLockHook() + t.backend.txPostLockInsideApplyHook() } } diff --git a/server/storage/backend/verify_test.go b/server/storage/backend/verify_test.go index 2345f46b55f3..5cb38ee9da75 100644 --- a/server/storage/backend/verify_test.go +++ b/server/storage/backend/verify_test.go @@ -25,11 +25,11 @@ import ( func TestLockVerify(t *testing.T) { tcs := []struct { - name string - insideApply bool - lock func(tx backend.BatchTx) - txPostLockHook func() - expectPanic bool + name string + insideApply bool + lock func(tx backend.BatchTx) + txPostLockInsideApplyHook func() + expectPanic bool }{ { name: "call lockInsideApply from inside apply", @@ -38,17 +38,17 @@ func TestLockVerify(t *testing.T) { expectPanic: false, }, { - name: "call lockInsideApply from outside apply (without txPostLockHook)", + name: "call lockInsideApply from outside apply (without txPostLockInsideApplyHook)", insideApply: false, lock: lockInsideApply, expectPanic: false, }, { - name: "call lockInsideApply from outside apply (with txPostLockHook)", - insideApply: false, - lock: lockInsideApply, - txPostLockHook: func() {}, - expectPanic: true, + name: "call lockInsideApply from outside apply (with txPostLockInsideApplyHook)", + insideApply: false, + lock: lockInsideApply, + txPostLockInsideApplyHook: func() {}, + expectPanic: true, }, { name: "call lockOutsideApply from outside apply", @@ -78,7 +78,7 @@ func TestLockVerify(t *testing.T) { t.Run(tc.name, func(t *testing.T) { be, _ := betesting.NewTmpBackend(t, time.Hour, 10000) - be.SetTxPostLockInsideApplyHook(tc.txPostLockHook) + be.SetTxPostLockInsideApplyHook(tc.txPostLockInsideApplyHook) hasPaniced := handlePanic(func() { if tc.insideApply { From 7cc00ec9810bf606c3aa0cd50103c646d7fcf891 Mon Sep 17 00:00:00 2001 From: Danielle Lancashire Date: Tue, 15 Mar 2022 18:56:19 +0000 Subject: [PATCH 257/258] tests/framework/integration: Fail nesting early Currently there are a handful of tests within etcd that silently fail because LeakDetection will skip the test before it manages to hit this check. Here we move the check to the beginning of the process to highlight these cases earlier, and to avoid them accidentally presenting as leaks. --- tests/framework/integration/testing.go | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/tests/framework/integration/testing.go b/tests/framework/integration/testing.go index ca4a27f0d524..a992c87f065a 100644 --- a/tests/framework/integration/testing.go +++ b/tests/framework/integration/testing.go @@ -72,6 +72,10 @@ func BeforeTest(t testutil.TB, opts ...TestOption) { t.Helper() options := newTestOptions(opts...) + if insideTestContext { + t.Fatal("already in test context. BeforeTest was likely already called") + } + if options.skipInShort { testutil.SkipTestIfShortMode(t, "Cannot create clusters in --short tests") } @@ -93,10 +97,6 @@ func BeforeTest(t testutil.TB, opts ...TestOption) { os.Chdir(previousWD) }) - if insideTestContext { - t.Fatal("already in test context. BeforeTest was likely already called") - } - grpc_logger.Set(zapgrpc.NewLogger(zaptest.NewLogger(t).Named("grpc"))) insideTestContext = true From 1ea53d527e09382e32f3ef7ddc562b4e5a9c5d93 Mon Sep 17 00:00:00 2001 From: Marek Siarkowicz Date: Thu, 7 Apr 2022 17:32:21 +0200 Subject: [PATCH 258/258] server: Save consistency index and term to backend even when they decrease Reason to store CI and term in backend was to make db fully independent snapshot, it was never meant to interfere with apply logic. Skip of CI was introduced for v2->v3 migration where we wanted to prevent it from decreasing when replaying wal in https://github.com/etcd-io/etcd/pull/5391. By mistake it was added to apply flow during refactor in https://github.com/etcd-io/etcd/pull/12855#commitcomment-70713670. Consistency index and term should only be negotiated and used by raft to make decisions. Their values should only driven by raft state machine and backend should only be responsible for storing them. --- etcdutl/etcdutl/backup_command.go | 2 +- etcdutl/snapshot/v3_snapshot.go | 2 +- server/etcdserver/bootstrap_test.go | 4 +- server/etcdserver/cindex/cindex.go | 7 ++-- server/etcdserver/cindex/cindex_test.go | 52 +++++++++++++++++++++++++ server/storage/schema/cindex.go | 24 +----------- server/storage/schema/schema_test.go | 8 ++-- 7 files changed, 65 insertions(+), 34 deletions(-) diff --git a/etcdutl/etcdutl/backup_command.go b/etcdutl/etcdutl/backup_command.go index e0d53fc1b1f8..28a02cfda3d5 100644 --- a/etcdutl/etcdutl/backup_command.go +++ b/etcdutl/etcdutl/backup_command.go @@ -325,7 +325,7 @@ func saveDB(lg *zap.Logger, destDB, srcDB string, idx uint64, term uint64, desir tx.LockOutsideApply() defer tx.Unlock() schema.UnsafeCreateMetaBucket(tx) - schema.UnsafeUpdateConsistentIndex(tx, idx, term, false) + schema.UnsafeUpdateConsistentIndex(tx, idx, term) } else { // Thanks to translateWAL not moving entries, but just replacing them with // 'empty', there is no need to update the consistency index. diff --git a/etcdutl/snapshot/v3_snapshot.go b/etcdutl/snapshot/v3_snapshot.go index fcce5bf8282a..53203588afe2 100644 --- a/etcdutl/snapshot/v3_snapshot.go +++ b/etcdutl/snapshot/v3_snapshot.go @@ -483,6 +483,6 @@ func (s *v3Manager) updateCIndex(commit uint64, term uint64) error { be := backend.NewDefaultBackend(s.lg, s.outDbPath()) defer be.Close() - cindex.UpdateConsistentIndex(be.BatchTx(), commit, term, false) + cindex.UpdateConsistentIndex(be.BatchTx(), commit, term) return nil } diff --git a/server/etcdserver/bootstrap_test.go b/server/etcdserver/bootstrap_test.go index a95ff34800ed..93cc177d4502 100644 --- a/server/etcdserver/bootstrap_test.go +++ b/server/etcdserver/bootstrap_test.go @@ -288,7 +288,7 @@ func createSnapshotAndBackendDB(cfg config.ServerConfig, snapshotTerm, snapshotI // create snapshot db file: "%016x.snap.db" be := serverstorage.OpenBackend(cfg, nil) schema.CreateMetaBucket(be.BatchTx()) - schema.UnsafeUpdateConsistentIndex(be.BatchTx(), snapshotIndex, snapshotTerm, false) + schema.UnsafeUpdateConsistentIndex(be.BatchTx(), snapshotIndex, snapshotTerm) schema.MustUnsafeSaveConfStateToBackend(cfg.Logger, be.BatchTx(), &confState) if err = be.Close(); err != nil { return @@ -301,6 +301,6 @@ func createSnapshotAndBackendDB(cfg config.ServerConfig, snapshotTerm, snapshotI // create backend db file be = serverstorage.OpenBackend(cfg, nil) schema.CreateMetaBucket(be.BatchTx()) - schema.UnsafeUpdateConsistentIndex(be.BatchTx(), 1, 1, false) + schema.UnsafeUpdateConsistentIndex(be.BatchTx(), 1, 1) return be.Close() } diff --git a/server/etcdserver/cindex/cindex.go b/server/etcdserver/cindex/cindex.go index de64c1c11886..05b4069bbf30 100644 --- a/server/etcdserver/cindex/cindex.go +++ b/server/etcdserver/cindex/cindex.go @@ -24,7 +24,6 @@ import ( type Backend interface { ReadTx() backend.ReadTx - BatchTx() backend.BatchTx } // ConsistentIndexer is an interface that wraps the Get/Set/Save method for consistentIndex. @@ -119,7 +118,7 @@ func (ci *consistentIndex) SetConsistentIndex(v uint64, term uint64) { func (ci *consistentIndex) UnsafeSave(tx backend.BatchTx) { index := atomic.LoadUint64(&ci.consistentIndex) term := atomic.LoadUint64(&ci.term) - schema.UnsafeUpdateConsistentIndex(tx, index, term, true) + schema.UnsafeUpdateConsistentIndex(tx, index, term) } func (ci *consistentIndex) SetBackend(be Backend) { @@ -170,8 +169,8 @@ func (f *fakeConsistentIndex) SetConsistentApplyingIndex(index uint64, term uint func (f *fakeConsistentIndex) UnsafeSave(_ backend.BatchTx) {} func (f *fakeConsistentIndex) SetBackend(_ Backend) {} -func UpdateConsistentIndex(tx backend.BatchTx, index uint64, term uint64, onlyGrow bool) { +func UpdateConsistentIndex(tx backend.BatchTx, index uint64, term uint64) { tx.LockOutsideApply() defer tx.Unlock() - schema.UnsafeUpdateConsistentIndex(tx, index, term, onlyGrow) + schema.UnsafeUpdateConsistentIndex(tx, index, term) } diff --git a/server/etcdserver/cindex/cindex_test.go b/server/etcdserver/cindex/cindex_test.go index 026c5a624666..da93d51c28fa 100644 --- a/server/etcdserver/cindex/cindex_test.go +++ b/server/etcdserver/cindex/cindex_test.go @@ -65,6 +65,58 @@ func TestConsistentIndex(t *testing.T) { assert.Equal(t, r, index) } +func TestConsistentIndexDecrease(t *testing.T) { + initIndex := uint64(100) + initTerm := uint64(10) + + tcs := []struct { + name string + index uint64 + term uint64 + }{ + { + name: "Decrease term", + index: initIndex + 1, + term: initTerm - 1, + }, + { + name: "Decrease CI", + index: initIndex - 1, + term: initTerm + 1, + }, + { + name: "Decrease CI and term", + index: initIndex - 1, + term: initTerm - 1, + }, + } + for _, tc := range tcs { + t.Run(tc.name, func(t *testing.T) { + be, tmpPath := betesting.NewTmpBackend(t, time.Microsecond, 10) + tx := be.BatchTx() + tx.Lock() + schema.UnsafeCreateMetaBucket(tx) + schema.UnsafeUpdateConsistentIndex(tx, initIndex, initTerm) + tx.Unlock() + be.ForceCommit() + be.Close() + + be = backend.NewDefaultBackend(zaptest.NewLogger(t), tmpPath) + defer be.Close() + ci := NewConsistentIndex(be) + ci.SetConsistentIndex(tc.index, tc.term) + tx = be.BatchTx() + tx.Lock() + ci.UnsafeSave(tx) + tx.Unlock() + assert.Equal(t, tc.index, ci.ConsistentIndex()) + + ci = NewConsistentIndex(be) + assert.Equal(t, tc.index, ci.ConsistentIndex()) + }) + } +} + func TestFakeConsistentIndex(t *testing.T) { r := rand.Uint64() diff --git a/server/storage/schema/cindex.go b/server/storage/schema/cindex.go index 7d215bac6547..afd98d8d939a 100644 --- a/server/storage/schema/cindex.go +++ b/server/storage/schema/cindex.go @@ -16,6 +16,7 @@ package schema import ( "encoding/binary" + "go.etcd.io/etcd/server/v3/storage/backend" ) @@ -56,32 +57,11 @@ func ReadConsistentIndex(tx backend.ReadTx) (uint64, uint64) { return UnsafeReadConsistentIndex(tx) } -func UnsafeUpdateConsistentIndex(tx backend.BatchTx, index uint64, term uint64, onlyGrow bool) { +func UnsafeUpdateConsistentIndex(tx backend.BatchTx, index uint64, term uint64) { if index == 0 { // Never save 0 as it means that we didn't load the real index yet. return } - - if onlyGrow { - oldi, oldTerm := UnsafeReadConsistentIndex(tx) - if term < oldTerm { - return - } - if index > oldi { - bs1 := make([]byte, 8) - binary.BigEndian.PutUint64(bs1, index) - // put the index into the underlying backend - // tx has been locked in TxnBegin, so there is no need to lock it again - tx.UnsafePut(Meta, MetaConsistentIndexKeyName, bs1) - } - if term > 0 && term > oldTerm { - bs2 := make([]byte, 8) - binary.BigEndian.PutUint64(bs2, term) - tx.UnsafePut(Meta, MetaTermKeyName, bs2) - } - return - } - bs1 := make([]byte, 8) binary.BigEndian.PutUint64(bs1, index) // put the index into the underlying backend diff --git a/server/storage/schema/schema_test.go b/server/storage/schema/schema_test.go index 8dbd337b2e5b..3272b189340d 100644 --- a/server/storage/schema/schema_test.go +++ b/server/storage/schema/schema_test.go @@ -67,7 +67,7 @@ func TestValidate(t *testing.T) { version: V3_5, overrideKeys: func(tx backend.BatchTx) { MustUnsafeSaveConfStateToBackend(zap.NewNop(), tx, &raftpb.ConfState{}) - UnsafeUpdateConsistentIndex(tx, 1, 1, false) + UnsafeUpdateConsistentIndex(tx, 1, 1) }, }, { @@ -313,14 +313,14 @@ func setupBackendData(t *testing.T, version semver.Version, overrideKeys func(tx case V3_4: case V3_5: MustUnsafeSaveConfStateToBackend(zap.NewNop(), tx, &raftpb.ConfState{}) - UnsafeUpdateConsistentIndex(tx, 1, 1, false) + UnsafeUpdateConsistentIndex(tx, 1, 1) case V3_6: MustUnsafeSaveConfStateToBackend(zap.NewNop(), tx, &raftpb.ConfState{}) - UnsafeUpdateConsistentIndex(tx, 1, 1, false) + UnsafeUpdateConsistentIndex(tx, 1, 1) UnsafeSetStorageVersion(tx, &V3_6) case V3_7: MustUnsafeSaveConfStateToBackend(zap.NewNop(), tx, &raftpb.ConfState{}) - UnsafeUpdateConsistentIndex(tx, 1, 1, false) + UnsafeUpdateConsistentIndex(tx, 1, 1) UnsafeSetStorageVersion(tx, &V3_7) tx.UnsafePut(Meta, []byte("future-key"), []byte("")) default: