Update vendor package github.com/coreos/...
This commit is contained in:
7
vendor/github.com/coreos/etcd/clientv3/concurrency/mutex.go
generated
vendored
7
vendor/github.com/coreos/etcd/clientv3/concurrency/mutex.go
generated
vendored
@@ -68,11 +68,10 @@ func (m *Mutex) Lock(ctx context.Context) error {
|
||||
|
||||
// wait for deletion revisions prior to myKey
|
||||
hdr, werr := waitDeletes(ctx, client, m.pfx, m.myRev-1)
|
||||
// release lock key if cancelled
|
||||
select {
|
||||
case <-ctx.Done():
|
||||
// release lock key if wait failed
|
||||
if werr != nil {
|
||||
m.Unlock(client.Ctx())
|
||||
default:
|
||||
} else {
|
||||
m.hdr = hdr
|
||||
}
|
||||
return werr
|
||||
|
||||
1
vendor/github.com/coreos/etcd/etcdserver/api/etcdhttp/BUILD
generated
vendored
1
vendor/github.com/coreos/etcd/etcdserver/api/etcdhttp/BUILD
generated
vendored
@@ -23,6 +23,7 @@ go_library(
|
||||
"//vendor/github.com/coreos/etcd/rafthttp:go_default_library",
|
||||
"//vendor/github.com/coreos/etcd/version:go_default_library",
|
||||
"//vendor/github.com/coreos/pkg/capnslog:go_default_library",
|
||||
"//vendor/github.com/prometheus/client_golang/prometheus:go_default_library",
|
||||
"//vendor/github.com/prometheus/client_golang/prometheus/promhttp:go_default_library",
|
||||
],
|
||||
)
|
||||
|
||||
32
vendor/github.com/coreos/etcd/etcdserver/api/etcdhttp/metrics.go
generated
vendored
32
vendor/github.com/coreos/etcd/etcdserver/api/etcdhttp/metrics.go
generated
vendored
@@ -24,6 +24,7 @@ import (
|
||||
"github.com/coreos/etcd/etcdserver/etcdserverpb"
|
||||
"github.com/coreos/etcd/raft"
|
||||
|
||||
"github.com/prometheus/client_golang/prometheus"
|
||||
"github.com/prometheus/client_golang/prometheus/promhttp"
|
||||
)
|
||||
|
||||
@@ -43,11 +44,6 @@ func HandlePrometheus(mux *http.ServeMux) {
|
||||
mux.Handle(pathMetrics, promhttp.Handler())
|
||||
}
|
||||
|
||||
// HandleHealth registers health handler on '/health'.
|
||||
func HandleHealth(mux *http.ServeMux, srv etcdserver.ServerV2) {
|
||||
mux.Handle(PathHealth, NewHealthHandler(func() Health { return checkHealth(srv) }))
|
||||
}
|
||||
|
||||
// NewHealthHandler handles '/health' requests.
|
||||
func NewHealthHandler(hfunc func() Health) http.HandlerFunc {
|
||||
return func(w http.ResponseWriter, r *http.Request) {
|
||||
@@ -67,6 +63,26 @@ func NewHealthHandler(hfunc func() Health) http.HandlerFunc {
|
||||
}
|
||||
}
|
||||
|
||||
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 {
|
||||
@@ -97,5 +113,11 @@ func checkHealth(srv etcdserver.ServerV2) Health {
|
||||
h.Health = "false"
|
||||
}
|
||||
}
|
||||
|
||||
if h.Health == "true" {
|
||||
healthSuccess.Inc()
|
||||
} else {
|
||||
healthFailed.Inc()
|
||||
}
|
||||
return h
|
||||
}
|
||||
|
||||
4
vendor/github.com/coreos/etcd/etcdserver/api/v3rpc/BUILD
generated
vendored
4
vendor/github.com/coreos/etcd/etcdserver/api/v3rpc/BUILD
generated
vendored
@@ -37,15 +37,17 @@ go_library(
|
||||
"//vendor/github.com/coreos/etcd/version:go_default_library",
|
||||
"//vendor/github.com/coreos/pkg/capnslog:go_default_library",
|
||||
"//vendor/github.com/gogo/protobuf/proto:go_default_library",
|
||||
"//vendor/github.com/grpc-ecosystem/go-grpc-middleware:go_default_library",
|
||||
"//vendor/github.com/grpc-ecosystem/go-grpc-prometheus:go_default_library",
|
||||
"//vendor/github.com/prometheus/client_golang/prometheus:go_default_library",
|
||||
"//vendor/go.uber.org/zap:go_default_library",
|
||||
"//vendor/google.golang.org/grpc:go_default_library",
|
||||
"//vendor/google.golang.org/grpc/codes:go_default_library",
|
||||
"//vendor/google.golang.org/grpc/credentials:go_default_library",
|
||||
"//vendor/google.golang.org/grpc/grpclog:go_default_library",
|
||||
"//vendor/google.golang.org/grpc/health:go_default_library",
|
||||
"//vendor/google.golang.org/grpc/health/grpc_health_v1:go_default_library",
|
||||
"//vendor/google.golang.org/grpc/metadata:go_default_library",
|
||||
"//vendor/google.golang.org/grpc/peer:go_default_library",
|
||||
"//vendor/google.golang.org/grpc/status:go_default_library",
|
||||
],
|
||||
)
|
||||
|
||||
30
vendor/github.com/coreos/etcd/etcdserver/api/v3rpc/grpc.go
generated
vendored
30
vendor/github.com/coreos/etcd/etcdserver/api/v3rpc/grpc.go
generated
vendored
@@ -16,18 +16,15 @@ package v3rpc
|
||||
|
||||
import (
|
||||
"crypto/tls"
|
||||
"io/ioutil"
|
||||
"math"
|
||||
"os"
|
||||
"sync"
|
||||
|
||||
"github.com/coreos/etcd/etcdserver"
|
||||
pb "github.com/coreos/etcd/etcdserver/etcdserverpb"
|
||||
|
||||
"github.com/grpc-ecosystem/go-grpc-middleware"
|
||||
"github.com/grpc-ecosystem/go-grpc-prometheus"
|
||||
"google.golang.org/grpc"
|
||||
"google.golang.org/grpc/credentials"
|
||||
"google.golang.org/grpc/grpclog"
|
||||
"google.golang.org/grpc/health"
|
||||
healthpb "google.golang.org/grpc/health/grpc_health_v1"
|
||||
)
|
||||
@@ -38,17 +35,21 @@ const (
|
||||
maxSendBytes = math.MaxInt32
|
||||
)
|
||||
|
||||
// integration tests call this multiple times, which is racey in gRPC side
|
||||
var grpclogOnce sync.Once
|
||||
|
||||
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 {
|
||||
opts = append(opts, grpc.Creds(credentials.NewTLS(tls)))
|
||||
}
|
||||
opts = append(opts, grpc.UnaryInterceptor(newUnaryInterceptor(s)))
|
||||
opts = append(opts, grpc.StreamInterceptor(newStreamInterceptor(s)))
|
||||
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))
|
||||
@@ -71,16 +72,5 @@ func Server(s *etcdserver.EtcdServer, tls *tls.Config, gopts ...grpc.ServerOptio
|
||||
// set zero values for metrics registered for this grpc server
|
||||
grpc_prometheus.Register(grpcServer)
|
||||
|
||||
grpclogOnce.Do(func() {
|
||||
if s.Cfg.Debug {
|
||||
grpc.EnableTracing = true
|
||||
// enable info, warning, error
|
||||
grpclog.SetLoggerV2(grpclog.NewLoggerV2(os.Stderr, os.Stderr, os.Stderr))
|
||||
} else {
|
||||
// only discard info
|
||||
grpclog.SetLoggerV2(grpclog.NewLoggerV2(ioutil.Discard, os.Stderr, os.Stderr))
|
||||
}
|
||||
})
|
||||
|
||||
return grpcServer
|
||||
}
|
||||
|
||||
127
vendor/github.com/coreos/etcd/etcdserver/api/v3rpc/interceptor.go
generated
vendored
127
vendor/github.com/coreos/etcd/etcdserver/api/v3rpc/interceptor.go
generated
vendored
@@ -25,9 +25,11 @@ import (
|
||||
"github.com/coreos/etcd/pkg/types"
|
||||
"github.com/coreos/etcd/raft"
|
||||
|
||||
prometheus "github.com/grpc-ecosystem/go-grpc-prometheus"
|
||||
pb "github.com/coreos/etcd/etcdserver/etcdserverpb"
|
||||
"go.uber.org/zap"
|
||||
"google.golang.org/grpc"
|
||||
"google.golang.org/grpc/metadata"
|
||||
"google.golang.org/grpc/peer"
|
||||
)
|
||||
|
||||
const (
|
||||
@@ -40,7 +42,7 @@ type streamsMap struct {
|
||||
}
|
||||
|
||||
func newUnaryInterceptor(s *etcdserver.EtcdServer) grpc.UnaryServerInterceptor {
|
||||
return func(ctx context.Context, req interface{}, info *grpc.UnaryServerInfo, handler grpc.UnaryHandler) (resp interface{}, err error) {
|
||||
return func(ctx context.Context, req interface{}, info *grpc.UnaryServerInfo, handler grpc.UnaryHandler) (interface{}, error) {
|
||||
if !api.IsCapabilityEnabled(api.V3rpcCapability) {
|
||||
return nil, rpctypes.ErrGRPCNotCapable
|
||||
}
|
||||
@@ -54,7 +56,124 @@ func newUnaryInterceptor(s *etcdserver.EtcdServer) grpc.UnaryServerInterceptor {
|
||||
}
|
||||
}
|
||||
|
||||
return prometheus.UnaryServerInterceptor(ctx, req, info, handler)
|
||||
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)
|
||||
defer logUnaryRequestStats(ctx, nil, 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()
|
||||
}
|
||||
var responseType string = 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),
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -90,7 +209,7 @@ func newStreamInterceptor(s *etcdserver.EtcdServer) grpc.StreamServerInterceptor
|
||||
}
|
||||
}
|
||||
|
||||
return prometheus.StreamServerInterceptor(srv, ss, info, handler)
|
||||
return handler(srv, ss)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
6
vendor/github.com/coreos/etcd/etcdserver/etcdserverpb/raft_internal_stringer.go
generated
vendored
6
vendor/github.com/coreos/etcd/etcdserver/etcdserverpb/raft_internal_stringer.go
generated
vendored
@@ -59,7 +59,7 @@ func (as *InternalRaftStringer) String() string {
|
||||
case as.Request.Put != nil:
|
||||
return fmt.Sprintf("header:<%s> put:<%s>",
|
||||
as.Request.Header.String(),
|
||||
newLoggablePutRequest(as.Request.Put).String(),
|
||||
NewLoggablePutRequest(as.Request.Put).String(),
|
||||
)
|
||||
case as.Request.Txn != nil:
|
||||
return fmt.Sprintf("header:<%s> txn:<%s>",
|
||||
@@ -121,7 +121,7 @@ func newLoggableRequestOp(op *RequestOp) *requestOpStringer {
|
||||
func (as *requestOpStringer) String() string {
|
||||
switch op := as.Op.Request.(type) {
|
||||
case *RequestOp_RequestPut:
|
||||
return fmt.Sprintf("request_put:<%s>", newLoggablePutRequest(op.RequestPut).String())
|
||||
return fmt.Sprintf("request_put:<%s>", NewLoggablePutRequest(op.RequestPut).String())
|
||||
case *RequestOp_RequestTxn:
|
||||
return fmt.Sprintf("request_txn:<%s>", NewLoggableTxnRequest(op.RequestTxn).String())
|
||||
default:
|
||||
@@ -167,7 +167,7 @@ type loggablePutRequest struct {
|
||||
IgnoreLease bool `protobuf:"varint,6,opt,name=ignore_lease,proto3"`
|
||||
}
|
||||
|
||||
func newLoggablePutRequest(request *PutRequest) *loggablePutRequest {
|
||||
func NewLoggablePutRequest(request *PutRequest) *loggablePutRequest {
|
||||
return &loggablePutRequest{
|
||||
request.Key,
|
||||
len(request.Value),
|
||||
|
||||
15
vendor/github.com/coreos/etcd/etcdserver/metrics.go
generated
vendored
15
vendor/github.com/coreos/etcd/etcdserver/metrics.go
generated
vendored
@@ -90,6 +90,12 @@ var (
|
||||
Name: "slow_read_indexes_total",
|
||||
Help: "The total number of pending read indexes not in sync with leader's or timed out read index requests.",
|
||||
})
|
||||
readIndexFailed = prometheus.NewCounter(prometheus.CounterOpts{
|
||||
Namespace: "etcd",
|
||||
Subsystem: "server",
|
||||
Name: "read_indexes_failed_total",
|
||||
Help: "The total number of failed read indexes seen.",
|
||||
})
|
||||
quotaBackendBytes = prometheus.NewGauge(prometheus.GaugeOpts{
|
||||
Namespace: "etcd",
|
||||
Subsystem: "server",
|
||||
@@ -110,6 +116,13 @@ var (
|
||||
Help: "Which Go version server is running with. 1 for 'server_go_version' label with current version.",
|
||||
},
|
||||
[]string{"server_go_version"})
|
||||
serverID = prometheus.NewGaugeVec(prometheus.GaugeOpts{
|
||||
Namespace: "etcd",
|
||||
Subsystem: "server",
|
||||
Name: "id",
|
||||
Help: "Server or member ID in hexadecimal format. 1 for 'server_id' label with current ID.",
|
||||
},
|
||||
[]string{"server_id"})
|
||||
)
|
||||
|
||||
func init() {
|
||||
@@ -124,9 +137,11 @@ func init() {
|
||||
prometheus.MustRegister(proposalsFailed)
|
||||
prometheus.MustRegister(leaseExpired)
|
||||
prometheus.MustRegister(slowReadIndex)
|
||||
prometheus.MustRegister(readIndexFailed)
|
||||
prometheus.MustRegister(quotaBackendBytes)
|
||||
prometheus.MustRegister(currentVersion)
|
||||
prometheus.MustRegister(currentGoVersion)
|
||||
prometheus.MustRegister(serverID)
|
||||
|
||||
currentVersion.With(prometheus.Labels{
|
||||
"server_version": version.Version,
|
||||
|
||||
2
vendor/github.com/coreos/etcd/etcdserver/server.go
generated
vendored
2
vendor/github.com/coreos/etcd/etcdserver/server.go
generated
vendored
@@ -59,6 +59,7 @@ import (
|
||||
|
||||
"github.com/coreos/go-semver/semver"
|
||||
"github.com/coreos/pkg/capnslog"
|
||||
"github.com/prometheus/client_golang/prometheus"
|
||||
)
|
||||
|
||||
const (
|
||||
@@ -435,6 +436,7 @@ func NewServer(cfg ServerConfig) (srv *EtcdServer, err error) {
|
||||
reqIDGen: idutil.NewGenerator(uint16(id), time.Now()),
|
||||
forceVersionC: make(chan struct{}),
|
||||
}
|
||||
serverID.With(prometheus.Labels{"server_id": id.String()}).Set(1)
|
||||
|
||||
srv.applyV2 = &applierV2store{store: srv.store, cluster: srv.cluster}
|
||||
|
||||
|
||||
3
vendor/github.com/coreos/etcd/etcdserver/v3_server.go
generated
vendored
3
vendor/github.com/coreos/etcd/etcdserver/v3_server.go
generated
vendored
@@ -634,6 +634,7 @@ func (s *EtcdServer) linearizableReadLoop() {
|
||||
return
|
||||
}
|
||||
plog.Errorf("failed to get read index from raft: %v", err)
|
||||
readIndexFailed.Inc()
|
||||
nr.notify(err)
|
||||
continue
|
||||
}
|
||||
@@ -659,7 +660,7 @@ func (s *EtcdServer) linearizableReadLoop() {
|
||||
}
|
||||
|
||||
case <-time.After(s.Cfg.ReqTimeout()):
|
||||
plog.Warningf("timed out waiting for read index response")
|
||||
plog.Warningf("timed out waiting for read index response (local node might have slow network)")
|
||||
nr.notify(ErrTimeout)
|
||||
timeout = true
|
||||
slowReadIndex.Inc()
|
||||
|
||||
19
vendor/github.com/coreos/etcd/rafthttp/http.go
generated
vendored
19
vendor/github.com/coreos/etcd/rafthttp/http.go
generated
vendored
@@ -22,6 +22,7 @@ import (
|
||||
"net/http"
|
||||
"path"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
pioutil "github.com/coreos/etcd/pkg/ioutil"
|
||||
"github.com/coreos/etcd/pkg/types"
|
||||
@@ -149,6 +150,8 @@ func newSnapshotHandler(tr Transporter, r Raft, snapshotter *snap.Snapshotter, c
|
||||
}
|
||||
}
|
||||
|
||||
const unknownSnapshotSender = "UNKNOWN_SNAPSHOT_SENDER"
|
||||
|
||||
// ServeHTTP serves HTTP request to receive and process snapshot message.
|
||||
//
|
||||
// If request sender dies without closing underlying TCP connection,
|
||||
@@ -159,9 +162,12 @@ func newSnapshotHandler(tr Transporter, r Raft, snapshotter *snap.Snapshotter, c
|
||||
// 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
|
||||
}
|
||||
|
||||
@@ -169,6 +175,7 @@ func (h *snapshotHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
|
||||
|
||||
if err := checkClusterCompatibilityFromHeader(r.Header, h.cid); err != nil {
|
||||
http.Error(w, err.Error(), http.StatusPreconditionFailed)
|
||||
snapshotReceiveFailures.WithLabelValues(unknownSnapshotSender).Inc()
|
||||
return
|
||||
}
|
||||
|
||||
@@ -177,19 +184,22 @@ func (h *snapshotHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
|
||||
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)
|
||||
plog.Errorf(msg)
|
||||
http.Error(w, msg, http.StatusBadRequest)
|
||||
recvFailures.WithLabelValues(r.RemoteAddr).Inc()
|
||||
snapshotReceiveFailures.WithLabelValues(from).Inc()
|
||||
return
|
||||
}
|
||||
|
||||
receivedBytes.WithLabelValues(types.ID(m.From).String()).Add(float64(m.Size()))
|
||||
receivedBytes.WithLabelValues(from).Add(float64(m.Size()))
|
||||
|
||||
if m.Type != raftpb.MsgSnap {
|
||||
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
|
||||
}
|
||||
|
||||
@@ -200,9 +210,10 @@ func (h *snapshotHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
|
||||
msg := fmt.Sprintf("failed to save KV snapshot (%v)", err)
|
||||
plog.Error(msg)
|
||||
http.Error(w, msg, http.StatusInternalServerError)
|
||||
snapshotReceiveFailures.WithLabelValues(from).Inc()
|
||||
return
|
||||
}
|
||||
receivedBytes.WithLabelValues(types.ID(m.From).String()).Add(float64(n))
|
||||
receivedBytes.WithLabelValues(from).Add(float64(n))
|
||||
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 {
|
||||
@@ -215,12 +226,16 @@ func (h *snapshotHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
|
||||
msg := fmt.Sprintf("failed to process raft message (%v)", err)
|
||||
plog.Warningf(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 {
|
||||
|
||||
70
vendor/github.com/coreos/etcd/rafthttp/metrics.go
generated
vendored
70
vendor/github.com/coreos/etcd/rafthttp/metrics.go
generated
vendored
@@ -53,6 +53,68 @@ var (
|
||||
[]string{"From"},
|
||||
)
|
||||
|
||||
snapshotSend = prometheus.NewCounterVec(prometheus.CounterOpts{
|
||||
Namespace: "etcd",
|
||||
Subsystem: "network",
|
||||
Name: "snapshot_send_success",
|
||||
Help: "Total number of successful 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"},
|
||||
)
|
||||
|
||||
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"},
|
||||
)
|
||||
|
||||
rtts = prometheus.NewHistogramVec(prometheus.HistogramOpts{
|
||||
Namespace: "etcd",
|
||||
Subsystem: "network",
|
||||
@@ -69,5 +131,13 @@ func init() {
|
||||
prometheus.MustRegister(receivedBytes)
|
||||
prometheus.MustRegister(sentFailures)
|
||||
prometheus.MustRegister(recvFailures)
|
||||
|
||||
prometheus.MustRegister(snapshotSend)
|
||||
prometheus.MustRegister(snapshotSendFailures)
|
||||
prometheus.MustRegister(snapshotSendSeconds)
|
||||
prometheus.MustRegister(snapshotReceive)
|
||||
prometheus.MustRegister(snapshotReceiveFailures)
|
||||
prometheus.MustRegister(snapshotReceiveSeconds)
|
||||
|
||||
prometheus.MustRegister(rtts)
|
||||
}
|
||||
|
||||
2
vendor/github.com/coreos/etcd/rafthttp/peer_status.go
generated
vendored
2
vendor/github.com/coreos/etcd/rafthttp/peer_status.go
generated
vendored
@@ -56,7 +56,7 @@ func (s *peerStatus) deactivate(failure failureType, reason string) {
|
||||
msg := fmt.Sprintf("failed to %s %s on %s (%s)", failure.action, s.id, failure.source, reason)
|
||||
if s.active {
|
||||
plog.Errorf(msg)
|
||||
plog.Infof("peer %s became inactive", s.id)
|
||||
plog.Infof("peer %s became inactive (message send to peer failed)", s.id)
|
||||
s.active = false
|
||||
s.since = time.Time{}
|
||||
return
|
||||
|
||||
21
vendor/github.com/coreos/etcd/rafthttp/probing_status.go
generated
vendored
21
vendor/github.com/coreos/etcd/rafthttp/probing_status.go
generated
vendored
@@ -17,6 +17,7 @@ package rafthttp
|
||||
import (
|
||||
"time"
|
||||
|
||||
"github.com/prometheus/client_golang/prometheus"
|
||||
"github.com/xiang90/probing"
|
||||
)
|
||||
|
||||
@@ -28,7 +29,15 @@ var (
|
||||
statusErrorInterval = 5 * time.Second
|
||||
)
|
||||
|
||||
func addPeerToProber(p probing.Prober, id string, us []string) {
|
||||
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"
|
||||
)
|
||||
|
||||
func addPeerToProber(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
|
||||
@@ -40,26 +49,26 @@ func addPeerToProber(p probing.Prober, id string, us []string) {
|
||||
if err != nil {
|
||||
plog.Errorf("failed to add peer %s into prober", id)
|
||||
} else {
|
||||
go monitorProbingStatus(s, id)
|
||||
go monitorProbingStatus(s, id, roundTripperName, rttSecProm)
|
||||
}
|
||||
}
|
||||
|
||||
func monitorProbingStatus(s probing.Status, id string) {
|
||||
func monitorProbingStatus(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() {
|
||||
plog.Warningf("health check for peer %s could not connect: %v", id, s.Err())
|
||||
plog.Warningf("health check for peer %s could not connect: %v (prober %q)", id, s.Err(), roundTripperName)
|
||||
interval = statusErrorInterval
|
||||
} else {
|
||||
interval = statusMonitoringInterval
|
||||
}
|
||||
if s.ClockDiff() > time.Second {
|
||||
plog.Warningf("the clock difference against peer %s is too high [%v > %v]", id, s.ClockDiff(), time.Second)
|
||||
plog.Warningf("the clock difference against peer %s is too high [%v > %v] (prober %q)", id, s.ClockDiff(), time.Second, roundTripperName)
|
||||
}
|
||||
rtts.WithLabelValues(id).Observe(s.SRTT().Seconds())
|
||||
rttSecProm.WithLabelValues(id).Observe(s.SRTT().Seconds())
|
||||
case <-s.StopNotify():
|
||||
return
|
||||
}
|
||||
|
||||
11
vendor/github.com/coreos/etcd/rafthttp/snapshot_sender.go
generated
vendored
11
vendor/github.com/coreos/etcd/rafthttp/snapshot_sender.go
generated
vendored
@@ -64,7 +64,10 @@ func newSnapshotSender(tr *Transport, picker *urlPicker, to types.ID, status *pe
|
||||
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(merged)
|
||||
defer body.Close()
|
||||
@@ -92,14 +95,18 @@ func (s *snapshotSender) send(merged snap.Message) {
|
||||
// machine knows about it, it would pause a while and retry sending
|
||||
// new snapshot message.
|
||||
s.r.ReportSnapshot(m.To, raft.SnapshotFailure)
|
||||
sentFailures.WithLabelValues(types.ID(m.To).String()).Inc()
|
||||
sentFailures.WithLabelValues(to).Inc()
|
||||
snapshotSendFailures.WithLabelValues(to).Inc()
|
||||
return
|
||||
}
|
||||
s.status.activate()
|
||||
s.r.ReportSnapshot(m.To, raft.SnapshotFinish)
|
||||
plog.Infof("database snapshot [index: %d, to: %s] sent out successfully", m.Snapshot.Metadata.Index, types.ID(m.To))
|
||||
|
||||
sentBytes.WithLabelValues(types.ID(m.To).String()).Add(float64(merged.TotalSize))
|
||||
sentBytes.WithLabelValues(to).Add(float64(merged.TotalSize))
|
||||
|
||||
snapshotSend.WithLabelValues(to).Inc()
|
||||
snapshotSendSeconds.WithLabelValues(to).Observe(time.Since(start).Seconds())
|
||||
}
|
||||
|
||||
// post posts the given request.
|
||||
|
||||
22
vendor/github.com/coreos/etcd/rafthttp/transport.go
generated
vendored
22
vendor/github.com/coreos/etcd/rafthttp/transport.go
generated
vendored
@@ -127,7 +127,8 @@ type Transport struct {
|
||||
remotes map[types.ID]*remote // remotes map that helps newly joined member to catch up
|
||||
peers map[types.ID]Peer // peers map
|
||||
|
||||
prober probing.Prober
|
||||
pipelineProber probing.Prober
|
||||
streamProber probing.Prober
|
||||
}
|
||||
|
||||
func (t *Transport) Start() error {
|
||||
@@ -142,7 +143,8 @@ func (t *Transport) Start() error {
|
||||
}
|
||||
t.remotes = make(map[types.ID]*remote)
|
||||
t.peers = make(map[types.ID]Peer)
|
||||
t.prober = probing.NewProber(t.pipelineRt)
|
||||
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),
|
||||
@@ -210,7 +212,8 @@ func (t *Transport) Stop() {
|
||||
for _, p := range t.peers {
|
||||
p.stop()
|
||||
}
|
||||
t.prober.RemoveAll()
|
||||
t.pipelineProber.RemoveAll()
|
||||
t.streamProber.RemoveAll()
|
||||
if tr, ok := t.streamRt.(*http.Transport); ok {
|
||||
tr.CloseIdleConnections()
|
||||
}
|
||||
@@ -289,8 +292,8 @@ func (t *Transport) AddPeer(id types.ID, us []string) {
|
||||
}
|
||||
fs := t.LeaderStats.Follower(id.String())
|
||||
t.peers[id] = startPeer(t, urls, id, fs)
|
||||
addPeerToProber(t.prober, id.String(), us)
|
||||
|
||||
addPeerToProber(t.pipelineProber, id.String(), us, RoundTripperNameSnapshot, rtts)
|
||||
addPeerToProber(t.streamProber, id.String(), us, RoundTripperNameRaftMessage, rtts)
|
||||
plog.Infof("added peer %s", id)
|
||||
}
|
||||
|
||||
@@ -317,7 +320,8 @@ func (t *Transport) removePeer(id types.ID) {
|
||||
}
|
||||
delete(t.peers, id)
|
||||
delete(t.LeaderStats.Followers, id.String())
|
||||
t.prober.Remove(id.String())
|
||||
t.pipelineProber.Remove(id.String())
|
||||
t.streamProber.Remove(id.String())
|
||||
plog.Infof("removed peer %s", id)
|
||||
}
|
||||
|
||||
@@ -334,8 +338,10 @@ func (t *Transport) UpdatePeer(id types.ID, us []string) {
|
||||
}
|
||||
t.peers[id].update(urls)
|
||||
|
||||
t.prober.Remove(id.String())
|
||||
addPeerToProber(t.prober, id.String(), us)
|
||||
t.pipelineProber.Remove(id.String())
|
||||
addPeerToProber(t.pipelineProber, id.String(), us, RoundTripperNameSnapshot, rtts)
|
||||
t.streamProber.Remove(id.String())
|
||||
addPeerToProber(t.streamProber, id.String(), us, RoundTripperNameRaftMessage, rtts)
|
||||
plog.Infof("updated peer %s", id)
|
||||
}
|
||||
|
||||
|
||||
6
vendor/github.com/coreos/etcd/snap/db.go
generated
vendored
6
vendor/github.com/coreos/etcd/snap/db.go
generated
vendored
@@ -21,6 +21,7 @@ import (
|
||||
"io/ioutil"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"time"
|
||||
|
||||
"github.com/coreos/etcd/pkg/fileutil"
|
||||
)
|
||||
@@ -30,6 +31,8 @@ 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
|
||||
@@ -37,7 +40,9 @@ func (s *Snapshotter) SaveDBFrom(r io.Reader, id uint64) (int64, error) {
|
||||
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 {
|
||||
@@ -57,6 +62,7 @@ func (s *Snapshotter) SaveDBFrom(r io.Reader, id uint64) (int64, error) {
|
||||
|
||||
plog.Infof("saved database snapshot to disk [total bytes: %d]", n)
|
||||
|
||||
snapDBSaveSec.Observe(time.Since(start).Seconds())
|
||||
return n, nil
|
||||
}
|
||||
|
||||
|
||||
24
vendor/github.com/coreos/etcd/snap/metrics.go
generated
vendored
24
vendor/github.com/coreos/etcd/snap/metrics.go
generated
vendored
@@ -33,9 +33,33 @@ var (
|
||||
Help: "The marshalling cost distributions of save called by snapshot.",
|
||||
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(saveDurations)
|
||||
prometheus.MustRegister(marshallingDurations)
|
||||
prometheus.MustRegister(snapDBSaveSec)
|
||||
prometheus.MustRegister(snapDBFsyncSec)
|
||||
}
|
||||
|
||||
2
vendor/github.com/coreos/etcd/version/version.go
generated
vendored
2
vendor/github.com/coreos/etcd/version/version.go
generated
vendored
@@ -26,7 +26,7 @@ import (
|
||||
var (
|
||||
// MinClusterVersion is the min cluster version this etcd binary is compatible with.
|
||||
MinClusterVersion = "3.0.0"
|
||||
Version = "3.3.9"
|
||||
Version = "3.3.10"
|
||||
APIVersion = "unknown"
|
||||
|
||||
// Git SHA Value will be set during build
|
||||
|
||||
5
vendor/github.com/coreos/go-semver/NOTICE
generated
vendored
Normal file
5
vendor/github.com/coreos/go-semver/NOTICE
generated
vendored
Normal file
@@ -0,0 +1,5 @@
|
||||
CoreOS Project
|
||||
Copyright 2018 CoreOS, Inc
|
||||
|
||||
This product includes software developed at CoreOS, Inc.
|
||||
(http://www.coreos.com/).
|
||||
179
vendor/github.com/coreos/go-semver/semver/semver.go
generated
vendored
179
vendor/github.com/coreos/go-semver/semver/semver.go
generated
vendored
@@ -1,9 +1,25 @@
|
||||
// Copyright 2013-2015 CoreOS, Inc.
|
||||
//
|
||||
// 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.
|
||||
|
||||
// Semantic Versions http://semver.org
|
||||
package semver
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"errors"
|
||||
"fmt"
|
||||
"regexp"
|
||||
"strconv"
|
||||
"strings"
|
||||
)
|
||||
@@ -29,35 +45,21 @@ func splitOff(input *string, delim string) (val string) {
|
||||
return val
|
||||
}
|
||||
|
||||
func New(version string) *Version {
|
||||
return Must(NewVersion(version))
|
||||
}
|
||||
|
||||
func NewVersion(version string) (*Version, error) {
|
||||
v := Version{}
|
||||
|
||||
dotParts := strings.SplitN(version, ".", 3)
|
||||
|
||||
if len(dotParts) != 3 {
|
||||
return nil, errors.New(fmt.Sprintf("%s is not in dotted-tri format", version))
|
||||
if err := v.Set(version); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
v.Metadata = splitOff(&dotParts[2], "+")
|
||||
v.PreRelease = PreRelease(splitOff(&dotParts[2], "-"))
|
||||
|
||||
parsed := make([]int64, 3, 3)
|
||||
|
||||
for i, v := range dotParts[:3] {
|
||||
val, err := strconv.ParseInt(v, 10, 64)
|
||||
parsed[i] = val
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
|
||||
v.Major = parsed[0]
|
||||
v.Minor = parsed[1]
|
||||
v.Patch = parsed[2]
|
||||
|
||||
return &v, nil
|
||||
}
|
||||
|
||||
// Must is a helper for wrapping NewVersion and will panic if err is not nil.
|
||||
func Must(v *Version, err error) *Version {
|
||||
if err != nil {
|
||||
panic(err)
|
||||
@@ -65,45 +67,107 @@ func Must(v *Version, err error) *Version {
|
||||
return v
|
||||
}
|
||||
|
||||
func (v *Version) String() string {
|
||||
// Set parses and updates v from the given version string. Implements flag.Value
|
||||
func (v *Version) Set(version string) error {
|
||||
metadata := splitOff(&version, "+")
|
||||
preRelease := PreRelease(splitOff(&version, "-"))
|
||||
dotParts := strings.SplitN(version, ".", 3)
|
||||
|
||||
if len(dotParts) != 3 {
|
||||
return fmt.Errorf("%s is not in dotted-tri format", version)
|
||||
}
|
||||
|
||||
if err := validateIdentifier(string(preRelease)); err != nil {
|
||||
return fmt.Errorf("failed to validate pre-release: %v", err)
|
||||
}
|
||||
|
||||
if err := validateIdentifier(metadata); err != nil {
|
||||
return fmt.Errorf("failed to validate metadata: %v", err)
|
||||
}
|
||||
|
||||
parsed := make([]int64, 3, 3)
|
||||
|
||||
for i, v := range dotParts[:3] {
|
||||
val, err := strconv.ParseInt(v, 10, 64)
|
||||
parsed[i] = val
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
v.Metadata = metadata
|
||||
v.PreRelease = preRelease
|
||||
v.Major = parsed[0]
|
||||
v.Minor = parsed[1]
|
||||
v.Patch = parsed[2]
|
||||
return nil
|
||||
}
|
||||
|
||||
func (v Version) String() string {
|
||||
var buffer bytes.Buffer
|
||||
|
||||
base := fmt.Sprintf("%d.%d.%d", v.Major, v.Minor, v.Patch)
|
||||
buffer.WriteString(base)
|
||||
fmt.Fprintf(&buffer, "%d.%d.%d", v.Major, v.Minor, v.Patch)
|
||||
|
||||
if v.PreRelease != "" {
|
||||
buffer.WriteString(fmt.Sprintf("-%s", v.PreRelease))
|
||||
fmt.Fprintf(&buffer, "-%s", v.PreRelease)
|
||||
}
|
||||
|
||||
if v.Metadata != "" {
|
||||
buffer.WriteString(fmt.Sprintf("+%s", v.Metadata))
|
||||
fmt.Fprintf(&buffer, "+%s", v.Metadata)
|
||||
}
|
||||
|
||||
return buffer.String()
|
||||
}
|
||||
|
||||
func (v *Version) LessThan(versionB Version) bool {
|
||||
versionA := *v
|
||||
cmp := recursiveCompare(versionA.Slice(), versionB.Slice())
|
||||
|
||||
if cmp == 0 {
|
||||
cmp = preReleaseCompare(versionA, versionB)
|
||||
func (v *Version) UnmarshalYAML(unmarshal func(interface{}) error) error {
|
||||
var data string
|
||||
if err := unmarshal(&data); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if cmp == -1 {
|
||||
return true
|
||||
}
|
||||
|
||||
return false
|
||||
return v.Set(data)
|
||||
}
|
||||
|
||||
/* Slice converts the comparable parts of the semver into a slice of strings */
|
||||
func (v *Version) Slice() []int64 {
|
||||
func (v Version) MarshalJSON() ([]byte, error) {
|
||||
return []byte(`"` + v.String() + `"`), nil
|
||||
}
|
||||
|
||||
func (v *Version) UnmarshalJSON(data []byte) error {
|
||||
l := len(data)
|
||||
if l == 0 || string(data) == `""` {
|
||||
return nil
|
||||
}
|
||||
if l < 2 || data[0] != '"' || data[l-1] != '"' {
|
||||
return errors.New("invalid semver string")
|
||||
}
|
||||
return v.Set(string(data[1 : l-1]))
|
||||
}
|
||||
|
||||
// Compare tests if v is less than, equal to, or greater than versionB,
|
||||
// returning -1, 0, or +1 respectively.
|
||||
func (v Version) Compare(versionB Version) int {
|
||||
if cmp := recursiveCompare(v.Slice(), versionB.Slice()); cmp != 0 {
|
||||
return cmp
|
||||
}
|
||||
return preReleaseCompare(v, versionB)
|
||||
}
|
||||
|
||||
// Equal tests if v is equal to versionB.
|
||||
func (v Version) Equal(versionB Version) bool {
|
||||
return v.Compare(versionB) == 0
|
||||
}
|
||||
|
||||
// LessThan tests if v is less than versionB.
|
||||
func (v Version) LessThan(versionB Version) bool {
|
||||
return v.Compare(versionB) < 0
|
||||
}
|
||||
|
||||
// Slice converts the comparable parts of the semver into a slice of integers.
|
||||
func (v Version) Slice() []int64 {
|
||||
return []int64{v.Major, v.Minor, v.Patch}
|
||||
}
|
||||
|
||||
func (p *PreRelease) Slice() []string {
|
||||
preRelease := string(*p)
|
||||
func (p PreRelease) Slice() []string {
|
||||
preRelease := string(p)
|
||||
return strings.Split(preRelease, ".")
|
||||
}
|
||||
|
||||
@@ -119,7 +183,7 @@ func preReleaseCompare(versionA Version, versionB Version) int {
|
||||
return -1
|
||||
}
|
||||
|
||||
// If there is a prelease, check and compare each part.
|
||||
// If there is a prerelease, check and compare each part.
|
||||
return recursivePreReleaseCompare(a.Slice(), b.Slice())
|
||||
}
|
||||
|
||||
@@ -141,9 +205,12 @@ func recursiveCompare(versionA []int64, versionB []int64) int {
|
||||
}
|
||||
|
||||
func recursivePreReleaseCompare(versionA []string, versionB []string) int {
|
||||
// Handle slice length disparity.
|
||||
// A larger set of pre-release fields has a higher precedence than a smaller set,
|
||||
// if all of the preceding identifiers are equal.
|
||||
if len(versionA) == 0 {
|
||||
// Nothing to compare too, so we return 0
|
||||
if len(versionB) > 0 {
|
||||
return -1
|
||||
}
|
||||
return 0
|
||||
} else if len(versionB) == 0 {
|
||||
// We're longer than versionB so return 1.
|
||||
@@ -153,7 +220,8 @@ func recursivePreReleaseCompare(versionA []string, versionB []string) int {
|
||||
a := versionA[0]
|
||||
b := versionB[0]
|
||||
|
||||
aInt := false; bInt := false
|
||||
aInt := false
|
||||
bInt := false
|
||||
|
||||
aI, err := strconv.Atoi(versionA[0])
|
||||
if err == nil {
|
||||
@@ -165,6 +233,13 @@ func recursivePreReleaseCompare(versionA []string, versionB []string) int {
|
||||
bInt = true
|
||||
}
|
||||
|
||||
// Numeric identifiers always have lower precedence than non-numeric identifiers.
|
||||
if aInt && !bInt {
|
||||
return -1
|
||||
} else if !aInt && bInt {
|
||||
return 1
|
||||
}
|
||||
|
||||
// Handle Integer Comparison
|
||||
if aInt && bInt {
|
||||
if aI > bI {
|
||||
@@ -207,3 +282,15 @@ func (v *Version) BumpPatch() {
|
||||
v.PreRelease = PreRelease("")
|
||||
v.Metadata = ""
|
||||
}
|
||||
|
||||
// validateIdentifier makes sure the provided identifier satisfies semver spec
|
||||
func validateIdentifier(id string) error {
|
||||
if id != "" && !reIdentifier.MatchString(id) {
|
||||
return fmt.Errorf("%s is not a valid semver identifier", id)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// reIdentifier is a regular expression used to check that pre-release and metadata
|
||||
// identifiers satisfy the spec requirements
|
||||
var reIdentifier = regexp.MustCompile(`^[0-9A-Za-z-]+(\.[0-9A-Za-z-]+)*$`)
|
||||
|
||||
14
vendor/github.com/coreos/go-semver/semver/sort.go
generated
vendored
14
vendor/github.com/coreos/go-semver/semver/sort.go
generated
vendored
@@ -1,3 +1,17 @@
|
||||
// Copyright 2013-2015 CoreOS, Inc.
|
||||
//
|
||||
// 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 semver
|
||||
|
||||
import (
|
||||
|
||||
5
vendor/github.com/coreos/go-systemd/NOTICE
generated
vendored
Normal file
5
vendor/github.com/coreos/go-systemd/NOTICE
generated
vendored
Normal file
@@ -0,0 +1,5 @@
|
||||
CoreOS Project
|
||||
Copyright 2018 CoreOS, Inc
|
||||
|
||||
This product includes software developed at CoreOS, Inc.
|
||||
(http://www.coreos.com/).
|
||||
39
vendor/github.com/coreos/go-systemd/daemon/sdnotify.go
generated
vendored
39
vendor/github.com/coreos/go-systemd/daemon/sdnotify.go
generated
vendored
@@ -1,4 +1,5 @@
|
||||
// Copyright 2014 Docker, Inc.
|
||||
// Copyright 2015-2018 CoreOS, Inc.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
@@ -13,7 +14,11 @@
|
||||
// limitations under the License.
|
||||
//
|
||||
|
||||
// Code forked from Docker project
|
||||
// Package daemon provides a Go implementation of the sd_notify protocol.
|
||||
// It can be used to inform systemd of service start-up completion, watchdog
|
||||
// events, and other status changes.
|
||||
//
|
||||
// https://www.freedesktop.org/software/systemd/man/sd_notify.html#Description
|
||||
package daemon
|
||||
|
||||
import (
|
||||
@@ -21,6 +26,25 @@ import (
|
||||
"os"
|
||||
)
|
||||
|
||||
const (
|
||||
// SdNotifyReady tells the service manager that service startup is finished
|
||||
// or the service finished loading its configuration.
|
||||
SdNotifyReady = "READY=1"
|
||||
|
||||
// SdNotifyStopping tells the service manager that the service is beginning
|
||||
// its shutdown.
|
||||
SdNotifyStopping = "STOPPING=1"
|
||||
|
||||
// SdNotifyReloading tells the service manager that this service is
|
||||
// reloading its configuration. Note that you must call SdNotifyReady when
|
||||
// it completed reloading.
|
||||
SdNotifyReloading = "RELOADING=1"
|
||||
|
||||
// SdNotifyWatchdog tells the service manager to update the watchdog
|
||||
// timestamp for the service.
|
||||
SdNotifyWatchdog = "WATCHDOG=1"
|
||||
)
|
||||
|
||||
// SdNotify sends a message to the init daemon. It is common to ignore the error.
|
||||
// If `unsetEnvironment` is true, the environment variable `NOTIFY_SOCKET`
|
||||
// will be unconditionally unset.
|
||||
@@ -29,7 +53,7 @@ import (
|
||||
// (false, nil) - notification not supported (i.e. NOTIFY_SOCKET is unset)
|
||||
// (false, err) - notification supported, but failure happened (e.g. error connecting to NOTIFY_SOCKET or while sending data)
|
||||
// (true, nil) - notification supported, data has been sent
|
||||
func SdNotify(unsetEnvironment bool, state string) (sent bool, err error) {
|
||||
func SdNotify(unsetEnvironment bool, state string) (bool, error) {
|
||||
socketAddr := &net.UnixAddr{
|
||||
Name: os.Getenv("NOTIFY_SOCKET"),
|
||||
Net: "unixgram",
|
||||
@@ -41,10 +65,9 @@ func SdNotify(unsetEnvironment bool, state string) (sent bool, err error) {
|
||||
}
|
||||
|
||||
if unsetEnvironment {
|
||||
err = os.Unsetenv("NOTIFY_SOCKET")
|
||||
}
|
||||
if err != nil {
|
||||
return false, err
|
||||
if err := os.Unsetenv("NOTIFY_SOCKET"); err != nil {
|
||||
return false, err
|
||||
}
|
||||
}
|
||||
|
||||
conn, err := net.DialUnix(socketAddr.Net, nil, socketAddr)
|
||||
@@ -54,9 +77,7 @@ func SdNotify(unsetEnvironment bool, state string) (sent bool, err error) {
|
||||
}
|
||||
defer conn.Close()
|
||||
|
||||
_, err = conn.Write([]byte(state))
|
||||
// Error sending the message
|
||||
if err != nil {
|
||||
if _, err = conn.Write([]byte(state)); err != nil {
|
||||
return false, err
|
||||
}
|
||||
return true, nil
|
||||
|
||||
9
vendor/github.com/coreos/go-systemd/daemon/watchdog.go
generated
vendored
9
vendor/github.com/coreos/go-systemd/daemon/watchdog.go
generated
vendored
@@ -21,10 +21,11 @@ import (
|
||||
"time"
|
||||
)
|
||||
|
||||
// SdWatchdogEnabled return watchdog information for a service.
|
||||
// Process should send daemon.SdNotify("WATCHDOG=1") every time / 2.
|
||||
// If `unsetEnvironment` is true, the environment variables `WATCHDOG_USEC`
|
||||
// and `WATCHDOG_PID` will be unconditionally unset.
|
||||
// SdWatchdogEnabled returns watchdog information for a service.
|
||||
// Processes should call daemon.SdNotify(false, daemon.SdNotifyWatchdog) every
|
||||
// time / 2.
|
||||
// If `unsetEnvironment` is true, the environment variables `WATCHDOG_USEC` and
|
||||
// `WATCHDOG_PID` will be unconditionally unset.
|
||||
//
|
||||
// It returns one of the following:
|
||||
// (0, nil) - watchdog isn't enabled or we aren't the watched PID.
|
||||
|
||||
31
vendor/github.com/coreos/go-systemd/dbus/dbus.go
generated
vendored
31
vendor/github.com/coreos/go-systemd/dbus/dbus.go
generated
vendored
@@ -16,6 +16,7 @@
|
||||
package dbus
|
||||
|
||||
import (
|
||||
"encoding/hex"
|
||||
"fmt"
|
||||
"os"
|
||||
"strconv"
|
||||
@@ -60,6 +61,27 @@ func PathBusEscape(path string) string {
|
||||
return string(n)
|
||||
}
|
||||
|
||||
// pathBusUnescape is the inverse of PathBusEscape.
|
||||
func pathBusUnescape(path string) string {
|
||||
if path == "_" {
|
||||
return ""
|
||||
}
|
||||
n := []byte{}
|
||||
for i := 0; i < len(path); i++ {
|
||||
c := path[i]
|
||||
if c == '_' && i+2 < len(path) {
|
||||
res, err := hex.DecodeString(path[i+1 : i+3])
|
||||
if err == nil {
|
||||
n = append(n, res...)
|
||||
}
|
||||
i += 2
|
||||
} else {
|
||||
n = append(n, c)
|
||||
}
|
||||
}
|
||||
return string(n)
|
||||
}
|
||||
|
||||
// Conn is a connection to systemd's dbus endpoint.
|
||||
type Conn struct {
|
||||
// sysconn/sysobj are only used to call dbus methods
|
||||
@@ -74,13 +96,18 @@ type Conn struct {
|
||||
jobs map[dbus.ObjectPath]chan<- string
|
||||
sync.Mutex
|
||||
}
|
||||
subscriber struct {
|
||||
subStateSubscriber struct {
|
||||
updateCh chan<- *SubStateUpdate
|
||||
errCh chan<- error
|
||||
sync.Mutex
|
||||
ignore map[dbus.ObjectPath]int64
|
||||
cleanIgnore int64
|
||||
}
|
||||
propertiesSubscriber struct {
|
||||
updateCh chan<- *PropertiesUpdate
|
||||
errCh chan<- error
|
||||
sync.Mutex
|
||||
}
|
||||
}
|
||||
|
||||
// New establishes a connection to any available bus and authenticates.
|
||||
@@ -152,7 +179,7 @@ func NewConnection(dialBus func() (*dbus.Conn, error)) (*Conn, error) {
|
||||
sigobj: systemdObject(sigconn),
|
||||
}
|
||||
|
||||
c.subscriber.ignore = make(map[dbus.ObjectPath]int64)
|
||||
c.subStateSubscriber.ignore = make(map[dbus.ObjectPath]int64)
|
||||
c.jobListener.jobs = make(map[dbus.ObjectPath]chan<- string)
|
||||
|
||||
// Setup the listeners on jobs so that we can get completions
|
||||
|
||||
43
vendor/github.com/coreos/go-systemd/dbus/methods.go
generated
vendored
43
vendor/github.com/coreos/go-systemd/dbus/methods.go
generated
vendored
@@ -1,4 +1,4 @@
|
||||
// Copyright 2015 CoreOS, Inc.
|
||||
// Copyright 2015, 2018 CoreOS, Inc.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
@@ -16,6 +16,7 @@ package dbus
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"path"
|
||||
"strconv"
|
||||
|
||||
@@ -148,14 +149,27 @@ func (c *Conn) ResetFailedUnit(name string) error {
|
||||
return c.sysobj.Call("org.freedesktop.systemd1.Manager.ResetFailedUnit", 0, name).Store()
|
||||
}
|
||||
|
||||
// getProperties takes the unit name and returns all of its dbus object properties, for the given dbus interface
|
||||
func (c *Conn) getProperties(unit string, dbusInterface string) (map[string]interface{}, error) {
|
||||
// SystemState returns the systemd state. Equivalent to `systemctl is-system-running`.
|
||||
func (c *Conn) SystemState() (*Property, error) {
|
||||
var err error
|
||||
var prop dbus.Variant
|
||||
|
||||
obj := c.sysconn.Object("org.freedesktop.systemd1", "/org/freedesktop/systemd1")
|
||||
err = obj.Call("org.freedesktop.DBus.Properties.Get", 0, "org.freedesktop.systemd1.Manager", "SystemState").Store(&prop)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return &Property{Name: "SystemState", Value: prop}, nil
|
||||
}
|
||||
|
||||
// getProperties takes the unit path and returns all of its dbus object properties, for the given dbus interface
|
||||
func (c *Conn) getProperties(path dbus.ObjectPath, dbusInterface string) (map[string]interface{}, error) {
|
||||
var err error
|
||||
var props map[string]dbus.Variant
|
||||
|
||||
path := unitPath(unit)
|
||||
if !path.IsValid() {
|
||||
return nil, errors.New("invalid unit name: " + unit)
|
||||
return nil, fmt.Errorf("invalid unit name: %v", path)
|
||||
}
|
||||
|
||||
obj := c.sysconn.Object("org.freedesktop.systemd1", path)
|
||||
@@ -172,9 +186,15 @@ func (c *Conn) getProperties(unit string, dbusInterface string) (map[string]inte
|
||||
return out, nil
|
||||
}
|
||||
|
||||
// GetUnitProperties takes the unit name and returns all of its dbus object properties.
|
||||
// GetUnitProperties takes the (unescaped) unit name and returns all of its dbus object properties.
|
||||
func (c *Conn) GetUnitProperties(unit string) (map[string]interface{}, error) {
|
||||
return c.getProperties(unit, "org.freedesktop.systemd1.Unit")
|
||||
path := unitPath(unit)
|
||||
return c.getProperties(path, "org.freedesktop.systemd1.Unit")
|
||||
}
|
||||
|
||||
// GetUnitProperties takes the (escaped) unit path and returns all of its dbus object properties.
|
||||
func (c *Conn) GetUnitPathProperties(path dbus.ObjectPath) (map[string]interface{}, error) {
|
||||
return c.getProperties(path, "org.freedesktop.systemd1.Unit")
|
||||
}
|
||||
|
||||
func (c *Conn) getProperty(unit string, dbusInterface string, propertyName string) (*Property, error) {
|
||||
@@ -208,7 +228,8 @@ func (c *Conn) GetServiceProperty(service string, propertyName string) (*Propert
|
||||
// Valid values for unitType: Service, Socket, Target, Device, Mount, Automount, Snapshot, Timer, Swap, Path, Slice, Scope
|
||||
// return "dbus.Error: Unknown interface" if the unitType is not the correct type of the unit
|
||||
func (c *Conn) GetUnitTypeProperties(unit string, unitType string) (map[string]interface{}, error) {
|
||||
return c.getProperties(unit, "org.freedesktop.systemd1."+unitType)
|
||||
path := unitPath(unit)
|
||||
return c.getProperties(path, "org.freedesktop.systemd1."+unitType)
|
||||
}
|
||||
|
||||
// SetUnitProperties() may be used to modify certain unit properties at runtime.
|
||||
@@ -292,6 +313,7 @@ func (c *Conn) ListUnitsByPatterns(states []string, patterns []string) ([]UnitSt
|
||||
// names and returns an UnitStatus array. Comparing to ListUnitsByPatterns
|
||||
// method, this method returns statuses even for inactive or non-existing
|
||||
// units. Input array should contain exact unit names, but not patterns.
|
||||
// Note: Requires systemd v230 or higher
|
||||
func (c *Conn) ListUnitsByNames(units []string) ([]UnitStatus, error) {
|
||||
return c.listUnitsInternal(c.sysobj.Call("org.freedesktop.systemd1.Manager.ListUnitsByNames", 0, units).Store)
|
||||
}
|
||||
@@ -563,3 +585,8 @@ func (c *Conn) Reload() error {
|
||||
func unitPath(name string) dbus.ObjectPath {
|
||||
return dbus.ObjectPath("/org/freedesktop/systemd1/unit/" + PathBusEscape(name))
|
||||
}
|
||||
|
||||
// unitName returns the unescaped base element of the supplied escaped path
|
||||
func unitName(dpath dbus.ObjectPath) string {
|
||||
return pathBusUnescape(path.Base(string(dpath)))
|
||||
}
|
||||
|
||||
2
vendor/github.com/coreos/go-systemd/dbus/set.go
generated
vendored
2
vendor/github.com/coreos/go-systemd/dbus/set.go
generated
vendored
@@ -36,7 +36,7 @@ func (s *set) Length() int {
|
||||
}
|
||||
|
||||
func (s *set) Values() (values []string) {
|
||||
for val, _ := range s.data {
|
||||
for val := range s.data {
|
||||
values = append(values, val)
|
||||
}
|
||||
return
|
||||
|
||||
171
vendor/github.com/coreos/go-systemd/dbus/subscription.go
generated
vendored
171
vendor/github.com/coreos/go-systemd/dbus/subscription.go
generated
vendored
@@ -16,6 +16,7 @@ package dbus
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"log"
|
||||
"time"
|
||||
|
||||
"github.com/godbus/dbus"
|
||||
@@ -36,22 +37,12 @@ func (c *Conn) Subscribe() error {
|
||||
c.sigconn.BusObject().Call("org.freedesktop.DBus.AddMatch", 0,
|
||||
"type='signal',interface='org.freedesktop.DBus.Properties',member='PropertiesChanged'")
|
||||
|
||||
err := c.sigobj.Call("org.freedesktop.systemd1.Manager.Subscribe", 0).Store()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
return c.sigobj.Call("org.freedesktop.systemd1.Manager.Subscribe", 0).Store()
|
||||
}
|
||||
|
||||
// Unsubscribe this connection from systemd dbus events.
|
||||
func (c *Conn) Unsubscribe() error {
|
||||
err := c.sigobj.Call("org.freedesktop.systemd1.Manager.Unsubscribe", 0).Store()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
return c.sigobj.Call("org.freedesktop.systemd1.Manager.Unsubscribe", 0).Store()
|
||||
}
|
||||
|
||||
func (c *Conn) dispatch() {
|
||||
@@ -70,7 +61,8 @@ func (c *Conn) dispatch() {
|
||||
c.jobComplete(signal)
|
||||
}
|
||||
|
||||
if c.subscriber.updateCh == nil {
|
||||
if c.subStateSubscriber.updateCh == nil &&
|
||||
c.propertiesSubscriber.updateCh == nil {
|
||||
continue
|
||||
}
|
||||
|
||||
@@ -84,6 +76,12 @@ func (c *Conn) dispatch() {
|
||||
case "org.freedesktop.DBus.Properties.PropertiesChanged":
|
||||
if signal.Body[0].(string) == "org.freedesktop.systemd1.Unit" {
|
||||
unitPath = signal.Path
|
||||
|
||||
if len(signal.Body) >= 2 {
|
||||
if changed, ok := signal.Body[1].(map[string]dbus.Variant); ok {
|
||||
c.sendPropertiesUpdate(unitPath, changed)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -169,42 +167,80 @@ type SubStateUpdate struct {
|
||||
// is full, it attempts to write an error to errCh; if errCh is full, the error
|
||||
// passes silently.
|
||||
func (c *Conn) SetSubStateSubscriber(updateCh chan<- *SubStateUpdate, errCh chan<- error) {
|
||||
c.subscriber.Lock()
|
||||
defer c.subscriber.Unlock()
|
||||
c.subscriber.updateCh = updateCh
|
||||
c.subscriber.errCh = errCh
|
||||
}
|
||||
|
||||
func (c *Conn) sendSubStateUpdate(path dbus.ObjectPath) {
|
||||
c.subscriber.Lock()
|
||||
defer c.subscriber.Unlock()
|
||||
|
||||
if c.shouldIgnore(path) {
|
||||
if c == nil {
|
||||
msg := "nil receiver"
|
||||
select {
|
||||
case errCh <- errors.New(msg):
|
||||
default:
|
||||
log.Printf("full error channel while reporting: %s\n", msg)
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
info, err := c.GetUnitProperties(string(path))
|
||||
if err != nil {
|
||||
select {
|
||||
case c.subscriber.errCh <- err:
|
||||
default:
|
||||
}
|
||||
c.subStateSubscriber.Lock()
|
||||
defer c.subStateSubscriber.Unlock()
|
||||
c.subStateSubscriber.updateCh = updateCh
|
||||
c.subStateSubscriber.errCh = errCh
|
||||
}
|
||||
|
||||
func (c *Conn) sendSubStateUpdate(unitPath dbus.ObjectPath) {
|
||||
c.subStateSubscriber.Lock()
|
||||
defer c.subStateSubscriber.Unlock()
|
||||
|
||||
if c.subStateSubscriber.updateCh == nil {
|
||||
return
|
||||
}
|
||||
|
||||
name := info["Id"].(string)
|
||||
substate := info["SubState"].(string)
|
||||
isIgnored := c.shouldIgnore(unitPath)
|
||||
defer c.cleanIgnore()
|
||||
if isIgnored {
|
||||
return
|
||||
}
|
||||
|
||||
info, err := c.GetUnitPathProperties(unitPath)
|
||||
if err != nil {
|
||||
select {
|
||||
case c.subStateSubscriber.errCh <- err:
|
||||
default:
|
||||
log.Printf("full error channel while reporting: %s\n", err)
|
||||
}
|
||||
return
|
||||
}
|
||||
defer c.updateIgnore(unitPath, info)
|
||||
|
||||
name, ok := info["Id"].(string)
|
||||
if !ok {
|
||||
msg := "failed to cast info.Id"
|
||||
select {
|
||||
case c.subStateSubscriber.errCh <- errors.New(msg):
|
||||
default:
|
||||
log.Printf("full error channel while reporting: %s\n", err)
|
||||
}
|
||||
return
|
||||
}
|
||||
substate, ok := info["SubState"].(string)
|
||||
if !ok {
|
||||
msg := "failed to cast info.SubState"
|
||||
select {
|
||||
case c.subStateSubscriber.errCh <- errors.New(msg):
|
||||
default:
|
||||
log.Printf("full error channel while reporting: %s\n", msg)
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
update := &SubStateUpdate{name, substate}
|
||||
select {
|
||||
case c.subscriber.updateCh <- update:
|
||||
case c.subStateSubscriber.updateCh <- update:
|
||||
default:
|
||||
msg := "update channel is full"
|
||||
select {
|
||||
case c.subscriber.errCh <- errors.New("update channel full!"):
|
||||
case c.subStateSubscriber.errCh <- errors.New(msg):
|
||||
default:
|
||||
log.Printf("full error channel while reporting: %s\n", msg)
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
c.updateIgnore(path, info)
|
||||
}
|
||||
|
||||
// The ignore functions work around a wart in the systemd dbus interface.
|
||||
@@ -222,29 +258,76 @@ func (c *Conn) sendSubStateUpdate(path dbus.ObjectPath) {
|
||||
// the properties).
|
||||
|
||||
func (c *Conn) shouldIgnore(path dbus.ObjectPath) bool {
|
||||
t, ok := c.subscriber.ignore[path]
|
||||
t, ok := c.subStateSubscriber.ignore[path]
|
||||
return ok && t >= time.Now().UnixNano()
|
||||
}
|
||||
|
||||
func (c *Conn) updateIgnore(path dbus.ObjectPath, info map[string]interface{}) {
|
||||
c.cleanIgnore()
|
||||
loadState, ok := info["LoadState"].(string)
|
||||
if !ok {
|
||||
return
|
||||
}
|
||||
|
||||
// unit is unloaded - it will trigger bad systemd dbus behavior
|
||||
if info["LoadState"].(string) == "not-found" {
|
||||
c.subscriber.ignore[path] = time.Now().UnixNano() + ignoreInterval
|
||||
if loadState == "not-found" {
|
||||
c.subStateSubscriber.ignore[path] = time.Now().UnixNano() + ignoreInterval
|
||||
}
|
||||
}
|
||||
|
||||
// without this, ignore would grow unboundedly over time
|
||||
func (c *Conn) cleanIgnore() {
|
||||
now := time.Now().UnixNano()
|
||||
if c.subscriber.cleanIgnore < now {
|
||||
c.subscriber.cleanIgnore = now + cleanIgnoreInterval
|
||||
if c.subStateSubscriber.cleanIgnore < now {
|
||||
c.subStateSubscriber.cleanIgnore = now + cleanIgnoreInterval
|
||||
|
||||
for p, t := range c.subscriber.ignore {
|
||||
for p, t := range c.subStateSubscriber.ignore {
|
||||
if t < now {
|
||||
delete(c.subscriber.ignore, p)
|
||||
delete(c.subStateSubscriber.ignore, p)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// PropertiesUpdate holds a map of a unit's changed properties
|
||||
type PropertiesUpdate struct {
|
||||
UnitName string
|
||||
Changed map[string]dbus.Variant
|
||||
}
|
||||
|
||||
// SetPropertiesSubscriber writes to updateCh when any unit's properties
|
||||
// change. Every property change reported by systemd will be sent; that is, no
|
||||
// transitions will be "missed" (as they might be with SetSubStateSubscriber).
|
||||
// However, state changes will only be written to the channel with non-blocking
|
||||
// writes. If updateCh is full, it attempts to write an error to errCh; if
|
||||
// errCh is full, the error passes silently.
|
||||
func (c *Conn) SetPropertiesSubscriber(updateCh chan<- *PropertiesUpdate, errCh chan<- error) {
|
||||
c.propertiesSubscriber.Lock()
|
||||
defer c.propertiesSubscriber.Unlock()
|
||||
c.propertiesSubscriber.updateCh = updateCh
|
||||
c.propertiesSubscriber.errCh = errCh
|
||||
}
|
||||
|
||||
// we don't need to worry about shouldIgnore() here because
|
||||
// sendPropertiesUpdate doesn't call GetProperties()
|
||||
func (c *Conn) sendPropertiesUpdate(unitPath dbus.ObjectPath, changedProps map[string]dbus.Variant) {
|
||||
c.propertiesSubscriber.Lock()
|
||||
defer c.propertiesSubscriber.Unlock()
|
||||
|
||||
if c.propertiesSubscriber.updateCh == nil {
|
||||
return
|
||||
}
|
||||
|
||||
update := &PropertiesUpdate{unitName(unitPath), changedProps}
|
||||
|
||||
select {
|
||||
case c.propertiesSubscriber.updateCh <- update:
|
||||
default:
|
||||
msg := "update channel is full"
|
||||
select {
|
||||
case c.propertiesSubscriber.errCh <- errors.New(msg):
|
||||
default:
|
||||
log.Printf("full error channel while reporting: %s\n", msg)
|
||||
}
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
7
vendor/github.com/coreos/go-systemd/journal/journal.go
generated
vendored
7
vendor/github.com/coreos/go-systemd/journal/journal.go
generated
vendored
@@ -103,7 +103,10 @@ func Send(message string, priority Priority, vars map[string]string) error {
|
||||
if !ok {
|
||||
return journalError("can't send file through non-Unix connection")
|
||||
}
|
||||
unixConn.WriteMsgUnix([]byte{}, rights, nil)
|
||||
_, _, err = unixConn.WriteMsgUnix([]byte{}, rights, nil)
|
||||
if err != nil {
|
||||
return journalError(err.Error())
|
||||
}
|
||||
} else if err != nil {
|
||||
return journalError(err.Error())
|
||||
}
|
||||
@@ -165,7 +168,7 @@ func tempFd() (*os.File, error) {
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
syscall.Unlink(file.Name())
|
||||
err = syscall.Unlink(file.Name())
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
5
vendor/github.com/coreos/go-systemd/util/util_cgo.go
generated
vendored
5
vendor/github.com/coreos/go-systemd/util/util_cgo.go
generated
vendored
@@ -122,11 +122,12 @@ func runningFromSystemService() (ret bool, err error) {
|
||||
errno := C.my_sd_pid_get_owner_uid(sd_pid_get_owner_uid, 0, &uid)
|
||||
serrno := syscall.Errno(-errno)
|
||||
// when we're running from a unit file, sd_pid_get_owner_uid returns
|
||||
// ENOENT (systemd <220) or ENXIO (systemd >=220)
|
||||
// ENOENT (systemd <220), ENXIO (systemd 220-223), or ENODATA
|
||||
// (systemd >=234)
|
||||
switch {
|
||||
case errno >= 0:
|
||||
ret = false
|
||||
case serrno == syscall.ENOENT, serrno == syscall.ENXIO:
|
||||
case serrno == syscall.ENOENT, serrno == syscall.ENXIO, serrno == syscall.ENODATA:
|
||||
// Since the implementation of sessions in systemd relies on
|
||||
// the `pam_systemd` module, using the sd_pid_get_owner_uid
|
||||
// heuristic alone can result in false positives if that module
|
||||
|
||||
2
vendor/github.com/coreos/pkg/capnslog/README.md
generated
vendored
2
vendor/github.com/coreos/pkg/capnslog/README.md
generated
vendored
@@ -21,7 +21,7 @@ Still the job of `main` to expose these configurations. `main` may delegate this
|
||||
|
||||
Splitting streams is probably not the job of your program, but rather, your log aggregation framework. If you must split output streams, again, `main` configures this and you can write a very simple two-output struct that satisfies io.Writer.
|
||||
|
||||
Fancy colorful formatting and JSON output are beyond the scope of a basic logging framework -- they're application/log-collector dependant. These are, at best, provided as options, but more likely, provided by your application.
|
||||
Fancy colorful formatting and JSON output are beyond the scope of a basic logging framework -- they're application/log-collector dependent. These are, at best, provided as options, but more likely, provided by your application.
|
||||
|
||||
##### Log objects are an interface
|
||||
|
||||
|
||||
5
vendor/github.com/coreos/pkg/capnslog/logmap.go
generated
vendored
5
vendor/github.com/coreos/pkg/capnslog/logmap.go
generated
vendored
@@ -95,6 +95,11 @@ func (l *LogLevel) Set(s string) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
// Returns an empty string, only here to fulfill the pflag.Value interface.
|
||||
func (l *LogLevel) Type() string {
|
||||
return ""
|
||||
}
|
||||
|
||||
// ParseLevel translates some potential loglevel strings into their corresponding levels.
|
||||
func ParseLevel(s string) (LogLevel, error) {
|
||||
switch s {
|
||||
|
||||
14
vendor/github.com/coreos/pkg/capnslog/pkg_logger.go
generated
vendored
14
vendor/github.com/coreos/pkg/capnslog/pkg_logger.go
generated
vendored
@@ -37,6 +37,14 @@ func (p *PackageLogger) internalLog(depth int, inLevel LogLevel, entries ...inte
|
||||
}
|
||||
}
|
||||
|
||||
// SetLevel allows users to change the current logging level.
|
||||
func (p *PackageLogger) SetLevel(l LogLevel) {
|
||||
logger.Lock()
|
||||
defer logger.Unlock()
|
||||
p.level = l
|
||||
}
|
||||
|
||||
// LevelAt checks if the given log level will be outputted under current setting.
|
||||
func (p *PackageLogger) LevelAt(l LogLevel) bool {
|
||||
logger.Lock()
|
||||
defer logger.Unlock()
|
||||
@@ -81,6 +89,12 @@ func (p *PackageLogger) Panic(args ...interface{}) {
|
||||
panic(s)
|
||||
}
|
||||
|
||||
func (p *PackageLogger) Panicln(args ...interface{}) {
|
||||
s := fmt.Sprintln(args...)
|
||||
p.internalLog(calldepth, CRITICAL, s)
|
||||
panic(s)
|
||||
}
|
||||
|
||||
func (p *PackageLogger) Fatalf(format string, args ...interface{}) {
|
||||
p.Logf(CRITICAL, format, args...)
|
||||
os.Exit(1)
|
||||
|
||||
202
vendor/github.com/grpc-ecosystem/go-grpc-middleware/.gitignore
generated
vendored
Normal file
202
vendor/github.com/grpc-ecosystem/go-grpc-middleware/.gitignore
generated
vendored
Normal file
@@ -0,0 +1,202 @@
|
||||
# Created by .ignore support plugin (hsz.mobi)
|
||||
### Go template
|
||||
# Compiled Object files, Static and Dynamic libs (Shared Objects)
|
||||
*.o
|
||||
*.a
|
||||
*.so
|
||||
|
||||
# Folders
|
||||
_obj
|
||||
_test
|
||||
|
||||
# Architecture specific extensions/prefixes
|
||||
*.[568vq]
|
||||
[568vq].out
|
||||
|
||||
*.cgo1.go
|
||||
*.cgo2.c
|
||||
_cgo_defun.c
|
||||
_cgo_gotypes.go
|
||||
_cgo_export.*
|
||||
|
||||
_testmain.go
|
||||
|
||||
*.exe
|
||||
*.test
|
||||
*.prof
|
||||
### Windows template
|
||||
# Windows image file caches
|
||||
Thumbs.db
|
||||
ehthumbs.db
|
||||
|
||||
# Folder config file
|
||||
Desktop.ini
|
||||
|
||||
# Recycle Bin used on file shares
|
||||
$RECYCLE.BIN/
|
||||
|
||||
# Windows Installer files
|
||||
*.cab
|
||||
*.msi
|
||||
*.msm
|
||||
*.msp
|
||||
|
||||
# Windows shortcuts
|
||||
*.lnk
|
||||
### Kate template
|
||||
# Swap Files #
|
||||
.*.kate-swp
|
||||
.swp.*
|
||||
### SublimeText template
|
||||
# cache files for sublime text
|
||||
*.tmlanguage.cache
|
||||
*.tmPreferences.cache
|
||||
*.stTheme.cache
|
||||
|
||||
# workspace files are user-specific
|
||||
*.sublime-workspace
|
||||
|
||||
# project files should be checked into the repository, unless a significant
|
||||
# proportion of contributors will probably not be using SublimeText
|
||||
# *.sublime-project
|
||||
|
||||
# sftp configuration file
|
||||
sftp-config.json
|
||||
### Linux template
|
||||
*~
|
||||
|
||||
# temporary files which can be created if a process still has a handle open of a deleted file
|
||||
.fuse_hidden*
|
||||
|
||||
# KDE directory preferences
|
||||
.directory
|
||||
|
||||
# Linux trash folder which might appear on any partition or disk
|
||||
.Trash-*
|
||||
### JetBrains template
|
||||
# Covers JetBrains IDEs: IntelliJ, RubyMine, PhpStorm, AppCode, PyCharm, CLion, Android Studio and Webstorm
|
||||
# Reference: https://intellij-support.jetbrains.com/hc/en-us/articles/206544839
|
||||
|
||||
# User-specific stuff:
|
||||
.idea
|
||||
.idea/tasks.xml
|
||||
.idea/dictionaries
|
||||
.idea/vcs.xml
|
||||
.idea/jsLibraryMappings.xml
|
||||
|
||||
# Sensitive or high-churn files:
|
||||
.idea/dataSources.ids
|
||||
.idea/dataSources.xml
|
||||
.idea/dataSources.local.xml
|
||||
.idea/sqlDataSources.xml
|
||||
.idea/dynamic.xml
|
||||
.idea/uiDesigner.xml
|
||||
|
||||
# Gradle:
|
||||
.idea/gradle.xml
|
||||
.idea/libraries
|
||||
|
||||
# Mongo Explorer plugin:
|
||||
.idea/mongoSettings.xml
|
||||
|
||||
## File-based project format:
|
||||
*.iws
|
||||
|
||||
## Plugin-specific files:
|
||||
|
||||
# IntelliJ
|
||||
/out/
|
||||
|
||||
# mpeltonen/sbt-idea plugin
|
||||
.idea_modules/
|
||||
|
||||
# JIRA plugin
|
||||
atlassian-ide-plugin.xml
|
||||
|
||||
# Crashlytics plugin (for Android Studio and IntelliJ)
|
||||
com_crashlytics_export_strings.xml
|
||||
crashlytics.properties
|
||||
crashlytics-build.properties
|
||||
fabric.properties
|
||||
### Xcode template
|
||||
# Xcode
|
||||
#
|
||||
# gitignore contributors: remember to update Global/Xcode.gitignore, Objective-C.gitignore & Swift.gitignore
|
||||
|
||||
## Build generated
|
||||
build/
|
||||
DerivedData/
|
||||
|
||||
## Various settings
|
||||
*.pbxuser
|
||||
!default.pbxuser
|
||||
*.mode1v3
|
||||
!default.mode1v3
|
||||
*.mode2v3
|
||||
!default.mode2v3
|
||||
*.perspectivev3
|
||||
!default.perspectivev3
|
||||
xcuserdata/
|
||||
|
||||
## Other
|
||||
*.moved-aside
|
||||
*.xccheckout
|
||||
*.xcscmblueprint
|
||||
### Eclipse template
|
||||
|
||||
.metadata
|
||||
bin/
|
||||
tmp/
|
||||
*.tmp
|
||||
*.bak
|
||||
*.swp
|
||||
*~.nib
|
||||
local.properties
|
||||
.settings/
|
||||
.loadpath
|
||||
.recommenders
|
||||
|
||||
# Eclipse Core
|
||||
.project
|
||||
|
||||
# External tool builders
|
||||
.externalToolBuilders/
|
||||
|
||||
# Locally stored "Eclipse launch configurations"
|
||||
*.launch
|
||||
|
||||
# PyDev specific (Python IDE for Eclipse)
|
||||
*.pydevproject
|
||||
|
||||
# CDT-specific (C/C++ Development Tooling)
|
||||
.cproject
|
||||
|
||||
# JDT-specific (Eclipse Java Development Tools)
|
||||
.classpath
|
||||
|
||||
# Java annotation processor (APT)
|
||||
.factorypath
|
||||
|
||||
# PDT-specific (PHP Development Tools)
|
||||
.buildpath
|
||||
|
||||
# sbteclipse plugin
|
||||
.target
|
||||
|
||||
# Tern plugin
|
||||
.tern-project
|
||||
|
||||
# TeXlipse plugin
|
||||
.texlipse
|
||||
|
||||
# STS (Spring Tool Suite)
|
||||
.springBeans
|
||||
|
||||
# Code Recommenders
|
||||
.recommenders/
|
||||
|
||||
|
||||
coverage.txt
|
||||
|
||||
#vendor
|
||||
vendor/
|
||||
22
vendor/github.com/grpc-ecosystem/go-grpc-middleware/.travis.yml
generated
vendored
Normal file
22
vendor/github.com/grpc-ecosystem/go-grpc-middleware/.travis.yml
generated
vendored
Normal file
@@ -0,0 +1,22 @@
|
||||
sudo: false
|
||||
language: go
|
||||
go:
|
||||
- 1.8.x
|
||||
env:
|
||||
- DEP_VERSION="0.3.2"
|
||||
|
||||
before_install:
|
||||
# Download the binary to bin folder in $GOPATH
|
||||
- curl -L -s https://github.com/golang/dep/releases/download/v${DEP_VERSION}/dep-linux-amd64 -o $GOPATH/bin/dep
|
||||
# Make the binary executable
|
||||
- chmod +x $GOPATH/bin/dep
|
||||
|
||||
install:
|
||||
- dep ensure
|
||||
|
||||
script:
|
||||
- make checkdocs
|
||||
- make test
|
||||
|
||||
after_success:
|
||||
- bash <(curl -s https://codecov.io/bash)
|
||||
31
vendor/github.com/grpc-ecosystem/go-grpc-middleware/BUILD
generated
vendored
Normal file
31
vendor/github.com/grpc-ecosystem/go-grpc-middleware/BUILD
generated
vendored
Normal file
@@ -0,0 +1,31 @@
|
||||
load("@io_bazel_rules_go//go:def.bzl", "go_library")
|
||||
|
||||
go_library(
|
||||
name = "go_default_library",
|
||||
srcs = [
|
||||
"chain.go",
|
||||
"doc.go",
|
||||
"wrappers.go",
|
||||
],
|
||||
importmap = "k8s.io/kubernetes/vendor/github.com/grpc-ecosystem/go-grpc-middleware",
|
||||
importpath = "github.com/grpc-ecosystem/go-grpc-middleware",
|
||||
visibility = ["//visibility:public"],
|
||||
deps = [
|
||||
"//vendor/golang.org/x/net/context:go_default_library",
|
||||
"//vendor/google.golang.org/grpc:go_default_library",
|
||||
],
|
||||
)
|
||||
|
||||
filegroup(
|
||||
name = "package-srcs",
|
||||
srcs = glob(["**"]),
|
||||
tags = ["automanaged"],
|
||||
visibility = ["//visibility:private"],
|
||||
)
|
||||
|
||||
filegroup(
|
||||
name = "all-srcs",
|
||||
srcs = [":package-srcs"],
|
||||
tags = ["automanaged"],
|
||||
visibility = ["//visibility:public"],
|
||||
)
|
||||
30
vendor/github.com/grpc-ecosystem/go-grpc-middleware/CHANGELOG.md
generated
vendored
Normal file
30
vendor/github.com/grpc-ecosystem/go-grpc-middleware/CHANGELOG.md
generated
vendored
Normal file
@@ -0,0 +1,30 @@
|
||||
# Changelog
|
||||
All notable changes to this project will be documented in this file.
|
||||
|
||||
The format is based on [Keep a Changelog](http://keepachangelog.com/en/1.0.0/)
|
||||
and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0.html).
|
||||
|
||||
Types of changes:
|
||||
- `Added` for new features.
|
||||
- `Changed` for changes in existing functionality.
|
||||
- `Deprecated` for soon-to-be removed features.
|
||||
- `Removed` for now removed features.
|
||||
- `Fixed` for any bug fixes.
|
||||
- `Security` in case of vulnerabilities.
|
||||
|
||||
## [Unreleased]
|
||||
### Added
|
||||
- This CHANGELOG file to keep track of changes.
|
||||
|
||||
## 1.0.0 - 2018-05-08
|
||||
### Added
|
||||
- grpc_auth
|
||||
- grpc_ctxtags
|
||||
- grpc_zap
|
||||
- grpc_logrus
|
||||
- grpc_opentracing
|
||||
- grpc_retry
|
||||
- grpc_validator
|
||||
- grpc_recovery
|
||||
|
||||
[Unreleased]: https://github.com/grpc-ecosystem/go-grpc-middleware/compare/v1.0.0...HEAD
|
||||
20
vendor/github.com/grpc-ecosystem/go-grpc-middleware/CONTRIBUTING.md
generated
vendored
Normal file
20
vendor/github.com/grpc-ecosystem/go-grpc-middleware/CONTRIBUTING.md
generated
vendored
Normal file
@@ -0,0 +1,20 @@
|
||||
# Contributing
|
||||
|
||||
We would love to have people submit pull requests and help make `grpc-ecosystem/go-grpc-middleware` even better 👍.
|
||||
|
||||
Fork, then clone the repo:
|
||||
|
||||
```bash
|
||||
git clone git@github.com:your-username/go-grpc-middleware.git
|
||||
```
|
||||
|
||||
Before checking in please run the following:
|
||||
|
||||
```bash
|
||||
make all
|
||||
```
|
||||
|
||||
This will `vet`, `fmt`, regenerate documentation and run all tests.
|
||||
|
||||
|
||||
Push to your fork and open a pull request.
|
||||
166
vendor/github.com/grpc-ecosystem/go-grpc-middleware/DOC.md
generated
vendored
Normal file
166
vendor/github.com/grpc-ecosystem/go-grpc-middleware/DOC.md
generated
vendored
Normal file
@@ -0,0 +1,166 @@
|
||||
# grpc_middleware
|
||||
`import "github.com/grpc-ecosystem/go-grpc-middleware"`
|
||||
|
||||
* [Overview](#pkg-overview)
|
||||
* [Imported Packages](#pkg-imports)
|
||||
* [Index](#pkg-index)
|
||||
|
||||
## <a name="pkg-overview">Overview</a>
|
||||
`grpc_middleware` is a collection of gRPC middleware packages: interceptors, helpers and tools.
|
||||
|
||||
### Middleware
|
||||
gRPC is a fantastic RPC middleware, which sees a lot of adoption in the Golang world. However, the
|
||||
upstream gRPC codebase is relatively bare bones.
|
||||
|
||||
This package, and most of its child packages provides commonly needed middleware for gRPC:
|
||||
client-side interceptors for retires, server-side interceptors for input validation and auth,
|
||||
functions for chaining said interceptors, metadata convenience methods and more.
|
||||
|
||||
### Chaining
|
||||
By default, gRPC doesn't allow one to have more than one interceptor either on the client nor on
|
||||
the server side. `grpc_middleware` provides convenient chaining methods
|
||||
|
||||
Simple way of turning a multiple interceptors into a single interceptor. Here's an example for
|
||||
server chaining:
|
||||
|
||||
myServer := grpc.NewServer(
|
||||
grpc.StreamInterceptor(grpc_middleware.ChainStreamServer(loggingStream, monitoringStream, authStream)),
|
||||
grpc.UnaryInterceptor(grpc_middleware.ChainUnaryServer(loggingUnary, monitoringUnary, authUnary),
|
||||
)
|
||||
|
||||
These interceptors will be executed from left to right: logging, monitoring and auth.
|
||||
|
||||
Here's an example for client side chaining:
|
||||
|
||||
clientConn, err = grpc.Dial(
|
||||
address,
|
||||
grpc.WithUnaryInterceptor(grpc_middleware.ChainUnaryClient(monitoringClientUnary, retryUnary)),
|
||||
grpc.WithStreamInterceptor(grpc_middleware.ChainStreamClient(monitoringClientStream, retryStream)),
|
||||
)
|
||||
client = pb_testproto.NewTestServiceClient(clientConn)
|
||||
resp, err := client.PingEmpty(s.ctx, &myservice.Request{Msg: "hello"})
|
||||
|
||||
These interceptors will be executed from left to right: monitoring and then retry logic.
|
||||
|
||||
The retry interceptor will call every interceptor that follows it whenever when a retry happens.
|
||||
|
||||
### Writing Your Own
|
||||
Implementing your own interceptor is pretty trivial: there are interfaces for that. But the interesting
|
||||
bit exposing common data to handlers (and other middleware), similarly to HTTP Middleware design.
|
||||
For example, you may want to pass the identity of the caller from the auth interceptor all the way
|
||||
to the handling function.
|
||||
|
||||
For example, a client side interceptor example for auth looks like:
|
||||
|
||||
func FakeAuthUnaryInterceptor(ctx context.Context, req interface{}, info *grpc.UnaryServerInfo, handler grpc.UnaryHandler) (interface{}, error) {
|
||||
newCtx := context.WithValue(ctx, "user_id", "john@example.com")
|
||||
return handler(newCtx, req)
|
||||
}
|
||||
|
||||
Unfortunately, it's not as easy for streaming RPCs. These have the `context.Context` embedded within
|
||||
the `grpc.ServerStream` object. To pass values through context, a wrapper (`WrappedServerStream`) is
|
||||
needed. For example:
|
||||
|
||||
func FakeAuthStreamingInterceptor(srv interface{}, stream grpc.ServerStream, info *grpc.StreamServerInfo, handler grpc.StreamHandler) error {
|
||||
newStream := grpc_middleware.WrapServerStream(stream)
|
||||
newStream.WrappedContext = context.WithValue(ctx, "user_id", "john@example.com")
|
||||
return handler(srv, stream)
|
||||
}
|
||||
|
||||
## <a name="pkg-imports">Imported Packages</a>
|
||||
|
||||
- [golang.org/x/net/context](https://godoc.org/golang.org/x/net/context)
|
||||
- [google.golang.org/grpc](https://godoc.org/google.golang.org/grpc)
|
||||
|
||||
## <a name="pkg-index">Index</a>
|
||||
* [func ChainStreamClient(interceptors ...grpc.StreamClientInterceptor) grpc.StreamClientInterceptor](#ChainStreamClient)
|
||||
* [func ChainStreamServer(interceptors ...grpc.StreamServerInterceptor) grpc.StreamServerInterceptor](#ChainStreamServer)
|
||||
* [func ChainUnaryClient(interceptors ...grpc.UnaryClientInterceptor) grpc.UnaryClientInterceptor](#ChainUnaryClient)
|
||||
* [func ChainUnaryServer(interceptors ...grpc.UnaryServerInterceptor) grpc.UnaryServerInterceptor](#ChainUnaryServer)
|
||||
* [func WithStreamServerChain(interceptors ...grpc.StreamServerInterceptor) grpc.ServerOption](#WithStreamServerChain)
|
||||
* [func WithUnaryServerChain(interceptors ...grpc.UnaryServerInterceptor) grpc.ServerOption](#WithUnaryServerChain)
|
||||
* [type WrappedServerStream](#WrappedServerStream)
|
||||
* [func WrapServerStream(stream grpc.ServerStream) \*WrappedServerStream](#WrapServerStream)
|
||||
* [func (w \*WrappedServerStream) Context() context.Context](#WrappedServerStream.Context)
|
||||
|
||||
#### <a name="pkg-files">Package files</a>
|
||||
[chain.go](./chain.go) [doc.go](./doc.go) [wrappers.go](./wrappers.go)
|
||||
|
||||
## <a name="ChainStreamClient">func</a> [ChainStreamClient](./chain.go#L136)
|
||||
``` go
|
||||
func ChainStreamClient(interceptors ...grpc.StreamClientInterceptor) grpc.StreamClientInterceptor
|
||||
```
|
||||
ChainStreamClient creates a single interceptor out of a chain of many interceptors.
|
||||
|
||||
Execution is done in left-to-right order, including passing of context.
|
||||
For example ChainStreamClient(one, two, three) will execute one before two before three.
|
||||
|
||||
## <a name="ChainStreamServer">func</a> [ChainStreamServer](./chain.go#L58)
|
||||
``` go
|
||||
func ChainStreamServer(interceptors ...grpc.StreamServerInterceptor) grpc.StreamServerInterceptor
|
||||
```
|
||||
ChainStreamServer creates a single interceptor out of a chain of many interceptors.
|
||||
|
||||
Execution is done in left-to-right order, including passing of context.
|
||||
For example ChainUnaryServer(one, two, three) will execute one before two before three.
|
||||
If you want to pass context between interceptors, use WrapServerStream.
|
||||
|
||||
## <a name="ChainUnaryClient">func</a> [ChainUnaryClient](./chain.go#L97)
|
||||
``` go
|
||||
func ChainUnaryClient(interceptors ...grpc.UnaryClientInterceptor) grpc.UnaryClientInterceptor
|
||||
```
|
||||
ChainUnaryClient creates a single interceptor out of a chain of many interceptors.
|
||||
|
||||
Execution is done in left-to-right order, including passing of context.
|
||||
For example ChainUnaryClient(one, two, three) will execute one before two before three.
|
||||
|
||||
## <a name="ChainUnaryServer">func</a> [ChainUnaryServer](./chain.go#L18)
|
||||
``` go
|
||||
func ChainUnaryServer(interceptors ...grpc.UnaryServerInterceptor) grpc.UnaryServerInterceptor
|
||||
```
|
||||
ChainUnaryServer creates a single interceptor out of a chain of many interceptors.
|
||||
|
||||
Execution is done in left-to-right order, including passing of context.
|
||||
For example ChainUnaryServer(one, two, three) will execute one before two before three, and three
|
||||
will see context changes of one and two.
|
||||
|
||||
## <a name="WithStreamServerChain">func</a> [WithStreamServerChain](./chain.go#L181)
|
||||
``` go
|
||||
func WithStreamServerChain(interceptors ...grpc.StreamServerInterceptor) grpc.ServerOption
|
||||
```
|
||||
WithStreamServerChain is a grpc.Server config option that accepts multiple stream interceptors.
|
||||
Basically syntactic sugar.
|
||||
|
||||
## <a name="WithUnaryServerChain">func</a> [WithUnaryServerChain](./chain.go#L175)
|
||||
``` go
|
||||
func WithUnaryServerChain(interceptors ...grpc.UnaryServerInterceptor) grpc.ServerOption
|
||||
```
|
||||
Chain creates a single interceptor out of a chain of many interceptors.
|
||||
|
||||
WithUnaryServerChain is a grpc.Server config option that accepts multiple unary interceptors.
|
||||
Basically syntactic sugar.
|
||||
|
||||
## <a name="WrappedServerStream">type</a> [WrappedServerStream](./wrappers.go#L12-L16)
|
||||
``` go
|
||||
type WrappedServerStream struct {
|
||||
grpc.ServerStream
|
||||
// WrappedContext is the wrapper's own Context. You can assign it.
|
||||
WrappedContext context.Context
|
||||
}
|
||||
```
|
||||
WrappedServerStream is a thin wrapper around grpc.ServerStream that allows modifying context.
|
||||
|
||||
### <a name="WrapServerStream">func</a> [WrapServerStream](./wrappers.go#L24)
|
||||
``` go
|
||||
func WrapServerStream(stream grpc.ServerStream) *WrappedServerStream
|
||||
```
|
||||
WrapServerStream returns a ServerStream that has the ability to overwrite context.
|
||||
|
||||
### <a name="WrappedServerStream.Context">func</a> (\*WrappedServerStream) [Context](./wrappers.go#L19)
|
||||
``` go
|
||||
func (w *WrappedServerStream) Context() context.Context
|
||||
```
|
||||
Context returns the wrapper's WrappedContext, overwriting the nested grpc.ServerStream.Context()
|
||||
|
||||
- - -
|
||||
Generated by [godoc2ghmd](https://github.com/GandalfUK/godoc2ghmd)
|
||||
123
vendor/github.com/grpc-ecosystem/go-grpc-middleware/Gopkg.lock
generated
vendored
Normal file
123
vendor/github.com/grpc-ecosystem/go-grpc-middleware/Gopkg.lock
generated
vendored
Normal file
@@ -0,0 +1,123 @@
|
||||
# This file is autogenerated, do not edit; changes may be undone by the next 'dep ensure'.
|
||||
|
||||
|
||||
[[projects]]
|
||||
name = "cloud.google.com/go"
|
||||
packages = ["compute/metadata"]
|
||||
revision = "2d3a6656c17a60b0815b7e06ab0be04eacb6e613"
|
||||
version = "v0.16.0"
|
||||
|
||||
[[projects]]
|
||||
name = "github.com/davecgh/go-spew"
|
||||
packages = ["spew"]
|
||||
revision = "346938d642f2ec3594ed81d874461961cd0faa76"
|
||||
version = "v1.1.0"
|
||||
|
||||
[[projects]]
|
||||
name = "github.com/gogo/protobuf"
|
||||
packages = ["gogoproto","proto","protoc-gen-gogo/descriptor"]
|
||||
revision = "342cbe0a04158f6dcb03ca0079991a51a4248c02"
|
||||
version = "v0.5"
|
||||
|
||||
[[projects]]
|
||||
branch = "master"
|
||||
name = "github.com/golang/protobuf"
|
||||
packages = ["jsonpb","proto","ptypes","ptypes/any","ptypes/duration","ptypes/struct","ptypes/timestamp"]
|
||||
revision = "1e59b77b52bf8e4b449a57e6f79f21226d571845"
|
||||
|
||||
[[projects]]
|
||||
name = "github.com/opentracing/opentracing-go"
|
||||
packages = [".","ext","log","mocktracer"]
|
||||
revision = "1949ddbfd147afd4d964a9f00b24eb291e0e7c38"
|
||||
version = "v1.0.2"
|
||||
|
||||
[[projects]]
|
||||
name = "github.com/pmezard/go-difflib"
|
||||
packages = ["difflib"]
|
||||
revision = "792786c7400a136282c1664665ae0a8db921c6c2"
|
||||
version = "v1.0.0"
|
||||
|
||||
[[projects]]
|
||||
name = "github.com/sirupsen/logrus"
|
||||
packages = ["."]
|
||||
revision = "f006c2ac4710855cf0f916dd6b77acf6b048dc6e"
|
||||
version = "v1.0.3"
|
||||
|
||||
[[projects]]
|
||||
name = "github.com/stretchr/testify"
|
||||
packages = ["assert","require","suite"]
|
||||
revision = "69483b4bd14f5845b5a1e55bca19e954e827f1d0"
|
||||
version = "v1.1.4"
|
||||
|
||||
[[projects]]
|
||||
name = "go.uber.org/atomic"
|
||||
packages = ["."]
|
||||
revision = "8474b86a5a6f79c443ce4b2992817ff32cf208b8"
|
||||
version = "v1.3.1"
|
||||
|
||||
[[projects]]
|
||||
name = "go.uber.org/multierr"
|
||||
packages = ["."]
|
||||
revision = "3c4937480c32f4c13a875a1829af76c98ca3d40a"
|
||||
version = "v1.1.0"
|
||||
|
||||
[[projects]]
|
||||
name = "go.uber.org/zap"
|
||||
packages = [".","buffer","internal/bufferpool","internal/color","internal/exit","zapcore"]
|
||||
revision = "35aad584952c3e7020db7b839f6b102de6271f89"
|
||||
version = "v1.7.1"
|
||||
|
||||
[[projects]]
|
||||
branch = "master"
|
||||
name = "golang.org/x/crypto"
|
||||
packages = ["ssh/terminal"]
|
||||
revision = "94eea52f7b742c7cbe0b03b22f0c4c8631ece122"
|
||||
|
||||
[[projects]]
|
||||
branch = "master"
|
||||
name = "golang.org/x/net"
|
||||
packages = ["context","context/ctxhttp","http2","http2/hpack","idna","internal/timeseries","lex/httplex","trace"]
|
||||
revision = "a8b9294777976932365dabb6640cf1468d95c70f"
|
||||
|
||||
[[projects]]
|
||||
branch = "master"
|
||||
name = "golang.org/x/oauth2"
|
||||
packages = [".","google","internal","jws","jwt"]
|
||||
revision = "f95fa95eaa936d9d87489b15d1d18b97c1ba9c28"
|
||||
|
||||
[[projects]]
|
||||
branch = "master"
|
||||
name = "golang.org/x/sys"
|
||||
packages = ["unix","windows"]
|
||||
revision = "13fcbd661c8ececa8807a29b48407d674b1d8ed8"
|
||||
|
||||
[[projects]]
|
||||
branch = "master"
|
||||
name = "golang.org/x/text"
|
||||
packages = ["collate","collate/build","internal/colltab","internal/gen","internal/tag","internal/triegen","internal/ucd","language","secure/bidirule","transform","unicode/bidi","unicode/cldr","unicode/norm","unicode/rangetable"]
|
||||
revision = "75cc3cad82b5f47d3fb229ddda8c5167da14f294"
|
||||
|
||||
[[projects]]
|
||||
name = "google.golang.org/appengine"
|
||||
packages = [".","internal","internal/app_identity","internal/base","internal/datastore","internal/log","internal/modules","internal/remote_api","internal/urlfetch","urlfetch"]
|
||||
revision = "150dc57a1b433e64154302bdc40b6bb8aefa313a"
|
||||
version = "v1.0.0"
|
||||
|
||||
[[projects]]
|
||||
branch = "master"
|
||||
name = "google.golang.org/genproto"
|
||||
packages = ["googleapis/rpc/status"]
|
||||
revision = "7f0da29060c682909f650ad8ed4e515bd74fa12a"
|
||||
|
||||
[[projects]]
|
||||
name = "google.golang.org/grpc"
|
||||
packages = [".","balancer","balancer/roundrobin","codes","connectivity","credentials","credentials/oauth","encoding","grpclb/grpc_lb_v1/messages","grpclog","internal","keepalive","metadata","naming","peer","resolver","resolver/dns","resolver/passthrough","stats","status","tap","transport"]
|
||||
revision = "5a9f7b402fe85096d2e1d0383435ee1876e863d0"
|
||||
version = "v1.8.0"
|
||||
|
||||
[solve-meta]
|
||||
analyzer-name = "dep"
|
||||
analyzer-version = 1
|
||||
inputs-digest = "b24c6670412eb0bc44ed1db77fecc52333f8725f3e3272bdc568f5683a63031f"
|
||||
solver-name = "gps-cdcl"
|
||||
solver-version = 1
|
||||
35
vendor/github.com/grpc-ecosystem/go-grpc-middleware/Gopkg.toml
generated
vendored
Normal file
35
vendor/github.com/grpc-ecosystem/go-grpc-middleware/Gopkg.toml
generated
vendored
Normal file
@@ -0,0 +1,35 @@
|
||||
[[constraint]]
|
||||
name = "github.com/gogo/protobuf"
|
||||
version = "0.5.0"
|
||||
|
||||
[[constraint]]
|
||||
branch = "master"
|
||||
name = "github.com/golang/protobuf"
|
||||
|
||||
[[constraint]]
|
||||
name = "github.com/opentracing/opentracing-go"
|
||||
version = "1.0.2"
|
||||
|
||||
[[constraint]]
|
||||
name = "github.com/sirupsen/logrus"
|
||||
version = "1.0.3"
|
||||
|
||||
[[constraint]]
|
||||
name = "github.com/stretchr/testify"
|
||||
version = "1.1.4"
|
||||
|
||||
[[constraint]]
|
||||
name = "go.uber.org/zap"
|
||||
version = "1.7.1"
|
||||
|
||||
[[constraint]]
|
||||
branch = "master"
|
||||
name = "golang.org/x/net"
|
||||
|
||||
[[constraint]]
|
||||
branch = "master"
|
||||
name = "golang.org/x/oauth2"
|
||||
|
||||
[[constraint]]
|
||||
name = "google.golang.org/grpc"
|
||||
version = "1.8.0"
|
||||
201
vendor/github.com/grpc-ecosystem/go-grpc-middleware/LICENSE
generated
vendored
Normal file
201
vendor/github.com/grpc-ecosystem/go-grpc-middleware/LICENSE
generated
vendored
Normal file
@@ -0,0 +1,201 @@
|
||||
Apache License
|
||||
Version 2.0, January 2004
|
||||
http://www.apache.org/licenses/
|
||||
|
||||
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
|
||||
|
||||
1. Definitions.
|
||||
|
||||
"License" shall mean the terms and conditions for use, reproduction,
|
||||
and distribution as defined by Sections 1 through 9 of this document.
|
||||
|
||||
"Licensor" shall mean the copyright owner or entity authorized by
|
||||
the copyright owner that is granting the License.
|
||||
|
||||
"Legal Entity" shall mean the union of the acting entity and all
|
||||
other entities that control, are controlled by, or are under common
|
||||
control with that entity. For the purposes of this definition,
|
||||
"control" means (i) the power, direct or indirect, to cause the
|
||||
direction or management of such entity, whether by contract or
|
||||
otherwise, or (ii) ownership of fifty percent (50%) or more of the
|
||||
outstanding shares, or (iii) beneficial ownership of such entity.
|
||||
|
||||
"You" (or "Your") shall mean an individual or Legal Entity
|
||||
exercising permissions granted by this License.
|
||||
|
||||
"Source" form shall mean the preferred form for making modifications,
|
||||
including but not limited to software source code, documentation
|
||||
source, and configuration files.
|
||||
|
||||
"Object" form shall mean any form resulting from mechanical
|
||||
transformation or translation of a Source form, including but
|
||||
not limited to compiled object code, generated documentation,
|
||||
and conversions to other media types.
|
||||
|
||||
"Work" shall mean the work of authorship, whether in Source or
|
||||
Object form, made available under the License, as indicated by a
|
||||
copyright notice that is included in or attached to the work
|
||||
(an example is provided in the Appendix below).
|
||||
|
||||
"Derivative Works" shall mean any work, whether in Source or Object
|
||||
form, that is based on (or derived from) the Work and for which the
|
||||
editorial revisions, annotations, elaborations, or other modifications
|
||||
represent, as a whole, an original work of authorship. For the purposes
|
||||
of this License, Derivative Works shall not include works that remain
|
||||
separable from, or merely link (or bind by name) to the interfaces of,
|
||||
the Work and Derivative Works thereof.
|
||||
|
||||
"Contribution" shall mean any work of authorship, including
|
||||
the original version of the Work and any modifications or additions
|
||||
to that Work or Derivative Works thereof, that is intentionally
|
||||
submitted to Licensor for inclusion in the Work by the copyright owner
|
||||
or by an individual or Legal Entity authorized to submit on behalf of
|
||||
the copyright owner. For the purposes of this definition, "submitted"
|
||||
means any form of electronic, verbal, or written communication sent
|
||||
to the Licensor or its representatives, including but not limited to
|
||||
communication on electronic mailing lists, source code control systems,
|
||||
and issue tracking systems that are managed by, or on behalf of, the
|
||||
Licensor for the purpose of discussing and improving the Work, but
|
||||
excluding communication that is conspicuously marked or otherwise
|
||||
designated in writing by the copyright owner as "Not a Contribution."
|
||||
|
||||
"Contributor" shall mean Licensor and any individual or Legal Entity
|
||||
on behalf of whom a Contribution has been received by Licensor and
|
||||
subsequently incorporated within the Work.
|
||||
|
||||
2. Grant of Copyright License. Subject to the terms and conditions of
|
||||
this License, each Contributor hereby grants to You a perpetual,
|
||||
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
||||
copyright license to reproduce, prepare Derivative Works of,
|
||||
publicly display, publicly perform, sublicense, and distribute the
|
||||
Work and such Derivative Works in Source or Object form.
|
||||
|
||||
3. Grant of Patent License. Subject to the terms and conditions of
|
||||
this License, each Contributor hereby grants to You a perpetual,
|
||||
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
||||
(except as stated in this section) patent license to make, have made,
|
||||
use, offer to sell, sell, import, and otherwise transfer the Work,
|
||||
where such license applies only to those patent claims licensable
|
||||
by such Contributor that are necessarily infringed by their
|
||||
Contribution(s) alone or by combination of their Contribution(s)
|
||||
with the Work to which such Contribution(s) was submitted. If You
|
||||
institute patent litigation against any entity (including a
|
||||
cross-claim or counterclaim in a lawsuit) alleging that the Work
|
||||
or a Contribution incorporated within the Work constitutes direct
|
||||
or contributory patent infringement, then any patent licenses
|
||||
granted to You under this License for that Work shall terminate
|
||||
as of the date such litigation is filed.
|
||||
|
||||
4. Redistribution. You may reproduce and distribute copies of the
|
||||
Work or Derivative Works thereof in any medium, with or without
|
||||
modifications, and in Source or Object form, provided that You
|
||||
meet the following conditions:
|
||||
|
||||
(a) You must give any other recipients of the Work or
|
||||
Derivative Works a copy of this License; and
|
||||
|
||||
(b) You must cause any modified files to carry prominent notices
|
||||
stating that You changed the files; and
|
||||
|
||||
(c) You must retain, in the Source form of any Derivative Works
|
||||
that You distribute, all copyright, patent, trademark, and
|
||||
attribution notices from the Source form of the Work,
|
||||
excluding those notices that do not pertain to any part of
|
||||
the Derivative Works; and
|
||||
|
||||
(d) If the Work includes a "NOTICE" text file as part of its
|
||||
distribution, then any Derivative Works that You distribute must
|
||||
include a readable copy of the attribution notices contained
|
||||
within such NOTICE file, excluding those notices that do not
|
||||
pertain to any part of the Derivative Works, in at least one
|
||||
of the following places: within a NOTICE text file distributed
|
||||
as part of the Derivative Works; within the Source form or
|
||||
documentation, if provided along with the Derivative Works; or,
|
||||
within a display generated by the Derivative Works, if and
|
||||
wherever such third-party notices normally appear. The contents
|
||||
of the NOTICE file are for informational purposes only and
|
||||
do not modify the License. You may add Your own attribution
|
||||
notices within Derivative Works that You distribute, alongside
|
||||
or as an addendum to the NOTICE text from the Work, provided
|
||||
that such additional attribution notices cannot be construed
|
||||
as modifying the License.
|
||||
|
||||
You may add Your own copyright statement to Your modifications and
|
||||
may provide additional or different license terms and conditions
|
||||
for use, reproduction, or distribution of Your modifications, or
|
||||
for any such Derivative Works as a whole, provided Your use,
|
||||
reproduction, and distribution of the Work otherwise complies with
|
||||
the conditions stated in this License.
|
||||
|
||||
5. Submission of Contributions. Unless You explicitly state otherwise,
|
||||
any Contribution intentionally submitted for inclusion in the Work
|
||||
by You to the Licensor shall be under the terms and conditions of
|
||||
this License, without any additional terms or conditions.
|
||||
Notwithstanding the above, nothing herein shall supersede or modify
|
||||
the terms of any separate license agreement you may have executed
|
||||
with Licensor regarding such Contributions.
|
||||
|
||||
6. Trademarks. This License does not grant permission to use the trade
|
||||
names, trademarks, service marks, or product names of the Licensor,
|
||||
except as required for reasonable and customary use in describing the
|
||||
origin of the Work and reproducing the content of the NOTICE file.
|
||||
|
||||
7. Disclaimer of Warranty. Unless required by applicable law or
|
||||
agreed to in writing, Licensor provides the Work (and each
|
||||
Contributor provides its Contributions) on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
|
||||
implied, including, without limitation, any warranties or conditions
|
||||
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
|
||||
PARTICULAR PURPOSE. You are solely responsible for determining the
|
||||
appropriateness of using or redistributing the Work and assume any
|
||||
risks associated with Your exercise of permissions under this License.
|
||||
|
||||
8. Limitation of Liability. In no event and under no legal theory,
|
||||
whether in tort (including negligence), contract, or otherwise,
|
||||
unless required by applicable law (such as deliberate and grossly
|
||||
negligent acts) or agreed to in writing, shall any Contributor be
|
||||
liable to You for damages, including any direct, indirect, special,
|
||||
incidental, or consequential damages of any character arising as a
|
||||
result of this License or out of the use or inability to use the
|
||||
Work (including but not limited to damages for loss of goodwill,
|
||||
work stoppage, computer failure or malfunction, or any and all
|
||||
other commercial damages or losses), even if such Contributor
|
||||
has been advised of the possibility of such damages.
|
||||
|
||||
9. Accepting Warranty or Additional Liability. While redistributing
|
||||
the Work or Derivative Works thereof, You may choose to offer,
|
||||
and charge a fee for, acceptance of support, warranty, indemnity,
|
||||
or other liability obligations and/or rights consistent with this
|
||||
License. However, in accepting such obligations, You may act only
|
||||
on Your own behalf and on Your sole responsibility, not on behalf
|
||||
of any other Contributor, and only if You agree to indemnify,
|
||||
defend, and hold each Contributor harmless for any liability
|
||||
incurred by, or claims asserted against, such Contributor by reason
|
||||
of your accepting any such warranty or additional liability.
|
||||
|
||||
END OF TERMS AND CONDITIONS
|
||||
|
||||
APPENDIX: How to apply the Apache License to your work.
|
||||
|
||||
To apply the Apache License to your work, attach the following
|
||||
boilerplate notice, with the fields enclosed by brackets "[]"
|
||||
replaced with your own identifying information. (Don't include
|
||||
the brackets!) The text should be enclosed in the appropriate
|
||||
comment syntax for the file format. We also recommend that a
|
||||
file or class name and description of purpose be included on the
|
||||
same "printed page" as the copyright notice for easier
|
||||
identification within third-party archives.
|
||||
|
||||
Copyright [yyyy] [name of copyright owner]
|
||||
|
||||
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.
|
||||
86
vendor/github.com/grpc-ecosystem/go-grpc-middleware/README.md
generated
vendored
Normal file
86
vendor/github.com/grpc-ecosystem/go-grpc-middleware/README.md
generated
vendored
Normal file
@@ -0,0 +1,86 @@
|
||||
# Go gRPC Middleware
|
||||
|
||||
[](https://travis-ci.org/grpc-ecosystem/go-grpc-middleware)
|
||||
[](https://goreportcard.com/report/github.com/grpc-ecosystem/go-grpc-middleware)
|
||||
[](https://godoc.org/github.com/grpc-ecosystem/go-grpc-middleware)
|
||||
[](https://sourcegraph.com/github.com/grpc-ecosystem/go-grpc-middleware/?badge)
|
||||
[](https://codecov.io/gh/grpc-ecosystem/go-grpc-middleware)
|
||||
[](LICENSE)
|
||||
[](#status)
|
||||
[](https://join.slack.com/t/improbable-eng/shared_invite/enQtMzQ1ODcyMzQ5MjM4LWY5ZWZmNGM2ODc5MmViNmQ3ZTA3ZTY3NzQwOTBlMTkzZmIxZTIxODk0OWU3YjZhNWVlNDU3MDlkZGViZjhkMjc)
|
||||
|
||||
[gRPC Go](https://github.com/grpc/grpc-go) Middleware: interceptors, helpers, utilities.
|
||||
|
||||
**Important** The repo recently moved to `github.com/grpc-ecosystem/go-grpc-middleware`, please update your import paths.
|
||||
|
||||
## Middleware
|
||||
|
||||
[gRPC Go](https://github.com/grpc/grpc-go) recently acquired support for
|
||||
Interceptors, i.e. [middleware](https://medium.com/@matryer/writing-middleware-in-golang-and-how-go-makes-it-so-much-fun-4375c1246e81#.gv7tdlghs)
|
||||
that is executed either on the gRPC Server before the request is passed onto the user's application logic, or on the gRPC client either around the user call. It is a perfect way to implement
|
||||
common patterns: auth, logging, message, validation, retries or monitoring.
|
||||
|
||||
These are generic building blocks that make it easy to build multiple microservices easily.
|
||||
The purpose of this repository is to act as a go-to point for such reusable functionality. It contains
|
||||
some of them itself, but also will link to useful external repos.
|
||||
|
||||
`grpc_middleware` itself provides support for chaining interceptors. See [Documentation](DOC.md), but here's an example:
|
||||
|
||||
```go
|
||||
import "github.com/grpc-ecosystem/go-grpc-middleware"
|
||||
|
||||
myServer := grpc.NewServer(
|
||||
grpc.StreamInterceptor(grpc_middleware.ChainStreamServer(
|
||||
grpc_ctxtags.StreamServerInterceptor(),
|
||||
grpc_opentracing.StreamServerInterceptor(),
|
||||
grpc_prometheus.StreamServerInterceptor,
|
||||
grpc_zap.StreamServerInterceptor(zapLogger),
|
||||
grpc_auth.StreamServerInterceptor(myAuthFunction),
|
||||
grpc_recovery.StreamServerInterceptor(),
|
||||
)),
|
||||
grpc.UnaryInterceptor(grpc_middleware.ChainUnaryServer(
|
||||
grpc_ctxtags.UnaryServerInterceptor(),
|
||||
grpc_opentracing.UnaryServerInterceptor(),
|
||||
grpc_prometheus.UnaryServerInterceptor,
|
||||
grpc_zap.UnaryServerInterceptor(zapLogger),
|
||||
grpc_auth.UnaryServerInterceptor(myAuthFunction),
|
||||
grpc_recovery.UnaryServerInterceptor(),
|
||||
)),
|
||||
)
|
||||
```
|
||||
|
||||
## Interceptors
|
||||
|
||||
*Please send a PR to add new interceptors or middleware to this list*
|
||||
|
||||
#### Auth
|
||||
* [`grpc_auth`](auth) - a customizable (via `AuthFunc`) piece of auth middleware
|
||||
|
||||
#### Logging
|
||||
* [`grpc_ctxtags`](tags/) - a library that adds a `Tag` map to context, with data populated from request body
|
||||
* [`grpc_zap`](logging/zap/) - integration of [zap](https://github.com/uber-go/zap) logging library into gRPC handlers.
|
||||
* [`grpc_logrus`](logging/logrus/) - integration of [logrus](https://github.com/sirupsen/logrus) logging library into gRPC handlers.
|
||||
|
||||
|
||||
#### Monitoring
|
||||
* [`grpc_prometheus`⚡](https://github.com/grpc-ecosystem/go-grpc-prometheus) - Prometheus client-side and server-side monitoring middleware
|
||||
* [`otgrpc`⚡](https://github.com/grpc-ecosystem/grpc-opentracing/tree/master/go/otgrpc) - [OpenTracing](http://opentracing.io/) client-side and server-side interceptors
|
||||
* [`grpc_opentracing`](tracing/opentracing) - [OpenTracing](http://opentracing.io/) client-side and server-side interceptors with support for streaming and handler-returned tags
|
||||
|
||||
#### Client
|
||||
* [`grpc_retry`](retry/) - a generic gRPC response code retry mechanism, client-side middleware
|
||||
|
||||
#### Server
|
||||
* [`grpc_validator`](validator/) - codegen inbound message validation from `.proto` options
|
||||
* [`grpc_recovery`](recovery/) - turn panics into gRPC errors
|
||||
|
||||
|
||||
## Status
|
||||
|
||||
This code has been running in *production* since May 2016 as the basis of the gRPC micro services stack at [Improbable](https://improbable.io).
|
||||
|
||||
Additional tooling will be added, and contributions are welcome.
|
||||
|
||||
## License
|
||||
|
||||
`go-grpc-middleware` is released under the Apache 2.0 license. See the [LICENSE](LICENSE) file for details.
|
||||
183
vendor/github.com/grpc-ecosystem/go-grpc-middleware/chain.go
generated
vendored
Normal file
183
vendor/github.com/grpc-ecosystem/go-grpc-middleware/chain.go
generated
vendored
Normal file
@@ -0,0 +1,183 @@
|
||||
// Copyright 2016 Michal Witkowski. All Rights Reserved.
|
||||
// See LICENSE for licensing terms.
|
||||
|
||||
// gRPC Server Interceptor chaining middleware.
|
||||
|
||||
package grpc_middleware
|
||||
|
||||
import (
|
||||
"golang.org/x/net/context"
|
||||
"google.golang.org/grpc"
|
||||
)
|
||||
|
||||
// ChainUnaryServer creates a single interceptor out of a chain of many interceptors.
|
||||
//
|
||||
// Execution is done in left-to-right order, including passing of context.
|
||||
// For example ChainUnaryServer(one, two, three) will execute one before two before three, and three
|
||||
// will see context changes of one and two.
|
||||
func ChainUnaryServer(interceptors ...grpc.UnaryServerInterceptor) grpc.UnaryServerInterceptor {
|
||||
n := len(interceptors)
|
||||
|
||||
if n > 1 {
|
||||
lastI := n - 1
|
||||
return func(ctx context.Context, req interface{}, info *grpc.UnaryServerInfo, handler grpc.UnaryHandler) (interface{}, error) {
|
||||
var (
|
||||
chainHandler grpc.UnaryHandler
|
||||
curI int
|
||||
)
|
||||
|
||||
chainHandler = func(currentCtx context.Context, currentReq interface{}) (interface{}, error) {
|
||||
if curI == lastI {
|
||||
return handler(currentCtx, currentReq)
|
||||
}
|
||||
curI++
|
||||
resp, err := interceptors[curI](currentCtx, currentReq, info, chainHandler)
|
||||
curI--
|
||||
return resp, err
|
||||
}
|
||||
|
||||
return interceptors[0](ctx, req, info, chainHandler)
|
||||
}
|
||||
}
|
||||
|
||||
if n == 1 {
|
||||
return interceptors[0]
|
||||
}
|
||||
|
||||
// n == 0; Dummy interceptor maintained for backward compatibility to avoid returning nil.
|
||||
return func(ctx context.Context, req interface{}, _ *grpc.UnaryServerInfo, handler grpc.UnaryHandler) (interface{}, error) {
|
||||
return handler(ctx, req)
|
||||
}
|
||||
}
|
||||
|
||||
// ChainStreamServer creates a single interceptor out of a chain of many interceptors.
|
||||
//
|
||||
// Execution is done in left-to-right order, including passing of context.
|
||||
// For example ChainUnaryServer(one, two, three) will execute one before two before three.
|
||||
// If you want to pass context between interceptors, use WrapServerStream.
|
||||
func ChainStreamServer(interceptors ...grpc.StreamServerInterceptor) grpc.StreamServerInterceptor {
|
||||
n := len(interceptors)
|
||||
|
||||
if n > 1 {
|
||||
lastI := n - 1
|
||||
return func(srv interface{}, stream grpc.ServerStream, info *grpc.StreamServerInfo, handler grpc.StreamHandler) error {
|
||||
var (
|
||||
chainHandler grpc.StreamHandler
|
||||
curI int
|
||||
)
|
||||
|
||||
chainHandler = func(currentSrv interface{}, currentStream grpc.ServerStream) error {
|
||||
if curI == lastI {
|
||||
return handler(currentSrv, currentStream)
|
||||
}
|
||||
curI++
|
||||
err := interceptors[curI](currentSrv, currentStream, info, chainHandler)
|
||||
curI--
|
||||
return err
|
||||
}
|
||||
|
||||
return interceptors[0](srv, stream, info, chainHandler)
|
||||
}
|
||||
}
|
||||
|
||||
if n == 1 {
|
||||
return interceptors[0]
|
||||
}
|
||||
|
||||
// n == 0; Dummy interceptor maintained for backward compatibility to avoid returning nil.
|
||||
return func(srv interface{}, stream grpc.ServerStream, _ *grpc.StreamServerInfo, handler grpc.StreamHandler) error {
|
||||
return handler(srv, stream)
|
||||
}
|
||||
}
|
||||
|
||||
// ChainUnaryClient creates a single interceptor out of a chain of many interceptors.
|
||||
//
|
||||
// Execution is done in left-to-right order, including passing of context.
|
||||
// For example ChainUnaryClient(one, two, three) will execute one before two before three.
|
||||
func ChainUnaryClient(interceptors ...grpc.UnaryClientInterceptor) grpc.UnaryClientInterceptor {
|
||||
n := len(interceptors)
|
||||
|
||||
if n > 1 {
|
||||
lastI := n - 1
|
||||
return func(ctx context.Context, method string, req, reply interface{}, cc *grpc.ClientConn, invoker grpc.UnaryInvoker, opts ...grpc.CallOption) error {
|
||||
var (
|
||||
chainHandler grpc.UnaryInvoker
|
||||
curI int
|
||||
)
|
||||
|
||||
chainHandler = func(currentCtx context.Context, currentMethod string, currentReq, currentRepl interface{}, currentConn *grpc.ClientConn, currentOpts ...grpc.CallOption) error {
|
||||
if curI == lastI {
|
||||
return invoker(currentCtx, currentMethod, currentReq, currentRepl, currentConn, currentOpts...)
|
||||
}
|
||||
curI++
|
||||
err := interceptors[curI](currentCtx, currentMethod, currentReq, currentRepl, currentConn, chainHandler, currentOpts...)
|
||||
curI--
|
||||
return err
|
||||
}
|
||||
|
||||
return interceptors[0](ctx, method, req, reply, cc, chainHandler, opts...)
|
||||
}
|
||||
}
|
||||
|
||||
if n == 1 {
|
||||
return interceptors[0]
|
||||
}
|
||||
|
||||
// n == 0; Dummy interceptor maintained for backward compatibility to avoid returning nil.
|
||||
return func(ctx context.Context, method string, req, reply interface{}, cc *grpc.ClientConn, invoker grpc.UnaryInvoker, opts ...grpc.CallOption) error {
|
||||
return invoker(ctx, method, req, reply, cc, opts...)
|
||||
}
|
||||
}
|
||||
|
||||
// ChainStreamClient creates a single interceptor out of a chain of many interceptors.
|
||||
//
|
||||
// Execution is done in left-to-right order, including passing of context.
|
||||
// For example ChainStreamClient(one, two, three) will execute one before two before three.
|
||||
func ChainStreamClient(interceptors ...grpc.StreamClientInterceptor) grpc.StreamClientInterceptor {
|
||||
n := len(interceptors)
|
||||
|
||||
if n > 1 {
|
||||
lastI := n - 1
|
||||
return func(ctx context.Context, desc *grpc.StreamDesc, cc *grpc.ClientConn, method string, streamer grpc.Streamer, opts ...grpc.CallOption) (grpc.ClientStream, error) {
|
||||
var (
|
||||
chainHandler grpc.Streamer
|
||||
curI int
|
||||
)
|
||||
|
||||
chainHandler = func(currentCtx context.Context, currentDesc *grpc.StreamDesc, currentConn *grpc.ClientConn, currentMethod string, currentOpts ...grpc.CallOption) (grpc.ClientStream, error) {
|
||||
if curI == lastI {
|
||||
return streamer(currentCtx, currentDesc, currentConn, currentMethod, currentOpts...)
|
||||
}
|
||||
curI++
|
||||
stream, err := interceptors[curI](currentCtx, currentDesc, currentConn, currentMethod, chainHandler, currentOpts...)
|
||||
curI--
|
||||
return stream, err
|
||||
}
|
||||
|
||||
return interceptors[0](ctx, desc, cc, method, chainHandler, opts...)
|
||||
}
|
||||
}
|
||||
|
||||
if n == 1 {
|
||||
return interceptors[0]
|
||||
}
|
||||
|
||||
// n == 0; Dummy interceptor maintained for backward compatibility to avoid returning nil.
|
||||
return func(ctx context.Context, desc *grpc.StreamDesc, cc *grpc.ClientConn, method string, streamer grpc.Streamer, opts ...grpc.CallOption) (grpc.ClientStream, error) {
|
||||
return streamer(ctx, desc, cc, method, opts...)
|
||||
}
|
||||
}
|
||||
|
||||
// Chain creates a single interceptor out of a chain of many interceptors.
|
||||
//
|
||||
// WithUnaryServerChain is a grpc.Server config option that accepts multiple unary interceptors.
|
||||
// Basically syntactic sugar.
|
||||
func WithUnaryServerChain(interceptors ...grpc.UnaryServerInterceptor) grpc.ServerOption {
|
||||
return grpc.UnaryInterceptor(ChainUnaryServer(interceptors...))
|
||||
}
|
||||
|
||||
// WithStreamServerChain is a grpc.Server config option that accepts multiple stream interceptors.
|
||||
// Basically syntactic sugar.
|
||||
func WithStreamServerChain(interceptors ...grpc.StreamServerInterceptor) grpc.ServerOption {
|
||||
return grpc.StreamInterceptor(ChainStreamServer(interceptors...))
|
||||
}
|
||||
69
vendor/github.com/grpc-ecosystem/go-grpc-middleware/doc.go
generated
vendored
Normal file
69
vendor/github.com/grpc-ecosystem/go-grpc-middleware/doc.go
generated
vendored
Normal file
@@ -0,0 +1,69 @@
|
||||
// Copyright 2016 Michal Witkowski. All Rights Reserved.
|
||||
// See LICENSE for licensing terms.
|
||||
|
||||
/*
|
||||
`grpc_middleware` is a collection of gRPC middleware packages: interceptors, helpers and tools.
|
||||
|
||||
Middleware
|
||||
|
||||
gRPC is a fantastic RPC middleware, which sees a lot of adoption in the Golang world. However, the
|
||||
upstream gRPC codebase is relatively bare bones.
|
||||
|
||||
This package, and most of its child packages provides commonly needed middleware for gRPC:
|
||||
client-side interceptors for retires, server-side interceptors for input validation and auth,
|
||||
functions for chaining said interceptors, metadata convenience methods and more.
|
||||
|
||||
Chaining
|
||||
|
||||
By default, gRPC doesn't allow one to have more than one interceptor either on the client nor on
|
||||
the server side. `grpc_middleware` provides convenient chaining methods
|
||||
|
||||
Simple way of turning a multiple interceptors into a single interceptor. Here's an example for
|
||||
server chaining:
|
||||
|
||||
myServer := grpc.NewServer(
|
||||
grpc.StreamInterceptor(grpc_middleware.ChainStreamServer(loggingStream, monitoringStream, authStream)),
|
||||
grpc.UnaryInterceptor(grpc_middleware.ChainUnaryServer(loggingUnary, monitoringUnary, authUnary),
|
||||
)
|
||||
|
||||
These interceptors will be executed from left to right: logging, monitoring and auth.
|
||||
|
||||
Here's an example for client side chaining:
|
||||
|
||||
clientConn, err = grpc.Dial(
|
||||
address,
|
||||
grpc.WithUnaryInterceptor(grpc_middleware.ChainUnaryClient(monitoringClientUnary, retryUnary)),
|
||||
grpc.WithStreamInterceptor(grpc_middleware.ChainStreamClient(monitoringClientStream, retryStream)),
|
||||
)
|
||||
client = pb_testproto.NewTestServiceClient(clientConn)
|
||||
resp, err := client.PingEmpty(s.ctx, &myservice.Request{Msg: "hello"})
|
||||
|
||||
These interceptors will be executed from left to right: monitoring and then retry logic.
|
||||
|
||||
The retry interceptor will call every interceptor that follows it whenever when a retry happens.
|
||||
|
||||
Writing Your Own
|
||||
|
||||
Implementing your own interceptor is pretty trivial: there are interfaces for that. But the interesting
|
||||
bit exposing common data to handlers (and other middleware), similarly to HTTP Middleware design.
|
||||
For example, you may want to pass the identity of the caller from the auth interceptor all the way
|
||||
to the handling function.
|
||||
|
||||
For example, a client side interceptor example for auth looks like:
|
||||
|
||||
func FakeAuthUnaryInterceptor(ctx context.Context, req interface{}, info *grpc.UnaryServerInfo, handler grpc.UnaryHandler) (interface{}, error) {
|
||||
newCtx := context.WithValue(ctx, "user_id", "john@example.com")
|
||||
return handler(newCtx, req)
|
||||
}
|
||||
|
||||
Unfortunately, it's not as easy for streaming RPCs. These have the `context.Context` embedded within
|
||||
the `grpc.ServerStream` object. To pass values through context, a wrapper (`WrappedServerStream`) is
|
||||
needed. For example:
|
||||
|
||||
func FakeAuthStreamingInterceptor(srv interface{}, stream grpc.ServerStream, info *grpc.StreamServerInfo, handler grpc.StreamHandler) error {
|
||||
newStream := grpc_middleware.WrapServerStream(stream)
|
||||
newStream.WrappedContext = context.WithValue(ctx, "user_id", "john@example.com")
|
||||
return handler(srv, stream)
|
||||
}
|
||||
*/
|
||||
package grpc_middleware
|
||||
22
vendor/github.com/grpc-ecosystem/go-grpc-middleware/makefile
generated
vendored
Normal file
22
vendor/github.com/grpc-ecosystem/go-grpc-middleware/makefile
generated
vendored
Normal file
@@ -0,0 +1,22 @@
|
||||
SHELL="/bin/bash"
|
||||
|
||||
GOFILES_NOVENDOR = $(shell go list ./... | grep -v /vendor/)
|
||||
|
||||
all: vet fmt docs test
|
||||
|
||||
docs:
|
||||
./scripts/docs.sh generate
|
||||
|
||||
checkdocs:
|
||||
./scripts/docs.sh check
|
||||
|
||||
fmt:
|
||||
go fmt $(GOFILES_NOVENDOR)
|
||||
|
||||
vet:
|
||||
go vet $(GOFILES_NOVENDOR)
|
||||
|
||||
test: vet
|
||||
./scripts/test_all.sh
|
||||
|
||||
.PHONY: all docs validate test
|
||||
BIN
vendor/github.com/grpc-ecosystem/go-grpc-middleware/slack.png
generated
vendored
Normal file
BIN
vendor/github.com/grpc-ecosystem/go-grpc-middleware/slack.png
generated
vendored
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 5.0 KiB |
29
vendor/github.com/grpc-ecosystem/go-grpc-middleware/wrappers.go
generated
vendored
Normal file
29
vendor/github.com/grpc-ecosystem/go-grpc-middleware/wrappers.go
generated
vendored
Normal file
@@ -0,0 +1,29 @@
|
||||
// Copyright 2016 Michal Witkowski. All Rights Reserved.
|
||||
// See LICENSE for licensing terms.
|
||||
|
||||
package grpc_middleware
|
||||
|
||||
import (
|
||||
"golang.org/x/net/context"
|
||||
"google.golang.org/grpc"
|
||||
)
|
||||
|
||||
// WrappedServerStream is a thin wrapper around grpc.ServerStream that allows modifying context.
|
||||
type WrappedServerStream struct {
|
||||
grpc.ServerStream
|
||||
// WrappedContext is the wrapper's own Context. You can assign it.
|
||||
WrappedContext context.Context
|
||||
}
|
||||
|
||||
// Context returns the wrapper's WrappedContext, overwriting the nested grpc.ServerStream.Context()
|
||||
func (w *WrappedServerStream) Context() context.Context {
|
||||
return w.WrappedContext
|
||||
}
|
||||
|
||||
// WrapServerStream returns a ServerStream that has the ability to overwrite context.
|
||||
func WrapServerStream(stream grpc.ServerStream) *WrappedServerStream {
|
||||
if existing, ok := stream.(*WrappedServerStream); ok {
|
||||
return existing
|
||||
}
|
||||
return &WrappedServerStream{ServerStream: stream, WrappedContext: stream.Context()}
|
||||
}
|
||||
Reference in New Issue
Block a user