[VOL-4291] Rw-core updates for gRPC migration
Change-Id: I8d5a554409115b29318089671ca4e1ab3fa98810
diff --git a/vendor/go.etcd.io/etcd/etcdserver/api/capability.go b/vendor/go.etcd.io/etcd/etcdserver/api/capability.go
deleted file mode 100644
index 09b754d..0000000
--- a/vendor/go.etcd.io/etcd/etcdserver/api/capability.go
+++ /dev/null
@@ -1,99 +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 api
-
-import (
- "sync"
-
- "go.etcd.io/etcd/version"
- "go.uber.org/zap"
-
- "github.com/coreos/go-semver/semver"
- "github.com/coreos/pkg/capnslog"
-)
-
-type Capability string
-
-const (
- AuthCapability Capability = "auth"
- V3rpcCapability Capability = "v3rpc"
-)
-
-var (
- plog = capnslog.NewPackageLogger("go.etcd.io/etcd", "etcdserver/api")
-
- // capabilityMaps is a static map of version to capability map.
- capabilityMaps = map[string]map[Capability]bool{
- "3.0.0": {AuthCapability: true, V3rpcCapability: true},
- "3.1.0": {AuthCapability: true, V3rpcCapability: true},
- "3.2.0": {AuthCapability: true, V3rpcCapability: true},
- "3.3.0": {AuthCapability: true, V3rpcCapability: true},
- "3.4.0": {AuthCapability: true, V3rpcCapability: true},
- "3.5.0": {AuthCapability: true, V3rpcCapability: true},
- }
-
- enableMapMu sync.RWMutex
- // enabledMap points to a map in capabilityMaps
- enabledMap map[Capability]bool
-
- curVersion *semver.Version
-)
-
-func init() {
- enabledMap = map[Capability]bool{
- AuthCapability: true,
- V3rpcCapability: true,
- }
-}
-
-// UpdateCapability updates the enabledMap when the cluster version increases.
-func UpdateCapability(lg *zap.Logger, v *semver.Version) {
- if v == nil {
- // if recovered but version was never set by cluster
- return
- }
- enableMapMu.Lock()
- if curVersion != nil && !curVersion.LessThan(*v) {
- enableMapMu.Unlock()
- return
- }
- curVersion = v
- enabledMap = capabilityMaps[curVersion.String()]
- enableMapMu.Unlock()
-
- if lg != nil {
- lg.Info(
- "enabled capabilities for version",
- zap.String("cluster-version", version.Cluster(v.String())),
- )
- } else {
- plog.Infof("enabled capabilities for version %s", version.Cluster(v.String()))
- }
-}
-
-func IsCapabilityEnabled(c Capability) bool {
- enableMapMu.RLock()
- defer enableMapMu.RUnlock()
- if enabledMap == nil {
- return false
- }
- return enabledMap[c]
-}
-
-func EnableCapability(c Capability) {
- enableMapMu.Lock()
- defer enableMapMu.Unlock()
- enabledMap[c] = true
-}
diff --git a/vendor/go.etcd.io/etcd/etcdserver/api/cluster.go b/vendor/go.etcd.io/etcd/etcdserver/api/cluster.go
deleted file mode 100644
index 901be9d..0000000
--- a/vendor/go.etcd.io/etcd/etcdserver/api/cluster.go
+++ /dev/null
@@ -1,38 +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 api
-
-import (
- "go.etcd.io/etcd/etcdserver/api/membership"
- "go.etcd.io/etcd/pkg/types"
-
- "github.com/coreos/go-semver/semver"
-)
-
-// Cluster is an interface representing a collection of members in one etcd cluster.
-type Cluster interface {
- // ID returns the cluster ID
- ID() types.ID
- // ClientURLs returns an aggregate set of all URLs on which this
- // cluster is listening for client requests
- ClientURLs() []string
- // Members returns a slice of members sorted by their ID
- Members() []*membership.Member
- // Member retrieves a particular member based on ID, or nil if the
- // member does not exist in the cluster
- Member(id types.ID) *membership.Member
- // Version is the cluster-wide minimum major.minor version.
- Version() *semver.Version
-}
diff --git a/vendor/go.etcd.io/etcd/etcdserver/api/doc.go b/vendor/go.etcd.io/etcd/etcdserver/api/doc.go
deleted file mode 100644
index f44881b..0000000
--- a/vendor/go.etcd.io/etcd/etcdserver/api/doc.go
+++ /dev/null
@@ -1,16 +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 api manages the capabilities and features that are exposed to clients by the etcd cluster.
-package api
diff --git a/vendor/go.etcd.io/etcd/etcdserver/api/etcdhttp/base.go b/vendor/go.etcd.io/etcd/etcdserver/api/etcdhttp/base.go
deleted file mode 100644
index c9df62e..0000000
--- a/vendor/go.etcd.io/etcd/etcdserver/api/etcdhttp/base.go
+++ /dev/null
@@ -1,203 +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 etcdhttp
-
-import (
- "encoding/json"
- "expvar"
- "fmt"
- "net/http"
- "strings"
-
- "go.etcd.io/etcd/etcdserver"
- "go.etcd.io/etcd/etcdserver/api"
- "go.etcd.io/etcd/etcdserver/api/v2error"
- "go.etcd.io/etcd/etcdserver/api/v2http/httptypes"
- "go.etcd.io/etcd/pkg/logutil"
- "go.etcd.io/etcd/version"
-
- "github.com/coreos/pkg/capnslog"
- "go.uber.org/zap"
-)
-
-var (
- plog = capnslog.NewPackageLogger("go.etcd.io/etcd", "etcdserver/api/etcdhttp")
- mlog = logutil.NewMergeLogger(plog)
-)
-
-const (
- configPath = "/config"
- varsPath = "/debug/vars"
- versionPath = "/version"
-)
-
-// HandleBasic adds handlers to a mux for serving JSON etcd client requests
-// that do not access the v2 store.
-func HandleBasic(mux *http.ServeMux, server etcdserver.ServerPeer) {
- mux.HandleFunc(varsPath, serveVars)
-
- // TODO: deprecate '/config/local/log' in v3.5
- mux.HandleFunc(configPath+"/local/log", logHandleFunc)
-
- HandleMetricsHealth(mux, server)
- mux.HandleFunc(versionPath, versionHandler(server.Cluster(), serveVersion))
-}
-
-func versionHandler(c api.Cluster, fn func(http.ResponseWriter, *http.Request, string)) http.HandlerFunc {
- return func(w http.ResponseWriter, r *http.Request) {
- v := c.Version()
- if v != nil {
- fn(w, r, v.String())
- } else {
- fn(w, r, "not_decided")
- }
- }
-}
-
-func serveVersion(w http.ResponseWriter, r *http.Request, clusterV string) {
- if !allowMethod(w, r, "GET") {
- return
- }
- vs := version.Versions{
- Server: version.Version,
- Cluster: clusterV,
- }
-
- w.Header().Set("Content-Type", "application/json")
- b, err := json.Marshal(&vs)
- if err != nil {
- plog.Panicf("cannot marshal versions to json (%v)", err)
- }
- w.Write(b)
-}
-
-// TODO: deprecate '/config/local/log' in v3.5
-func logHandleFunc(w http.ResponseWriter, r *http.Request) {
- if !allowMethod(w, r, "PUT") {
- return
- }
-
- in := struct{ Level string }{}
-
- d := json.NewDecoder(r.Body)
- if err := d.Decode(&in); err != nil {
- WriteError(nil, w, r, httptypes.NewHTTPError(http.StatusBadRequest, "Invalid json body"))
- return
- }
-
- logl, err := capnslog.ParseLevel(strings.ToUpper(in.Level))
- if err != nil {
- WriteError(nil, w, r, httptypes.NewHTTPError(http.StatusBadRequest, "Invalid log level "+in.Level))
- return
- }
-
- plog.Noticef("globalLogLevel set to %q", logl.String())
- capnslog.SetGlobalLogLevel(logl)
- w.WriteHeader(http.StatusNoContent)
-}
-
-func serveVars(w http.ResponseWriter, r *http.Request) {
- if !allowMethod(w, r, "GET") {
- return
- }
-
- w.Header().Set("Content-Type", "application/json; charset=utf-8")
- fmt.Fprintf(w, "{\n")
- first := true
- expvar.Do(func(kv expvar.KeyValue) {
- if !first {
- fmt.Fprintf(w, ",\n")
- }
- first = false
- fmt.Fprintf(w, "%q: %s", kv.Key, kv.Value)
- })
- fmt.Fprintf(w, "\n}\n")
-}
-
-func allowMethod(w http.ResponseWriter, r *http.Request, m string) bool {
- if m == r.Method {
- return true
- }
- w.Header().Set("Allow", m)
- http.Error(w, "Method Not Allowed", http.StatusMethodNotAllowed)
- return false
-}
-
-// WriteError logs and writes the given Error to the ResponseWriter
-// If Error is an etcdErr, it is rendered to the ResponseWriter
-// Otherwise, it is assumed to be a StatusInternalServerError
-func WriteError(lg *zap.Logger, w http.ResponseWriter, r *http.Request, err error) {
- if err == nil {
- return
- }
- switch e := err.(type) {
- case *v2error.Error:
- e.WriteTo(w)
-
- case *httptypes.HTTPError:
- if et := e.WriteTo(w); et != nil {
- if lg != nil {
- lg.Debug(
- "failed to write v2 HTTP error",
- zap.String("remote-addr", r.RemoteAddr),
- zap.String("internal-server-error", e.Error()),
- zap.Error(et),
- )
- } else {
- plog.Debugf("error writing HTTPError (%v) to %s", et, r.RemoteAddr)
- }
- }
-
- default:
- switch err {
- case etcdserver.ErrTimeoutDueToLeaderFail, etcdserver.ErrTimeoutDueToConnectionLost, etcdserver.ErrNotEnoughStartedMembers,
- etcdserver.ErrUnhealthy:
- if lg != nil {
- lg.Warn(
- "v2 response error",
- zap.String("remote-addr", r.RemoteAddr),
- zap.String("internal-server-error", err.Error()),
- )
- } else {
- mlog.MergeError(err)
- }
-
- default:
- if lg != nil {
- lg.Warn(
- "unexpected v2 response error",
- zap.String("remote-addr", r.RemoteAddr),
- zap.String("internal-server-error", err.Error()),
- )
- } else {
- mlog.MergeErrorf("got unexpected response error (%v)", err)
- }
- }
-
- herr := httptypes.NewHTTPError(http.StatusInternalServerError, "Internal Server 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("internal-server-error", err.Error()),
- zap.Error(et),
- )
- } else {
- plog.Debugf("error writing HTTPError (%v) to %s", et, r.RemoteAddr)
- }
- }
- }
-}
diff --git a/vendor/go.etcd.io/etcd/etcdserver/api/etcdhttp/doc.go b/vendor/go.etcd.io/etcd/etcdserver/api/etcdhttp/doc.go
deleted file mode 100644
index a03b626..0000000
--- a/vendor/go.etcd.io/etcd/etcdserver/api/etcdhttp/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 etcdhttp implements HTTP transportation layer for etcdserver.
-package etcdhttp
diff --git a/vendor/go.etcd.io/etcd/etcdserver/api/etcdhttp/metrics.go b/vendor/go.etcd.io/etcd/etcdserver/api/etcdhttp/metrics.go
deleted file mode 100644
index f455e40..0000000
--- a/vendor/go.etcd.io/etcd/etcdserver/api/etcdhttp/metrics.go
+++ /dev/null
@@ -1,123 +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 etcdhttp
-
-import (
- "context"
- "encoding/json"
- "net/http"
- "time"
-
- "go.etcd.io/etcd/etcdserver"
- "go.etcd.io/etcd/etcdserver/etcdserverpb"
- "go.etcd.io/etcd/raft"
-
- "github.com/prometheus/client_golang/prometheus"
- "github.com/prometheus/client_golang/prometheus/promhttp"
-)
-
-const (
- PathMetrics = "/metrics"
- PathHealth = "/health"
-)
-
-// HandleMetricsHealth registers metrics and health handlers.
-func HandleMetricsHealth(mux *http.ServeMux, srv etcdserver.ServerV2) {
- mux.Handle(PathMetrics, promhttp.Handler())
- mux.Handle(PathHealth, NewHealthHandler(func() Health { return checkHealth(srv) }))
-}
-
-// HandlePrometheus registers prometheus handler on '/metrics'.
-func HandlePrometheus(mux *http.ServeMux) {
- mux.Handle(PathMetrics, promhttp.Handler())
-}
-
-// NewHealthHandler handles '/health' requests.
-func NewHealthHandler(hfunc func() Health) http.HandlerFunc {
- return func(w http.ResponseWriter, r *http.Request) {
- if r.Method != http.MethodGet {
- w.Header().Set("Allow", http.MethodGet)
- http.Error(w, "Method Not Allowed", http.StatusMethodNotAllowed)
- return
- }
- h := hfunc()
- d, _ := json.Marshal(h)
- if h.Health != "true" {
- http.Error(w, string(d), http.StatusServiceUnavailable)
- return
- }
- w.WriteHeader(http.StatusOK)
- w.Write(d)
- }
-}
-
-var (
- healthSuccess = prometheus.NewCounter(prometheus.CounterOpts{
- Namespace: "etcd",
- Subsystem: "server",
- Name: "health_success",
- Help: "The total number of successful health checks",
- })
- healthFailed = prometheus.NewCounter(prometheus.CounterOpts{
- Namespace: "etcd",
- Subsystem: "server",
- Name: "health_failures",
- Help: "The total number of failed health checks",
- })
-)
-
-func init() {
- prometheus.MustRegister(healthSuccess)
- prometheus.MustRegister(healthFailed)
-}
-
-// Health defines etcd server health status.
-// TODO: remove manual parsing in etcdctl cluster-health
-type Health struct {
- Health string `json:"health"`
-}
-
-// TODO: server NOSPACE, etcdserver.ErrNoLeader in health API
-
-func checkHealth(srv etcdserver.ServerV2) Health {
- h := Health{Health: "true"}
-
- as := srv.Alarms()
- if len(as) > 0 {
- h.Health = "false"
- }
-
- if h.Health == "true" {
- if uint64(srv.Leader()) == raft.None {
- h.Health = "false"
- }
- }
-
- if h.Health == "true" {
- ctx, cancel := context.WithTimeout(context.Background(), time.Second)
- _, err := srv.Do(ctx, etcdserverpb.Request{Method: "QGET"})
- cancel()
- if err != nil {
- h.Health = "false"
- }
- }
-
- if h.Health == "true" {
- healthSuccess.Inc()
- } else {
- healthFailed.Inc()
- }
- return h
-}
diff --git a/vendor/go.etcd.io/etcd/etcdserver/api/etcdhttp/peer.go b/vendor/go.etcd.io/etcd/etcdserver/api/etcdhttp/peer.go
deleted file mode 100644
index 6c61bf5..0000000
--- a/vendor/go.etcd.io/etcd/etcdserver/api/etcdhttp/peer.go
+++ /dev/null
@@ -1,159 +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 etcdhttp
-
-import (
- "encoding/json"
- "fmt"
- "net/http"
- "strconv"
- "strings"
-
- "go.etcd.io/etcd/etcdserver"
- "go.etcd.io/etcd/etcdserver/api"
- "go.etcd.io/etcd/etcdserver/api/membership"
- "go.etcd.io/etcd/etcdserver/api/rafthttp"
- "go.etcd.io/etcd/lease/leasehttp"
- "go.etcd.io/etcd/pkg/types"
-
- "go.uber.org/zap"
-)
-
-const (
- peerMembersPath = "/members"
- peerMemberPromotePrefix = "/members/promote/"
-)
-
-// NewPeerHandler generates an http.Handler to handle etcd peer requests.
-func NewPeerHandler(lg *zap.Logger, s etcdserver.ServerPeer) http.Handler {
- return newPeerHandler(lg, s, s.RaftHandler(), s.LeaseHandler())
-}
-
-func newPeerHandler(lg *zap.Logger, s etcdserver.Server, raftHandler http.Handler, leaseHandler http.Handler) http.Handler {
- peerMembersHandler := newPeerMembersHandler(lg, s.Cluster())
- peerMemberPromoteHandler := newPeerMemberPromoteHandler(lg, s)
-
- mux := http.NewServeMux()
- mux.HandleFunc("/", http.NotFound)
- mux.Handle(rafthttp.RaftPrefix, raftHandler)
- mux.Handle(rafthttp.RaftPrefix+"/", raftHandler)
- mux.Handle(peerMembersPath, peerMembersHandler)
- mux.Handle(peerMemberPromotePrefix, peerMemberPromoteHandler)
- if leaseHandler != nil {
- mux.Handle(leasehttp.LeasePrefix, leaseHandler)
- mux.Handle(leasehttp.LeaseInternalPrefix, leaseHandler)
- }
- mux.HandleFunc(versionPath, versionHandler(s.Cluster(), serveVersion))
- return mux
-}
-
-func newPeerMembersHandler(lg *zap.Logger, cluster api.Cluster) http.Handler {
- return &peerMembersHandler{
- lg: lg,
- cluster: cluster,
- }
-}
-
-type peerMembersHandler struct {
- lg *zap.Logger
- cluster api.Cluster
-}
-
-func newPeerMemberPromoteHandler(lg *zap.Logger, s etcdserver.Server) http.Handler {
- return &peerMemberPromoteHandler{
- lg: lg,
- cluster: s.Cluster(),
- server: s,
- }
-}
-
-type peerMemberPromoteHandler struct {
- lg *zap.Logger
- cluster api.Cluster
- server etcdserver.Server
-}
-
-func (h *peerMembersHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
- if !allowMethod(w, r, "GET") {
- return
- }
- w.Header().Set("X-Etcd-Cluster-ID", h.cluster.ID().String())
-
- if r.URL.Path != peerMembersPath {
- http.Error(w, "bad path", http.StatusBadRequest)
- return
- }
- ms := h.cluster.Members()
- w.Header().Set("Content-Type", "application/json")
- if err := json.NewEncoder(w).Encode(ms); err != nil {
- if h.lg != nil {
- h.lg.Warn("failed to encode membership members", zap.Error(err))
- } else {
- plog.Warningf("failed to encode members response (%v)", err)
- }
- }
-}
-
-func (h *peerMemberPromoteHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
- if !allowMethod(w, r, "POST") {
- return
- }
- w.Header().Set("X-Etcd-Cluster-ID", h.cluster.ID().String())
-
- if !strings.HasPrefix(r.URL.Path, peerMemberPromotePrefix) {
- http.Error(w, "bad path", http.StatusBadRequest)
- return
- }
- idStr := strings.TrimPrefix(r.URL.Path, peerMemberPromotePrefix)
- id, err := strconv.ParseUint(idStr, 10, 64)
- if err != nil {
- http.Error(w, fmt.Sprintf("member %s not found in cluster", idStr), http.StatusNotFound)
- return
- }
-
- resp, err := h.server.PromoteMember(r.Context(), id)
- if err != nil {
- switch err {
- case membership.ErrIDNotFound:
- http.Error(w, err.Error(), http.StatusNotFound)
- case membership.ErrMemberNotLearner:
- http.Error(w, err.Error(), http.StatusPreconditionFailed)
- case etcdserver.ErrLearnerNotReady:
- http.Error(w, err.Error(), http.StatusPreconditionFailed)
- default:
- WriteError(h.lg, w, r, err)
- }
- if h.lg != nil {
- h.lg.Warn(
- "failed to promote a member",
- zap.String("member-id", types.ID(id).String()),
- zap.Error(err),
- )
- } else {
- plog.Errorf("error promoting member %s (%v)", types.ID(id).String(), err)
- }
- return
- }
-
- w.Header().Set("Content-Type", "application/json")
- w.WriteHeader(http.StatusOK)
- if err := json.NewEncoder(w).Encode(resp); err != nil {
- if h.lg != nil {
- h.lg.Warn("failed to encode members response", zap.Error(err))
- } else {
- plog.Warningf("failed to encode members response (%v)", err)
- }
- }
-}
diff --git a/vendor/go.etcd.io/etcd/etcdserver/api/membership/cluster.go b/vendor/go.etcd.io/etcd/etcdserver/api/membership/cluster.go
deleted file mode 100644
index 89a6edd..0000000
--- a/vendor/go.etcd.io/etcd/etcdserver/api/membership/cluster.go
+++ /dev/null
@@ -1,841 +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 membership
-
-import (
- "bytes"
- "context"
- "crypto/sha1"
- "encoding/binary"
- "encoding/json"
- "fmt"
- "path"
- "sort"
- "strings"
- "sync"
- "time"
-
- "go.etcd.io/etcd/etcdserver/api/v2store"
- "go.etcd.io/etcd/mvcc/backend"
- "go.etcd.io/etcd/pkg/netutil"
- "go.etcd.io/etcd/pkg/types"
- "go.etcd.io/etcd/raft"
- "go.etcd.io/etcd/raft/raftpb"
- "go.etcd.io/etcd/version"
-
- "github.com/coreos/go-semver/semver"
- "github.com/prometheus/client_golang/prometheus"
- "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
-
- localID types.ID
- cid types.ID
- token string
-
- v2store v2store.Store
- be backend.Backend
-
- sync.Mutex // guards the fields below
- version *semver.Version
- members map[types.ID]*Member
- // removed contains the ids of removed members in the cluster.
- // removed id cannot be reused.
- removed map[types.ID]bool
-}
-
-// ConfigChangeContext represents a context for confChange.
-type ConfigChangeContext struct {
- Member
- // IsPromote indicates if the config change is for promoting a learner member.
- // This flag is needed because both adding a new member and promoting a learner member
- // uses the same config change type 'ConfChangeAddNode'.
- IsPromote bool `json:"isPromote"`
-}
-
-// 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, token)
- for name, urls := range urlsmap {
- m := NewMember(name, urls, token, nil)
- if _, ok := c.members[m.ID]; ok {
- return nil, fmt.Errorf("member exists with identical ID %v", m)
- }
- if uint64(m.ID) == raft.None {
- return nil, fmt.Errorf("cannot use %x as member id", raft.None)
- }
- c.members[m.ID] = m
- }
- c.genID()
- return c, nil
-}
-
-func NewClusterFromMembers(lg *zap.Logger, token string, id types.ID, membs []*Member) *RaftCluster {
- c := NewCluster(lg, token)
- c.cid = id
- for _, m := range membs {
- c.members[m.ID] = m
- }
- return c
-}
-
-func NewCluster(lg *zap.Logger, token string) *RaftCluster {
- return &RaftCluster{
- lg: lg,
- token: token,
- members: make(map[types.ID]*Member),
- removed: make(map[types.ID]bool),
- }
-}
-
-func (c *RaftCluster) ID() types.ID { return c.cid }
-
-func (c *RaftCluster) Members() []*Member {
- c.Lock()
- defer c.Unlock()
- var ms MembersByID
- for _, m := range c.members {
- ms = append(ms, m.Clone())
- }
- sort.Sort(ms)
- return []*Member(ms)
-}
-
-func (c *RaftCluster) Member(id types.ID) *Member {
- c.Lock()
- defer c.Unlock()
- return c.members[id].Clone()
-}
-
-func (c *RaftCluster) VotingMembers() []*Member {
- c.Lock()
- defer c.Unlock()
- var ms MembersByID
- for _, m := range c.members {
- if !m.IsLearner {
- ms = append(ms, m.Clone())
- }
- }
- sort.Sort(ms)
- return []*Member(ms)
-}
-
-// MemberByName returns a Member with the given name if exists.
-// If more than one member has the given name, it will panic.
-func (c *RaftCluster) MemberByName(name string) *Member {
- c.Lock()
- defer c.Unlock()
- var memb *Member
- for _, m := range c.members {
- if m.Name == name {
- if memb != nil {
- if c.lg != nil {
- c.lg.Panic("two member with same name found", zap.String("name", name))
- } else {
- plog.Panicf("two members with the given name %q exist", name)
- }
- }
- memb = m
- }
- }
- return memb.Clone()
-}
-
-func (c *RaftCluster) MemberIDs() []types.ID {
- c.Lock()
- defer c.Unlock()
- var ids []types.ID
- for _, m := range c.members {
- ids = append(ids, m.ID)
- }
- sort.Sort(types.IDSlice(ids))
- return ids
-}
-
-func (c *RaftCluster) IsIDRemoved(id types.ID) bool {
- c.Lock()
- defer c.Unlock()
- return c.removed[id]
-}
-
-// PeerURLs returns a list of all peer addresses.
-// The returned list is sorted in ascending lexicographical order.
-func (c *RaftCluster) PeerURLs() []string {
- c.Lock()
- defer c.Unlock()
- urls := make([]string, 0)
- for _, p := range c.members {
- urls = append(urls, p.PeerURLs...)
- }
- sort.Strings(urls)
- return urls
-}
-
-// ClientURLs returns a list of all client addresses.
-// The returned list is sorted in ascending lexicographical order.
-func (c *RaftCluster) ClientURLs() []string {
- c.Lock()
- defer c.Unlock()
- urls := make([]string, 0)
- for _, p := range c.members {
- urls = append(urls, p.ClientURLs...)
- }
- sort.Strings(urls)
- return urls
-}
-
-func (c *RaftCluster) String() string {
- c.Lock()
- defer c.Unlock()
- b := &bytes.Buffer{}
- fmt.Fprintf(b, "{ClusterID:%s ", c.cid)
- var ms []string
- for _, m := range c.members {
- ms = append(ms, fmt.Sprintf("%+v", m))
- }
- fmt.Fprintf(b, "Members:[%s] ", strings.Join(ms, " "))
- var ids []string
- for id := range c.removed {
- ids = append(ids, id.String())
- }
- fmt.Fprintf(b, "RemovedMemberIDs:[%s]}", strings.Join(ids, " "))
- return b.String()
-}
-
-func (c *RaftCluster) genID() {
- mIDs := c.MemberIDs()
- b := make([]byte, 8*len(mIDs))
- for i, id := range mIDs {
- binary.BigEndian.PutUint64(b[8*i:], uint64(id))
- }
- hash := sha1.Sum(b)
- c.cid = types.ID(binary.BigEndian.Uint64(hash[:8]))
-}
-
-func (c *RaftCluster) SetID(localID, cid types.ID) {
- c.localID = localID
- c.cid = cid
-}
-
-func (c *RaftCluster) SetStore(st v2store.Store) { c.v2store = st }
-
-func (c *RaftCluster) SetBackend(be backend.Backend) {
- c.be = be
- mustCreateBackendBuckets(c.be)
-}
-
-func (c *RaftCluster) Recover(onSet func(*zap.Logger, *semver.Version)) {
- c.Lock()
- defer c.Unlock()
-
- c.members, c.removed = membersFromStore(c.lg, c.v2store)
- c.version = clusterVersionFromStore(c.lg, c.v2store)
- mustDetectDowngrade(c.lg, c.version)
- onSet(c.lg, c.version)
-
- for _, m := range c.members {
- if c.lg != nil {
- c.lg.Info(
- "recovered/added member from store",
- zap.String("cluster-id", c.cid.String()),
- 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),
- )
- } else {
- plog.Infof("added member %s %v to cluster %s from store", m.ID, m.PeerURLs, c.cid)
- }
- }
- if c.version != nil {
- if c.lg != nil {
- c.lg.Info(
- "set cluster version from store",
- zap.String("cluster-version", version.Cluster(c.version.String())),
- )
- } else {
- plog.Infof("set the cluster version to %v from store", version.Cluster(c.version.String()))
- }
- }
-}
-
-// ValidateConfigurationChange takes a proposed ConfChange and
-// ensures that it is still valid.
-func (c *RaftCluster) ValidateConfigurationChange(cc raftpb.ConfChange) error {
- members, removed := membersFromStore(c.lg, c.v2store)
- id := types.ID(cc.NodeID)
- if removed[id] {
- return ErrIDRemoved
- }
- switch cc.Type {
- case raftpb.ConfChangeAddNode, raftpb.ConfChangeAddLearnerNode:
- confChangeContext := new(ConfigChangeContext)
- if err := json.Unmarshal(cc.Context, confChangeContext); err != nil {
- if c.lg != nil {
- c.lg.Panic("failed to unmarshal confChangeContext", zap.Error(err))
- } else {
- plog.Panicf("unmarshal confChangeContext should never fail: %v", err)
- }
- }
-
- if confChangeContext.IsPromote { // promoting a learner member to voting member
- if members[id] == nil {
- return ErrIDNotFound
- }
- if !members[id].IsLearner {
- return ErrMemberNotLearner
- }
- } else { // adding a new member
- if members[id] != nil {
- return ErrIDExists
- }
-
- urls := make(map[string]bool)
- for _, m := range members {
- for _, u := range m.PeerURLs {
- urls[u] = true
- }
- }
- for _, u := range confChangeContext.Member.PeerURLs {
- if urls[u] {
- return ErrPeerURLexists
- }
- }
-
- 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
- }
- }
- }
- case raftpb.ConfChangeRemoveNode:
- if members[id] == nil {
- return ErrIDNotFound
- }
-
- case raftpb.ConfChangeUpdateNode:
- if members[id] == nil {
- return ErrIDNotFound
- }
- urls := make(map[string]bool)
- for _, m := range members {
- if m.ID == id {
- continue
- }
- for _, u := range m.PeerURLs {
- urls[u] = true
- }
- }
- m := new(Member)
- if err := json.Unmarshal(cc.Context, m); err != nil {
- if c.lg != nil {
- c.lg.Panic("failed to unmarshal member", zap.Error(err))
- } else {
- plog.Panicf("unmarshal member should never fail: %v", err)
- }
- }
- for _, u := range m.PeerURLs {
- if urls[u] {
- return ErrPeerURLexists
- }
- }
-
- default:
- if c.lg != nil {
- c.lg.Panic("unknown ConfChange type", zap.String("type", cc.Type.String()))
- } else {
- plog.Panicf("ConfChange type should be either AddNode, RemoveNode or UpdateNode")
- }
- }
- return nil
-}
-
-// AddMember adds a new Member into the cluster, and saves the given member's
-// raftAttributes into the store. The given member should have empty attributes.
-// A Member with a matching id must not exist.
-func (c *RaftCluster) AddMember(m *Member) {
- c.Lock()
- defer c.Unlock()
- if c.v2store != nil {
- mustSaveMemberToStore(c.v2store, m)
- }
- if c.be != nil {
- mustSaveMemberToBackend(c.be, m)
- }
-
- c.members[m.ID] = m
-
- if c.lg != nil {
- c.lg.Info(
- "added member",
- zap.String("cluster-id", c.cid.String()),
- zap.String("local-member-id", c.localID.String()),
- zap.String("added-peer-id", m.ID.String()),
- zap.Strings("added-peer-peer-urls", m.PeerURLs),
- )
- } else {
- plog.Infof("added member %s %v to cluster %s", m.ID, m.PeerURLs, c.cid)
- }
-}
-
-// RemoveMember removes a member from the store.
-// The given id MUST exist, or the function panics.
-func (c *RaftCluster) RemoveMember(id types.ID) {
- c.Lock()
- defer c.Unlock()
- if c.v2store != nil {
- mustDeleteMemberFromStore(c.v2store, id)
- }
- if c.be != nil {
- mustDeleteMemberFromBackend(c.be, id)
- }
-
- m, ok := c.members[id]
- delete(c.members, id)
- c.removed[id] = true
-
- if c.lg != nil {
- if ok {
- c.lg.Info(
- "removed member",
- zap.String("cluster-id", c.cid.String()),
- zap.String("local-member-id", c.localID.String()),
- zap.String("removed-remote-peer-id", id.String()),
- zap.Strings("removed-remote-peer-urls", m.PeerURLs),
- )
- } else {
- c.lg.Warn(
- "skipped removing already removed member",
- zap.String("cluster-id", c.cid.String()),
- zap.String("local-member-id", c.localID.String()),
- zap.String("removed-remote-peer-id", id.String()),
- )
- }
- } else {
- plog.Infof("removed member %s from cluster %s", id, c.cid)
- }
-}
-
-func (c *RaftCluster) UpdateAttributes(id types.ID, attr Attributes) {
- c.Lock()
- defer c.Unlock()
-
- if m, ok := c.members[id]; ok {
- m.Attributes = attr
- if c.v2store != nil {
- mustUpdateMemberAttrInStore(c.v2store, m)
- }
- if c.be != nil {
- mustSaveMemberToBackend(c.be, m)
- }
- return
- }
-
- _, ok := c.removed[id]
- if !ok {
- if c.lg != nil {
- c.lg.Panic(
- "failed to update; member unknown",
- zap.String("cluster-id", c.cid.String()),
- zap.String("local-member-id", c.localID.String()),
- zap.String("unknown-remote-peer-id", id.String()),
- )
- } else {
- plog.Panicf("error updating attributes of unknown member %s", id)
- }
- }
-
- if c.lg != nil {
- c.lg.Warn(
- "skipped attributes update of removed member",
- zap.String("cluster-id", c.cid.String()),
- zap.String("local-member-id", c.localID.String()),
- zap.String("updated-peer-id", id.String()),
- )
- } else {
- plog.Warningf("skipped updating attributes of removed member %s", id)
- }
-}
-
-// PromoteMember marks the member's IsLearner RaftAttributes to false.
-func (c *RaftCluster) PromoteMember(id types.ID) {
- c.Lock()
- defer c.Unlock()
-
- c.members[id].RaftAttributes.IsLearner = false
- if c.v2store != nil {
- mustUpdateMemberInStore(c.v2store, c.members[id])
- }
- if c.be != nil {
- mustSaveMemberToBackend(c.be, c.members[id])
- }
-
- if c.lg != nil {
- c.lg.Info(
- "promote member",
- zap.String("cluster-id", c.cid.String()),
- zap.String("local-member-id", c.localID.String()),
- )
- } else {
- plog.Noticef("promote member %s in cluster %s", id, c.cid)
- }
-}
-
-func (c *RaftCluster) UpdateRaftAttributes(id types.ID, raftAttr RaftAttributes) {
- c.Lock()
- defer c.Unlock()
-
- c.members[id].RaftAttributes = raftAttr
- if c.v2store != nil {
- mustUpdateMemberInStore(c.v2store, c.members[id])
- }
- if c.be != nil {
- mustSaveMemberToBackend(c.be, c.members[id])
- }
-
- if c.lg != nil {
- c.lg.Info(
- "updated member",
- zap.String("cluster-id", c.cid.String()),
- zap.String("local-member-id", c.localID.String()),
- zap.String("updated-remote-peer-id", id.String()),
- zap.Strings("updated-remote-peer-urls", raftAttr.PeerURLs),
- )
- } else {
- plog.Noticef("updated member %s %v in cluster %s", id, raftAttr.PeerURLs, c.cid)
- }
-}
-
-func (c *RaftCluster) Version() *semver.Version {
- c.Lock()
- defer c.Unlock()
- if c.version == nil {
- return nil
- }
- return semver.Must(semver.NewVersion(c.version.String()))
-}
-
-func (c *RaftCluster) SetVersion(ver *semver.Version, onSet func(*zap.Logger, *semver.Version)) {
- c.Lock()
- defer c.Unlock()
- if c.version != nil {
- if c.lg != nil {
- c.lg.Info(
- "updated cluster version",
- zap.String("cluster-id", c.cid.String()),
- zap.String("local-member-id", c.localID.String()),
- zap.String("from", version.Cluster(c.version.String())),
- zap.String("from", version.Cluster(ver.String())),
- )
- } else {
- plog.Noticef("updated the cluster version from %v to %v", version.Cluster(c.version.String()), version.Cluster(ver.String()))
- }
- } else {
- if c.lg != nil {
- c.lg.Info(
- "set initial cluster version",
- zap.String("cluster-id", c.cid.String()),
- zap.String("local-member-id", c.localID.String()),
- zap.String("cluster-version", version.Cluster(ver.String())),
- )
- } else {
- plog.Noticef("set the initial cluster version to %v", version.Cluster(ver.String()))
- }
- }
- c.version = ver
- mustDetectDowngrade(c.lg, c.version)
- if c.v2store != nil {
- mustSaveClusterVersionToStore(c.v2store, ver)
- }
- if c.be != nil {
- mustSaveClusterVersionToBackend(c.be, ver)
- }
- ClusterVersionMetrics.With(prometheus.Labels{"cluster_version": ver.String()}).Set(1)
- onSet(c.lg, ver)
-}
-
-func (c *RaftCluster) IsReadyToAddVotingMember() bool {
- nmembers := 1
- nstarted := 0
-
- for _, member := range c.VotingMembers() {
- if member.IsStarted() {
- nstarted++
- }
- nmembers++
- }
-
- if nstarted == 1 && nmembers == 2 {
- // a case of adding a new node to 1-member cluster for restoring cluster data
- // https://github.com/etcd-io/etcd/blob/master/Documentation/v2/admin_guide.md#restoring-the-cluster
- if c.lg != nil {
- c.lg.Debug("number of started member is 1; can accept add member request")
- } else {
- plog.Debugf("The number of started member is 1. This cluster can accept add member request.")
- }
- return true
- }
-
- nquorum := nmembers/2 + 1
- if nstarted < nquorum {
- if c.lg != nil {
- c.lg.Warn(
- "rejecting member add; started member will be less than quorum",
- zap.Int("number-of-started-member", nstarted),
- zap.Int("quorum", nquorum),
- zap.String("cluster-id", c.cid.String()),
- zap.String("local-member-id", c.localID.String()),
- )
- } else {
- plog.Warningf("Reject add member request: the number of started member (%d) will be less than the quorum number of the cluster (%d)", nstarted, nquorum)
- }
- return false
- }
-
- return true
-}
-
-func (c *RaftCluster) IsReadyToRemoveVotingMember(id uint64) bool {
- nmembers := 0
- nstarted := 0
-
- for _, member := range c.VotingMembers() {
- if uint64(member.ID) == id {
- continue
- }
-
- if member.IsStarted() {
- nstarted++
- }
- nmembers++
- }
-
- nquorum := nmembers/2 + 1
- if nstarted < nquorum {
- if c.lg != nil {
- c.lg.Warn(
- "rejecting member remove; started member will be less than quorum",
- zap.Int("number-of-started-member", nstarted),
- zap.Int("quorum", nquorum),
- zap.String("cluster-id", c.cid.String()),
- zap.String("local-member-id", c.localID.String()),
- )
- } else {
- plog.Warningf("Reject remove member request: the number of started member (%d) will be less than the quorum number of the cluster (%d)", nstarted, nquorum)
- }
- return false
- }
-
- return true
-}
-
-func (c *RaftCluster) IsReadyToPromoteMember(id uint64) bool {
- nmembers := 1
- nstarted := 0
-
- for _, member := range c.VotingMembers() {
- if member.IsStarted() {
- nstarted++
- }
- nmembers++
- }
-
- nquorum := nmembers/2 + 1
- if nstarted < nquorum {
- if c.lg != nil {
- c.lg.Warn(
- "rejecting member promote; started member will be less than quorum",
- zap.Int("number-of-started-member", nstarted),
- zap.Int("quorum", nquorum),
- zap.String("cluster-id", c.cid.String()),
- zap.String("local-member-id", c.localID.String()),
- )
- } else {
- plog.Warningf("Reject promote member request: the number of started member (%d) will be less than the quorum number of the cluster (%d)", nstarted, nquorum)
- }
- return false
- }
-
- return true
-}
-
-func membersFromStore(lg *zap.Logger, st v2store.Store) (map[types.ID]*Member, map[types.ID]bool) {
- members := make(map[types.ID]*Member)
- removed := make(map[types.ID]bool)
- e, err := st.Get(StoreMembersPrefix, true, true)
- if err != nil {
- if isKeyNotFound(err) {
- return members, removed
- }
- if lg != nil {
- lg.Panic("failed to get members from store", zap.String("path", StoreMembersPrefix), zap.Error(err))
- } else {
- plog.Panicf("get storeMembers should never fail: %v", err)
- }
- }
- for _, n := range e.Node.Nodes {
- var m *Member
- m, err = nodeToMember(n)
- if err != nil {
- if lg != nil {
- lg.Panic("failed to nodeToMember", zap.Error(err))
- } else {
- plog.Panicf("nodeToMember should never fail: %v", err)
- }
- }
- members[m.ID] = m
- }
-
- e, err = st.Get(storeRemovedMembersPrefix, true, true)
- if err != nil {
- if isKeyNotFound(err) {
- return members, removed
- }
- if lg != nil {
- lg.Panic(
- "failed to get removed members from store",
- zap.String("path", storeRemovedMembersPrefix),
- zap.Error(err),
- )
- } else {
- plog.Panicf("get storeRemovedMembers should never fail: %v", err)
- }
- }
- for _, n := range e.Node.Nodes {
- removed[MustParseMemberIDFromKey(n.Key)] = true
- }
- return members, removed
-}
-
-func clusterVersionFromStore(lg *zap.Logger, st v2store.Store) *semver.Version {
- e, err := st.Get(path.Join(storePrefix, "version"), false, false)
- if err != nil {
- if isKeyNotFound(err) {
- return nil
- }
- if lg != nil {
- lg.Panic(
- "failed to get cluster version from store",
- zap.String("path", path.Join(storePrefix, "version")),
- zap.Error(err),
- )
- } else {
- plog.Panicf("unexpected error (%v) when getting cluster version from store", err)
- }
- }
- return semver.Must(semver.NewVersion(*e.Node.Value))
-}
-
-// ValidateClusterAndAssignIDs validates the local cluster by matching the PeerURLs
-// with the existing cluster. If the validation succeeds, it assigns the IDs
-// from the existing cluster to the local cluster.
-// If the validation fails, an error will be returned.
-func ValidateClusterAndAssignIDs(lg *zap.Logger, local *RaftCluster, existing *RaftCluster) error {
- ems := existing.Members()
- lms := local.Members()
- if len(ems) != len(lms) {
- return fmt.Errorf("member count is unequal")
- }
-
- ctx, cancel := context.WithTimeout(context.TODO(), 30*time.Second)
- defer cancel()
- for i := range ems {
- var err error
- ok := false
- for j := range lms {
- if ok, err = netutil.URLStringsEqual(ctx, lg, ems[i].PeerURLs, lms[j].PeerURLs); ok {
- lms[j].ID = ems[i].ID
- break
- }
- }
- if !ok {
- return fmt.Errorf("PeerURLs: no match found for existing member (%v, %v), last resolver error (%v)", ems[i].ID, ems[i].PeerURLs, err)
- }
- }
- local.members = make(map[types.ID]*Member)
- for _, m := range lms {
- local.members[m.ID] = m
- }
- return nil
-}
-
-func mustDetectDowngrade(lg *zap.Logger, cv *semver.Version) {
- lv := semver.Must(semver.NewVersion(version.Version))
- // only keep major.minor version for comparison against cluster version
- lv = &semver.Version{Major: lv.Major, Minor: lv.Minor}
- if cv != nil && lv.LessThan(*cv) {
- if lg != nil {
- lg.Fatal(
- "invalid downgrade; server version is lower than determined cluster version",
- zap.String("current-server-version", version.Version),
- zap.String("determined-cluster-version", version.Cluster(cv.String())),
- )
- } else {
- plog.Fatalf("cluster cannot be downgraded (current version: %s is lower than determined cluster version: %s).", version.Version, version.Cluster(cv.String()))
- }
- }
-}
-
-// IsLocalMemberLearner returns if the local member is raft learner
-func (c *RaftCluster) IsLocalMemberLearner() bool {
- c.Lock()
- defer c.Unlock()
- localMember, ok := c.members[c.localID]
- if !ok {
- if c.lg != nil {
- c.lg.Panic(
- "failed to find local ID in cluster members",
- zap.String("cluster-id", c.cid.String()),
- zap.String("local-member-id", c.localID.String()),
- )
- } else {
- plog.Panicf("failed to find local ID %s in cluster %s", c.localID.String(), c.cid.String())
- }
- }
- return localMember.IsLearner
-}
-
-// IsMemberExist returns if the member with the given id exists in cluster.
-func (c *RaftCluster) IsMemberExist(id types.ID) bool {
- c.Lock()
- defer c.Unlock()
- _, ok := c.members[id]
- return ok
-}
-
-// VotingMemberIDs returns the ID of voting members in cluster.
-func (c *RaftCluster) VotingMemberIDs() []types.ID {
- c.Lock()
- defer c.Unlock()
- var ids []types.ID
- for _, m := range c.members {
- if !m.IsLearner {
- ids = append(ids, m.ID)
- }
- }
- sort.Sort(types.IDSlice(ids))
- return ids
-}
diff --git a/vendor/go.etcd.io/etcd/etcdserver/api/membership/doc.go b/vendor/go.etcd.io/etcd/etcdserver/api/membership/doc.go
deleted file mode 100644
index b07fb2d..0000000
--- a/vendor/go.etcd.io/etcd/etcdserver/api/membership/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 membership describes individual etcd members and clusters of members.
-package membership
diff --git a/vendor/go.etcd.io/etcd/etcdserver/api/membership/errors.go b/vendor/go.etcd.io/etcd/etcdserver/api/membership/errors.go
deleted file mode 100644
index 8f6fe50..0000000
--- a/vendor/go.etcd.io/etcd/etcdserver/api/membership/errors.go
+++ /dev/null
@@ -1,35 +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 membership
-
-import (
- "errors"
-
- "go.etcd.io/etcd/etcdserver/api/v2error"
-)
-
-var (
- ErrIDRemoved = errors.New("membership: ID removed")
- ErrIDExists = errors.New("membership: ID exists")
- ErrIDNotFound = errors.New("membership: ID not found")
- ErrPeerURLexists = errors.New("membership: peerURL exists")
- ErrMemberNotLearner = errors.New("membership: can only promote a learner member")
- ErrTooManyLearners = errors.New("membership: too many learner members in cluster")
-)
-
-func isKeyNotFound(err error) bool {
- e, ok := err.(*v2error.Error)
- return ok && e.ErrorCode == v2error.EcodeKeyNotFound
-}
diff --git a/vendor/go.etcd.io/etcd/etcdserver/api/membership/member.go b/vendor/go.etcd.io/etcd/etcdserver/api/membership/member.go
deleted file mode 100644
index 896cb36..0000000
--- a/vendor/go.etcd.io/etcd/etcdserver/api/membership/member.go
+++ /dev/null
@@ -1,142 +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 membership
-
-import (
- "crypto/sha1"
- "encoding/binary"
- "fmt"
- "math/rand"
- "sort"
- "time"
-
- "github.com/coreos/pkg/capnslog"
- "go.etcd.io/etcd/pkg/types"
-)
-
-var (
- plog = capnslog.NewPackageLogger("go.etcd.io/etcd/v3", "etcdserver/membership")
-)
-
-// RaftAttributes represents the raft related attributes of an etcd member.
-type RaftAttributes struct {
- // PeerURLs is the list of peers in the raft cluster.
- // TODO(philips): ensure these are URLs
- PeerURLs []string `json:"peerURLs"`
- // IsLearner indicates if the member is raft learner.
- IsLearner bool `json:"isLearner,omitempty"`
-}
-
-// Attributes represents all the non-raft related attributes of an etcd member.
-type Attributes struct {
- Name string `json:"name,omitempty"`
- ClientURLs []string `json:"clientURLs,omitempty"`
-}
-
-type Member struct {
- ID types.ID `json:"id"`
- RaftAttributes
- Attributes
-}
-
-// NewMember creates a Member without an ID and generates one based on the
-// cluster name, peer URLs, and time. This is used for bootstrapping/adding new member.
-func NewMember(name string, peerURLs types.URLs, clusterName string, now *time.Time) *Member {
- return newMember(name, peerURLs, clusterName, now, false)
-}
-
-// NewMemberAsLearner creates a learner Member without an ID and generates one based on the
-// cluster name, peer URLs, and time. This is used for adding new learner member.
-func NewMemberAsLearner(name string, peerURLs types.URLs, clusterName string, now *time.Time) *Member {
- return newMember(name, peerURLs, clusterName, now, true)
-}
-
-func newMember(name string, peerURLs types.URLs, clusterName string, now *time.Time, isLearner bool) *Member {
- m := &Member{
- RaftAttributes: RaftAttributes{
- PeerURLs: peerURLs.StringSlice(),
- IsLearner: isLearner,
- },
- Attributes: Attributes{Name: name},
- }
-
- var b []byte
- sort.Strings(m.PeerURLs)
- for _, p := range m.PeerURLs {
- b = append(b, []byte(p)...)
- }
-
- b = append(b, []byte(clusterName)...)
- if now != nil {
- b = append(b, []byte(fmt.Sprintf("%d", now.Unix()))...)
- }
-
- hash := sha1.Sum(b)
- m.ID = types.ID(binary.BigEndian.Uint64(hash[:8]))
- return m
-}
-
-// PickPeerURL chooses a random address from a given Member's PeerURLs.
-// It will panic if there is no PeerURLs available in Member.
-func (m *Member) PickPeerURL() string {
- if len(m.PeerURLs) == 0 {
- panic("member should always have some peer url")
- }
- return m.PeerURLs[rand.Intn(len(m.PeerURLs))]
-}
-
-func (m *Member) Clone() *Member {
- if m == nil {
- return nil
- }
- mm := &Member{
- ID: m.ID,
- RaftAttributes: RaftAttributes{
- IsLearner: m.IsLearner,
- },
- Attributes: Attributes{
- Name: m.Name,
- },
- }
- if m.PeerURLs != nil {
- mm.PeerURLs = make([]string, len(m.PeerURLs))
- copy(mm.PeerURLs, m.PeerURLs)
- }
- if m.ClientURLs != nil {
- mm.ClientURLs = make([]string, len(m.ClientURLs))
- copy(mm.ClientURLs, m.ClientURLs)
- }
- return mm
-}
-
-func (m *Member) IsStarted() bool {
- return len(m.Name) != 0
-}
-
-// MembersByID implements sort by ID interface
-type MembersByID []*Member
-
-func (ms MembersByID) Len() int { return len(ms) }
-func (ms MembersByID) Less(i, j int) bool { return ms[i].ID < ms[j].ID }
-func (ms MembersByID) Swap(i, j int) { ms[i], ms[j] = ms[j], ms[i] }
-
-// MembersByPeerURLs implements sort by peer urls interface
-type MembersByPeerURLs []*Member
-
-func (ms MembersByPeerURLs) Len() int { return len(ms) }
-func (ms MembersByPeerURLs) Less(i, j int) bool {
- return ms[i].PeerURLs[0] < ms[j].PeerURLs[0]
-}
-func (ms MembersByPeerURLs) Swap(i, j int) { ms[i], ms[j] = ms[j], ms[i] }
diff --git a/vendor/go.etcd.io/etcd/etcdserver/api/membership/metrics.go b/vendor/go.etcd.io/etcd/etcdserver/api/membership/metrics.go
deleted file mode 100644
index b3212bc..0000000
--- a/vendor/go.etcd.io/etcd/etcdserver/api/membership/metrics.go
+++ /dev/null
@@ -1,31 +0,0 @@
-// Copyright 2018 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
-
-import "github.com/prometheus/client_golang/prometheus"
-
-var (
- ClusterVersionMetrics = prometheus.NewGaugeVec(prometheus.GaugeOpts{
- Namespace: "etcd",
- Subsystem: "cluster",
- Name: "version",
- Help: "Which version is running. 1 for 'cluster_version' label with current cluster version",
- },
- []string{"cluster_version"})
-)
-
-func init() {
- prometheus.MustRegister(ClusterVersionMetrics)
-}
diff --git a/vendor/go.etcd.io/etcd/etcdserver/api/membership/store.go b/vendor/go.etcd.io/etcd/etcdserver/api/membership/store.go
deleted file mode 100644
index 14ab119..0000000
--- a/vendor/go.etcd.io/etcd/etcdserver/api/membership/store.go
+++ /dev/null
@@ -1,193 +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 membership
-
-import (
- "encoding/json"
- "fmt"
- "path"
-
- "go.etcd.io/etcd/etcdserver/api/v2store"
- "go.etcd.io/etcd/mvcc/backend"
- "go.etcd.io/etcd/pkg/types"
-
- "github.com/coreos/go-semver/semver"
-)
-
-const (
- attributesSuffix = "attributes"
- raftAttributesSuffix = "raftAttributes"
-
- // the prefix for stroing membership related information in store provided by store pkg.
- storePrefix = "/0"
-)
-
-var (
- membersBucketName = []byte("members")
- membersRemovedBucketName = []byte("members_removed")
- clusterBucketName = []byte("cluster")
-
- StoreMembersPrefix = path.Join(storePrefix, "members")
- storeRemovedMembersPrefix = path.Join(storePrefix, "removed_members")
-)
-
-func mustSaveMemberToBackend(be backend.Backend, m *Member) {
- mkey := backendMemberKey(m.ID)
- mvalue, err := json.Marshal(m)
- if err != nil {
- plog.Panicf("marshal raftAttributes should never fail: %v", err)
- }
-
- tx := be.BatchTx()
- tx.Lock()
- tx.UnsafePut(membersBucketName, mkey, mvalue)
- tx.Unlock()
-}
-
-func mustDeleteMemberFromBackend(be backend.Backend, id types.ID) {
- mkey := backendMemberKey(id)
-
- tx := be.BatchTx()
- tx.Lock()
- tx.UnsafeDelete(membersBucketName, mkey)
- tx.UnsafePut(membersRemovedBucketName, mkey, []byte("removed"))
- tx.Unlock()
-}
-
-func mustSaveClusterVersionToBackend(be backend.Backend, ver *semver.Version) {
- ckey := backendClusterVersionKey()
-
- tx := be.BatchTx()
- tx.Lock()
- defer tx.Unlock()
- tx.UnsafePut(clusterBucketName, ckey, []byte(ver.String()))
-}
-
-func mustSaveMemberToStore(s v2store.Store, m *Member) {
- b, err := json.Marshal(m.RaftAttributes)
- if err != nil {
- plog.Panicf("marshal raftAttributes should never fail: %v", err)
- }
- p := path.Join(MemberStoreKey(m.ID), raftAttributesSuffix)
- if _, err := s.Create(p, false, string(b), false, v2store.TTLOptionSet{ExpireTime: v2store.Permanent}); err != nil {
- plog.Panicf("create raftAttributes should never fail: %v", err)
- }
-}
-
-func mustDeleteMemberFromStore(s v2store.Store, id types.ID) {
- if _, err := s.Delete(MemberStoreKey(id), true, true); err != nil {
- plog.Panicf("delete member should never fail: %v", err)
- }
- if _, err := s.Create(RemovedMemberStoreKey(id), false, "", false, v2store.TTLOptionSet{ExpireTime: v2store.Permanent}); err != nil {
- plog.Panicf("create removedMember should never fail: %v", err)
- }
-}
-
-func mustUpdateMemberInStore(s v2store.Store, m *Member) {
- b, err := json.Marshal(m.RaftAttributes)
- if err != nil {
- plog.Panicf("marshal raftAttributes should never fail: %v", err)
- }
- p := path.Join(MemberStoreKey(m.ID), raftAttributesSuffix)
- if _, err := s.Update(p, string(b), v2store.TTLOptionSet{ExpireTime: v2store.Permanent}); err != nil {
- plog.Panicf("update raftAttributes should never fail: %v", err)
- }
-}
-
-func mustUpdateMemberAttrInStore(s v2store.Store, m *Member) {
- b, err := json.Marshal(m.Attributes)
- if err != nil {
- plog.Panicf("marshal raftAttributes should never fail: %v", err)
- }
- p := path.Join(MemberStoreKey(m.ID), attributesSuffix)
- if _, err := s.Set(p, false, string(b), v2store.TTLOptionSet{ExpireTime: v2store.Permanent}); err != nil {
- plog.Panicf("update raftAttributes should never fail: %v", err)
- }
-}
-
-func mustSaveClusterVersionToStore(s v2store.Store, ver *semver.Version) {
- if _, err := s.Set(StoreClusterVersionKey(), false, ver.String(), v2store.TTLOptionSet{ExpireTime: v2store.Permanent}); err != nil {
- plog.Panicf("save cluster version should never fail: %v", err)
- }
-}
-
-// nodeToMember builds member from a key value node.
-// the child nodes of the given node MUST be sorted by key.
-func nodeToMember(n *v2store.NodeExtern) (*Member, error) {
- m := &Member{ID: MustParseMemberIDFromKey(n.Key)}
- attrs := make(map[string][]byte)
- raftAttrKey := path.Join(n.Key, raftAttributesSuffix)
- attrKey := path.Join(n.Key, attributesSuffix)
- for _, nn := range n.Nodes {
- if nn.Key != raftAttrKey && nn.Key != attrKey {
- return nil, fmt.Errorf("unknown key %q", nn.Key)
- }
- attrs[nn.Key] = []byte(*nn.Value)
- }
- if data := attrs[raftAttrKey]; data != nil {
- if err := json.Unmarshal(data, &m.RaftAttributes); err != nil {
- return nil, fmt.Errorf("unmarshal raftAttributes error: %v", err)
- }
- } else {
- return nil, fmt.Errorf("raftAttributes key doesn't exist")
- }
- if data := attrs[attrKey]; data != nil {
- if err := json.Unmarshal(data, &m.Attributes); err != nil {
- return m, fmt.Errorf("unmarshal attributes error: %v", err)
- }
- }
- return m, nil
-}
-
-func backendMemberKey(id types.ID) []byte {
- return []byte(id.String())
-}
-
-func backendClusterVersionKey() []byte {
- return []byte("clusterVersion")
-}
-
-func mustCreateBackendBuckets(be backend.Backend) {
- tx := be.BatchTx()
- tx.Lock()
- defer tx.Unlock()
- tx.UnsafeCreateBucket(membersBucketName)
- tx.UnsafeCreateBucket(membersRemovedBucketName)
- tx.UnsafeCreateBucket(clusterBucketName)
-}
-
-func MemberStoreKey(id types.ID) string {
- return path.Join(StoreMembersPrefix, id.String())
-}
-
-func StoreClusterVersionKey() string {
- return path.Join(storePrefix, "version")
-}
-
-func MemberAttributesStorePath(id types.ID) string {
- return path.Join(MemberStoreKey(id), attributesSuffix)
-}
-
-func MustParseMemberIDFromKey(key string) types.ID {
- id, err := types.IDFromString(path.Base(key))
- if err != nil {
- plog.Panicf("unexpected parse member id error: %v", err)
- }
- return id
-}
-
-func RemovedMemberStoreKey(id types.ID) string {
- return path.Join(storeRemovedMembersPrefix, id.String())
-}
diff --git a/vendor/go.etcd.io/etcd/etcdserver/api/rafthttp/coder.go b/vendor/go.etcd.io/etcd/etcdserver/api/rafthttp/coder.go
deleted file mode 100644
index 12c3e44..0000000
--- a/vendor/go.etcd.io/etcd/etcdserver/api/rafthttp/coder.go
+++ /dev/null
@@ -1,27 +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 rafthttp
-
-import "go.etcd.io/etcd/raft/raftpb"
-
-type encoder interface {
- // encode encodes the given message to an output stream.
- encode(m *raftpb.Message) error
-}
-
-type decoder interface {
- // decode decodes the message from an input stream.
- decode() (raftpb.Message, error)
-}
diff --git a/vendor/go.etcd.io/etcd/etcdserver/api/rafthttp/doc.go b/vendor/go.etcd.io/etcd/etcdserver/api/rafthttp/doc.go
deleted file mode 100644
index a9486a8..0000000
--- a/vendor/go.etcd.io/etcd/etcdserver/api/rafthttp/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 rafthttp implements HTTP transportation layer for etcd/raft pkg.
-package rafthttp
diff --git a/vendor/go.etcd.io/etcd/etcdserver/api/rafthttp/http.go b/vendor/go.etcd.io/etcd/etcdserver/api/rafthttp/http.go
deleted file mode 100644
index d0e0c81..0000000
--- a/vendor/go.etcd.io/etcd/etcdserver/api/rafthttp/http.go
+++ /dev/null
@@ -1,577 +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 rafthttp
-
-import (
- "context"
- "errors"
- "fmt"
- "io/ioutil"
- "net/http"
- "path"
- "strings"
- "time"
-
- "go.etcd.io/etcd/etcdserver/api/snap"
- pioutil "go.etcd.io/etcd/pkg/ioutil"
- "go.etcd.io/etcd/pkg/types"
- "go.etcd.io/etcd/raft/raftpb"
- "go.etcd.io/etcd/version"
-
- humanize "github.com/dustin/go-humanize"
- "go.uber.org/zap"
-)
-
-const (
- // connReadLimitByte limits the number of bytes
- // a single read can read out.
- //
- // 64KB should be large enough for not causing
- // throughput bottleneck as well as small enough
- // for not causing a read timeout.
- connReadLimitByte = 64 * 1024
-)
-
-var (
- RaftPrefix = "/raft"
- ProbingPrefix = path.Join(RaftPrefix, "probing")
- RaftStreamPrefix = path.Join(RaftPrefix, "stream")
- RaftSnapshotPrefix = path.Join(RaftPrefix, "snapshot")
-
- errIncompatibleVersion = errors.New("incompatible version")
- errClusterIDMismatch = errors.New("cluster ID mismatch")
-)
-
-type peerGetter interface {
- Get(id types.ID) Peer
-}
-
-type writerToResponse interface {
- WriteTo(w http.ResponseWriter)
-}
-
-type pipelineHandler struct {
- lg *zap.Logger
- localID types.ID
- tr Transporter
- r Raft
- cid types.ID
-}
-
-// newPipelineHandler returns a handler for handling raft messages
-// from pipeline for RaftPrefix.
-//
-// The handler reads out the raft message from request body,
-// and forwards it to the given raft state machine for processing.
-func newPipelineHandler(t *Transport, r Raft, cid types.ID) http.Handler {
- return &pipelineHandler{
- lg: t.Logger,
- localID: t.ID,
- tr: t,
- r: r,
- cid: cid,
- }
-}
-
-func (h *pipelineHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
- if r.Method != "POST" {
- w.Header().Set("Allow", "POST")
- http.Error(w, "Method Not Allowed", http.StatusMethodNotAllowed)
- return
- }
-
- w.Header().Set("X-Etcd-Cluster-ID", h.cid.String())
-
- if err := checkClusterCompatibilityFromHeader(h.lg, h.localID, r.Header, h.cid); err != nil {
- http.Error(w, err.Error(), http.StatusPreconditionFailed)
- return
- }
-
- addRemoteFromRequest(h.tr, r)
-
- // Limit the data size that could be read from the request body, which ensures that read from
- // connection will not time out accidentally due to possible blocking in underlying implementation.
- limitedr := pioutil.NewLimitedBufferReader(r.Body, connReadLimitByte)
- b, err := ioutil.ReadAll(limitedr)
- if err != nil {
- if h.lg != nil {
- h.lg.Warn(
- "failed to read Raft message",
- zap.String("local-member-id", h.localID.String()),
- zap.Error(err),
- )
- } else {
- plog.Errorf("failed to read raft message (%v)", err)
- }
- http.Error(w, "error reading raft message", http.StatusBadRequest)
- recvFailures.WithLabelValues(r.RemoteAddr).Inc()
- return
- }
-
- var m raftpb.Message
- if err := m.Unmarshal(b); err != nil {
- if h.lg != nil {
- h.lg.Warn(
- "failed to unmarshal Raft message",
- zap.String("local-member-id", h.localID.String()),
- zap.Error(err),
- )
- } else {
- plog.Errorf("failed to unmarshal raft message (%v)", err)
- }
- http.Error(w, "error unmarshalling raft message", http.StatusBadRequest)
- recvFailures.WithLabelValues(r.RemoteAddr).Inc()
- return
- }
-
- receivedBytes.WithLabelValues(types.ID(m.From).String()).Add(float64(len(b)))
-
- if err := h.r.Process(context.TODO(), m); err != nil {
- switch v := err.(type) {
- case writerToResponse:
- v.WriteTo(w)
- default:
- if h.lg != nil {
- h.lg.Warn(
- "failed to process Raft message",
- zap.String("local-member-id", h.localID.String()),
- zap.Error(err),
- )
- } else {
- plog.Warningf("failed to process raft message (%v)", err)
- }
- http.Error(w, "error processing raft message", http.StatusInternalServerError)
- w.(http.Flusher).Flush()
- // disconnect the http stream
- panic(err)
- }
- return
- }
-
- // Write StatusNoContent header after the message has been processed by
- // raft, which facilitates the client to report MsgSnap status.
- w.WriteHeader(http.StatusNoContent)
-}
-
-type snapshotHandler struct {
- lg *zap.Logger
- tr Transporter
- r Raft
- snapshotter *snap.Snapshotter
-
- localID types.ID
- cid types.ID
-}
-
-func newSnapshotHandler(t *Transport, r Raft, snapshotter *snap.Snapshotter, cid types.ID) http.Handler {
- return &snapshotHandler{
- lg: t.Logger,
- tr: t,
- r: r,
- snapshotter: snapshotter,
- localID: t.ID,
- cid: cid,
- }
-}
-
-const unknownSnapshotSender = "UNKNOWN_SNAPSHOT_SENDER"
-
-// ServeHTTP serves HTTP request to receive and process snapshot message.
-//
-// If request sender dies without closing underlying TCP connection,
-// the handler will keep waiting for the request body until TCP keepalive
-// finds out that the connection is broken after several minutes.
-// This is acceptable because
-// 1. snapshot messages sent through other TCP connections could still be
-// received and processed.
-// 2. this case should happen rarely, so no further optimization is done.
-func (h *snapshotHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
- start := time.Now()
-
- if r.Method != "POST" {
- w.Header().Set("Allow", "POST")
- http.Error(w, "Method Not Allowed", http.StatusMethodNotAllowed)
- snapshotReceiveFailures.WithLabelValues(unknownSnapshotSender).Inc()
- return
- }
-
- w.Header().Set("X-Etcd-Cluster-ID", h.cid.String())
-
- if err := checkClusterCompatibilityFromHeader(h.lg, h.localID, r.Header, h.cid); err != nil {
- http.Error(w, err.Error(), http.StatusPreconditionFailed)
- snapshotReceiveFailures.WithLabelValues(unknownSnapshotSender).Inc()
- return
- }
-
- addRemoteFromRequest(h.tr, r)
-
- dec := &messageDecoder{r: r.Body}
- // let snapshots be very large since they can exceed 512MB for large installations
- m, err := dec.decodeLimit(uint64(1 << 63))
- from := types.ID(m.From).String()
- if err != nil {
- msg := fmt.Sprintf("failed to decode raft message (%v)", err)
- if h.lg != nil {
- h.lg.Warn(
- "failed to decode Raft message",
- zap.String("local-member-id", h.localID.String()),
- zap.String("remote-snapshot-sender-id", from),
- zap.Error(err),
- )
- } else {
- plog.Error(msg)
- }
- http.Error(w, msg, http.StatusBadRequest)
- recvFailures.WithLabelValues(r.RemoteAddr).Inc()
- snapshotReceiveFailures.WithLabelValues(from).Inc()
- return
- }
-
- msgSize := m.Size()
- receivedBytes.WithLabelValues(from).Add(float64(msgSize))
-
- if m.Type != raftpb.MsgSnap {
- if h.lg != nil {
- h.lg.Warn(
- "unexpected Raft message type",
- zap.String("local-member-id", h.localID.String()),
- zap.String("remote-snapshot-sender-id", from),
- zap.String("message-type", m.Type.String()),
- )
- } else {
- plog.Errorf("unexpected raft message type %s on snapshot path", m.Type)
- }
- http.Error(w, "wrong raft message type", http.StatusBadRequest)
- snapshotReceiveFailures.WithLabelValues(from).Inc()
- return
- }
-
- snapshotReceiveInflights.WithLabelValues(from).Inc()
- defer func() {
- snapshotReceiveInflights.WithLabelValues(from).Dec()
- }()
-
- if h.lg != nil {
- h.lg.Info(
- "receiving database snapshot",
- zap.String("local-member-id", h.localID.String()),
- zap.String("remote-snapshot-sender-id", from),
- zap.Uint64("incoming-snapshot-index", m.Snapshot.Metadata.Index),
- zap.Int("incoming-snapshot-message-size-bytes", msgSize),
- zap.String("incoming-snapshot-message-size", humanize.Bytes(uint64(msgSize))),
- )
- } else {
- plog.Infof("receiving database snapshot [index:%d, from %s] ...", m.Snapshot.Metadata.Index, types.ID(m.From))
- }
-
- // save incoming database snapshot.
- n, err := h.snapshotter.SaveDBFrom(r.Body, m.Snapshot.Metadata.Index)
- if err != nil {
- msg := fmt.Sprintf("failed to save KV snapshot (%v)", err)
- if h.lg != nil {
- h.lg.Warn(
- "failed to save incoming database snapshot",
- zap.String("local-member-id", h.localID.String()),
- zap.String("remote-snapshot-sender-id", from),
- zap.Uint64("incoming-snapshot-index", m.Snapshot.Metadata.Index),
- zap.Error(err),
- )
- } else {
- plog.Error(msg)
- }
- http.Error(w, msg, http.StatusInternalServerError)
- snapshotReceiveFailures.WithLabelValues(from).Inc()
- return
- }
-
- receivedBytes.WithLabelValues(from).Add(float64(n))
-
- if h.lg != nil {
- h.lg.Info(
- "received and saved database snapshot",
- zap.String("local-member-id", h.localID.String()),
- zap.String("remote-snapshot-sender-id", from),
- zap.Uint64("incoming-snapshot-index", m.Snapshot.Metadata.Index),
- zap.Int64("incoming-snapshot-size-bytes", n),
- zap.String("incoming-snapshot-size", humanize.Bytes(uint64(n))),
- )
- } else {
- plog.Infof("received and saved database snapshot [index: %d, from: %s] successfully", m.Snapshot.Metadata.Index, types.ID(m.From))
- }
-
- if err := h.r.Process(context.TODO(), m); err != nil {
- switch v := err.(type) {
- // Process may return writerToResponse error when doing some
- // additional checks before calling raft.Node.Step.
- case writerToResponse:
- v.WriteTo(w)
- default:
- msg := fmt.Sprintf("failed to process raft message (%v)", err)
- if h.lg != nil {
- h.lg.Warn(
- "failed to process Raft message",
- zap.String("local-member-id", h.localID.String()),
- zap.String("remote-snapshot-sender-id", from),
- zap.Error(err),
- )
- } else {
- plog.Error(msg)
- }
- http.Error(w, msg, http.StatusInternalServerError)
- snapshotReceiveFailures.WithLabelValues(from).Inc()
- }
- return
- }
-
- // Write StatusNoContent header after the message has been processed by
- // raft, which facilitates the client to report MsgSnap status.
- w.WriteHeader(http.StatusNoContent)
-
- snapshotReceive.WithLabelValues(from).Inc()
- snapshotReceiveSeconds.WithLabelValues(from).Observe(time.Since(start).Seconds())
-}
-
-type streamHandler struct {
- lg *zap.Logger
- tr *Transport
- peerGetter peerGetter
- r Raft
- id types.ID
- cid types.ID
-}
-
-func newStreamHandler(t *Transport, pg peerGetter, r Raft, id, cid types.ID) http.Handler {
- return &streamHandler{
- lg: t.Logger,
- tr: t,
- peerGetter: pg,
- r: r,
- id: id,
- cid: cid,
- }
-}
-
-func (h *streamHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
- if r.Method != "GET" {
- w.Header().Set("Allow", "GET")
- http.Error(w, "Method Not Allowed", http.StatusMethodNotAllowed)
- return
- }
-
- w.Header().Set("X-Server-Version", version.Version)
- w.Header().Set("X-Etcd-Cluster-ID", h.cid.String())
-
- if err := checkClusterCompatibilityFromHeader(h.lg, h.tr.ID, r.Header, h.cid); err != nil {
- http.Error(w, err.Error(), http.StatusPreconditionFailed)
- return
- }
-
- var t streamType
- switch path.Dir(r.URL.Path) {
- case streamTypeMsgAppV2.endpoint():
- t = streamTypeMsgAppV2
- case streamTypeMessage.endpoint():
- t = streamTypeMessage
- default:
- if h.lg != nil {
- h.lg.Debug(
- "ignored unexpected streaming request path",
- zap.String("local-member-id", h.tr.ID.String()),
- zap.String("remote-peer-id-stream-handler", h.id.String()),
- zap.String("path", r.URL.Path),
- )
- } else {
- plog.Debugf("ignored unexpected streaming request path %s", r.URL.Path)
- }
- http.Error(w, "invalid path", http.StatusNotFound)
- return
- }
-
- fromStr := path.Base(r.URL.Path)
- from, err := types.IDFromString(fromStr)
- if err != nil {
- if h.lg != nil {
- h.lg.Warn(
- "failed to parse path into ID",
- zap.String("local-member-id", h.tr.ID.String()),
- zap.String("remote-peer-id-stream-handler", h.id.String()),
- zap.String("path", fromStr),
- zap.Error(err),
- )
- } else {
- plog.Errorf("failed to parse from %s into ID (%v)", fromStr, err)
- }
- http.Error(w, "invalid from", http.StatusNotFound)
- return
- }
- if h.r.IsIDRemoved(uint64(from)) {
- if h.lg != nil {
- h.lg.Warn(
- "rejected stream from remote peer because it was removed",
- zap.String("local-member-id", h.tr.ID.String()),
- zap.String("remote-peer-id-stream-handler", h.id.String()),
- zap.String("remote-peer-id-from", from.String()),
- )
- } else {
- plog.Warningf("rejected the stream from peer %s since it was removed", from)
- }
- http.Error(w, "removed member", http.StatusGone)
- return
- }
- p := h.peerGetter.Get(from)
- if p == nil {
- // This may happen in following cases:
- // 1. user starts a remote peer that belongs to a different cluster
- // with the same cluster ID.
- // 2. local etcd falls behind of the cluster, and cannot recognize
- // the members that joined after its current progress.
- if urls := r.Header.Get("X-PeerURLs"); urls != "" {
- h.tr.AddRemote(from, strings.Split(urls, ","))
- }
- if h.lg != nil {
- h.lg.Warn(
- "failed to find remote peer in cluster",
- zap.String("local-member-id", h.tr.ID.String()),
- zap.String("remote-peer-id-stream-handler", h.id.String()),
- zap.String("remote-peer-id-from", from.String()),
- zap.String("cluster-id", h.cid.String()),
- )
- } else {
- plog.Errorf("failed to find member %s in cluster %s", from, h.cid)
- }
- http.Error(w, "error sender not found", http.StatusNotFound)
- return
- }
-
- wto := h.id.String()
- if gto := r.Header.Get("X-Raft-To"); gto != wto {
- if h.lg != nil {
- h.lg.Warn(
- "ignored streaming request; ID mismatch",
- zap.String("local-member-id", h.tr.ID.String()),
- zap.String("remote-peer-id-stream-handler", h.id.String()),
- zap.String("remote-peer-id-header", gto),
- zap.String("remote-peer-id-from", from.String()),
- zap.String("cluster-id", h.cid.String()),
- )
- } else {
- plog.Errorf("streaming request ignored (ID mismatch got %s want %s)", gto, wto)
- }
- http.Error(w, "to field mismatch", http.StatusPreconditionFailed)
- return
- }
-
- w.WriteHeader(http.StatusOK)
- w.(http.Flusher).Flush()
-
- c := newCloseNotifier()
- conn := &outgoingConn{
- t: t,
- Writer: w,
- Flusher: w.(http.Flusher),
- Closer: c,
- localID: h.tr.ID,
- peerID: h.id,
- }
- p.attachOutgoingConn(conn)
- <-c.closeNotify()
-}
-
-// checkClusterCompatibilityFromHeader checks the cluster compatibility of
-// the local member from the given header.
-// It checks whether the version of local member is compatible with
-// the versions in the header, and whether the cluster ID of local member
-// matches the one in the header.
-func checkClusterCompatibilityFromHeader(lg *zap.Logger, localID types.ID, header http.Header, cid types.ID) error {
- remoteName := header.Get("X-Server-From")
-
- remoteServer := serverVersion(header)
- remoteVs := ""
- if remoteServer != nil {
- remoteVs = remoteServer.String()
- }
-
- remoteMinClusterVer := minClusterVersion(header)
- remoteMinClusterVs := ""
- if remoteMinClusterVer != nil {
- remoteMinClusterVs = remoteMinClusterVer.String()
- }
-
- localServer, localMinCluster, err := checkVersionCompatibility(remoteName, remoteServer, remoteMinClusterVer)
-
- localVs := ""
- if localServer != nil {
- localVs = localServer.String()
- }
- localMinClusterVs := ""
- if localMinCluster != nil {
- localMinClusterVs = localMinCluster.String()
- }
-
- if err != nil {
- if lg != nil {
- lg.Warn(
- "failed to check version compatibility",
- zap.String("local-member-id", localID.String()),
- zap.String("local-member-cluster-id", cid.String()),
- zap.String("local-member-server-version", localVs),
- zap.String("local-member-server-minimum-cluster-version", localMinClusterVs),
- zap.String("remote-peer-server-name", remoteName),
- zap.String("remote-peer-server-version", remoteVs),
- zap.String("remote-peer-server-minimum-cluster-version", remoteMinClusterVs),
- zap.Error(err),
- )
- } else {
- plog.Errorf("request version incompatibility (%v)", err)
- }
- return errIncompatibleVersion
- }
- if gcid := header.Get("X-Etcd-Cluster-ID"); gcid != cid.String() {
- if lg != nil {
- lg.Warn(
- "request cluster ID mismatch",
- zap.String("local-member-id", localID.String()),
- zap.String("local-member-cluster-id", cid.String()),
- zap.String("local-member-server-version", localVs),
- zap.String("local-member-server-minimum-cluster-version", localMinClusterVs),
- zap.String("remote-peer-server-name", remoteName),
- zap.String("remote-peer-server-version", remoteVs),
- zap.String("remote-peer-server-minimum-cluster-version", remoteMinClusterVs),
- zap.String("remote-peer-cluster-id", gcid),
- )
- } else {
- plog.Errorf("request cluster ID mismatch (got %s want %s)", gcid, cid)
- }
- return errClusterIDMismatch
- }
- return nil
-}
-
-type closeNotifier struct {
- done chan struct{}
-}
-
-func newCloseNotifier() *closeNotifier {
- return &closeNotifier{
- done: make(chan struct{}),
- }
-}
-
-func (n *closeNotifier) Close() error {
- close(n.done)
- return nil
-}
-
-func (n *closeNotifier) closeNotify() <-chan struct{} { return n.done }
diff --git a/vendor/go.etcd.io/etcd/etcdserver/api/rafthttp/metrics.go b/vendor/go.etcd.io/etcd/etcdserver/api/rafthttp/metrics.go
deleted file mode 100644
index 02fff84..0000000
--- a/vendor/go.etcd.io/etcd/etcdserver/api/rafthttp/metrics.go
+++ /dev/null
@@ -1,186 +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 rafthttp
-
-import "github.com/prometheus/client_golang/prometheus"
-
-var (
- activePeers = prometheus.NewGaugeVec(prometheus.GaugeOpts{
- Namespace: "etcd",
- Subsystem: "network",
- Name: "active_peers",
- Help: "The current number of active peer connections.",
- },
- []string{"Local", "Remote"},
- )
-
- disconnectedPeers = prometheus.NewCounterVec(prometheus.CounterOpts{
- Namespace: "etcd",
- Subsystem: "network",
- Name: "disconnected_peers_total",
- Help: "The total number of disconnected peers.",
- },
- []string{"Local", "Remote"},
- )
-
- sentBytes = prometheus.NewCounterVec(prometheus.CounterOpts{
- Namespace: "etcd",
- Subsystem: "network",
- Name: "peer_sent_bytes_total",
- Help: "The total number of bytes sent to peers.",
- },
- []string{"To"},
- )
-
- receivedBytes = prometheus.NewCounterVec(prometheus.CounterOpts{
- Namespace: "etcd",
- Subsystem: "network",
- Name: "peer_received_bytes_total",
- Help: "The total number of bytes received from peers.",
- },
- []string{"From"},
- )
-
- sentFailures = prometheus.NewCounterVec(prometheus.CounterOpts{
- Namespace: "etcd",
- Subsystem: "network",
- Name: "peer_sent_failures_total",
- Help: "The total number of send failures from peers.",
- },
- []string{"To"},
- )
-
- recvFailures = prometheus.NewCounterVec(prometheus.CounterOpts{
- Namespace: "etcd",
- Subsystem: "network",
- Name: "peer_received_failures_total",
- Help: "The total number of receive failures from peers.",
- },
- []string{"From"},
- )
-
- snapshotSend = prometheus.NewCounterVec(prometheus.CounterOpts{
- Namespace: "etcd",
- Subsystem: "network",
- Name: "snapshot_send_success",
- Help: "Total number of successful snapshot sends",
- },
- []string{"To"},
- )
-
- snapshotSendInflights = prometheus.NewGaugeVec(prometheus.GaugeOpts{
- Namespace: "etcd",
- Subsystem: "network",
- Name: "snapshot_send_inflights_total",
- Help: "Total number of inflight snapshot sends",
- },
- []string{"To"},
- )
-
- snapshotSendFailures = prometheus.NewCounterVec(prometheus.CounterOpts{
- Namespace: "etcd",
- Subsystem: "network",
- Name: "snapshot_send_failures",
- Help: "Total number of snapshot send failures",
- },
- []string{"To"},
- )
-
- snapshotSendSeconds = prometheus.NewHistogramVec(prometheus.HistogramOpts{
- Namespace: "etcd",
- Subsystem: "network",
- Name: "snapshot_send_total_duration_seconds",
- Help: "Total latency distributions of v3 snapshot sends",
-
- // lowest bucket start of upper bound 0.1 sec (100 ms) with factor 2
- // highest bucket start of 0.1 sec * 2^9 == 51.2 sec
- Buckets: prometheus.ExponentialBuckets(0.1, 2, 10),
- },
- []string{"To"},
- )
-
- snapshotReceive = prometheus.NewCounterVec(prometheus.CounterOpts{
- Namespace: "etcd",
- Subsystem: "network",
- Name: "snapshot_receive_success",
- Help: "Total number of successful snapshot receives",
- },
- []string{"From"},
- )
-
- snapshotReceiveInflights = prometheus.NewGaugeVec(prometheus.GaugeOpts{
- Namespace: "etcd",
- Subsystem: "network",
- Name: "snapshot_receive_inflights_total",
- Help: "Total number of inflight snapshot receives",
- },
- []string{"From"},
- )
-
- snapshotReceiveFailures = prometheus.NewCounterVec(prometheus.CounterOpts{
- Namespace: "etcd",
- Subsystem: "network",
- Name: "snapshot_receive_failures",
- Help: "Total number of snapshot receive failures",
- },
- []string{"From"},
- )
-
- snapshotReceiveSeconds = prometheus.NewHistogramVec(prometheus.HistogramOpts{
- Namespace: "etcd",
- Subsystem: "network",
- Name: "snapshot_receive_total_duration_seconds",
- Help: "Total latency distributions of v3 snapshot receives",
-
- // lowest bucket start of upper bound 0.1 sec (100 ms) with factor 2
- // highest bucket start of 0.1 sec * 2^9 == 51.2 sec
- Buckets: prometheus.ExponentialBuckets(0.1, 2, 10),
- },
- []string{"From"},
- )
-
- rttSec = prometheus.NewHistogramVec(prometheus.HistogramOpts{
- Namespace: "etcd",
- Subsystem: "network",
- Name: "peer_round_trip_time_seconds",
- Help: "Round-Trip-Time histogram between peers",
-
- // lowest bucket start of upper bound 0.0001 sec (0.1 ms) with factor 2
- // highest bucket start of 0.0001 sec * 2^15 == 3.2768 sec
- Buckets: prometheus.ExponentialBuckets(0.0001, 2, 16),
- },
- []string{"To"},
- )
-)
-
-func init() {
- prometheus.MustRegister(activePeers)
- prometheus.MustRegister(disconnectedPeers)
- prometheus.MustRegister(sentBytes)
- prometheus.MustRegister(receivedBytes)
- prometheus.MustRegister(sentFailures)
- prometheus.MustRegister(recvFailures)
-
- prometheus.MustRegister(snapshotSend)
- prometheus.MustRegister(snapshotSendInflights)
- prometheus.MustRegister(snapshotSendFailures)
- prometheus.MustRegister(snapshotSendSeconds)
- prometheus.MustRegister(snapshotReceive)
- prometheus.MustRegister(snapshotReceiveInflights)
- prometheus.MustRegister(snapshotReceiveFailures)
- prometheus.MustRegister(snapshotReceiveSeconds)
-
- prometheus.MustRegister(rttSec)
-}
diff --git a/vendor/go.etcd.io/etcd/etcdserver/api/rafthttp/msg_codec.go b/vendor/go.etcd.io/etcd/etcdserver/api/rafthttp/msg_codec.go
deleted file mode 100644
index 2417d22..0000000
--- a/vendor/go.etcd.io/etcd/etcdserver/api/rafthttp/msg_codec.go
+++ /dev/null
@@ -1,68 +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 rafthttp
-
-import (
- "encoding/binary"
- "errors"
- "io"
-
- "go.etcd.io/etcd/pkg/pbutil"
- "go.etcd.io/etcd/raft/raftpb"
-)
-
-// messageEncoder is a encoder that can encode all kinds of messages.
-// It MUST be used with a paired messageDecoder.
-type messageEncoder struct {
- w io.Writer
-}
-
-func (enc *messageEncoder) encode(m *raftpb.Message) error {
- if err := binary.Write(enc.w, binary.BigEndian, uint64(m.Size())); err != nil {
- return err
- }
- _, err := enc.w.Write(pbutil.MustMarshal(m))
- return err
-}
-
-// messageDecoder is a decoder that can decode all kinds of messages.
-type messageDecoder struct {
- r io.Reader
-}
-
-var (
- readBytesLimit uint64 = 512 * 1024 * 1024 // 512 MB
- ErrExceedSizeLimit = errors.New("rafthttp: error limit exceeded")
-)
-
-func (dec *messageDecoder) decode() (raftpb.Message, error) {
- return dec.decodeLimit(readBytesLimit)
-}
-
-func (dec *messageDecoder) decodeLimit(numBytes uint64) (raftpb.Message, error) {
- var m raftpb.Message
- var l uint64
- if err := binary.Read(dec.r, binary.BigEndian, &l); err != nil {
- return m, err
- }
- if l > numBytes {
- return m, ErrExceedSizeLimit
- }
- buf := make([]byte, int(l))
- if _, err := io.ReadFull(dec.r, buf); err != nil {
- return m, err
- }
- return m, m.Unmarshal(buf)
-}
diff --git a/vendor/go.etcd.io/etcd/etcdserver/api/rafthttp/msgappv2_codec.go b/vendor/go.etcd.io/etcd/etcdserver/api/rafthttp/msgappv2_codec.go
deleted file mode 100644
index 1fa36de..0000000
--- a/vendor/go.etcd.io/etcd/etcdserver/api/rafthttp/msgappv2_codec.go
+++ /dev/null
@@ -1,248 +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 rafthttp
-
-import (
- "encoding/binary"
- "fmt"
- "io"
- "time"
-
- stats "go.etcd.io/etcd/etcdserver/api/v2stats"
- "go.etcd.io/etcd/pkg/pbutil"
- "go.etcd.io/etcd/pkg/types"
- "go.etcd.io/etcd/raft/raftpb"
-)
-
-const (
- msgTypeLinkHeartbeat uint8 = 0
- msgTypeAppEntries uint8 = 1
- msgTypeApp uint8 = 2
-
- msgAppV2BufSize = 1024 * 1024
-)
-
-// msgappv2 stream sends three types of message: linkHeartbeatMessage,
-// AppEntries and MsgApp. AppEntries is the MsgApp that is sent in
-// replicate state in raft, whose index and term are fully predictable.
-//
-// Data format of linkHeartbeatMessage:
-// | offset | bytes | description |
-// +--------+-------+-------------+
-// | 0 | 1 | \x00 |
-//
-// Data format of AppEntries:
-// | offset | bytes | description |
-// +--------+-------+-------------+
-// | 0 | 1 | \x01 |
-// | 1 | 8 | length of entries |
-// | 9 | 8 | length of first entry |
-// | 17 | n1 | first entry |
-// ...
-// | x | 8 | length of k-th entry data |
-// | x+8 | nk | k-th entry data |
-// | x+8+nk | 8 | commit index |
-//
-// Data format of MsgApp:
-// | offset | bytes | description |
-// +--------+-------+-------------+
-// | 0 | 1 | \x02 |
-// | 1 | 8 | length of encoded message |
-// | 9 | n | encoded message |
-type msgAppV2Encoder struct {
- w io.Writer
- fs *stats.FollowerStats
-
- term uint64
- index uint64
- buf []byte
- uint64buf []byte
- uint8buf []byte
-}
-
-func newMsgAppV2Encoder(w io.Writer, fs *stats.FollowerStats) *msgAppV2Encoder {
- return &msgAppV2Encoder{
- w: w,
- fs: fs,
- buf: make([]byte, msgAppV2BufSize),
- uint64buf: make([]byte, 8),
- uint8buf: make([]byte, 1),
- }
-}
-
-func (enc *msgAppV2Encoder) encode(m *raftpb.Message) error {
- start := time.Now()
- switch {
- case isLinkHeartbeatMessage(m):
- enc.uint8buf[0] = msgTypeLinkHeartbeat
- if _, err := enc.w.Write(enc.uint8buf); err != nil {
- return err
- }
- case enc.index == m.Index && enc.term == m.LogTerm && m.LogTerm == m.Term:
- enc.uint8buf[0] = msgTypeAppEntries
- if _, err := enc.w.Write(enc.uint8buf); err != nil {
- return err
- }
- // write length of entries
- binary.BigEndian.PutUint64(enc.uint64buf, uint64(len(m.Entries)))
- if _, err := enc.w.Write(enc.uint64buf); err != nil {
- return err
- }
- for i := 0; i < len(m.Entries); i++ {
- // write length of entry
- binary.BigEndian.PutUint64(enc.uint64buf, uint64(m.Entries[i].Size()))
- if _, err := enc.w.Write(enc.uint64buf); err != nil {
- return err
- }
- if n := m.Entries[i].Size(); n < msgAppV2BufSize {
- if _, err := m.Entries[i].MarshalTo(enc.buf); err != nil {
- return err
- }
- if _, err := enc.w.Write(enc.buf[:n]); err != nil {
- return err
- }
- } else {
- if _, err := enc.w.Write(pbutil.MustMarshal(&m.Entries[i])); err != nil {
- return err
- }
- }
- enc.index++
- }
- // write commit index
- binary.BigEndian.PutUint64(enc.uint64buf, m.Commit)
- if _, err := enc.w.Write(enc.uint64buf); err != nil {
- return err
- }
- enc.fs.Succ(time.Since(start))
- default:
- if err := binary.Write(enc.w, binary.BigEndian, msgTypeApp); err != nil {
- return err
- }
- // write size of message
- if err := binary.Write(enc.w, binary.BigEndian, uint64(m.Size())); err != nil {
- return err
- }
- // write message
- if _, err := enc.w.Write(pbutil.MustMarshal(m)); err != nil {
- return err
- }
-
- enc.term = m.Term
- enc.index = m.Index
- if l := len(m.Entries); l > 0 {
- enc.index = m.Entries[l-1].Index
- }
- enc.fs.Succ(time.Since(start))
- }
- return nil
-}
-
-type msgAppV2Decoder struct {
- r io.Reader
- local, remote types.ID
-
- term uint64
- index uint64
- buf []byte
- uint64buf []byte
- uint8buf []byte
-}
-
-func newMsgAppV2Decoder(r io.Reader, local, remote types.ID) *msgAppV2Decoder {
- return &msgAppV2Decoder{
- r: r,
- local: local,
- remote: remote,
- buf: make([]byte, msgAppV2BufSize),
- uint64buf: make([]byte, 8),
- uint8buf: make([]byte, 1),
- }
-}
-
-func (dec *msgAppV2Decoder) decode() (raftpb.Message, error) {
- var (
- m raftpb.Message
- typ uint8
- )
- if _, err := io.ReadFull(dec.r, dec.uint8buf); err != nil {
- return m, err
- }
- typ = dec.uint8buf[0]
- switch typ {
- case msgTypeLinkHeartbeat:
- return linkHeartbeatMessage, nil
- case msgTypeAppEntries:
- m = raftpb.Message{
- Type: raftpb.MsgApp,
- From: uint64(dec.remote),
- To: uint64(dec.local),
- Term: dec.term,
- LogTerm: dec.term,
- Index: dec.index,
- }
-
- // decode entries
- if _, err := io.ReadFull(dec.r, dec.uint64buf); err != nil {
- return m, err
- }
- l := binary.BigEndian.Uint64(dec.uint64buf)
- m.Entries = make([]raftpb.Entry, int(l))
- for i := 0; i < int(l); i++ {
- if _, err := io.ReadFull(dec.r, dec.uint64buf); err != nil {
- return m, err
- }
- size := binary.BigEndian.Uint64(dec.uint64buf)
- var buf []byte
- if size < msgAppV2BufSize {
- buf = dec.buf[:size]
- if _, err := io.ReadFull(dec.r, buf); err != nil {
- return m, err
- }
- } else {
- buf = make([]byte, int(size))
- if _, err := io.ReadFull(dec.r, buf); err != nil {
- return m, err
- }
- }
- dec.index++
- // 1 alloc
- pbutil.MustUnmarshal(&m.Entries[i], buf)
- }
- // decode commit index
- if _, err := io.ReadFull(dec.r, dec.uint64buf); err != nil {
- return m, err
- }
- m.Commit = binary.BigEndian.Uint64(dec.uint64buf)
- case msgTypeApp:
- var size uint64
- if err := binary.Read(dec.r, binary.BigEndian, &size); err != nil {
- return m, err
- }
- buf := make([]byte, int(size))
- if _, err := io.ReadFull(dec.r, buf); err != nil {
- return m, err
- }
- pbutil.MustUnmarshal(&m, buf)
-
- dec.term = m.Term
- dec.index = m.Index
- if l := len(m.Entries); l > 0 {
- dec.index = m.Entries[l-1].Index
- }
- default:
- return m, fmt.Errorf("failed to parse type %d in msgappv2 stream", typ)
- }
- return m, nil
-}
diff --git a/vendor/go.etcd.io/etcd/etcdserver/api/rafthttp/peer.go b/vendor/go.etcd.io/etcd/etcdserver/api/rafthttp/peer.go
deleted file mode 100644
index 8130c4a..0000000
--- a/vendor/go.etcd.io/etcd/etcdserver/api/rafthttp/peer.go
+++ /dev/null
@@ -1,374 +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 rafthttp
-
-import (
- "context"
- "sync"
- "time"
-
- "go.etcd.io/etcd/etcdserver/api/snap"
- stats "go.etcd.io/etcd/etcdserver/api/v2stats"
- "go.etcd.io/etcd/pkg/types"
- "go.etcd.io/etcd/raft"
- "go.etcd.io/etcd/raft/raftpb"
-
- "go.uber.org/zap"
- "golang.org/x/time/rate"
-)
-
-const (
- // ConnReadTimeout and ConnWriteTimeout are the i/o timeout set on each connection rafthttp pkg creates.
- // A 5 seconds timeout is good enough for recycling bad connections. Or we have to wait for
- // tcp keepalive failing to detect a bad connection, which is at minutes level.
- // For long term streaming connections, rafthttp pkg sends application level linkHeartbeatMessage
- // to keep the connection alive.
- // For short term pipeline connections, the connection MUST be killed to avoid it being
- // put back to http pkg connection pool.
- ConnReadTimeout = 5 * time.Second
- ConnWriteTimeout = 5 * time.Second
-
- recvBufSize = 4096
- // maxPendingProposals holds the proposals during one leader election process.
- // Generally one leader election takes at most 1 sec. It should have
- // 0-2 election conflicts, and each one takes 0.5 sec.
- // We assume the number of concurrent proposers is smaller than 4096.
- // One client blocks on its proposal for at least 1 sec, so 4096 is enough
- // to hold all proposals.
- maxPendingProposals = 4096
-
- streamAppV2 = "streamMsgAppV2"
- streamMsg = "streamMsg"
- pipelineMsg = "pipeline"
- sendSnap = "sendMsgSnap"
-)
-
-type Peer interface {
- // send sends the message to the remote peer. The function is non-blocking
- // and has no promise that the message will be received by the remote.
- // When it fails to send message out, it will report the status to underlying
- // raft.
- send(m raftpb.Message)
-
- // sendSnap sends the merged snapshot message to the remote peer. Its behavior
- // is similar to send.
- sendSnap(m snap.Message)
-
- // update updates the urls of remote peer.
- update(urls types.URLs)
-
- // attachOutgoingConn attaches the outgoing connection to the peer for
- // stream usage. After the call, the ownership of the outgoing
- // connection hands over to the peer. The peer will close the connection
- // when it is no longer used.
- attachOutgoingConn(conn *outgoingConn)
- // activeSince returns the time that the connection with the
- // peer becomes active.
- activeSince() time.Time
- // stop performs any necessary finalization and terminates the peer
- // elegantly.
- stop()
-}
-
-// peer is the representative of a remote raft node. Local raft node sends
-// messages to the remote through peer.
-// Each peer has two underlying mechanisms to send out a message: stream and
-// pipeline.
-// A stream is a receiver initialized long-polling connection, which
-// is always open to transfer messages. Besides general stream, peer also has
-// a optimized stream for sending msgApp since msgApp accounts for large part
-// of all messages. Only raft leader uses the optimized stream to send msgApp
-// to the remote follower node.
-// A pipeline is a series of http clients that send http requests to the remote.
-// It is only used when the stream has not been established.
-type peer struct {
- lg *zap.Logger
-
- localID types.ID
- // id of the remote raft peer node
- id types.ID
-
- r Raft
-
- status *peerStatus
-
- picker *urlPicker
-
- msgAppV2Writer *streamWriter
- writer *streamWriter
- pipeline *pipeline
- snapSender *snapshotSender // snapshot sender to send v3 snapshot messages
- msgAppV2Reader *streamReader
- msgAppReader *streamReader
-
- recvc chan raftpb.Message
- propc chan raftpb.Message
-
- mu sync.Mutex
- paused bool
-
- cancel context.CancelFunc // cancel pending works in go routine created by peer.
- stopc chan struct{}
-}
-
-func startPeer(t *Transport, urls types.URLs, peerID types.ID, fs *stats.FollowerStats) *peer {
- if t.Logger != nil {
- t.Logger.Info("starting remote peer", zap.String("remote-peer-id", peerID.String()))
- } else {
- plog.Infof("starting peer %s...", peerID)
- }
- defer func() {
- if t.Logger != nil {
- t.Logger.Info("started remote peer", zap.String("remote-peer-id", peerID.String()))
- } else {
- plog.Infof("started peer %s", peerID)
- }
- }()
-
- status := newPeerStatus(t.Logger, t.ID, peerID)
- picker := newURLPicker(urls)
- errorc := t.ErrorC
- r := t.Raft
- pipeline := &pipeline{
- peerID: peerID,
- tr: t,
- picker: picker,
- status: status,
- followerStats: fs,
- raft: r,
- errorc: errorc,
- }
- pipeline.start()
-
- p := &peer{
- lg: t.Logger,
- localID: t.ID,
- id: peerID,
- r: r,
- status: status,
- picker: picker,
- msgAppV2Writer: startStreamWriter(t.Logger, t.ID, peerID, status, fs, r),
- writer: startStreamWriter(t.Logger, t.ID, peerID, status, fs, r),
- pipeline: pipeline,
- snapSender: newSnapshotSender(t, picker, peerID, status),
- recvc: make(chan raftpb.Message, recvBufSize),
- propc: make(chan raftpb.Message, maxPendingProposals),
- stopc: make(chan struct{}),
- }
-
- ctx, cancel := context.WithCancel(context.Background())
- p.cancel = cancel
- go func() {
- for {
- select {
- case mm := <-p.recvc:
- if err := r.Process(ctx, mm); err != nil {
- if t.Logger != nil {
- t.Logger.Warn("failed to process Raft message", zap.Error(err))
- } else {
- plog.Warningf("failed to process raft message (%v)", err)
- }
- }
- case <-p.stopc:
- return
- }
- }
- }()
-
- // r.Process might block for processing proposal when there is no leader.
- // Thus propc must be put into a separate routine with recvc to avoid blocking
- // processing other raft messages.
- go func() {
- for {
- select {
- case mm := <-p.propc:
- if err := r.Process(ctx, mm); err != nil {
- plog.Warningf("failed to process raft message (%v)", err)
- }
- case <-p.stopc:
- return
- }
- }
- }()
-
- p.msgAppV2Reader = &streamReader{
- lg: t.Logger,
- peerID: peerID,
- typ: streamTypeMsgAppV2,
- tr: t,
- picker: picker,
- status: status,
- recvc: p.recvc,
- propc: p.propc,
- rl: rate.NewLimiter(t.DialRetryFrequency, 1),
- }
- p.msgAppReader = &streamReader{
- lg: t.Logger,
- peerID: peerID,
- typ: streamTypeMessage,
- tr: t,
- picker: picker,
- status: status,
- recvc: p.recvc,
- propc: p.propc,
- rl: rate.NewLimiter(t.DialRetryFrequency, 1),
- }
-
- p.msgAppV2Reader.start()
- p.msgAppReader.start()
-
- return p
-}
-
-func (p *peer) send(m raftpb.Message) {
- p.mu.Lock()
- paused := p.paused
- p.mu.Unlock()
-
- if paused {
- return
- }
-
- writec, name := p.pick(m)
- select {
- case writec <- m:
- default:
- p.r.ReportUnreachable(m.To)
- if isMsgSnap(m) {
- p.r.ReportSnapshot(m.To, raft.SnapshotFailure)
- }
- if p.status.isActive() {
- if p.lg != nil {
- p.lg.Warn(
- "dropped internal Raft message since sending buffer is full (overloaded network)",
- zap.String("message-type", m.Type.String()),
- zap.String("local-member-id", p.localID.String()),
- zap.String("from", types.ID(m.From).String()),
- zap.String("remote-peer-id", p.id.String()),
- zap.Bool("remote-peer-active", p.status.isActive()),
- )
- } else {
- plog.MergeWarningf("dropped internal raft message to %s since %s's sending buffer is full (bad/overloaded network)", p.id, name)
- }
- } else {
- if p.lg != nil {
- p.lg.Warn(
- "dropped internal Raft message since sending buffer is full (overloaded network)",
- zap.String("message-type", m.Type.String()),
- zap.String("local-member-id", p.localID.String()),
- zap.String("from", types.ID(m.From).String()),
- zap.String("remote-peer-id", p.id.String()),
- zap.Bool("remote-peer-active", p.status.isActive()),
- )
- } else {
- plog.Debugf("dropped %s to %s since %s's sending buffer is full", m.Type, p.id, name)
- }
- }
- sentFailures.WithLabelValues(types.ID(m.To).String()).Inc()
- }
-}
-
-func (p *peer) sendSnap(m snap.Message) {
- go p.snapSender.send(m)
-}
-
-func (p *peer) update(urls types.URLs) {
- p.picker.update(urls)
-}
-
-func (p *peer) attachOutgoingConn(conn *outgoingConn) {
- var ok bool
- switch conn.t {
- case streamTypeMsgAppV2:
- ok = p.msgAppV2Writer.attach(conn)
- case streamTypeMessage:
- ok = p.writer.attach(conn)
- default:
- if p.lg != nil {
- p.lg.Panic("unknown stream type", zap.String("type", conn.t.String()))
- } else {
- plog.Panicf("unhandled stream type %s", conn.t)
- }
- }
- if !ok {
- conn.Close()
- }
-}
-
-func (p *peer) activeSince() time.Time { return p.status.activeSince() }
-
-// Pause pauses the peer. The peer will simply drops all incoming
-// messages without returning an error.
-func (p *peer) Pause() {
- p.mu.Lock()
- defer p.mu.Unlock()
- p.paused = true
- p.msgAppReader.pause()
- p.msgAppV2Reader.pause()
-}
-
-// Resume resumes a paused peer.
-func (p *peer) Resume() {
- p.mu.Lock()
- defer p.mu.Unlock()
- p.paused = false
- p.msgAppReader.resume()
- p.msgAppV2Reader.resume()
-}
-
-func (p *peer) stop() {
- if p.lg != nil {
- p.lg.Info("stopping remote peer", zap.String("remote-peer-id", p.id.String()))
- } else {
- plog.Infof("stopping peer %s...", p.id)
- }
-
- defer func() {
- if p.lg != nil {
- p.lg.Info("stopped remote peer", zap.String("remote-peer-id", p.id.String()))
- } else {
- plog.Infof("stopped peer %s", p.id)
- }
- }()
-
- close(p.stopc)
- p.cancel()
- p.msgAppV2Writer.stop()
- p.writer.stop()
- p.pipeline.stop()
- p.snapSender.stop()
- p.msgAppV2Reader.stop()
- p.msgAppReader.stop()
-}
-
-// pick picks a chan for sending the given message. The picked chan and the picked chan
-// string name are returned.
-func (p *peer) pick(m raftpb.Message) (writec chan<- raftpb.Message, picked string) {
- var ok bool
- // Considering MsgSnap may have a big size, e.g., 1G, and will block
- // stream for a long time, only use one of the N pipelines to send MsgSnap.
- if isMsgSnap(m) {
- return p.pipeline.msgc, pipelineMsg
- } else if writec, ok = p.msgAppV2Writer.writec(); ok && isMsgApp(m) {
- return writec, streamAppV2
- } else if writec, ok = p.writer.writec(); ok {
- return writec, streamMsg
- }
- return p.pipeline.msgc, pipelineMsg
-}
-
-func isMsgApp(m raftpb.Message) bool { return m.Type == raftpb.MsgApp }
-
-func isMsgSnap(m raftpb.Message) bool { return m.Type == raftpb.MsgSnap }
diff --git a/vendor/go.etcd.io/etcd/etcdserver/api/rafthttp/peer_status.go b/vendor/go.etcd.io/etcd/etcdserver/api/rafthttp/peer_status.go
deleted file mode 100644
index 66149ff..0000000
--- a/vendor/go.etcd.io/etcd/etcdserver/api/rafthttp/peer_status.go
+++ /dev/null
@@ -1,96 +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 rafthttp
-
-import (
- "errors"
- "fmt"
- "sync"
- "time"
-
- "go.etcd.io/etcd/pkg/types"
-
- "go.uber.org/zap"
-)
-
-type failureType struct {
- source string
- action string
-}
-
-type peerStatus struct {
- lg *zap.Logger
- local types.ID
- id types.ID
- mu sync.Mutex // protect variables below
- active bool
- since time.Time
-}
-
-func newPeerStatus(lg *zap.Logger, local, id types.ID) *peerStatus {
- return &peerStatus{lg: lg, local: local, id: id}
-}
-
-func (s *peerStatus) activate() {
- s.mu.Lock()
- defer s.mu.Unlock()
- if !s.active {
- if s.lg != nil {
- s.lg.Info("peer became active", zap.String("peer-id", s.id.String()))
- } else {
- plog.Infof("peer %s became active", s.id)
- }
- s.active = true
- s.since = time.Now()
-
- activePeers.WithLabelValues(s.local.String(), s.id.String()).Inc()
- }
-}
-
-func (s *peerStatus) deactivate(failure failureType, reason string) {
- s.mu.Lock()
- defer s.mu.Unlock()
- msg := fmt.Sprintf("failed to %s %s on %s (%s)", failure.action, s.id, failure.source, reason)
- if s.active {
- if s.lg != nil {
- s.lg.Warn("peer became inactive (message send to peer failed)", zap.String("peer-id", s.id.String()), zap.Error(errors.New(msg)))
- } else {
- plog.Errorf(msg)
- plog.Infof("peer %s became inactive (message send to peer failed)", s.id)
- }
- s.active = false
- s.since = time.Time{}
-
- activePeers.WithLabelValues(s.local.String(), s.id.String()).Dec()
- disconnectedPeers.WithLabelValues(s.local.String(), s.id.String()).Inc()
- return
- }
-
- if s.lg != nil {
- s.lg.Debug("peer deactivated again", zap.String("peer-id", s.id.String()), zap.Error(errors.New(msg)))
- }
-}
-
-func (s *peerStatus) isActive() bool {
- s.mu.Lock()
- defer s.mu.Unlock()
- return s.active
-}
-
-func (s *peerStatus) activeSince() time.Time {
- s.mu.Lock()
- defer s.mu.Unlock()
- return s.since
-}
diff --git a/vendor/go.etcd.io/etcd/etcdserver/api/rafthttp/pipeline.go b/vendor/go.etcd.io/etcd/etcdserver/api/rafthttp/pipeline.go
deleted file mode 100644
index 70f9257..0000000
--- a/vendor/go.etcd.io/etcd/etcdserver/api/rafthttp/pipeline.go
+++ /dev/null
@@ -1,180 +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 rafthttp
-
-import (
- "bytes"
- "context"
- "errors"
- "io/ioutil"
- "sync"
- "time"
-
- stats "go.etcd.io/etcd/etcdserver/api/v2stats"
- "go.etcd.io/etcd/pkg/pbutil"
- "go.etcd.io/etcd/pkg/types"
- "go.etcd.io/etcd/raft"
- "go.etcd.io/etcd/raft/raftpb"
-
- "go.uber.org/zap"
-)
-
-const (
- connPerPipeline = 4
- // pipelineBufSize is the size of pipeline buffer, which helps hold the
- // temporary network latency.
- // The size ensures that pipeline does not drop messages when the network
- // is out of work for less than 1 second in good path.
- pipelineBufSize = 64
-)
-
-var errStopped = errors.New("stopped")
-
-type pipeline struct {
- peerID types.ID
-
- tr *Transport
- picker *urlPicker
- status *peerStatus
- raft Raft
- errorc chan error
- // deprecate when we depercate v2 API
- followerStats *stats.FollowerStats
-
- msgc chan raftpb.Message
- // wait for the handling routines
- wg sync.WaitGroup
- stopc chan struct{}
-}
-
-func (p *pipeline) start() {
- p.stopc = make(chan struct{})
- p.msgc = make(chan raftpb.Message, pipelineBufSize)
- p.wg.Add(connPerPipeline)
- for i := 0; i < connPerPipeline; i++ {
- go p.handle()
- }
-
- if p.tr != nil && p.tr.Logger != nil {
- p.tr.Logger.Info(
- "started HTTP pipelining with remote peer",
- zap.String("local-member-id", p.tr.ID.String()),
- zap.String("remote-peer-id", p.peerID.String()),
- )
- } else {
- plog.Infof("started HTTP pipelining with peer %s", p.peerID)
- }
-}
-
-func (p *pipeline) stop() {
- close(p.stopc)
- p.wg.Wait()
-
- if p.tr != nil && p.tr.Logger != nil {
- p.tr.Logger.Info(
- "stopped HTTP pipelining with remote peer",
- zap.String("local-member-id", p.tr.ID.String()),
- zap.String("remote-peer-id", p.peerID.String()),
- )
- } else {
- plog.Infof("stopped HTTP pipelining with peer %s", p.peerID)
- }
-}
-
-func (p *pipeline) handle() {
- defer p.wg.Done()
-
- for {
- select {
- case m := <-p.msgc:
- start := time.Now()
- err := p.post(pbutil.MustMarshal(&m))
- end := time.Now()
-
- if err != nil {
- p.status.deactivate(failureType{source: pipelineMsg, action: "write"}, err.Error())
-
- if m.Type == raftpb.MsgApp && p.followerStats != nil {
- p.followerStats.Fail()
- }
- p.raft.ReportUnreachable(m.To)
- if isMsgSnap(m) {
- p.raft.ReportSnapshot(m.To, raft.SnapshotFailure)
- }
- sentFailures.WithLabelValues(types.ID(m.To).String()).Inc()
- continue
- }
-
- p.status.activate()
- if m.Type == raftpb.MsgApp && p.followerStats != nil {
- p.followerStats.Succ(end.Sub(start))
- }
- if isMsgSnap(m) {
- p.raft.ReportSnapshot(m.To, raft.SnapshotFinish)
- }
- sentBytes.WithLabelValues(types.ID(m.To).String()).Add(float64(m.Size()))
- case <-p.stopc:
- return
- }
- }
-}
-
-// post POSTs a data payload to a url. Returns nil if the POST succeeds,
-// error on any failure.
-func (p *pipeline) post(data []byte) (err error) {
- u := p.picker.pick()
- req := createPostRequest(u, RaftPrefix, bytes.NewBuffer(data), "application/protobuf", p.tr.URLs, p.tr.ID, p.tr.ClusterID)
-
- done := make(chan struct{}, 1)
- ctx, cancel := context.WithCancel(context.Background())
- req = req.WithContext(ctx)
- go func() {
- select {
- case <-done:
- case <-p.stopc:
- waitSchedule()
- cancel()
- }
- }()
-
- resp, err := p.tr.pipelineRt.RoundTrip(req)
- done <- struct{}{}
- if err != nil {
- p.picker.unreachable(u)
- return err
- }
- defer resp.Body.Close()
- b, err := ioutil.ReadAll(resp.Body)
- if err != nil {
- p.picker.unreachable(u)
- return err
- }
-
- err = checkPostResponse(resp, b, req, p.peerID)
- if err != nil {
- p.picker.unreachable(u)
- // errMemberRemoved is a critical error since a removed member should
- // always be stopped. So we use reportCriticalError to report it to errorc.
- if err == errMemberRemoved {
- reportCriticalError(err, p.errorc)
- }
- return err
- }
-
- return nil
-}
-
-// waitSchedule waits other goroutines to be scheduled for a while
-func waitSchedule() { time.Sleep(time.Millisecond) }
diff --git a/vendor/go.etcd.io/etcd/etcdserver/api/rafthttp/probing_status.go b/vendor/go.etcd.io/etcd/etcdserver/api/rafthttp/probing_status.go
deleted file mode 100644
index 474d9a0..0000000
--- a/vendor/go.etcd.io/etcd/etcdserver/api/rafthttp/probing_status.go
+++ /dev/null
@@ -1,104 +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 rafthttp
-
-import (
- "time"
-
- "github.com/prometheus/client_golang/prometheus"
- "github.com/xiang90/probing"
- "go.uber.org/zap"
-)
-
-const (
- // RoundTripperNameRaftMessage is the name of round-tripper that sends
- // all other Raft messages, other than "snap.Message".
- RoundTripperNameRaftMessage = "ROUND_TRIPPER_RAFT_MESSAGE"
- // RoundTripperNameSnapshot is the name of round-tripper that sends merged snapshot message.
- RoundTripperNameSnapshot = "ROUND_TRIPPER_SNAPSHOT"
-)
-
-var (
- // proberInterval must be shorter than read timeout.
- // Or the connection will time-out.
- proberInterval = ConnReadTimeout - time.Second
- statusMonitoringInterval = 30 * time.Second
- statusErrorInterval = 5 * time.Second
-)
-
-func addPeerToProber(lg *zap.Logger, p probing.Prober, id string, us []string, roundTripperName string, rttSecProm *prometheus.HistogramVec) {
- hus := make([]string, len(us))
- for i := range us {
- hus[i] = us[i] + ProbingPrefix
- }
-
- p.AddHTTP(id, proberInterval, hus)
-
- s, err := p.Status(id)
- if err != nil {
- if lg != nil {
- lg.Warn("failed to add peer into prober", zap.String("remote-peer-id", id))
- } else {
- plog.Errorf("failed to add peer %s into prober", id)
- }
- return
- }
-
- go monitorProbingStatus(lg, s, id, roundTripperName, rttSecProm)
-}
-
-func monitorProbingStatus(lg *zap.Logger, s probing.Status, id string, roundTripperName string, rttSecProm *prometheus.HistogramVec) {
- // set the first interval short to log error early.
- interval := statusErrorInterval
- for {
- select {
- case <-time.After(interval):
- if !s.Health() {
- if lg != nil {
- lg.Warn(
- "prober detected unhealthy status",
- zap.String("round-tripper-name", roundTripperName),
- zap.String("remote-peer-id", id),
- zap.Duration("rtt", s.SRTT()),
- zap.Error(s.Err()),
- )
- } else {
- plog.Warningf("health check for peer %s could not connect: %v", id, s.Err())
- }
- interval = statusErrorInterval
- } else {
- interval = statusMonitoringInterval
- }
- if s.ClockDiff() > time.Second {
- if lg != nil {
- lg.Warn(
- "prober found high clock drift",
- zap.String("round-tripper-name", roundTripperName),
- zap.String("remote-peer-id", id),
- zap.Duration("clock-drift", s.ClockDiff()),
- zap.Duration("rtt", s.SRTT()),
- zap.Error(s.Err()),
- )
- } else {
- plog.Warningf("the clock difference against peer %s is too high [%v > %v]", id, s.ClockDiff(), time.Second)
- }
- }
- rttSecProm.WithLabelValues(id).Observe(s.SRTT().Seconds())
-
- case <-s.StopNotify():
- return
- }
- }
-}
diff --git a/vendor/go.etcd.io/etcd/etcdserver/api/rafthttp/remote.go b/vendor/go.etcd.io/etcd/etcdserver/api/rafthttp/remote.go
deleted file mode 100644
index 1ef2493..0000000
--- a/vendor/go.etcd.io/etcd/etcdserver/api/rafthttp/remote.go
+++ /dev/null
@@ -1,99 +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 rafthttp
-
-import (
- "go.etcd.io/etcd/pkg/types"
- "go.etcd.io/etcd/raft/raftpb"
-
- "go.uber.org/zap"
-)
-
-type remote struct {
- lg *zap.Logger
- localID types.ID
- id types.ID
- status *peerStatus
- pipeline *pipeline
-}
-
-func startRemote(tr *Transport, urls types.URLs, id types.ID) *remote {
- picker := newURLPicker(urls)
- status := newPeerStatus(tr.Logger, tr.ID, id)
- pipeline := &pipeline{
- peerID: id,
- tr: tr,
- picker: picker,
- status: status,
- raft: tr.Raft,
- errorc: tr.ErrorC,
- }
- pipeline.start()
-
- return &remote{
- lg: tr.Logger,
- localID: tr.ID,
- id: id,
- status: status,
- pipeline: pipeline,
- }
-}
-
-func (g *remote) send(m raftpb.Message) {
- select {
- case g.pipeline.msgc <- m:
- default:
- if g.status.isActive() {
- if g.lg != nil {
- g.lg.Warn(
- "dropped internal Raft message since sending buffer is full (overloaded network)",
- zap.String("message-type", m.Type.String()),
- zap.String("local-member-id", g.localID.String()),
- zap.String("from", types.ID(m.From).String()),
- zap.String("remote-peer-id", g.id.String()),
- zap.Bool("remote-peer-active", g.status.isActive()),
- )
- } else {
- plog.MergeWarningf("dropped internal raft message to %s since sending buffer is full (bad/overloaded network)", g.id)
- }
- } else {
- if g.lg != nil {
- g.lg.Warn(
- "dropped Raft message since sending buffer is full (overloaded network)",
- zap.String("message-type", m.Type.String()),
- zap.String("local-member-id", g.localID.String()),
- zap.String("from", types.ID(m.From).String()),
- zap.String("remote-peer-id", g.id.String()),
- zap.Bool("remote-peer-active", g.status.isActive()),
- )
- } else {
- plog.Debugf("dropped %s to %s since sending buffer is full", m.Type, g.id)
- }
- }
- sentFailures.WithLabelValues(types.ID(m.To).String()).Inc()
- }
-}
-
-func (g *remote) stop() {
- g.pipeline.stop()
-}
-
-func (g *remote) Pause() {
- g.stop()
-}
-
-func (g *remote) Resume() {
- g.pipeline.start()
-}
diff --git a/vendor/go.etcd.io/etcd/etcdserver/api/rafthttp/snapshot_sender.go b/vendor/go.etcd.io/etcd/etcdserver/api/rafthttp/snapshot_sender.go
deleted file mode 100644
index 62efb0c..0000000
--- a/vendor/go.etcd.io/etcd/etcdserver/api/rafthttp/snapshot_sender.go
+++ /dev/null
@@ -1,207 +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 rafthttp
-
-import (
- "bytes"
- "context"
- "io"
- "io/ioutil"
- "net/http"
- "time"
-
- "go.etcd.io/etcd/etcdserver/api/snap"
- "go.etcd.io/etcd/pkg/httputil"
- pioutil "go.etcd.io/etcd/pkg/ioutil"
- "go.etcd.io/etcd/pkg/types"
- "go.etcd.io/etcd/raft"
-
- "github.com/dustin/go-humanize"
- "go.uber.org/zap"
-)
-
-var (
- // timeout for reading snapshot response body
- snapResponseReadTimeout = 5 * time.Second
-)
-
-type snapshotSender struct {
- from, to types.ID
- cid types.ID
-
- tr *Transport
- picker *urlPicker
- status *peerStatus
- r Raft
- errorc chan error
-
- stopc chan struct{}
-}
-
-func newSnapshotSender(tr *Transport, picker *urlPicker, to types.ID, status *peerStatus) *snapshotSender {
- return &snapshotSender{
- from: tr.ID,
- to: to,
- cid: tr.ClusterID,
- tr: tr,
- picker: picker,
- status: status,
- r: tr.Raft,
- errorc: tr.ErrorC,
- stopc: make(chan struct{}),
- }
-}
-
-func (s *snapshotSender) stop() { close(s.stopc) }
-
-func (s *snapshotSender) send(merged snap.Message) {
- start := time.Now()
-
- m := merged.Message
- to := types.ID(m.To).String()
-
- body := createSnapBody(s.tr.Logger, merged)
- defer body.Close()
-
- u := s.picker.pick()
- req := createPostRequest(u, RaftSnapshotPrefix, body, "application/octet-stream", s.tr.URLs, s.from, s.cid)
-
- if s.tr.Logger != nil {
- s.tr.Logger.Info(
- "sending database snapshot",
- zap.Uint64("snapshot-index", m.Snapshot.Metadata.Index),
- zap.String("remote-peer-id", to),
- zap.Int64("bytes", merged.TotalSize),
- zap.String("size", humanize.Bytes(uint64(merged.TotalSize))),
- )
- } else {
- plog.Infof("start to send database snapshot [index: %d, to %s]...", m.Snapshot.Metadata.Index, types.ID(m.To))
- }
-
- snapshotSendInflights.WithLabelValues(to).Inc()
- defer func() {
- snapshotSendInflights.WithLabelValues(to).Dec()
- }()
-
- err := s.post(req)
- defer merged.CloseWithError(err)
- if err != nil {
- if s.tr.Logger != nil {
- s.tr.Logger.Warn(
- "failed to send database snapshot",
- zap.Uint64("snapshot-index", m.Snapshot.Metadata.Index),
- zap.String("remote-peer-id", to),
- zap.Int64("bytes", merged.TotalSize),
- zap.String("size", humanize.Bytes(uint64(merged.TotalSize))),
- zap.Error(err),
- )
- } else {
- plog.Warningf("database snapshot [index: %d, to: %s] failed to be sent out (%v)", m.Snapshot.Metadata.Index, types.ID(m.To), err)
- }
-
- // errMemberRemoved is a critical error since a removed member should
- // always be stopped. So we use reportCriticalError to report it to errorc.
- if err == errMemberRemoved {
- reportCriticalError(err, s.errorc)
- }
-
- s.picker.unreachable(u)
- s.status.deactivate(failureType{source: sendSnap, action: "post"}, err.Error())
- s.r.ReportUnreachable(m.To)
- // report SnapshotFailure to raft state machine. After raft state
- // machine knows about it, it would pause a while and retry sending
- // new snapshot message.
- s.r.ReportSnapshot(m.To, raft.SnapshotFailure)
- sentFailures.WithLabelValues(to).Inc()
- snapshotSendFailures.WithLabelValues(to).Inc()
- return
- }
- s.status.activate()
- s.r.ReportSnapshot(m.To, raft.SnapshotFinish)
-
- if s.tr.Logger != nil {
- s.tr.Logger.Info(
- "sent database snapshot",
- zap.Uint64("snapshot-index", m.Snapshot.Metadata.Index),
- zap.String("remote-peer-id", to),
- zap.Int64("bytes", merged.TotalSize),
- zap.String("size", humanize.Bytes(uint64(merged.TotalSize))),
- )
- } else {
- plog.Infof("database snapshot [index: %d, to: %s] sent out successfully", m.Snapshot.Metadata.Index, types.ID(m.To))
- }
-
- sentBytes.WithLabelValues(to).Add(float64(merged.TotalSize))
- snapshotSend.WithLabelValues(to).Inc()
- snapshotSendSeconds.WithLabelValues(to).Observe(time.Since(start).Seconds())
-}
-
-// post posts the given request.
-// It returns nil when request is sent out and processed successfully.
-func (s *snapshotSender) post(req *http.Request) (err error) {
- ctx, cancel := context.WithCancel(context.Background())
- req = req.WithContext(ctx)
- defer cancel()
-
- type responseAndError struct {
- resp *http.Response
- body []byte
- err error
- }
- result := make(chan responseAndError, 1)
-
- go func() {
- resp, err := s.tr.pipelineRt.RoundTrip(req)
- if err != nil {
- result <- responseAndError{resp, nil, err}
- return
- }
-
- // close the response body when timeouts.
- // prevents from reading the body forever when the other side dies right after
- // successfully receives the request body.
- time.AfterFunc(snapResponseReadTimeout, func() { httputil.GracefulClose(resp) })
- body, err := ioutil.ReadAll(resp.Body)
- result <- responseAndError{resp, body, err}
- }()
-
- select {
- case <-s.stopc:
- return errStopped
- case r := <-result:
- if r.err != nil {
- return r.err
- }
- return checkPostResponse(r.resp, r.body, req, s.to)
- }
-}
-
-func createSnapBody(lg *zap.Logger, merged snap.Message) io.ReadCloser {
- buf := new(bytes.Buffer)
- enc := &messageEncoder{w: buf}
- // encode raft message
- if err := enc.encode(&merged.Message); err != nil {
- if lg != nil {
- lg.Panic("failed to encode message", zap.Error(err))
- } else {
- plog.Panicf("encode message error (%v)", err)
- }
- }
-
- return &pioutil.ReaderAndCloser{
- Reader: io.MultiReader(buf, merged.ReadCloser),
- Closer: merged.ReadCloser,
- }
-}
diff --git a/vendor/go.etcd.io/etcd/etcdserver/api/rafthttp/stream.go b/vendor/go.etcd.io/etcd/etcdserver/api/rafthttp/stream.go
deleted file mode 100644
index dcb2223..0000000
--- a/vendor/go.etcd.io/etcd/etcdserver/api/rafthttp/stream.go
+++ /dev/null
@@ -1,746 +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 rafthttp
-
-import (
- "context"
- "fmt"
- "io"
- "io/ioutil"
- "net/http"
- "path"
- "strings"
- "sync"
- "time"
-
- stats "go.etcd.io/etcd/etcdserver/api/v2stats"
- "go.etcd.io/etcd/pkg/httputil"
- "go.etcd.io/etcd/pkg/transport"
- "go.etcd.io/etcd/pkg/types"
- "go.etcd.io/etcd/raft/raftpb"
- "go.etcd.io/etcd/version"
-
- "github.com/coreos/go-semver/semver"
- "go.uber.org/zap"
- "golang.org/x/time/rate"
-)
-
-const (
- streamTypeMessage streamType = "message"
- streamTypeMsgAppV2 streamType = "msgappv2"
-
- streamBufSize = 4096
-)
-
-var (
- errUnsupportedStreamType = fmt.Errorf("unsupported stream type")
-
- // the key is in string format "major.minor.patch"
- supportedStream = map[string][]streamType{
- "2.0.0": {},
- "2.1.0": {streamTypeMsgAppV2, streamTypeMessage},
- "2.2.0": {streamTypeMsgAppV2, streamTypeMessage},
- "2.3.0": {streamTypeMsgAppV2, streamTypeMessage},
- "3.0.0": {streamTypeMsgAppV2, streamTypeMessage},
- "3.1.0": {streamTypeMsgAppV2, streamTypeMessage},
- "3.2.0": {streamTypeMsgAppV2, streamTypeMessage},
- "3.3.0": {streamTypeMsgAppV2, streamTypeMessage},
- }
-)
-
-type streamType string
-
-func (t streamType) endpoint() string {
- switch t {
- case streamTypeMsgAppV2:
- return path.Join(RaftStreamPrefix, "msgapp")
- case streamTypeMessage:
- return path.Join(RaftStreamPrefix, "message")
- default:
- plog.Panicf("unhandled stream type %v", t)
- return ""
- }
-}
-
-func (t streamType) String() string {
- switch t {
- case streamTypeMsgAppV2:
- return "stream MsgApp v2"
- case streamTypeMessage:
- return "stream Message"
- default:
- return "unknown stream"
- }
-}
-
-var (
- // linkHeartbeatMessage is a special message used as heartbeat message in
- // link layer. It never conflicts with messages from raft because raft
- // doesn't send out messages without From and To fields.
- linkHeartbeatMessage = raftpb.Message{Type: raftpb.MsgHeartbeat}
-)
-
-func isLinkHeartbeatMessage(m *raftpb.Message) bool {
- return m.Type == raftpb.MsgHeartbeat && m.From == 0 && m.To == 0
-}
-
-type outgoingConn struct {
- t streamType
- io.Writer
- http.Flusher
- io.Closer
-
- localID types.ID
- peerID types.ID
-}
-
-// streamWriter writes messages to the attached outgoingConn.
-type streamWriter struct {
- lg *zap.Logger
-
- localID types.ID
- peerID types.ID
-
- status *peerStatus
- fs *stats.FollowerStats
- r Raft
-
- mu sync.Mutex // guard field working and closer
- closer io.Closer
- working bool
-
- msgc chan raftpb.Message
- connc chan *outgoingConn
- stopc chan struct{}
- done chan struct{}
-}
-
-// startStreamWriter creates a streamWrite and starts a long running go-routine that accepts
-// messages and writes to the attached outgoing connection.
-func startStreamWriter(lg *zap.Logger, local, id types.ID, status *peerStatus, fs *stats.FollowerStats, r Raft) *streamWriter {
- w := &streamWriter{
- lg: lg,
-
- localID: local,
- peerID: id,
-
- status: status,
- fs: fs,
- r: r,
- msgc: make(chan raftpb.Message, streamBufSize),
- connc: make(chan *outgoingConn),
- stopc: make(chan struct{}),
- done: make(chan struct{}),
- }
- go w.run()
- return w
-}
-
-func (cw *streamWriter) run() {
- var (
- msgc chan raftpb.Message
- heartbeatc <-chan time.Time
- t streamType
- enc encoder
- flusher http.Flusher
- batched int
- )
- tickc := time.NewTicker(ConnReadTimeout / 3)
- defer tickc.Stop()
- unflushed := 0
-
- if cw.lg != nil {
- cw.lg.Info(
- "started stream writer with remote peer",
- zap.String("local-member-id", cw.localID.String()),
- zap.String("remote-peer-id", cw.peerID.String()),
- )
- } else {
- plog.Infof("started streaming with peer %s (writer)", cw.peerID)
- }
-
- for {
- select {
- case <-heartbeatc:
- err := enc.encode(&linkHeartbeatMessage)
- unflushed += linkHeartbeatMessage.Size()
- if err == nil {
- flusher.Flush()
- batched = 0
- sentBytes.WithLabelValues(cw.peerID.String()).Add(float64(unflushed))
- unflushed = 0
- continue
- }
-
- cw.status.deactivate(failureType{source: t.String(), action: "heartbeat"}, err.Error())
-
- sentFailures.WithLabelValues(cw.peerID.String()).Inc()
- cw.close()
- if cw.lg != nil {
- cw.lg.Warn(
- "lost TCP streaming connection with remote peer",
- zap.String("stream-writer-type", t.String()),
- zap.String("local-member-id", cw.localID.String()),
- zap.String("remote-peer-id", cw.peerID.String()),
- )
- } else {
- plog.Warningf("lost the TCP streaming connection with peer %s (%s writer)", cw.peerID, t)
- }
- heartbeatc, msgc = nil, nil
-
- case m := <-msgc:
- err := enc.encode(&m)
- if err == nil {
- unflushed += m.Size()
-
- if len(msgc) == 0 || batched > streamBufSize/2 {
- flusher.Flush()
- sentBytes.WithLabelValues(cw.peerID.String()).Add(float64(unflushed))
- unflushed = 0
- batched = 0
- } else {
- batched++
- }
-
- continue
- }
-
- cw.status.deactivate(failureType{source: t.String(), action: "write"}, err.Error())
- cw.close()
- if cw.lg != nil {
- cw.lg.Warn(
- "lost TCP streaming connection with remote peer",
- zap.String("stream-writer-type", t.String()),
- zap.String("local-member-id", cw.localID.String()),
- zap.String("remote-peer-id", cw.peerID.String()),
- )
- } else {
- plog.Warningf("lost the TCP streaming connection with peer %s (%s writer)", cw.peerID, t)
- }
- heartbeatc, msgc = nil, nil
- cw.r.ReportUnreachable(m.To)
- sentFailures.WithLabelValues(cw.peerID.String()).Inc()
-
- case conn := <-cw.connc:
- cw.mu.Lock()
- closed := cw.closeUnlocked()
- t = conn.t
- switch conn.t {
- case streamTypeMsgAppV2:
- enc = newMsgAppV2Encoder(conn.Writer, cw.fs)
- case streamTypeMessage:
- enc = &messageEncoder{w: conn.Writer}
- default:
- plog.Panicf("unhandled stream type %s", conn.t)
- }
- if cw.lg != nil {
- cw.lg.Info(
- "set message encoder",
- zap.String("from", conn.localID.String()),
- zap.String("to", conn.peerID.String()),
- zap.String("stream-type", t.String()),
- )
- }
- flusher = conn.Flusher
- unflushed = 0
- cw.status.activate()
- cw.closer = conn.Closer
- cw.working = true
- cw.mu.Unlock()
-
- if closed {
- if cw.lg != nil {
- cw.lg.Warn(
- "closed TCP streaming connection with remote peer",
- zap.String("stream-writer-type", t.String()),
- zap.String("local-member-id", cw.localID.String()),
- zap.String("remote-peer-id", cw.peerID.String()),
- )
- } else {
- plog.Warningf("closed an existing TCP streaming connection with peer %s (%s writer)", cw.peerID, t)
- }
- }
- if cw.lg != nil {
- cw.lg.Warn(
- "established TCP streaming connection with remote peer",
- zap.String("stream-writer-type", t.String()),
- zap.String("local-member-id", cw.localID.String()),
- zap.String("remote-peer-id", cw.peerID.String()),
- )
- } else {
- plog.Infof("established a TCP streaming connection with peer %s (%s writer)", cw.peerID, t)
- }
- heartbeatc, msgc = tickc.C, cw.msgc
-
- case <-cw.stopc:
- if cw.close() {
- if cw.lg != nil {
- cw.lg.Warn(
- "closed TCP streaming connection with remote peer",
- zap.String("stream-writer-type", t.String()),
- zap.String("remote-peer-id", cw.peerID.String()),
- )
- } else {
- plog.Infof("closed the TCP streaming connection with peer %s (%s writer)", cw.peerID, t)
- }
- }
- if cw.lg != nil {
- cw.lg.Warn(
- "stopped TCP streaming connection with remote peer",
- zap.String("stream-writer-type", t.String()),
- zap.String("remote-peer-id", cw.peerID.String()),
- )
- } else {
- plog.Infof("stopped streaming with peer %s (writer)", cw.peerID)
- }
- close(cw.done)
- return
- }
- }
-}
-
-func (cw *streamWriter) writec() (chan<- raftpb.Message, bool) {
- cw.mu.Lock()
- defer cw.mu.Unlock()
- return cw.msgc, cw.working
-}
-
-func (cw *streamWriter) close() bool {
- cw.mu.Lock()
- defer cw.mu.Unlock()
- return cw.closeUnlocked()
-}
-
-func (cw *streamWriter) closeUnlocked() bool {
- if !cw.working {
- return false
- }
- if err := cw.closer.Close(); err != nil {
- if cw.lg != nil {
- cw.lg.Warn(
- "failed to close connection with remote peer",
- zap.String("remote-peer-id", cw.peerID.String()),
- zap.Error(err),
- )
- } else {
- plog.Errorf("peer %s (writer) connection close error: %v", cw.peerID, err)
- }
- }
- if len(cw.msgc) > 0 {
- cw.r.ReportUnreachable(uint64(cw.peerID))
- }
- cw.msgc = make(chan raftpb.Message, streamBufSize)
- cw.working = false
- return true
-}
-
-func (cw *streamWriter) attach(conn *outgoingConn) bool {
- select {
- case cw.connc <- conn:
- return true
- case <-cw.done:
- return false
- }
-}
-
-func (cw *streamWriter) stop() {
- close(cw.stopc)
- <-cw.done
-}
-
-// streamReader is a long-running go-routine that dials to the remote stream
-// endpoint and reads messages from the response body returned.
-type streamReader struct {
- lg *zap.Logger
-
- peerID types.ID
- typ streamType
-
- tr *Transport
- picker *urlPicker
- status *peerStatus
- recvc chan<- raftpb.Message
- propc chan<- raftpb.Message
-
- rl *rate.Limiter // alters the frequency of dial retrial attempts
-
- errorc chan<- error
-
- mu sync.Mutex
- paused bool
- closer io.Closer
-
- ctx context.Context
- cancel context.CancelFunc
- done chan struct{}
-}
-
-func (cr *streamReader) start() {
- cr.done = make(chan struct{})
- if cr.errorc == nil {
- cr.errorc = cr.tr.ErrorC
- }
- if cr.ctx == nil {
- cr.ctx, cr.cancel = context.WithCancel(context.Background())
- }
- go cr.run()
-}
-
-func (cr *streamReader) run() {
- t := cr.typ
-
- if cr.lg != nil {
- cr.lg.Info(
- "started stream reader with remote peer",
- zap.String("stream-reader-type", t.String()),
- zap.String("local-member-id", cr.tr.ID.String()),
- zap.String("remote-peer-id", cr.peerID.String()),
- )
- } else {
- plog.Infof("started streaming with peer %s (%s reader)", cr.peerID, t)
- }
-
- for {
- rc, err := cr.dial(t)
- if err != nil {
- if err != errUnsupportedStreamType {
- cr.status.deactivate(failureType{source: t.String(), action: "dial"}, err.Error())
- }
- } else {
- cr.status.activate()
- if cr.lg != nil {
- cr.lg.Info(
- "established TCP streaming connection with remote peer",
- zap.String("stream-reader-type", cr.typ.String()),
- zap.String("local-member-id", cr.tr.ID.String()),
- zap.String("remote-peer-id", cr.peerID.String()),
- )
- } else {
- plog.Infof("established a TCP streaming connection with peer %s (%s reader)", cr.peerID, cr.typ)
- }
- err = cr.decodeLoop(rc, t)
- if cr.lg != nil {
- cr.lg.Warn(
- "lost TCP streaming connection with remote peer",
- zap.String("stream-reader-type", cr.typ.String()),
- zap.String("local-member-id", cr.tr.ID.String()),
- zap.String("remote-peer-id", cr.peerID.String()),
- zap.Error(err),
- )
- } else {
- plog.Warningf("lost the TCP streaming connection with peer %s (%s reader)", cr.peerID, cr.typ)
- }
- switch {
- // all data is read out
- case err == io.EOF:
- // connection is closed by the remote
- case transport.IsClosedConnError(err):
- default:
- cr.status.deactivate(failureType{source: t.String(), action: "read"}, err.Error())
- }
- }
- // Wait for a while before new dial attempt
- err = cr.rl.Wait(cr.ctx)
- if cr.ctx.Err() != nil {
- if cr.lg != nil {
- cr.lg.Info(
- "stopped stream reader with remote peer",
- zap.String("stream-reader-type", t.String()),
- zap.String("local-member-id", cr.tr.ID.String()),
- zap.String("remote-peer-id", cr.peerID.String()),
- )
- } else {
- plog.Infof("stopped streaming with peer %s (%s reader)", cr.peerID, t)
- }
- close(cr.done)
- return
- }
- if err != nil {
- if cr.lg != nil {
- cr.lg.Warn(
- "rate limit on stream reader with remote peer",
- zap.String("stream-reader-type", t.String()),
- zap.String("local-member-id", cr.tr.ID.String()),
- zap.String("remote-peer-id", cr.peerID.String()),
- zap.Error(err),
- )
- } else {
- plog.Errorf("streaming with peer %s (%s reader) rate limiter error: %v", cr.peerID, t, err)
- }
- }
- }
-}
-
-func (cr *streamReader) decodeLoop(rc io.ReadCloser, t streamType) error {
- var dec decoder
- cr.mu.Lock()
- switch t {
- case streamTypeMsgAppV2:
- dec = newMsgAppV2Decoder(rc, cr.tr.ID, cr.peerID)
- case streamTypeMessage:
- dec = &messageDecoder{r: rc}
- default:
- if cr.lg != nil {
- cr.lg.Panic("unknown stream type", zap.String("type", t.String()))
- } else {
- plog.Panicf("unhandled stream type %s", t)
- }
- }
- select {
- case <-cr.ctx.Done():
- cr.mu.Unlock()
- if err := rc.Close(); err != nil {
- return err
- }
- return io.EOF
- default:
- cr.closer = rc
- }
- cr.mu.Unlock()
-
- // gofail: labelRaftDropHeartbeat:
- for {
- m, err := dec.decode()
- if err != nil {
- cr.mu.Lock()
- cr.close()
- cr.mu.Unlock()
- return err
- }
-
- // gofail-go: var raftDropHeartbeat struct{}
- // continue labelRaftDropHeartbeat
- receivedBytes.WithLabelValues(types.ID(m.From).String()).Add(float64(m.Size()))
-
- cr.mu.Lock()
- paused := cr.paused
- cr.mu.Unlock()
-
- if paused {
- continue
- }
-
- if isLinkHeartbeatMessage(&m) {
- // raft is not interested in link layer
- // heartbeat message, so we should ignore
- // it.
- continue
- }
-
- recvc := cr.recvc
- if m.Type == raftpb.MsgProp {
- recvc = cr.propc
- }
-
- select {
- case recvc <- m:
- default:
- if cr.status.isActive() {
- if cr.lg != nil {
- cr.lg.Warn(
- "dropped internal Raft message since receiving buffer is full (overloaded network)",
- zap.String("message-type", m.Type.String()),
- zap.String("local-member-id", cr.tr.ID.String()),
- zap.String("from", types.ID(m.From).String()),
- zap.String("remote-peer-id", types.ID(m.To).String()),
- zap.Bool("remote-peer-active", cr.status.isActive()),
- )
- } else {
- plog.MergeWarningf("dropped internal raft message from %s since receiving buffer is full (overloaded network)", types.ID(m.From))
- }
- } else {
- if cr.lg != nil {
- cr.lg.Warn(
- "dropped Raft message since receiving buffer is full (overloaded network)",
- zap.String("message-type", m.Type.String()),
- zap.String("local-member-id", cr.tr.ID.String()),
- zap.String("from", types.ID(m.From).String()),
- zap.String("remote-peer-id", types.ID(m.To).String()),
- zap.Bool("remote-peer-active", cr.status.isActive()),
- )
- } else {
- plog.Debugf("dropped %s from %s since receiving buffer is full", m.Type, types.ID(m.From))
- }
- }
- recvFailures.WithLabelValues(types.ID(m.From).String()).Inc()
- }
- }
-}
-
-func (cr *streamReader) stop() {
- cr.mu.Lock()
- cr.cancel()
- cr.close()
- cr.mu.Unlock()
- <-cr.done
-}
-
-func (cr *streamReader) dial(t streamType) (io.ReadCloser, error) {
- u := cr.picker.pick()
- uu := u
- uu.Path = path.Join(t.endpoint(), cr.tr.ID.String())
-
- if cr.lg != nil {
- cr.lg.Debug(
- "dial stream reader",
- zap.String("from", cr.tr.ID.String()),
- zap.String("to", cr.peerID.String()),
- zap.String("address", uu.String()),
- )
- }
- req, err := http.NewRequest("GET", uu.String(), nil)
- if err != nil {
- cr.picker.unreachable(u)
- return nil, fmt.Errorf("failed to make http request to %v (%v)", u, err)
- }
- req.Header.Set("X-Server-From", cr.tr.ID.String())
- req.Header.Set("X-Server-Version", version.Version)
- req.Header.Set("X-Min-Cluster-Version", version.MinClusterVersion)
- req.Header.Set("X-Etcd-Cluster-ID", cr.tr.ClusterID.String())
- req.Header.Set("X-Raft-To", cr.peerID.String())
-
- setPeerURLsHeader(req, cr.tr.URLs)
-
- req = req.WithContext(cr.ctx)
-
- cr.mu.Lock()
- select {
- case <-cr.ctx.Done():
- cr.mu.Unlock()
- return nil, fmt.Errorf("stream reader is stopped")
- default:
- }
- cr.mu.Unlock()
-
- resp, err := cr.tr.streamRt.RoundTrip(req)
- if err != nil {
- cr.picker.unreachable(u)
- return nil, err
- }
-
- rv := serverVersion(resp.Header)
- lv := semver.Must(semver.NewVersion(version.Version))
- if compareMajorMinorVersion(rv, lv) == -1 && !checkStreamSupport(rv, t) {
- httputil.GracefulClose(resp)
- cr.picker.unreachable(u)
- return nil, errUnsupportedStreamType
- }
-
- switch resp.StatusCode {
- case http.StatusGone:
- httputil.GracefulClose(resp)
- cr.picker.unreachable(u)
- reportCriticalError(errMemberRemoved, cr.errorc)
- return nil, errMemberRemoved
-
- case http.StatusOK:
- return resp.Body, nil
-
- case http.StatusNotFound:
- httputil.GracefulClose(resp)
- cr.picker.unreachable(u)
- return nil, fmt.Errorf("peer %s failed to find local node %s", cr.peerID, cr.tr.ID)
-
- case http.StatusPreconditionFailed:
- b, err := ioutil.ReadAll(resp.Body)
- if err != nil {
- cr.picker.unreachable(u)
- return nil, err
- }
- httputil.GracefulClose(resp)
- cr.picker.unreachable(u)
-
- switch strings.TrimSuffix(string(b), "\n") {
- case errIncompatibleVersion.Error():
- if cr.lg != nil {
- cr.lg.Warn(
- "request sent was ignored by remote peer due to server version incompatibility",
- zap.String("local-member-id", cr.tr.ID.String()),
- zap.String("remote-peer-id", cr.peerID.String()),
- zap.Error(errIncompatibleVersion),
- )
- } else {
- plog.Errorf("request sent was ignored by peer %s (server version incompatible)", cr.peerID)
- }
- return nil, errIncompatibleVersion
-
- case errClusterIDMismatch.Error():
- if cr.lg != nil {
- cr.lg.Warn(
- "request sent was ignored by remote peer due to cluster ID mismatch",
- zap.String("remote-peer-id", cr.peerID.String()),
- zap.String("remote-peer-cluster-id", resp.Header.Get("X-Etcd-Cluster-ID")),
- zap.String("local-member-id", cr.tr.ID.String()),
- zap.String("local-member-cluster-id", cr.tr.ClusterID.String()),
- zap.Error(errClusterIDMismatch),
- )
- } else {
- plog.Errorf("request sent was ignored (cluster ID mismatch: peer[%s]=%s, local=%s)",
- cr.peerID, resp.Header.Get("X-Etcd-Cluster-ID"), cr.tr.ClusterID)
- }
- return nil, errClusterIDMismatch
-
- default:
- return nil, fmt.Errorf("unhandled error %q when precondition failed", string(b))
- }
-
- default:
- httputil.GracefulClose(resp)
- cr.picker.unreachable(u)
- return nil, fmt.Errorf("unhandled http status %d", resp.StatusCode)
- }
-}
-
-func (cr *streamReader) close() {
- if cr.closer != nil {
- if err := cr.closer.Close(); err != nil {
- if cr.lg != nil {
- cr.lg.Warn(
- "failed to close remote peer connection",
- zap.String("local-member-id", cr.tr.ID.String()),
- zap.String("remote-peer-id", cr.peerID.String()),
- zap.Error(err),
- )
- } else {
- plog.Errorf("peer %s (reader) connection close error: %v", cr.peerID, err)
- }
- }
- }
- cr.closer = nil
-}
-
-func (cr *streamReader) pause() {
- cr.mu.Lock()
- defer cr.mu.Unlock()
- cr.paused = true
-}
-
-func (cr *streamReader) resume() {
- cr.mu.Lock()
- defer cr.mu.Unlock()
- cr.paused = false
-}
-
-// checkStreamSupport checks whether the stream type is supported in the
-// given version.
-func checkStreamSupport(v *semver.Version, t streamType) bool {
- nv := &semver.Version{Major: v.Major, Minor: v.Minor}
- for _, s := range supportedStream[nv.String()] {
- if s == t {
- return true
- }
- }
- return false
-}
diff --git a/vendor/go.etcd.io/etcd/etcdserver/api/rafthttp/transport.go b/vendor/go.etcd.io/etcd/etcdserver/api/rafthttp/transport.go
deleted file mode 100644
index 7191c3d..0000000
--- a/vendor/go.etcd.io/etcd/etcdserver/api/rafthttp/transport.go
+++ /dev/null
@@ -1,467 +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 rafthttp
-
-import (
- "context"
- "net/http"
- "sync"
- "time"
-
- "go.etcd.io/etcd/etcdserver/api/snap"
- stats "go.etcd.io/etcd/etcdserver/api/v2stats"
- "go.etcd.io/etcd/pkg/logutil"
- "go.etcd.io/etcd/pkg/transport"
- "go.etcd.io/etcd/pkg/types"
- "go.etcd.io/etcd/raft"
- "go.etcd.io/etcd/raft/raftpb"
-
- "github.com/coreos/pkg/capnslog"
- "github.com/xiang90/probing"
- "go.uber.org/zap"
- "golang.org/x/time/rate"
-)
-
-var plog = logutil.NewMergeLogger(capnslog.NewPackageLogger("go.etcd.io/etcd", "rafthttp"))
-
-type Raft interface {
- Process(ctx context.Context, m raftpb.Message) error
- IsIDRemoved(id uint64) bool
- ReportUnreachable(id uint64)
- ReportSnapshot(id uint64, status raft.SnapshotStatus)
-}
-
-type Transporter interface {
- // Start starts the given Transporter.
- // Start MUST be called before calling other functions in the interface.
- Start() error
- // Handler returns the HTTP handler of the transporter.
- // A transporter HTTP handler handles the HTTP requests
- // from remote peers.
- // The handler MUST be used to handle RaftPrefix(/raft)
- // endpoint.
- Handler() http.Handler
- // Send sends out the given messages to the remote peers.
- // Each message has a To field, which is an id that maps
- // to an existing peer in the transport.
- // If the id cannot be found in the transport, the message
- // will be ignored.
- Send(m []raftpb.Message)
- // SendSnapshot sends out the given snapshot message to a remote peer.
- // The behavior of SendSnapshot is similar to Send.
- SendSnapshot(m snap.Message)
- // AddRemote adds a remote with given peer urls into the transport.
- // A remote helps newly joined member to catch up the progress of cluster,
- // and will not be used after that.
- // It is the caller's responsibility to ensure the urls are all valid,
- // or it panics.
- AddRemote(id types.ID, urls []string)
- // AddPeer adds a peer with given peer urls into the transport.
- // It is the caller's responsibility to ensure the urls are all valid,
- // or it panics.
- // Peer urls are used to connect to the remote peer.
- AddPeer(id types.ID, urls []string)
- // RemovePeer removes the peer with given id.
- RemovePeer(id types.ID)
- // RemoveAllPeers removes all the existing peers in the transport.
- RemoveAllPeers()
- // UpdatePeer updates the peer urls of the peer with the given id.
- // It is the caller's responsibility to ensure the urls are all valid,
- // or it panics.
- UpdatePeer(id types.ID, urls []string)
- // ActiveSince returns the time that the connection with the peer
- // of the given id becomes active.
- // If the connection is active since peer was added, it returns the adding time.
- // If the connection is currently inactive, it returns zero time.
- ActiveSince(id types.ID) time.Time
- // ActivePeers returns the number of active peers.
- ActivePeers() int
- // Stop closes the connections and stops the transporter.
- Stop()
-}
-
-// Transport implements Transporter interface. It provides the functionality
-// to send raft messages to peers, and receive raft messages from peers.
-// User should call Handler method to get a handler to serve requests
-// received from peerURLs.
-// User needs to call Start before calling other functions, and call
-// Stop when the Transport is no longer used.
-type Transport struct {
- Logger *zap.Logger
-
- DialTimeout time.Duration // maximum duration before timing out dial of the request
- // DialRetryFrequency defines the frequency of streamReader dial retrial attempts;
- // a distinct rate limiter is created per every peer (default value: 10 events/sec)
- DialRetryFrequency rate.Limit
-
- TLSInfo transport.TLSInfo // TLS information used when creating connection
-
- ID types.ID // local member ID
- URLs types.URLs // local peer URLs
- ClusterID types.ID // raft cluster ID for request validation
- Raft Raft // raft state machine, to which the Transport forwards received messages and reports status
- Snapshotter *snap.Snapshotter
- ServerStats *stats.ServerStats // used to record general transportation statistics
- // used to record transportation statistics with followers when
- // performing as leader in raft protocol
- LeaderStats *stats.LeaderStats
- // ErrorC is used to report detected critical errors, e.g.,
- // the member has been permanently removed from the cluster
- // When an error is received from ErrorC, user should stop raft state
- // machine and thus stop the Transport.
- ErrorC chan error
-
- streamRt http.RoundTripper // roundTripper used by streams
- pipelineRt http.RoundTripper // roundTripper used by pipelines
-
- mu sync.RWMutex // protect the remote and peer map
- remotes map[types.ID]*remote // remotes map that helps newly joined member to catch up
- peers map[types.ID]Peer // peers map
-
- pipelineProber probing.Prober
- streamProber probing.Prober
-}
-
-func (t *Transport) Start() error {
- var err error
- t.streamRt, err = newStreamRoundTripper(t.TLSInfo, t.DialTimeout)
- if err != nil {
- return err
- }
- t.pipelineRt, err = NewRoundTripper(t.TLSInfo, t.DialTimeout)
- if err != nil {
- return err
- }
- t.remotes = make(map[types.ID]*remote)
- t.peers = make(map[types.ID]Peer)
- t.pipelineProber = probing.NewProber(t.pipelineRt)
- t.streamProber = probing.NewProber(t.streamRt)
-
- // If client didn't provide dial retry frequency, use the default
- // (100ms backoff between attempts to create a new stream),
- // so it doesn't bring too much overhead when retry.
- if t.DialRetryFrequency == 0 {
- t.DialRetryFrequency = rate.Every(100 * time.Millisecond)
- }
- return nil
-}
-
-func (t *Transport) Handler() http.Handler {
- pipelineHandler := newPipelineHandler(t, t.Raft, t.ClusterID)
- streamHandler := newStreamHandler(t, t, t.Raft, t.ID, t.ClusterID)
- snapHandler := newSnapshotHandler(t, t.Raft, t.Snapshotter, t.ClusterID)
- mux := http.NewServeMux()
- mux.Handle(RaftPrefix, pipelineHandler)
- mux.Handle(RaftStreamPrefix+"/", streamHandler)
- mux.Handle(RaftSnapshotPrefix, snapHandler)
- mux.Handle(ProbingPrefix, probing.NewHandler())
- return mux
-}
-
-func (t *Transport) Get(id types.ID) Peer {
- t.mu.RLock()
- defer t.mu.RUnlock()
- return t.peers[id]
-}
-
-func (t *Transport) Send(msgs []raftpb.Message) {
- for _, m := range msgs {
- if m.To == 0 {
- // ignore intentionally dropped message
- continue
- }
- to := types.ID(m.To)
-
- t.mu.RLock()
- p, pok := t.peers[to]
- g, rok := t.remotes[to]
- t.mu.RUnlock()
-
- if pok {
- if m.Type == raftpb.MsgApp {
- t.ServerStats.SendAppendReq(m.Size())
- }
- p.send(m)
- continue
- }
-
- if rok {
- g.send(m)
- continue
- }
-
- if t.Logger != nil {
- t.Logger.Debug(
- "ignored message send request; unknown remote peer target",
- zap.String("type", m.Type.String()),
- zap.String("unknown-target-peer-id", to.String()),
- )
- } else {
- plog.Debugf("ignored message %s (sent to unknown peer %s)", m.Type, to)
- }
- }
-}
-
-func (t *Transport) Stop() {
- t.mu.Lock()
- defer t.mu.Unlock()
- for _, r := range t.remotes {
- r.stop()
- }
- for _, p := range t.peers {
- p.stop()
- }
- t.pipelineProber.RemoveAll()
- t.streamProber.RemoveAll()
- if tr, ok := t.streamRt.(*http.Transport); ok {
- tr.CloseIdleConnections()
- }
- if tr, ok := t.pipelineRt.(*http.Transport); ok {
- tr.CloseIdleConnections()
- }
- t.peers = nil
- t.remotes = nil
-}
-
-// CutPeer drops messages to the specified peer.
-func (t *Transport) CutPeer(id types.ID) {
- t.mu.RLock()
- p, pok := t.peers[id]
- g, gok := t.remotes[id]
- t.mu.RUnlock()
-
- if pok {
- p.(Pausable).Pause()
- }
- if gok {
- g.Pause()
- }
-}
-
-// MendPeer recovers the message dropping behavior of the given peer.
-func (t *Transport) MendPeer(id types.ID) {
- t.mu.RLock()
- p, pok := t.peers[id]
- g, gok := t.remotes[id]
- t.mu.RUnlock()
-
- if pok {
- p.(Pausable).Resume()
- }
- if gok {
- g.Resume()
- }
-}
-
-func (t *Transport) AddRemote(id types.ID, us []string) {
- t.mu.Lock()
- defer t.mu.Unlock()
- if t.remotes == nil {
- // there's no clean way to shutdown the golang http server
- // (see: https://github.com/golang/go/issues/4674) before
- // stopping the transport; ignore any new connections.
- return
- }
- if _, ok := t.peers[id]; ok {
- return
- }
- if _, ok := t.remotes[id]; ok {
- return
- }
- urls, err := types.NewURLs(us)
- if err != nil {
- if t.Logger != nil {
- t.Logger.Panic("failed NewURLs", zap.Strings("urls", us), zap.Error(err))
- } else {
- plog.Panicf("newURLs %+v should never fail: %+v", us, err)
- }
- }
- t.remotes[id] = startRemote(t, urls, id)
-
- if t.Logger != nil {
- t.Logger.Info(
- "added new remote peer",
- zap.String("local-member-id", t.ID.String()),
- zap.String("remote-peer-id", id.String()),
- zap.Strings("remote-peer-urls", us),
- )
- }
-}
-
-func (t *Transport) AddPeer(id types.ID, us []string) {
- t.mu.Lock()
- defer t.mu.Unlock()
-
- if t.peers == nil {
- panic("transport stopped")
- }
- if _, ok := t.peers[id]; ok {
- return
- }
- urls, err := types.NewURLs(us)
- if err != nil {
- if t.Logger != nil {
- t.Logger.Panic("failed NewURLs", zap.Strings("urls", us), zap.Error(err))
- } else {
- plog.Panicf("newURLs %+v should never fail: %+v", us, err)
- }
- }
- fs := t.LeaderStats.Follower(id.String())
- t.peers[id] = startPeer(t, urls, id, fs)
- addPeerToProber(t.Logger, t.pipelineProber, id.String(), us, RoundTripperNameSnapshot, rttSec)
- addPeerToProber(t.Logger, t.streamProber, id.String(), us, RoundTripperNameRaftMessage, rttSec)
-
- if t.Logger != nil {
- t.Logger.Info(
- "added remote peer",
- zap.String("local-member-id", t.ID.String()),
- zap.String("remote-peer-id", id.String()),
- zap.Strings("remote-peer-urls", us),
- )
- } else {
- plog.Infof("added peer %s", id)
- }
-}
-
-func (t *Transport) RemovePeer(id types.ID) {
- t.mu.Lock()
- defer t.mu.Unlock()
- t.removePeer(id)
-}
-
-func (t *Transport) RemoveAllPeers() {
- t.mu.Lock()
- defer t.mu.Unlock()
- for id := range t.peers {
- t.removePeer(id)
- }
-}
-
-// the caller of this function must have the peers mutex.
-func (t *Transport) removePeer(id types.ID) {
- if peer, ok := t.peers[id]; ok {
- peer.stop()
- } else {
- if t.Logger != nil {
- t.Logger.Panic("unexpected removal of unknown remote peer", zap.String("remote-peer-id", id.String()))
- } else {
- plog.Panicf("unexpected removal of unknown peer '%d'", id)
- }
- }
- 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()),
- )
- } else {
- plog.Infof("removed peer %s", id)
- }
-}
-
-func (t *Transport) UpdatePeer(id types.ID, us []string) {
- t.mu.Lock()
- defer t.mu.Unlock()
- // TODO: return error or just panic?
- if _, ok := t.peers[id]; !ok {
- return
- }
- urls, err := types.NewURLs(us)
- if err != nil {
- if t.Logger != nil {
- t.Logger.Panic("failed NewURLs", zap.Strings("urls", us), zap.Error(err))
- } else {
- plog.Panicf("newURLs %+v should never fail: %+v", us, err)
- }
- }
- t.peers[id].update(urls)
-
- t.pipelineProber.Remove(id.String())
- addPeerToProber(t.Logger, t.pipelineProber, id.String(), us, RoundTripperNameSnapshot, rttSec)
- t.streamProber.Remove(id.String())
- addPeerToProber(t.Logger, t.streamProber, id.String(), us, RoundTripperNameRaftMessage, rttSec)
-
- if t.Logger != nil {
- t.Logger.Info(
- "updated remote peer",
- zap.String("local-member-id", t.ID.String()),
- zap.String("updated-remote-peer-id", id.String()),
- zap.Strings("updated-remote-peer-urls", us),
- )
- } else {
- plog.Infof("updated peer %s", id)
- }
-}
-
-func (t *Transport) ActiveSince(id types.ID) time.Time {
- t.mu.RLock()
- defer t.mu.RUnlock()
- if p, ok := t.peers[id]; ok {
- return p.activeSince()
- }
- return time.Time{}
-}
-
-func (t *Transport) SendSnapshot(m snap.Message) {
- t.mu.Lock()
- defer t.mu.Unlock()
- p := t.peers[types.ID(m.To)]
- if p == nil {
- m.CloseWithError(errMemberNotFound)
- return
- }
- p.sendSnap(m)
-}
-
-// Pausable is a testing interface for pausing transport traffic.
-type Pausable interface {
- Pause()
- Resume()
-}
-
-func (t *Transport) Pause() {
- t.mu.RLock()
- defer t.mu.RUnlock()
- for _, p := range t.peers {
- p.(Pausable).Pause()
- }
-}
-
-func (t *Transport) Resume() {
- t.mu.RLock()
- defer t.mu.RUnlock()
- for _, p := range t.peers {
- p.(Pausable).Resume()
- }
-}
-
-// ActivePeers returns a channel that closes when an initial
-// peer connection has been established. Use this to wait until the
-// first peer connection becomes active.
-func (t *Transport) ActivePeers() (cnt int) {
- t.mu.RLock()
- defer t.mu.RUnlock()
- for _, p := range t.peers {
- if !p.activeSince().IsZero() {
- cnt++
- }
- }
- return cnt
-}
diff --git a/vendor/go.etcd.io/etcd/etcdserver/api/rafthttp/urlpick.go b/vendor/go.etcd.io/etcd/etcdserver/api/rafthttp/urlpick.go
deleted file mode 100644
index 61ef468..0000000
--- a/vendor/go.etcd.io/etcd/etcdserver/api/rafthttp/urlpick.go
+++ /dev/null
@@ -1,57 +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 rafthttp
-
-import (
- "net/url"
- "sync"
-
- "go.etcd.io/etcd/pkg/types"
-)
-
-type urlPicker struct {
- mu sync.Mutex // guards urls and picked
- urls types.URLs
- picked int
-}
-
-func newURLPicker(urls types.URLs) *urlPicker {
- return &urlPicker{
- urls: urls,
- }
-}
-
-func (p *urlPicker) update(urls types.URLs) {
- p.mu.Lock()
- defer p.mu.Unlock()
- p.urls = urls
- p.picked = 0
-}
-
-func (p *urlPicker) pick() url.URL {
- p.mu.Lock()
- defer p.mu.Unlock()
- return p.urls[p.picked]
-}
-
-// unreachable notices the picker that the given url is unreachable,
-// and it should use other possible urls.
-func (p *urlPicker) unreachable(u url.URL) {
- p.mu.Lock()
- defer p.mu.Unlock()
- if u == p.urls[p.picked] {
- p.picked = (p.picked + 1) % len(p.urls)
- }
-}
diff --git a/vendor/go.etcd.io/etcd/etcdserver/api/rafthttp/util.go b/vendor/go.etcd.io/etcd/etcdserver/api/rafthttp/util.go
deleted file mode 100644
index 2093864..0000000
--- a/vendor/go.etcd.io/etcd/etcdserver/api/rafthttp/util.go
+++ /dev/null
@@ -1,190 +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 rafthttp
-
-import (
- "fmt"
- "io"
- "net"
- "net/http"
- "net/url"
- "strings"
- "time"
-
- "go.etcd.io/etcd/pkg/transport"
- "go.etcd.io/etcd/pkg/types"
- "go.etcd.io/etcd/version"
-
- "github.com/coreos/go-semver/semver"
-)
-
-var (
- errMemberRemoved = fmt.Errorf("the member has been permanently removed from the cluster")
- errMemberNotFound = fmt.Errorf("member not found")
-)
-
-// NewListener returns a listener for raft message transfer between peers.
-// It uses timeout listener to identify broken streams promptly.
-func NewListener(u url.URL, tlsinfo *transport.TLSInfo) (net.Listener, error) {
- return transport.NewTimeoutListener(u.Host, u.Scheme, tlsinfo, ConnReadTimeout, ConnWriteTimeout)
-}
-
-// NewRoundTripper returns a roundTripper used to send requests
-// to rafthttp listener of remote peers.
-func NewRoundTripper(tlsInfo transport.TLSInfo, dialTimeout time.Duration) (http.RoundTripper, error) {
- // It uses timeout transport to pair with remote timeout listeners.
- // It sets no read/write timeout, because message in requests may
- // take long time to write out before reading out the response.
- return transport.NewTimeoutTransport(tlsInfo, dialTimeout, 0, 0)
-}
-
-// newStreamRoundTripper returns a roundTripper used to send stream requests
-// to rafthttp listener of remote peers.
-// Read/write timeout is set for stream roundTripper to promptly
-// find out broken status, which minimizes the number of messages
-// sent on broken connection.
-func newStreamRoundTripper(tlsInfo transport.TLSInfo, dialTimeout time.Duration) (http.RoundTripper, error) {
- return transport.NewTimeoutTransport(tlsInfo, dialTimeout, ConnReadTimeout, ConnWriteTimeout)
-}
-
-// createPostRequest creates a HTTP POST request that sends raft message.
-func createPostRequest(u url.URL, path string, body io.Reader, ct string, urls types.URLs, from, cid types.ID) *http.Request {
- uu := u
- uu.Path = path
- req, err := http.NewRequest("POST", uu.String(), body)
- if err != nil {
- plog.Panicf("unexpected new request error (%v)", err)
- }
- req.Header.Set("Content-Type", ct)
- req.Header.Set("X-Server-From", from.String())
- req.Header.Set("X-Server-Version", version.Version)
- req.Header.Set("X-Min-Cluster-Version", version.MinClusterVersion)
- req.Header.Set("X-Etcd-Cluster-ID", cid.String())
- setPeerURLsHeader(req, urls)
-
- return req
-}
-
-// checkPostResponse checks the response of the HTTP POST request that sends
-// raft message.
-func checkPostResponse(resp *http.Response, body []byte, req *http.Request, to types.ID) error {
- switch resp.StatusCode {
- case http.StatusPreconditionFailed:
- switch strings.TrimSuffix(string(body), "\n") {
- case errIncompatibleVersion.Error():
- plog.Errorf("request sent was ignored by peer %s (server version incompatible)", to)
- return errIncompatibleVersion
- case errClusterIDMismatch.Error():
- plog.Errorf("request sent was ignored (cluster ID mismatch: remote[%s]=%s, local=%s)",
- to, resp.Header.Get("X-Etcd-Cluster-ID"), req.Header.Get("X-Etcd-Cluster-ID"))
- return errClusterIDMismatch
- default:
- return fmt.Errorf("unhandled error %q when precondition failed", string(body))
- }
- case http.StatusForbidden:
- return errMemberRemoved
- case http.StatusNoContent:
- return nil
- default:
- return fmt.Errorf("unexpected http status %s while posting to %q", http.StatusText(resp.StatusCode), req.URL.String())
- }
-}
-
-// reportCriticalError reports the given error through sending it into
-// the given error channel.
-// If the error channel is filled up when sending error, it drops the error
-// because the fact that error has happened is reported, which is
-// good enough.
-func reportCriticalError(err error, errc chan<- error) {
- select {
- case errc <- err:
- default:
- }
-}
-
-// compareMajorMinorVersion returns an integer comparing two versions based on
-// their major and minor version. The result will be 0 if a==b, -1 if a < b,
-// and 1 if a > b.
-func compareMajorMinorVersion(a, b *semver.Version) int {
- na := &semver.Version{Major: a.Major, Minor: a.Minor}
- nb := &semver.Version{Major: b.Major, Minor: b.Minor}
- switch {
- case na.LessThan(*nb):
- return -1
- case nb.LessThan(*na):
- return 1
- default:
- return 0
- }
-}
-
-// serverVersion returns the server version from the given header.
-func serverVersion(h http.Header) *semver.Version {
- verStr := h.Get("X-Server-Version")
- // backward compatibility with etcd 2.0
- if verStr == "" {
- verStr = "2.0.0"
- }
- return semver.Must(semver.NewVersion(verStr))
-}
-
-// serverVersion returns the min cluster version from the given header.
-func minClusterVersion(h http.Header) *semver.Version {
- verStr := h.Get("X-Min-Cluster-Version")
- // backward compatibility with etcd 2.0
- if verStr == "" {
- verStr = "2.0.0"
- }
- return semver.Must(semver.NewVersion(verStr))
-}
-
-// checkVersionCompatibility checks whether the given version is compatible
-// with the local version.
-func checkVersionCompatibility(name string, server, minCluster *semver.Version) (
- localServer *semver.Version,
- localMinCluster *semver.Version,
- err error) {
- localServer = semver.Must(semver.NewVersion(version.Version))
- localMinCluster = semver.Must(semver.NewVersion(version.MinClusterVersion))
- if compareMajorMinorVersion(server, localMinCluster) == -1 {
- return localServer, localMinCluster, fmt.Errorf("remote version is too low: remote[%s]=%s, local=%s", name, server, localServer)
- }
- if compareMajorMinorVersion(minCluster, localServer) == 1 {
- return localServer, localMinCluster, fmt.Errorf("local version is too low: remote[%s]=%s, local=%s", name, server, localServer)
- }
- return localServer, localMinCluster, nil
-}
-
-// setPeerURLsHeader reports local urls for peer discovery
-func setPeerURLsHeader(req *http.Request, urls types.URLs) {
- if urls == nil {
- // often not set in unit tests
- return
- }
- peerURLs := make([]string, urls.Len())
- for i := range urls {
- peerURLs[i] = urls[i].String()
- }
- req.Header.Set("X-PeerURLs", strings.Join(peerURLs, ","))
-}
-
-// addRemoteFromRequest adds a remote peer according to an http request header
-func addRemoteFromRequest(tr Transporter, r *http.Request) {
- if from, err := types.IDFromString(r.Header.Get("X-Server-From")); err == nil {
- if urls := r.Header.Get("X-PeerURLs"); urls != "" {
- tr.AddRemote(from, strings.Split(urls, ","))
- }
- }
-}
diff --git a/vendor/go.etcd.io/etcd/etcdserver/api/snap/db.go b/vendor/go.etcd.io/etcd/etcdserver/api/snap/db.go
deleted file mode 100644
index 3002ccd..0000000
--- a/vendor/go.etcd.io/etcd/etcdserver/api/snap/db.go
+++ /dev/null
@@ -1,104 +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 snap
-
-import (
- "errors"
- "fmt"
- "io"
- "io/ioutil"
- "os"
- "path/filepath"
- "time"
-
- "go.etcd.io/etcd/pkg/fileutil"
-
- humanize "github.com/dustin/go-humanize"
- "go.uber.org/zap"
-)
-
-var ErrNoDBSnapshot = errors.New("snap: snapshot file doesn't exist")
-
-// SaveDBFrom saves snapshot of the database from the given reader. It
-// guarantees the save operation is atomic.
-func (s *Snapshotter) SaveDBFrom(r io.Reader, id uint64) (int64, error) {
- start := time.Now()
-
- f, err := ioutil.TempFile(s.dir, "tmp")
- if err != nil {
- return 0, err
- }
- var n int64
- n, err = io.Copy(f, r)
- if err == nil {
- fsyncStart := time.Now()
- err = fileutil.Fsync(f)
- snapDBFsyncSec.Observe(time.Since(fsyncStart).Seconds())
- }
- f.Close()
- if err != nil {
- os.Remove(f.Name())
- return n, err
- }
- fn := s.dbFilePath(id)
- if fileutil.Exist(fn) {
- os.Remove(f.Name())
- return n, nil
- }
- err = os.Rename(f.Name(), fn)
- if err != nil {
- os.Remove(f.Name())
- return n, err
- }
-
- if s.lg != nil {
- s.lg.Info(
- "saved database snapshot to disk",
- zap.String("path", fn),
- zap.Int64("bytes", n),
- zap.String("size", humanize.Bytes(uint64(n))),
- )
- } else {
- plog.Infof("saved database snapshot to disk [total bytes: %d]", n)
- }
-
- snapDBSaveSec.Observe(time.Since(start).Seconds())
- return n, nil
-}
-
-// DBFilePath returns the file path for the snapshot of the database with
-// given id. If the snapshot does not exist, it returns error.
-func (s *Snapshotter) DBFilePath(id uint64) (string, error) {
- if _, err := fileutil.ReadDir(s.dir); err != nil {
- return "", err
- }
- fn := s.dbFilePath(id)
- if fileutil.Exist(fn) {
- return fn, nil
- }
- if s.lg != nil {
- s.lg.Warn(
- "failed to find [SNAPSHOT-INDEX].snap.db",
- zap.Uint64("snapshot-index", id),
- zap.String("snapshot-file-path", fn),
- zap.Error(ErrNoDBSnapshot),
- )
- }
- return "", ErrNoDBSnapshot
-}
-
-func (s *Snapshotter) dbFilePath(id uint64) string {
- return filepath.Join(s.dir, fmt.Sprintf("%016x.snap.db", id))
-}
diff --git a/vendor/go.etcd.io/etcd/etcdserver/api/snap/doc.go b/vendor/go.etcd.io/etcd/etcdserver/api/snap/doc.go
deleted file mode 100644
index dcc5db5..0000000
--- a/vendor/go.etcd.io/etcd/etcdserver/api/snap/doc.go
+++ /dev/null
@@ -1,17 +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 snap handles Raft nodes' states with snapshots.
-// The snapshot logic is internal to etcd server and raft package.
-package snap
diff --git a/vendor/go.etcd.io/etcd/etcdserver/api/snap/message.go b/vendor/go.etcd.io/etcd/etcdserver/api/snap/message.go
deleted file mode 100644
index c1151e2..0000000
--- a/vendor/go.etcd.io/etcd/etcdserver/api/snap/message.go
+++ /dev/null
@@ -1,64 +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 snap
-
-import (
- "io"
-
- "go.etcd.io/etcd/pkg/ioutil"
- "go.etcd.io/etcd/raft/raftpb"
-)
-
-// Message is a struct that contains a raft Message and a ReadCloser. The type
-// of raft message MUST be MsgSnap, which contains the raft meta-data and an
-// additional data []byte field that contains the snapshot of the actual state
-// machine.
-// Message contains the ReadCloser field for handling large snapshot. This avoid
-// copying the entire snapshot into a byte array, which consumes a lot of memory.
-//
-// User of Message should close the Message after sending it.
-type Message struct {
- raftpb.Message
- ReadCloser io.ReadCloser
- TotalSize int64
- closeC chan bool
-}
-
-func NewMessage(rs raftpb.Message, rc io.ReadCloser, rcSize int64) *Message {
- return &Message{
- Message: rs,
- ReadCloser: ioutil.NewExactReadCloser(rc, rcSize),
- TotalSize: int64(rs.Size()) + rcSize,
- closeC: make(chan bool, 1),
- }
-}
-
-// CloseNotify returns a channel that receives a single value
-// when the message sent is finished. true indicates the sent
-// is successful.
-func (m Message) CloseNotify() <-chan bool {
- return m.closeC
-}
-
-func (m Message) CloseWithError(err error) {
- if cerr := m.ReadCloser.Close(); cerr != nil {
- err = cerr
- }
- if err == nil {
- m.closeC <- true
- } else {
- m.closeC <- false
- }
-}
diff --git a/vendor/go.etcd.io/etcd/etcdserver/api/snap/metrics.go b/vendor/go.etcd.io/etcd/etcdserver/api/snap/metrics.go
deleted file mode 100644
index 2affecf..0000000
--- a/vendor/go.etcd.io/etcd/etcdserver/api/snap/metrics.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 snap
-
-import "github.com/prometheus/client_golang/prometheus"
-
-var (
- snapMarshallingSec = prometheus.NewHistogram(prometheus.HistogramOpts{
- Namespace: "etcd_debugging",
- Subsystem: "snap",
- Name: "save_marshalling_duration_seconds",
- Help: "The marshalling cost distributions of save called by snapshot.",
-
- // lowest bucket start of upper bound 0.001 sec (1 ms) with factor 2
- // highest bucket start of 0.001 sec * 2^13 == 8.192 sec
- Buckets: prometheus.ExponentialBuckets(0.001, 2, 14),
- })
-
- snapSaveSec = prometheus.NewHistogram(prometheus.HistogramOpts{
- Namespace: "etcd_debugging",
- Subsystem: "snap",
- Name: "save_total_duration_seconds",
- Help: "The total latency distributions of save called by snapshot.",
-
- // lowest bucket start of upper bound 0.001 sec (1 ms) with factor 2
- // highest bucket start of 0.001 sec * 2^13 == 8.192 sec
- Buckets: prometheus.ExponentialBuckets(0.001, 2, 14),
- })
-
- snapFsyncSec = prometheus.NewHistogram(prometheus.HistogramOpts{
- Namespace: "etcd",
- Subsystem: "snap",
- Name: "fsync_duration_seconds",
- Help: "The latency distributions of fsync called by snap.",
-
- // lowest bucket start of upper bound 0.001 sec (1 ms) with factor 2
- // highest bucket start of 0.001 sec * 2^13 == 8.192 sec
- Buckets: prometheus.ExponentialBuckets(0.001, 2, 14),
- })
-
- snapDBSaveSec = prometheus.NewHistogram(prometheus.HistogramOpts{
- Namespace: "etcd",
- Subsystem: "snap_db",
- Name: "save_total_duration_seconds",
- Help: "The total latency distributions of v3 snapshot save",
-
- // lowest bucket start of upper bound 0.1 sec (100 ms) with factor 2
- // highest bucket start of 0.1 sec * 2^9 == 51.2 sec
- Buckets: prometheus.ExponentialBuckets(0.1, 2, 10),
- })
-
- snapDBFsyncSec = prometheus.NewHistogram(prometheus.HistogramOpts{
- Namespace: "etcd",
- Subsystem: "snap_db",
- Name: "fsync_duration_seconds",
- Help: "The latency distributions of fsyncing .snap.db file",
-
- // lowest bucket start of upper bound 0.001 sec (1 ms) with factor 2
- // highest bucket start of 0.001 sec * 2^13 == 8.192 sec
- Buckets: prometheus.ExponentialBuckets(0.001, 2, 14),
- })
-)
-
-func init() {
- prometheus.MustRegister(snapMarshallingSec)
- prometheus.MustRegister(snapSaveSec)
- prometheus.MustRegister(snapFsyncSec)
- prometheus.MustRegister(snapDBSaveSec)
- prometheus.MustRegister(snapDBFsyncSec)
-}
diff --git a/vendor/go.etcd.io/etcd/etcdserver/api/snap/snappb/snap.pb.go b/vendor/go.etcd.io/etcd/etcdserver/api/snap/snappb/snap.pb.go
deleted file mode 100644
index e72b577..0000000
--- a/vendor/go.etcd.io/etcd/etcdserver/api/snap/snappb/snap.pb.go
+++ /dev/null
@@ -1,336 +0,0 @@
-// Code generated by protoc-gen-gogo. DO NOT EDIT.
-// source: snap.proto
-
-/*
- Package snappb is a generated protocol buffer package.
-
- It is generated from these files:
- snap.proto
-
- It has these top-level messages:
- Snapshot
-*/
-package snappb
-
-import (
- "fmt"
-
- proto "github.com/golang/protobuf/proto"
-
- math "math"
-
- _ "github.com/gogo/protobuf/gogoproto"
-
- io "io"
-)
-
-// Reference imports to suppress errors if they are not otherwise used.
-var _ = proto.Marshal
-var _ = fmt.Errorf
-var _ = math.Inf
-
-// This is a compile-time assertion to ensure that this generated file
-// is compatible with the proto package it is being compiled against.
-// A compilation error at this line likely means your copy of the
-// proto package needs to be updated.
-const _ = proto.ProtoPackageIsVersion2 // please upgrade the proto package
-
-type Snapshot struct {
- Crc uint32 `protobuf:"varint,1,opt,name=crc" json:"crc"`
- Data []byte `protobuf:"bytes,2,opt,name=data" json:"data,omitempty"`
- XXX_unrecognized []byte `json:"-"`
-}
-
-func (m *Snapshot) Reset() { *m = Snapshot{} }
-func (m *Snapshot) String() string { return proto.CompactTextString(m) }
-func (*Snapshot) ProtoMessage() {}
-func (*Snapshot) Descriptor() ([]byte, []int) { return fileDescriptorSnap, []int{0} }
-
-func init() {
- proto.RegisterType((*Snapshot)(nil), "snappb.snapshot")
-}
-func (m *Snapshot) Marshal() (dAtA []byte, err error) {
- size := m.Size()
- dAtA = make([]byte, size)
- n, err := m.MarshalTo(dAtA)
- if err != nil {
- return nil, err
- }
- return dAtA[:n], nil
-}
-
-func (m *Snapshot) MarshalTo(dAtA []byte) (int, error) {
- var i int
- _ = i
- var l int
- _ = l
- dAtA[i] = 0x8
- i++
- i = encodeVarintSnap(dAtA, i, uint64(m.Crc))
- if m.Data != nil {
- dAtA[i] = 0x12
- i++
- i = encodeVarintSnap(dAtA, i, uint64(len(m.Data)))
- i += copy(dAtA[i:], m.Data)
- }
- if m.XXX_unrecognized != nil {
- i += copy(dAtA[i:], m.XXX_unrecognized)
- }
- return i, nil
-}
-
-func encodeVarintSnap(dAtA []byte, offset int, v uint64) int {
- for v >= 1<<7 {
- dAtA[offset] = uint8(v&0x7f | 0x80)
- v >>= 7
- offset++
- }
- dAtA[offset] = uint8(v)
- return offset + 1
-}
-func (m *Snapshot) Size() (n int) {
- var l int
- _ = l
- n += 1 + sovSnap(uint64(m.Crc))
- if m.Data != nil {
- l = len(m.Data)
- n += 1 + l + sovSnap(uint64(l))
- }
- if m.XXX_unrecognized != nil {
- n += len(m.XXX_unrecognized)
- }
- return n
-}
-
-func sovSnap(x uint64) (n int) {
- for {
- n++
- x >>= 7
- if x == 0 {
- break
- }
- }
- return n
-}
-func sozSnap(x uint64) (n int) {
- return sovSnap(uint64((x << 1) ^ uint64((int64(x) >> 63))))
-}
-func (m *Snapshot) Unmarshal(dAtA []byte) error {
- l := len(dAtA)
- iNdEx := 0
- for iNdEx < l {
- preIndex := iNdEx
- var wire uint64
- for shift := uint(0); ; shift += 7 {
- if shift >= 64 {
- return ErrIntOverflowSnap
- }
- if iNdEx >= l {
- return io.ErrUnexpectedEOF
- }
- b := dAtA[iNdEx]
- iNdEx++
- wire |= (uint64(b) & 0x7F) << shift
- if b < 0x80 {
- break
- }
- }
- fieldNum := int32(wire >> 3)
- wireType := int(wire & 0x7)
- if wireType == 4 {
- return fmt.Errorf("proto: snapshot: wiretype end group for non-group")
- }
- if fieldNum <= 0 {
- return fmt.Errorf("proto: snapshot: illegal tag %d (wire type %d)", fieldNum, wire)
- }
- switch fieldNum {
- case 1:
- if wireType != 0 {
- return fmt.Errorf("proto: wrong wireType = %d for field Crc", wireType)
- }
- m.Crc = 0
- for shift := uint(0); ; shift += 7 {
- if shift >= 64 {
- return ErrIntOverflowSnap
- }
- if iNdEx >= l {
- return io.ErrUnexpectedEOF
- }
- b := dAtA[iNdEx]
- iNdEx++
- m.Crc |= (uint32(b) & 0x7F) << shift
- if b < 0x80 {
- break
- }
- }
- case 2:
- if wireType != 2 {
- return fmt.Errorf("proto: wrong wireType = %d for field Data", wireType)
- }
- var byteLen int
- for shift := uint(0); ; shift += 7 {
- if shift >= 64 {
- return ErrIntOverflowSnap
- }
- if iNdEx >= l {
- return io.ErrUnexpectedEOF
- }
- b := dAtA[iNdEx]
- iNdEx++
- byteLen |= (int(b) & 0x7F) << shift
- if b < 0x80 {
- break
- }
- }
- if byteLen < 0 {
- return ErrInvalidLengthSnap
- }
- postIndex := iNdEx + byteLen
- if postIndex > l {
- return io.ErrUnexpectedEOF
- }
- m.Data = append(m.Data[:0], dAtA[iNdEx:postIndex]...)
- if m.Data == nil {
- m.Data = []byte{}
- }
- iNdEx = postIndex
- default:
- iNdEx = preIndex
- skippy, err := skipSnap(dAtA[iNdEx:])
- if err != nil {
- return err
- }
- if skippy < 0 {
- return ErrInvalidLengthSnap
- }
- if (iNdEx + skippy) > l {
- return io.ErrUnexpectedEOF
- }
- m.XXX_unrecognized = append(m.XXX_unrecognized, dAtA[iNdEx:iNdEx+skippy]...)
- iNdEx += skippy
- }
- }
-
- if iNdEx > l {
- return io.ErrUnexpectedEOF
- }
- return nil
-}
-func skipSnap(dAtA []byte) (n int, err error) {
- l := len(dAtA)
- iNdEx := 0
- for iNdEx < l {
- var wire uint64
- for shift := uint(0); ; shift += 7 {
- if shift >= 64 {
- return 0, ErrIntOverflowSnap
- }
- if iNdEx >= l {
- return 0, io.ErrUnexpectedEOF
- }
- b := dAtA[iNdEx]
- iNdEx++
- wire |= (uint64(b) & 0x7F) << shift
- if b < 0x80 {
- break
- }
- }
- wireType := int(wire & 0x7)
- switch wireType {
- case 0:
- for shift := uint(0); ; shift += 7 {
- if shift >= 64 {
- return 0, ErrIntOverflowSnap
- }
- if iNdEx >= l {
- return 0, io.ErrUnexpectedEOF
- }
- iNdEx++
- if dAtA[iNdEx-1] < 0x80 {
- break
- }
- }
- return iNdEx, nil
- case 1:
- iNdEx += 8
- return iNdEx, nil
- case 2:
- var length int
- for shift := uint(0); ; shift += 7 {
- if shift >= 64 {
- return 0, ErrIntOverflowSnap
- }
- if iNdEx >= l {
- return 0, io.ErrUnexpectedEOF
- }
- b := dAtA[iNdEx]
- iNdEx++
- length |= (int(b) & 0x7F) << shift
- if b < 0x80 {
- break
- }
- }
- iNdEx += length
- if length < 0 {
- return 0, ErrInvalidLengthSnap
- }
- return iNdEx, nil
- case 3:
- for {
- var innerWire uint64
- var start int = iNdEx
- for shift := uint(0); ; shift += 7 {
- if shift >= 64 {
- return 0, ErrIntOverflowSnap
- }
- if iNdEx >= l {
- return 0, io.ErrUnexpectedEOF
- }
- b := dAtA[iNdEx]
- iNdEx++
- innerWire |= (uint64(b) & 0x7F) << shift
- if b < 0x80 {
- break
- }
- }
- innerWireType := int(innerWire & 0x7)
- if innerWireType == 4 {
- break
- }
- next, err := skipSnap(dAtA[start:])
- if err != nil {
- return 0, err
- }
- iNdEx = start + next
- }
- return iNdEx, nil
- case 4:
- return iNdEx, nil
- case 5:
- iNdEx += 4
- return iNdEx, nil
- default:
- return 0, fmt.Errorf("proto: illegal wireType %d", wireType)
- }
- }
- panic("unreachable")
-}
-
-var (
- ErrInvalidLengthSnap = fmt.Errorf("proto: negative length found during unmarshaling")
- ErrIntOverflowSnap = fmt.Errorf("proto: integer overflow")
-)
-
-func init() { proto.RegisterFile("snap.proto", fileDescriptorSnap) }
-
-var fileDescriptorSnap = []byte{
- // 126 bytes of a gzipped FileDescriptorProto
- 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xe2, 0xe2, 0x2a, 0xce, 0x4b, 0x2c,
- 0xd0, 0x2b, 0x28, 0xca, 0x2f, 0xc9, 0x17, 0x62, 0x03, 0xb1, 0x0b, 0x92, 0xa4, 0x44, 0xd2, 0xf3,
- 0xd3, 0xf3, 0xc1, 0x42, 0xfa, 0x20, 0x16, 0x44, 0x56, 0xc9, 0x8c, 0x8b, 0x03, 0x24, 0x5f, 0x9c,
- 0x91, 0x5f, 0x22, 0x24, 0xc6, 0xc5, 0x9c, 0x5c, 0x94, 0x2c, 0xc1, 0xa8, 0xc0, 0xa8, 0xc1, 0xeb,
- 0xc4, 0x72, 0xe2, 0x9e, 0x3c, 0x43, 0x10, 0x48, 0x40, 0x48, 0x88, 0x8b, 0x25, 0x25, 0xb1, 0x24,
- 0x51, 0x82, 0x49, 0x81, 0x51, 0x83, 0x27, 0x08, 0xcc, 0x76, 0x12, 0x39, 0xf1, 0x50, 0x8e, 0xe1,
- 0xc4, 0x23, 0x39, 0xc6, 0x0b, 0x8f, 0xe4, 0x18, 0x1f, 0x3c, 0x92, 0x63, 0x9c, 0xf1, 0x58, 0x8e,
- 0x01, 0x10, 0x00, 0x00, 0xff, 0xff, 0xd8, 0x0f, 0x32, 0xb2, 0x78, 0x00, 0x00, 0x00,
-}
diff --git a/vendor/go.etcd.io/etcd/etcdserver/api/snap/snappb/snap.proto b/vendor/go.etcd.io/etcd/etcdserver/api/snap/snappb/snap.proto
deleted file mode 100644
index cd3d21d..0000000
--- a/vendor/go.etcd.io/etcd/etcdserver/api/snap/snappb/snap.proto
+++ /dev/null
@@ -1,14 +0,0 @@
-syntax = "proto2";
-package snappb;
-
-import "gogoproto/gogo.proto";
-
-option (gogoproto.marshaler_all) = true;
-option (gogoproto.sizer_all) = true;
-option (gogoproto.unmarshaler_all) = true;
-option (gogoproto.goproto_getters_all) = false;
-
-message snapshot {
- optional uint32 crc = 1 [(gogoproto.nullable) = false];
- optional bytes data = 2;
-}
diff --git a/vendor/go.etcd.io/etcd/etcdserver/api/snap/snapshotter.go b/vendor/go.etcd.io/etcd/etcdserver/api/snap/snapshotter.go
deleted file mode 100644
index 7e79333..0000000
--- a/vendor/go.etcd.io/etcd/etcdserver/api/snap/snapshotter.go
+++ /dev/null
@@ -1,255 +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 snap
-
-import (
- "errors"
- "fmt"
- "hash/crc32"
- "io/ioutil"
- "os"
- "path/filepath"
- "sort"
- "strings"
- "time"
-
- "go.etcd.io/etcd/etcdserver/api/snap/snappb"
- pioutil "go.etcd.io/etcd/pkg/ioutil"
- "go.etcd.io/etcd/pkg/pbutil"
- "go.etcd.io/etcd/raft"
- "go.etcd.io/etcd/raft/raftpb"
-
- "github.com/coreos/pkg/capnslog"
- "go.uber.org/zap"
-)
-
-const snapSuffix = ".snap"
-
-var (
- plog = capnslog.NewPackageLogger("go.etcd.io/etcd/v3", "snap")
-
- ErrNoSnapshot = errors.New("snap: no available snapshot")
- ErrEmptySnapshot = errors.New("snap: empty snapshot")
- ErrCRCMismatch = errors.New("snap: crc mismatch")
- crcTable = crc32.MakeTable(crc32.Castagnoli)
-
- // A map of valid files that can be present in the snap folder.
- validFiles = map[string]bool{
- "db": true,
- }
-)
-
-type Snapshotter struct {
- lg *zap.Logger
- dir string
-}
-
-func New(lg *zap.Logger, dir string) *Snapshotter {
- return &Snapshotter{
- lg: lg,
- dir: dir,
- }
-}
-
-func (s *Snapshotter) SaveSnap(snapshot raftpb.Snapshot) error {
- if raft.IsEmptySnap(snapshot) {
- return nil
- }
- return s.save(&snapshot)
-}
-
-func (s *Snapshotter) save(snapshot *raftpb.Snapshot) error {
- start := time.Now()
-
- fname := fmt.Sprintf("%016x-%016x%s", snapshot.Metadata.Term, snapshot.Metadata.Index, snapSuffix)
- b := pbutil.MustMarshal(snapshot)
- crc := crc32.Update(0, crcTable, b)
- snap := snappb.Snapshot{Crc: crc, Data: b}
- d, err := snap.Marshal()
- if err != nil {
- return err
- }
- snapMarshallingSec.Observe(time.Since(start).Seconds())
-
- spath := filepath.Join(s.dir, fname)
-
- fsyncStart := time.Now()
- err = pioutil.WriteAndSyncFile(spath, d, 0666)
- snapFsyncSec.Observe(time.Since(fsyncStart).Seconds())
-
- if err != nil {
- if s.lg != nil {
- s.lg.Warn("failed to write a snap file", zap.String("path", spath), zap.Error(err))
- }
- rerr := os.Remove(spath)
- if rerr != nil {
- if s.lg != nil {
- s.lg.Warn("failed to remove a broken snap file", zap.String("path", spath), zap.Error(err))
- } else {
- plog.Errorf("failed to remove broken snapshot file %s", spath)
- }
- }
- return err
- }
-
- snapSaveSec.Observe(time.Since(start).Seconds())
- return nil
-}
-
-func (s *Snapshotter) Load() (*raftpb.Snapshot, error) {
- names, err := s.snapNames()
- if err != nil {
- return nil, err
- }
- var snap *raftpb.Snapshot
- for _, name := range names {
- if snap, err = loadSnap(s.lg, s.dir, name); err == nil {
- break
- }
- }
- if err != nil {
- return nil, ErrNoSnapshot
- }
- return snap, nil
-}
-
-func loadSnap(lg *zap.Logger, dir, name string) (*raftpb.Snapshot, error) {
- fpath := filepath.Join(dir, name)
- snap, err := Read(lg, fpath)
- if err != nil {
- brokenPath := fpath + ".broken"
- if lg != nil {
- lg.Warn("failed to read a snap file", zap.String("path", fpath), zap.Error(err))
- }
- if rerr := os.Rename(fpath, brokenPath); rerr != nil {
- if lg != nil {
- lg.Warn("failed to rename a broken snap file", zap.String("path", fpath), zap.String("broken-path", brokenPath), zap.Error(rerr))
- } else {
- plog.Warningf("cannot rename broken snapshot file %v to %v: %v", fpath, brokenPath, rerr)
- }
- } else {
- if lg != nil {
- lg.Warn("renamed to a broken snap file", zap.String("path", fpath), zap.String("broken-path", brokenPath))
- }
- }
- }
- return snap, err
-}
-
-// Read reads the snapshot named by snapname and returns the snapshot.
-func Read(lg *zap.Logger, snapname string) (*raftpb.Snapshot, error) {
- b, err := ioutil.ReadFile(snapname)
- if err != nil {
- if lg != nil {
- lg.Warn("failed to read a snap file", zap.String("path", snapname), zap.Error(err))
- } else {
- plog.Errorf("cannot read file %v: %v", snapname, err)
- }
- return nil, err
- }
-
- if len(b) == 0 {
- if lg != nil {
- lg.Warn("failed to read empty snapshot file", zap.String("path", snapname))
- } else {
- plog.Errorf("unexpected empty snapshot")
- }
- return nil, ErrEmptySnapshot
- }
-
- var serializedSnap snappb.Snapshot
- if err = serializedSnap.Unmarshal(b); err != nil {
- if lg != nil {
- lg.Warn("failed to unmarshal snappb.Snapshot", zap.String("path", snapname), zap.Error(err))
- } else {
- plog.Errorf("corrupted snapshot file %v: %v", snapname, err)
- }
- return nil, err
- }
-
- if len(serializedSnap.Data) == 0 || serializedSnap.Crc == 0 {
- if lg != nil {
- lg.Warn("failed to read empty snapshot data", zap.String("path", snapname))
- } else {
- plog.Errorf("unexpected empty snapshot")
- }
- return nil, ErrEmptySnapshot
- }
-
- crc := crc32.Update(0, crcTable, serializedSnap.Data)
- if crc != serializedSnap.Crc {
- if lg != nil {
- lg.Warn("snap file is corrupt",
- zap.String("path", snapname),
- zap.Uint32("prev-crc", serializedSnap.Crc),
- zap.Uint32("new-crc", crc),
- )
- } else {
- plog.Errorf("corrupted snapshot file %v: crc mismatch", snapname)
- }
- return nil, ErrCRCMismatch
- }
-
- var snap raftpb.Snapshot
- if err = snap.Unmarshal(serializedSnap.Data); err != nil {
- if lg != nil {
- lg.Warn("failed to unmarshal raftpb.Snapshot", zap.String("path", snapname), zap.Error(err))
- } else {
- plog.Errorf("corrupted snapshot file %v: %v", snapname, err)
- }
- return nil, err
- }
- return &snap, nil
-}
-
-// snapNames returns the filename of the snapshots in logical time order (from newest to oldest).
-// If there is no available snapshots, an ErrNoSnapshot will be returned.
-func (s *Snapshotter) snapNames() ([]string, error) {
- dir, err := os.Open(s.dir)
- if err != nil {
- return nil, err
- }
- defer dir.Close()
- names, err := dir.Readdirnames(-1)
- if err != nil {
- return nil, err
- }
- snaps := checkSuffix(s.lg, names)
- if len(snaps) == 0 {
- return nil, ErrNoSnapshot
- }
- sort.Sort(sort.Reverse(sort.StringSlice(snaps)))
- return snaps, nil
-}
-
-func checkSuffix(lg *zap.Logger, names []string) []string {
- snaps := []string{}
- for i := range names {
- if strings.HasSuffix(names[i], snapSuffix) {
- snaps = append(snaps, names[i])
- } else {
- // If we find a file which is not a snapshot then check if it's
- // a vaild file. If not throw out a warning.
- if _, ok := validFiles[names[i]]; !ok {
- if lg != nil {
- lg.Warn("found unexpected non-snap file; skipping", zap.String("path", names[i]))
- } else {
- plog.Warningf("skipped unexpected non snapshot file %v", names[i])
- }
- }
- }
- }
- return snaps
-}
diff --git a/vendor/go.etcd.io/etcd/etcdserver/api/v2auth/auth.go b/vendor/go.etcd.io/etcd/etcdserver/api/v2auth/auth.go
deleted file mode 100644
index b438074..0000000
--- a/vendor/go.etcd.io/etcd/etcdserver/api/v2auth/auth.go
+++ /dev/null
@@ -1,736 +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/etcdserver"
- "go.etcd.io/etcd/etcdserver/api/v2error"
- "go.etcd.io/etcd/etcdserver/etcdserverpb"
- "go.etcd.io/etcd/pkg/types"
-
- "github.com/coreos/pkg/capnslog"
- "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 (
- plog = capnslog.NewPackageLogger("go.etcd.io/etcd/v3", "etcdserver/auth")
-)
-
-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 {
- 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 {
- if s.lg != nil {
- s.lg.Info("created a user", zap.String("user-name", user.User))
- } else {
- plog.Noticef("created user %s", 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
- }
- if s.lg != nil {
- s.lg.Info("deleted a user", zap.String("user-name", name))
- } else {
- plog.Noticef("deleted user %s", 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 {
- if s.lg != nil {
- s.lg.Info("updated a user", zap.String("user-name", user.User))
- } else {
- plog.Noticef("updated user %s", 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 {
- if s.lg != nil {
- s.lg.Info("created a new role", zap.String("role-name", role.Role))
- } else {
- plog.Noticef("created new role %s", 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 {
- if s.lg != nil {
- s.lg.Info("delete a new role", zap.String("role-name", name))
- } else {
- plog.Noticef("deleted role %s", 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 {
- if s.lg != nil {
- s.lg.Info("updated a new role", zap.String("role-name", role.Role))
- } else {
- plog.Noticef("updated role %s", 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 {
- if s.lg != nil {
- s.lg.Info(
- "no guest role access found; creating default",
- zap.String("role-name", GuestRoleName),
- )
- } else {
- plog.Printf("no guest role access found, creating default")
- }
- if err := s.CreateRole(guestRole); err != nil {
- if s.lg != nil {
- s.lg.Warn(
- "failed to create a guest role; aborting auth enable",
- zap.String("role-name", GuestRoleName),
- zap.Error(err),
- )
- } else {
- plog.Errorf("error creating guest role. aborting auth enable.")
- }
- return err
- }
- }
-
- if err := s.enableAuth(); err != nil {
- if s.lg != nil {
- s.lg.Warn("failed to enable auth", zap.Error(err))
- } else {
- plog.Errorf("error enabling auth (%v)", err)
- }
- return err
- }
-
- if s.lg != nil {
- s.lg.Info("enabled auth")
- } else {
- plog.Noticef("auth: enabled auth")
- }
- return nil
-}
-
-func (s *store) DisableAuth() error {
- if !s.AuthEnabled() {
- return authErr(http.StatusConflict, "already disabled")
- }
-
- err := s.disableAuth()
- if err == nil {
- if s.lg != nil {
- s.lg.Info("disabled auth")
- } else {
- plog.Noticef("auth: disabled auth")
- }
- } else {
- if s.lg != nil {
- s.lg.Warn("failed to disable auth", zap.Error(err))
- } else {
- plog.Errorf("error disabling auth (%v)", 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) {
- if lg != nil {
- lg.Warn(
- "attempted to grant a duplicate role for a user",
- zap.String("user-name", nu.User),
- zap.String("role-name", g),
- )
- } else {
- plog.Noticef("granting duplicate role %s for user %s", g, nu.User)
- }
- 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) {
- if lg != nil {
- lg.Warn(
- "attempted to revoke a ungranted role for a user",
- zap.String("user-name", nu.User),
- zap.String("role-name", r),
- )
- } else {
- plog.Noticef("revoking ungranted role %s for user %s", r, nu.User)
- }
- 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) {
- if lg != nil {
- lg.Info(
- "revoking ungranted read permission",
- zap.String("read-permission", r),
- )
- } else {
- plog.Noticef("revoking ungranted read permission %s", r)
- }
- continue
- }
- currentRead.Remove(r)
- }
- currentWrite := types.NewUnsafeSet(rw.Write...)
- for _, w := range n.Write {
- if !currentWrite.Contains(w) {
- if lg != nil {
- lg.Info(
- "revoking ungranted write permission",
- zap.String("write-permission", w),
- )
- } else {
- plog.Noticef("revoking ungranted write permission %s", 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/vendor/go.etcd.io/etcd/etcdserver/api/v2auth/auth_requests.go b/vendor/go.etcd.io/etcd/etcdserver/api/v2auth/auth_requests.go
deleted file mode 100644
index d6574ec..0000000
--- a/vendor/go.etcd.io/etcd/etcdserver/api/v2auth/auth_requests.go
+++ /dev/null
@@ -1,189 +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/etcdserver"
- "go.etcd.io/etcd/etcdserver/api/v2error"
- "go.etcd.io/etcd/etcdserver/etcdserverpb"
-
- "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
- }
- }
- if s.lg != nil {
- s.lg.Warn(
- "failed to create auth directories",
- zap.Error(err),
- )
- } else {
- plog.Errorf("failed to create auth directories in the store (%v)", 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
- }
- }
- if s.lg != nil {
- s.lg.Warn(
- "failed to detect auth settings",
- zap.Error(err),
- )
- } else {
- plog.Errorf("failed to detect auth settings (%s)", err)
- }
- return false
- }
-
- var u bool
- err = json.Unmarshal([]byte(*value.Event.Node.Value), &u)
- if err != nil {
- if s.lg != nil {
- s.lg.Warn(
- "internal bookkeeping value for enabled isn't valid JSON",
- zap.Error(err),
- )
- } else {
- plog.Errorf("internal bookkeeping value for enabled isn't valid JSON (%v)", 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/vendor/go.etcd.io/etcd/etcdserver/api/v2discovery/discovery.go b/vendor/go.etcd.io/etcd/etcdserver/api/v2discovery/discovery.go
deleted file mode 100644
index cf770b3..0000000
--- a/vendor/go.etcd.io/etcd/etcdserver/api/v2discovery/discovery.go
+++ /dev/null
@@ -1,440 +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 v2discovery provides an implementation of the cluster discovery that
-// is used by etcd with v2 client.
-package v2discovery
-
-import (
- "context"
- "errors"
- "fmt"
- "math"
- "net/http"
- "net/url"
- "path"
- "sort"
- "strconv"
- "strings"
- "time"
-
- "go.etcd.io/etcd/client"
- "go.etcd.io/etcd/pkg/transport"
- "go.etcd.io/etcd/pkg/types"
-
- "github.com/coreos/pkg/capnslog"
- "github.com/jonboulle/clockwork"
- "go.uber.org/zap"
-)
-
-var (
- plog = capnslog.NewPackageLogger("go.etcd.io/etcd", "discovery")
-
- ErrInvalidURL = errors.New("discovery: invalid URL")
- ErrBadSizeKey = errors.New("discovery: size key is bad")
- ErrSizeNotFound = errors.New("discovery: size key not found")
- ErrTokenNotFound = errors.New("discovery: token not found")
- ErrDuplicateID = errors.New("discovery: found duplicate id")
- ErrDuplicateName = errors.New("discovery: found duplicate name")
- ErrFullCluster = errors.New("discovery: cluster is full")
- ErrTooManyRetries = errors.New("discovery: too many retries")
- ErrBadDiscoveryEndpoint = errors.New("discovery: bad discovery endpoint")
-)
-
-var (
- // Number of retries discovery will attempt before giving up and erroring out.
- nRetries = uint(math.MaxUint32)
- maxExpoentialRetries = uint(8)
-)
-
-// 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
-func JoinCluster(lg *zap.Logger, durl, dproxyurl string, id types.ID, config string) (string, error) {
- d, err := newDiscovery(lg, durl, dproxyurl, id)
- if err != nil {
- return "", err
- }
- return d.joinCluster(config)
-}
-
-// GetCluster will connect to the discovery service at the given url and
-// retrieve a string describing the cluster
-func GetCluster(lg *zap.Logger, durl, dproxyurl string) (string, error) {
- d, err := newDiscovery(lg, durl, dproxyurl, 0)
- if err != nil {
- return "", err
- }
- return d.getCluster()
-}
-
-type discovery struct {
- lg *zap.Logger
- cluster string
- id types.ID
- c client.KeysAPI
- retries uint
- url *url.URL
-
- clock clockwork.Clock
-}
-
-// newProxyFunc builds a proxy function from the given string, which should
-// represent a URL that can be used as a proxy. It performs basic
-// sanitization of the URL and returns any error encountered.
-func newProxyFunc(lg *zap.Logger, proxy string) (func(*http.Request) (*url.URL, error), error) {
- if proxy == "" {
- return nil, nil
- }
- // Do a small amount of URL sanitization to help the user
- // Derived from net/http.ProxyFromEnvironment
- proxyURL, err := url.Parse(proxy)
- if err != nil || !strings.HasPrefix(proxyURL.Scheme, "http") {
- // proxy was bogus. Try prepending "http://" to it and
- // see if that parses correctly. If not, we ignore the
- // error and complain about the original one
- var err2 error
- proxyURL, err2 = url.Parse("http://" + proxy)
- if err2 == nil {
- err = nil
- }
- }
- if err != nil {
- return nil, fmt.Errorf("invalid proxy address %q: %v", proxy, err)
- }
-
- if lg != nil {
- lg.Info("running proxy with discovery", zap.String("proxy-url", proxyURL.String()))
- } else {
- plog.Infof("using proxy %q", proxyURL.String())
- }
- return http.ProxyURL(proxyURL), nil
-}
-
-func newDiscovery(lg *zap.Logger, durl, dproxyurl string, id types.ID) (*discovery, error) {
- u, err := url.Parse(durl)
- if err != nil {
- return nil, err
- }
- token := u.Path
- u.Path = ""
- pf, err := newProxyFunc(lg, dproxyurl)
- if err != nil {
- return nil, err
- }
-
- // TODO: add ResponseHeaderTimeout back when watch on discovery service writes header early
- tr, err := transport.NewTransport(transport.TLSInfo{}, 30*time.Second)
- if err != nil {
- return nil, err
- }
- tr.Proxy = pf
- cfg := client.Config{
- Transport: tr,
- Endpoints: []string{u.String()},
- }
- c, err := client.New(cfg)
- if err != nil {
- return nil, err
- }
- dc := client.NewKeysAPIWithPrefix(c, "")
- return &discovery{
- lg: lg,
- cluster: token,
- c: dc,
- id: id,
- url: u,
- clock: clockwork.NewRealClock(),
- }, nil
-}
-
-func (d *discovery) joinCluster(config string) (string, error) {
- // fast path: if the cluster is full, return the error
- // do not need to register to the cluster in this case.
- if _, _, _, err := d.checkCluster(); err != nil {
- return "", err
- }
-
- if err := d.createSelf(config); err != nil {
- // Fails, even on a timeout, if createSelf times out.
- // TODO(barakmich): Retrying the same node might want to succeed here
- // (ie, createSelf should be idempotent for discovery).
- return "", err
- }
-
- nodes, size, index, err := d.checkCluster()
- if err != nil {
- return "", err
- }
-
- all, err := d.waitNodes(nodes, size, index)
- if err != nil {
- return "", err
- }
-
- return nodesToCluster(all, size)
-}
-
-func (d *discovery) getCluster() (string, error) {
- nodes, size, index, err := d.checkCluster()
- if err != nil {
- if err == ErrFullCluster {
- return nodesToCluster(nodes, size)
- }
- return "", err
- }
-
- all, err := d.waitNodes(nodes, size, index)
- if err != nil {
- return "", err
- }
- return nodesToCluster(all, size)
-}
-
-func (d *discovery) createSelf(contents string) error {
- ctx, cancel := context.WithTimeout(context.Background(), client.DefaultRequestTimeout)
- resp, err := d.c.Create(ctx, d.selfKey(), contents)
- cancel()
- if err != nil {
- if eerr, ok := err.(client.Error); ok && eerr.Code == client.ErrorCodeNodeExist {
- return ErrDuplicateID
- }
- return err
- }
-
- // ensure self appears on the server we connected to
- w := d.c.Watcher(d.selfKey(), &client.WatcherOptions{AfterIndex: resp.Node.CreatedIndex - 1})
- _, err = w.Next(context.Background())
- return err
-}
-
-func (d *discovery) checkCluster() ([]*client.Node, int, uint64, error) {
- configKey := path.Join("/", d.cluster, "_config")
- ctx, cancel := context.WithTimeout(context.Background(), client.DefaultRequestTimeout)
- // find cluster size
- resp, err := d.c.Get(ctx, path.Join(configKey, "size"), nil)
- cancel()
- if err != nil {
- if eerr, ok := err.(*client.Error); ok && eerr.Code == client.ErrorCodeKeyNotFound {
- return nil, 0, 0, ErrSizeNotFound
- }
- if err == client.ErrInvalidJSON {
- return nil, 0, 0, ErrBadDiscoveryEndpoint
- }
- if ce, ok := err.(*client.ClusterError); ok {
- if d.lg != nil {
- d.lg.Warn(
- "failed to get from discovery server",
- zap.String("discovery-url", d.url.String()),
- zap.String("path", path.Join(configKey, "size")),
- zap.Error(err),
- zap.String("err-detail", ce.Detail()),
- )
- } else {
- plog.Error(ce.Detail())
- }
- return d.checkClusterRetry()
- }
- return nil, 0, 0, err
- }
- size, err := strconv.Atoi(resp.Node.Value)
- if err != nil {
- return nil, 0, 0, ErrBadSizeKey
- }
-
- ctx, cancel = context.WithTimeout(context.Background(), client.DefaultRequestTimeout)
- resp, err = d.c.Get(ctx, d.cluster, nil)
- cancel()
- if err != nil {
- if ce, ok := err.(*client.ClusterError); ok {
- if d.lg != nil {
- d.lg.Warn(
- "failed to get from discovery server",
- zap.String("discovery-url", d.url.String()),
- zap.String("path", d.cluster),
- zap.Error(err),
- zap.String("err-detail", ce.Detail()),
- )
- } else {
- plog.Error(ce.Detail())
- }
- return d.checkClusterRetry()
- }
- return nil, 0, 0, err
- }
- var nodes []*client.Node
- // append non-config keys to nodes
- for _, n := range resp.Node.Nodes {
- if path.Base(n.Key) != path.Base(configKey) {
- nodes = append(nodes, n)
- }
- }
-
- snodes := sortableNodes{nodes}
- sort.Sort(snodes)
-
- // find self position
- for i := range nodes {
- if path.Base(nodes[i].Key) == path.Base(d.selfKey()) {
- break
- }
- if i >= size-1 {
- return nodes[:size], size, resp.Index, ErrFullCluster
- }
- }
- return nodes, size, resp.Index, nil
-}
-
-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 > maxExpoentialRetries {
- retries = maxExpoentialRetries
- }
- retryTimeInSecond := time.Duration(0x1<<retries) * time.Second
- if d.lg != nil {
- d.lg.Info(
- "retry connecting to discovery service",
- zap.String("url", d.url.String()),
- zap.String("reason", step),
- zap.Duration("backoff", retryTimeInSecond),
- )
- } else {
- plog.Infof("%s: error connecting to %s, retrying in %s", step, d.url, retryTimeInSecond)
- }
- d.clock.Sleep(retryTimeInSecond)
-}
-
-func (d *discovery) checkClusterRetry() ([]*client.Node, int, uint64, error) {
- if d.retries < nRetries {
- d.logAndBackoffForRetry("cluster status check")
- return d.checkCluster()
- }
- return nil, 0, 0, ErrTooManyRetries
-}
-
-func (d *discovery) waitNodesRetry() ([]*client.Node, error) {
- if d.retries < nRetries {
- d.logAndBackoffForRetry("waiting for other nodes")
- nodes, n, index, err := d.checkCluster()
- if err != nil {
- return nil, err
- }
- return d.waitNodes(nodes, n, index)
- }
- return nil, ErrTooManyRetries
-}
-
-func (d *discovery) waitNodes(nodes []*client.Node, size int, index uint64) ([]*client.Node, error) {
- if len(nodes) > size {
- nodes = nodes[:size]
- }
- // watch from the next index
- w := d.c.Watcher(d.cluster, &client.WatcherOptions{AfterIndex: index, Recursive: true})
- all := make([]*client.Node, len(nodes))
- copy(all, nodes)
- for _, n := range all {
- if path.Base(n.Key) == path.Base(d.selfKey()) {
- if d.lg != nil {
- d.lg.Info(
- "found self from discovery server",
- zap.String("discovery-url", d.url.String()),
- zap.String("self", path.Base(d.selfKey())),
- )
- } else {
- plog.Noticef("found self %s in the cluster", path.Base(d.selfKey()))
- }
- } else {
- if d.lg != nil {
- d.lg.Info(
- "found peer from discovery server",
- zap.String("discovery-url", d.url.String()),
- zap.String("peer", path.Base(n.Key)),
- )
- } else {
- plog.Noticef("found peer %s in the cluster", path.Base(n.Key))
- }
- }
- }
-
- // wait for others
- for len(all) < size {
- if d.lg != nil {
- d.lg.Info(
- "found peers from discovery server; waiting for more",
- zap.String("discovery-url", d.url.String()),
- zap.Int("found-peers", len(all)),
- zap.Int("needed-peers", size-len(all)),
- )
- } else {
- plog.Noticef("found %d peer(s), waiting for %d more", len(all), size-len(all))
- }
- resp, err := w.Next(context.Background())
- if err != nil {
- if ce, ok := err.(*client.ClusterError); ok {
- plog.Error(ce.Detail())
- return d.waitNodesRetry()
- }
- return nil, err
- }
- if d.lg != nil {
- d.lg.Info(
- "found peer from discovery server",
- zap.String("discovery-url", d.url.String()),
- zap.String("peer", path.Base(resp.Node.Key)),
- )
- } else {
- plog.Noticef("found peer %s in the cluster", path.Base(resp.Node.Key))
- }
- all = append(all, resp.Node)
- }
- if d.lg != nil {
- d.lg.Info(
- "found all needed peers from discovery server",
- zap.String("discovery-url", d.url.String()),
- zap.Int("found-peers", len(all)),
- )
- } else {
- plog.Noticef("found %d needed peer(s)", len(all))
- }
- return all, nil
-}
-
-func (d *discovery) selfKey() string {
- return path.Join("/", d.cluster, d.id.String())
-}
-
-func nodesToCluster(ns []*client.Node, size int) (string, error) {
- s := make([]string, len(ns))
- for i, n := range ns {
- s[i] = n.Value
- }
- us := strings.Join(s, ",")
- m, err := types.NewURLsMap(us)
- if err != nil {
- return us, ErrInvalidURL
- }
- if m.Len() != size {
- return us, ErrDuplicateName
- }
- return us, nil
-}
-
-type sortableNodes struct{ Nodes []*client.Node }
-
-func (ns sortableNodes) Len() int { return len(ns.Nodes) }
-func (ns sortableNodes) Less(i, j int) bool {
- return ns.Nodes[i].CreatedIndex < ns.Nodes[j].CreatedIndex
-}
-func (ns sortableNodes) Swap(i, j int) { ns.Nodes[i], ns.Nodes[j] = ns.Nodes[j], ns.Nodes[i] }
diff --git a/vendor/go.etcd.io/etcd/etcdserver/api/v2error/error.go b/vendor/go.etcd.io/etcd/etcdserver/api/v2error/error.go
deleted file mode 100644
index 1244290..0000000
--- a/vendor/go.etcd.io/etcd/etcdserver/api/v2error/error.go
+++ /dev/null
@@ -1,164 +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 v2error describes errors in etcd project. When any change happens,
-// Documentation/v2/errorcode.md needs to be updated correspondingly.
-// To be deprecated in favor of v3 APIs.
-package v2error
-
-import (
- "encoding/json"
- "fmt"
- "net/http"
-)
-
-var errors = map[int]string{
- // command related errors
- EcodeKeyNotFound: "Key not found",
- EcodeTestFailed: "Compare failed", //test and set
- EcodeNotFile: "Not a file",
- ecodeNoMorePeer: "Reached the max number of peers in the cluster",
- EcodeNotDir: "Not a directory",
- EcodeNodeExist: "Key already exists", // create
- ecodeKeyIsPreserved: "The prefix of given key is a keyword in etcd",
- EcodeRootROnly: "Root is read only",
- EcodeDirNotEmpty: "Directory not empty",
- ecodeExistingPeerAddr: "Peer address has existed",
- EcodeUnauthorized: "The request requires user authentication",
-
- // Post form related errors
- ecodeValueRequired: "Value is Required in POST form",
- EcodePrevValueRequired: "PrevValue is Required in POST form",
- EcodeTTLNaN: "The given TTL in POST form is not a number",
- EcodeIndexNaN: "The given index in POST form is not a number",
- ecodeValueOrTTLRequired: "Value or TTL is required in POST form",
- ecodeTimeoutNaN: "The given timeout in POST form is not a number",
- ecodeNameRequired: "Name is required in POST form",
- ecodeIndexOrValueRequired: "Index or value is required",
- ecodeIndexValueMutex: "Index and value cannot both be specified",
- EcodeInvalidField: "Invalid field",
- EcodeInvalidForm: "Invalid POST form",
- EcodeRefreshValue: "Value provided on refresh",
- EcodeRefreshTTLRequired: "A TTL must be provided on refresh",
-
- // raft related errors
- EcodeRaftInternal: "Raft Internal Error",
- EcodeLeaderElect: "During Leader Election",
-
- // etcd related errors
- EcodeWatcherCleared: "watcher is cleared due to etcd recovery",
- EcodeEventIndexCleared: "The event in requested index is outdated and cleared",
- ecodeStandbyInternal: "Standby Internal Error",
- ecodeInvalidActiveSize: "Invalid active size",
- ecodeInvalidRemoveDelay: "Standby remove delay",
-
- // client related errors
- ecodeClientInternal: "Client Internal Error",
-}
-
-var errorStatus = map[int]int{
- EcodeKeyNotFound: http.StatusNotFound,
- EcodeNotFile: http.StatusForbidden,
- EcodeDirNotEmpty: http.StatusForbidden,
- EcodeUnauthorized: http.StatusUnauthorized,
- EcodeTestFailed: http.StatusPreconditionFailed,
- EcodeNodeExist: http.StatusPreconditionFailed,
- EcodeRaftInternal: http.StatusInternalServerError,
- EcodeLeaderElect: http.StatusInternalServerError,
-}
-
-const (
- EcodeKeyNotFound = 100
- EcodeTestFailed = 101
- EcodeNotFile = 102
- ecodeNoMorePeer = 103
- EcodeNotDir = 104
- EcodeNodeExist = 105
- ecodeKeyIsPreserved = 106
- EcodeRootROnly = 107
- EcodeDirNotEmpty = 108
- ecodeExistingPeerAddr = 109
- EcodeUnauthorized = 110
-
- ecodeValueRequired = 200
- EcodePrevValueRequired = 201
- EcodeTTLNaN = 202
- EcodeIndexNaN = 203
- ecodeValueOrTTLRequired = 204
- ecodeTimeoutNaN = 205
- ecodeNameRequired = 206
- ecodeIndexOrValueRequired = 207
- ecodeIndexValueMutex = 208
- EcodeInvalidField = 209
- EcodeInvalidForm = 210
- EcodeRefreshValue = 211
- EcodeRefreshTTLRequired = 212
-
- EcodeRaftInternal = 300
- EcodeLeaderElect = 301
-
- EcodeWatcherCleared = 400
- EcodeEventIndexCleared = 401
- ecodeStandbyInternal = 402
- ecodeInvalidActiveSize = 403
- ecodeInvalidRemoveDelay = 404
-
- ecodeClientInternal = 500
-)
-
-type Error struct {
- ErrorCode int `json:"errorCode"`
- Message string `json:"message"`
- Cause string `json:"cause,omitempty"`
- 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,
- Message: errors[errorCode],
- Cause: cause,
- Index: index,
- }
-}
-
-// Error is for the error interface
-func (e Error) Error() string {
- return e.Message + " (" + e.Cause + ")"
-}
-
-func (e Error) toJsonString() string {
- b, _ := json.Marshal(e)
- return string(b)
-}
-
-func (e Error) StatusCode() int {
- status, ok := errorStatus[e.ErrorCode]
- if !ok {
- status = http.StatusBadRequest
- }
- return status
-}
-
-func (e Error) WriteTo(w http.ResponseWriter) error {
- w.Header().Add("X-Etcd-Index", fmt.Sprint(e.Index))
- w.Header().Set("Content-Type", "application/json")
- w.WriteHeader(e.StatusCode())
- _, err := w.Write([]byte(e.toJsonString() + "\n"))
- return err
-}
diff --git a/vendor/go.etcd.io/etcd/etcdserver/api/v2http/capability.go b/vendor/go.etcd.io/etcd/etcdserver/api/v2http/capability.go
deleted file mode 100644
index ed6c456..0000000
--- a/vendor/go.etcd.io/etcd/etcdserver/api/v2http/capability.go
+++ /dev/null
@@ -1,40 +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/etcdserver/api"
- "go.etcd.io/etcd/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 {
- plog.Debugf("error writing HTTPError (%v) to %s", err, r.RemoteAddr)
- }
-}
diff --git a/vendor/go.etcd.io/etcd/etcdserver/api/v2http/client.go b/vendor/go.etcd.io/etcd/etcdserver/api/v2http/client.go
deleted file mode 100644
index 1d1e592..0000000
--- a/vendor/go.etcd.io/etcd/etcdserver/api/v2http/client.go
+++ /dev/null
@@ -1,788 +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"
- "encoding/json"
- "errors"
- "fmt"
- "io/ioutil"
- "net/http"
- "net/url"
- "path"
- "strconv"
- "strings"
- "time"
-
- "go.etcd.io/etcd/etcdserver"
- "go.etcd.io/etcd/etcdserver/api"
- "go.etcd.io/etcd/etcdserver/api/etcdhttp"
- "go.etcd.io/etcd/etcdserver/api/membership"
- "go.etcd.io/etcd/etcdserver/api/v2auth"
- "go.etcd.io/etcd/etcdserver/api/v2error"
- "go.etcd.io/etcd/etcdserver/api/v2http/httptypes"
- stats "go.etcd.io/etcd/etcdserver/api/v2stats"
- "go.etcd.io/etcd/etcdserver/api/v2store"
- "go.etcd.io/etcd/etcdserver/etcdserverpb"
- "go.etcd.io/etcd/pkg/types"
-
- "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 {
- mux := http.NewServeMux()
- etcdhttp.HandleBasic(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
- if h.lg != nil {
- h.lg.Warn("failed to write key event", zap.Error(err))
- } else {
- plog.Errorf("error writing event (%v)", 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 {
- if h.lg != nil {
- h.lg.Warn("failed to encode members response", zap.Error(err))
- } else {
- plog.Warningf("failed to encode members response (%v)", 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 {
- if h.lg != nil {
- h.lg.Warn("failed to encode members response", zap.Error(err))
- } else {
- plog.Warningf("failed to encode members response (%v)", 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:
- if h.lg != nil {
- h.lg.Warn(
- "failed to add a member",
- zap.String("member-id", m.ID.String()),
- zap.Error(err),
- )
- } else {
- plog.Errorf("error adding member %s (%v)", m.ID, 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 {
- if h.lg != nil {
- h.lg.Warn("failed to encode members response", zap.Error(err))
- } else {
- plog.Warningf("failed to encode members response (%v)", 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:
- if h.lg != nil {
- h.lg.Warn(
- "failed to remove a member",
- zap.String("member-id", id.String()),
- zap.Error(err),
- )
- } else {
- plog.Errorf("error removing member %s (%v)", id, 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:
- if h.lg != nil {
- h.lg.Warn(
- "failed to update a member",
- zap.String("member-id", m.ID.String()),
- zap.Error(err),
- )
- } else {
- plog.Errorf("error updating member %s (%v)", m.ID, 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"`,
- )
- }
- 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()),
- )
- } else {
- mlog.MergeError(err)
- }
- default:
- if lg != nil {
- lg.Warn(
- "unexpected v2 response error",
- zap.String("internal-server-error", err.Error()),
- )
- } else {
- mlog.MergeErrorf("got unexpected response error (%v)", err)
- }
- }
- 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
- if lg != nil {
- lg.Warn("failed to encode event", zap.Error(err))
- } else {
- plog.Warningf("error writing event (%v)", 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 := ioutil.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
-}
diff --git a/vendor/go.etcd.io/etcd/etcdserver/api/v2http/client_auth.go b/vendor/go.etcd.io/etcd/etcdserver/api/v2http/client_auth.go
deleted file mode 100644
index d8d6a88..0000000
--- a/vendor/go.etcd.io/etcd/etcdserver/api/v2http/client_auth.go
+++ /dev/null
@@ -1,664 +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/etcdserver/api"
- "go.etcd.io/etcd/etcdserver/api/v2auth"
- "go.etcd.io/etcd/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 {
- if lg != nil {
- lg.Warn("malformed basic auth encoding")
- } else {
- plog.Warningf("auth: malformed basic auth encoding")
- }
- return nil
- }
- user, err := sec.GetUser(username)
- if err != nil {
- return nil
- }
-
- ok = sec.CheckPassword(user, password)
- if !ok {
- if lg != nil {
- lg.Warn("incorrect password", zap.String("user-name", username))
- } else {
- plog.Warningf("auth: incorrect password for user: %s", 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 {
- if lg != nil {
- lg.Debug("found common name", zap.String("common-name", chain.Subject.CommonName))
- } else {
- plog.Debugf("auth: found common name %s.\n", chain.Subject.CommonName)
- }
- user, err := sec.GetUser(chain.Subject.CommonName)
- if err == nil {
- if lg != nil {
- lg.Debug(
- "authenticated a user via common name",
- zap.String("user-name", user.User),
- zap.String("common-name", chain.Subject.CommonName),
- )
- } else {
- plog.Debugf("auth: authenticated user %s by cert common name.", user.User)
- }
- 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
- }
- }
-
- if lg != nil {
- 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),
- )
- } else {
- plog.Warningf("auth: user %s does not have the %s role for resource %s.", rootUser.User, v2auth.RootRoleName, 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
- }
- }
-
- if lg != nil {
- lg.Warn(
- "invalid access for user on key",
- zap.String("user-name", user.User),
- zap.String("key", key),
- )
- } else {
- plog.Warningf("auth: invalid access for user %s on key %s.", user.User, 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
- }
-
- if lg != nil {
- lg.Warn(
- "invalid access for a guest role on key",
- zap.String("role-name", v2auth.GuestRoleName),
- zap.String("key", key),
- )
- } else {
- plog.Warningf("auth: invalid access for unauthenticated user on resource %s.", 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 {
- if lg != nil {
- lg.Debug(
- "failed to write v2 HTTP error",
- zap.String("remote-addr", r.RemoteAddr),
- zap.Error(err),
- )
- } else {
- plog.Debugf("error writing HTTPError (%v) to %s", err, r.RemoteAddr)
- }
- }
-}
-
-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 {
- if sh.lg != nil {
- sh.lg.Warn(
- "failed to encode base roles",
- zap.String("url", r.URL.String()),
- zap.Error(err),
- )
- } else {
- plog.Warningf("baseRoles error encoding on %s", r.URL)
- }
- 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 {
- if sh.lg != nil {
- sh.lg.Warn(
- "failed to encode a role",
- zap.String("url", r.URL.String()),
- zap.Error(err),
- )
- } else {
- plog.Warningf("forRole error encoding on %s", r.URL)
- }
- 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 {
- if sh.lg != nil {
- sh.lg.Warn(
- "failed to encode a role",
- zap.String("url", r.URL.String()),
- zap.Error(err),
- )
- } else {
- plog.Warningf("forRole error encoding on %s", r.URL)
- }
- 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 {
- if sh.lg != nil {
- sh.lg.Warn(
- "failed to encode users",
- zap.String("url", r.URL.String()),
- zap.Error(err),
- )
- } else {
- plog.Warningf("baseUsers error encoding on %s", r.URL)
- }
- 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 {
- if sh.lg != nil {
- sh.lg.Warn(
- "failed to encode roles",
- zap.String("url", r.URL.String()),
- zap.Error(err),
- )
- } else {
- plog.Warningf("forUser error encoding on %s", r.URL)
- }
- 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 {
- if sh.lg != nil {
- sh.lg.Warn(
- "failed to encode a user",
- zap.String("url", r.URL.String()),
- zap.Error(err),
- )
- } else {
- plog.Warningf("forUser error encoding on %s", r.URL)
- }
- 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 {
- if sh.lg != nil {
- sh.lg.Warn(
- "failed to encode a auth state",
- zap.String("url", r.URL.String()),
- zap.Error(err),
- )
- } else {
- plog.Warningf("error encoding auth state on %s", r.URL)
- }
- }
-
- 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/vendor/go.etcd.io/etcd/etcdserver/api/v2http/doc.go b/vendor/go.etcd.io/etcd/etcdserver/api/v2http/doc.go
deleted file mode 100644
index 475c4b1..0000000
--- a/vendor/go.etcd.io/etcd/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/vendor/go.etcd.io/etcd/etcdserver/api/v2http/http.go b/vendor/go.etcd.io/etcd/etcdserver/api/v2http/http.go
deleted file mode 100644
index c695689..0000000
--- a/vendor/go.etcd.io/etcd/etcdserver/api/v2http/http.go
+++ /dev/null
@@ -1,93 +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/etcdserver/api/etcdhttp"
- "go.etcd.io/etcd/etcdserver/api/v2auth"
- "go.etcd.io/etcd/etcdserver/api/v2http/httptypes"
- "go.etcd.io/etcd/pkg/logutil"
-
- "github.com/coreos/pkg/capnslog"
- "go.uber.org/zap"
-)
-
-const (
- // time to wait for a Watch request
- defaultWatchTimeout = time.Duration(math.MaxInt64)
-)
-
-var (
- plog = capnslog.NewPackageLogger("go.etcd.io/etcd", "etcdserver/api/v2http")
- mlog = logutil.NewMergeLogger(plog)
-)
-
-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),
- )
- } else {
- plog.Debugf("error writing HTTPError (%v) to %s", et, r.RemoteAddr)
- }
- }
- 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),
- )
- } else {
- plog.Debugf("[%s] %s remote:%s", r.Method, r.RequestURI, r.RemoteAddr)
- }
- handler.ServeHTTP(w, r)
- })
-}
diff --git a/vendor/go.etcd.io/etcd/etcdserver/api/v2http/httptypes/errors.go b/vendor/go.etcd.io/etcd/etcdserver/api/v2http/httptypes/errors.go
deleted file mode 100644
index 245c089..0000000
--- a/vendor/go.etcd.io/etcd/etcdserver/api/v2http/httptypes/errors.go
+++ /dev/null
@@ -1,56 +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/http"
-
- "github.com/coreos/pkg/capnslog"
-)
-
-var (
- plog = capnslog.NewPackageLogger("go.etcd.io/etcd", "etcdserver/api/v2http/httptypes")
-)
-
-type HTTPError struct {
- Message string `json:"message"`
- // Code is the HTTP status code
- Code int `json:"-"`
-}
-
-func (e HTTPError) Error() string {
- return e.Message
-}
-
-func (e HTTPError) WriteTo(w http.ResponseWriter) error {
- w.Header().Set("Content-Type", "application/json")
- w.WriteHeader(e.Code)
- b, err := json.Marshal(e)
- if err != nil {
- plog.Panicf("marshal HTTPError should never fail (%v)", err)
- }
- if _, err := w.Write(b); err != nil {
- return err
- }
- return nil
-}
-
-func NewHTTPError(code int, m string) *HTTPError {
- return &HTTPError{
- Message: m,
- Code: code,
- }
-}
diff --git a/vendor/go.etcd.io/etcd/etcdserver/api/v2http/httptypes/member.go b/vendor/go.etcd.io/etcd/etcdserver/api/v2http/httptypes/member.go
deleted file mode 100644
index 95fd443..0000000
--- a/vendor/go.etcd.io/etcd/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/pkg/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/vendor/go.etcd.io/etcd/etcdserver/api/v2http/metrics.go b/vendor/go.etcd.io/etcd/etcdserver/api/v2http/metrics.go
deleted file mode 100644
index 14f7da0..0000000
--- a/vendor/go.etcd.io/etcd/etcdserver/api/v2http/metrics.go
+++ /dev/null
@@ -1,99 +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 (
- "strconv"
- "time"
-
- "net/http"
-
- "go.etcd.io/etcd/etcdserver/api/v2error"
- "go.etcd.io/etcd/etcdserver/api/v2http/httptypes"
- "go.etcd.io/etcd/etcdserver/etcdserverpb"
-
- "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/vendor/go.etcd.io/etcd/etcdserver/api/v2stats/leader.go b/vendor/go.etcd.io/etcd/etcdserver/api/v2stats/leader.go
deleted file mode 100644
index ca47f0f..0000000
--- a/vendor/go.etcd.io/etcd/etcdserver/api/v2stats/leader.go
+++ /dev/null
@@ -1,128 +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
-
-import (
- "encoding/json"
- "math"
- "sync"
- "time"
-)
-
-// LeaderStats is used by the leader in an etcd cluster, and encapsulates
-// statistics about communication with its followers
-type LeaderStats struct {
- leaderStats
- sync.Mutex
-}
-
-type leaderStats struct {
- // Leader is the ID of the leader in the etcd cluster.
- // TODO(jonboulle): clarify that these are IDs, not names
- Leader string `json:"leader"`
- Followers map[string]*FollowerStats `json:"followers"`
-}
-
-// NewLeaderStats generates a new LeaderStats with the given id as leader
-func NewLeaderStats(id string) *LeaderStats {
- return &LeaderStats{
- leaderStats: leaderStats{
- Leader: id,
- Followers: make(map[string]*FollowerStats),
- },
- }
-}
-
-func (ls *LeaderStats) JSON() []byte {
- ls.Lock()
- stats := ls.leaderStats
- ls.Unlock()
- b, err := json.Marshal(stats)
- // TODO(jonboulle): appropriate error handling?
- if err != nil {
- plog.Errorf("error marshalling leader stats (%v)", err)
- }
- return b
-}
-
-func (ls *LeaderStats) Follower(name string) *FollowerStats {
- ls.Lock()
- defer ls.Unlock()
- fs, ok := ls.Followers[name]
- if !ok {
- fs = &FollowerStats{}
- fs.Latency.Minimum = 1 << 63
- ls.Followers[name] = fs
- }
- return fs
-}
-
-// FollowerStats encapsulates various statistics about a follower in an etcd cluster
-type FollowerStats struct {
- Latency LatencyStats `json:"latency"`
- Counts CountsStats `json:"counts"`
-
- sync.Mutex
-}
-
-// LatencyStats encapsulates latency statistics.
-type LatencyStats struct {
- Current float64 `json:"current"`
- Average float64 `json:"average"`
- averageSquare float64
- StandardDeviation float64 `json:"standardDeviation"`
- Minimum float64 `json:"minimum"`
- Maximum float64 `json:"maximum"`
-}
-
-// CountsStats encapsulates raft statistics.
-type CountsStats struct {
- Fail uint64 `json:"fail"`
- Success uint64 `json:"success"`
-}
-
-// Succ updates the FollowerStats with a successful send
-func (fs *FollowerStats) Succ(d time.Duration) {
- fs.Lock()
- defer fs.Unlock()
-
- total := float64(fs.Counts.Success) * fs.Latency.Average
- totalSquare := float64(fs.Counts.Success) * fs.Latency.averageSquare
-
- fs.Counts.Success++
-
- fs.Latency.Current = float64(d) / (1000000.0)
-
- if fs.Latency.Current > fs.Latency.Maximum {
- fs.Latency.Maximum = fs.Latency.Current
- }
-
- if fs.Latency.Current < fs.Latency.Minimum {
- fs.Latency.Minimum = fs.Latency.Current
- }
-
- fs.Latency.Average = (total + fs.Latency.Current) / float64(fs.Counts.Success)
- fs.Latency.averageSquare = (totalSquare + fs.Latency.Current*fs.Latency.Current) / float64(fs.Counts.Success)
-
- // sdv = sqrt(avg(x^2) - avg(x)^2)
- fs.Latency.StandardDeviation = math.Sqrt(fs.Latency.averageSquare - fs.Latency.Average*fs.Latency.Average)
-}
-
-// Fail updates the FollowerStats with an unsuccessful send
-func (fs *FollowerStats) Fail() {
- fs.Lock()
- defer fs.Unlock()
- fs.Counts.Fail++
-}
diff --git a/vendor/go.etcd.io/etcd/etcdserver/api/v2stats/queue.go b/vendor/go.etcd.io/etcd/etcdserver/api/v2stats/queue.go
deleted file mode 100644
index 2c3dff3..0000000
--- a/vendor/go.etcd.io/etcd/etcdserver/api/v2stats/queue.go
+++ /dev/null
@@ -1,110 +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
-
-import (
- "sync"
- "time"
-)
-
-const (
- queueCapacity = 200
-)
-
-// RequestStats represent the stats for a request.
-// It encapsulates the sending time and the size of the request.
-type RequestStats struct {
- SendingTime time.Time
- Size int
-}
-
-type statsQueue struct {
- items [queueCapacity]*RequestStats
- size int
- front int
- back int
- totalReqSize int
- rwl sync.RWMutex
-}
-
-func (q *statsQueue) Len() int {
- return q.size
-}
-
-func (q *statsQueue) ReqSize() int {
- return q.totalReqSize
-}
-
-// FrontAndBack gets the front and back elements in the queue
-// We must grab front and back together with the protection of the lock
-func (q *statsQueue) frontAndBack() (*RequestStats, *RequestStats) {
- q.rwl.RLock()
- defer q.rwl.RUnlock()
- if q.size != 0 {
- return q.items[q.front], q.items[q.back]
- }
- return nil, nil
-}
-
-// Insert function insert a RequestStats into the queue and update the records
-func (q *statsQueue) Insert(p *RequestStats) {
- q.rwl.Lock()
- defer q.rwl.Unlock()
-
- q.back = (q.back + 1) % queueCapacity
-
- if q.size == queueCapacity { //dequeue
- q.totalReqSize -= q.items[q.front].Size
- q.front = (q.back + 1) % queueCapacity
- } else {
- q.size++
- }
-
- q.items[q.back] = p
- q.totalReqSize += q.items[q.back].Size
-
-}
-
-// Rate function returns the package rate and byte rate
-func (q *statsQueue) Rate() (float64, float64) {
- front, back := q.frontAndBack()
-
- if front == nil || back == nil {
- return 0, 0
- }
-
- if time.Since(back.SendingTime) > time.Second {
- q.Clear()
- return 0, 0
- }
-
- sampleDuration := back.SendingTime.Sub(front.SendingTime)
-
- pr := float64(q.Len()) / float64(sampleDuration) * float64(time.Second)
-
- br := float64(q.ReqSize()) / float64(sampleDuration) * float64(time.Second)
-
- return pr, br
-}
-
-// Clear function clear up the statsQueue
-func (q *statsQueue) Clear() {
- q.rwl.Lock()
- defer q.rwl.Unlock()
- q.back = -1
- q.front = 0
- q.size = 0
- q.totalReqSize = 0
-}
diff --git a/vendor/go.etcd.io/etcd/etcdserver/api/v2stats/server.go b/vendor/go.etcd.io/etcd/etcdserver/api/v2stats/server.go
deleted file mode 100644
index c4accc7..0000000
--- a/vendor/go.etcd.io/etcd/etcdserver/api/v2stats/server.go
+++ /dev/null
@@ -1,142 +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
-
-import (
- "encoding/json"
- "log"
- "sync"
- "time"
-
- "go.etcd.io/etcd/raft"
-)
-
-// ServerStats encapsulates various statistics about an EtcdServer and its
-// communication with other members of the cluster
-type ServerStats struct {
- serverStats
- sync.Mutex
-}
-
-func NewServerStats(name, id string) *ServerStats {
- ss := &ServerStats{
- serverStats: serverStats{
- Name: name,
- ID: id,
- },
- }
- now := time.Now()
- ss.StartTime = now
- ss.LeaderInfo.StartTime = now
- ss.sendRateQueue = &statsQueue{back: -1}
- ss.recvRateQueue = &statsQueue{back: -1}
- return ss
-}
-
-type serverStats struct {
- Name string `json:"name"`
- // ID is the raft ID of the node.
- // TODO(jonboulle): use ID instead of name?
- ID string `json:"id"`
- State raft.StateType `json:"state"`
- StartTime time.Time `json:"startTime"`
-
- LeaderInfo struct {
- Name string `json:"leader"`
- Uptime string `json:"uptime"`
- StartTime time.Time `json:"startTime"`
- } `json:"leaderInfo"`
-
- RecvAppendRequestCnt uint64 `json:"recvAppendRequestCnt,"`
- RecvingPkgRate float64 `json:"recvPkgRate,omitempty"`
- RecvingBandwidthRate float64 `json:"recvBandwidthRate,omitempty"`
-
- SendAppendRequestCnt uint64 `json:"sendAppendRequestCnt"`
- SendingPkgRate float64 `json:"sendPkgRate,omitempty"`
- SendingBandwidthRate float64 `json:"sendBandwidthRate,omitempty"`
-
- sendRateQueue *statsQueue
- recvRateQueue *statsQueue
-}
-
-func (ss *ServerStats) JSON() []byte {
- ss.Lock()
- stats := ss.serverStats
- stats.SendingPkgRate, stats.SendingBandwidthRate = stats.sendRateQueue.Rate()
- stats.RecvingPkgRate, stats.RecvingBandwidthRate = stats.recvRateQueue.Rate()
- stats.LeaderInfo.Uptime = time.Since(stats.LeaderInfo.StartTime).String()
- ss.Unlock()
- b, err := json.Marshal(stats)
- // TODO(jonboulle): appropriate error handling?
- if err != nil {
- log.Printf("stats: error marshalling server stats: %v", err)
- }
- return b
-}
-
-// RecvAppendReq updates the ServerStats in response to an AppendRequest
-// from the given leader being received
-func (ss *ServerStats) RecvAppendReq(leader string, reqSize int) {
- ss.Lock()
- defer ss.Unlock()
-
- now := time.Now()
-
- ss.State = raft.StateFollower
- if leader != ss.LeaderInfo.Name {
- ss.LeaderInfo.Name = leader
- ss.LeaderInfo.StartTime = now
- }
-
- ss.recvRateQueue.Insert(
- &RequestStats{
- SendingTime: now,
- Size: reqSize,
- },
- )
- ss.RecvAppendRequestCnt++
-}
-
-// SendAppendReq updates the ServerStats in response to an AppendRequest
-// being sent by this server
-func (ss *ServerStats) SendAppendReq(reqSize int) {
- ss.Lock()
- defer ss.Unlock()
-
- ss.becomeLeader()
-
- ss.sendRateQueue.Insert(
- &RequestStats{
- SendingTime: time.Now(),
- Size: reqSize,
- },
- )
-
- ss.SendAppendRequestCnt++
-}
-
-func (ss *ServerStats) BecomeLeader() {
- ss.Lock()
- defer ss.Unlock()
- ss.becomeLeader()
-}
-
-func (ss *ServerStats) becomeLeader() {
- if ss.State != raft.StateLeader {
- ss.State = raft.StateLeader
- ss.LeaderInfo.Name = ss.ID
- ss.LeaderInfo.StartTime = time.Now()
- }
-}
diff --git a/vendor/go.etcd.io/etcd/etcdserver/api/v2stats/stats.go b/vendor/go.etcd.io/etcd/etcdserver/api/v2stats/stats.go
deleted file mode 100644
index c50a200..0000000
--- a/vendor/go.etcd.io/etcd/etcdserver/api/v2stats/stats.go
+++ /dev/null
@@ -1,30 +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
-
-import "github.com/coreos/pkg/capnslog"
-
-var plog = capnslog.NewPackageLogger("go.etcd.io/etcd", "etcdserver/stats")
-
-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/vendor/go.etcd.io/etcd/etcdserver/api/v2store/doc.go b/vendor/go.etcd.io/etcd/etcdserver/api/v2store/doc.go
deleted file mode 100644
index 1933e4c..0000000
--- a/vendor/go.etcd.io/etcd/etcdserver/api/v2store/doc.go
+++ /dev/null
@@ -1,17 +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 v2store defines etcd's in-memory key/value store in v2 API.
-// To be deprecated in favor of v3 storage.
-package v2store
diff --git a/vendor/go.etcd.io/etcd/etcdserver/api/v2store/event.go b/vendor/go.etcd.io/etcd/etcdserver/api/v2store/event.go
deleted file mode 100644
index 33e9017..0000000
--- a/vendor/go.etcd.io/etcd/etcdserver/api/v2store/event.go
+++ /dev/null
@@ -1,71 +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 v2store
-
-const (
- Get = "get"
- Create = "create"
- Set = "set"
- Update = "update"
- Delete = "delete"
- CompareAndSwap = "compareAndSwap"
- CompareAndDelete = "compareAndDelete"
- Expire = "expire"
-)
-
-type Event struct {
- Action string `json:"action"`
- Node *NodeExtern `json:"node,omitempty"`
- PrevNode *NodeExtern `json:"prevNode,omitempty"`
- EtcdIndex uint64 `json:"-"`
- Refresh bool `json:"refresh,omitempty"`
-}
-
-func newEvent(action string, key string, modifiedIndex, createdIndex uint64) *Event {
- n := &NodeExtern{
- Key: key,
- ModifiedIndex: modifiedIndex,
- CreatedIndex: createdIndex,
- }
-
- return &Event{
- Action: action,
- Node: n,
- }
-}
-
-func (e *Event) IsCreated() bool {
- if e.Action == Create {
- return true
- }
- return e.Action == Set && e.PrevNode == nil
-}
-
-func (e *Event) Index() uint64 {
- return e.Node.ModifiedIndex
-}
-
-func (e *Event) Clone() *Event {
- return &Event{
- Action: e.Action,
- EtcdIndex: e.EtcdIndex,
- Node: e.Node.Clone(),
- PrevNode: e.PrevNode.Clone(),
- }
-}
-
-func (e *Event) SetRefresh() {
- e.Refresh = true
-}
diff --git a/vendor/go.etcd.io/etcd/etcdserver/api/v2store/event_history.go b/vendor/go.etcd.io/etcd/etcdserver/api/v2store/event_history.go
deleted file mode 100644
index e4a969f..0000000
--- a/vendor/go.etcd.io/etcd/etcdserver/api/v2store/event_history.go
+++ /dev/null
@@ -1,129 +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 v2store
-
-import (
- "fmt"
- "path"
- "strings"
- "sync"
-
- "go.etcd.io/etcd/etcdserver/api/v2error"
-)
-
-type EventHistory struct {
- Queue eventQueue
- StartIndex uint64
- LastIndex uint64
- rwl sync.RWMutex
-}
-
-func newEventHistory(capacity int) *EventHistory {
- return &EventHistory{
- Queue: eventQueue{
- Capacity: capacity,
- Events: make([]*Event, capacity),
- },
- }
-}
-
-// addEvent function adds event into the eventHistory
-func (eh *EventHistory) addEvent(e *Event) *Event {
- eh.rwl.Lock()
- defer eh.rwl.Unlock()
-
- eh.Queue.insert(e)
-
- eh.LastIndex = e.Index()
-
- eh.StartIndex = eh.Queue.Events[eh.Queue.Front].Index()
-
- return e
-}
-
-// scan enumerates events from the index history and stops at the first point
-// where the key matches.
-func (eh *EventHistory) scan(key string, recursive bool, index uint64) (*Event, *v2error.Error) {
- eh.rwl.RLock()
- defer eh.rwl.RUnlock()
-
- // index should be after the event history's StartIndex
- if index < eh.StartIndex {
- return nil,
- v2error.NewError(v2error.EcodeEventIndexCleared,
- fmt.Sprintf("the requested history has been cleared [%v/%v]",
- eh.StartIndex, index), 0)
- }
-
- // the index should come before the size of the queue minus the duplicate count
- if index > eh.LastIndex { // future index
- return nil, nil
- }
-
- offset := index - eh.StartIndex
- i := (eh.Queue.Front + int(offset)) % eh.Queue.Capacity
-
- for {
- e := eh.Queue.Events[i]
-
- if !e.Refresh {
- ok := e.Node.Key == key
-
- if recursive {
- // add tailing slash
- nkey := path.Clean(key)
- if nkey[len(nkey)-1] != '/' {
- nkey = nkey + "/"
- }
-
- ok = ok || strings.HasPrefix(e.Node.Key, nkey)
- }
-
- if (e.Action == Delete || e.Action == Expire) && e.PrevNode != nil && e.PrevNode.Dir {
- ok = ok || strings.HasPrefix(key, e.PrevNode.Key)
- }
-
- if ok {
- return e, nil
- }
- }
-
- i = (i + 1) % eh.Queue.Capacity
-
- if i == eh.Queue.Back {
- return nil, nil
- }
- }
-}
-
-// clone will be protected by a stop-world lock
-// do not need to obtain internal lock
-func (eh *EventHistory) clone() *EventHistory {
- clonedQueue := eventQueue{
- Capacity: eh.Queue.Capacity,
- Events: make([]*Event, eh.Queue.Capacity),
- Size: eh.Queue.Size,
- Front: eh.Queue.Front,
- Back: eh.Queue.Back,
- }
-
- copy(clonedQueue.Events, eh.Queue.Events)
- return &EventHistory{
- StartIndex: eh.StartIndex,
- Queue: clonedQueue,
- LastIndex: eh.LastIndex,
- }
-
-}
diff --git a/vendor/go.etcd.io/etcd/etcdserver/api/v2store/event_queue.go b/vendor/go.etcd.io/etcd/etcdserver/api/v2store/event_queue.go
deleted file mode 100644
index 7ea03de..0000000
--- a/vendor/go.etcd.io/etcd/etcdserver/api/v2store/event_queue.go
+++ /dev/null
@@ -1,34 +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 v2store
-
-type eventQueue struct {
- Events []*Event
- Size int
- Front int
- Back int
- Capacity int
-}
-
-func (eq *eventQueue) insert(e *Event) {
- eq.Events[eq.Back] = e
- eq.Back = (eq.Back + 1) % eq.Capacity
-
- if eq.Size == eq.Capacity { //dequeue
- eq.Front = (eq.Front + 1) % eq.Capacity
- } else {
- eq.Size++
- }
-}
diff --git a/vendor/go.etcd.io/etcd/etcdserver/api/v2store/metrics.go b/vendor/go.etcd.io/etcd/etcdserver/api/v2store/metrics.go
deleted file mode 100644
index 5adea1e..0000000
--- a/vendor/go.etcd.io/etcd/etcdserver/api/v2store/metrics.go
+++ /dev/null
@@ -1,130 +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 v2store
-
-import "github.com/prometheus/client_golang/prometheus"
-
-// Set of raw Prometheus metrics.
-// Labels
-// * action = declared in event.go
-// * outcome = Outcome
-// Do not increment directly, use Report* methods.
-var (
- readCounter = prometheus.NewCounterVec(
- prometheus.CounterOpts{
- Namespace: "etcd_debugging",
- Subsystem: "store",
- Name: "reads_total",
- Help: "Total number of reads action by (get/getRecursive), local to this member.",
- }, []string{"action"})
-
- writeCounter = prometheus.NewCounterVec(
- prometheus.CounterOpts{
- Namespace: "etcd_debugging",
- Subsystem: "store",
- Name: "writes_total",
- Help: "Total number of writes (e.g. set/compareAndDelete) seen by this member.",
- }, []string{"action"})
-
- readFailedCounter = prometheus.NewCounterVec(
- prometheus.CounterOpts{
- Namespace: "etcd_debugging",
- Subsystem: "store",
- Name: "reads_failed_total",
- Help: "Failed read actions by (get/getRecursive), local to this member.",
- }, []string{"action"})
-
- writeFailedCounter = prometheus.NewCounterVec(
- prometheus.CounterOpts{
- Namespace: "etcd_debugging",
- Subsystem: "store",
- Name: "writes_failed_total",
- Help: "Failed write actions (e.g. set/compareAndDelete), seen by this member.",
- }, []string{"action"})
-
- expireCounter = prometheus.NewCounter(
- prometheus.CounterOpts{
- Namespace: "etcd_debugging",
- Subsystem: "store",
- Name: "expires_total",
- Help: "Total number of expired keys.",
- })
-
- watchRequests = prometheus.NewCounter(
- prometheus.CounterOpts{
- Namespace: "etcd_debugging",
- Subsystem: "store",
- Name: "watch_requests_total",
- Help: "Total number of incoming watch requests (new or reestablished).",
- })
-
- watcherCount = prometheus.NewGauge(
- prometheus.GaugeOpts{
- Namespace: "etcd_debugging",
- Subsystem: "store",
- Name: "watchers",
- Help: "Count of currently active watchers.",
- })
-)
-
-const (
- GetRecursive = "getRecursive"
-)
-
-func init() {
- if prometheus.Register(readCounter) != nil {
- // Tests will try to double register since the tests use both
- // store and store_test packages; ignore second attempts.
- return
- }
- prometheus.MustRegister(writeCounter)
- prometheus.MustRegister(expireCounter)
- prometheus.MustRegister(watchRequests)
- prometheus.MustRegister(watcherCount)
-}
-
-func reportReadSuccess(readAction string) {
- readCounter.WithLabelValues(readAction).Inc()
-}
-
-func reportReadFailure(readAction string) {
- readCounter.WithLabelValues(readAction).Inc()
- readFailedCounter.WithLabelValues(readAction).Inc()
-}
-
-func reportWriteSuccess(writeAction string) {
- writeCounter.WithLabelValues(writeAction).Inc()
-}
-
-func reportWriteFailure(writeAction string) {
- writeCounter.WithLabelValues(writeAction).Inc()
- writeFailedCounter.WithLabelValues(writeAction).Inc()
-}
-
-func reportExpiredKey() {
- expireCounter.Inc()
-}
-
-func reportWatchRequest() {
- watchRequests.Inc()
-}
-
-func reportWatcherAdded() {
- watcherCount.Inc()
-}
-
-func reportWatcherRemoved() {
- watcherCount.Dec()
-}
diff --git a/vendor/go.etcd.io/etcd/etcdserver/api/v2store/node.go b/vendor/go.etcd.io/etcd/etcdserver/api/v2store/node.go
deleted file mode 100644
index 38a6984..0000000
--- a/vendor/go.etcd.io/etcd/etcdserver/api/v2store/node.go
+++ /dev/null
@@ -1,396 +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 v2store
-
-import (
- "path"
- "sort"
- "time"
-
- "go.etcd.io/etcd/etcdserver/api/v2error"
-
- "github.com/jonboulle/clockwork"
-)
-
-// explanations of Compare function result
-const (
- CompareMatch = iota
- CompareIndexNotMatch
- CompareValueNotMatch
- CompareNotMatch
-)
-
-var Permanent time.Time
-
-// node is the basic element in the store system.
-// A key-value pair will have a string value
-// A directory will have a children map
-type node struct {
- Path string
-
- CreatedIndex uint64
- ModifiedIndex uint64
-
- Parent *node `json:"-"` // should not encode this field! avoid circular dependency.
-
- ExpireTime time.Time
- Value string // for key-value pair
- Children map[string]*node // for directory
-
- // A reference to the store this node is attached to.
- store *store
-}
-
-// newKV creates a Key-Value pair
-func newKV(store *store, nodePath string, value string, createdIndex uint64, parent *node, expireTime time.Time) *node {
- return &node{
- Path: nodePath,
- CreatedIndex: createdIndex,
- ModifiedIndex: createdIndex,
- Parent: parent,
- store: store,
- ExpireTime: expireTime,
- Value: value,
- }
-}
-
-// newDir creates a directory
-func newDir(store *store, nodePath string, createdIndex uint64, parent *node, expireTime time.Time) *node {
- return &node{
- Path: nodePath,
- CreatedIndex: createdIndex,
- ModifiedIndex: createdIndex,
- Parent: parent,
- ExpireTime: expireTime,
- Children: make(map[string]*node),
- store: store,
- }
-}
-
-// IsHidden function checks if the node is a hidden node. A hidden node
-// will begin with '_'
-// A hidden node will not be shown via get command under a directory
-// For example if we have /foo/_hidden and /foo/notHidden, get "/foo"
-// will only return /foo/notHidden
-func (n *node) IsHidden() bool {
- _, name := path.Split(n.Path)
-
- return name[0] == '_'
-}
-
-// IsPermanent function checks if the node is a permanent one.
-func (n *node) IsPermanent() bool {
- // we use a uninitialized time.Time to indicate the node is a
- // permanent one.
- // the uninitialized time.Time should equal zero.
- return n.ExpireTime.IsZero()
-}
-
-// IsDir function checks whether the node is a directory.
-// If the node is a directory, the function will return true.
-// Otherwise the function will return false.
-func (n *node) IsDir() bool {
- return n.Children != nil
-}
-
-// Read function gets the value of the node.
-// If the receiver node is not a key-value pair, a "Not A File" error will be returned.
-func (n *node) Read() (string, *v2error.Error) {
- if n.IsDir() {
- return "", v2error.NewError(v2error.EcodeNotFile, "", n.store.CurrentIndex)
- }
-
- return n.Value, nil
-}
-
-// Write function set the value of the node to the given value.
-// If the receiver node is a directory, a "Not A File" error will be returned.
-func (n *node) Write(value string, index uint64) *v2error.Error {
- if n.IsDir() {
- return v2error.NewError(v2error.EcodeNotFile, "", n.store.CurrentIndex)
- }
-
- n.Value = value
- n.ModifiedIndex = index
-
- return nil
-}
-
-func (n *node) expirationAndTTL(clock clockwork.Clock) (*time.Time, int64) {
- if !n.IsPermanent() {
- /* compute ttl as:
- ceiling( (expireTime - timeNow) / nanosecondsPerSecond )
- which ranges from 1..n
- rather than as:
- ( (expireTime - timeNow) / nanosecondsPerSecond ) + 1
- which ranges 1..n+1
- */
- ttlN := n.ExpireTime.Sub(clock.Now())
- ttl := ttlN / time.Second
- if (ttlN % time.Second) > 0 {
- ttl++
- }
- t := n.ExpireTime.UTC()
- return &t, int64(ttl)
- }
- return nil, 0
-}
-
-// List function return a slice of nodes under the receiver node.
-// If the receiver node is not a directory, a "Not A Directory" error will be returned.
-func (n *node) List() ([]*node, *v2error.Error) {
- if !n.IsDir() {
- return nil, v2error.NewError(v2error.EcodeNotDir, "", n.store.CurrentIndex)
- }
-
- nodes := make([]*node, len(n.Children))
-
- i := 0
- for _, node := range n.Children {
- nodes[i] = node
- i++
- }
-
- return nodes, nil
-}
-
-// GetChild function returns the child node under the directory node.
-// On success, it returns the file node
-func (n *node) GetChild(name string) (*node, *v2error.Error) {
- if !n.IsDir() {
- return nil, v2error.NewError(v2error.EcodeNotDir, n.Path, n.store.CurrentIndex)
- }
-
- child, ok := n.Children[name]
-
- if ok {
- return child, nil
- }
-
- return nil, nil
-}
-
-// Add function adds a node to the receiver node.
-// If the receiver is not a directory, a "Not A Directory" error will be returned.
-// If there is an existing node with the same name under the directory, a "Already Exist"
-// error will be returned
-func (n *node) Add(child *node) *v2error.Error {
- if !n.IsDir() {
- return v2error.NewError(v2error.EcodeNotDir, "", n.store.CurrentIndex)
- }
-
- _, name := path.Split(child.Path)
-
- if _, ok := n.Children[name]; ok {
- return v2error.NewError(v2error.EcodeNodeExist, "", n.store.CurrentIndex)
- }
-
- n.Children[name] = child
-
- return nil
-}
-
-// Remove function remove the node.
-func (n *node) Remove(dir, recursive bool, callback func(path string)) *v2error.Error {
- if !n.IsDir() { // key-value pair
- _, name := path.Split(n.Path)
-
- // find its parent and remove the node from the map
- if n.Parent != nil && n.Parent.Children[name] == n {
- delete(n.Parent.Children, name)
- }
-
- if callback != nil {
- callback(n.Path)
- }
-
- if !n.IsPermanent() {
- n.store.ttlKeyHeap.remove(n)
- }
-
- return nil
- }
-
- if !dir {
- // cannot delete a directory without dir set to true
- return v2error.NewError(v2error.EcodeNotFile, n.Path, n.store.CurrentIndex)
- }
-
- if len(n.Children) != 0 && !recursive {
- // cannot delete a directory if it is not empty and the operation
- // is not recursive
- return v2error.NewError(v2error.EcodeDirNotEmpty, n.Path, n.store.CurrentIndex)
- }
-
- for _, child := range n.Children { // delete all children
- child.Remove(true, true, callback)
- }
-
- // delete self
- _, name := path.Split(n.Path)
- if n.Parent != nil && n.Parent.Children[name] == n {
- delete(n.Parent.Children, name)
-
- if callback != nil {
- callback(n.Path)
- }
-
- if !n.IsPermanent() {
- n.store.ttlKeyHeap.remove(n)
- }
- }
-
- return nil
-}
-
-func (n *node) Repr(recursive, sorted bool, clock clockwork.Clock) *NodeExtern {
- if n.IsDir() {
- node := &NodeExtern{
- Key: n.Path,
- Dir: true,
- ModifiedIndex: n.ModifiedIndex,
- CreatedIndex: n.CreatedIndex,
- }
- node.Expiration, node.TTL = n.expirationAndTTL(clock)
-
- if !recursive {
- return node
- }
-
- children, _ := n.List()
- node.Nodes = make(NodeExterns, len(children))
-
- // we do not use the index in the children slice directly
- // we need to skip the hidden one
- i := 0
-
- for _, child := range children {
-
- if child.IsHidden() { // get will not list hidden node
- continue
- }
-
- node.Nodes[i] = child.Repr(recursive, sorted, clock)
-
- i++
- }
-
- // eliminate hidden nodes
- node.Nodes = node.Nodes[:i]
- if sorted {
- sort.Sort(node.Nodes)
- }
-
- return node
- }
-
- // since n.Value could be changed later, so we need to copy the value out
- value := n.Value
- node := &NodeExtern{
- Key: n.Path,
- Value: &value,
- ModifiedIndex: n.ModifiedIndex,
- CreatedIndex: n.CreatedIndex,
- }
- node.Expiration, node.TTL = n.expirationAndTTL(clock)
- return node
-}
-
-func (n *node) UpdateTTL(expireTime time.Time) {
- if !n.IsPermanent() {
- if expireTime.IsZero() {
- // from ttl to permanent
- n.ExpireTime = expireTime
- // remove from ttl heap
- n.store.ttlKeyHeap.remove(n)
- return
- }
-
- // update ttl
- n.ExpireTime = expireTime
- // update ttl heap
- n.store.ttlKeyHeap.update(n)
- return
- }
-
- if expireTime.IsZero() {
- return
- }
-
- // from permanent to ttl
- n.ExpireTime = expireTime
- // push into ttl heap
- n.store.ttlKeyHeap.push(n)
-}
-
-// Compare function compares node index and value with provided ones.
-// second result value explains result and equals to one of Compare.. constants
-func (n *node) Compare(prevValue string, prevIndex uint64) (ok bool, which int) {
- indexMatch := prevIndex == 0 || n.ModifiedIndex == prevIndex
- valueMatch := prevValue == "" || n.Value == prevValue
- ok = valueMatch && indexMatch
- switch {
- case valueMatch && indexMatch:
- which = CompareMatch
- case indexMatch && !valueMatch:
- which = CompareValueNotMatch
- case valueMatch && !indexMatch:
- which = CompareIndexNotMatch
- default:
- which = CompareNotMatch
- }
- return ok, which
-}
-
-// Clone function clone the node recursively and return the new node.
-// If the node is a directory, it will clone all the content under this directory.
-// If the node is a key-value pair, it will clone the pair.
-func (n *node) Clone() *node {
- if !n.IsDir() {
- newkv := newKV(n.store, n.Path, n.Value, n.CreatedIndex, n.Parent, n.ExpireTime)
- newkv.ModifiedIndex = n.ModifiedIndex
- return newkv
- }
-
- clone := newDir(n.store, n.Path, n.CreatedIndex, n.Parent, n.ExpireTime)
- clone.ModifiedIndex = n.ModifiedIndex
-
- for key, child := range n.Children {
- clone.Children[key] = child.Clone()
- }
-
- return clone
-}
-
-// recoverAndclean function help to do recovery.
-// Two things need to be done: 1. recovery structure; 2. delete expired nodes
-//
-// If the node is a directory, it will help recover children's parent pointer and recursively
-// call this function on its children.
-// We check the expire last since we need to recover the whole structure first and add all the
-// notifications into the event history.
-func (n *node) recoverAndclean() {
- if n.IsDir() {
- for _, child := range n.Children {
- child.Parent = n
- child.store = n.store
- child.recoverAndclean()
- }
- }
-
- if !n.ExpireTime.IsZero() {
- n.store.ttlKeyHeap.push(n)
- }
-}
diff --git a/vendor/go.etcd.io/etcd/etcdserver/api/v2store/node_extern.go b/vendor/go.etcd.io/etcd/etcdserver/api/v2store/node_extern.go
deleted file mode 100644
index b3bf5f3..0000000
--- a/vendor/go.etcd.io/etcd/etcdserver/api/v2store/node_extern.go
+++ /dev/null
@@ -1,116 +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 v2store
-
-import (
- "sort"
- "time"
-
- "github.com/jonboulle/clockwork"
-)
-
-// NodeExtern is the external representation of the
-// internal node with additional fields
-// PrevValue is the previous value of the node
-// TTL is time to live in second
-type NodeExtern struct {
- Key string `json:"key,omitempty"`
- Value *string `json:"value,omitempty"`
- Dir bool `json:"dir,omitempty"`
- Expiration *time.Time `json:"expiration,omitempty"`
- TTL int64 `json:"ttl,omitempty"`
- Nodes NodeExterns `json:"nodes,omitempty"`
- ModifiedIndex uint64 `json:"modifiedIndex,omitempty"`
- CreatedIndex uint64 `json:"createdIndex,omitempty"`
-}
-
-func (eNode *NodeExtern) loadInternalNode(n *node, recursive, sorted bool, clock clockwork.Clock) {
- if n.IsDir() { // node is a directory
- eNode.Dir = true
-
- children, _ := n.List()
- eNode.Nodes = make(NodeExterns, len(children))
-
- // we do not use the index in the children slice directly
- // we need to skip the hidden one
- i := 0
-
- for _, child := range children {
- if child.IsHidden() { // get will not return hidden nodes
- continue
- }
-
- eNode.Nodes[i] = child.Repr(recursive, sorted, clock)
- i++
- }
-
- // eliminate hidden nodes
- eNode.Nodes = eNode.Nodes[:i]
-
- if sorted {
- sort.Sort(eNode.Nodes)
- }
-
- } else { // node is a file
- value, _ := n.Read()
- eNode.Value = &value
- }
-
- eNode.Expiration, eNode.TTL = n.expirationAndTTL(clock)
-}
-
-func (eNode *NodeExtern) Clone() *NodeExtern {
- if eNode == nil {
- return nil
- }
- nn := &NodeExtern{
- Key: eNode.Key,
- Dir: eNode.Dir,
- TTL: eNode.TTL,
- ModifiedIndex: eNode.ModifiedIndex,
- CreatedIndex: eNode.CreatedIndex,
- }
- if eNode.Value != nil {
- s := *eNode.Value
- nn.Value = &s
- }
- if eNode.Expiration != nil {
- t := *eNode.Expiration
- nn.Expiration = &t
- }
- if eNode.Nodes != nil {
- nn.Nodes = make(NodeExterns, len(eNode.Nodes))
- for i, n := range eNode.Nodes {
- nn.Nodes[i] = n.Clone()
- }
- }
- return nn
-}
-
-type NodeExterns []*NodeExtern
-
-// interfaces for sorting
-
-func (ns NodeExterns) Len() int {
- return len(ns)
-}
-
-func (ns NodeExterns) Less(i, j int) bool {
- return ns[i].Key < ns[j].Key
-}
-
-func (ns NodeExterns) Swap(i, j int) {
- ns[i], ns[j] = ns[j], ns[i]
-}
diff --git a/vendor/go.etcd.io/etcd/etcdserver/api/v2store/stats.go b/vendor/go.etcd.io/etcd/etcdserver/api/v2store/stats.go
deleted file mode 100644
index 45bc97f..0000000
--- a/vendor/go.etcd.io/etcd/etcdserver/api/v2store/stats.go
+++ /dev/null
@@ -1,145 +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 v2store
-
-import (
- "encoding/json"
- "sync/atomic"
-)
-
-const (
- SetSuccess = iota
- SetFail
- DeleteSuccess
- DeleteFail
- CreateSuccess
- CreateFail
- UpdateSuccess
- UpdateFail
- CompareAndSwapSuccess
- CompareAndSwapFail
- GetSuccess
- GetFail
- ExpireCount
- CompareAndDeleteSuccess
- CompareAndDeleteFail
-)
-
-type Stats struct {
- // Number of get requests
-
- GetSuccess uint64 `json:"getsSuccess"`
- GetFail uint64 `json:"getsFail"`
-
- // Number of sets requests
-
- SetSuccess uint64 `json:"setsSuccess"`
- SetFail uint64 `json:"setsFail"`
-
- // Number of delete requests
-
- DeleteSuccess uint64 `json:"deleteSuccess"`
- DeleteFail uint64 `json:"deleteFail"`
-
- // Number of update requests
-
- UpdateSuccess uint64 `json:"updateSuccess"`
- UpdateFail uint64 `json:"updateFail"`
-
- // Number of create requests
-
- CreateSuccess uint64 `json:"createSuccess"`
- CreateFail uint64 `json:"createFail"`
-
- // Number of testAndSet requests
-
- CompareAndSwapSuccess uint64 `json:"compareAndSwapSuccess"`
- CompareAndSwapFail uint64 `json:"compareAndSwapFail"`
-
- // Number of compareAndDelete requests
-
- CompareAndDeleteSuccess uint64 `json:"compareAndDeleteSuccess"`
- CompareAndDeleteFail uint64 `json:"compareAndDeleteFail"`
-
- ExpireCount uint64 `json:"expireCount"`
-
- Watchers uint64 `json:"watchers"`
-}
-
-func newStats() *Stats {
- s := new(Stats)
- return s
-}
-
-func (s *Stats) clone() *Stats {
- return &Stats{
- GetSuccess: s.GetSuccess,
- GetFail: s.GetFail,
- SetSuccess: s.SetSuccess,
- SetFail: s.SetFail,
- DeleteSuccess: s.DeleteSuccess,
- DeleteFail: s.DeleteFail,
- UpdateSuccess: s.UpdateSuccess,
- UpdateFail: s.UpdateFail,
- CreateSuccess: s.CreateSuccess,
- CreateFail: s.CreateFail,
- CompareAndSwapSuccess: s.CompareAndSwapSuccess,
- CompareAndSwapFail: s.CompareAndSwapFail,
- CompareAndDeleteSuccess: s.CompareAndDeleteSuccess,
- CompareAndDeleteFail: s.CompareAndDeleteFail,
- ExpireCount: s.ExpireCount,
- Watchers: s.Watchers,
- }
-}
-
-func (s *Stats) toJson() []byte {
- b, _ := json.Marshal(s)
- return b
-}
-
-func (s *Stats) Inc(field int) {
- switch field {
- case SetSuccess:
- atomic.AddUint64(&s.SetSuccess, 1)
- case SetFail:
- atomic.AddUint64(&s.SetFail, 1)
- case CreateSuccess:
- atomic.AddUint64(&s.CreateSuccess, 1)
- case CreateFail:
- atomic.AddUint64(&s.CreateFail, 1)
- case DeleteSuccess:
- atomic.AddUint64(&s.DeleteSuccess, 1)
- case DeleteFail:
- atomic.AddUint64(&s.DeleteFail, 1)
- case GetSuccess:
- atomic.AddUint64(&s.GetSuccess, 1)
- case GetFail:
- atomic.AddUint64(&s.GetFail, 1)
- case UpdateSuccess:
- atomic.AddUint64(&s.UpdateSuccess, 1)
- case UpdateFail:
- atomic.AddUint64(&s.UpdateFail, 1)
- case CompareAndSwapSuccess:
- atomic.AddUint64(&s.CompareAndSwapSuccess, 1)
- case CompareAndSwapFail:
- atomic.AddUint64(&s.CompareAndSwapFail, 1)
- case CompareAndDeleteSuccess:
- atomic.AddUint64(&s.CompareAndDeleteSuccess, 1)
- case CompareAndDeleteFail:
- atomic.AddUint64(&s.CompareAndDeleteFail, 1)
- case ExpireCount:
- atomic.AddUint64(&s.ExpireCount, 1)
- }
-}
diff --git a/vendor/go.etcd.io/etcd/etcdserver/api/v2store/store.go b/vendor/go.etcd.io/etcd/etcdserver/api/v2store/store.go
deleted file mode 100644
index ce94043..0000000
--- a/vendor/go.etcd.io/etcd/etcdserver/api/v2store/store.go
+++ /dev/null
@@ -1,791 +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 v2store
-
-import (
- "encoding/json"
- "fmt"
- "path"
- "strconv"
- "strings"
- "sync"
- "time"
-
- "go.etcd.io/etcd/etcdserver/api/v2error"
- "go.etcd.io/etcd/pkg/types"
-
- "github.com/jonboulle/clockwork"
-)
-
-// The default version to set when the store is first initialized.
-const defaultVersion = 2
-
-var minExpireTime time.Time
-
-func init() {
- minExpireTime, _ = time.Parse(time.RFC3339, "2000-01-01T00:00:00Z")
-}
-
-type Store interface {
- Version() int
- Index() uint64
-
- Get(nodePath string, recursive, sorted bool) (*Event, error)
- Set(nodePath string, dir bool, value string, expireOpts TTLOptionSet) (*Event, error)
- Update(nodePath string, newValue string, expireOpts TTLOptionSet) (*Event, error)
- Create(nodePath string, dir bool, value string, unique bool,
- expireOpts TTLOptionSet) (*Event, error)
- CompareAndSwap(nodePath string, prevValue string, prevIndex uint64,
- value string, expireOpts TTLOptionSet) (*Event, error)
- Delete(nodePath string, dir, recursive bool) (*Event, error)
- CompareAndDelete(nodePath string, prevValue string, prevIndex uint64) (*Event, error)
-
- Watch(prefix string, recursive, stream bool, sinceIndex uint64) (Watcher, error)
-
- Save() ([]byte, error)
- Recovery(state []byte) error
-
- Clone() Store
- SaveNoCopy() ([]byte, error)
-
- JsonStats() []byte
- DeleteExpiredKeys(cutoff time.Time)
-
- HasTTLKeys() bool
-}
-
-type TTLOptionSet struct {
- ExpireTime time.Time
- Refresh bool
-}
-
-type store struct {
- Root *node
- WatcherHub *watcherHub
- CurrentIndex uint64
- Stats *Stats
- CurrentVersion int
- ttlKeyHeap *ttlKeyHeap // need to recovery manually
- worldLock sync.RWMutex // stop the world lock
- clock clockwork.Clock
- readonlySet types.Set
-}
-
-// New creates a store where the given namespaces will be created as initial directories.
-func New(namespaces ...string) Store {
- s := newStore(namespaces...)
- s.clock = clockwork.NewRealClock()
- return s
-}
-
-func newStore(namespaces ...string) *store {
- s := new(store)
- s.CurrentVersion = defaultVersion
- s.Root = newDir(s, "/", s.CurrentIndex, nil, Permanent)
- for _, namespace := range namespaces {
- s.Root.Add(newDir(s, namespace, s.CurrentIndex, s.Root, Permanent))
- }
- s.Stats = newStats()
- s.WatcherHub = newWatchHub(1000)
- s.ttlKeyHeap = newTtlKeyHeap()
- s.readonlySet = types.NewUnsafeSet(append(namespaces, "/")...)
- return s
-}
-
-// Version retrieves current version of the store.
-func (s *store) Version() int {
- return s.CurrentVersion
-}
-
-// Index retrieves the current index of the store.
-func (s *store) Index() uint64 {
- s.worldLock.RLock()
- defer s.worldLock.RUnlock()
- return s.CurrentIndex
-}
-
-// Get returns a get event.
-// If recursive is true, it will return all the content under the node path.
-// If sorted is true, it will sort the content by keys.
-func (s *store) Get(nodePath string, recursive, sorted bool) (*Event, error) {
- var err *v2error.Error
-
- s.worldLock.RLock()
- defer s.worldLock.RUnlock()
-
- defer func() {
- if err == nil {
- s.Stats.Inc(GetSuccess)
- if recursive {
- reportReadSuccess(GetRecursive)
- } else {
- reportReadSuccess(Get)
- }
- return
- }
-
- s.Stats.Inc(GetFail)
- if recursive {
- reportReadFailure(GetRecursive)
- } else {
- reportReadFailure(Get)
- }
- }()
-
- n, err := s.internalGet(nodePath)
- if err != nil {
- return nil, err
- }
-
- e := newEvent(Get, nodePath, n.ModifiedIndex, n.CreatedIndex)
- e.EtcdIndex = s.CurrentIndex
- e.Node.loadInternalNode(n, recursive, sorted, s.clock)
-
- return e, nil
-}
-
-// Create creates the node at nodePath. Create will help to create intermediate directories with no ttl.
-// If the node has already existed, create will fail.
-// If any node on the path is a file, create will fail.
-func (s *store) Create(nodePath string, dir bool, value string, unique bool, expireOpts TTLOptionSet) (*Event, error) {
- var err *v2error.Error
-
- s.worldLock.Lock()
- defer s.worldLock.Unlock()
-
- defer func() {
- if err == nil {
- s.Stats.Inc(CreateSuccess)
- reportWriteSuccess(Create)
- return
- }
-
- s.Stats.Inc(CreateFail)
- reportWriteFailure(Create)
- }()
-
- e, err := s.internalCreate(nodePath, dir, value, unique, false, expireOpts.ExpireTime, Create)
- if err != nil {
- return nil, err
- }
-
- e.EtcdIndex = s.CurrentIndex
- s.WatcherHub.notify(e)
-
- return e, nil
-}
-
-// Set creates or replace the node at nodePath.
-func (s *store) Set(nodePath string, dir bool, value string, expireOpts TTLOptionSet) (*Event, error) {
- var err *v2error.Error
-
- s.worldLock.Lock()
- defer s.worldLock.Unlock()
-
- defer func() {
- if err == nil {
- s.Stats.Inc(SetSuccess)
- reportWriteSuccess(Set)
- return
- }
-
- s.Stats.Inc(SetFail)
- reportWriteFailure(Set)
- }()
-
- // Get prevNode value
- n, getErr := s.internalGet(nodePath)
- if getErr != nil && getErr.ErrorCode != v2error.EcodeKeyNotFound {
- err = getErr
- return nil, err
- }
-
- if expireOpts.Refresh {
- if getErr != nil {
- err = getErr
- return nil, err
- }
- value = n.Value
- }
-
- // Set new value
- e, err := s.internalCreate(nodePath, dir, value, false, true, expireOpts.ExpireTime, Set)
- if err != nil {
- return nil, err
- }
- e.EtcdIndex = s.CurrentIndex
-
- // Put prevNode into event
- if getErr == nil {
- prev := newEvent(Get, nodePath, n.ModifiedIndex, n.CreatedIndex)
- prev.Node.loadInternalNode(n, false, false, s.clock)
- e.PrevNode = prev.Node
- }
-
- if !expireOpts.Refresh {
- s.WatcherHub.notify(e)
- } else {
- e.SetRefresh()
- s.WatcherHub.add(e)
- }
-
- return e, nil
-}
-
-// returns user-readable cause of failed comparison
-func getCompareFailCause(n *node, which int, prevValue string, prevIndex uint64) string {
- switch which {
- case CompareIndexNotMatch:
- return fmt.Sprintf("[%v != %v]", prevIndex, n.ModifiedIndex)
- case CompareValueNotMatch:
- return fmt.Sprintf("[%v != %v]", prevValue, n.Value)
- default:
- return fmt.Sprintf("[%v != %v] [%v != %v]", prevValue, n.Value, prevIndex, n.ModifiedIndex)
- }
-}
-
-func (s *store) CompareAndSwap(nodePath string, prevValue string, prevIndex uint64,
- value string, expireOpts TTLOptionSet) (*Event, error) {
-
- var err *v2error.Error
-
- s.worldLock.Lock()
- defer s.worldLock.Unlock()
-
- defer func() {
- if err == nil {
- s.Stats.Inc(CompareAndSwapSuccess)
- reportWriteSuccess(CompareAndSwap)
- return
- }
-
- s.Stats.Inc(CompareAndSwapFail)
- reportWriteFailure(CompareAndSwap)
- }()
-
- nodePath = path.Clean(path.Join("/", nodePath))
- // we do not allow the user to change "/"
- if s.readonlySet.Contains(nodePath) {
- return nil, v2error.NewError(v2error.EcodeRootROnly, "/", s.CurrentIndex)
- }
-
- n, err := s.internalGet(nodePath)
- if err != nil {
- return nil, err
- }
- if n.IsDir() { // can only compare and swap file
- err = v2error.NewError(v2error.EcodeNotFile, nodePath, s.CurrentIndex)
- return nil, err
- }
-
- // If both of the prevValue and prevIndex are given, we will test both of them.
- // Command will be executed, only if both of the tests are successful.
- if ok, which := n.Compare(prevValue, prevIndex); !ok {
- cause := getCompareFailCause(n, which, prevValue, prevIndex)
- err = v2error.NewError(v2error.EcodeTestFailed, cause, s.CurrentIndex)
- return nil, err
- }
-
- if expireOpts.Refresh {
- value = n.Value
- }
-
- // update etcd index
- s.CurrentIndex++
-
- e := newEvent(CompareAndSwap, nodePath, s.CurrentIndex, n.CreatedIndex)
- e.EtcdIndex = s.CurrentIndex
- e.PrevNode = n.Repr(false, false, s.clock)
- eNode := e.Node
-
- // if test succeed, write the value
- n.Write(value, s.CurrentIndex)
- n.UpdateTTL(expireOpts.ExpireTime)
-
- // copy the value for safety
- valueCopy := value
- eNode.Value = &valueCopy
- eNode.Expiration, eNode.TTL = n.expirationAndTTL(s.clock)
-
- if !expireOpts.Refresh {
- s.WatcherHub.notify(e)
- } else {
- e.SetRefresh()
- s.WatcherHub.add(e)
- }
-
- return e, nil
-}
-
-// Delete deletes the node at the given path.
-// If the node is a directory, recursive must be true to delete it.
-func (s *store) Delete(nodePath string, dir, recursive bool) (*Event, error) {
- var err *v2error.Error
-
- s.worldLock.Lock()
- defer s.worldLock.Unlock()
-
- defer func() {
- if err == nil {
- s.Stats.Inc(DeleteSuccess)
- reportWriteSuccess(Delete)
- return
- }
-
- s.Stats.Inc(DeleteFail)
- reportWriteFailure(Delete)
- }()
-
- nodePath = path.Clean(path.Join("/", nodePath))
- // we do not allow the user to change "/"
- if s.readonlySet.Contains(nodePath) {
- return nil, v2error.NewError(v2error.EcodeRootROnly, "/", s.CurrentIndex)
- }
-
- // recursive implies dir
- if recursive {
- dir = true
- }
-
- n, err := s.internalGet(nodePath)
- if err != nil { // if the node does not exist, return error
- return nil, err
- }
-
- nextIndex := s.CurrentIndex + 1
- e := newEvent(Delete, nodePath, nextIndex, n.CreatedIndex)
- e.EtcdIndex = nextIndex
- e.PrevNode = n.Repr(false, false, s.clock)
- eNode := e.Node
-
- if n.IsDir() {
- eNode.Dir = true
- }
-
- callback := func(path string) { // notify function
- // notify the watchers with deleted set true
- s.WatcherHub.notifyWatchers(e, path, true)
- }
-
- err = n.Remove(dir, recursive, callback)
- if err != nil {
- return nil, err
- }
-
- // update etcd index
- s.CurrentIndex++
-
- s.WatcherHub.notify(e)
-
- return e, nil
-}
-
-func (s *store) CompareAndDelete(nodePath string, prevValue string, prevIndex uint64) (*Event, error) {
- var err *v2error.Error
-
- s.worldLock.Lock()
- defer s.worldLock.Unlock()
-
- defer func() {
- if err == nil {
- s.Stats.Inc(CompareAndDeleteSuccess)
- reportWriteSuccess(CompareAndDelete)
- return
- }
-
- s.Stats.Inc(CompareAndDeleteFail)
- reportWriteFailure(CompareAndDelete)
- }()
-
- nodePath = path.Clean(path.Join("/", nodePath))
-
- n, err := s.internalGet(nodePath)
- if err != nil { // if the node does not exist, return error
- return nil, err
- }
- if n.IsDir() { // can only compare and delete file
- return nil, v2error.NewError(v2error.EcodeNotFile, nodePath, s.CurrentIndex)
- }
-
- // If both of the prevValue and prevIndex are given, we will test both of them.
- // Command will be executed, only if both of the tests are successful.
- if ok, which := n.Compare(prevValue, prevIndex); !ok {
- cause := getCompareFailCause(n, which, prevValue, prevIndex)
- return nil, v2error.NewError(v2error.EcodeTestFailed, cause, s.CurrentIndex)
- }
-
- // update etcd index
- s.CurrentIndex++
-
- e := newEvent(CompareAndDelete, nodePath, s.CurrentIndex, n.CreatedIndex)
- e.EtcdIndex = s.CurrentIndex
- e.PrevNode = n.Repr(false, false, s.clock)
-
- callback := func(path string) { // notify function
- // notify the watchers with deleted set true
- s.WatcherHub.notifyWatchers(e, path, true)
- }
-
- err = n.Remove(false, false, callback)
- if err != nil {
- return nil, err
- }
-
- s.WatcherHub.notify(e)
-
- return e, nil
-}
-
-func (s *store) Watch(key string, recursive, stream bool, sinceIndex uint64) (Watcher, error) {
- s.worldLock.RLock()
- defer s.worldLock.RUnlock()
-
- key = path.Clean(path.Join("/", key))
- if sinceIndex == 0 {
- sinceIndex = s.CurrentIndex + 1
- }
- // WatcherHub does not know about the current index, so we need to pass it in
- w, err := s.WatcherHub.watch(key, recursive, stream, sinceIndex, s.CurrentIndex)
- if err != nil {
- return nil, err
- }
-
- return w, nil
-}
-
-// walk walks all the nodePath and apply the walkFunc on each directory
-func (s *store) walk(nodePath string, walkFunc func(prev *node, component string) (*node, *v2error.Error)) (*node, *v2error.Error) {
- components := strings.Split(nodePath, "/")
-
- curr := s.Root
- var err *v2error.Error
-
- for i := 1; i < len(components); i++ {
- if len(components[i]) == 0 { // ignore empty string
- return curr, nil
- }
-
- curr, err = walkFunc(curr, components[i])
- if err != nil {
- return nil, err
- }
- }
-
- return curr, nil
-}
-
-// Update updates the value/ttl of the node.
-// If the node is a file, the value and the ttl can be updated.
-// If the node is a directory, only the ttl can be updated.
-func (s *store) Update(nodePath string, newValue string, expireOpts TTLOptionSet) (*Event, error) {
- var err *v2error.Error
-
- s.worldLock.Lock()
- defer s.worldLock.Unlock()
-
- defer func() {
- if err == nil {
- s.Stats.Inc(UpdateSuccess)
- reportWriteSuccess(Update)
- return
- }
-
- s.Stats.Inc(UpdateFail)
- reportWriteFailure(Update)
- }()
-
- nodePath = path.Clean(path.Join("/", nodePath))
- // we do not allow the user to change "/"
- if s.readonlySet.Contains(nodePath) {
- return nil, v2error.NewError(v2error.EcodeRootROnly, "/", s.CurrentIndex)
- }
-
- currIndex, nextIndex := s.CurrentIndex, s.CurrentIndex+1
-
- n, err := s.internalGet(nodePath)
- if err != nil { // if the node does not exist, return error
- return nil, err
- }
- if n.IsDir() && len(newValue) != 0 {
- // if the node is a directory, we cannot update value to non-empty
- return nil, v2error.NewError(v2error.EcodeNotFile, nodePath, currIndex)
- }
-
- if expireOpts.Refresh {
- newValue = n.Value
- }
-
- e := newEvent(Update, nodePath, nextIndex, n.CreatedIndex)
- e.EtcdIndex = nextIndex
- e.PrevNode = n.Repr(false, false, s.clock)
- eNode := e.Node
-
- n.Write(newValue, nextIndex)
-
- if n.IsDir() {
- eNode.Dir = true
- } else {
- // copy the value for safety
- newValueCopy := newValue
- eNode.Value = &newValueCopy
- }
-
- // update ttl
- n.UpdateTTL(expireOpts.ExpireTime)
-
- eNode.Expiration, eNode.TTL = n.expirationAndTTL(s.clock)
-
- if !expireOpts.Refresh {
- s.WatcherHub.notify(e)
- } else {
- e.SetRefresh()
- s.WatcherHub.add(e)
- }
-
- s.CurrentIndex = nextIndex
-
- return e, nil
-}
-
-func (s *store) internalCreate(nodePath string, dir bool, value string, unique, replace bool,
- expireTime time.Time, action string) (*Event, *v2error.Error) {
-
- currIndex, nextIndex := s.CurrentIndex, s.CurrentIndex+1
-
- if unique { // append unique item under the node path
- nodePath += "/" + fmt.Sprintf("%020s", strconv.FormatUint(nextIndex, 10))
- }
-
- nodePath = path.Clean(path.Join("/", nodePath))
-
- // we do not allow the user to change "/"
- if s.readonlySet.Contains(nodePath) {
- return nil, v2error.NewError(v2error.EcodeRootROnly, "/", currIndex)
- }
-
- // Assume expire times that are way in the past are
- // This can occur when the time is serialized to JS
- if expireTime.Before(minExpireTime) {
- expireTime = Permanent
- }
-
- dirName, nodeName := path.Split(nodePath)
-
- // walk through the nodePath, create dirs and get the last directory node
- d, err := s.walk(dirName, s.checkDir)
-
- if err != nil {
- s.Stats.Inc(SetFail)
- reportWriteFailure(action)
- err.Index = currIndex
- return nil, err
- }
-
- e := newEvent(action, nodePath, nextIndex, nextIndex)
- eNode := e.Node
-
- n, _ := d.GetChild(nodeName)
-
- // force will try to replace an existing file
- if n != nil {
- if replace {
- if n.IsDir() {
- return nil, v2error.NewError(v2error.EcodeNotFile, nodePath, currIndex)
- }
- e.PrevNode = n.Repr(false, false, s.clock)
-
- n.Remove(false, false, nil)
- } else {
- return nil, v2error.NewError(v2error.EcodeNodeExist, nodePath, currIndex)
- }
- }
-
- if !dir { // create file
- // copy the value for safety
- valueCopy := value
- eNode.Value = &valueCopy
-
- n = newKV(s, nodePath, value, nextIndex, d, expireTime)
-
- } else { // create directory
- eNode.Dir = true
-
- n = newDir(s, nodePath, nextIndex, d, expireTime)
- }
-
- // we are sure d is a directory and does not have the children with name n.Name
- d.Add(n)
-
- // node with TTL
- if !n.IsPermanent() {
- s.ttlKeyHeap.push(n)
-
- eNode.Expiration, eNode.TTL = n.expirationAndTTL(s.clock)
- }
-
- s.CurrentIndex = nextIndex
-
- return e, nil
-}
-
-// InternalGet gets the node of the given nodePath.
-func (s *store) internalGet(nodePath string) (*node, *v2error.Error) {
- nodePath = path.Clean(path.Join("/", nodePath))
-
- walkFunc := func(parent *node, name string) (*node, *v2error.Error) {
-
- if !parent.IsDir() {
- err := v2error.NewError(v2error.EcodeNotDir, parent.Path, s.CurrentIndex)
- return nil, err
- }
-
- child, ok := parent.Children[name]
- if ok {
- return child, nil
- }
-
- return nil, v2error.NewError(v2error.EcodeKeyNotFound, path.Join(parent.Path, name), s.CurrentIndex)
- }
-
- f, err := s.walk(nodePath, walkFunc)
-
- if err != nil {
- return nil, err
- }
- return f, nil
-}
-
-// DeleteExpiredKeys will delete all expired keys
-func (s *store) DeleteExpiredKeys(cutoff time.Time) {
- s.worldLock.Lock()
- defer s.worldLock.Unlock()
-
- for {
- node := s.ttlKeyHeap.top()
- if node == nil || node.ExpireTime.After(cutoff) {
- break
- }
-
- s.CurrentIndex++
- e := newEvent(Expire, node.Path, s.CurrentIndex, node.CreatedIndex)
- e.EtcdIndex = s.CurrentIndex
- e.PrevNode = node.Repr(false, false, s.clock)
- if node.IsDir() {
- e.Node.Dir = true
- }
-
- callback := func(path string) { // notify function
- // notify the watchers with deleted set true
- s.WatcherHub.notifyWatchers(e, path, true)
- }
-
- s.ttlKeyHeap.pop()
- node.Remove(true, true, callback)
-
- reportExpiredKey()
- s.Stats.Inc(ExpireCount)
-
- s.WatcherHub.notify(e)
- }
-
-}
-
-// checkDir will check whether the component is a directory under parent node.
-// If it is a directory, this function will return the pointer to that node.
-// If it does not exist, this function will create a new directory and return the pointer to that node.
-// If it is a file, this function will return error.
-func (s *store) checkDir(parent *node, dirName string) (*node, *v2error.Error) {
- node, ok := parent.Children[dirName]
-
- if ok {
- if node.IsDir() {
- return node, nil
- }
-
- return nil, v2error.NewError(v2error.EcodeNotDir, node.Path, s.CurrentIndex)
- }
-
- n := newDir(s, path.Join(parent.Path, dirName), s.CurrentIndex+1, parent, Permanent)
-
- parent.Children[dirName] = n
-
- return n, nil
-}
-
-// Save saves the static state of the store system.
-// It will not be able to save the state of watchers.
-// It will not save the parent field of the node. Or there will
-// be cyclic dependencies issue for the json package.
-func (s *store) Save() ([]byte, error) {
- b, err := json.Marshal(s.Clone())
- if err != nil {
- return nil, err
- }
-
- return b, nil
-}
-
-func (s *store) SaveNoCopy() ([]byte, error) {
- b, err := json.Marshal(s)
- if err != nil {
- return nil, err
- }
-
- return b, nil
-}
-
-func (s *store) Clone() Store {
- s.worldLock.Lock()
-
- clonedStore := newStore()
- clonedStore.CurrentIndex = s.CurrentIndex
- clonedStore.Root = s.Root.Clone()
- clonedStore.WatcherHub = s.WatcherHub.clone()
- clonedStore.Stats = s.Stats.clone()
- clonedStore.CurrentVersion = s.CurrentVersion
-
- s.worldLock.Unlock()
- return clonedStore
-}
-
-// Recovery recovers the store system from a static state
-// It needs to recover the parent field of the nodes.
-// It needs to delete the expired nodes since the saved time and also
-// needs to create monitoring go routines.
-func (s *store) Recovery(state []byte) error {
- s.worldLock.Lock()
- defer s.worldLock.Unlock()
- err := json.Unmarshal(state, s)
-
- if err != nil {
- return err
- }
-
- s.ttlKeyHeap = newTtlKeyHeap()
-
- s.Root.recoverAndclean()
- return nil
-}
-
-func (s *store) JsonStats() []byte {
- s.Stats.Watchers = uint64(s.WatcherHub.count)
- return s.Stats.toJson()
-}
-
-func (s *store) HasTTLKeys() bool {
- s.worldLock.RLock()
- defer s.worldLock.RUnlock()
- return s.ttlKeyHeap.Len() != 0
-}
diff --git a/vendor/go.etcd.io/etcd/etcdserver/api/v2store/ttl_key_heap.go b/vendor/go.etcd.io/etcd/etcdserver/api/v2store/ttl_key_heap.go
deleted file mode 100644
index 477d2b9..0000000
--- a/vendor/go.etcd.io/etcd/etcdserver/api/v2store/ttl_key_heap.go
+++ /dev/null
@@ -1,97 +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 v2store
-
-import "container/heap"
-
-// An TTLKeyHeap is a min-heap of TTLKeys order by expiration time
-type ttlKeyHeap struct {
- array []*node
- keyMap map[*node]int
-}
-
-func newTtlKeyHeap() *ttlKeyHeap {
- h := &ttlKeyHeap{keyMap: make(map[*node]int)}
- heap.Init(h)
- return h
-}
-
-func (h ttlKeyHeap) Len() int {
- return len(h.array)
-}
-
-func (h ttlKeyHeap) Less(i, j int) bool {
- return h.array[i].ExpireTime.Before(h.array[j].ExpireTime)
-}
-
-func (h ttlKeyHeap) Swap(i, j int) {
- // swap node
- h.array[i], h.array[j] = h.array[j], h.array[i]
-
- // update map
- h.keyMap[h.array[i]] = i
- h.keyMap[h.array[j]] = j
-}
-
-func (h *ttlKeyHeap) Push(x interface{}) {
- n, _ := x.(*node)
- h.keyMap[n] = len(h.array)
- h.array = append(h.array, n)
-}
-
-func (h *ttlKeyHeap) Pop() interface{} {
- old := h.array
- n := len(old)
- x := old[n-1]
- // Set slice element to nil, so GC can recycle the node.
- // This is due to golang GC doesn't support partial recycling:
- // https://github.com/golang/go/issues/9618
- old[n-1] = nil
- h.array = old[0 : n-1]
- delete(h.keyMap, x)
- return x
-}
-
-func (h *ttlKeyHeap) top() *node {
- if h.Len() != 0 {
- return h.array[0]
- }
- return nil
-}
-
-func (h *ttlKeyHeap) pop() *node {
- x := heap.Pop(h)
- n, _ := x.(*node)
- return n
-}
-
-func (h *ttlKeyHeap) push(x interface{}) {
- heap.Push(h, x)
-}
-
-func (h *ttlKeyHeap) update(n *node) {
- index, ok := h.keyMap[n]
- if ok {
- heap.Remove(h, index)
- heap.Push(h, n)
- }
-}
-
-func (h *ttlKeyHeap) remove(n *node) {
- index, ok := h.keyMap[n]
- if ok {
- heap.Remove(h, index)
- }
-}
diff --git a/vendor/go.etcd.io/etcd/etcdserver/api/v2store/watcher.go b/vendor/go.etcd.io/etcd/etcdserver/api/v2store/watcher.go
deleted file mode 100644
index 4b1e846..0000000
--- a/vendor/go.etcd.io/etcd/etcdserver/api/v2store/watcher.go
+++ /dev/null
@@ -1,95 +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 v2store
-
-type Watcher interface {
- EventChan() chan *Event
- StartIndex() uint64 // The EtcdIndex at which the Watcher was created
- Remove()
-}
-
-type watcher struct {
- eventChan chan *Event
- stream bool
- recursive bool
- sinceIndex uint64
- startIndex uint64
- hub *watcherHub
- removed bool
- remove func()
-}
-
-func (w *watcher) EventChan() chan *Event {
- return w.eventChan
-}
-
-func (w *watcher) StartIndex() uint64 {
- return w.startIndex
-}
-
-// notify function notifies the watcher. If the watcher interests in the given path,
-// the function will return true.
-func (w *watcher) notify(e *Event, originalPath bool, deleted bool) bool {
- // watcher is interested the path in three cases and under one condition
- // the condition is that the event happens after the watcher's sinceIndex
-
- // 1. the path at which the event happens is the path the watcher is watching at.
- // For example if the watcher is watching at "/foo" and the event happens at "/foo",
- // the watcher must be interested in that event.
-
- // 2. the watcher is a recursive watcher, it interests in the event happens after
- // its watching path. For example if watcher A watches at "/foo" and it is a recursive
- // one, it will interest in the event happens at "/foo/bar".
-
- // 3. when we delete a directory, we need to force notify all the watchers who watches
- // at the file we need to delete.
- // For example a watcher is watching at "/foo/bar". And we deletes "/foo". The watcher
- // should get notified even if "/foo" is not the path it is watching.
- if (w.recursive || originalPath || deleted) && e.Index() >= w.sinceIndex {
- // We cannot block here if the eventChan capacity is full, otherwise
- // etcd will hang. eventChan capacity is full when the rate of
- // notifications are higher than our send rate.
- // If this happens, we close the channel.
- select {
- case w.eventChan <- e:
- default:
- // We have missed a notification. Remove the watcher.
- // Removing the watcher also closes the eventChan.
- w.remove()
- }
- return true
- }
- return false
-}
-
-// Remove removes the watcher from watcherHub
-// The actual remove function is guaranteed to only be executed once
-func (w *watcher) Remove() {
- w.hub.mutex.Lock()
- defer w.hub.mutex.Unlock()
-
- close(w.eventChan)
- if w.remove != nil {
- w.remove()
- }
-}
-
-// nopWatcher is a watcher that receives nothing, always blocking.
-type nopWatcher struct{}
-
-func NewNopWatcher() Watcher { return &nopWatcher{} }
-func (w *nopWatcher) EventChan() chan *Event { return nil }
-func (w *nopWatcher) StartIndex() uint64 { return 0 }
-func (w *nopWatcher) Remove() {}
diff --git a/vendor/go.etcd.io/etcd/etcdserver/api/v2store/watcher_hub.go b/vendor/go.etcd.io/etcd/etcdserver/api/v2store/watcher_hub.go
deleted file mode 100644
index a452e7e..0000000
--- a/vendor/go.etcd.io/etcd/etcdserver/api/v2store/watcher_hub.go
+++ /dev/null
@@ -1,200 +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 v2store
-
-import (
- "container/list"
- "path"
- "strings"
- "sync"
- "sync/atomic"
-
- "go.etcd.io/etcd/etcdserver/api/v2error"
-)
-
-// A watcherHub contains all subscribed watchers
-// watchers is a map with watched path as key and watcher as value
-// EventHistory keeps the old events for watcherHub. It is used to help
-// watcher to get a continuous event history. Or a watcher might miss the
-// event happens between the end of the first watch command and the start
-// of the second command.
-type watcherHub struct {
- // count must be the first element to keep 64-bit alignment for atomic
- // access
-
- count int64 // current number of watchers.
-
- mutex sync.Mutex
- watchers map[string]*list.List
- EventHistory *EventHistory
-}
-
-// newWatchHub creates a watcherHub. The capacity determines how many events we will
-// keep in the eventHistory.
-// Typically, we only need to keep a small size of history[smaller than 20K].
-// Ideally, it should smaller than 20K/s[max throughput] * 2 * 50ms[RTT] = 2000
-func newWatchHub(capacity int) *watcherHub {
- return &watcherHub{
- watchers: make(map[string]*list.List),
- EventHistory: newEventHistory(capacity),
- }
-}
-
-// Watch function returns a Watcher.
-// If recursive is true, the first change after index under key will be sent to the event channel of the watcher.
-// If recursive is false, the first change after index at key will be sent to the event channel of the watcher.
-// If index is zero, watch will start from the current index + 1.
-func (wh *watcherHub) watch(key string, recursive, stream bool, index, storeIndex uint64) (Watcher, *v2error.Error) {
- reportWatchRequest()
- event, err := wh.EventHistory.scan(key, recursive, index)
-
- if err != nil {
- err.Index = storeIndex
- return nil, err
- }
-
- w := &watcher{
- eventChan: make(chan *Event, 100), // use a buffered channel
- recursive: recursive,
- stream: stream,
- sinceIndex: index,
- startIndex: storeIndex,
- hub: wh,
- }
-
- wh.mutex.Lock()
- defer wh.mutex.Unlock()
- // If the event exists in the known history, append the EtcdIndex and return immediately
- if event != nil {
- ne := event.Clone()
- ne.EtcdIndex = storeIndex
- w.eventChan <- ne
- return w, nil
- }
-
- l, ok := wh.watchers[key]
-
- var elem *list.Element
-
- if ok { // add the new watcher to the back of the list
- elem = l.PushBack(w)
- } else { // create a new list and add the new watcher
- l = list.New()
- elem = l.PushBack(w)
- wh.watchers[key] = l
- }
-
- w.remove = func() {
- if w.removed { // avoid removing it twice
- return
- }
- w.removed = true
- l.Remove(elem)
- atomic.AddInt64(&wh.count, -1)
- reportWatcherRemoved()
- if l.Len() == 0 {
- delete(wh.watchers, key)
- }
- }
-
- atomic.AddInt64(&wh.count, 1)
- reportWatcherAdded()
-
- return w, nil
-}
-
-func (wh *watcherHub) add(e *Event) {
- wh.EventHistory.addEvent(e)
-}
-
-// notify function accepts an event and notify to the watchers.
-func (wh *watcherHub) notify(e *Event) {
- e = wh.EventHistory.addEvent(e) // add event into the eventHistory
-
- segments := strings.Split(e.Node.Key, "/")
-
- currPath := "/"
-
- // walk through all the segments of the path and notify the watchers
- // if the path is "/foo/bar", it will notify watchers with path "/",
- // "/foo" and "/foo/bar"
-
- for _, segment := range segments {
- currPath = path.Join(currPath, segment)
- // notify the watchers who interests in the changes of current path
- wh.notifyWatchers(e, currPath, false)
- }
-}
-
-func (wh *watcherHub) notifyWatchers(e *Event, nodePath string, deleted bool) {
- wh.mutex.Lock()
- defer wh.mutex.Unlock()
-
- l, ok := wh.watchers[nodePath]
- if ok {
- curr := l.Front()
-
- for curr != nil {
- next := curr.Next() // save reference to the next one in the list
-
- w, _ := curr.Value.(*watcher)
-
- originalPath := e.Node.Key == nodePath
- if (originalPath || !isHidden(nodePath, e.Node.Key)) && w.notify(e, originalPath, deleted) {
- if !w.stream { // do not remove the stream watcher
- // if we successfully notify a watcher
- // we need to remove the watcher from the list
- // and decrease the counter
- w.removed = true
- l.Remove(curr)
- atomic.AddInt64(&wh.count, -1)
- reportWatcherRemoved()
- }
- }
-
- curr = next // update current to the next element in the list
- }
-
- if l.Len() == 0 {
- // if we have notified all watcher in the list
- // we can delete the list
- delete(wh.watchers, nodePath)
- }
- }
-}
-
-// clone function clones the watcherHub and return the cloned one.
-// only clone the static content. do not clone the current watchers.
-func (wh *watcherHub) clone() *watcherHub {
- clonedHistory := wh.EventHistory.clone()
-
- return &watcherHub{
- EventHistory: clonedHistory,
- }
-}
-
-// isHidden checks to see if key path is considered hidden to watch path i.e. the
-// last element is hidden or it's within a hidden directory
-func isHidden(watchPath, keyPath string) bool {
- // When deleting a directory, watchPath might be deeper than the actual keyPath
- // For example, when deleting /foo we also need to notify watchers on /foo/bar.
- if len(watchPath) > len(keyPath) {
- return false
- }
- // if watch path is just a "/", after path will start without "/"
- // add a "/" to deal with the special case when watchPath is "/"
- afterPath := path.Clean("/" + keyPath[len(watchPath):])
- return strings.Contains(afterPath, "/_")
-}
diff --git a/vendor/go.etcd.io/etcd/etcdserver/api/v2v3/cluster.go b/vendor/go.etcd.io/etcd/etcdserver/api/v2v3/cluster.go
deleted file mode 100644
index a22e4af..0000000
--- a/vendor/go.etcd.io/etcd/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/etcdserver/api/membership"
- "go.etcd.io/etcd/pkg/types"
-
- "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/vendor/go.etcd.io/etcd/etcdserver/api/v2v3/doc.go b/vendor/go.etcd.io/etcd/etcdserver/api/v2v3/doc.go
deleted file mode 100644
index 2ff372f..0000000
--- a/vendor/go.etcd.io/etcd/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/vendor/go.etcd.io/etcd/etcdserver/api/v2v3/server.go b/vendor/go.etcd.io/etcd/etcdserver/api/v2v3/server.go
deleted file mode 100644
index 5ff9b96..0000000
--- a/vendor/go.etcd.io/etcd/etcdserver/api/v2v3/server.go
+++ /dev/null
@@ -1,129 +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"
-
- "go.etcd.io/etcd/clientv3"
- "go.etcd.io/etcd/etcdserver"
- "go.etcd.io/etcd/etcdserver/api"
- "go.etcd.io/etcd/etcdserver/api/membership"
- pb "go.etcd.io/etcd/etcdserver/etcdserverpb"
- "go.etcd.io/etcd/pkg/types"
-
- "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) 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/vendor/go.etcd.io/etcd/etcdserver/api/v2v3/store.go b/vendor/go.etcd.io/etcd/etcdserver/api/v2v3/store.go
deleted file mode 100644
index f1c7ab3..0000000
--- a/vendor/go.etcd.io/etcd/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/clientv3"
- "go.etcd.io/etcd/clientv3/concurrency"
- "go.etcd.io/etcd/etcdserver/api/v2error"
- "go.etcd.io/etcd/etcdserver/api/v2store"
- "go.etcd.io/etcd/mvcc/mvccpb"
-)
-
-// 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/vendor/go.etcd.io/etcd/etcdserver/api/v2v3/watcher.go b/vendor/go.etcd.io/etcd/etcdserver/api/v2v3/watcher.go
deleted file mode 100644
index e8a3557..0000000
--- a/vendor/go.etcd.io/etcd/etcdserver/api/v2v3/watcher.go
+++ /dev/null
@@ -1,140 +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/clientv3"
- "go.etcd.io/etcd/etcdserver/api/v2error"
- "go.etcd.io/etcd/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
- }
- }
- 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/vendor/go.etcd.io/etcd/etcdserver/api/v3alarm/alarms.go b/vendor/go.etcd.io/etcd/etcdserver/api/v3alarm/alarms.go
deleted file mode 100644
index 2b085a8..0000000
--- a/vendor/go.etcd.io/etcd/etcdserver/api/v3alarm/alarms.go
+++ /dev/null
@@ -1,153 +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 v3alarm manages health status alarms in etcd.
-package v3alarm
-
-import (
- "sync"
-
- pb "go.etcd.io/etcd/etcdserver/etcdserverpb"
- "go.etcd.io/etcd/mvcc/backend"
- "go.etcd.io/etcd/pkg/types"
-
- "github.com/coreos/pkg/capnslog"
-)
-
-var (
- alarmBucketName = []byte("alarm")
- plog = capnslog.NewPackageLogger("go.etcd.io/etcd", "alarm")
-)
-
-type BackendGetter interface {
- Backend() backend.Backend
-}
-
-type alarmSet map[types.ID]*pb.AlarmMember
-
-// AlarmStore persists alarms to the backend.
-type AlarmStore struct {
- mu sync.Mutex
- types map[pb.AlarmType]alarmSet
-
- bg BackendGetter
-}
-
-func NewAlarmStore(bg BackendGetter) (*AlarmStore, error) {
- ret := &AlarmStore{types: make(map[pb.AlarmType]alarmSet), bg: bg}
- err := ret.restore()
- return ret, err
-}
-
-func (a *AlarmStore) Activate(id types.ID, at pb.AlarmType) *pb.AlarmMember {
- a.mu.Lock()
- defer a.mu.Unlock()
-
- newAlarm := &pb.AlarmMember{MemberID: uint64(id), Alarm: at}
- if m := a.addToMap(newAlarm); m != newAlarm {
- return m
- }
-
- v, err := newAlarm.Marshal()
- if err != nil {
- plog.Panicf("failed to marshal alarm member")
- }
-
- b := a.bg.Backend()
- b.BatchTx().Lock()
- b.BatchTx().UnsafePut(alarmBucketName, v, nil)
- b.BatchTx().Unlock()
-
- return newAlarm
-}
-
-func (a *AlarmStore) Deactivate(id types.ID, at pb.AlarmType) *pb.AlarmMember {
- a.mu.Lock()
- defer a.mu.Unlock()
-
- t := a.types[at]
- if t == nil {
- t = make(alarmSet)
- a.types[at] = t
- }
- m := t[id]
- if m == nil {
- return nil
- }
-
- delete(t, id)
-
- v, err := m.Marshal()
- if err != nil {
- plog.Panicf("failed to marshal alarm member")
- }
-
- b := a.bg.Backend()
- b.BatchTx().Lock()
- b.BatchTx().UnsafeDelete(alarmBucketName, v)
- b.BatchTx().Unlock()
-
- return m
-}
-
-func (a *AlarmStore) Get(at pb.AlarmType) (ret []*pb.AlarmMember) {
- a.mu.Lock()
- defer a.mu.Unlock()
- if at == pb.AlarmType_NONE {
- for _, t := range a.types {
- for _, m := range t {
- ret = append(ret, m)
- }
- }
- return ret
- }
- for _, m := range a.types[at] {
- ret = append(ret, m)
- }
- return ret
-}
-
-func (a *AlarmStore) restore() error {
- b := a.bg.Backend()
- tx := b.BatchTx()
-
- tx.Lock()
- tx.UnsafeCreateBucket(alarmBucketName)
- err := tx.UnsafeForEach(alarmBucketName, func(k, v []byte) error {
- var m pb.AlarmMember
- if err := m.Unmarshal(k); err != nil {
- return err
- }
- a.addToMap(&m)
- return nil
- })
- tx.Unlock()
-
- b.ForceCommit()
- return err
-}
-
-func (a *AlarmStore) addToMap(newAlarm *pb.AlarmMember) *pb.AlarmMember {
- t := a.types[newAlarm.Alarm]
- if t == nil {
- t = make(alarmSet)
- a.types[newAlarm.Alarm] = t
- }
- m := t[types.ID(newAlarm.MemberID)]
- if m != nil {
- return m
- }
- t[types.ID(newAlarm.MemberID)] = newAlarm
- return newAlarm
-}
diff --git a/vendor/go.etcd.io/etcd/etcdserver/api/v3client/doc.go b/vendor/go.etcd.io/etcd/etcdserver/api/v3client/doc.go
deleted file mode 100644
index 47922c4..0000000
--- a/vendor/go.etcd.io/etcd/etcdserver/api/v3client/doc.go
+++ /dev/null
@@ -1,45 +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 v3client provides clientv3 interfaces from an etcdserver.
-//
-// Use v3client by creating an EtcdServer instance, then wrapping it with v3client.New:
-//
-// import (
-// "context"
-//
-// "go.etcd.io/etcd/embed"
-// "go.etcd.io/etcd/etcdserver/api/v3client"
-// )
-//
-// ...
-//
-// // create an embedded EtcdServer from the default configuration
-// cfg := embed.NewConfig()
-// cfg.Dir = "default.etcd"
-// e, err := embed.StartEtcd(cfg)
-// if err != nil {
-// // handle error!
-// }
-//
-// // wrap the EtcdServer with v3client
-// cli := v3client.New(e.Server)
-//
-// // use like an ordinary clientv3
-// resp, err := cli.Put(context.TODO(), "some-key", "it works!")
-// if err != nil {
-// // handle error!
-// }
-//
-package v3client
diff --git a/vendor/go.etcd.io/etcd/etcdserver/api/v3client/v3client.go b/vendor/go.etcd.io/etcd/etcdserver/api/v3client/v3client.go
deleted file mode 100644
index d203121..0000000
--- a/vendor/go.etcd.io/etcd/etcdserver/api/v3client/v3client.go
+++ /dev/null
@@ -1,66 +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 v3client
-
-import (
- "context"
- "time"
-
- "go.etcd.io/etcd/clientv3"
- "go.etcd.io/etcd/etcdserver"
- "go.etcd.io/etcd/etcdserver/api/v3rpc"
- "go.etcd.io/etcd/proxy/grpcproxy/adapter"
-)
-
-// New creates a clientv3 client that wraps an in-process EtcdServer. Instead
-// of making gRPC calls through sockets, the client makes direct function calls
-// to the etcd server through its api/v3rpc function interfaces.
-func New(s *etcdserver.EtcdServer) *clientv3.Client {
- c := clientv3.NewCtxClient(context.Background())
-
- kvc := adapter.KvServerToKvClient(v3rpc.NewQuotaKVServer(s))
- c.KV = clientv3.NewKVFromKVClient(kvc, c)
-
- lc := adapter.LeaseServerToLeaseClient(v3rpc.NewQuotaLeaseServer(s))
- c.Lease = clientv3.NewLeaseFromLeaseClient(lc, c, time.Second)
-
- wc := adapter.WatchServerToWatchClient(v3rpc.NewWatchServer(s))
- c.Watcher = &watchWrapper{clientv3.NewWatchFromWatchClient(wc, c)}
-
- mc := adapter.MaintenanceServerToMaintenanceClient(v3rpc.NewMaintenanceServer(s))
- c.Maintenance = clientv3.NewMaintenanceFromMaintenanceClient(mc, c)
-
- clc := adapter.ClusterServerToClusterClient(v3rpc.NewClusterServer(s))
- c.Cluster = clientv3.NewClusterFromClusterClient(clc, c)
-
- // TODO: implement clientv3.Auth interface?
-
- return c
-}
-
-// BlankContext implements Stringer on a context so the ctx string doesn't
-// depend on the context's WithValue data, which tends to be unsynchronized
-// (e.g., x/net/trace), causing ctx.String() to throw data races.
-type blankContext struct{ context.Context }
-
-func (*blankContext) String() string { return "(blankCtx)" }
-
-// watchWrapper wraps clientv3 watch calls to blank out the context
-// to avoid races on trace data.
-type watchWrapper struct{ clientv3.Watcher }
-
-func (ww *watchWrapper) Watch(ctx context.Context, key string, opts ...clientv3.OpOption) clientv3.WatchChan {
- return ww.Watcher.Watch(&blankContext{ctx}, key, opts...)
-}
diff --git a/vendor/go.etcd.io/etcd/etcdserver/api/v3compactor/compactor.go b/vendor/go.etcd.io/etcd/etcdserver/api/v3compactor/compactor.go
deleted file mode 100644
index 73a9684..0000000
--- a/vendor/go.etcd.io/etcd/etcdserver/api/v3compactor/compactor.go
+++ /dev/null
@@ -1,75 +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 v3compactor
-
-import (
- "context"
- "fmt"
- "time"
-
- pb "go.etcd.io/etcd/etcdserver/etcdserverpb"
-
- "github.com/coreos/pkg/capnslog"
- "github.com/jonboulle/clockwork"
- "go.uber.org/zap"
-)
-
-var (
- plog = capnslog.NewPackageLogger("go.etcd.io/etcd", "compactor")
-)
-
-const (
- ModePeriodic = "periodic"
- ModeRevision = "revision"
-)
-
-// Compactor purges old log from the storage periodically.
-type Compactor interface {
- // Run starts the main loop of the compactor in background.
- // Use Stop() to halt the loop and release the resource.
- Run()
- // Stop halts the main loop of the compactor.
- Stop()
- // Pause temporally suspend the compactor not to run compaction. Resume() to unpose.
- Pause()
- // Resume restarts the compactor suspended by Pause().
- Resume()
-}
-
-type Compactable interface {
- Compact(ctx context.Context, r *pb.CompactionRequest) (*pb.CompactionResponse, error)
-}
-
-type RevGetter interface {
- Rev() int64
-}
-
-// New returns a new Compactor based on given "mode".
-func New(
- lg *zap.Logger,
- mode string,
- retention time.Duration,
- rg RevGetter,
- c Compactable,
-) (Compactor, error) {
- switch mode {
- case ModePeriodic:
- return newPeriodic(lg, clockwork.NewRealClock(), retention, rg, c), nil
- case ModeRevision:
- return newRevision(lg, clockwork.NewRealClock(), int64(retention), rg, c), nil
- default:
- return nil, fmt.Errorf("unsupported compaction mode %s", mode)
- }
-}
diff --git a/vendor/go.etcd.io/etcd/etcdserver/api/v3compactor/doc.go b/vendor/go.etcd.io/etcd/etcdserver/api/v3compactor/doc.go
deleted file mode 100644
index bb28046..0000000
--- a/vendor/go.etcd.io/etcd/etcdserver/api/v3compactor/doc.go
+++ /dev/null
@@ -1,16 +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 v3compactor implements automated policies for compacting etcd's mvcc storage.
-package v3compactor
diff --git a/vendor/go.etcd.io/etcd/etcdserver/api/v3compactor/periodic.go b/vendor/go.etcd.io/etcd/etcdserver/api/v3compactor/periodic.go
deleted file mode 100644
index ab64cb7..0000000
--- a/vendor/go.etcd.io/etcd/etcdserver/api/v3compactor/periodic.go
+++ /dev/null
@@ -1,217 +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 v3compactor
-
-import (
- "context"
- "sync"
- "time"
-
- pb "go.etcd.io/etcd/etcdserver/etcdserverpb"
- "go.etcd.io/etcd/mvcc"
-
- "github.com/jonboulle/clockwork"
- "go.uber.org/zap"
-)
-
-// Periodic compacts the log by purging revisions older than
-// the configured retention time.
-type Periodic struct {
- lg *zap.Logger
- clock clockwork.Clock
- period time.Duration
-
- rg RevGetter
- c Compactable
-
- revs []int64
- ctx context.Context
- cancel context.CancelFunc
-
- // mu protects paused
- mu sync.RWMutex
- paused bool
-}
-
-// newPeriodic creates a new instance of Periodic compactor that purges
-// the log older than h Duration.
-func newPeriodic(lg *zap.Logger, clock clockwork.Clock, h time.Duration, rg RevGetter, c Compactable) *Periodic {
- pc := &Periodic{
- lg: lg,
- clock: clock,
- period: h,
- rg: rg,
- c: c,
- revs: make([]int64, 0),
- }
- pc.ctx, pc.cancel = context.WithCancel(context.Background())
- return pc
-}
-
-/*
-Compaction period 1-hour:
- 1. compute compaction period, which is 1-hour
- 2. record revisions for every 1/10 of 1-hour (6-minute)
- 3. keep recording revisions with no compaction for first 1-hour
- 4. do compact with revs[0]
- - success? contiue on for-loop and move sliding window; revs = revs[1:]
- - failure? update revs, and retry after 1/10 of 1-hour (6-minute)
-
-Compaction period 24-hour:
- 1. compute compaction period, which is 1-hour
- 2. record revisions for every 1/10 of 1-hour (6-minute)
- 3. keep recording revisions with no compaction for first 24-hour
- 4. do compact with revs[0]
- - success? contiue on for-loop and move sliding window; revs = revs[1:]
- - failure? update revs, and retry after 1/10 of 1-hour (6-minute)
-
-Compaction period 59-min:
- 1. compute compaction period, which is 59-min
- 2. record revisions for every 1/10 of 59-min (5.9-min)
- 3. keep recording revisions with no compaction for first 59-min
- 4. do compact with revs[0]
- - success? contiue on for-loop and move sliding window; revs = revs[1:]
- - failure? update revs, and retry after 1/10 of 59-min (5.9-min)
-
-Compaction period 5-sec:
- 1. compute compaction period, which is 5-sec
- 2. record revisions for every 1/10 of 5-sec (0.5-sec)
- 3. keep recording revisions with no compaction for first 5-sec
- 4. do compact with revs[0]
- - success? contiue on for-loop and move sliding window; revs = revs[1:]
- - failure? update revs, and retry after 1/10 of 5-sec (0.5-sec)
-*/
-
-// Run runs periodic compactor.
-func (pc *Periodic) Run() {
- compactInterval := pc.getCompactInterval()
- retryInterval := pc.getRetryInterval()
- retentions := pc.getRetentions()
-
- go func() {
- lastSuccess := pc.clock.Now()
- baseInterval := pc.period
- for {
- pc.revs = append(pc.revs, pc.rg.Rev())
- if len(pc.revs) > retentions {
- pc.revs = pc.revs[1:] // pc.revs[0] is always the rev at pc.period ago
- }
-
- select {
- case <-pc.ctx.Done():
- return
- case <-pc.clock.After(retryInterval):
- pc.mu.Lock()
- p := pc.paused
- pc.mu.Unlock()
- if p {
- continue
- }
- }
-
- if pc.clock.Now().Sub(lastSuccess) < baseInterval {
- continue
- }
-
- // wait up to initial given period
- if baseInterval == pc.period {
- baseInterval = compactInterval
- }
- rev := pc.revs[0]
-
- if pc.lg != nil {
- pc.lg.Info(
- "starting auto periodic compaction",
- zap.Int64("revision", rev),
- zap.Duration("compact-period", pc.period),
- )
- } else {
- plog.Noticef("Starting auto-compaction at revision %d (retention: %v)", rev, pc.period)
- }
- _, err := pc.c.Compact(pc.ctx, &pb.CompactionRequest{Revision: rev})
- if err == nil || err == mvcc.ErrCompacted {
- if pc.lg != nil {
- pc.lg.Info(
- "completed auto periodic compaction",
- zap.Int64("revision", rev),
- zap.Duration("compact-period", pc.period),
- zap.Duration("took", time.Since(lastSuccess)),
- )
- } else {
- plog.Noticef("Finished auto-compaction at revision %d", rev)
- }
- lastSuccess = pc.clock.Now()
- } else {
- if pc.lg != nil {
- pc.lg.Warn(
- "failed auto periodic compaction",
- zap.Int64("revision", rev),
- zap.Duration("compact-period", pc.period),
- zap.Duration("retry-interval", retryInterval),
- zap.Error(err),
- )
- } else {
- plog.Noticef("Failed auto-compaction at revision %d (%v)", rev, err)
- plog.Noticef("Retry after %v", retryInterval)
- }
- }
- }
- }()
-}
-
-// if given compaction period x is <1-hour, compact every x duration.
-// (e.g. --auto-compaction-mode 'periodic' --auto-compaction-retention='10m', then compact every 10-minute)
-// if given compaction period x is >1-hour, compact every hour.
-// (e.g. --auto-compaction-mode 'periodic' --auto-compaction-retention='2h', then compact every 1-hour)
-func (pc *Periodic) getCompactInterval() time.Duration {
- itv := pc.period
- if itv > time.Hour {
- itv = time.Hour
- }
- return itv
-}
-
-func (pc *Periodic) getRetentions() int {
- return int(pc.period/pc.getRetryInterval()) + 1
-}
-
-const retryDivisor = 10
-
-func (pc *Periodic) getRetryInterval() time.Duration {
- itv := pc.period
- if itv > time.Hour {
- itv = time.Hour
- }
- return itv / retryDivisor
-}
-
-// Stop stops periodic compactor.
-func (pc *Periodic) Stop() {
- pc.cancel()
-}
-
-// Pause pauses periodic compactor.
-func (pc *Periodic) Pause() {
- pc.mu.Lock()
- pc.paused = true
- pc.mu.Unlock()
-}
-
-// Resume resumes periodic compactor.
-func (pc *Periodic) Resume() {
- pc.mu.Lock()
- pc.paused = false
- pc.mu.Unlock()
-}
diff --git a/vendor/go.etcd.io/etcd/etcdserver/api/v3compactor/revision.go b/vendor/go.etcd.io/etcd/etcdserver/api/v3compactor/revision.go
deleted file mode 100644
index cf8ac43..0000000
--- a/vendor/go.etcd.io/etcd/etcdserver/api/v3compactor/revision.go
+++ /dev/null
@@ -1,143 +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 v3compactor
-
-import (
- "context"
- "sync"
- "time"
-
- pb "go.etcd.io/etcd/etcdserver/etcdserverpb"
- "go.etcd.io/etcd/mvcc"
-
- "github.com/jonboulle/clockwork"
- "go.uber.org/zap"
-)
-
-// Revision compacts the log by purging revisions older than
-// the configured reivison number. Compaction happens every 5 minutes.
-type Revision struct {
- lg *zap.Logger
-
- clock clockwork.Clock
- retention int64
-
- rg RevGetter
- c Compactable
-
- ctx context.Context
- cancel context.CancelFunc
-
- mu sync.Mutex
- paused bool
-}
-
-// newRevision creates a new instance of Revisonal compactor that purges
-// the log older than retention revisions from the current revision.
-func newRevision(lg *zap.Logger, clock clockwork.Clock, retention int64, rg RevGetter, c Compactable) *Revision {
- rc := &Revision{
- lg: lg,
- clock: clock,
- retention: retention,
- rg: rg,
- c: c,
- }
- rc.ctx, rc.cancel = context.WithCancel(context.Background())
- return rc
-}
-
-const revInterval = 5 * time.Minute
-
-// Run runs revision-based compactor.
-func (rc *Revision) Run() {
- prev := int64(0)
- go func() {
- for {
- select {
- case <-rc.ctx.Done():
- return
- case <-rc.clock.After(revInterval):
- rc.mu.Lock()
- p := rc.paused
- rc.mu.Unlock()
- if p {
- continue
- }
- }
-
- rev := rc.rg.Rev() - rc.retention
- if rev <= 0 || rev == prev {
- continue
- }
-
- now := time.Now()
- if rc.lg != nil {
- rc.lg.Info(
- "starting auto revision compaction",
- zap.Int64("revision", rev),
- zap.Int64("revision-compaction-retention", rc.retention),
- )
- } else {
- plog.Noticef("Starting auto-compaction at revision %d (retention: %d revisions)", rev, rc.retention)
- }
- _, err := rc.c.Compact(rc.ctx, &pb.CompactionRequest{Revision: rev})
- if err == nil || err == mvcc.ErrCompacted {
- prev = rev
- if rc.lg != nil {
- rc.lg.Info(
- "completed auto revision compaction",
- zap.Int64("revision", rev),
- zap.Int64("revision-compaction-retention", rc.retention),
- zap.Duration("took", time.Since(now)),
- )
- } else {
- plog.Noticef("Finished auto-compaction at revision %d", rev)
- }
- } else {
- if rc.lg != nil {
- rc.lg.Warn(
- "failed auto revision compaction",
- zap.Int64("revision", rev),
- zap.Int64("revision-compaction-retention", rc.retention),
- zap.Duration("retry-interval", revInterval),
- zap.Error(err),
- )
- } else {
- plog.Noticef("Failed auto-compaction at revision %d (%v)", rev, err)
- plog.Noticef("Retry after %v", revInterval)
- }
- }
- }
- }()
-}
-
-// Stop stops revision-based compactor.
-func (rc *Revision) Stop() {
- rc.cancel()
-}
-
-// Pause pauses revision-based compactor.
-func (rc *Revision) Pause() {
- rc.mu.Lock()
- rc.paused = true
- rc.mu.Unlock()
-}
-
-// Resume resumes revision-based compactor.
-func (rc *Revision) Resume() {
- rc.mu.Lock()
- rc.paused = false
- rc.mu.Unlock()
-}
diff --git a/vendor/go.etcd.io/etcd/etcdserver/api/v3election/doc.go b/vendor/go.etcd.io/etcd/etcdserver/api/v3election/doc.go
deleted file mode 100644
index d6fefd7..0000000
--- a/vendor/go.etcd.io/etcd/etcdserver/api/v3election/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 v3election provides a v3 election service from an etcdserver.
-package v3election
diff --git a/vendor/go.etcd.io/etcd/etcdserver/api/v3election/election.go b/vendor/go.etcd.io/etcd/etcdserver/api/v3election/election.go
deleted file mode 100644
index f5a3be3..0000000
--- a/vendor/go.etcd.io/etcd/etcdserver/api/v3election/election.go
+++ /dev/null
@@ -1,134 +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 v3election
-
-import (
- "context"
- "errors"
-
- "go.etcd.io/etcd/clientv3"
- "go.etcd.io/etcd/clientv3/concurrency"
- epb "go.etcd.io/etcd/etcdserver/api/v3election/v3electionpb"
-)
-
-// ErrMissingLeaderKey is returned when election API request
-// is missing the "leader" field.
-var ErrMissingLeaderKey = errors.New(`"leader" field must be provided`)
-
-type electionServer struct {
- c *clientv3.Client
-}
-
-func NewElectionServer(c *clientv3.Client) epb.ElectionServer {
- return &electionServer{c}
-}
-
-func (es *electionServer) Campaign(ctx context.Context, req *epb.CampaignRequest) (*epb.CampaignResponse, error) {
- s, err := es.session(ctx, req.Lease)
- if err != nil {
- return nil, err
- }
- e := concurrency.NewElection(s, string(req.Name))
- if err = e.Campaign(ctx, string(req.Value)); err != nil {
- return nil, err
- }
- return &epb.CampaignResponse{
- Header: e.Header(),
- Leader: &epb.LeaderKey{
- Name: req.Name,
- Key: []byte(e.Key()),
- Rev: e.Rev(),
- Lease: int64(s.Lease()),
- },
- }, nil
-}
-
-func (es *electionServer) Proclaim(ctx context.Context, req *epb.ProclaimRequest) (*epb.ProclaimResponse, error) {
- if req.Leader == nil {
- return nil, ErrMissingLeaderKey
- }
- s, err := es.session(ctx, req.Leader.Lease)
- if err != nil {
- return nil, err
- }
- e := concurrency.ResumeElection(s, string(req.Leader.Name), string(req.Leader.Key), req.Leader.Rev)
- if err := e.Proclaim(ctx, string(req.Value)); err != nil {
- return nil, err
- }
- return &epb.ProclaimResponse{Header: e.Header()}, nil
-}
-
-func (es *electionServer) Observe(req *epb.LeaderRequest, stream epb.Election_ObserveServer) error {
- s, err := es.session(stream.Context(), -1)
- if err != nil {
- return err
- }
- e := concurrency.NewElection(s, string(req.Name))
- ch := e.Observe(stream.Context())
- for stream.Context().Err() == nil {
- select {
- case <-stream.Context().Done():
- case resp, ok := <-ch:
- if !ok {
- return nil
- }
- lresp := &epb.LeaderResponse{Header: resp.Header, Kv: resp.Kvs[0]}
- if err := stream.Send(lresp); err != nil {
- return err
- }
- }
- }
- return stream.Context().Err()
-}
-
-func (es *electionServer) Leader(ctx context.Context, req *epb.LeaderRequest) (*epb.LeaderResponse, error) {
- s, err := es.session(ctx, -1)
- if err != nil {
- return nil, err
- }
- l, lerr := concurrency.NewElection(s, string(req.Name)).Leader(ctx)
- if lerr != nil {
- return nil, lerr
- }
- return &epb.LeaderResponse{Header: l.Header, Kv: l.Kvs[0]}, nil
-}
-
-func (es *electionServer) Resign(ctx context.Context, req *epb.ResignRequest) (*epb.ResignResponse, error) {
- if req.Leader == nil {
- return nil, ErrMissingLeaderKey
- }
- s, err := es.session(ctx, req.Leader.Lease)
- if err != nil {
- return nil, err
- }
- e := concurrency.ResumeElection(s, string(req.Leader.Name), string(req.Leader.Key), req.Leader.Rev)
- if err := e.Resign(ctx); err != nil {
- return nil, err
- }
- return &epb.ResignResponse{Header: e.Header()}, nil
-}
-
-func (es *electionServer) session(ctx context.Context, lease int64) (*concurrency.Session, error) {
- s, err := concurrency.NewSession(
- es.c,
- concurrency.WithLease(clientv3.LeaseID(lease)),
- concurrency.WithContext(ctx),
- )
- if err != nil {
- return nil, err
- }
- s.Orphan()
- return s, nil
-}
diff --git a/vendor/go.etcd.io/etcd/etcdserver/api/v3election/v3electionpb/gw/v3election.pb.gw.go b/vendor/go.etcd.io/etcd/etcdserver/api/v3election/v3electionpb/gw/v3election.pb.gw.go
deleted file mode 100644
index 23551b5..0000000
--- a/vendor/go.etcd.io/etcd/etcdserver/api/v3election/v3electionpb/gw/v3election.pb.gw.go
+++ /dev/null
@@ -1,313 +0,0 @@
-// Code generated by protoc-gen-grpc-gateway. DO NOT EDIT.
-// source: etcdserver/api/v3election/v3electionpb/v3election.proto
-
-/*
-Package v3electionpb is a reverse proxy.
-
-It translates gRPC into RESTful JSON APIs.
-*/
-package gw
-
-import (
- "go.etcd.io/etcd/etcdserver/api/v3election/v3electionpb"
- "io"
- "net/http"
-
- "github.com/golang/protobuf/proto"
- "github.com/grpc-ecosystem/grpc-gateway/runtime"
- "github.com/grpc-ecosystem/grpc-gateway/utilities"
- "golang.org/x/net/context"
- "google.golang.org/grpc"
- "google.golang.org/grpc/codes"
- "google.golang.org/grpc/grpclog"
- "google.golang.org/grpc/status"
-)
-
-var _ codes.Code
-var _ io.Reader
-var _ status.Status
-var _ = runtime.String
-var _ = utilities.NewDoubleArray
-
-func request_Election_Campaign_0(ctx context.Context, marshaler runtime.Marshaler, client v3electionpb.ElectionClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) {
- var protoReq v3electionpb.CampaignRequest
- var metadata runtime.ServerMetadata
-
- if err := marshaler.NewDecoder(req.Body).Decode(&protoReq); err != nil && err != io.EOF {
- return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err)
- }
-
- msg, err := client.Campaign(ctx, &protoReq, grpc.Header(&metadata.HeaderMD), grpc.Trailer(&metadata.TrailerMD))
- return msg, metadata, err
-
-}
-
-func request_Election_Proclaim_0(ctx context.Context, marshaler runtime.Marshaler, client v3electionpb.ElectionClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) {
- var protoReq v3electionpb.ProclaimRequest
- var metadata runtime.ServerMetadata
-
- if err := marshaler.NewDecoder(req.Body).Decode(&protoReq); err != nil && err != io.EOF {
- return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err)
- }
-
- msg, err := client.Proclaim(ctx, &protoReq, grpc.Header(&metadata.HeaderMD), grpc.Trailer(&metadata.TrailerMD))
- return msg, metadata, err
-
-}
-
-func request_Election_Leader_0(ctx context.Context, marshaler runtime.Marshaler, client v3electionpb.ElectionClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) {
- var protoReq v3electionpb.LeaderRequest
- var metadata runtime.ServerMetadata
-
- if err := marshaler.NewDecoder(req.Body).Decode(&protoReq); err != nil && err != io.EOF {
- return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err)
- }
-
- msg, err := client.Leader(ctx, &protoReq, grpc.Header(&metadata.HeaderMD), grpc.Trailer(&metadata.TrailerMD))
- return msg, metadata, err
-
-}
-
-func request_Election_Observe_0(ctx context.Context, marshaler runtime.Marshaler, client v3electionpb.ElectionClient, req *http.Request, pathParams map[string]string) (v3electionpb.Election_ObserveClient, runtime.ServerMetadata, error) {
- var protoReq v3electionpb.LeaderRequest
- var metadata runtime.ServerMetadata
-
- if err := marshaler.NewDecoder(req.Body).Decode(&protoReq); err != nil && err != io.EOF {
- return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err)
- }
-
- stream, err := client.Observe(ctx, &protoReq)
- if err != nil {
- return nil, metadata, err
- }
- header, err := stream.Header()
- if err != nil {
- return nil, metadata, err
- }
- metadata.HeaderMD = header
- return stream, metadata, nil
-
-}
-
-func request_Election_Resign_0(ctx context.Context, marshaler runtime.Marshaler, client v3electionpb.ElectionClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) {
- var protoReq v3electionpb.ResignRequest
- var metadata runtime.ServerMetadata
-
- if err := marshaler.NewDecoder(req.Body).Decode(&protoReq); err != nil && err != io.EOF {
- return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err)
- }
-
- msg, err := client.Resign(ctx, &protoReq, grpc.Header(&metadata.HeaderMD), grpc.Trailer(&metadata.TrailerMD))
- return msg, metadata, err
-
-}
-
-// RegisterElectionHandlerFromEndpoint is same as RegisterElectionHandler but
-// automatically dials to "endpoint" and closes the connection when "ctx" gets done.
-func RegisterElectionHandlerFromEndpoint(ctx context.Context, mux *runtime.ServeMux, endpoint string, opts []grpc.DialOption) (err error) {
- conn, err := grpc.Dial(endpoint, opts...)
- if err != nil {
- return err
- }
- defer func() {
- if err != nil {
- if cerr := conn.Close(); cerr != nil {
- grpclog.Printf("Failed to close conn to %s: %v", endpoint, cerr)
- }
- return
- }
- go func() {
- <-ctx.Done()
- if cerr := conn.Close(); cerr != nil {
- grpclog.Printf("Failed to close conn to %s: %v", endpoint, cerr)
- }
- }()
- }()
-
- return RegisterElectionHandler(ctx, mux, conn)
-}
-
-// RegisterElectionHandler registers the http handlers for service Election to "mux".
-// The handlers forward requests to the grpc endpoint over "conn".
-func RegisterElectionHandler(ctx context.Context, mux *runtime.ServeMux, conn *grpc.ClientConn) error {
- return RegisterElectionHandlerClient(ctx, mux, v3electionpb.NewElectionClient(conn))
-}
-
-// RegisterElectionHandler registers the http handlers for service Election to "mux".
-// The handlers forward requests to the grpc endpoint over the given implementation of "ElectionClient".
-// Note: the gRPC framework executes interceptors within the gRPC handler. If the passed in "ElectionClient"
-// doesn't go through the normal gRPC flow (creating a gRPC client etc.) then it will be up to the passed in
-// "ElectionClient" to call the correct interceptors.
-func RegisterElectionHandlerClient(ctx context.Context, mux *runtime.ServeMux, client v3electionpb.ElectionClient) error {
-
- mux.Handle("POST", pattern_Election_Campaign_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) {
- ctx, cancel := context.WithCancel(req.Context())
- defer cancel()
- if cn, ok := w.(http.CloseNotifier); ok {
- go func(done <-chan struct{}, closed <-chan bool) {
- select {
- case <-done:
- case <-closed:
- cancel()
- }
- }(ctx.Done(), cn.CloseNotify())
- }
- inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req)
- rctx, err := runtime.AnnotateContext(ctx, mux, req)
- if err != nil {
- runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err)
- return
- }
- resp, md, err := request_Election_Campaign_0(rctx, inboundMarshaler, client, req, pathParams)
- ctx = runtime.NewServerMetadataContext(ctx, md)
- if err != nil {
- runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err)
- return
- }
-
- forward_Election_Campaign_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...)
-
- })
-
- mux.Handle("POST", pattern_Election_Proclaim_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) {
- ctx, cancel := context.WithCancel(req.Context())
- defer cancel()
- if cn, ok := w.(http.CloseNotifier); ok {
- go func(done <-chan struct{}, closed <-chan bool) {
- select {
- case <-done:
- case <-closed:
- cancel()
- }
- }(ctx.Done(), cn.CloseNotify())
- }
- inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req)
- rctx, err := runtime.AnnotateContext(ctx, mux, req)
- if err != nil {
- runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err)
- return
- }
- resp, md, err := request_Election_Proclaim_0(rctx, inboundMarshaler, client, req, pathParams)
- ctx = runtime.NewServerMetadataContext(ctx, md)
- if err != nil {
- runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err)
- return
- }
-
- forward_Election_Proclaim_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...)
-
- })
-
- mux.Handle("POST", pattern_Election_Leader_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) {
- ctx, cancel := context.WithCancel(req.Context())
- defer cancel()
- if cn, ok := w.(http.CloseNotifier); ok {
- go func(done <-chan struct{}, closed <-chan bool) {
- select {
- case <-done:
- case <-closed:
- cancel()
- }
- }(ctx.Done(), cn.CloseNotify())
- }
- inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req)
- rctx, err := runtime.AnnotateContext(ctx, mux, req)
- if err != nil {
- runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err)
- return
- }
- resp, md, err := request_Election_Leader_0(rctx, inboundMarshaler, client, req, pathParams)
- ctx = runtime.NewServerMetadataContext(ctx, md)
- if err != nil {
- runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err)
- return
- }
-
- forward_Election_Leader_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...)
-
- })
-
- mux.Handle("POST", pattern_Election_Observe_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) {
- ctx, cancel := context.WithCancel(req.Context())
- defer cancel()
- if cn, ok := w.(http.CloseNotifier); ok {
- go func(done <-chan struct{}, closed <-chan bool) {
- select {
- case <-done:
- case <-closed:
- cancel()
- }
- }(ctx.Done(), cn.CloseNotify())
- }
- inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req)
- rctx, err := runtime.AnnotateContext(ctx, mux, req)
- if err != nil {
- runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err)
- return
- }
- resp, md, err := request_Election_Observe_0(rctx, inboundMarshaler, client, req, pathParams)
- ctx = runtime.NewServerMetadataContext(ctx, md)
- if err != nil {
- runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err)
- return
- }
-
- forward_Election_Observe_0(ctx, mux, outboundMarshaler, w, req, func() (proto.Message, error) { return resp.Recv() }, mux.GetForwardResponseOptions()...)
-
- })
-
- mux.Handle("POST", pattern_Election_Resign_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) {
- ctx, cancel := context.WithCancel(req.Context())
- defer cancel()
- if cn, ok := w.(http.CloseNotifier); ok {
- go func(done <-chan struct{}, closed <-chan bool) {
- select {
- case <-done:
- case <-closed:
- cancel()
- }
- }(ctx.Done(), cn.CloseNotify())
- }
- inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req)
- rctx, err := runtime.AnnotateContext(ctx, mux, req)
- if err != nil {
- runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err)
- return
- }
- resp, md, err := request_Election_Resign_0(rctx, inboundMarshaler, client, req, pathParams)
- ctx = runtime.NewServerMetadataContext(ctx, md)
- if err != nil {
- runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err)
- return
- }
-
- forward_Election_Resign_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...)
-
- })
-
- return nil
-}
-
-var (
- pattern_Election_Campaign_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2}, []string{"v3", "election", "campaign"}, ""))
-
- pattern_Election_Proclaim_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2}, []string{"v3", "election", "proclaim"}, ""))
-
- pattern_Election_Leader_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2}, []string{"v3", "election", "leader"}, ""))
-
- pattern_Election_Observe_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2}, []string{"v3", "election", "observe"}, ""))
-
- pattern_Election_Resign_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2}, []string{"v3", "election", "resign"}, ""))
-)
-
-var (
- forward_Election_Campaign_0 = runtime.ForwardResponseMessage
-
- forward_Election_Proclaim_0 = runtime.ForwardResponseMessage
-
- forward_Election_Leader_0 = runtime.ForwardResponseMessage
-
- forward_Election_Observe_0 = runtime.ForwardResponseStream
-
- forward_Election_Resign_0 = runtime.ForwardResponseMessage
-)
diff --git a/vendor/go.etcd.io/etcd/etcdserver/api/v3election/v3electionpb/v3election.pb.go b/vendor/go.etcd.io/etcd/etcdserver/api/v3election/v3electionpb/v3election.pb.go
deleted file mode 100644
index 1fc1bce..0000000
--- a/vendor/go.etcd.io/etcd/etcdserver/api/v3election/v3electionpb/v3election.pb.go
+++ /dev/null
@@ -1,2079 +0,0 @@
-// Code generated by protoc-gen-gogo. DO NOT EDIT.
-// source: v3election.proto
-
-/*
- Package v3electionpb is a generated protocol buffer package.
-
- It is generated from these files:
- v3election.proto
-
- It has these top-level messages:
- CampaignRequest
- CampaignResponse
- LeaderKey
- LeaderRequest
- LeaderResponse
- ResignRequest
- ResignResponse
- ProclaimRequest
- ProclaimResponse
-*/
-package v3electionpb
-
-import (
- "fmt"
-
- proto "github.com/golang/protobuf/proto"
-
- math "math"
-
- _ "github.com/gogo/protobuf/gogoproto"
-
- etcdserverpb "go.etcd.io/etcd/etcdserver/etcdserverpb"
-
- mvccpb "go.etcd.io/etcd/mvcc/mvccpb"
-
- context "golang.org/x/net/context"
-
- grpc "google.golang.org/grpc"
-
- io "io"
-)
-
-// Reference imports to suppress errors if they are not otherwise used.
-var _ = proto.Marshal
-var _ = fmt.Errorf
-var _ = math.Inf
-
-// This is a compile-time assertion to ensure that this generated file
-// is compatible with the proto package it is being compiled against.
-// A compilation error at this line likely means your copy of the
-// proto package needs to be updated.
-const _ = proto.ProtoPackageIsVersion2 // please upgrade the proto package
-
-type CampaignRequest struct {
- // name is the election's identifier for the campaign.
- Name []byte `protobuf:"bytes,1,opt,name=name,proto3" json:"name,omitempty"`
- // lease is the ID of the lease attached to leadership of the election. If the
- // lease expires or is revoked before resigning leadership, then the
- // leadership is transferred to the next campaigner, if any.
- Lease int64 `protobuf:"varint,2,opt,name=lease,proto3" json:"lease,omitempty"`
- // value is the initial proclaimed value set when the campaigner wins the
- // election.
- Value []byte `protobuf:"bytes,3,opt,name=value,proto3" json:"value,omitempty"`
-}
-
-func (m *CampaignRequest) Reset() { *m = CampaignRequest{} }
-func (m *CampaignRequest) String() string { return proto.CompactTextString(m) }
-func (*CampaignRequest) ProtoMessage() {}
-func (*CampaignRequest) Descriptor() ([]byte, []int) { return fileDescriptorV3Election, []int{0} }
-
-func (m *CampaignRequest) GetName() []byte {
- if m != nil {
- return m.Name
- }
- return nil
-}
-
-func (m *CampaignRequest) GetLease() int64 {
- if m != nil {
- return m.Lease
- }
- return 0
-}
-
-func (m *CampaignRequest) GetValue() []byte {
- if m != nil {
- return m.Value
- }
- return nil
-}
-
-type CampaignResponse struct {
- Header *etcdserverpb.ResponseHeader `protobuf:"bytes,1,opt,name=header" json:"header,omitempty"`
- // leader describes the resources used for holding leadereship of the election.
- Leader *LeaderKey `protobuf:"bytes,2,opt,name=leader" json:"leader,omitempty"`
-}
-
-func (m *CampaignResponse) Reset() { *m = CampaignResponse{} }
-func (m *CampaignResponse) String() string { return proto.CompactTextString(m) }
-func (*CampaignResponse) ProtoMessage() {}
-func (*CampaignResponse) Descriptor() ([]byte, []int) { return fileDescriptorV3Election, []int{1} }
-
-func (m *CampaignResponse) GetHeader() *etcdserverpb.ResponseHeader {
- if m != nil {
- return m.Header
- }
- return nil
-}
-
-func (m *CampaignResponse) GetLeader() *LeaderKey {
- if m != nil {
- return m.Leader
- }
- return nil
-}
-
-type LeaderKey struct {
- // name is the election identifier that correponds to the leadership key.
- Name []byte `protobuf:"bytes,1,opt,name=name,proto3" json:"name,omitempty"`
- // key is an opaque key representing the ownership of the election. If the key
- // is deleted, then leadership is lost.
- Key []byte `protobuf:"bytes,2,opt,name=key,proto3" json:"key,omitempty"`
- // rev is the creation revision of the key. It can be used to test for ownership
- // of an election during transactions by testing the key's creation revision
- // matches rev.
- Rev int64 `protobuf:"varint,3,opt,name=rev,proto3" json:"rev,omitempty"`
- // lease is the lease ID of the election leader.
- Lease int64 `protobuf:"varint,4,opt,name=lease,proto3" json:"lease,omitempty"`
-}
-
-func (m *LeaderKey) Reset() { *m = LeaderKey{} }
-func (m *LeaderKey) String() string { return proto.CompactTextString(m) }
-func (*LeaderKey) ProtoMessage() {}
-func (*LeaderKey) Descriptor() ([]byte, []int) { return fileDescriptorV3Election, []int{2} }
-
-func (m *LeaderKey) GetName() []byte {
- if m != nil {
- return m.Name
- }
- return nil
-}
-
-func (m *LeaderKey) GetKey() []byte {
- if m != nil {
- return m.Key
- }
- return nil
-}
-
-func (m *LeaderKey) GetRev() int64 {
- if m != nil {
- return m.Rev
- }
- return 0
-}
-
-func (m *LeaderKey) GetLease() int64 {
- if m != nil {
- return m.Lease
- }
- return 0
-}
-
-type LeaderRequest struct {
- // name is the election identifier for the leadership information.
- Name []byte `protobuf:"bytes,1,opt,name=name,proto3" json:"name,omitempty"`
-}
-
-func (m *LeaderRequest) Reset() { *m = LeaderRequest{} }
-func (m *LeaderRequest) String() string { return proto.CompactTextString(m) }
-func (*LeaderRequest) ProtoMessage() {}
-func (*LeaderRequest) Descriptor() ([]byte, []int) { return fileDescriptorV3Election, []int{3} }
-
-func (m *LeaderRequest) GetName() []byte {
- if m != nil {
- return m.Name
- }
- return nil
-}
-
-type LeaderResponse struct {
- Header *etcdserverpb.ResponseHeader `protobuf:"bytes,1,opt,name=header" json:"header,omitempty"`
- // kv is the key-value pair representing the latest leader update.
- Kv *mvccpb.KeyValue `protobuf:"bytes,2,opt,name=kv" json:"kv,omitempty"`
-}
-
-func (m *LeaderResponse) Reset() { *m = LeaderResponse{} }
-func (m *LeaderResponse) String() string { return proto.CompactTextString(m) }
-func (*LeaderResponse) ProtoMessage() {}
-func (*LeaderResponse) Descriptor() ([]byte, []int) { return fileDescriptorV3Election, []int{4} }
-
-func (m *LeaderResponse) GetHeader() *etcdserverpb.ResponseHeader {
- if m != nil {
- return m.Header
- }
- return nil
-}
-
-func (m *LeaderResponse) GetKv() *mvccpb.KeyValue {
- if m != nil {
- return m.Kv
- }
- return nil
-}
-
-type ResignRequest struct {
- // leader is the leadership to relinquish by resignation.
- Leader *LeaderKey `protobuf:"bytes,1,opt,name=leader" json:"leader,omitempty"`
-}
-
-func (m *ResignRequest) Reset() { *m = ResignRequest{} }
-func (m *ResignRequest) String() string { return proto.CompactTextString(m) }
-func (*ResignRequest) ProtoMessage() {}
-func (*ResignRequest) Descriptor() ([]byte, []int) { return fileDescriptorV3Election, []int{5} }
-
-func (m *ResignRequest) GetLeader() *LeaderKey {
- if m != nil {
- return m.Leader
- }
- return nil
-}
-
-type ResignResponse struct {
- Header *etcdserverpb.ResponseHeader `protobuf:"bytes,1,opt,name=header" json:"header,omitempty"`
-}
-
-func (m *ResignResponse) Reset() { *m = ResignResponse{} }
-func (m *ResignResponse) String() string { return proto.CompactTextString(m) }
-func (*ResignResponse) ProtoMessage() {}
-func (*ResignResponse) Descriptor() ([]byte, []int) { return fileDescriptorV3Election, []int{6} }
-
-func (m *ResignResponse) GetHeader() *etcdserverpb.ResponseHeader {
- if m != nil {
- return m.Header
- }
- return nil
-}
-
-type ProclaimRequest struct {
- // leader is the leadership hold on the election.
- Leader *LeaderKey `protobuf:"bytes,1,opt,name=leader" json:"leader,omitempty"`
- // value is an update meant to overwrite the leader's current value.
- Value []byte `protobuf:"bytes,2,opt,name=value,proto3" json:"value,omitempty"`
-}
-
-func (m *ProclaimRequest) Reset() { *m = ProclaimRequest{} }
-func (m *ProclaimRequest) String() string { return proto.CompactTextString(m) }
-func (*ProclaimRequest) ProtoMessage() {}
-func (*ProclaimRequest) Descriptor() ([]byte, []int) { return fileDescriptorV3Election, []int{7} }
-
-func (m *ProclaimRequest) GetLeader() *LeaderKey {
- if m != nil {
- return m.Leader
- }
- return nil
-}
-
-func (m *ProclaimRequest) GetValue() []byte {
- if m != nil {
- return m.Value
- }
- return nil
-}
-
-type ProclaimResponse struct {
- Header *etcdserverpb.ResponseHeader `protobuf:"bytes,1,opt,name=header" json:"header,omitempty"`
-}
-
-func (m *ProclaimResponse) Reset() { *m = ProclaimResponse{} }
-func (m *ProclaimResponse) String() string { return proto.CompactTextString(m) }
-func (*ProclaimResponse) ProtoMessage() {}
-func (*ProclaimResponse) Descriptor() ([]byte, []int) { return fileDescriptorV3Election, []int{8} }
-
-func (m *ProclaimResponse) GetHeader() *etcdserverpb.ResponseHeader {
- if m != nil {
- return m.Header
- }
- return nil
-}
-
-func init() {
- proto.RegisterType((*CampaignRequest)(nil), "v3electionpb.CampaignRequest")
- proto.RegisterType((*CampaignResponse)(nil), "v3electionpb.CampaignResponse")
- proto.RegisterType((*LeaderKey)(nil), "v3electionpb.LeaderKey")
- proto.RegisterType((*LeaderRequest)(nil), "v3electionpb.LeaderRequest")
- proto.RegisterType((*LeaderResponse)(nil), "v3electionpb.LeaderResponse")
- proto.RegisterType((*ResignRequest)(nil), "v3electionpb.ResignRequest")
- proto.RegisterType((*ResignResponse)(nil), "v3electionpb.ResignResponse")
- proto.RegisterType((*ProclaimRequest)(nil), "v3electionpb.ProclaimRequest")
- proto.RegisterType((*ProclaimResponse)(nil), "v3electionpb.ProclaimResponse")
-}
-
-// Reference imports to suppress errors if they are not otherwise used.
-var _ context.Context
-var _ grpc.ClientConn
-
-// This is a compile-time assertion to ensure that this generated file
-// is compatible with the grpc package it is being compiled against.
-const _ = grpc.SupportPackageIsVersion4
-
-// Client API for Election service
-
-type ElectionClient interface {
- // Campaign waits to acquire leadership in an election, returning a LeaderKey
- // representing the leadership if successful. The LeaderKey can then be used
- // to issue new values on the election, transactionally guard API requests on
- // leadership still being held, and resign from the election.
- Campaign(ctx context.Context, in *CampaignRequest, opts ...grpc.CallOption) (*CampaignResponse, error)
- // Proclaim updates the leader's posted value with a new value.
- Proclaim(ctx context.Context, in *ProclaimRequest, opts ...grpc.CallOption) (*ProclaimResponse, error)
- // Leader returns the current election proclamation, if any.
- Leader(ctx context.Context, in *LeaderRequest, opts ...grpc.CallOption) (*LeaderResponse, error)
- // Observe streams election proclamations in-order as made by the election's
- // elected leaders.
- Observe(ctx context.Context, in *LeaderRequest, opts ...grpc.CallOption) (Election_ObserveClient, error)
- // Resign releases election leadership so other campaigners may acquire
- // leadership on the election.
- Resign(ctx context.Context, in *ResignRequest, opts ...grpc.CallOption) (*ResignResponse, error)
-}
-
-type electionClient struct {
- cc *grpc.ClientConn
-}
-
-func NewElectionClient(cc *grpc.ClientConn) ElectionClient {
- return &electionClient{cc}
-}
-
-func (c *electionClient) Campaign(ctx context.Context, in *CampaignRequest, opts ...grpc.CallOption) (*CampaignResponse, error) {
- out := new(CampaignResponse)
- err := grpc.Invoke(ctx, "/v3electionpb.Election/Campaign", in, out, c.cc, opts...)
- if err != nil {
- return nil, err
- }
- return out, nil
-}
-
-func (c *electionClient) Proclaim(ctx context.Context, in *ProclaimRequest, opts ...grpc.CallOption) (*ProclaimResponse, error) {
- out := new(ProclaimResponse)
- err := grpc.Invoke(ctx, "/v3electionpb.Election/Proclaim", in, out, c.cc, opts...)
- if err != nil {
- return nil, err
- }
- return out, nil
-}
-
-func (c *electionClient) Leader(ctx context.Context, in *LeaderRequest, opts ...grpc.CallOption) (*LeaderResponse, error) {
- out := new(LeaderResponse)
- err := grpc.Invoke(ctx, "/v3electionpb.Election/Leader", in, out, c.cc, opts...)
- if err != nil {
- return nil, err
- }
- return out, nil
-}
-
-func (c *electionClient) Observe(ctx context.Context, in *LeaderRequest, opts ...grpc.CallOption) (Election_ObserveClient, error) {
- stream, err := grpc.NewClientStream(ctx, &_Election_serviceDesc.Streams[0], c.cc, "/v3electionpb.Election/Observe", opts...)
- if err != nil {
- return nil, err
- }
- x := &electionObserveClient{stream}
- if err := x.ClientStream.SendMsg(in); err != nil {
- return nil, err
- }
- if err := x.ClientStream.CloseSend(); err != nil {
- return nil, err
- }
- return x, nil
-}
-
-type Election_ObserveClient interface {
- Recv() (*LeaderResponse, error)
- grpc.ClientStream
-}
-
-type electionObserveClient struct {
- grpc.ClientStream
-}
-
-func (x *electionObserveClient) Recv() (*LeaderResponse, error) {
- m := new(LeaderResponse)
- if err := x.ClientStream.RecvMsg(m); err != nil {
- return nil, err
- }
- return m, nil
-}
-
-func (c *electionClient) Resign(ctx context.Context, in *ResignRequest, opts ...grpc.CallOption) (*ResignResponse, error) {
- out := new(ResignResponse)
- err := grpc.Invoke(ctx, "/v3electionpb.Election/Resign", in, out, c.cc, opts...)
- if err != nil {
- return nil, err
- }
- return out, nil
-}
-
-// Server API for Election service
-
-type ElectionServer interface {
- // Campaign waits to acquire leadership in an election, returning a LeaderKey
- // representing the leadership if successful. The LeaderKey can then be used
- // to issue new values on the election, transactionally guard API requests on
- // leadership still being held, and resign from the election.
- Campaign(context.Context, *CampaignRequest) (*CampaignResponse, error)
- // Proclaim updates the leader's posted value with a new value.
- Proclaim(context.Context, *ProclaimRequest) (*ProclaimResponse, error)
- // Leader returns the current election proclamation, if any.
- Leader(context.Context, *LeaderRequest) (*LeaderResponse, error)
- // Observe streams election proclamations in-order as made by the election's
- // elected leaders.
- Observe(*LeaderRequest, Election_ObserveServer) error
- // Resign releases election leadership so other campaigners may acquire
- // leadership on the election.
- Resign(context.Context, *ResignRequest) (*ResignResponse, error)
-}
-
-func RegisterElectionServer(s *grpc.Server, srv ElectionServer) {
- s.RegisterService(&_Election_serviceDesc, srv)
-}
-
-func _Election_Campaign_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
- in := new(CampaignRequest)
- if err := dec(in); err != nil {
- return nil, err
- }
- if interceptor == nil {
- return srv.(ElectionServer).Campaign(ctx, in)
- }
- info := &grpc.UnaryServerInfo{
- Server: srv,
- FullMethod: "/v3electionpb.Election/Campaign",
- }
- handler := func(ctx context.Context, req interface{}) (interface{}, error) {
- return srv.(ElectionServer).Campaign(ctx, req.(*CampaignRequest))
- }
- return interceptor(ctx, in, info, handler)
-}
-
-func _Election_Proclaim_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
- in := new(ProclaimRequest)
- if err := dec(in); err != nil {
- return nil, err
- }
- if interceptor == nil {
- return srv.(ElectionServer).Proclaim(ctx, in)
- }
- info := &grpc.UnaryServerInfo{
- Server: srv,
- FullMethod: "/v3electionpb.Election/Proclaim",
- }
- handler := func(ctx context.Context, req interface{}) (interface{}, error) {
- return srv.(ElectionServer).Proclaim(ctx, req.(*ProclaimRequest))
- }
- return interceptor(ctx, in, info, handler)
-}
-
-func _Election_Leader_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
- in := new(LeaderRequest)
- if err := dec(in); err != nil {
- return nil, err
- }
- if interceptor == nil {
- return srv.(ElectionServer).Leader(ctx, in)
- }
- info := &grpc.UnaryServerInfo{
- Server: srv,
- FullMethod: "/v3electionpb.Election/Leader",
- }
- handler := func(ctx context.Context, req interface{}) (interface{}, error) {
- return srv.(ElectionServer).Leader(ctx, req.(*LeaderRequest))
- }
- return interceptor(ctx, in, info, handler)
-}
-
-func _Election_Observe_Handler(srv interface{}, stream grpc.ServerStream) error {
- m := new(LeaderRequest)
- if err := stream.RecvMsg(m); err != nil {
- return err
- }
- return srv.(ElectionServer).Observe(m, &electionObserveServer{stream})
-}
-
-type Election_ObserveServer interface {
- Send(*LeaderResponse) error
- grpc.ServerStream
-}
-
-type electionObserveServer struct {
- grpc.ServerStream
-}
-
-func (x *electionObserveServer) Send(m *LeaderResponse) error {
- return x.ServerStream.SendMsg(m)
-}
-
-func _Election_Resign_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
- in := new(ResignRequest)
- if err := dec(in); err != nil {
- return nil, err
- }
- if interceptor == nil {
- return srv.(ElectionServer).Resign(ctx, in)
- }
- info := &grpc.UnaryServerInfo{
- Server: srv,
- FullMethod: "/v3electionpb.Election/Resign",
- }
- handler := func(ctx context.Context, req interface{}) (interface{}, error) {
- return srv.(ElectionServer).Resign(ctx, req.(*ResignRequest))
- }
- return interceptor(ctx, in, info, handler)
-}
-
-var _Election_serviceDesc = grpc.ServiceDesc{
- ServiceName: "v3electionpb.Election",
- HandlerType: (*ElectionServer)(nil),
- Methods: []grpc.MethodDesc{
- {
- MethodName: "Campaign",
- Handler: _Election_Campaign_Handler,
- },
- {
- MethodName: "Proclaim",
- Handler: _Election_Proclaim_Handler,
- },
- {
- MethodName: "Leader",
- Handler: _Election_Leader_Handler,
- },
- {
- MethodName: "Resign",
- Handler: _Election_Resign_Handler,
- },
- },
- Streams: []grpc.StreamDesc{
- {
- StreamName: "Observe",
- Handler: _Election_Observe_Handler,
- ServerStreams: true,
- },
- },
- Metadata: "v3election.proto",
-}
-
-func (m *CampaignRequest) Marshal() (dAtA []byte, err error) {
- size := m.Size()
- dAtA = make([]byte, size)
- n, err := m.MarshalTo(dAtA)
- if err != nil {
- return nil, err
- }
- return dAtA[:n], nil
-}
-
-func (m *CampaignRequest) MarshalTo(dAtA []byte) (int, error) {
- var i int
- _ = i
- var l int
- _ = l
- if len(m.Name) > 0 {
- dAtA[i] = 0xa
- i++
- i = encodeVarintV3Election(dAtA, i, uint64(len(m.Name)))
- i += copy(dAtA[i:], m.Name)
- }
- if m.Lease != 0 {
- dAtA[i] = 0x10
- i++
- i = encodeVarintV3Election(dAtA, i, uint64(m.Lease))
- }
- if len(m.Value) > 0 {
- dAtA[i] = 0x1a
- i++
- i = encodeVarintV3Election(dAtA, i, uint64(len(m.Value)))
- i += copy(dAtA[i:], m.Value)
- }
- return i, nil
-}
-
-func (m *CampaignResponse) Marshal() (dAtA []byte, err error) {
- size := m.Size()
- dAtA = make([]byte, size)
- n, err := m.MarshalTo(dAtA)
- if err != nil {
- return nil, err
- }
- return dAtA[:n], nil
-}
-
-func (m *CampaignResponse) MarshalTo(dAtA []byte) (int, error) {
- var i int
- _ = i
- var l int
- _ = l
- if m.Header != nil {
- dAtA[i] = 0xa
- i++
- i = encodeVarintV3Election(dAtA, i, uint64(m.Header.Size()))
- n1, err := m.Header.MarshalTo(dAtA[i:])
- if err != nil {
- return 0, err
- }
- i += n1
- }
- if m.Leader != nil {
- dAtA[i] = 0x12
- i++
- i = encodeVarintV3Election(dAtA, i, uint64(m.Leader.Size()))
- n2, err := m.Leader.MarshalTo(dAtA[i:])
- if err != nil {
- return 0, err
- }
- i += n2
- }
- return i, nil
-}
-
-func (m *LeaderKey) Marshal() (dAtA []byte, err error) {
- size := m.Size()
- dAtA = make([]byte, size)
- n, err := m.MarshalTo(dAtA)
- if err != nil {
- return nil, err
- }
- return dAtA[:n], nil
-}
-
-func (m *LeaderKey) MarshalTo(dAtA []byte) (int, error) {
- var i int
- _ = i
- var l int
- _ = l
- if len(m.Name) > 0 {
- dAtA[i] = 0xa
- i++
- i = encodeVarintV3Election(dAtA, i, uint64(len(m.Name)))
- i += copy(dAtA[i:], m.Name)
- }
- if len(m.Key) > 0 {
- dAtA[i] = 0x12
- i++
- i = encodeVarintV3Election(dAtA, i, uint64(len(m.Key)))
- i += copy(dAtA[i:], m.Key)
- }
- if m.Rev != 0 {
- dAtA[i] = 0x18
- i++
- i = encodeVarintV3Election(dAtA, i, uint64(m.Rev))
- }
- if m.Lease != 0 {
- dAtA[i] = 0x20
- i++
- i = encodeVarintV3Election(dAtA, i, uint64(m.Lease))
- }
- return i, nil
-}
-
-func (m *LeaderRequest) Marshal() (dAtA []byte, err error) {
- size := m.Size()
- dAtA = make([]byte, size)
- n, err := m.MarshalTo(dAtA)
- if err != nil {
- return nil, err
- }
- return dAtA[:n], nil
-}
-
-func (m *LeaderRequest) MarshalTo(dAtA []byte) (int, error) {
- var i int
- _ = i
- var l int
- _ = l
- if len(m.Name) > 0 {
- dAtA[i] = 0xa
- i++
- i = encodeVarintV3Election(dAtA, i, uint64(len(m.Name)))
- i += copy(dAtA[i:], m.Name)
- }
- return i, nil
-}
-
-func (m *LeaderResponse) Marshal() (dAtA []byte, err error) {
- size := m.Size()
- dAtA = make([]byte, size)
- n, err := m.MarshalTo(dAtA)
- if err != nil {
- return nil, err
- }
- return dAtA[:n], nil
-}
-
-func (m *LeaderResponse) MarshalTo(dAtA []byte) (int, error) {
- var i int
- _ = i
- var l int
- _ = l
- if m.Header != nil {
- dAtA[i] = 0xa
- i++
- i = encodeVarintV3Election(dAtA, i, uint64(m.Header.Size()))
- n3, err := m.Header.MarshalTo(dAtA[i:])
- if err != nil {
- return 0, err
- }
- i += n3
- }
- if m.Kv != nil {
- dAtA[i] = 0x12
- i++
- i = encodeVarintV3Election(dAtA, i, uint64(m.Kv.Size()))
- n4, err := m.Kv.MarshalTo(dAtA[i:])
- if err != nil {
- return 0, err
- }
- i += n4
- }
- return i, nil
-}
-
-func (m *ResignRequest) Marshal() (dAtA []byte, err error) {
- size := m.Size()
- dAtA = make([]byte, size)
- n, err := m.MarshalTo(dAtA)
- if err != nil {
- return nil, err
- }
- return dAtA[:n], nil
-}
-
-func (m *ResignRequest) MarshalTo(dAtA []byte) (int, error) {
- var i int
- _ = i
- var l int
- _ = l
- if m.Leader != nil {
- dAtA[i] = 0xa
- i++
- i = encodeVarintV3Election(dAtA, i, uint64(m.Leader.Size()))
- n5, err := m.Leader.MarshalTo(dAtA[i:])
- if err != nil {
- return 0, err
- }
- i += n5
- }
- return i, nil
-}
-
-func (m *ResignResponse) Marshal() (dAtA []byte, err error) {
- size := m.Size()
- dAtA = make([]byte, size)
- n, err := m.MarshalTo(dAtA)
- if err != nil {
- return nil, err
- }
- return dAtA[:n], nil
-}
-
-func (m *ResignResponse) MarshalTo(dAtA []byte) (int, error) {
- var i int
- _ = i
- var l int
- _ = l
- if m.Header != nil {
- dAtA[i] = 0xa
- i++
- i = encodeVarintV3Election(dAtA, i, uint64(m.Header.Size()))
- n6, err := m.Header.MarshalTo(dAtA[i:])
- if err != nil {
- return 0, err
- }
- i += n6
- }
- return i, nil
-}
-
-func (m *ProclaimRequest) Marshal() (dAtA []byte, err error) {
- size := m.Size()
- dAtA = make([]byte, size)
- n, err := m.MarshalTo(dAtA)
- if err != nil {
- return nil, err
- }
- return dAtA[:n], nil
-}
-
-func (m *ProclaimRequest) MarshalTo(dAtA []byte) (int, error) {
- var i int
- _ = i
- var l int
- _ = l
- if m.Leader != nil {
- dAtA[i] = 0xa
- i++
- i = encodeVarintV3Election(dAtA, i, uint64(m.Leader.Size()))
- n7, err := m.Leader.MarshalTo(dAtA[i:])
- if err != nil {
- return 0, err
- }
- i += n7
- }
- if len(m.Value) > 0 {
- dAtA[i] = 0x12
- i++
- i = encodeVarintV3Election(dAtA, i, uint64(len(m.Value)))
- i += copy(dAtA[i:], m.Value)
- }
- return i, nil
-}
-
-func (m *ProclaimResponse) Marshal() (dAtA []byte, err error) {
- size := m.Size()
- dAtA = make([]byte, size)
- n, err := m.MarshalTo(dAtA)
- if err != nil {
- return nil, err
- }
- return dAtA[:n], nil
-}
-
-func (m *ProclaimResponse) MarshalTo(dAtA []byte) (int, error) {
- var i int
- _ = i
- var l int
- _ = l
- if m.Header != nil {
- dAtA[i] = 0xa
- i++
- i = encodeVarintV3Election(dAtA, i, uint64(m.Header.Size()))
- n8, err := m.Header.MarshalTo(dAtA[i:])
- if err != nil {
- return 0, err
- }
- i += n8
- }
- return i, nil
-}
-
-func encodeVarintV3Election(dAtA []byte, offset int, v uint64) int {
- for v >= 1<<7 {
- dAtA[offset] = uint8(v&0x7f | 0x80)
- v >>= 7
- offset++
- }
- dAtA[offset] = uint8(v)
- return offset + 1
-}
-func (m *CampaignRequest) Size() (n int) {
- var l int
- _ = l
- l = len(m.Name)
- if l > 0 {
- n += 1 + l + sovV3Election(uint64(l))
- }
- if m.Lease != 0 {
- n += 1 + sovV3Election(uint64(m.Lease))
- }
- l = len(m.Value)
- if l > 0 {
- n += 1 + l + sovV3Election(uint64(l))
- }
- return n
-}
-
-func (m *CampaignResponse) Size() (n int) {
- var l int
- _ = l
- if m.Header != nil {
- l = m.Header.Size()
- n += 1 + l + sovV3Election(uint64(l))
- }
- if m.Leader != nil {
- l = m.Leader.Size()
- n += 1 + l + sovV3Election(uint64(l))
- }
- return n
-}
-
-func (m *LeaderKey) Size() (n int) {
- var l int
- _ = l
- l = len(m.Name)
- if l > 0 {
- n += 1 + l + sovV3Election(uint64(l))
- }
- l = len(m.Key)
- if l > 0 {
- n += 1 + l + sovV3Election(uint64(l))
- }
- if m.Rev != 0 {
- n += 1 + sovV3Election(uint64(m.Rev))
- }
- if m.Lease != 0 {
- n += 1 + sovV3Election(uint64(m.Lease))
- }
- return n
-}
-
-func (m *LeaderRequest) Size() (n int) {
- var l int
- _ = l
- l = len(m.Name)
- if l > 0 {
- n += 1 + l + sovV3Election(uint64(l))
- }
- return n
-}
-
-func (m *LeaderResponse) Size() (n int) {
- var l int
- _ = l
- if m.Header != nil {
- l = m.Header.Size()
- n += 1 + l + sovV3Election(uint64(l))
- }
- if m.Kv != nil {
- l = m.Kv.Size()
- n += 1 + l + sovV3Election(uint64(l))
- }
- return n
-}
-
-func (m *ResignRequest) Size() (n int) {
- var l int
- _ = l
- if m.Leader != nil {
- l = m.Leader.Size()
- n += 1 + l + sovV3Election(uint64(l))
- }
- return n
-}
-
-func (m *ResignResponse) Size() (n int) {
- var l int
- _ = l
- if m.Header != nil {
- l = m.Header.Size()
- n += 1 + l + sovV3Election(uint64(l))
- }
- return n
-}
-
-func (m *ProclaimRequest) Size() (n int) {
- var l int
- _ = l
- if m.Leader != nil {
- l = m.Leader.Size()
- n += 1 + l + sovV3Election(uint64(l))
- }
- l = len(m.Value)
- if l > 0 {
- n += 1 + l + sovV3Election(uint64(l))
- }
- return n
-}
-
-func (m *ProclaimResponse) Size() (n int) {
- var l int
- _ = l
- if m.Header != nil {
- l = m.Header.Size()
- n += 1 + l + sovV3Election(uint64(l))
- }
- return n
-}
-
-func sovV3Election(x uint64) (n int) {
- for {
- n++
- x >>= 7
- if x == 0 {
- break
- }
- }
- return n
-}
-func sozV3Election(x uint64) (n int) {
- return sovV3Election(uint64((x << 1) ^ uint64((int64(x) >> 63))))
-}
-func (m *CampaignRequest) Unmarshal(dAtA []byte) error {
- l := len(dAtA)
- iNdEx := 0
- for iNdEx < l {
- preIndex := iNdEx
- var wire uint64
- for shift := uint(0); ; shift += 7 {
- if shift >= 64 {
- return ErrIntOverflowV3Election
- }
- if iNdEx >= l {
- return io.ErrUnexpectedEOF
- }
- b := dAtA[iNdEx]
- iNdEx++
- wire |= (uint64(b) & 0x7F) << shift
- if b < 0x80 {
- break
- }
- }
- fieldNum := int32(wire >> 3)
- wireType := int(wire & 0x7)
- if wireType == 4 {
- return fmt.Errorf("proto: CampaignRequest: wiretype end group for non-group")
- }
- if fieldNum <= 0 {
- return fmt.Errorf("proto: CampaignRequest: illegal tag %d (wire type %d)", fieldNum, wire)
- }
- switch fieldNum {
- case 1:
- if wireType != 2 {
- return fmt.Errorf("proto: wrong wireType = %d for field Name", wireType)
- }
- var byteLen int
- for shift := uint(0); ; shift += 7 {
- if shift >= 64 {
- return ErrIntOverflowV3Election
- }
- if iNdEx >= l {
- return io.ErrUnexpectedEOF
- }
- b := dAtA[iNdEx]
- iNdEx++
- byteLen |= (int(b) & 0x7F) << shift
- if b < 0x80 {
- break
- }
- }
- if byteLen < 0 {
- return ErrInvalidLengthV3Election
- }
- postIndex := iNdEx + byteLen
- if postIndex > l {
- return io.ErrUnexpectedEOF
- }
- m.Name = append(m.Name[:0], dAtA[iNdEx:postIndex]...)
- if m.Name == nil {
- m.Name = []byte{}
- }
- iNdEx = postIndex
- case 2:
- if wireType != 0 {
- return fmt.Errorf("proto: wrong wireType = %d for field Lease", wireType)
- }
- m.Lease = 0
- for shift := uint(0); ; shift += 7 {
- if shift >= 64 {
- return ErrIntOverflowV3Election
- }
- if iNdEx >= l {
- return io.ErrUnexpectedEOF
- }
- b := dAtA[iNdEx]
- iNdEx++
- m.Lease |= (int64(b) & 0x7F) << shift
- if b < 0x80 {
- break
- }
- }
- case 3:
- if wireType != 2 {
- return fmt.Errorf("proto: wrong wireType = %d for field Value", wireType)
- }
- var byteLen int
- for shift := uint(0); ; shift += 7 {
- if shift >= 64 {
- return ErrIntOverflowV3Election
- }
- if iNdEx >= l {
- return io.ErrUnexpectedEOF
- }
- b := dAtA[iNdEx]
- iNdEx++
- byteLen |= (int(b) & 0x7F) << shift
- if b < 0x80 {
- break
- }
- }
- if byteLen < 0 {
- return ErrInvalidLengthV3Election
- }
- postIndex := iNdEx + byteLen
- if postIndex > l {
- return io.ErrUnexpectedEOF
- }
- m.Value = append(m.Value[:0], dAtA[iNdEx:postIndex]...)
- if m.Value == nil {
- m.Value = []byte{}
- }
- iNdEx = postIndex
- default:
- iNdEx = preIndex
- skippy, err := skipV3Election(dAtA[iNdEx:])
- if err != nil {
- return err
- }
- if skippy < 0 {
- return ErrInvalidLengthV3Election
- }
- if (iNdEx + skippy) > l {
- return io.ErrUnexpectedEOF
- }
- iNdEx += skippy
- }
- }
-
- if iNdEx > l {
- return io.ErrUnexpectedEOF
- }
- return nil
-}
-func (m *CampaignResponse) Unmarshal(dAtA []byte) error {
- l := len(dAtA)
- iNdEx := 0
- for iNdEx < l {
- preIndex := iNdEx
- var wire uint64
- for shift := uint(0); ; shift += 7 {
- if shift >= 64 {
- return ErrIntOverflowV3Election
- }
- if iNdEx >= l {
- return io.ErrUnexpectedEOF
- }
- b := dAtA[iNdEx]
- iNdEx++
- wire |= (uint64(b) & 0x7F) << shift
- if b < 0x80 {
- break
- }
- }
- fieldNum := int32(wire >> 3)
- wireType := int(wire & 0x7)
- if wireType == 4 {
- return fmt.Errorf("proto: CampaignResponse: wiretype end group for non-group")
- }
- if fieldNum <= 0 {
- return fmt.Errorf("proto: CampaignResponse: illegal tag %d (wire type %d)", fieldNum, wire)
- }
- switch fieldNum {
- case 1:
- if wireType != 2 {
- return fmt.Errorf("proto: wrong wireType = %d for field Header", wireType)
- }
- var msglen int
- for shift := uint(0); ; shift += 7 {
- if shift >= 64 {
- return ErrIntOverflowV3Election
- }
- if iNdEx >= l {
- return io.ErrUnexpectedEOF
- }
- b := dAtA[iNdEx]
- iNdEx++
- msglen |= (int(b) & 0x7F) << shift
- if b < 0x80 {
- break
- }
- }
- if msglen < 0 {
- return ErrInvalidLengthV3Election
- }
- postIndex := iNdEx + msglen
- if postIndex > l {
- return io.ErrUnexpectedEOF
- }
- if m.Header == nil {
- m.Header = &etcdserverpb.ResponseHeader{}
- }
- if err := m.Header.Unmarshal(dAtA[iNdEx:postIndex]); err != nil {
- return err
- }
- iNdEx = postIndex
- case 2:
- if wireType != 2 {
- return fmt.Errorf("proto: wrong wireType = %d for field Leader", wireType)
- }
- var msglen int
- for shift := uint(0); ; shift += 7 {
- if shift >= 64 {
- return ErrIntOverflowV3Election
- }
- if iNdEx >= l {
- return io.ErrUnexpectedEOF
- }
- b := dAtA[iNdEx]
- iNdEx++
- msglen |= (int(b) & 0x7F) << shift
- if b < 0x80 {
- break
- }
- }
- if msglen < 0 {
- return ErrInvalidLengthV3Election
- }
- postIndex := iNdEx + msglen
- if postIndex > l {
- return io.ErrUnexpectedEOF
- }
- if m.Leader == nil {
- m.Leader = &LeaderKey{}
- }
- if err := m.Leader.Unmarshal(dAtA[iNdEx:postIndex]); err != nil {
- return err
- }
- iNdEx = postIndex
- default:
- iNdEx = preIndex
- skippy, err := skipV3Election(dAtA[iNdEx:])
- if err != nil {
- return err
- }
- if skippy < 0 {
- return ErrInvalidLengthV3Election
- }
- if (iNdEx + skippy) > l {
- return io.ErrUnexpectedEOF
- }
- iNdEx += skippy
- }
- }
-
- if iNdEx > l {
- return io.ErrUnexpectedEOF
- }
- return nil
-}
-func (m *LeaderKey) Unmarshal(dAtA []byte) error {
- l := len(dAtA)
- iNdEx := 0
- for iNdEx < l {
- preIndex := iNdEx
- var wire uint64
- for shift := uint(0); ; shift += 7 {
- if shift >= 64 {
- return ErrIntOverflowV3Election
- }
- if iNdEx >= l {
- return io.ErrUnexpectedEOF
- }
- b := dAtA[iNdEx]
- iNdEx++
- wire |= (uint64(b) & 0x7F) << shift
- if b < 0x80 {
- break
- }
- }
- fieldNum := int32(wire >> 3)
- wireType := int(wire & 0x7)
- if wireType == 4 {
- return fmt.Errorf("proto: LeaderKey: wiretype end group for non-group")
- }
- if fieldNum <= 0 {
- return fmt.Errorf("proto: LeaderKey: illegal tag %d (wire type %d)", fieldNum, wire)
- }
- switch fieldNum {
- case 1:
- if wireType != 2 {
- return fmt.Errorf("proto: wrong wireType = %d for field Name", wireType)
- }
- var byteLen int
- for shift := uint(0); ; shift += 7 {
- if shift >= 64 {
- return ErrIntOverflowV3Election
- }
- if iNdEx >= l {
- return io.ErrUnexpectedEOF
- }
- b := dAtA[iNdEx]
- iNdEx++
- byteLen |= (int(b) & 0x7F) << shift
- if b < 0x80 {
- break
- }
- }
- if byteLen < 0 {
- return ErrInvalidLengthV3Election
- }
- postIndex := iNdEx + byteLen
- if postIndex > l {
- return io.ErrUnexpectedEOF
- }
- m.Name = append(m.Name[:0], dAtA[iNdEx:postIndex]...)
- if m.Name == nil {
- m.Name = []byte{}
- }
- iNdEx = postIndex
- case 2:
- if wireType != 2 {
- return fmt.Errorf("proto: wrong wireType = %d for field Key", wireType)
- }
- var byteLen int
- for shift := uint(0); ; shift += 7 {
- if shift >= 64 {
- return ErrIntOverflowV3Election
- }
- if iNdEx >= l {
- return io.ErrUnexpectedEOF
- }
- b := dAtA[iNdEx]
- iNdEx++
- byteLen |= (int(b) & 0x7F) << shift
- if b < 0x80 {
- break
- }
- }
- if byteLen < 0 {
- return ErrInvalidLengthV3Election
- }
- postIndex := iNdEx + byteLen
- if postIndex > l {
- return io.ErrUnexpectedEOF
- }
- m.Key = append(m.Key[:0], dAtA[iNdEx:postIndex]...)
- if m.Key == nil {
- m.Key = []byte{}
- }
- iNdEx = postIndex
- case 3:
- if wireType != 0 {
- return fmt.Errorf("proto: wrong wireType = %d for field Rev", wireType)
- }
- m.Rev = 0
- for shift := uint(0); ; shift += 7 {
- if shift >= 64 {
- return ErrIntOverflowV3Election
- }
- if iNdEx >= l {
- return io.ErrUnexpectedEOF
- }
- b := dAtA[iNdEx]
- iNdEx++
- m.Rev |= (int64(b) & 0x7F) << shift
- if b < 0x80 {
- break
- }
- }
- case 4:
- if wireType != 0 {
- return fmt.Errorf("proto: wrong wireType = %d for field Lease", wireType)
- }
- m.Lease = 0
- for shift := uint(0); ; shift += 7 {
- if shift >= 64 {
- return ErrIntOverflowV3Election
- }
- if iNdEx >= l {
- return io.ErrUnexpectedEOF
- }
- b := dAtA[iNdEx]
- iNdEx++
- m.Lease |= (int64(b) & 0x7F) << shift
- if b < 0x80 {
- break
- }
- }
- default:
- iNdEx = preIndex
- skippy, err := skipV3Election(dAtA[iNdEx:])
- if err != nil {
- return err
- }
- if skippy < 0 {
- return ErrInvalidLengthV3Election
- }
- if (iNdEx + skippy) > l {
- return io.ErrUnexpectedEOF
- }
- iNdEx += skippy
- }
- }
-
- if iNdEx > l {
- return io.ErrUnexpectedEOF
- }
- return nil
-}
-func (m *LeaderRequest) Unmarshal(dAtA []byte) error {
- l := len(dAtA)
- iNdEx := 0
- for iNdEx < l {
- preIndex := iNdEx
- var wire uint64
- for shift := uint(0); ; shift += 7 {
- if shift >= 64 {
- return ErrIntOverflowV3Election
- }
- if iNdEx >= l {
- return io.ErrUnexpectedEOF
- }
- b := dAtA[iNdEx]
- iNdEx++
- wire |= (uint64(b) & 0x7F) << shift
- if b < 0x80 {
- break
- }
- }
- fieldNum := int32(wire >> 3)
- wireType := int(wire & 0x7)
- if wireType == 4 {
- return fmt.Errorf("proto: LeaderRequest: wiretype end group for non-group")
- }
- if fieldNum <= 0 {
- return fmt.Errorf("proto: LeaderRequest: illegal tag %d (wire type %d)", fieldNum, wire)
- }
- switch fieldNum {
- case 1:
- if wireType != 2 {
- return fmt.Errorf("proto: wrong wireType = %d for field Name", wireType)
- }
- var byteLen int
- for shift := uint(0); ; shift += 7 {
- if shift >= 64 {
- return ErrIntOverflowV3Election
- }
- if iNdEx >= l {
- return io.ErrUnexpectedEOF
- }
- b := dAtA[iNdEx]
- iNdEx++
- byteLen |= (int(b) & 0x7F) << shift
- if b < 0x80 {
- break
- }
- }
- if byteLen < 0 {
- return ErrInvalidLengthV3Election
- }
- postIndex := iNdEx + byteLen
- if postIndex > l {
- return io.ErrUnexpectedEOF
- }
- m.Name = append(m.Name[:0], dAtA[iNdEx:postIndex]...)
- if m.Name == nil {
- m.Name = []byte{}
- }
- iNdEx = postIndex
- default:
- iNdEx = preIndex
- skippy, err := skipV3Election(dAtA[iNdEx:])
- if err != nil {
- return err
- }
- if skippy < 0 {
- return ErrInvalidLengthV3Election
- }
- if (iNdEx + skippy) > l {
- return io.ErrUnexpectedEOF
- }
- iNdEx += skippy
- }
- }
-
- if iNdEx > l {
- return io.ErrUnexpectedEOF
- }
- return nil
-}
-func (m *LeaderResponse) Unmarshal(dAtA []byte) error {
- l := len(dAtA)
- iNdEx := 0
- for iNdEx < l {
- preIndex := iNdEx
- var wire uint64
- for shift := uint(0); ; shift += 7 {
- if shift >= 64 {
- return ErrIntOverflowV3Election
- }
- if iNdEx >= l {
- return io.ErrUnexpectedEOF
- }
- b := dAtA[iNdEx]
- iNdEx++
- wire |= (uint64(b) & 0x7F) << shift
- if b < 0x80 {
- break
- }
- }
- fieldNum := int32(wire >> 3)
- wireType := int(wire & 0x7)
- if wireType == 4 {
- return fmt.Errorf("proto: LeaderResponse: wiretype end group for non-group")
- }
- if fieldNum <= 0 {
- return fmt.Errorf("proto: LeaderResponse: illegal tag %d (wire type %d)", fieldNum, wire)
- }
- switch fieldNum {
- case 1:
- if wireType != 2 {
- return fmt.Errorf("proto: wrong wireType = %d for field Header", wireType)
- }
- var msglen int
- for shift := uint(0); ; shift += 7 {
- if shift >= 64 {
- return ErrIntOverflowV3Election
- }
- if iNdEx >= l {
- return io.ErrUnexpectedEOF
- }
- b := dAtA[iNdEx]
- iNdEx++
- msglen |= (int(b) & 0x7F) << shift
- if b < 0x80 {
- break
- }
- }
- if msglen < 0 {
- return ErrInvalidLengthV3Election
- }
- postIndex := iNdEx + msglen
- if postIndex > l {
- return io.ErrUnexpectedEOF
- }
- if m.Header == nil {
- m.Header = &etcdserverpb.ResponseHeader{}
- }
- if err := m.Header.Unmarshal(dAtA[iNdEx:postIndex]); err != nil {
- return err
- }
- iNdEx = postIndex
- case 2:
- if wireType != 2 {
- return fmt.Errorf("proto: wrong wireType = %d for field Kv", wireType)
- }
- var msglen int
- for shift := uint(0); ; shift += 7 {
- if shift >= 64 {
- return ErrIntOverflowV3Election
- }
- if iNdEx >= l {
- return io.ErrUnexpectedEOF
- }
- b := dAtA[iNdEx]
- iNdEx++
- msglen |= (int(b) & 0x7F) << shift
- if b < 0x80 {
- break
- }
- }
- if msglen < 0 {
- return ErrInvalidLengthV3Election
- }
- postIndex := iNdEx + msglen
- if postIndex > l {
- return io.ErrUnexpectedEOF
- }
- if m.Kv == nil {
- m.Kv = &mvccpb.KeyValue{}
- }
- if err := m.Kv.Unmarshal(dAtA[iNdEx:postIndex]); err != nil {
- return err
- }
- iNdEx = postIndex
- default:
- iNdEx = preIndex
- skippy, err := skipV3Election(dAtA[iNdEx:])
- if err != nil {
- return err
- }
- if skippy < 0 {
- return ErrInvalidLengthV3Election
- }
- if (iNdEx + skippy) > l {
- return io.ErrUnexpectedEOF
- }
- iNdEx += skippy
- }
- }
-
- if iNdEx > l {
- return io.ErrUnexpectedEOF
- }
- return nil
-}
-func (m *ResignRequest) Unmarshal(dAtA []byte) error {
- l := len(dAtA)
- iNdEx := 0
- for iNdEx < l {
- preIndex := iNdEx
- var wire uint64
- for shift := uint(0); ; shift += 7 {
- if shift >= 64 {
- return ErrIntOverflowV3Election
- }
- if iNdEx >= l {
- return io.ErrUnexpectedEOF
- }
- b := dAtA[iNdEx]
- iNdEx++
- wire |= (uint64(b) & 0x7F) << shift
- if b < 0x80 {
- break
- }
- }
- fieldNum := int32(wire >> 3)
- wireType := int(wire & 0x7)
- if wireType == 4 {
- return fmt.Errorf("proto: ResignRequest: wiretype end group for non-group")
- }
- if fieldNum <= 0 {
- return fmt.Errorf("proto: ResignRequest: illegal tag %d (wire type %d)", fieldNum, wire)
- }
- switch fieldNum {
- case 1:
- if wireType != 2 {
- return fmt.Errorf("proto: wrong wireType = %d for field Leader", wireType)
- }
- var msglen int
- for shift := uint(0); ; shift += 7 {
- if shift >= 64 {
- return ErrIntOverflowV3Election
- }
- if iNdEx >= l {
- return io.ErrUnexpectedEOF
- }
- b := dAtA[iNdEx]
- iNdEx++
- msglen |= (int(b) & 0x7F) << shift
- if b < 0x80 {
- break
- }
- }
- if msglen < 0 {
- return ErrInvalidLengthV3Election
- }
- postIndex := iNdEx + msglen
- if postIndex > l {
- return io.ErrUnexpectedEOF
- }
- if m.Leader == nil {
- m.Leader = &LeaderKey{}
- }
- if err := m.Leader.Unmarshal(dAtA[iNdEx:postIndex]); err != nil {
- return err
- }
- iNdEx = postIndex
- default:
- iNdEx = preIndex
- skippy, err := skipV3Election(dAtA[iNdEx:])
- if err != nil {
- return err
- }
- if skippy < 0 {
- return ErrInvalidLengthV3Election
- }
- if (iNdEx + skippy) > l {
- return io.ErrUnexpectedEOF
- }
- iNdEx += skippy
- }
- }
-
- if iNdEx > l {
- return io.ErrUnexpectedEOF
- }
- return nil
-}
-func (m *ResignResponse) Unmarshal(dAtA []byte) error {
- l := len(dAtA)
- iNdEx := 0
- for iNdEx < l {
- preIndex := iNdEx
- var wire uint64
- for shift := uint(0); ; shift += 7 {
- if shift >= 64 {
- return ErrIntOverflowV3Election
- }
- if iNdEx >= l {
- return io.ErrUnexpectedEOF
- }
- b := dAtA[iNdEx]
- iNdEx++
- wire |= (uint64(b) & 0x7F) << shift
- if b < 0x80 {
- break
- }
- }
- fieldNum := int32(wire >> 3)
- wireType := int(wire & 0x7)
- if wireType == 4 {
- return fmt.Errorf("proto: ResignResponse: wiretype end group for non-group")
- }
- if fieldNum <= 0 {
- return fmt.Errorf("proto: ResignResponse: illegal tag %d (wire type %d)", fieldNum, wire)
- }
- switch fieldNum {
- case 1:
- if wireType != 2 {
- return fmt.Errorf("proto: wrong wireType = %d for field Header", wireType)
- }
- var msglen int
- for shift := uint(0); ; shift += 7 {
- if shift >= 64 {
- return ErrIntOverflowV3Election
- }
- if iNdEx >= l {
- return io.ErrUnexpectedEOF
- }
- b := dAtA[iNdEx]
- iNdEx++
- msglen |= (int(b) & 0x7F) << shift
- if b < 0x80 {
- break
- }
- }
- if msglen < 0 {
- return ErrInvalidLengthV3Election
- }
- postIndex := iNdEx + msglen
- if postIndex > l {
- return io.ErrUnexpectedEOF
- }
- if m.Header == nil {
- m.Header = &etcdserverpb.ResponseHeader{}
- }
- if err := m.Header.Unmarshal(dAtA[iNdEx:postIndex]); err != nil {
- return err
- }
- iNdEx = postIndex
- default:
- iNdEx = preIndex
- skippy, err := skipV3Election(dAtA[iNdEx:])
- if err != nil {
- return err
- }
- if skippy < 0 {
- return ErrInvalidLengthV3Election
- }
- if (iNdEx + skippy) > l {
- return io.ErrUnexpectedEOF
- }
- iNdEx += skippy
- }
- }
-
- if iNdEx > l {
- return io.ErrUnexpectedEOF
- }
- return nil
-}
-func (m *ProclaimRequest) Unmarshal(dAtA []byte) error {
- l := len(dAtA)
- iNdEx := 0
- for iNdEx < l {
- preIndex := iNdEx
- var wire uint64
- for shift := uint(0); ; shift += 7 {
- if shift >= 64 {
- return ErrIntOverflowV3Election
- }
- if iNdEx >= l {
- return io.ErrUnexpectedEOF
- }
- b := dAtA[iNdEx]
- iNdEx++
- wire |= (uint64(b) & 0x7F) << shift
- if b < 0x80 {
- break
- }
- }
- fieldNum := int32(wire >> 3)
- wireType := int(wire & 0x7)
- if wireType == 4 {
- return fmt.Errorf("proto: ProclaimRequest: wiretype end group for non-group")
- }
- if fieldNum <= 0 {
- return fmt.Errorf("proto: ProclaimRequest: illegal tag %d (wire type %d)", fieldNum, wire)
- }
- switch fieldNum {
- case 1:
- if wireType != 2 {
- return fmt.Errorf("proto: wrong wireType = %d for field Leader", wireType)
- }
- var msglen int
- for shift := uint(0); ; shift += 7 {
- if shift >= 64 {
- return ErrIntOverflowV3Election
- }
- if iNdEx >= l {
- return io.ErrUnexpectedEOF
- }
- b := dAtA[iNdEx]
- iNdEx++
- msglen |= (int(b) & 0x7F) << shift
- if b < 0x80 {
- break
- }
- }
- if msglen < 0 {
- return ErrInvalidLengthV3Election
- }
- postIndex := iNdEx + msglen
- if postIndex > l {
- return io.ErrUnexpectedEOF
- }
- if m.Leader == nil {
- m.Leader = &LeaderKey{}
- }
- if err := m.Leader.Unmarshal(dAtA[iNdEx:postIndex]); err != nil {
- return err
- }
- iNdEx = postIndex
- case 2:
- if wireType != 2 {
- return fmt.Errorf("proto: wrong wireType = %d for field Value", wireType)
- }
- var byteLen int
- for shift := uint(0); ; shift += 7 {
- if shift >= 64 {
- return ErrIntOverflowV3Election
- }
- if iNdEx >= l {
- return io.ErrUnexpectedEOF
- }
- b := dAtA[iNdEx]
- iNdEx++
- byteLen |= (int(b) & 0x7F) << shift
- if b < 0x80 {
- break
- }
- }
- if byteLen < 0 {
- return ErrInvalidLengthV3Election
- }
- postIndex := iNdEx + byteLen
- if postIndex > l {
- return io.ErrUnexpectedEOF
- }
- m.Value = append(m.Value[:0], dAtA[iNdEx:postIndex]...)
- if m.Value == nil {
- m.Value = []byte{}
- }
- iNdEx = postIndex
- default:
- iNdEx = preIndex
- skippy, err := skipV3Election(dAtA[iNdEx:])
- if err != nil {
- return err
- }
- if skippy < 0 {
- return ErrInvalidLengthV3Election
- }
- if (iNdEx + skippy) > l {
- return io.ErrUnexpectedEOF
- }
- iNdEx += skippy
- }
- }
-
- if iNdEx > l {
- return io.ErrUnexpectedEOF
- }
- return nil
-}
-func (m *ProclaimResponse) Unmarshal(dAtA []byte) error {
- l := len(dAtA)
- iNdEx := 0
- for iNdEx < l {
- preIndex := iNdEx
- var wire uint64
- for shift := uint(0); ; shift += 7 {
- if shift >= 64 {
- return ErrIntOverflowV3Election
- }
- if iNdEx >= l {
- return io.ErrUnexpectedEOF
- }
- b := dAtA[iNdEx]
- iNdEx++
- wire |= (uint64(b) & 0x7F) << shift
- if b < 0x80 {
- break
- }
- }
- fieldNum := int32(wire >> 3)
- wireType := int(wire & 0x7)
- if wireType == 4 {
- return fmt.Errorf("proto: ProclaimResponse: wiretype end group for non-group")
- }
- if fieldNum <= 0 {
- return fmt.Errorf("proto: ProclaimResponse: illegal tag %d (wire type %d)", fieldNum, wire)
- }
- switch fieldNum {
- case 1:
- if wireType != 2 {
- return fmt.Errorf("proto: wrong wireType = %d for field Header", wireType)
- }
- var msglen int
- for shift := uint(0); ; shift += 7 {
- if shift >= 64 {
- return ErrIntOverflowV3Election
- }
- if iNdEx >= l {
- return io.ErrUnexpectedEOF
- }
- b := dAtA[iNdEx]
- iNdEx++
- msglen |= (int(b) & 0x7F) << shift
- if b < 0x80 {
- break
- }
- }
- if msglen < 0 {
- return ErrInvalidLengthV3Election
- }
- postIndex := iNdEx + msglen
- if postIndex > l {
- return io.ErrUnexpectedEOF
- }
- if m.Header == nil {
- m.Header = &etcdserverpb.ResponseHeader{}
- }
- if err := m.Header.Unmarshal(dAtA[iNdEx:postIndex]); err != nil {
- return err
- }
- iNdEx = postIndex
- default:
- iNdEx = preIndex
- skippy, err := skipV3Election(dAtA[iNdEx:])
- if err != nil {
- return err
- }
- if skippy < 0 {
- return ErrInvalidLengthV3Election
- }
- if (iNdEx + skippy) > l {
- return io.ErrUnexpectedEOF
- }
- iNdEx += skippy
- }
- }
-
- if iNdEx > l {
- return io.ErrUnexpectedEOF
- }
- return nil
-}
-func skipV3Election(dAtA []byte) (n int, err error) {
- l := len(dAtA)
- iNdEx := 0
- for iNdEx < l {
- var wire uint64
- for shift := uint(0); ; shift += 7 {
- if shift >= 64 {
- return 0, ErrIntOverflowV3Election
- }
- if iNdEx >= l {
- return 0, io.ErrUnexpectedEOF
- }
- b := dAtA[iNdEx]
- iNdEx++
- wire |= (uint64(b) & 0x7F) << shift
- if b < 0x80 {
- break
- }
- }
- wireType := int(wire & 0x7)
- switch wireType {
- case 0:
- for shift := uint(0); ; shift += 7 {
- if shift >= 64 {
- return 0, ErrIntOverflowV3Election
- }
- if iNdEx >= l {
- return 0, io.ErrUnexpectedEOF
- }
- iNdEx++
- if dAtA[iNdEx-1] < 0x80 {
- break
- }
- }
- return iNdEx, nil
- case 1:
- iNdEx += 8
- return iNdEx, nil
- case 2:
- var length int
- for shift := uint(0); ; shift += 7 {
- if shift >= 64 {
- return 0, ErrIntOverflowV3Election
- }
- if iNdEx >= l {
- return 0, io.ErrUnexpectedEOF
- }
- b := dAtA[iNdEx]
- iNdEx++
- length |= (int(b) & 0x7F) << shift
- if b < 0x80 {
- break
- }
- }
- iNdEx += length
- if length < 0 {
- return 0, ErrInvalidLengthV3Election
- }
- return iNdEx, nil
- case 3:
- for {
- var innerWire uint64
- var start int = iNdEx
- for shift := uint(0); ; shift += 7 {
- if shift >= 64 {
- return 0, ErrIntOverflowV3Election
- }
- if iNdEx >= l {
- return 0, io.ErrUnexpectedEOF
- }
- b := dAtA[iNdEx]
- iNdEx++
- innerWire |= (uint64(b) & 0x7F) << shift
- if b < 0x80 {
- break
- }
- }
- innerWireType := int(innerWire & 0x7)
- if innerWireType == 4 {
- break
- }
- next, err := skipV3Election(dAtA[start:])
- if err != nil {
- return 0, err
- }
- iNdEx = start + next
- }
- return iNdEx, nil
- case 4:
- return iNdEx, nil
- case 5:
- iNdEx += 4
- return iNdEx, nil
- default:
- return 0, fmt.Errorf("proto: illegal wireType %d", wireType)
- }
- }
- panic("unreachable")
-}
-
-var (
- ErrInvalidLengthV3Election = fmt.Errorf("proto: negative length found during unmarshaling")
- ErrIntOverflowV3Election = fmt.Errorf("proto: integer overflow")
-)
-
-func init() { proto.RegisterFile("v3election.proto", fileDescriptorV3Election) }
-
-var fileDescriptorV3Election = []byte{
- // 535 bytes of a gzipped FileDescriptorProto
- 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xa4, 0x94, 0xcf, 0x6e, 0xd3, 0x40,
- 0x10, 0xc6, 0x59, 0x27, 0x84, 0x32, 0xa4, 0xad, 0x65, 0x82, 0x48, 0x43, 0x30, 0xd1, 0x22, 0xa1,
- 0x2a, 0x07, 0x2f, 0x6a, 0x38, 0xe5, 0x84, 0x40, 0xa0, 0x4a, 0x45, 0x02, 0x7c, 0x40, 0x70, 0xdc,
- 0xb8, 0x23, 0x37, 0x8a, 0xe3, 0x35, 0xb6, 0x6b, 0x29, 0x57, 0x5e, 0x81, 0x03, 0x3c, 0x12, 0x47,
- 0x24, 0x5e, 0x00, 0x05, 0x1e, 0x04, 0xed, 0xae, 0x8d, 0xff, 0x28, 0x41, 0xa8, 0xb9, 0x58, 0xe3,
- 0x9d, 0xcf, 0xf3, 0x9b, 0x6f, 0x76, 0x12, 0x30, 0xb3, 0x09, 0x06, 0xe8, 0xa5, 0x73, 0x11, 0x3a,
- 0x51, 0x2c, 0x52, 0x61, 0x75, 0xcb, 0x93, 0x68, 0x36, 0xe8, 0xf9, 0xc2, 0x17, 0x2a, 0xc1, 0x64,
- 0xa4, 0x35, 0x83, 0x47, 0x98, 0x7a, 0xe7, 0x4c, 0x3e, 0x12, 0x8c, 0x33, 0x8c, 0x2b, 0x61, 0x34,
- 0x63, 0x71, 0xe4, 0xe5, 0xba, 0x23, 0xa5, 0x5b, 0x66, 0x9e, 0xa7, 0x1e, 0xd1, 0x8c, 0x2d, 0xb2,
- 0x3c, 0x35, 0xf4, 0x85, 0xf0, 0x03, 0x64, 0x3c, 0x9a, 0x33, 0x1e, 0x86, 0x22, 0xe5, 0x92, 0x98,
- 0xe8, 0x2c, 0x7d, 0x0b, 0x87, 0xcf, 0xf9, 0x32, 0xe2, 0x73, 0x3f, 0x74, 0xf1, 0xe3, 0x25, 0x26,
- 0xa9, 0x65, 0x41, 0x3b, 0xe4, 0x4b, 0xec, 0x93, 0x11, 0x39, 0xee, 0xba, 0x2a, 0xb6, 0x7a, 0x70,
- 0x3d, 0x40, 0x9e, 0x60, 0xdf, 0x18, 0x91, 0xe3, 0x96, 0xab, 0x5f, 0xe4, 0x69, 0xc6, 0x83, 0x4b,
- 0xec, 0xb7, 0x94, 0x54, 0xbf, 0xd0, 0x15, 0x98, 0x65, 0xc9, 0x24, 0x12, 0x61, 0x82, 0xd6, 0x13,
- 0xe8, 0x5c, 0x20, 0x3f, 0xc7, 0x58, 0x55, 0xbd, 0x75, 0x32, 0x74, 0xaa, 0x46, 0x9c, 0x42, 0x77,
- 0xaa, 0x34, 0x6e, 0xae, 0xb5, 0x18, 0x74, 0x02, 0xfd, 0x95, 0xa1, 0xbe, 0xba, 0xeb, 0x54, 0x47,
- 0xe6, 0xbc, 0x52, 0xb9, 0x33, 0x5c, 0xb9, 0xb9, 0x8c, 0x7e, 0x80, 0x9b, 0x7f, 0x0f, 0x37, 0xfa,
- 0x30, 0xa1, 0xb5, 0xc0, 0x95, 0x2a, 0xd7, 0x75, 0x65, 0x28, 0x4f, 0x62, 0xcc, 0x94, 0x83, 0x96,
- 0x2b, 0xc3, 0xd2, 0x6b, 0xbb, 0xe2, 0x95, 0x3e, 0x84, 0x7d, 0x5d, 0xfa, 0x1f, 0x63, 0xa2, 0x17,
- 0x70, 0x50, 0x88, 0x76, 0x32, 0x3e, 0x02, 0x63, 0x91, 0xe5, 0xa6, 0x4d, 0x47, 0xdf, 0xa8, 0x73,
- 0x86, 0xab, 0x77, 0x72, 0xc0, 0xae, 0xb1, 0xc8, 0xe8, 0x53, 0xd8, 0x77, 0x31, 0xa9, 0xdc, 0x5a,
- 0x39, 0x2b, 0xf2, 0x7f, 0xb3, 0x7a, 0x09, 0x07, 0x45, 0x85, 0x5d, 0x7a, 0xa5, 0xef, 0xe1, 0xf0,
- 0x4d, 0x2c, 0xbc, 0x80, 0xcf, 0x97, 0x57, 0xed, 0xa5, 0x5c, 0x24, 0xa3, 0xba, 0x48, 0xa7, 0x60,
- 0x96, 0x95, 0x77, 0xe9, 0xf1, 0xe4, 0x4b, 0x1b, 0xf6, 0x5e, 0xe4, 0x0d, 0x58, 0x0b, 0xd8, 0x2b,
- 0xf6, 0xd3, 0xba, 0x5f, 0xef, 0xac, 0xf1, 0x53, 0x18, 0xd8, 0xdb, 0xd2, 0x9a, 0x42, 0x47, 0x9f,
- 0x7e, 0xfc, 0xfe, 0x6c, 0x0c, 0xe8, 0x1d, 0x96, 0x4d, 0x58, 0x21, 0x64, 0x5e, 0x2e, 0x9b, 0x92,
- 0xb1, 0x84, 0x15, 0x1e, 0x9a, 0xb0, 0xc6, 0xd4, 0x9a, 0xb0, 0xa6, 0xf5, 0x2d, 0xb0, 0x28, 0x97,
- 0x49, 0x98, 0x07, 0x1d, 0x3d, 0x5b, 0xeb, 0xde, 0xa6, 0x89, 0x17, 0xa0, 0xe1, 0xe6, 0x64, 0x8e,
- 0xb1, 0x15, 0xa6, 0x4f, 0x6f, 0xd7, 0x30, 0xfa, 0xa2, 0x24, 0xc4, 0x87, 0x1b, 0xaf, 0x67, 0x6a,
- 0xe0, 0xbb, 0x50, 0x1e, 0x28, 0xca, 0x11, 0xed, 0xd5, 0x28, 0x42, 0x17, 0x9e, 0x92, 0xf1, 0x63,
- 0x22, 0xdd, 0xe8, 0x05, 0x6d, 0x72, 0x6a, 0x8b, 0xdf, 0xe4, 0xd4, 0x77, 0x7a, 0x8b, 0x9b, 0x58,
- 0x89, 0xa6, 0x64, 0xfc, 0xcc, 0xfc, 0xb6, 0xb6, 0xc9, 0xf7, 0xb5, 0x4d, 0x7e, 0xae, 0x6d, 0xf2,
- 0xf5, 0x97, 0x7d, 0x6d, 0xd6, 0x51, 0x7f, 0x8c, 0x93, 0x3f, 0x01, 0x00, 0x00, 0xff, 0xff, 0x2f,
- 0x1d, 0xfa, 0x11, 0xb1, 0x05, 0x00, 0x00,
-}
diff --git a/vendor/go.etcd.io/etcd/etcdserver/api/v3election/v3electionpb/v3election.proto b/vendor/go.etcd.io/etcd/etcdserver/api/v3election/v3electionpb/v3election.proto
deleted file mode 100644
index 918f39f..0000000
--- a/vendor/go.etcd.io/etcd/etcdserver/api/v3election/v3electionpb/v3election.proto
+++ /dev/null
@@ -1,119 +0,0 @@
-syntax = "proto3";
-package v3electionpb;
-
-import "gogoproto/gogo.proto";
-import "etcd/etcdserver/etcdserverpb/rpc.proto";
-import "etcd/mvcc/mvccpb/kv.proto";
-
-// for grpc-gateway
-import "google/api/annotations.proto";
-
-option (gogoproto.marshaler_all) = true;
-option (gogoproto.unmarshaler_all) = true;
-
-// The election service exposes client-side election facilities as a gRPC interface.
-service Election {
- // Campaign waits to acquire leadership in an election, returning a LeaderKey
- // representing the leadership if successful. The LeaderKey can then be used
- // to issue new values on the election, transactionally guard API requests on
- // leadership still being held, and resign from the election.
- rpc Campaign(CampaignRequest) returns (CampaignResponse) {
- option (google.api.http) = {
- post: "/v3/election/campaign"
- body: "*"
- };
- }
- // Proclaim updates the leader's posted value with a new value.
- rpc Proclaim(ProclaimRequest) returns (ProclaimResponse) {
- option (google.api.http) = {
- post: "/v3/election/proclaim"
- body: "*"
- };
- }
- // Leader returns the current election proclamation, if any.
- rpc Leader(LeaderRequest) returns (LeaderResponse) {
- option (google.api.http) = {
- post: "/v3/election/leader"
- body: "*"
- };
- }
- // Observe streams election proclamations in-order as made by the election's
- // elected leaders.
- rpc Observe(LeaderRequest) returns (stream LeaderResponse) {
- option (google.api.http) = {
- post: "/v3/election/observe"
- body: "*"
- };
- }
- // Resign releases election leadership so other campaigners may acquire
- // leadership on the election.
- rpc Resign(ResignRequest) returns (ResignResponse) {
- option (google.api.http) = {
- post: "/v3/election/resign"
- body: "*"
- };
- }
-}
-
-message CampaignRequest {
- // name is the election's identifier for the campaign.
- bytes name = 1;
- // lease is the ID of the lease attached to leadership of the election. If the
- // lease expires or is revoked before resigning leadership, then the
- // leadership is transferred to the next campaigner, if any.
- int64 lease = 2;
- // value is the initial proclaimed value set when the campaigner wins the
- // election.
- bytes value = 3;
-}
-
-message CampaignResponse {
- etcdserverpb.ResponseHeader header = 1;
- // leader describes the resources used for holding leadereship of the election.
- LeaderKey leader = 2;
-}
-
-message LeaderKey {
- // name is the election identifier that correponds to the leadership key.
- bytes name = 1;
- // key is an opaque key representing the ownership of the election. If the key
- // is deleted, then leadership is lost.
- bytes key = 2;
- // rev is the creation revision of the key. It can be used to test for ownership
- // of an election during transactions by testing the key's creation revision
- // matches rev.
- int64 rev = 3;
- // lease is the lease ID of the election leader.
- int64 lease = 4;
-}
-
-message LeaderRequest {
- // name is the election identifier for the leadership information.
- bytes name = 1;
-}
-
-message LeaderResponse {
- etcdserverpb.ResponseHeader header = 1;
- // kv is the key-value pair representing the latest leader update.
- mvccpb.KeyValue kv = 2;
-}
-
-message ResignRequest {
- // leader is the leadership to relinquish by resignation.
- LeaderKey leader = 1;
-}
-
-message ResignResponse {
- etcdserverpb.ResponseHeader header = 1;
-}
-
-message ProclaimRequest {
- // leader is the leadership hold on the election.
- LeaderKey leader = 1;
- // value is an update meant to overwrite the leader's current value.
- bytes value = 2;
-}
-
-message ProclaimResponse {
- etcdserverpb.ResponseHeader header = 1;
-}
diff --git a/vendor/go.etcd.io/etcd/etcdserver/api/v3lock/doc.go b/vendor/go.etcd.io/etcd/etcdserver/api/v3lock/doc.go
deleted file mode 100644
index e0a1008..0000000
--- a/vendor/go.etcd.io/etcd/etcdserver/api/v3lock/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 v3lock provides a v3 locking service from an etcdserver.
-package v3lock
diff --git a/vendor/go.etcd.io/etcd/etcdserver/api/v3lock/lock.go b/vendor/go.etcd.io/etcd/etcdserver/api/v3lock/lock.go
deleted file mode 100644
index 5a17c86..0000000
--- a/vendor/go.etcd.io/etcd/etcdserver/api/v3lock/lock.go
+++ /dev/null
@@ -1,56 +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 v3lock
-
-import (
- "context"
-
- "go.etcd.io/etcd/clientv3"
- "go.etcd.io/etcd/clientv3/concurrency"
- "go.etcd.io/etcd/etcdserver/api/v3lock/v3lockpb"
-)
-
-type lockServer struct {
- c *clientv3.Client
-}
-
-func NewLockServer(c *clientv3.Client) v3lockpb.LockServer {
- return &lockServer{c}
-}
-
-func (ls *lockServer) Lock(ctx context.Context, req *v3lockpb.LockRequest) (*v3lockpb.LockResponse, error) {
- s, err := concurrency.NewSession(
- ls.c,
- concurrency.WithLease(clientv3.LeaseID(req.Lease)),
- concurrency.WithContext(ctx),
- )
- if err != nil {
- return nil, err
- }
- s.Orphan()
- m := concurrency.NewMutex(s, string(req.Name))
- if err = m.Lock(ctx); err != nil {
- return nil, err
- }
- return &v3lockpb.LockResponse{Header: m.Header(), Key: []byte(m.Key())}, nil
-}
-
-func (ls *lockServer) Unlock(ctx context.Context, req *v3lockpb.UnlockRequest) (*v3lockpb.UnlockResponse, error) {
- resp, err := ls.c.Delete(ctx, string(req.Key))
- if err != nil {
- return nil, err
- }
- return &v3lockpb.UnlockResponse{Header: resp.Header}, nil
-}
diff --git a/vendor/go.etcd.io/etcd/etcdserver/api/v3lock/v3lockpb/gw/v3lock.pb.gw.go b/vendor/go.etcd.io/etcd/etcdserver/api/v3lock/v3lockpb/gw/v3lock.pb.gw.go
deleted file mode 100644
index 1eeeff1..0000000
--- a/vendor/go.etcd.io/etcd/etcdserver/api/v3lock/v3lockpb/gw/v3lock.pb.gw.go
+++ /dev/null
@@ -1,167 +0,0 @@
-// Code generated by protoc-gen-grpc-gateway. DO NOT EDIT.
-// source: etcdserver/api/v3lock/v3lockpb/v3lock.proto
-
-/*
-Package v3lockpb is a reverse proxy.
-
-It translates gRPC into RESTful JSON APIs.
-*/
-package gw
-
-import (
- "go.etcd.io/etcd/etcdserver/api/v3lock/v3lockpb"
- "io"
- "net/http"
-
- "github.com/golang/protobuf/proto"
- "github.com/grpc-ecosystem/grpc-gateway/runtime"
- "github.com/grpc-ecosystem/grpc-gateway/utilities"
- "golang.org/x/net/context"
- "google.golang.org/grpc"
- "google.golang.org/grpc/codes"
- "google.golang.org/grpc/grpclog"
- "google.golang.org/grpc/status"
-)
-
-var _ codes.Code
-var _ io.Reader
-var _ status.Status
-var _ = runtime.String
-var _ = utilities.NewDoubleArray
-
-func request_Lock_Lock_0(ctx context.Context, marshaler runtime.Marshaler, client v3lockpb.LockClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) {
- var protoReq v3lockpb.LockRequest
- var metadata runtime.ServerMetadata
-
- if err := marshaler.NewDecoder(req.Body).Decode(&protoReq); err != nil && err != io.EOF {
- return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err)
- }
-
- msg, err := client.Lock(ctx, &protoReq, grpc.Header(&metadata.HeaderMD), grpc.Trailer(&metadata.TrailerMD))
- return msg, metadata, err
-
-}
-
-func request_Lock_Unlock_0(ctx context.Context, marshaler runtime.Marshaler, client v3lockpb.LockClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) {
- var protoReq v3lockpb.UnlockRequest
- var metadata runtime.ServerMetadata
-
- if err := marshaler.NewDecoder(req.Body).Decode(&protoReq); err != nil && err != io.EOF {
- return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err)
- }
-
- msg, err := client.Unlock(ctx, &protoReq, grpc.Header(&metadata.HeaderMD), grpc.Trailer(&metadata.TrailerMD))
- return msg, metadata, err
-
-}
-
-// RegisterLockHandlerFromEndpoint is same as RegisterLockHandler but
-// automatically dials to "endpoint" and closes the connection when "ctx" gets done.
-func RegisterLockHandlerFromEndpoint(ctx context.Context, mux *runtime.ServeMux, endpoint string, opts []grpc.DialOption) (err error) {
- conn, err := grpc.Dial(endpoint, opts...)
- if err != nil {
- return err
- }
- defer func() {
- if err != nil {
- if cerr := conn.Close(); cerr != nil {
- grpclog.Printf("Failed to close conn to %s: %v", endpoint, cerr)
- }
- return
- }
- go func() {
- <-ctx.Done()
- if cerr := conn.Close(); cerr != nil {
- grpclog.Printf("Failed to close conn to %s: %v", endpoint, cerr)
- }
- }()
- }()
-
- return RegisterLockHandler(ctx, mux, conn)
-}
-
-// RegisterLockHandler registers the http handlers for service Lock to "mux".
-// The handlers forward requests to the grpc endpoint over "conn".
-func RegisterLockHandler(ctx context.Context, mux *runtime.ServeMux, conn *grpc.ClientConn) error {
- return RegisterLockHandlerClient(ctx, mux, v3lockpb.NewLockClient(conn))
-}
-
-// RegisterLockHandler registers the http handlers for service Lock to "mux".
-// The handlers forward requests to the grpc endpoint over the given implementation of "LockClient".
-// Note: the gRPC framework executes interceptors within the gRPC handler. If the passed in "LockClient"
-// doesn't go through the normal gRPC flow (creating a gRPC client etc.) then it will be up to the passed in
-// "LockClient" to call the correct interceptors.
-func RegisterLockHandlerClient(ctx context.Context, mux *runtime.ServeMux, client v3lockpb.LockClient) error {
-
- mux.Handle("POST", pattern_Lock_Lock_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) {
- ctx, cancel := context.WithCancel(req.Context())
- defer cancel()
- if cn, ok := w.(http.CloseNotifier); ok {
- go func(done <-chan struct{}, closed <-chan bool) {
- select {
- case <-done:
- case <-closed:
- cancel()
- }
- }(ctx.Done(), cn.CloseNotify())
- }
- inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req)
- rctx, err := runtime.AnnotateContext(ctx, mux, req)
- if err != nil {
- runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err)
- return
- }
- resp, md, err := request_Lock_Lock_0(rctx, inboundMarshaler, client, req, pathParams)
- ctx = runtime.NewServerMetadataContext(ctx, md)
- if err != nil {
- runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err)
- return
- }
-
- forward_Lock_Lock_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...)
-
- })
-
- mux.Handle("POST", pattern_Lock_Unlock_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) {
- ctx, cancel := context.WithCancel(req.Context())
- defer cancel()
- if cn, ok := w.(http.CloseNotifier); ok {
- go func(done <-chan struct{}, closed <-chan bool) {
- select {
- case <-done:
- case <-closed:
- cancel()
- }
- }(ctx.Done(), cn.CloseNotify())
- }
- inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req)
- rctx, err := runtime.AnnotateContext(ctx, mux, req)
- if err != nil {
- runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err)
- return
- }
- resp, md, err := request_Lock_Unlock_0(rctx, inboundMarshaler, client, req, pathParams)
- ctx = runtime.NewServerMetadataContext(ctx, md)
- if err != nil {
- runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err)
- return
- }
-
- forward_Lock_Unlock_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...)
-
- })
-
- return nil
-}
-
-var (
- pattern_Lock_Lock_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 1}, []string{"v3", "lock"}, ""))
-
- pattern_Lock_Unlock_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2}, []string{"v3", "lock", "unlock"}, ""))
-)
-
-var (
- forward_Lock_Lock_0 = runtime.ForwardResponseMessage
-
- forward_Lock_Unlock_0 = runtime.ForwardResponseMessage
-)
diff --git a/vendor/go.etcd.io/etcd/etcdserver/api/v3lock/v3lockpb/v3lock.pb.go b/vendor/go.etcd.io/etcd/etcdserver/api/v3lock/v3lockpb/v3lock.pb.go
deleted file mode 100644
index 36ebdd9..0000000
--- a/vendor/go.etcd.io/etcd/etcdserver/api/v3lock/v3lockpb/v3lock.pb.go
+++ /dev/null
@@ -1,959 +0,0 @@
-// Code generated by protoc-gen-gogo. DO NOT EDIT.
-// source: v3lock.proto
-
-/*
- Package v3lockpb is a generated protocol buffer package.
-
- It is generated from these files:
- v3lock.proto
-
- It has these top-level messages:
- LockRequest
- LockResponse
- UnlockRequest
- UnlockResponse
-*/
-package v3lockpb
-
-import (
- "fmt"
-
- proto "github.com/golang/protobuf/proto"
-
- math "math"
-
- _ "github.com/gogo/protobuf/gogoproto"
-
- etcdserverpb "go.etcd.io/etcd/etcdserver/etcdserverpb"
-
- context "golang.org/x/net/context"
-
- grpc "google.golang.org/grpc"
-
- io "io"
-)
-
-// Reference imports to suppress errors if they are not otherwise used.
-var _ = proto.Marshal
-var _ = fmt.Errorf
-var _ = math.Inf
-
-// This is a compile-time assertion to ensure that this generated file
-// is compatible with the proto package it is being compiled against.
-// A compilation error at this line likely means your copy of the
-// proto package needs to be updated.
-const _ = proto.ProtoPackageIsVersion2 // please upgrade the proto package
-
-type LockRequest struct {
- // name is the identifier for the distributed shared lock to be acquired.
- Name []byte `protobuf:"bytes,1,opt,name=name,proto3" json:"name,omitempty"`
- // lease is the ID of the lease that will be attached to ownership of the
- // lock. If the lease expires or is revoked and currently holds the lock,
- // the lock is automatically released. Calls to Lock with the same lease will
- // be treated as a single acquisition; locking twice with the same lease is a
- // no-op.
- Lease int64 `protobuf:"varint,2,opt,name=lease,proto3" json:"lease,omitempty"`
-}
-
-func (m *LockRequest) Reset() { *m = LockRequest{} }
-func (m *LockRequest) String() string { return proto.CompactTextString(m) }
-func (*LockRequest) ProtoMessage() {}
-func (*LockRequest) Descriptor() ([]byte, []int) { return fileDescriptorV3Lock, []int{0} }
-
-func (m *LockRequest) GetName() []byte {
- if m != nil {
- return m.Name
- }
- return nil
-}
-
-func (m *LockRequest) GetLease() int64 {
- if m != nil {
- return m.Lease
- }
- return 0
-}
-
-type LockResponse struct {
- Header *etcdserverpb.ResponseHeader `protobuf:"bytes,1,opt,name=header" json:"header,omitempty"`
- // key is a key that will exist on etcd for the duration that the Lock caller
- // owns the lock. Users should not modify this key or the lock may exhibit
- // undefined behavior.
- Key []byte `protobuf:"bytes,2,opt,name=key,proto3" json:"key,omitempty"`
-}
-
-func (m *LockResponse) Reset() { *m = LockResponse{} }
-func (m *LockResponse) String() string { return proto.CompactTextString(m) }
-func (*LockResponse) ProtoMessage() {}
-func (*LockResponse) Descriptor() ([]byte, []int) { return fileDescriptorV3Lock, []int{1} }
-
-func (m *LockResponse) GetHeader() *etcdserverpb.ResponseHeader {
- if m != nil {
- return m.Header
- }
- return nil
-}
-
-func (m *LockResponse) GetKey() []byte {
- if m != nil {
- return m.Key
- }
- return nil
-}
-
-type UnlockRequest struct {
- // key is the lock ownership key granted by Lock.
- Key []byte `protobuf:"bytes,1,opt,name=key,proto3" json:"key,omitempty"`
-}
-
-func (m *UnlockRequest) Reset() { *m = UnlockRequest{} }
-func (m *UnlockRequest) String() string { return proto.CompactTextString(m) }
-func (*UnlockRequest) ProtoMessage() {}
-func (*UnlockRequest) Descriptor() ([]byte, []int) { return fileDescriptorV3Lock, []int{2} }
-
-func (m *UnlockRequest) GetKey() []byte {
- if m != nil {
- return m.Key
- }
- return nil
-}
-
-type UnlockResponse struct {
- Header *etcdserverpb.ResponseHeader `protobuf:"bytes,1,opt,name=header" json:"header,omitempty"`
-}
-
-func (m *UnlockResponse) Reset() { *m = UnlockResponse{} }
-func (m *UnlockResponse) String() string { return proto.CompactTextString(m) }
-func (*UnlockResponse) ProtoMessage() {}
-func (*UnlockResponse) Descriptor() ([]byte, []int) { return fileDescriptorV3Lock, []int{3} }
-
-func (m *UnlockResponse) GetHeader() *etcdserverpb.ResponseHeader {
- if m != nil {
- return m.Header
- }
- return nil
-}
-
-func init() {
- proto.RegisterType((*LockRequest)(nil), "v3lockpb.LockRequest")
- proto.RegisterType((*LockResponse)(nil), "v3lockpb.LockResponse")
- proto.RegisterType((*UnlockRequest)(nil), "v3lockpb.UnlockRequest")
- proto.RegisterType((*UnlockResponse)(nil), "v3lockpb.UnlockResponse")
-}
-
-// Reference imports to suppress errors if they are not otherwise used.
-var _ context.Context
-var _ grpc.ClientConn
-
-// This is a compile-time assertion to ensure that this generated file
-// is compatible with the grpc package it is being compiled against.
-const _ = grpc.SupportPackageIsVersion4
-
-// Client API for Lock service
-
-type LockClient interface {
- // Lock acquires a distributed shared lock on a given named lock.
- // On success, it will return a unique key that exists so long as the
- // lock is held by the caller. This key can be used in conjunction with
- // transactions to safely ensure updates to etcd only occur while holding
- // lock ownership. The lock is held until Unlock is called on the key or the
- // lease associate with the owner expires.
- Lock(ctx context.Context, in *LockRequest, opts ...grpc.CallOption) (*LockResponse, error)
- // Unlock takes a key returned by Lock and releases the hold on lock. The
- // next Lock caller waiting for the lock will then be woken up and given
- // ownership of the lock.
- Unlock(ctx context.Context, in *UnlockRequest, opts ...grpc.CallOption) (*UnlockResponse, error)
-}
-
-type lockClient struct {
- cc *grpc.ClientConn
-}
-
-func NewLockClient(cc *grpc.ClientConn) LockClient {
- return &lockClient{cc}
-}
-
-func (c *lockClient) Lock(ctx context.Context, in *LockRequest, opts ...grpc.CallOption) (*LockResponse, error) {
- out := new(LockResponse)
- err := grpc.Invoke(ctx, "/v3lockpb.Lock/Lock", in, out, c.cc, opts...)
- if err != nil {
- return nil, err
- }
- return out, nil
-}
-
-func (c *lockClient) Unlock(ctx context.Context, in *UnlockRequest, opts ...grpc.CallOption) (*UnlockResponse, error) {
- out := new(UnlockResponse)
- err := grpc.Invoke(ctx, "/v3lockpb.Lock/Unlock", in, out, c.cc, opts...)
- if err != nil {
- return nil, err
- }
- return out, nil
-}
-
-// Server API for Lock service
-
-type LockServer interface {
- // Lock acquires a distributed shared lock on a given named lock.
- // On success, it will return a unique key that exists so long as the
- // lock is held by the caller. This key can be used in conjunction with
- // transactions to safely ensure updates to etcd only occur while holding
- // lock ownership. The lock is held until Unlock is called on the key or the
- // lease associate with the owner expires.
- Lock(context.Context, *LockRequest) (*LockResponse, error)
- // Unlock takes a key returned by Lock and releases the hold on lock. The
- // next Lock caller waiting for the lock will then be woken up and given
- // ownership of the lock.
- Unlock(context.Context, *UnlockRequest) (*UnlockResponse, error)
-}
-
-func RegisterLockServer(s *grpc.Server, srv LockServer) {
- s.RegisterService(&_Lock_serviceDesc, srv)
-}
-
-func _Lock_Lock_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
- in := new(LockRequest)
- if err := dec(in); err != nil {
- return nil, err
- }
- if interceptor == nil {
- return srv.(LockServer).Lock(ctx, in)
- }
- info := &grpc.UnaryServerInfo{
- Server: srv,
- FullMethod: "/v3lockpb.Lock/Lock",
- }
- handler := func(ctx context.Context, req interface{}) (interface{}, error) {
- return srv.(LockServer).Lock(ctx, req.(*LockRequest))
- }
- return interceptor(ctx, in, info, handler)
-}
-
-func _Lock_Unlock_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
- in := new(UnlockRequest)
- if err := dec(in); err != nil {
- return nil, err
- }
- if interceptor == nil {
- return srv.(LockServer).Unlock(ctx, in)
- }
- info := &grpc.UnaryServerInfo{
- Server: srv,
- FullMethod: "/v3lockpb.Lock/Unlock",
- }
- handler := func(ctx context.Context, req interface{}) (interface{}, error) {
- return srv.(LockServer).Unlock(ctx, req.(*UnlockRequest))
- }
- return interceptor(ctx, in, info, handler)
-}
-
-var _Lock_serviceDesc = grpc.ServiceDesc{
- ServiceName: "v3lockpb.Lock",
- HandlerType: (*LockServer)(nil),
- Methods: []grpc.MethodDesc{
- {
- MethodName: "Lock",
- Handler: _Lock_Lock_Handler,
- },
- {
- MethodName: "Unlock",
- Handler: _Lock_Unlock_Handler,
- },
- },
- Streams: []grpc.StreamDesc{},
- Metadata: "v3lock.proto",
-}
-
-func (m *LockRequest) Marshal() (dAtA []byte, err error) {
- size := m.Size()
- dAtA = make([]byte, size)
- n, err := m.MarshalTo(dAtA)
- if err != nil {
- return nil, err
- }
- return dAtA[:n], nil
-}
-
-func (m *LockRequest) MarshalTo(dAtA []byte) (int, error) {
- var i int
- _ = i
- var l int
- _ = l
- if len(m.Name) > 0 {
- dAtA[i] = 0xa
- i++
- i = encodeVarintV3Lock(dAtA, i, uint64(len(m.Name)))
- i += copy(dAtA[i:], m.Name)
- }
- if m.Lease != 0 {
- dAtA[i] = 0x10
- i++
- i = encodeVarintV3Lock(dAtA, i, uint64(m.Lease))
- }
- return i, nil
-}
-
-func (m *LockResponse) Marshal() (dAtA []byte, err error) {
- size := m.Size()
- dAtA = make([]byte, size)
- n, err := m.MarshalTo(dAtA)
- if err != nil {
- return nil, err
- }
- return dAtA[:n], nil
-}
-
-func (m *LockResponse) MarshalTo(dAtA []byte) (int, error) {
- var i int
- _ = i
- var l int
- _ = l
- if m.Header != nil {
- dAtA[i] = 0xa
- i++
- i = encodeVarintV3Lock(dAtA, i, uint64(m.Header.Size()))
- n1, err := m.Header.MarshalTo(dAtA[i:])
- if err != nil {
- return 0, err
- }
- i += n1
- }
- if len(m.Key) > 0 {
- dAtA[i] = 0x12
- i++
- i = encodeVarintV3Lock(dAtA, i, uint64(len(m.Key)))
- i += copy(dAtA[i:], m.Key)
- }
- return i, nil
-}
-
-func (m *UnlockRequest) Marshal() (dAtA []byte, err error) {
- size := m.Size()
- dAtA = make([]byte, size)
- n, err := m.MarshalTo(dAtA)
- if err != nil {
- return nil, err
- }
- return dAtA[:n], nil
-}
-
-func (m *UnlockRequest) MarshalTo(dAtA []byte) (int, error) {
- var i int
- _ = i
- var l int
- _ = l
- if len(m.Key) > 0 {
- dAtA[i] = 0xa
- i++
- i = encodeVarintV3Lock(dAtA, i, uint64(len(m.Key)))
- i += copy(dAtA[i:], m.Key)
- }
- return i, nil
-}
-
-func (m *UnlockResponse) Marshal() (dAtA []byte, err error) {
- size := m.Size()
- dAtA = make([]byte, size)
- n, err := m.MarshalTo(dAtA)
- if err != nil {
- return nil, err
- }
- return dAtA[:n], nil
-}
-
-func (m *UnlockResponse) MarshalTo(dAtA []byte) (int, error) {
- var i int
- _ = i
- var l int
- _ = l
- if m.Header != nil {
- dAtA[i] = 0xa
- i++
- i = encodeVarintV3Lock(dAtA, i, uint64(m.Header.Size()))
- n2, err := m.Header.MarshalTo(dAtA[i:])
- if err != nil {
- return 0, err
- }
- i += n2
- }
- return i, nil
-}
-
-func encodeVarintV3Lock(dAtA []byte, offset int, v uint64) int {
- for v >= 1<<7 {
- dAtA[offset] = uint8(v&0x7f | 0x80)
- v >>= 7
- offset++
- }
- dAtA[offset] = uint8(v)
- return offset + 1
-}
-func (m *LockRequest) Size() (n int) {
- var l int
- _ = l
- l = len(m.Name)
- if l > 0 {
- n += 1 + l + sovV3Lock(uint64(l))
- }
- if m.Lease != 0 {
- n += 1 + sovV3Lock(uint64(m.Lease))
- }
- return n
-}
-
-func (m *LockResponse) Size() (n int) {
- var l int
- _ = l
- if m.Header != nil {
- l = m.Header.Size()
- n += 1 + l + sovV3Lock(uint64(l))
- }
- l = len(m.Key)
- if l > 0 {
- n += 1 + l + sovV3Lock(uint64(l))
- }
- return n
-}
-
-func (m *UnlockRequest) Size() (n int) {
- var l int
- _ = l
- l = len(m.Key)
- if l > 0 {
- n += 1 + l + sovV3Lock(uint64(l))
- }
- return n
-}
-
-func (m *UnlockResponse) Size() (n int) {
- var l int
- _ = l
- if m.Header != nil {
- l = m.Header.Size()
- n += 1 + l + sovV3Lock(uint64(l))
- }
- return n
-}
-
-func sovV3Lock(x uint64) (n int) {
- for {
- n++
- x >>= 7
- if x == 0 {
- break
- }
- }
- return n
-}
-func sozV3Lock(x uint64) (n int) {
- return sovV3Lock(uint64((x << 1) ^ uint64((int64(x) >> 63))))
-}
-func (m *LockRequest) Unmarshal(dAtA []byte) error {
- l := len(dAtA)
- iNdEx := 0
- for iNdEx < l {
- preIndex := iNdEx
- var wire uint64
- for shift := uint(0); ; shift += 7 {
- if shift >= 64 {
- return ErrIntOverflowV3Lock
- }
- if iNdEx >= l {
- return io.ErrUnexpectedEOF
- }
- b := dAtA[iNdEx]
- iNdEx++
- wire |= (uint64(b) & 0x7F) << shift
- if b < 0x80 {
- break
- }
- }
- fieldNum := int32(wire >> 3)
- wireType := int(wire & 0x7)
- if wireType == 4 {
- return fmt.Errorf("proto: LockRequest: wiretype end group for non-group")
- }
- if fieldNum <= 0 {
- return fmt.Errorf("proto: LockRequest: illegal tag %d (wire type %d)", fieldNum, wire)
- }
- switch fieldNum {
- case 1:
- if wireType != 2 {
- return fmt.Errorf("proto: wrong wireType = %d for field Name", wireType)
- }
- var byteLen int
- for shift := uint(0); ; shift += 7 {
- if shift >= 64 {
- return ErrIntOverflowV3Lock
- }
- if iNdEx >= l {
- return io.ErrUnexpectedEOF
- }
- b := dAtA[iNdEx]
- iNdEx++
- byteLen |= (int(b) & 0x7F) << shift
- if b < 0x80 {
- break
- }
- }
- if byteLen < 0 {
- return ErrInvalidLengthV3Lock
- }
- postIndex := iNdEx + byteLen
- if postIndex > l {
- return io.ErrUnexpectedEOF
- }
- m.Name = append(m.Name[:0], dAtA[iNdEx:postIndex]...)
- if m.Name == nil {
- m.Name = []byte{}
- }
- iNdEx = postIndex
- case 2:
- if wireType != 0 {
- return fmt.Errorf("proto: wrong wireType = %d for field Lease", wireType)
- }
- m.Lease = 0
- for shift := uint(0); ; shift += 7 {
- if shift >= 64 {
- return ErrIntOverflowV3Lock
- }
- if iNdEx >= l {
- return io.ErrUnexpectedEOF
- }
- b := dAtA[iNdEx]
- iNdEx++
- m.Lease |= (int64(b) & 0x7F) << shift
- if b < 0x80 {
- break
- }
- }
- default:
- iNdEx = preIndex
- skippy, err := skipV3Lock(dAtA[iNdEx:])
- if err != nil {
- return err
- }
- if skippy < 0 {
- return ErrInvalidLengthV3Lock
- }
- if (iNdEx + skippy) > l {
- return io.ErrUnexpectedEOF
- }
- iNdEx += skippy
- }
- }
-
- if iNdEx > l {
- return io.ErrUnexpectedEOF
- }
- return nil
-}
-func (m *LockResponse) Unmarshal(dAtA []byte) error {
- l := len(dAtA)
- iNdEx := 0
- for iNdEx < l {
- preIndex := iNdEx
- var wire uint64
- for shift := uint(0); ; shift += 7 {
- if shift >= 64 {
- return ErrIntOverflowV3Lock
- }
- if iNdEx >= l {
- return io.ErrUnexpectedEOF
- }
- b := dAtA[iNdEx]
- iNdEx++
- wire |= (uint64(b) & 0x7F) << shift
- if b < 0x80 {
- break
- }
- }
- fieldNum := int32(wire >> 3)
- wireType := int(wire & 0x7)
- if wireType == 4 {
- return fmt.Errorf("proto: LockResponse: wiretype end group for non-group")
- }
- if fieldNum <= 0 {
- return fmt.Errorf("proto: LockResponse: illegal tag %d (wire type %d)", fieldNum, wire)
- }
- switch fieldNum {
- case 1:
- if wireType != 2 {
- return fmt.Errorf("proto: wrong wireType = %d for field Header", wireType)
- }
- var msglen int
- for shift := uint(0); ; shift += 7 {
- if shift >= 64 {
- return ErrIntOverflowV3Lock
- }
- if iNdEx >= l {
- return io.ErrUnexpectedEOF
- }
- b := dAtA[iNdEx]
- iNdEx++
- msglen |= (int(b) & 0x7F) << shift
- if b < 0x80 {
- break
- }
- }
- if msglen < 0 {
- return ErrInvalidLengthV3Lock
- }
- postIndex := iNdEx + msglen
- if postIndex > l {
- return io.ErrUnexpectedEOF
- }
- if m.Header == nil {
- m.Header = &etcdserverpb.ResponseHeader{}
- }
- if err := m.Header.Unmarshal(dAtA[iNdEx:postIndex]); err != nil {
- return err
- }
- iNdEx = postIndex
- case 2:
- if wireType != 2 {
- return fmt.Errorf("proto: wrong wireType = %d for field Key", wireType)
- }
- var byteLen int
- for shift := uint(0); ; shift += 7 {
- if shift >= 64 {
- return ErrIntOverflowV3Lock
- }
- if iNdEx >= l {
- return io.ErrUnexpectedEOF
- }
- b := dAtA[iNdEx]
- iNdEx++
- byteLen |= (int(b) & 0x7F) << shift
- if b < 0x80 {
- break
- }
- }
- if byteLen < 0 {
- return ErrInvalidLengthV3Lock
- }
- postIndex := iNdEx + byteLen
- if postIndex > l {
- return io.ErrUnexpectedEOF
- }
- m.Key = append(m.Key[:0], dAtA[iNdEx:postIndex]...)
- if m.Key == nil {
- m.Key = []byte{}
- }
- iNdEx = postIndex
- default:
- iNdEx = preIndex
- skippy, err := skipV3Lock(dAtA[iNdEx:])
- if err != nil {
- return err
- }
- if skippy < 0 {
- return ErrInvalidLengthV3Lock
- }
- if (iNdEx + skippy) > l {
- return io.ErrUnexpectedEOF
- }
- iNdEx += skippy
- }
- }
-
- if iNdEx > l {
- return io.ErrUnexpectedEOF
- }
- return nil
-}
-func (m *UnlockRequest) Unmarshal(dAtA []byte) error {
- l := len(dAtA)
- iNdEx := 0
- for iNdEx < l {
- preIndex := iNdEx
- var wire uint64
- for shift := uint(0); ; shift += 7 {
- if shift >= 64 {
- return ErrIntOverflowV3Lock
- }
- if iNdEx >= l {
- return io.ErrUnexpectedEOF
- }
- b := dAtA[iNdEx]
- iNdEx++
- wire |= (uint64(b) & 0x7F) << shift
- if b < 0x80 {
- break
- }
- }
- fieldNum := int32(wire >> 3)
- wireType := int(wire & 0x7)
- if wireType == 4 {
- return fmt.Errorf("proto: UnlockRequest: wiretype end group for non-group")
- }
- if fieldNum <= 0 {
- return fmt.Errorf("proto: UnlockRequest: illegal tag %d (wire type %d)", fieldNum, wire)
- }
- switch fieldNum {
- case 1:
- if wireType != 2 {
- return fmt.Errorf("proto: wrong wireType = %d for field Key", wireType)
- }
- var byteLen int
- for shift := uint(0); ; shift += 7 {
- if shift >= 64 {
- return ErrIntOverflowV3Lock
- }
- if iNdEx >= l {
- return io.ErrUnexpectedEOF
- }
- b := dAtA[iNdEx]
- iNdEx++
- byteLen |= (int(b) & 0x7F) << shift
- if b < 0x80 {
- break
- }
- }
- if byteLen < 0 {
- return ErrInvalidLengthV3Lock
- }
- postIndex := iNdEx + byteLen
- if postIndex > l {
- return io.ErrUnexpectedEOF
- }
- m.Key = append(m.Key[:0], dAtA[iNdEx:postIndex]...)
- if m.Key == nil {
- m.Key = []byte{}
- }
- iNdEx = postIndex
- default:
- iNdEx = preIndex
- skippy, err := skipV3Lock(dAtA[iNdEx:])
- if err != nil {
- return err
- }
- if skippy < 0 {
- return ErrInvalidLengthV3Lock
- }
- if (iNdEx + skippy) > l {
- return io.ErrUnexpectedEOF
- }
- iNdEx += skippy
- }
- }
-
- if iNdEx > l {
- return io.ErrUnexpectedEOF
- }
- return nil
-}
-func (m *UnlockResponse) Unmarshal(dAtA []byte) error {
- l := len(dAtA)
- iNdEx := 0
- for iNdEx < l {
- preIndex := iNdEx
- var wire uint64
- for shift := uint(0); ; shift += 7 {
- if shift >= 64 {
- return ErrIntOverflowV3Lock
- }
- if iNdEx >= l {
- return io.ErrUnexpectedEOF
- }
- b := dAtA[iNdEx]
- iNdEx++
- wire |= (uint64(b) & 0x7F) << shift
- if b < 0x80 {
- break
- }
- }
- fieldNum := int32(wire >> 3)
- wireType := int(wire & 0x7)
- if wireType == 4 {
- return fmt.Errorf("proto: UnlockResponse: wiretype end group for non-group")
- }
- if fieldNum <= 0 {
- return fmt.Errorf("proto: UnlockResponse: illegal tag %d (wire type %d)", fieldNum, wire)
- }
- switch fieldNum {
- case 1:
- if wireType != 2 {
- return fmt.Errorf("proto: wrong wireType = %d for field Header", wireType)
- }
- var msglen int
- for shift := uint(0); ; shift += 7 {
- if shift >= 64 {
- return ErrIntOverflowV3Lock
- }
- if iNdEx >= l {
- return io.ErrUnexpectedEOF
- }
- b := dAtA[iNdEx]
- iNdEx++
- msglen |= (int(b) & 0x7F) << shift
- if b < 0x80 {
- break
- }
- }
- if msglen < 0 {
- return ErrInvalidLengthV3Lock
- }
- postIndex := iNdEx + msglen
- if postIndex > l {
- return io.ErrUnexpectedEOF
- }
- if m.Header == nil {
- m.Header = &etcdserverpb.ResponseHeader{}
- }
- if err := m.Header.Unmarshal(dAtA[iNdEx:postIndex]); err != nil {
- return err
- }
- iNdEx = postIndex
- default:
- iNdEx = preIndex
- skippy, err := skipV3Lock(dAtA[iNdEx:])
- if err != nil {
- return err
- }
- if skippy < 0 {
- return ErrInvalidLengthV3Lock
- }
- if (iNdEx + skippy) > l {
- return io.ErrUnexpectedEOF
- }
- iNdEx += skippy
- }
- }
-
- if iNdEx > l {
- return io.ErrUnexpectedEOF
- }
- return nil
-}
-func skipV3Lock(dAtA []byte) (n int, err error) {
- l := len(dAtA)
- iNdEx := 0
- for iNdEx < l {
- var wire uint64
- for shift := uint(0); ; shift += 7 {
- if shift >= 64 {
- return 0, ErrIntOverflowV3Lock
- }
- if iNdEx >= l {
- return 0, io.ErrUnexpectedEOF
- }
- b := dAtA[iNdEx]
- iNdEx++
- wire |= (uint64(b) & 0x7F) << shift
- if b < 0x80 {
- break
- }
- }
- wireType := int(wire & 0x7)
- switch wireType {
- case 0:
- for shift := uint(0); ; shift += 7 {
- if shift >= 64 {
- return 0, ErrIntOverflowV3Lock
- }
- if iNdEx >= l {
- return 0, io.ErrUnexpectedEOF
- }
- iNdEx++
- if dAtA[iNdEx-1] < 0x80 {
- break
- }
- }
- return iNdEx, nil
- case 1:
- iNdEx += 8
- return iNdEx, nil
- case 2:
- var length int
- for shift := uint(0); ; shift += 7 {
- if shift >= 64 {
- return 0, ErrIntOverflowV3Lock
- }
- if iNdEx >= l {
- return 0, io.ErrUnexpectedEOF
- }
- b := dAtA[iNdEx]
- iNdEx++
- length |= (int(b) & 0x7F) << shift
- if b < 0x80 {
- break
- }
- }
- iNdEx += length
- if length < 0 {
- return 0, ErrInvalidLengthV3Lock
- }
- return iNdEx, nil
- case 3:
- for {
- var innerWire uint64
- var start int = iNdEx
- for shift := uint(0); ; shift += 7 {
- if shift >= 64 {
- return 0, ErrIntOverflowV3Lock
- }
- if iNdEx >= l {
- return 0, io.ErrUnexpectedEOF
- }
- b := dAtA[iNdEx]
- iNdEx++
- innerWire |= (uint64(b) & 0x7F) << shift
- if b < 0x80 {
- break
- }
- }
- innerWireType := int(innerWire & 0x7)
- if innerWireType == 4 {
- break
- }
- next, err := skipV3Lock(dAtA[start:])
- if err != nil {
- return 0, err
- }
- iNdEx = start + next
- }
- return iNdEx, nil
- case 4:
- return iNdEx, nil
- case 5:
- iNdEx += 4
- return iNdEx, nil
- default:
- return 0, fmt.Errorf("proto: illegal wireType %d", wireType)
- }
- }
- panic("unreachable")
-}
-
-var (
- ErrInvalidLengthV3Lock = fmt.Errorf("proto: negative length found during unmarshaling")
- ErrIntOverflowV3Lock = fmt.Errorf("proto: integer overflow")
-)
-
-func init() { proto.RegisterFile("v3lock.proto", fileDescriptorV3Lock) }
-
-var fileDescriptorV3Lock = []byte{
- // 331 bytes of a gzipped FileDescriptorProto
- 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xe2, 0xe2, 0x29, 0x33, 0xce, 0xc9,
- 0x4f, 0xce, 0xd6, 0x2b, 0x28, 0xca, 0x2f, 0xc9, 0x17, 0xe2, 0x80, 0xf0, 0x0a, 0x92, 0xa4, 0x44,
- 0xd2, 0xf3, 0xd3, 0xf3, 0xc1, 0x82, 0xfa, 0x20, 0x16, 0x44, 0x5e, 0x4a, 0x2d, 0xb5, 0x24, 0x39,
- 0x45, 0x1f, 0x44, 0x14, 0xa7, 0x16, 0x95, 0xa5, 0x16, 0x21, 0x31, 0x0b, 0x92, 0xf4, 0x8b, 0x0a,
- 0x92, 0xa1, 0xea, 0x64, 0xd2, 0xf3, 0xf3, 0xd3, 0x73, 0x52, 0xf5, 0x13, 0x0b, 0x32, 0xf5, 0x13,
- 0xf3, 0xf2, 0xf2, 0x4b, 0x12, 0x4b, 0x32, 0xf3, 0xf3, 0x8a, 0x21, 0xb2, 0x4a, 0xe6, 0x5c, 0xdc,
- 0x3e, 0xf9, 0xc9, 0xd9, 0x41, 0xa9, 0x85, 0xa5, 0xa9, 0xc5, 0x25, 0x42, 0x42, 0x5c, 0x2c, 0x79,
- 0x89, 0xb9, 0xa9, 0x12, 0x8c, 0x0a, 0x8c, 0x1a, 0x3c, 0x41, 0x60, 0xb6, 0x90, 0x08, 0x17, 0x6b,
- 0x4e, 0x6a, 0x62, 0x71, 0xaa, 0x04, 0x93, 0x02, 0xa3, 0x06, 0x73, 0x10, 0x84, 0xa3, 0x14, 0xc6,
- 0xc5, 0x03, 0xd1, 0x58, 0x5c, 0x90, 0x9f, 0x57, 0x9c, 0x2a, 0x64, 0xc2, 0xc5, 0x96, 0x91, 0x9a,
- 0x98, 0x92, 0x5a, 0x04, 0xd6, 0xcb, 0x6d, 0x24, 0xa3, 0x87, 0xec, 0x1e, 0x3d, 0x98, 0x3a, 0x0f,
- 0xb0, 0x9a, 0x20, 0xa8, 0x5a, 0x21, 0x01, 0x2e, 0xe6, 0xec, 0xd4, 0x4a, 0xb0, 0xc9, 0x3c, 0x41,
- 0x20, 0xa6, 0x92, 0x22, 0x17, 0x6f, 0x68, 0x5e, 0x0e, 0x92, 0x93, 0xa0, 0x4a, 0x18, 0x11, 0x4a,
- 0xdc, 0xb8, 0xf8, 0x60, 0x4a, 0x28, 0xb1, 0xdc, 0x68, 0x03, 0x23, 0x17, 0x0b, 0xc8, 0x0f, 0x42,
- 0xfe, 0x50, 0x5a, 0x54, 0x0f, 0x16, 0xe6, 0x7a, 0x48, 0x81, 0x22, 0x25, 0x86, 0x2e, 0x0c, 0x31,
- 0x4d, 0x49, 0xa2, 0xe9, 0xf2, 0x93, 0xc9, 0x4c, 0x42, 0x4a, 0xbc, 0xfa, 0x65, 0xc6, 0xfa, 0x20,
- 0x05, 0x60, 0xc2, 0x8a, 0x51, 0x4b, 0x28, 0x9c, 0x8b, 0x0d, 0xe2, 0x42, 0x21, 0x71, 0x84, 0x5e,
- 0x14, 0x6f, 0x49, 0x49, 0x60, 0x4a, 0x40, 0x8d, 0x95, 0x02, 0x1b, 0x2b, 0xa2, 0xc4, 0x0f, 0x37,
- 0xb6, 0x34, 0x0f, 0x6a, 0xb0, 0x93, 0xc0, 0x89, 0x47, 0x72, 0x8c, 0x17, 0x1e, 0xc9, 0x31, 0x3e,
- 0x78, 0x24, 0xc7, 0x38, 0xe3, 0xb1, 0x1c, 0x43, 0x12, 0x1b, 0x38, 0x1e, 0x8d, 0x01, 0x01, 0x00,
- 0x00, 0xff, 0xff, 0x65, 0xa8, 0x61, 0xb1, 0x3d, 0x02, 0x00, 0x00,
-}
diff --git a/vendor/go.etcd.io/etcd/etcdserver/api/v3lock/v3lockpb/v3lock.proto b/vendor/go.etcd.io/etcd/etcdserver/api/v3lock/v3lockpb/v3lock.proto
deleted file mode 100644
index 7220c7f..0000000
--- a/vendor/go.etcd.io/etcd/etcdserver/api/v3lock/v3lockpb/v3lock.proto
+++ /dev/null
@@ -1,65 +0,0 @@
-syntax = "proto3";
-package v3lockpb;
-
-import "gogoproto/gogo.proto";
-import "etcd/etcdserver/etcdserverpb/rpc.proto";
-
-// for grpc-gateway
-import "google/api/annotations.proto";
-
-option (gogoproto.marshaler_all) = true;
-option (gogoproto.unmarshaler_all) = true;
-
-// The lock service exposes client-side locking facilities as a gRPC interface.
-service Lock {
- // Lock acquires a distributed shared lock on a given named lock.
- // On success, it will return a unique key that exists so long as the
- // lock is held by the caller. This key can be used in conjunction with
- // transactions to safely ensure updates to etcd only occur while holding
- // lock ownership. The lock is held until Unlock is called on the key or the
- // lease associate with the owner expires.
- rpc Lock(LockRequest) returns (LockResponse) {
- option (google.api.http) = {
- post: "/v3/lock/lock"
- body: "*"
- };
- }
-
- // Unlock takes a key returned by Lock and releases the hold on lock. The
- // next Lock caller waiting for the lock will then be woken up and given
- // ownership of the lock.
- rpc Unlock(UnlockRequest) returns (UnlockResponse) {
- option (google.api.http) = {
- post: "/v3/lock/unlock"
- body: "*"
- };
- }
-}
-
-message LockRequest {
- // name is the identifier for the distributed shared lock to be acquired.
- bytes name = 1;
- // lease is the ID of the lease that will be attached to ownership of the
- // lock. If the lease expires or is revoked and currently holds the lock,
- // the lock is automatically released. Calls to Lock with the same lease will
- // be treated as a single acquisition; locking twice with the same lease is a
- // no-op.
- int64 lease = 2;
-}
-
-message LockResponse {
- etcdserverpb.ResponseHeader header = 1;
- // key is a key that will exist on etcd for the duration that the Lock caller
- // owns the lock. Users should not modify this key or the lock may exhibit
- // undefined behavior.
- bytes key = 2;
-}
-
-message UnlockRequest {
- // key is the lock ownership key granted by Lock.
- bytes key = 1;
-}
-
-message UnlockResponse {
- etcdserverpb.ResponseHeader header = 1;
-}
diff --git a/vendor/go.etcd.io/etcd/etcdserver/api/v3rpc/auth.go b/vendor/go.etcd.io/etcd/etcdserver/api/v3rpc/auth.go
deleted file mode 100644
index 62ce757..0000000
--- a/vendor/go.etcd.io/etcd/etcdserver/api/v3rpc/auth.go
+++ /dev/null
@@ -1,158 +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 v3rpc
-
-import (
- "context"
-
- "go.etcd.io/etcd/etcdserver"
- pb "go.etcd.io/etcd/etcdserver/etcdserverpb"
-)
-
-type AuthServer struct {
- authenticator etcdserver.Authenticator
-}
-
-func NewAuthServer(s *etcdserver.EtcdServer) *AuthServer {
- return &AuthServer{authenticator: s}
-}
-
-func (as *AuthServer) AuthEnable(ctx context.Context, r *pb.AuthEnableRequest) (*pb.AuthEnableResponse, error) {
- resp, err := as.authenticator.AuthEnable(ctx, r)
- if err != nil {
- return nil, togRPCError(err)
- }
- return resp, nil
-}
-
-func (as *AuthServer) AuthDisable(ctx context.Context, r *pb.AuthDisableRequest) (*pb.AuthDisableResponse, error) {
- resp, err := as.authenticator.AuthDisable(ctx, r)
- if err != nil {
- return nil, togRPCError(err)
- }
- return resp, nil
-}
-
-func (as *AuthServer) Authenticate(ctx context.Context, r *pb.AuthenticateRequest) (*pb.AuthenticateResponse, error) {
- resp, err := as.authenticator.Authenticate(ctx, r)
- if err != nil {
- return nil, togRPCError(err)
- }
- return resp, nil
-}
-
-func (as *AuthServer) RoleAdd(ctx context.Context, r *pb.AuthRoleAddRequest) (*pb.AuthRoleAddResponse, error) {
- resp, err := as.authenticator.RoleAdd(ctx, r)
- if err != nil {
- return nil, togRPCError(err)
- }
- return resp, nil
-}
-
-func (as *AuthServer) RoleDelete(ctx context.Context, r *pb.AuthRoleDeleteRequest) (*pb.AuthRoleDeleteResponse, error) {
- resp, err := as.authenticator.RoleDelete(ctx, r)
- if err != nil {
- return nil, togRPCError(err)
- }
- return resp, nil
-}
-
-func (as *AuthServer) RoleGet(ctx context.Context, r *pb.AuthRoleGetRequest) (*pb.AuthRoleGetResponse, error) {
- resp, err := as.authenticator.RoleGet(ctx, r)
- if err != nil {
- return nil, togRPCError(err)
- }
- return resp, nil
-}
-
-func (as *AuthServer) RoleList(ctx context.Context, r *pb.AuthRoleListRequest) (*pb.AuthRoleListResponse, error) {
- resp, err := as.authenticator.RoleList(ctx, r)
- if err != nil {
- return nil, togRPCError(err)
- }
- return resp, nil
-}
-
-func (as *AuthServer) RoleRevokePermission(ctx context.Context, r *pb.AuthRoleRevokePermissionRequest) (*pb.AuthRoleRevokePermissionResponse, error) {
- resp, err := as.authenticator.RoleRevokePermission(ctx, r)
- if err != nil {
- return nil, togRPCError(err)
- }
- return resp, nil
-}
-
-func (as *AuthServer) RoleGrantPermission(ctx context.Context, r *pb.AuthRoleGrantPermissionRequest) (*pb.AuthRoleGrantPermissionResponse, error) {
- resp, err := as.authenticator.RoleGrantPermission(ctx, r)
- if err != nil {
- return nil, togRPCError(err)
- }
- return resp, nil
-}
-
-func (as *AuthServer) UserAdd(ctx context.Context, r *pb.AuthUserAddRequest) (*pb.AuthUserAddResponse, error) {
- resp, err := as.authenticator.UserAdd(ctx, r)
- if err != nil {
- return nil, togRPCError(err)
- }
- return resp, nil
-}
-
-func (as *AuthServer) UserDelete(ctx context.Context, r *pb.AuthUserDeleteRequest) (*pb.AuthUserDeleteResponse, error) {
- resp, err := as.authenticator.UserDelete(ctx, r)
- if err != nil {
- return nil, togRPCError(err)
- }
- return resp, nil
-}
-
-func (as *AuthServer) UserGet(ctx context.Context, r *pb.AuthUserGetRequest) (*pb.AuthUserGetResponse, error) {
- resp, err := as.authenticator.UserGet(ctx, r)
- if err != nil {
- return nil, togRPCError(err)
- }
- return resp, nil
-}
-
-func (as *AuthServer) UserList(ctx context.Context, r *pb.AuthUserListRequest) (*pb.AuthUserListResponse, error) {
- resp, err := as.authenticator.UserList(ctx, r)
- if err != nil {
- return nil, togRPCError(err)
- }
- return resp, nil
-}
-
-func (as *AuthServer) UserGrantRole(ctx context.Context, r *pb.AuthUserGrantRoleRequest) (*pb.AuthUserGrantRoleResponse, error) {
- resp, err := as.authenticator.UserGrantRole(ctx, r)
- if err != nil {
- return nil, togRPCError(err)
- }
- return resp, nil
-}
-
-func (as *AuthServer) UserRevokeRole(ctx context.Context, r *pb.AuthUserRevokeRoleRequest) (*pb.AuthUserRevokeRoleResponse, error) {
- resp, err := as.authenticator.UserRevokeRole(ctx, r)
- if err != nil {
- return nil, togRPCError(err)
- }
- return resp, nil
-}
-
-func (as *AuthServer) UserChangePassword(ctx context.Context, r *pb.AuthUserChangePasswordRequest) (*pb.AuthUserChangePasswordResponse, error) {
- resp, err := as.authenticator.UserChangePassword(ctx, r)
- if err != nil {
- return nil, togRPCError(err)
- }
- return resp, nil
-}
diff --git a/vendor/go.etcd.io/etcd/etcdserver/api/v3rpc/codec.go b/vendor/go.etcd.io/etcd/etcdserver/api/v3rpc/codec.go
deleted file mode 100644
index 17a2c87..0000000
--- a/vendor/go.etcd.io/etcd/etcdserver/api/v3rpc/codec.go
+++ /dev/null
@@ -1,34 +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 v3rpc
-
-import "github.com/gogo/protobuf/proto"
-
-type codec struct{}
-
-func (c *codec) Marshal(v interface{}) ([]byte, error) {
- b, err := proto.Marshal(v.(proto.Message))
- sentBytes.Add(float64(len(b)))
- return b, err
-}
-
-func (c *codec) Unmarshal(data []byte, v interface{}) error {
- receivedBytes.Add(float64(len(data)))
- return proto.Unmarshal(data, v.(proto.Message))
-}
-
-func (c *codec) String() string {
- return "proto"
-}
diff --git a/vendor/go.etcd.io/etcd/etcdserver/api/v3rpc/grpc.go b/vendor/go.etcd.io/etcd/etcdserver/api/v3rpc/grpc.go
deleted file mode 100644
index 3332016..0000000
--- a/vendor/go.etcd.io/etcd/etcdserver/api/v3rpc/grpc.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 v3rpc
-
-import (
- "crypto/tls"
- "math"
-
- "go.etcd.io/etcd/etcdserver"
- pb "go.etcd.io/etcd/etcdserver/etcdserverpb"
-
- grpc_middleware "github.com/grpc-ecosystem/go-grpc-middleware"
- grpc_prometheus "github.com/grpc-ecosystem/go-grpc-prometheus"
- "go.etcd.io/etcd/clientv3/credentials"
- "google.golang.org/grpc"
- "google.golang.org/grpc/health"
- healthpb "google.golang.org/grpc/health/grpc_health_v1"
-)
-
-const (
- grpcOverheadBytes = 512 * 1024
- maxStreams = math.MaxUint32
- maxSendBytes = math.MaxInt32
-)
-
-func Server(s *etcdserver.EtcdServer, tls *tls.Config, gopts ...grpc.ServerOption) *grpc.Server {
- var opts []grpc.ServerOption
- opts = append(opts, grpc.CustomCodec(&codec{}))
- if tls != nil {
- bundle := credentials.NewBundle(credentials.Config{TLSConfig: tls})
- opts = append(opts, grpc.Creds(bundle.TransportCredentials()))
- }
- opts = append(opts, grpc.UnaryInterceptor(grpc_middleware.ChainUnaryServer(
- newLogUnaryInterceptor(s),
- newUnaryInterceptor(s),
- grpc_prometheus.UnaryServerInterceptor,
- )))
- opts = append(opts, grpc.StreamInterceptor(grpc_middleware.ChainStreamServer(
- newStreamInterceptor(s),
- grpc_prometheus.StreamServerInterceptor,
- )))
- opts = append(opts, grpc.MaxRecvMsgSize(int(s.Cfg.MaxRequestBytes+grpcOverheadBytes)))
- opts = append(opts, grpc.MaxSendMsgSize(maxSendBytes))
- opts = append(opts, grpc.MaxConcurrentStreams(maxStreams))
- grpcServer := grpc.NewServer(append(opts, gopts...)...)
-
- pb.RegisterKVServer(grpcServer, NewQuotaKVServer(s))
- pb.RegisterWatchServer(grpcServer, NewWatchServer(s))
- pb.RegisterLeaseServer(grpcServer, NewQuotaLeaseServer(s))
- pb.RegisterClusterServer(grpcServer, NewClusterServer(s))
- pb.RegisterAuthServer(grpcServer, NewAuthServer(s))
- pb.RegisterMaintenanceServer(grpcServer, NewMaintenanceServer(s))
-
- // server should register all the services manually
- // use empty service name for all etcd services' health status,
- // see https://github.com/grpc/grpc/blob/master/doc/health-checking.md for more
- hsrv := health.NewServer()
- hsrv.SetServingStatus("", healthpb.HealthCheckResponse_SERVING)
- healthpb.RegisterHealthServer(grpcServer, hsrv)
-
- // set zero values for metrics registered for this grpc server
- grpc_prometheus.Register(grpcServer)
-
- return grpcServer
-}
diff --git a/vendor/go.etcd.io/etcd/etcdserver/api/v3rpc/header.go b/vendor/go.etcd.io/etcd/etcdserver/api/v3rpc/header.go
deleted file mode 100644
index f23b6a7..0000000
--- a/vendor/go.etcd.io/etcd/etcdserver/api/v3rpc/header.go
+++ /dev/null
@@ -1,49 +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 v3rpc
-
-import (
- "go.etcd.io/etcd/etcdserver"
- pb "go.etcd.io/etcd/etcdserver/etcdserverpb"
-)
-
-type header struct {
- clusterID int64
- memberID int64
- sg etcdserver.RaftStatusGetter
- rev func() int64
-}
-
-func newHeader(s *etcdserver.EtcdServer) header {
- return header{
- clusterID: int64(s.Cluster().ID()),
- memberID: int64(s.ID()),
- sg: s,
- rev: func() int64 { return s.KV().Rev() },
- }
-}
-
-// fill populates pb.ResponseHeader using etcdserver information
-func (h *header) fill(rh *pb.ResponseHeader) {
- if rh == nil {
- plog.Panic("unexpected nil resp.Header")
- }
- rh.ClusterId = uint64(h.clusterID)
- rh.MemberId = uint64(h.memberID)
- rh.RaftTerm = h.sg.Term()
- if rh.Revision == 0 {
- rh.Revision = h.rev()
- }
-}
diff --git a/vendor/go.etcd.io/etcd/etcdserver/api/v3rpc/interceptor.go b/vendor/go.etcd.io/etcd/etcdserver/api/v3rpc/interceptor.go
deleted file mode 100644
index ce9047e..0000000
--- a/vendor/go.etcd.io/etcd/etcdserver/api/v3rpc/interceptor.go
+++ /dev/null
@@ -1,276 +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 v3rpc
-
-import (
- "context"
- "sync"
- "time"
-
- "go.etcd.io/etcd/etcdserver"
- "go.etcd.io/etcd/etcdserver/api"
- "go.etcd.io/etcd/etcdserver/api/v3rpc/rpctypes"
- "go.etcd.io/etcd/pkg/types"
- "go.etcd.io/etcd/raft"
-
- "github.com/coreos/pkg/capnslog"
- pb "go.etcd.io/etcd/etcdserver/etcdserverpb"
- "go.uber.org/zap"
- "google.golang.org/grpc"
- "google.golang.org/grpc/metadata"
- "google.golang.org/grpc/peer"
-)
-
-const (
- maxNoLeaderCnt = 3
-)
-
-type streamsMap struct {
- mu sync.Mutex
- streams map[grpc.ServerStream]struct{}
-}
-
-func newUnaryInterceptor(s *etcdserver.EtcdServer) grpc.UnaryServerInterceptor {
- return func(ctx context.Context, req interface{}, info *grpc.UnaryServerInfo, handler grpc.UnaryHandler) (interface{}, error) {
- if !api.IsCapabilityEnabled(api.V3rpcCapability) {
- return nil, rpctypes.ErrGRPCNotCapable
- }
-
- if s.IsMemberExist(s.ID()) && s.IsLearner() && !isRPCSupportedForLearner(req) {
- return nil, rpctypes.ErrGPRCNotSupportedForLearner
- }
-
- md, ok := metadata.FromIncomingContext(ctx)
- if ok {
- if ks := md[rpctypes.MetadataRequireLeaderKey]; len(ks) > 0 && ks[0] == rpctypes.MetadataHasLeader {
- if s.Leader() == types.ID(raft.None) {
- return nil, rpctypes.ErrGRPCNoLeader
- }
- }
- }
-
- return handler(ctx, req)
- }
-}
-
-func newLogUnaryInterceptor(s *etcdserver.EtcdServer) grpc.UnaryServerInterceptor {
- return func(ctx context.Context, req interface{}, info *grpc.UnaryServerInfo, handler grpc.UnaryHandler) (interface{}, error) {
- startTime := time.Now()
- resp, err := handler(ctx, req)
- lg := s.Logger()
- if (lg != nil && lg.Core().Enabled(zap.DebugLevel)) || // using zap logger and debug level is enabled
- (lg == nil && plog.LevelAt(capnslog.DEBUG)) { // or, using capnslog and debug level is enabled
- defer logUnaryRequestStats(ctx, lg, info, startTime, req, resp)
- }
- return resp, err
- }
-}
-
-func logUnaryRequestStats(ctx context.Context, lg *zap.Logger, info *grpc.UnaryServerInfo, startTime time.Time, req interface{}, resp interface{}) {
- duration := time.Since(startTime)
- remote := "No remote client info."
- peerInfo, ok := peer.FromContext(ctx)
- if ok {
- remote = peerInfo.Addr.String()
- }
- responseType := info.FullMethod
- var reqCount, respCount int64
- var reqSize, respSize int
- var reqContent string
- switch _resp := resp.(type) {
- case *pb.RangeResponse:
- _req, ok := req.(*pb.RangeRequest)
- if ok {
- reqCount = 0
- reqSize = _req.Size()
- reqContent = _req.String()
- }
- if _resp != nil {
- respCount = _resp.GetCount()
- respSize = _resp.Size()
- }
- case *pb.PutResponse:
- _req, ok := req.(*pb.PutRequest)
- if ok {
- reqCount = 1
- reqSize = _req.Size()
- reqContent = pb.NewLoggablePutRequest(_req).String()
- // redact value field from request content, see PR #9821
- }
- if _resp != nil {
- respCount = 0
- respSize = _resp.Size()
- }
- case *pb.DeleteRangeResponse:
- _req, ok := req.(*pb.DeleteRangeRequest)
- if ok {
- reqCount = 0
- reqSize = _req.Size()
- reqContent = _req.String()
- }
- if _resp != nil {
- respCount = _resp.GetDeleted()
- respSize = _resp.Size()
- }
- case *pb.TxnResponse:
- _req, ok := req.(*pb.TxnRequest)
- if ok && _resp != nil {
- if _resp.GetSucceeded() { // determine the 'actual' count and size of request based on success or failure
- reqCount = int64(len(_req.GetSuccess()))
- reqSize = 0
- for _, r := range _req.GetSuccess() {
- reqSize += r.Size()
- }
- } else {
- reqCount = int64(len(_req.GetFailure()))
- reqSize = 0
- for _, r := range _req.GetFailure() {
- reqSize += r.Size()
- }
- }
- reqContent = pb.NewLoggableTxnRequest(_req).String()
- // redact value field from request content, see PR #9821
- }
- if _resp != nil {
- respCount = 0
- respSize = _resp.Size()
- }
- default:
- reqCount = -1
- reqSize = -1
- respCount = -1
- respSize = -1
- }
-
- logGenericRequestStats(lg, startTime, duration, remote, responseType, reqCount, reqSize, respCount, respSize, reqContent)
-}
-
-func logGenericRequestStats(lg *zap.Logger, startTime time.Time, duration time.Duration, remote string, responseType string,
- reqCount int64, reqSize int, respCount int64, respSize int, reqContent string) {
- if lg == nil {
- plog.Debugf("start time = %v, "+
- "time spent = %v, "+
- "remote = %s, "+
- "response type = %s, "+
- "request count = %d, "+
- "request size = %d, "+
- "response count = %d, "+
- "response size = %d, "+
- "request content = %s",
- startTime, duration, remote, responseType, reqCount, reqSize, respCount, respSize, reqContent,
- )
- } else {
- lg.Debug("request stats",
- zap.Time("start time", startTime),
- zap.Duration("time spent", duration),
- zap.String("remote", remote),
- zap.String("response type", responseType),
- zap.Int64("request count", reqCount),
- zap.Int("request size", reqSize),
- zap.Int64("response count", respCount),
- zap.Int("response size", respSize),
- zap.String("request content", reqContent),
- )
- }
-}
-
-func newStreamInterceptor(s *etcdserver.EtcdServer) grpc.StreamServerInterceptor {
- smap := monitorLeader(s)
-
- return func(srv interface{}, ss grpc.ServerStream, info *grpc.StreamServerInfo, handler grpc.StreamHandler) error {
- if !api.IsCapabilityEnabled(api.V3rpcCapability) {
- return rpctypes.ErrGRPCNotCapable
- }
-
- if s.IsMemberExist(s.ID()) && s.IsLearner() { // learner does not support stream RPC
- return rpctypes.ErrGPRCNotSupportedForLearner
- }
-
- md, ok := metadata.FromIncomingContext(ss.Context())
- if ok {
- if ks := md[rpctypes.MetadataRequireLeaderKey]; len(ks) > 0 && ks[0] == rpctypes.MetadataHasLeader {
- if s.Leader() == types.ID(raft.None) {
- return rpctypes.ErrGRPCNoLeader
- }
-
- cctx, cancel := context.WithCancel(ss.Context())
- ss = serverStreamWithCtx{ctx: cctx, cancel: &cancel, ServerStream: ss}
-
- smap.mu.Lock()
- smap.streams[ss] = struct{}{}
- smap.mu.Unlock()
-
- defer func() {
- smap.mu.Lock()
- delete(smap.streams, ss)
- smap.mu.Unlock()
- cancel()
- }()
-
- }
- }
-
- return handler(srv, ss)
- }
-}
-
-type serverStreamWithCtx struct {
- grpc.ServerStream
- ctx context.Context
- cancel *context.CancelFunc
-}
-
-func (ssc serverStreamWithCtx) Context() context.Context { return ssc.ctx }
-
-func monitorLeader(s *etcdserver.EtcdServer) *streamsMap {
- smap := &streamsMap{
- streams: make(map[grpc.ServerStream]struct{}),
- }
-
- go func() {
- election := time.Duration(s.Cfg.TickMs) * time.Duration(s.Cfg.ElectionTicks) * time.Millisecond
- noLeaderCnt := 0
-
- for {
- select {
- case <-s.StopNotify():
- return
- case <-time.After(election):
- if s.Leader() == types.ID(raft.None) {
- noLeaderCnt++
- } else {
- noLeaderCnt = 0
- }
-
- // We are more conservative on canceling existing streams. Reconnecting streams
- // cost much more than just rejecting new requests. So we wait until the member
- // cannot find a leader for maxNoLeaderCnt election timeouts to cancel existing streams.
- if noLeaderCnt >= maxNoLeaderCnt {
- smap.mu.Lock()
- for ss := range smap.streams {
- if ssWithCtx, ok := ss.(serverStreamWithCtx); ok {
- (*ssWithCtx.cancel)()
- <-ss.Context().Done()
- }
- }
- smap.streams = make(map[grpc.ServerStream]struct{})
- smap.mu.Unlock()
- }
- }
- }
- }()
-
- return smap
-}
diff --git a/vendor/go.etcd.io/etcd/etcdserver/api/v3rpc/key.go b/vendor/go.etcd.io/etcd/etcdserver/api/v3rpc/key.go
deleted file mode 100644
index ff59bac..0000000
--- a/vendor/go.etcd.io/etcd/etcdserver/api/v3rpc/key.go
+++ /dev/null
@@ -1,277 +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 v3rpc implements etcd v3 RPC system based on gRPC.
-package v3rpc
-
-import (
- "context"
-
- "go.etcd.io/etcd/etcdserver"
- "go.etcd.io/etcd/etcdserver/api/v3rpc/rpctypes"
- pb "go.etcd.io/etcd/etcdserver/etcdserverpb"
- "go.etcd.io/etcd/pkg/adt"
-
- "github.com/coreos/pkg/capnslog"
-)
-
-var (
- plog = capnslog.NewPackageLogger("go.etcd.io/etcd", "etcdserver/api/v3rpc")
-)
-
-type kvServer struct {
- hdr header
- kv etcdserver.RaftKV
- // maxTxnOps is the max operations per txn.
- // e.g suppose maxTxnOps = 128.
- // Txn.Success can have at most 128 operations,
- // and Txn.Failure can have at most 128 operations.
- maxTxnOps uint
-}
-
-func NewKVServer(s *etcdserver.EtcdServer) pb.KVServer {
- return &kvServer{hdr: newHeader(s), kv: s, maxTxnOps: s.Cfg.MaxTxnOps}
-}
-
-func (s *kvServer) Range(ctx context.Context, r *pb.RangeRequest) (*pb.RangeResponse, error) {
- if err := checkRangeRequest(r); err != nil {
- return nil, err
- }
-
- resp, err := s.kv.Range(ctx, r)
- if err != nil {
- return nil, togRPCError(err)
- }
-
- s.hdr.fill(resp.Header)
- return resp, nil
-}
-
-func (s *kvServer) Put(ctx context.Context, r *pb.PutRequest) (*pb.PutResponse, error) {
- if err := checkPutRequest(r); err != nil {
- return nil, err
- }
-
- resp, err := s.kv.Put(ctx, r)
- if err != nil {
- return nil, togRPCError(err)
- }
-
- s.hdr.fill(resp.Header)
- return resp, nil
-}
-
-func (s *kvServer) DeleteRange(ctx context.Context, r *pb.DeleteRangeRequest) (*pb.DeleteRangeResponse, error) {
- if err := checkDeleteRequest(r); err != nil {
- return nil, err
- }
-
- resp, err := s.kv.DeleteRange(ctx, r)
- if err != nil {
- return nil, togRPCError(err)
- }
-
- s.hdr.fill(resp.Header)
- return resp, nil
-}
-
-func (s *kvServer) Txn(ctx context.Context, r *pb.TxnRequest) (*pb.TxnResponse, error) {
- if err := checkTxnRequest(r, int(s.maxTxnOps)); err != nil {
- return nil, err
- }
- // check for forbidden put/del overlaps after checking request to avoid quadratic blowup
- if _, _, err := checkIntervals(r.Success); err != nil {
- return nil, err
- }
- if _, _, err := checkIntervals(r.Failure); err != nil {
- return nil, err
- }
-
- resp, err := s.kv.Txn(ctx, r)
- if err != nil {
- return nil, togRPCError(err)
- }
-
- s.hdr.fill(resp.Header)
- return resp, nil
-}
-
-func (s *kvServer) Compact(ctx context.Context, r *pb.CompactionRequest) (*pb.CompactionResponse, error) {
- resp, err := s.kv.Compact(ctx, r)
- if err != nil {
- return nil, togRPCError(err)
- }
-
- s.hdr.fill(resp.Header)
- return resp, nil
-}
-
-func checkRangeRequest(r *pb.RangeRequest) error {
- if len(r.Key) == 0 {
- return rpctypes.ErrGRPCEmptyKey
- }
- return nil
-}
-
-func checkPutRequest(r *pb.PutRequest) error {
- if len(r.Key) == 0 {
- return rpctypes.ErrGRPCEmptyKey
- }
- if r.IgnoreValue && len(r.Value) != 0 {
- return rpctypes.ErrGRPCValueProvided
- }
- if r.IgnoreLease && r.Lease != 0 {
- return rpctypes.ErrGRPCLeaseProvided
- }
- return nil
-}
-
-func checkDeleteRequest(r *pb.DeleteRangeRequest) error {
- if len(r.Key) == 0 {
- return rpctypes.ErrGRPCEmptyKey
- }
- return nil
-}
-
-func checkTxnRequest(r *pb.TxnRequest, maxTxnOps int) error {
- opc := len(r.Compare)
- if opc < len(r.Success) {
- opc = len(r.Success)
- }
- if opc < len(r.Failure) {
- opc = len(r.Failure)
- }
- if opc > maxTxnOps {
- return rpctypes.ErrGRPCTooManyOps
- }
-
- for _, c := range r.Compare {
- if len(c.Key) == 0 {
- return rpctypes.ErrGRPCEmptyKey
- }
- }
- for _, u := range r.Success {
- if err := checkRequestOp(u, maxTxnOps-opc); err != nil {
- return err
- }
- }
- for _, u := range r.Failure {
- if err := checkRequestOp(u, maxTxnOps-opc); err != nil {
- return err
- }
- }
-
- return nil
-}
-
-// checkIntervals tests whether puts and deletes overlap for a list of ops. If
-// there is an overlap, returns an error. If no overlap, return put and delete
-// sets for recursive evaluation.
-func checkIntervals(reqs []*pb.RequestOp) (map[string]struct{}, adt.IntervalTree, error) {
- dels := adt.NewIntervalTree()
-
- // collect deletes from this level; build first to check lower level overlapped puts
- for _, req := range reqs {
- tv, ok := req.Request.(*pb.RequestOp_RequestDeleteRange)
- if !ok {
- continue
- }
- dreq := tv.RequestDeleteRange
- if dreq == nil {
- continue
- }
- var iv adt.Interval
- if len(dreq.RangeEnd) != 0 {
- iv = adt.NewStringAffineInterval(string(dreq.Key), string(dreq.RangeEnd))
- } else {
- iv = adt.NewStringAffinePoint(string(dreq.Key))
- }
- dels.Insert(iv, struct{}{})
- }
-
- // collect children puts/deletes
- puts := make(map[string]struct{})
- for _, req := range reqs {
- tv, ok := req.Request.(*pb.RequestOp_RequestTxn)
- if !ok {
- continue
- }
- putsThen, delsThen, err := checkIntervals(tv.RequestTxn.Success)
- if err != nil {
- return nil, dels, err
- }
- putsElse, delsElse, err := checkIntervals(tv.RequestTxn.Failure)
- if err != nil {
- return nil, dels, err
- }
- for k := range putsThen {
- if _, ok := puts[k]; ok {
- return nil, dels, rpctypes.ErrGRPCDuplicateKey
- }
- if dels.Intersects(adt.NewStringAffinePoint(k)) {
- return nil, dels, rpctypes.ErrGRPCDuplicateKey
- }
- puts[k] = struct{}{}
- }
- for k := range putsElse {
- if _, ok := puts[k]; ok {
- // if key is from putsThen, overlap is OK since
- // either then/else are mutually exclusive
- if _, isSafe := putsThen[k]; !isSafe {
- return nil, dels, rpctypes.ErrGRPCDuplicateKey
- }
- }
- if dels.Intersects(adt.NewStringAffinePoint(k)) {
- return nil, dels, rpctypes.ErrGRPCDuplicateKey
- }
- puts[k] = struct{}{}
- }
- dels.Union(delsThen, adt.NewStringAffineInterval("\x00", ""))
- dels.Union(delsElse, adt.NewStringAffineInterval("\x00", ""))
- }
-
- // collect and check this level's puts
- for _, req := range reqs {
- tv, ok := req.Request.(*pb.RequestOp_RequestPut)
- if !ok || tv.RequestPut == nil {
- continue
- }
- k := string(tv.RequestPut.Key)
- if _, ok := puts[k]; ok {
- return nil, dels, rpctypes.ErrGRPCDuplicateKey
- }
- if dels.Intersects(adt.NewStringAffinePoint(k)) {
- return nil, dels, rpctypes.ErrGRPCDuplicateKey
- }
- puts[k] = struct{}{}
- }
- return puts, dels, nil
-}
-
-func checkRequestOp(u *pb.RequestOp, maxTxnOps int) error {
- // TODO: ensure only one of the field is set.
- switch uv := u.Request.(type) {
- case *pb.RequestOp_RequestRange:
- return checkRangeRequest(uv.RequestRange)
- case *pb.RequestOp_RequestPut:
- return checkPutRequest(uv.RequestPut)
- case *pb.RequestOp_RequestDeleteRange:
- return checkDeleteRequest(uv.RequestDeleteRange)
- case *pb.RequestOp_RequestTxn:
- return checkTxnRequest(uv.RequestTxn, maxTxnOps)
- default:
- // empty op / nil entry
- return rpctypes.ErrGRPCKeyNotFound
- }
-}
diff --git a/vendor/go.etcd.io/etcd/etcdserver/api/v3rpc/lease.go b/vendor/go.etcd.io/etcd/etcdserver/api/v3rpc/lease.go
deleted file mode 100644
index 7441bee..0000000
--- a/vendor/go.etcd.io/etcd/etcdserver/api/v3rpc/lease.go
+++ /dev/null
@@ -1,169 +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 v3rpc
-
-import (
- "context"
- "io"
-
- "go.etcd.io/etcd/etcdserver"
- "go.etcd.io/etcd/etcdserver/api/v3rpc/rpctypes"
- pb "go.etcd.io/etcd/etcdserver/etcdserverpb"
- "go.etcd.io/etcd/lease"
-
- "go.uber.org/zap"
-)
-
-type LeaseServer struct {
- lg *zap.Logger
- hdr header
- le etcdserver.Lessor
-}
-
-func NewLeaseServer(s *etcdserver.EtcdServer) pb.LeaseServer {
- return &LeaseServer{lg: s.Cfg.Logger, le: s, hdr: newHeader(s)}
-}
-
-func (ls *LeaseServer) LeaseGrant(ctx context.Context, cr *pb.LeaseGrantRequest) (*pb.LeaseGrantResponse, error) {
- resp, err := ls.le.LeaseGrant(ctx, cr)
-
- if err != nil {
- return nil, togRPCError(err)
- }
- ls.hdr.fill(resp.Header)
- return resp, nil
-}
-
-func (ls *LeaseServer) LeaseRevoke(ctx context.Context, rr *pb.LeaseRevokeRequest) (*pb.LeaseRevokeResponse, error) {
- resp, err := ls.le.LeaseRevoke(ctx, rr)
- if err != nil {
- return nil, togRPCError(err)
- }
- ls.hdr.fill(resp.Header)
- return resp, nil
-}
-
-func (ls *LeaseServer) LeaseTimeToLive(ctx context.Context, rr *pb.LeaseTimeToLiveRequest) (*pb.LeaseTimeToLiveResponse, error) {
- resp, err := ls.le.LeaseTimeToLive(ctx, rr)
- if err != nil && err != lease.ErrLeaseNotFound {
- return nil, togRPCError(err)
- }
- if err == lease.ErrLeaseNotFound {
- resp = &pb.LeaseTimeToLiveResponse{
- Header: &pb.ResponseHeader{},
- ID: rr.ID,
- TTL: -1,
- }
- }
- ls.hdr.fill(resp.Header)
- return resp, nil
-}
-
-func (ls *LeaseServer) LeaseLeases(ctx context.Context, rr *pb.LeaseLeasesRequest) (*pb.LeaseLeasesResponse, error) {
- resp, err := ls.le.LeaseLeases(ctx, rr)
- if err != nil && err != lease.ErrLeaseNotFound {
- return nil, togRPCError(err)
- }
- if err == lease.ErrLeaseNotFound {
- resp = &pb.LeaseLeasesResponse{
- Header: &pb.ResponseHeader{},
- Leases: []*pb.LeaseStatus{},
- }
- }
- ls.hdr.fill(resp.Header)
- return resp, nil
-}
-
-func (ls *LeaseServer) LeaseKeepAlive(stream pb.Lease_LeaseKeepAliveServer) (err error) {
- errc := make(chan error, 1)
- go func() {
- errc <- ls.leaseKeepAlive(stream)
- }()
- select {
- case err = <-errc:
- case <-stream.Context().Done():
- // the only server-side cancellation is noleader for now.
- err = stream.Context().Err()
- if err == context.Canceled {
- err = rpctypes.ErrGRPCNoLeader
- }
- }
- return err
-}
-
-func (ls *LeaseServer) leaseKeepAlive(stream pb.Lease_LeaseKeepAliveServer) error {
- for {
- req, err := stream.Recv()
- if err == io.EOF {
- return nil
- }
- if err != nil {
- if isClientCtxErr(stream.Context().Err(), err) {
- if ls.lg != nil {
- ls.lg.Debug("failed to receive lease keepalive request from gRPC stream", zap.Error(err))
- } else {
- plog.Debugf("failed to receive lease keepalive request from gRPC stream (%q)", err.Error())
- }
- } else {
- if ls.lg != nil {
- ls.lg.Warn("failed to receive lease keepalive request from gRPC stream", zap.Error(err))
- } else {
- plog.Warningf("failed to receive lease keepalive request from gRPC stream (%q)", err.Error())
- }
- streamFailures.WithLabelValues("receive", "lease-keepalive").Inc()
- }
- return err
- }
-
- // Create header before we sent out the renew request.
- // This can make sure that the revision is strictly smaller or equal to
- // when the keepalive happened at the local server (when the local server is the leader)
- // or remote leader.
- // Without this, a lease might be revoked at rev 3 but client can see the keepalive succeeded
- // at rev 4.
- resp := &pb.LeaseKeepAliveResponse{ID: req.ID, Header: &pb.ResponseHeader{}}
- ls.hdr.fill(resp.Header)
-
- ttl, err := ls.le.LeaseRenew(stream.Context(), lease.LeaseID(req.ID))
- if err == lease.ErrLeaseNotFound {
- err = nil
- ttl = 0
- }
-
- if err != nil {
- return togRPCError(err)
- }
-
- resp.TTL = ttl
- err = stream.Send(resp)
- if err != nil {
- if isClientCtxErr(stream.Context().Err(), err) {
- if ls.lg != nil {
- ls.lg.Debug("failed to send lease keepalive response to gRPC stream", zap.Error(err))
- } else {
- plog.Debugf("failed to send lease keepalive response to gRPC stream (%q)", err.Error())
- }
- } else {
- if ls.lg != nil {
- ls.lg.Warn("failed to send lease keepalive response to gRPC stream", zap.Error(err))
- } else {
- plog.Warningf("failed to send lease keepalive response to gRPC stream (%q)", err.Error())
- }
- streamFailures.WithLabelValues("send", "lease-keepalive").Inc()
- }
- return err
- }
- }
-}
diff --git a/vendor/go.etcd.io/etcd/etcdserver/api/v3rpc/maintenance.go b/vendor/go.etcd.io/etcd/etcdserver/api/v3rpc/maintenance.go
deleted file mode 100644
index c51271a..0000000
--- a/vendor/go.etcd.io/etcd/etcdserver/api/v3rpc/maintenance.go
+++ /dev/null
@@ -1,260 +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 v3rpc
-
-import (
- "context"
- "crypto/sha256"
- "io"
-
- "go.etcd.io/etcd/auth"
- "go.etcd.io/etcd/etcdserver"
- "go.etcd.io/etcd/etcdserver/api/v3rpc/rpctypes"
- pb "go.etcd.io/etcd/etcdserver/etcdserverpb"
- "go.etcd.io/etcd/mvcc"
- "go.etcd.io/etcd/mvcc/backend"
- "go.etcd.io/etcd/raft"
- "go.etcd.io/etcd/version"
-
- "go.uber.org/zap"
-)
-
-type KVGetter interface {
- KV() mvcc.ConsistentWatchableKV
-}
-
-type BackendGetter interface {
- Backend() backend.Backend
-}
-
-type Alarmer interface {
- // Alarms is implemented in Server interface located in etcdserver/server.go
- // It returns a list of alarms present in the AlarmStore
- Alarms() []*pb.AlarmMember
- Alarm(ctx context.Context, ar *pb.AlarmRequest) (*pb.AlarmResponse, error)
-}
-
-type LeaderTransferrer interface {
- MoveLeader(ctx context.Context, lead, target uint64) error
-}
-
-type AuthGetter interface {
- AuthInfoFromCtx(ctx context.Context) (*auth.AuthInfo, error)
- AuthStore() auth.AuthStore
-}
-
-type ClusterStatusGetter interface {
- IsLearner() bool
-}
-
-type maintenanceServer struct {
- lg *zap.Logger
- rg etcdserver.RaftStatusGetter
- kg KVGetter
- bg BackendGetter
- a Alarmer
- lt LeaderTransferrer
- hdr header
- cs ClusterStatusGetter
-}
-
-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}
- return &authMaintenanceServer{srv, s}
-}
-
-func (ms *maintenanceServer) Defragment(ctx context.Context, sr *pb.DefragmentRequest) (*pb.DefragmentResponse, error) {
- if ms.lg != nil {
- ms.lg.Info("starting defragment")
- } else {
- plog.Noticef("starting to defragment the storage backend...")
- }
- err := ms.bg.Backend().Defrag()
- if err != nil {
- if ms.lg != nil {
- ms.lg.Warn("failed to defragment", zap.Error(err))
- } else {
- plog.Errorf("failed to defragment the storage backend (%v)", err)
- }
- return nil, err
- }
- if ms.lg != nil {
- ms.lg.Info("finished defragment")
- } else {
- plog.Noticef("finished defragmenting the storage backend")
- }
- return &pb.DefragmentResponse{}, nil
-}
-
-func (ms *maintenanceServer) Snapshot(sr *pb.SnapshotRequest, srv pb.Maintenance_SnapshotServer) error {
- snap := ms.bg.Backend().Snapshot()
- pr, pw := io.Pipe()
-
- defer pr.Close()
-
- go func() {
- snap.WriteTo(pw)
- if err := snap.Close(); err != nil {
- if ms.lg != nil {
- ms.lg.Warn("failed to close snapshot", zap.Error(err))
- } else {
- plog.Errorf("error closing snapshot (%v)", err)
- }
- }
- pw.Close()
- }()
-
- // send file data
- h := sha256.New()
- br := int64(0)
- buf := make([]byte, 32*1024)
- sz := snap.Size()
- for br < sz {
- n, err := io.ReadFull(pr, buf)
- if err != nil && err != io.EOF && err != io.ErrUnexpectedEOF {
- return togRPCError(err)
- }
- br += int64(n)
- resp := &pb.SnapshotResponse{
- RemainingBytes: uint64(sz - br),
- Blob: buf[:n],
- }
- if err = srv.Send(resp); err != nil {
- return togRPCError(err)
- }
- h.Write(buf[:n])
- }
-
- // send sha
- sha := h.Sum(nil)
- hresp := &pb.SnapshotResponse{RemainingBytes: 0, Blob: sha}
- if err := srv.Send(hresp); err != nil {
- return togRPCError(err)
- }
-
- return nil
-}
-
-func (ms *maintenanceServer) Hash(ctx context.Context, r *pb.HashRequest) (*pb.HashResponse, error) {
- h, rev, err := ms.kg.KV().Hash()
- if err != nil {
- return nil, togRPCError(err)
- }
- resp := &pb.HashResponse{Header: &pb.ResponseHeader{Revision: rev}, Hash: h}
- ms.hdr.fill(resp.Header)
- return resp, nil
-}
-
-func (ms *maintenanceServer) HashKV(ctx context.Context, r *pb.HashKVRequest) (*pb.HashKVResponse, error) {
- h, rev, compactRev, err := ms.kg.KV().HashByRev(r.Revision)
- if err != nil {
- return nil, togRPCError(err)
- }
-
- resp := &pb.HashKVResponse{Header: &pb.ResponseHeader{Revision: rev}, Hash: h, CompactRevision: compactRev}
- ms.hdr.fill(resp.Header)
- return resp, nil
-}
-
-func (ms *maintenanceServer) Alarm(ctx context.Context, ar *pb.AlarmRequest) (*pb.AlarmResponse, error) {
- return ms.a.Alarm(ctx, ar)
-}
-
-func (ms *maintenanceServer) Status(ctx context.Context, ar *pb.StatusRequest) (*pb.StatusResponse, error) {
- hdr := &pb.ResponseHeader{}
- ms.hdr.fill(hdr)
- resp := &pb.StatusResponse{
- Header: hdr,
- Version: version.Version,
- Leader: uint64(ms.rg.Leader()),
- RaftIndex: ms.rg.CommittedIndex(),
- RaftAppliedIndex: ms.rg.AppliedIndex(),
- RaftTerm: ms.rg.Term(),
- DbSize: ms.bg.Backend().Size(),
- DbSizeInUse: ms.bg.Backend().SizeInUse(),
- IsLearner: ms.cs.IsLearner(),
- }
- if resp.Leader == raft.None {
- resp.Errors = append(resp.Errors, etcdserver.ErrNoLeader.Error())
- }
- for _, a := range ms.a.Alarms() {
- resp.Errors = append(resp.Errors, a.String())
- }
- return resp, nil
-}
-
-func (ms *maintenanceServer) MoveLeader(ctx context.Context, tr *pb.MoveLeaderRequest) (*pb.MoveLeaderResponse, error) {
- if ms.rg.ID() != ms.rg.Leader() {
- return nil, rpctypes.ErrGRPCNotLeader
- }
-
- if err := ms.lt.MoveLeader(ctx, uint64(ms.rg.Leader()), tr.TargetID); err != nil {
- return nil, togRPCError(err)
- }
- return &pb.MoveLeaderResponse{}, nil
-}
-
-type authMaintenanceServer struct {
- *maintenanceServer
- ag AuthGetter
-}
-
-func (ams *authMaintenanceServer) isAuthenticated(ctx context.Context) error {
- authInfo, err := ams.ag.AuthInfoFromCtx(ctx)
- if err != nil {
- return err
- }
-
- return ams.ag.AuthStore().IsAdminPermitted(authInfo)
-}
-
-func (ams *authMaintenanceServer) Defragment(ctx context.Context, sr *pb.DefragmentRequest) (*pb.DefragmentResponse, error) {
- if err := ams.isAuthenticated(ctx); err != nil {
- return nil, err
- }
-
- return ams.maintenanceServer.Defragment(ctx, sr)
-}
-
-func (ams *authMaintenanceServer) Snapshot(sr *pb.SnapshotRequest, srv pb.Maintenance_SnapshotServer) error {
- if err := ams.isAuthenticated(srv.Context()); err != nil {
- return err
- }
-
- return ams.maintenanceServer.Snapshot(sr, srv)
-}
-
-func (ams *authMaintenanceServer) Hash(ctx context.Context, r *pb.HashRequest) (*pb.HashResponse, error) {
- if err := ams.isAuthenticated(ctx); err != nil {
- return nil, err
- }
-
- return ams.maintenanceServer.Hash(ctx, r)
-}
-
-func (ams *authMaintenanceServer) HashKV(ctx context.Context, r *pb.HashKVRequest) (*pb.HashKVResponse, error) {
- if err := ams.isAuthenticated(ctx); err != nil {
- return nil, err
- }
- return ams.maintenanceServer.HashKV(ctx, r)
-}
-
-func (ams *authMaintenanceServer) Status(ctx context.Context, ar *pb.StatusRequest) (*pb.StatusResponse, error) {
- return ams.maintenanceServer.Status(ctx, ar)
-}
-
-func (ams *authMaintenanceServer) MoveLeader(ctx context.Context, tr *pb.MoveLeaderRequest) (*pb.MoveLeaderResponse, error) {
- return ams.maintenanceServer.MoveLeader(ctx, tr)
-}
diff --git a/vendor/go.etcd.io/etcd/etcdserver/api/v3rpc/member.go b/vendor/go.etcd.io/etcd/etcdserver/api/v3rpc/member.go
deleted file mode 100644
index b2ebc98..0000000
--- a/vendor/go.etcd.io/etcd/etcdserver/api/v3rpc/member.go
+++ /dev/null
@@ -1,119 +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 v3rpc
-
-import (
- "context"
- "time"
-
- "go.etcd.io/etcd/etcdserver"
- "go.etcd.io/etcd/etcdserver/api"
- "go.etcd.io/etcd/etcdserver/api/membership"
- "go.etcd.io/etcd/etcdserver/api/v3rpc/rpctypes"
- pb "go.etcd.io/etcd/etcdserver/etcdserverpb"
- "go.etcd.io/etcd/pkg/types"
-)
-
-type ClusterServer struct {
- cluster api.Cluster
- server etcdserver.ServerV3
-}
-
-func NewClusterServer(s etcdserver.ServerV3) *ClusterServer {
- return &ClusterServer{
- cluster: s.Cluster(),
- server: s,
- }
-}
-
-func (cs *ClusterServer) MemberAdd(ctx context.Context, r *pb.MemberAddRequest) (*pb.MemberAddResponse, error) {
- urls, err := types.NewURLs(r.PeerURLs)
- if err != nil {
- return nil, rpctypes.ErrGRPCMemberBadURLs
- }
-
- now := time.Now()
- var m *membership.Member
- if r.IsLearner {
- m = membership.NewMemberAsLearner("", urls, "", &now)
- } else {
- m = membership.NewMember("", urls, "", &now)
- }
- membs, merr := cs.server.AddMember(ctx, *m)
- if merr != nil {
- return nil, togRPCError(merr)
- }
-
- return &pb.MemberAddResponse{
- Header: cs.header(),
- Member: &pb.Member{
- ID: uint64(m.ID),
- PeerURLs: m.PeerURLs,
- IsLearner: m.IsLearner,
- },
- Members: membersToProtoMembers(membs),
- }, nil
-}
-
-func (cs *ClusterServer) MemberRemove(ctx context.Context, r *pb.MemberRemoveRequest) (*pb.MemberRemoveResponse, error) {
- membs, err := cs.server.RemoveMember(ctx, r.ID)
- if err != nil {
- return nil, togRPCError(err)
- }
- return &pb.MemberRemoveResponse{Header: cs.header(), Members: membersToProtoMembers(membs)}, nil
-}
-
-func (cs *ClusterServer) MemberUpdate(ctx context.Context, r *pb.MemberUpdateRequest) (*pb.MemberUpdateResponse, error) {
- m := membership.Member{
- ID: types.ID(r.ID),
- RaftAttributes: membership.RaftAttributes{PeerURLs: r.PeerURLs},
- }
- membs, err := cs.server.UpdateMember(ctx, m)
- if err != nil {
- return nil, togRPCError(err)
- }
- return &pb.MemberUpdateResponse{Header: cs.header(), Members: membersToProtoMembers(membs)}, nil
-}
-
-func (cs *ClusterServer) MemberList(ctx context.Context, r *pb.MemberListRequest) (*pb.MemberListResponse, error) {
- membs := membersToProtoMembers(cs.cluster.Members())
- return &pb.MemberListResponse{Header: cs.header(), Members: membs}, nil
-}
-
-func (cs *ClusterServer) MemberPromote(ctx context.Context, r *pb.MemberPromoteRequest) (*pb.MemberPromoteResponse, error) {
- membs, err := cs.server.PromoteMember(ctx, r.ID)
- if err != nil {
- return nil, togRPCError(err)
- }
- return &pb.MemberPromoteResponse{Header: cs.header(), Members: membersToProtoMembers(membs)}, nil
-}
-
-func (cs *ClusterServer) header() *pb.ResponseHeader {
- return &pb.ResponseHeader{ClusterId: uint64(cs.cluster.ID()), MemberId: uint64(cs.server.ID()), RaftTerm: cs.server.Term()}
-}
-
-func membersToProtoMembers(membs []*membership.Member) []*pb.Member {
- protoMembs := make([]*pb.Member, len(membs))
- for i := range membs {
- protoMembs[i] = &pb.Member{
- Name: membs[i].Name,
- ID: uint64(membs[i].ID),
- PeerURLs: membs[i].PeerURLs,
- ClientURLs: membs[i].ClientURLs,
- IsLearner: membs[i].IsLearner,
- }
- }
- return protoMembs
-}
diff --git a/vendor/go.etcd.io/etcd/etcdserver/api/v3rpc/metrics.go b/vendor/go.etcd.io/etcd/etcdserver/api/v3rpc/metrics.go
deleted file mode 100644
index d633d27..0000000
--- a/vendor/go.etcd.io/etcd/etcdserver/api/v3rpc/metrics.go
+++ /dev/null
@@ -1,48 +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 v3rpc
-
-import "github.com/prometheus/client_golang/prometheus"
-
-var (
- sentBytes = prometheus.NewCounter(prometheus.CounterOpts{
- Namespace: "etcd",
- Subsystem: "network",
- Name: "client_grpc_sent_bytes_total",
- Help: "The total number of bytes sent to grpc clients.",
- })
-
- receivedBytes = prometheus.NewCounter(prometheus.CounterOpts{
- Namespace: "etcd",
- Subsystem: "network",
- Name: "client_grpc_received_bytes_total",
- Help: "The total number of bytes received from grpc clients.",
- })
-
- streamFailures = prometheus.NewCounterVec(prometheus.CounterOpts{
- Namespace: "etcd",
- Subsystem: "network",
- Name: "server_stream_failures_total",
- Help: "The total number of stream failures from the local server.",
- },
- []string{"Type", "API"},
- )
-)
-
-func init() {
- prometheus.MustRegister(sentBytes)
- prometheus.MustRegister(receivedBytes)
- prometheus.MustRegister(streamFailures)
-}
diff --git a/vendor/go.etcd.io/etcd/etcdserver/api/v3rpc/quota.go b/vendor/go.etcd.io/etcd/etcdserver/api/v3rpc/quota.go
deleted file mode 100644
index a145b8b..0000000
--- a/vendor/go.etcd.io/etcd/etcdserver/api/v3rpc/quota.go
+++ /dev/null
@@ -1,90 +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 v3rpc
-
-import (
- "context"
-
- "go.etcd.io/etcd/etcdserver"
- "go.etcd.io/etcd/etcdserver/api/v3rpc/rpctypes"
- pb "go.etcd.io/etcd/etcdserver/etcdserverpb"
- "go.etcd.io/etcd/pkg/types"
-)
-
-type quotaKVServer struct {
- pb.KVServer
- qa quotaAlarmer
-}
-
-type quotaAlarmer struct {
- q etcdserver.Quota
- a Alarmer
- id types.ID
-}
-
-// check whether request satisfies the quota. If there is not enough space,
-// ignore request and raise the free space alarm.
-func (qa *quotaAlarmer) check(ctx context.Context, r interface{}) error {
- if qa.q.Available(r) {
- return nil
- }
- req := &pb.AlarmRequest{
- MemberID: uint64(qa.id),
- Action: pb.AlarmRequest_ACTIVATE,
- Alarm: pb.AlarmType_NOSPACE,
- }
- qa.a.Alarm(ctx, req)
- return rpctypes.ErrGRPCNoSpace
-}
-
-func NewQuotaKVServer(s *etcdserver.EtcdServer) pb.KVServer {
- return "aKVServer{
- NewKVServer(s),
- quotaAlarmer{etcdserver.NewBackendQuota(s, "kv"), s, s.ID()},
- }
-}
-
-func (s *quotaKVServer) Put(ctx context.Context, r *pb.PutRequest) (*pb.PutResponse, error) {
- if err := s.qa.check(ctx, r); err != nil {
- return nil, err
- }
- return s.KVServer.Put(ctx, r)
-}
-
-func (s *quotaKVServer) Txn(ctx context.Context, r *pb.TxnRequest) (*pb.TxnResponse, error) {
- if err := s.qa.check(ctx, r); err != nil {
- return nil, err
- }
- return s.KVServer.Txn(ctx, r)
-}
-
-type quotaLeaseServer struct {
- pb.LeaseServer
- qa quotaAlarmer
-}
-
-func (s *quotaLeaseServer) LeaseGrant(ctx context.Context, cr *pb.LeaseGrantRequest) (*pb.LeaseGrantResponse, error) {
- if err := s.qa.check(ctx, cr); err != nil {
- return nil, err
- }
- return s.LeaseServer.LeaseGrant(ctx, cr)
-}
-
-func NewQuotaLeaseServer(s *etcdserver.EtcdServer) pb.LeaseServer {
- return "aLeaseServer{
- NewLeaseServer(s),
- quotaAlarmer{etcdserver.NewBackendQuota(s, "lease"), s, s.ID()},
- }
-}
diff --git a/vendor/go.etcd.io/etcd/etcdserver/api/v3rpc/rpctypes/error.go b/vendor/go.etcd.io/etcd/etcdserver/api/v3rpc/rpctypes/error.go
index e6a2814..bc1ad7b 100644
--- a/vendor/go.etcd.io/etcd/etcdserver/api/v3rpc/rpctypes/error.go
+++ b/vendor/go.etcd.io/etcd/etcdserver/api/v3rpc/rpctypes/error.go
@@ -40,9 +40,6 @@
ErrGRPCMemberNotEnoughStarted = status.New(codes.FailedPrecondition, "etcdserver: re-configuration failed due to not enough started members").Err()
ErrGRPCMemberBadURLs = status.New(codes.InvalidArgument, "etcdserver: given member URLs are invalid").Err()
ErrGRPCMemberNotFound = status.New(codes.NotFound, "etcdserver: member not found").Err()
- ErrGRPCMemberNotLearner = status.New(codes.FailedPrecondition, "etcdserver: can only promote a learner member").Err()
- ErrGRPCLearnerNotReady = status.New(codes.FailedPrecondition, "etcdserver: can only promote a learner member which is in sync with leader").Err()
- ErrGRPCTooManyLearners = status.New(codes.FailedPrecondition, "etcdserver: too many learner members in cluster").Err()
ErrGRPCRequestTooLarge = status.New(codes.InvalidArgument, "etcdserver: request is too large").Err()
ErrGRPCRequestTooManyRequests = status.New(codes.ResourceExhausted, "etcdserver: too many requests").Err()
@@ -54,7 +51,6 @@
ErrGRPCUserNotFound = status.New(codes.FailedPrecondition, "etcdserver: user name not found").Err()
ErrGRPCRoleAlreadyExist = status.New(codes.FailedPrecondition, "etcdserver: role name already exists").Err()
ErrGRPCRoleNotFound = status.New(codes.FailedPrecondition, "etcdserver: role name not found").Err()
- ErrGRPCRoleEmpty = status.New(codes.InvalidArgument, "etcdserver: role name is empty").Err()
ErrGRPCAuthFailed = status.New(codes.InvalidArgument, "etcdserver: authentication failed, invalid user ID or password").Err()
ErrGRPCPermissionDenied = status.New(codes.PermissionDenied, "etcdserver: permission denied").Err()
ErrGRPCRoleNotGranted = status.New(codes.FailedPrecondition, "etcdserver: role is not granted to the user").Err()
@@ -73,8 +69,6 @@
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.Unavailable, "etcdserver: rpc not supported for learner").Err()
- ErrGRPCBadLeaderTransferee = status.New(codes.FailedPrecondition, "etcdserver: bad leader transferee").Err()
errStringToError = map[string]error{
ErrorDesc(ErrGRPCEmptyKey): ErrGRPCEmptyKey,
@@ -97,9 +91,6 @@
ErrorDesc(ErrGRPCMemberNotEnoughStarted): ErrGRPCMemberNotEnoughStarted,
ErrorDesc(ErrGRPCMemberBadURLs): ErrGRPCMemberBadURLs,
ErrorDesc(ErrGRPCMemberNotFound): ErrGRPCMemberNotFound,
- ErrorDesc(ErrGRPCMemberNotLearner): ErrGRPCMemberNotLearner,
- ErrorDesc(ErrGRPCLearnerNotReady): ErrGRPCLearnerNotReady,
- ErrorDesc(ErrGRPCTooManyLearners): ErrGRPCTooManyLearners,
ErrorDesc(ErrGRPCRequestTooLarge): ErrGRPCRequestTooLarge,
ErrorDesc(ErrGRPCRequestTooManyRequests): ErrGRPCRequestTooManyRequests,
@@ -111,7 +102,6 @@
ErrorDesc(ErrGRPCUserNotFound): ErrGRPCUserNotFound,
ErrorDesc(ErrGRPCRoleAlreadyExist): ErrGRPCRoleAlreadyExist,
ErrorDesc(ErrGRPCRoleNotFound): ErrGRPCRoleNotFound,
- ErrorDesc(ErrGRPCRoleEmpty): ErrGRPCRoleEmpty,
ErrorDesc(ErrGRPCAuthFailed): ErrGRPCAuthFailed,
ErrorDesc(ErrGRPCPermissionDenied): ErrGRPCPermissionDenied,
ErrorDesc(ErrGRPCRoleNotGranted): ErrGRPCRoleNotGranted,
@@ -122,7 +112,6 @@
ErrorDesc(ErrGRPCNoLeader): ErrGRPCNoLeader,
ErrorDesc(ErrGRPCNotLeader): ErrGRPCNotLeader,
- ErrorDesc(ErrGRPCLeaderChanged): ErrGRPCLeaderChanged,
ErrorDesc(ErrGRPCNotCapable): ErrGRPCNotCapable,
ErrorDesc(ErrGRPCStopped): ErrGRPCStopped,
ErrorDesc(ErrGRPCTimeout): ErrGRPCTimeout,
@@ -130,8 +119,6 @@
ErrorDesc(ErrGRPCTimeoutDueToConnectionLost): ErrGRPCTimeoutDueToConnectionLost,
ErrorDesc(ErrGRPCUnhealthy): ErrGRPCUnhealthy,
ErrorDesc(ErrGRPCCorrupt): ErrGRPCCorrupt,
- ErrorDesc(ErrGPRCNotSupportedForLearner): ErrGPRCNotSupportedForLearner,
- ErrorDesc(ErrGRPCBadLeaderTransferee): ErrGRPCBadLeaderTransferee,
}
)
@@ -156,9 +143,6 @@
ErrMemberNotEnoughStarted = Error(ErrGRPCMemberNotEnoughStarted)
ErrMemberBadURLs = Error(ErrGRPCMemberBadURLs)
ErrMemberNotFound = Error(ErrGRPCMemberNotFound)
- ErrMemberNotLearner = Error(ErrGRPCMemberNotLearner)
- ErrMemberLearnerNotReady = Error(ErrGRPCLearnerNotReady)
- ErrTooManyLearners = Error(ErrGRPCTooManyLearners)
ErrRequestTooLarge = Error(ErrGRPCRequestTooLarge)
ErrTooManyRequests = Error(ErrGRPCRequestTooManyRequests)
@@ -170,7 +154,6 @@
ErrUserNotFound = Error(ErrGRPCUserNotFound)
ErrRoleAlreadyExist = Error(ErrGRPCRoleAlreadyExist)
ErrRoleNotFound = Error(ErrGRPCRoleNotFound)
- ErrRoleEmpty = Error(ErrGRPCRoleEmpty)
ErrAuthFailed = Error(ErrGRPCAuthFailed)
ErrPermissionDenied = Error(ErrGRPCPermissionDenied)
ErrRoleNotGranted = Error(ErrGRPCRoleNotGranted)
@@ -189,7 +172,6 @@
ErrTimeoutDueToConnectionLost = Error(ErrGRPCTimeoutDueToConnectionLost)
ErrUnhealthy = Error(ErrGRPCUnhealthy)
ErrCorrupt = Error(ErrGRPCCorrupt)
- ErrBadLeaderTransferee = Error(ErrGRPCBadLeaderTransferee)
)
// EtcdError defines gRPC server errors.
diff --git a/vendor/go.etcd.io/etcd/etcdserver/api/v3rpc/rpctypes/md.go b/vendor/go.etcd.io/etcd/etcdserver/api/v3rpc/rpctypes/md.go
index 5c590e1..90b8b83 100644
--- a/vendor/go.etcd.io/etcd/etcdserver/api/v3rpc/rpctypes/md.go
+++ b/vendor/go.etcd.io/etcd/etcdserver/api/v3rpc/rpctypes/md.go
@@ -17,4 +17,6 @@
var (
MetadataRequireLeaderKey = "hasleader"
MetadataHasLeader = "true"
+
+ MetadataClientAPIVersionKey = "client-api-version"
)
diff --git a/vendor/go.etcd.io/etcd/etcdserver/api/v3rpc/util.go b/vendor/go.etcd.io/etcd/etcdserver/api/v3rpc/util.go
deleted file mode 100644
index 281ddc7..0000000
--- a/vendor/go.etcd.io/etcd/etcdserver/api/v3rpc/util.go
+++ /dev/null
@@ -1,136 +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 v3rpc
-
-import (
- "context"
- "strings"
-
- "go.etcd.io/etcd/auth"
- "go.etcd.io/etcd/etcdserver"
- "go.etcd.io/etcd/etcdserver/api/membership"
- "go.etcd.io/etcd/etcdserver/api/v3rpc/rpctypes"
- pb "go.etcd.io/etcd/etcdserver/etcdserverpb"
- "go.etcd.io/etcd/lease"
- "go.etcd.io/etcd/mvcc"
-
- "google.golang.org/grpc/codes"
- "google.golang.org/grpc/status"
-)
-
-var toGRPCErrorMap = map[error]error{
- membership.ErrIDRemoved: rpctypes.ErrGRPCMemberNotFound,
- membership.ErrIDNotFound: rpctypes.ErrGRPCMemberNotFound,
- membership.ErrIDExists: rpctypes.ErrGRPCMemberExist,
- membership.ErrPeerURLexists: rpctypes.ErrGRPCPeerURLExist,
- membership.ErrMemberNotLearner: rpctypes.ErrGRPCMemberNotLearner,
- membership.ErrTooManyLearners: rpctypes.ErrGRPCTooManyLearners,
- etcdserver.ErrNotEnoughStartedMembers: rpctypes.ErrMemberNotEnoughStarted,
- etcdserver.ErrLearnerNotReady: rpctypes.ErrGRPCLearnerNotReady,
-
- mvcc.ErrCompacted: rpctypes.ErrGRPCCompacted,
- mvcc.ErrFutureRev: rpctypes.ErrGRPCFutureRev,
- etcdserver.ErrRequestTooLarge: rpctypes.ErrGRPCRequestTooLarge,
- etcdserver.ErrNoSpace: rpctypes.ErrGRPCNoSpace,
- etcdserver.ErrTooManyRequests: rpctypes.ErrTooManyRequests,
-
- etcdserver.ErrNoLeader: rpctypes.ErrGRPCNoLeader,
- etcdserver.ErrNotLeader: rpctypes.ErrGRPCNotLeader,
- etcdserver.ErrLeaderChanged: rpctypes.ErrGRPCLeaderChanged,
- etcdserver.ErrStopped: rpctypes.ErrGRPCStopped,
- etcdserver.ErrTimeout: rpctypes.ErrGRPCTimeout,
- etcdserver.ErrTimeoutDueToLeaderFail: rpctypes.ErrGRPCTimeoutDueToLeaderFail,
- etcdserver.ErrTimeoutDueToConnectionLost: rpctypes.ErrGRPCTimeoutDueToConnectionLost,
- etcdserver.ErrUnhealthy: rpctypes.ErrGRPCUnhealthy,
- etcdserver.ErrKeyNotFound: rpctypes.ErrGRPCKeyNotFound,
- etcdserver.ErrCorrupt: rpctypes.ErrGRPCCorrupt,
- etcdserver.ErrBadLeaderTransferee: rpctypes.ErrGRPCBadLeaderTransferee,
-
- lease.ErrLeaseNotFound: rpctypes.ErrGRPCLeaseNotFound,
- lease.ErrLeaseExists: rpctypes.ErrGRPCLeaseExist,
- lease.ErrLeaseTTLTooLarge: rpctypes.ErrGRPCLeaseTTLTooLarge,
-
- auth.ErrRootUserNotExist: rpctypes.ErrGRPCRootUserNotExist,
- auth.ErrRootRoleNotExist: rpctypes.ErrGRPCRootRoleNotExist,
- auth.ErrUserAlreadyExist: rpctypes.ErrGRPCUserAlreadyExist,
- auth.ErrUserEmpty: rpctypes.ErrGRPCUserEmpty,
- auth.ErrUserNotFound: rpctypes.ErrGRPCUserNotFound,
- auth.ErrRoleAlreadyExist: rpctypes.ErrGRPCRoleAlreadyExist,
- auth.ErrRoleNotFound: rpctypes.ErrGRPCRoleNotFound,
- auth.ErrRoleEmpty: rpctypes.ErrGRPCRoleEmpty,
- auth.ErrAuthFailed: rpctypes.ErrGRPCAuthFailed,
- auth.ErrPermissionDenied: rpctypes.ErrGRPCPermissionDenied,
- auth.ErrRoleNotGranted: rpctypes.ErrGRPCRoleNotGranted,
- auth.ErrPermissionNotGranted: rpctypes.ErrGRPCPermissionNotGranted,
- auth.ErrAuthNotEnabled: rpctypes.ErrGRPCAuthNotEnabled,
- auth.ErrInvalidAuthToken: rpctypes.ErrGRPCInvalidAuthToken,
- auth.ErrInvalidAuthMgmt: rpctypes.ErrGRPCInvalidAuthMgmt,
-}
-
-func togRPCError(err error) error {
- // let gRPC server convert to codes.Canceled, codes.DeadlineExceeded
- if err == context.Canceled || err == context.DeadlineExceeded {
- return err
- }
- grpcErr, ok := toGRPCErrorMap[err]
- if !ok {
- return status.Error(codes.Unknown, err.Error())
- }
- return grpcErr
-}
-
-func isClientCtxErr(ctxErr error, err error) bool {
- if ctxErr != nil {
- return true
- }
-
- ev, ok := status.FromError(err)
- if !ok {
- return false
- }
-
- switch ev.Code() {
- case codes.Canceled, codes.DeadlineExceeded:
- // client-side context cancel or deadline exceeded
- // "rpc error: code = Canceled desc = context canceled"
- // "rpc error: code = DeadlineExceeded desc = context deadline exceeded"
- return true
- case codes.Unavailable:
- msg := ev.Message()
- // client-side context cancel or deadline exceeded with TLS ("http2.errClientDisconnected")
- // "rpc error: code = Unavailable desc = client disconnected"
- if msg == "client disconnected" {
- return true
- }
- // "grpc/transport.ClientTransport.CloseStream" on canceled streams
- // "rpc error: code = Unavailable desc = stream error: stream ID 21; CANCEL")
- if strings.HasPrefix(msg, "stream error: ") && strings.HasSuffix(msg, "; CANCEL") {
- return true
- }
- }
- return false
-}
-
-// in v3.4, learner is allowed to serve serializable read and endpoint status
-func isRPCSupportedForLearner(req interface{}) bool {
- switch r := req.(type) {
- case *pb.StatusRequest:
- return true
- case *pb.RangeRequest:
- return r.Serializable
- default:
- return false
- }
-}
diff --git a/vendor/go.etcd.io/etcd/etcdserver/api/v3rpc/watch.go b/vendor/go.etcd.io/etcd/etcdserver/api/v3rpc/watch.go
deleted file mode 100644
index f41cb6c..0000000
--- a/vendor/go.etcd.io/etcd/etcdserver/api/v3rpc/watch.go
+++ /dev/null
@@ -1,584 +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 v3rpc
-
-import (
- "context"
- "io"
- "math/rand"
- "sync"
- "time"
-
- "go.etcd.io/etcd/auth"
- "go.etcd.io/etcd/etcdserver"
- "go.etcd.io/etcd/etcdserver/api/v3rpc/rpctypes"
- pb "go.etcd.io/etcd/etcdserver/etcdserverpb"
- "go.etcd.io/etcd/mvcc"
- "go.etcd.io/etcd/mvcc/mvccpb"
-
- "go.uber.org/zap"
-)
-
-type watchServer struct {
- lg *zap.Logger
-
- clusterID int64
- memberID int64
-
- maxRequestBytes int
-
- sg etcdserver.RaftStatusGetter
- watchable mvcc.WatchableKV
- ag AuthGetter
-}
-
-// NewWatchServer returns a new watch server.
-func NewWatchServer(s *etcdserver.EtcdServer) pb.WatchServer {
- return &watchServer{
- lg: s.Cfg.Logger,
-
- clusterID: int64(s.Cluster().ID()),
- memberID: int64(s.ID()),
-
- maxRequestBytes: int(s.Cfg.MaxRequestBytes + grpcOverheadBytes),
-
- sg: s,
- watchable: s.Watchable(),
- ag: s,
- }
-}
-
-var (
- // External test can read this with GetProgressReportInterval()
- // and change this to a small value to finish fast with
- // SetProgressReportInterval().
- progressReportInterval = 10 * time.Minute
- progressReportIntervalMu sync.RWMutex
-)
-
-// GetProgressReportInterval returns the current progress report interval (for testing).
-func GetProgressReportInterval() time.Duration {
- progressReportIntervalMu.RLock()
- interval := progressReportInterval
- progressReportIntervalMu.RUnlock()
-
- // add rand(1/10*progressReportInterval) as jitter so that etcdserver will not
- // send progress notifications to watchers around the same time even when watchers
- // are created around the same time (which is common when a client restarts itself).
- jitter := time.Duration(rand.Int63n(int64(interval) / 10))
-
- return interval + jitter
-}
-
-// SetProgressReportInterval updates the current progress report interval (for testing).
-func SetProgressReportInterval(newTimeout time.Duration) {
- progressReportIntervalMu.Lock()
- progressReportInterval = newTimeout
- progressReportIntervalMu.Unlock()
-}
-
-// We send ctrl response inside the read loop. We do not want
-// send to block read, but we still want ctrl response we sent to
-// be serialized. Thus we use a buffered chan to solve the problem.
-// A small buffer should be OK for most cases, since we expect the
-// ctrl requests are infrequent.
-const ctrlStreamBufLen = 16
-
-// serverWatchStream is an etcd server side stream. It receives requests
-// from client side gRPC stream. It receives watch events from mvcc.WatchStream,
-// and creates responses that forwarded to gRPC stream.
-// It also forwards control message like watch created and canceled.
-type serverWatchStream struct {
- lg *zap.Logger
-
- clusterID int64
- memberID int64
-
- maxRequestBytes int
-
- sg etcdserver.RaftStatusGetter
- watchable mvcc.WatchableKV
- ag AuthGetter
-
- gRPCStream pb.Watch_WatchServer
- watchStream mvcc.WatchStream
- ctrlStream chan *pb.WatchResponse
-
- // mu protects progress, prevKV, fragment
- mu sync.RWMutex
- // tracks the watchID that stream might need to send progress to
- // TODO: combine progress and prevKV into a single struct?
- progress map[mvcc.WatchID]bool
- // record watch IDs that need return previous key-value pair
- prevKV map[mvcc.WatchID]bool
- // records fragmented watch IDs
- fragment map[mvcc.WatchID]bool
-
- // closec indicates the stream is closed.
- closec chan struct{}
-
- // wg waits for the send loop to complete
- wg sync.WaitGroup
-}
-
-func (ws *watchServer) Watch(stream pb.Watch_WatchServer) (err error) {
- sws := serverWatchStream{
- lg: ws.lg,
-
- clusterID: ws.clusterID,
- memberID: ws.memberID,
-
- maxRequestBytes: ws.maxRequestBytes,
-
- sg: ws.sg,
- watchable: ws.watchable,
- ag: ws.ag,
-
- gRPCStream: stream,
- watchStream: ws.watchable.NewWatchStream(),
- // chan for sending control response like watcher created and canceled.
- ctrlStream: make(chan *pb.WatchResponse, ctrlStreamBufLen),
-
- progress: make(map[mvcc.WatchID]bool),
- prevKV: make(map[mvcc.WatchID]bool),
- fragment: make(map[mvcc.WatchID]bool),
-
- closec: make(chan struct{}),
- }
-
- sws.wg.Add(1)
- go func() {
- sws.sendLoop()
- sws.wg.Done()
- }()
-
- errc := make(chan error, 1)
- // Ideally recvLoop would also use sws.wg to signal its completion
- // but when stream.Context().Done() is closed, the stream's recv
- // may continue to block since it uses a different context, leading to
- // deadlock when calling sws.close().
- go func() {
- if rerr := sws.recvLoop(); rerr != nil {
- if isClientCtxErr(stream.Context().Err(), rerr) {
- if sws.lg != nil {
- sws.lg.Debug("failed to receive watch request from gRPC stream", zap.Error(rerr))
- } else {
- plog.Debugf("failed to receive watch request from gRPC stream (%q)", rerr.Error())
- }
- } else {
- if sws.lg != nil {
- sws.lg.Warn("failed to receive watch request from gRPC stream", zap.Error(rerr))
- } else {
- plog.Warningf("failed to receive watch request from gRPC stream (%q)", rerr.Error())
- }
- streamFailures.WithLabelValues("receive", "watch").Inc()
- }
- errc <- rerr
- }
- }()
-
- select {
- case err = <-errc:
- close(sws.ctrlStream)
-
- case <-stream.Context().Done():
- err = stream.Context().Err()
- // the only server-side cancellation is noleader for now.
- if err == context.Canceled {
- err = rpctypes.ErrGRPCNoLeader
- }
- }
-
- sws.close()
- return err
-}
-
-func (sws *serverWatchStream) isWatchPermitted(wcr *pb.WatchCreateRequest) bool {
- authInfo, err := sws.ag.AuthInfoFromCtx(sws.gRPCStream.Context())
- if err != nil {
- return false
- }
- if authInfo == nil {
- // if auth is enabled, IsRangePermitted() can cause an error
- authInfo = &auth.AuthInfo{}
- }
- return sws.ag.AuthStore().IsRangePermitted(authInfo, wcr.Key, wcr.RangeEnd) == nil
-}
-
-func (sws *serverWatchStream) recvLoop() error {
- for {
- req, err := sws.gRPCStream.Recv()
- if err == io.EOF {
- return nil
- }
- if err != nil {
- return err
- }
-
- switch uv := req.RequestUnion.(type) {
- case *pb.WatchRequest_CreateRequest:
- if uv.CreateRequest == nil {
- break
- }
-
- creq := uv.CreateRequest
- if len(creq.Key) == 0 {
- // \x00 is the smallest key
- creq.Key = []byte{0}
- }
- if len(creq.RangeEnd) == 0 {
- // force nil since watchstream.Watch distinguishes
- // between nil and []byte{} for single key / >=
- creq.RangeEnd = nil
- }
- if len(creq.RangeEnd) == 1 && creq.RangeEnd[0] == 0 {
- // support >= key queries
- creq.RangeEnd = []byte{}
- }
-
- if !sws.isWatchPermitted(creq) {
- wr := &pb.WatchResponse{
- Header: sws.newResponseHeader(sws.watchStream.Rev()),
- WatchId: creq.WatchId,
- Canceled: true,
- Created: true,
- CancelReason: rpctypes.ErrGRPCPermissionDenied.Error(),
- }
-
- select {
- case sws.ctrlStream <- wr:
- case <-sws.closec:
- }
- return nil
- }
-
- filters := FiltersFromRequest(creq)
-
- wsrev := sws.watchStream.Rev()
- rev := creq.StartRevision
- if rev == 0 {
- rev = wsrev + 1
- }
- id, err := sws.watchStream.Watch(mvcc.WatchID(creq.WatchId), creq.Key, creq.RangeEnd, rev, filters...)
- if err == nil {
- sws.mu.Lock()
- if creq.ProgressNotify {
- sws.progress[id] = true
- }
- if creq.PrevKv {
- sws.prevKV[id] = true
- }
- if creq.Fragment {
- sws.fragment[id] = true
- }
- sws.mu.Unlock()
- }
- wr := &pb.WatchResponse{
- Header: sws.newResponseHeader(wsrev),
- WatchId: int64(id),
- Created: true,
- Canceled: err != nil,
- }
- if err != nil {
- wr.CancelReason = err.Error()
- }
- select {
- case sws.ctrlStream <- wr:
- case <-sws.closec:
- return nil
- }
-
- case *pb.WatchRequest_CancelRequest:
- if uv.CancelRequest != nil {
- id := uv.CancelRequest.WatchId
- err := sws.watchStream.Cancel(mvcc.WatchID(id))
- if err == nil {
- sws.ctrlStream <- &pb.WatchResponse{
- Header: sws.newResponseHeader(sws.watchStream.Rev()),
- WatchId: id,
- Canceled: true,
- }
- sws.mu.Lock()
- delete(sws.progress, mvcc.WatchID(id))
- delete(sws.prevKV, mvcc.WatchID(id))
- delete(sws.fragment, mvcc.WatchID(id))
- sws.mu.Unlock()
- }
- }
- case *pb.WatchRequest_ProgressRequest:
- if uv.ProgressRequest != nil {
- sws.ctrlStream <- &pb.WatchResponse{
- Header: sws.newResponseHeader(sws.watchStream.Rev()),
- WatchId: -1, // response is not associated with any WatchId and will be broadcast to all watch channels
- }
- }
- default:
- // we probably should not shutdown the entire stream when
- // receive an valid command.
- // so just do nothing instead.
- continue
- }
- }
-}
-
-func (sws *serverWatchStream) sendLoop() {
- // watch ids that are currently active
- ids := make(map[mvcc.WatchID]struct{})
- // watch responses pending on a watch id creation message
- pending := make(map[mvcc.WatchID][]*pb.WatchResponse)
-
- interval := GetProgressReportInterval()
- progressTicker := time.NewTicker(interval)
-
- defer func() {
- progressTicker.Stop()
- // drain the chan to clean up pending events
- for ws := range sws.watchStream.Chan() {
- mvcc.ReportEventReceived(len(ws.Events))
- }
- for _, wrs := range pending {
- for _, ws := range wrs {
- mvcc.ReportEventReceived(len(ws.Events))
- }
- }
- }()
-
- for {
- select {
- case wresp, ok := <-sws.watchStream.Chan():
- if !ok {
- return
- }
-
- // TODO: evs is []mvccpb.Event type
- // either return []*mvccpb.Event from the mvcc package
- // or define protocol buffer with []mvccpb.Event.
- evs := wresp.Events
- events := make([]*mvccpb.Event, len(evs))
- sws.mu.RLock()
- needPrevKV := sws.prevKV[wresp.WatchID]
- sws.mu.RUnlock()
- for i := range evs {
- events[i] = &evs[i]
- if needPrevKV {
- opt := mvcc.RangeOptions{Rev: evs[i].Kv.ModRevision - 1}
- r, err := sws.watchable.Range(evs[i].Kv.Key, nil, opt)
- if err == nil && len(r.KVs) != 0 {
- events[i].PrevKv = &(r.KVs[0])
- }
- }
- }
-
- canceled := wresp.CompactRevision != 0
- wr := &pb.WatchResponse{
- Header: sws.newResponseHeader(wresp.Revision),
- WatchId: int64(wresp.WatchID),
- Events: events,
- CompactRevision: wresp.CompactRevision,
- Canceled: canceled,
- }
-
- if _, okID := ids[wresp.WatchID]; !okID {
- // buffer if id not yet announced
- wrs := append(pending[wresp.WatchID], wr)
- pending[wresp.WatchID] = wrs
- continue
- }
-
- mvcc.ReportEventReceived(len(evs))
-
- sws.mu.RLock()
- fragmented, ok := sws.fragment[wresp.WatchID]
- sws.mu.RUnlock()
-
- var serr error
- if !fragmented && !ok {
- serr = sws.gRPCStream.Send(wr)
- } else {
- serr = sendFragments(wr, sws.maxRequestBytes, sws.gRPCStream.Send)
- }
-
- if serr != nil {
- if isClientCtxErr(sws.gRPCStream.Context().Err(), serr) {
- if sws.lg != nil {
- sws.lg.Debug("failed to send watch response to gRPC stream", zap.Error(serr))
- } else {
- plog.Debugf("failed to send watch response to gRPC stream (%q)", serr.Error())
- }
- } else {
- if sws.lg != nil {
- sws.lg.Warn("failed to send watch response to gRPC stream", zap.Error(serr))
- } else {
- plog.Warningf("failed to send watch response to gRPC stream (%q)", serr.Error())
- }
- streamFailures.WithLabelValues("send", "watch").Inc()
- }
- return
- }
-
- sws.mu.Lock()
- if len(evs) > 0 && sws.progress[wresp.WatchID] {
- // elide next progress update if sent a key update
- sws.progress[wresp.WatchID] = false
- }
- sws.mu.Unlock()
-
- case c, ok := <-sws.ctrlStream:
- if !ok {
- return
- }
-
- if err := sws.gRPCStream.Send(c); err != nil {
- if isClientCtxErr(sws.gRPCStream.Context().Err(), err) {
- if sws.lg != nil {
- sws.lg.Debug("failed to send watch control response to gRPC stream", zap.Error(err))
- } else {
- plog.Debugf("failed to send watch control response to gRPC stream (%q)", err.Error())
- }
- } else {
- if sws.lg != nil {
- sws.lg.Warn("failed to send watch control response to gRPC stream", zap.Error(err))
- } else {
- plog.Warningf("failed to send watch control response to gRPC stream (%q)", err.Error())
- }
- streamFailures.WithLabelValues("send", "watch").Inc()
- }
- return
- }
-
- // track id creation
- wid := mvcc.WatchID(c.WatchId)
- if c.Canceled {
- delete(ids, wid)
- continue
- }
- if c.Created {
- // flush buffered events
- ids[wid] = struct{}{}
- for _, v := range pending[wid] {
- mvcc.ReportEventReceived(len(v.Events))
- if err := sws.gRPCStream.Send(v); err != nil {
- if isClientCtxErr(sws.gRPCStream.Context().Err(), err) {
- if sws.lg != nil {
- sws.lg.Debug("failed to send pending watch response to gRPC stream", zap.Error(err))
- } else {
- plog.Debugf("failed to send pending watch response to gRPC stream (%q)", err.Error())
- }
- } else {
- if sws.lg != nil {
- sws.lg.Warn("failed to send pending watch response to gRPC stream", zap.Error(err))
- } else {
- plog.Warningf("failed to send pending watch response to gRPC stream (%q)", err.Error())
- }
- streamFailures.WithLabelValues("send", "watch").Inc()
- }
- return
- }
- }
- delete(pending, wid)
- }
-
- case <-progressTicker.C:
- sws.mu.Lock()
- for id, ok := range sws.progress {
- if ok {
- sws.watchStream.RequestProgress(id)
- }
- sws.progress[id] = true
- }
- sws.mu.Unlock()
-
- case <-sws.closec:
- return
- }
- }
-}
-
-func sendFragments(
- wr *pb.WatchResponse,
- maxRequestBytes int,
- sendFunc func(*pb.WatchResponse) error) error {
- // no need to fragment if total request size is smaller
- // than max request limit or response contains only one event
- if wr.Size() < maxRequestBytes || len(wr.Events) < 2 {
- return sendFunc(wr)
- }
-
- ow := *wr
- ow.Events = make([]*mvccpb.Event, 0)
- ow.Fragment = true
-
- var idx int
- for {
- cur := ow
- for _, ev := range wr.Events[idx:] {
- cur.Events = append(cur.Events, ev)
- if len(cur.Events) > 1 && cur.Size() >= maxRequestBytes {
- cur.Events = cur.Events[:len(cur.Events)-1]
- break
- }
- idx++
- }
- if idx == len(wr.Events) {
- // last response has no more fragment
- cur.Fragment = false
- }
- if err := sendFunc(&cur); err != nil {
- return err
- }
- if !cur.Fragment {
- break
- }
- }
- return nil
-}
-
-func (sws *serverWatchStream) close() {
- sws.watchStream.Close()
- close(sws.closec)
- sws.wg.Wait()
-}
-
-func (sws *serverWatchStream) newResponseHeader(rev int64) *pb.ResponseHeader {
- return &pb.ResponseHeader{
- ClusterId: uint64(sws.clusterID),
- MemberId: uint64(sws.memberID),
- Revision: rev,
- RaftTerm: sws.sg.Term(),
- }
-}
-
-func filterNoDelete(e mvccpb.Event) bool {
- return e.Type == mvccpb.DELETE
-}
-
-func filterNoPut(e mvccpb.Event) bool {
- return e.Type == mvccpb.PUT
-}
-
-// FiltersFromRequest returns "mvcc.FilterFunc" from a given watch create request.
-func FiltersFromRequest(creq *pb.WatchCreateRequest) []mvcc.FilterFunc {
- filters := make([]mvcc.FilterFunc, 0, len(creq.Filters))
- for _, ft := range creq.Filters {
- switch ft {
- case pb.WatchCreateRequest_NOPUT:
- filters = append(filters, filterNoPut)
- case pb.WatchCreateRequest_NODELETE:
- filters = append(filters, filterNoDelete)
- default:
- }
- }
- return filters
-}