From eebaa64d8ccc188a0d724490a119d0e9b43a27ee Mon Sep 17 00:00:00 2001 From: Asim Aslam Date: Sun, 29 Jul 2018 10:55:46 +0100 Subject: [PATCH 001/196] phase 1 --- transport/http_transport.go | 287 ++++++++++++++++++++++-------------- 1 file changed, 176 insertions(+), 111 deletions(-) diff --git a/transport/http_transport.go b/transport/http_transport.go index 10fb452e..ffda4d28 100644 --- a/transport/http_transport.go +++ b/transport/http_transport.go @@ -1,6 +1,7 @@ package transport import ( + //"fmt" "bufio" "bytes" "crypto/tls" @@ -13,10 +14,11 @@ import ( "sync" "time" - "github.com/micro/go-log" + "github.com/micro/h2c" maddr "github.com/micro/util/go/lib/addr" mnet "github.com/micro/util/go/lib/net" mls "github.com/micro/util/go/lib/tls" + "golang.org/x/net/http2" ) type buffer struct { @@ -41,13 +43,14 @@ type httpTransportClient struct { } type httpTransportSocket struct { - ht *httpTransport - r chan *http.Request - conn net.Conn - once sync.Once + ht *httpTransport + w http.ResponseWriter + r *http.Request + rw *bufio.ReadWriter - sync.Mutex - buff *bufio.Reader + conn net.Conn + // for the first request + ch chan *http.Request } type httpTransportListener struct { @@ -175,28 +178,74 @@ func (h *httpTransportSocket) Recv(m *Message) error { return errors.New("message passed in is nil") } - // set timeout if its greater than 0 - if h.ht.opts.Timeout > time.Duration(0) { - h.conn.SetDeadline(time.Now().Add(h.ht.opts.Timeout)) - } - - r, err := http.ReadRequest(h.buff) - if err != nil { - return err - } - - b, err := ioutil.ReadAll(r.Body) - if err != nil { - return err - } - r.Body.Close() - m.Body = b - if m.Header == nil { m.Header = make(map[string]string) } - for k, v := range r.Header { + // process http 1 + if h.r.ProtoMajor == 1 { + // set timeout if its greater than 0 + if h.ht.opts.Timeout > time.Duration(0) { + h.conn.SetDeadline(time.Now().Add(h.ht.opts.Timeout)) + } + + var r *http.Request + + select { + // get first request + case r = <-h.ch: + // read next request + default: + rr, err := http.ReadRequest(h.rw.Reader) + if err != nil { + return err + } + r = rr + } + + // read body + b, err := ioutil.ReadAll(r.Body) + if err != nil { + return err + } + + // set body + r.Body.Close() + m.Body = b + + // set headers + for k, v := range h.r.Header { + if len(v) > 0 { + m.Header[k] = v[0] + } else { + m.Header[k] = "" + } + } + + // return early early + return nil + } + + // processing http2 request + // read streaming body + + // set max buffer size + buf := make([]byte, 4*1024) + + // read the request body + n, err := h.r.Body.Read(buf) + // not an eof error + if err != nil { + return err + } + + // check if we have data + if n > 0 { + m.Body = buf[:n] + } + + // set headers + for k, v := range h.r.Header { if len(v) > 0 { m.Header[k] = v[0] } else { @@ -204,78 +253,73 @@ func (h *httpTransportSocket) Recv(m *Message) error { } } - select { - case h.r <- r: - default: - } - return nil } func (h *httpTransportSocket) Send(m *Message) error { - b := bytes.NewBuffer(m.Body) - defer b.Reset() + if h.r.ProtoMajor == 1 { + rsp := &http.Response{ + Header: h.r.Header, + Body: ioutil.NopCloser(bytes.NewReader(m.Body)), + Status: "200 OK", + StatusCode: 200, + Proto: "HTTP/1.1", + ProtoMajor: 1, + ProtoMinor: 1, + ContentLength: int64(len(m.Body)), + } - r := <-h.r + for k, v := range m.Header { + rsp.Header.Set(k, v) + } - rsp := &http.Response{ - Header: r.Header, - Body: &buffer{b}, - Status: "200 OK", - StatusCode: 200, - Proto: "HTTP/1.1", - ProtoMajor: 1, - ProtoMinor: 1, - ContentLength: int64(len(m.Body)), + // set timeout if its greater than 0 + if h.ht.opts.Timeout > time.Duration(0) { + h.conn.SetDeadline(time.Now().Add(h.ht.opts.Timeout)) + } + + return rsp.Write(h.conn) } + // http2 request + + // set headers for k, v := range m.Header { - rsp.Header.Set(k, v) + h.w.Header().Set(k, v) } - select { - case h.r <- r: - default: - } - - // set timeout if its greater than 0 - if h.ht.opts.Timeout > time.Duration(0) { - h.conn.SetDeadline(time.Now().Add(h.ht.opts.Timeout)) - } - - return rsp.Write(h.conn) + // write request + _, err := h.w.Write(m.Body) + return err } func (h *httpTransportSocket) error(m *Message) error { - b := bytes.NewBuffer(m.Body) - defer b.Reset() - rsp := &http.Response{ - Header: make(http.Header), - Body: &buffer{b}, - Status: "500 Internal Server Error", - StatusCode: 500, - Proto: "HTTP/1.1", - ProtoMajor: 1, - ProtoMinor: 1, - ContentLength: int64(len(m.Body)), - } + if h.r.ProtoMajor == 1 { + rsp := &http.Response{ + Header: make(http.Header), + Body: ioutil.NopCloser(bytes.NewReader(m.Body)), + Status: "500 Internal Server Error", + StatusCode: 500, + Proto: "HTTP/1.1", + ProtoMajor: 1, + ProtoMinor: 1, + ContentLength: int64(len(m.Body)), + } - for k, v := range m.Header { - rsp.Header.Set(k, v) - } + for k, v := range m.Header { + rsp.Header.Set(k, v) + } - return rsp.Write(h.conn) + return rsp.Write(h.conn) + } + return nil } func (h *httpTransportSocket) Close() error { - err := h.conn.Close() - h.once.Do(func() { - h.Lock() - h.buff.Reset(nil) - h.buff = nil - h.Unlock() - }) - return err + if h.r.ProtoMajor == 1 { + return h.conn.Close() + } + return nil } func (h *httpTransportListener) Addr() string { @@ -287,46 +331,67 @@ func (h *httpTransportListener) Close() error { } func (h *httpTransportListener) Accept(fn func(Socket)) error { - var tempDelay time.Duration + // create handler mux + mux := http.NewServeMux() + mux.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) { + var buf *bufio.ReadWriter + var con net.Conn - for { - c, err := h.listener.Accept() - if err != nil { - if ne, ok := err.(net.Error); ok && ne.Temporary() { - if tempDelay == 0 { - tempDelay = 5 * time.Millisecond - } else { - tempDelay *= 2 - } - if max := 1 * time.Second; tempDelay > max { - tempDelay = max - } - log.Logf("http: Accept error: %v; retrying in %v\n", err, tempDelay) - time.Sleep(tempDelay) - continue + // read a regular request + if r.ProtoMajor == 1 { + b, err := ioutil.ReadAll(r.Body) + if err != nil { + http.Error(w, err.Error(), http.StatusInternalServerError) + return } - return err + r.Body = ioutil.NopCloser(bytes.NewReader(b)) + // hijack the conn + hj, ok := w.(http.Hijacker) + if !ok { + // we're screwed + http.Error(w, "cannot serve conn", http.StatusInternalServerError) + return + } + + conn, bufrw, err := hj.Hijack() + if err != nil { + http.Error(w, err.Error(), http.StatusInternalServerError) + return + } + defer conn.Close() + buf = bufrw + con = conn } - sock := &httpTransportSocket{ + // save the request + ch := make(chan *http.Request, 1) + ch <- r + + fn(&httpTransportSocket{ ht: h.ht, - conn: c, - buff: bufio.NewReader(c), - r: make(chan *http.Request, 1), - } + w: w, + r: r, + rw: buf, + ch: ch, + conn: con, + }) + }) - go func() { - // TODO: think of a better error response strategy - defer func() { - if r := recover(); r != nil { - log.Log("panic recovered: ", r) - sock.Close() - } - }() - - fn(sock) - }() + // default http2 server + srv := &http.Server{ + Handler: mux, } + + // insecure connection use h2c + if !(h.ht.opts.Secure || h.ht.opts.TLSConfig != nil) { + srv.Handler = &h2c.HandlerH2C{ + Handler: mux, + H2Server: &http2.Server{}, + } + } + + // begin serving + return srv.Serve(h.listener) } func (h *httpTransport) Dial(addr string, opts ...DialOption) (Client, error) { From 9d3cb65daaf630acb1c87b8f45d13b8def7d7a22 Mon Sep 17 00:00:00 2001 From: Asim Aslam Date: Sat, 18 Aug 2018 17:28:58 +0100 Subject: [PATCH 002/196] set broker address on Init --- broker/http_broker.go | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/broker/http_broker.go b/broker/http_broker.go index c5dc13ff..48a110c6 100644 --- a/broker/http_broker.go +++ b/broker/http_broker.go @@ -276,7 +276,6 @@ func (h *httpBroker) Address() string { } func (h *httpBroker) Connect() error { - h.RLock() if h.running { h.RUnlock() @@ -397,6 +396,10 @@ func (h *httpBroker) Init(opts ...Option) error { o(&h.opts) } + if len(h.opts.Addrs) > 0 && len(h.opts.Addrs[0]) > 0 { + h.address = h.opts.Addrs[0] + } + if len(h.id) == 0 { h.id = "broker-" + uuid.NewUUID().String() } From 3732dc2f4201e14d2b20ae02e9c81ed87ff42e72 Mon Sep 17 00:00:00 2001 From: Asim Aslam Date: Tue, 28 Aug 2018 16:00:04 +0100 Subject: [PATCH 003/196] bump travis --- .travis.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index b67ea84a..96a32173 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,7 +1,7 @@ language: go go: -- 1.9.5 - 1.10.x +- 1.11.x notifications: slack: secure: aEvhLbhujaGaKSrOokiG3//PaVHTIrc3fBpoRbCRqfZpyq6WREoapJJhF+tIpWWOwaC9GmChbD6aHo/jMUgwKXVyPSaNjiEL87YzUUpL8B2zslNp1rgfTg/LrzthOx3Q1TYwpaAl3to0fuHUVFX4yMeC2vuThq7WSXgMMxFCtbc= From 395d70cf0132a8447e6d4af74deae2d028adc2e1 Mon Sep 17 00:00:00 2001 From: ahmadnurus Date: Wed, 12 Sep 2018 21:42:34 +0700 Subject: [PATCH 004/196] errors: Added 405 Method Not Allowed helper function --- errors/errors.go | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/errors/errors.go b/errors/errors.go index 9aa0ecdc..78e06c98 100644 --- a/errors/errors.go +++ b/errors/errors.go @@ -82,6 +82,16 @@ func NotFound(id, format string, a ...interface{}) error { } } +// MethodNotAllowed generates a 405 error. +func MethodNotAllowed(id, format string, a ...interface{}) error { + return &Error{ + Id: id, + Code: 405, + Detail: fmt.Sprintf(format, a...), + Status: http.StatusText(405), + } +} + // InternalServerError generates a 500 error. func InternalServerError(id, format string, a ...interface{}) error { return &Error{ From 156a51ab10f2da74457bd954b272c289d729b0e1 Mon Sep 17 00:00:00 2001 From: Anton Kucherov Date: Thu, 13 Sep 2018 19:02:08 +0300 Subject: [PATCH 005/196] fix bug with go-config panic See: https://github.com/micro/go-config/issues/49 --- cmd/cmd.go | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/cmd/cmd.go b/cmd/cmd.go index c2e4b5ed..2ed2954a 100644 --- a/cmd/cmd.go +++ b/cmd/cmd.go @@ -87,6 +87,11 @@ var ( EnvVar: "MICRO_REGISTER_INTERVAL", Usage: "Register interval in seconds", }, + cli.StringFlag{ + Name: "server", + EnvVar: "MICRO_SERVER", + Usage: "Server for go-micro; rpc", + }, cli.StringFlag{ Name: "server_name", EnvVar: "MICRO_SERVER_NAME", @@ -144,11 +149,6 @@ var ( Usage: "Selector used to pick nodes for querying", Value: "cache", }, - cli.StringFlag{ - Name: "server", - EnvVar: "MICRO_SERVER", - Usage: "Server for go-micro; rpc", - }, cli.StringFlag{ Name: "transport", EnvVar: "MICRO_TRANSPORT", From 446d3fc72e7fd3027da5fb1586309487150bc963 Mon Sep 17 00:00:00 2001 From: fireyang Date: Wed, 19 Sep 2018 21:58:20 +0800 Subject: [PATCH 006/196] fix bug: loop variable i captured by func literal --- client/rpc_client.go | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/client/rpc_client.go b/client/rpc_client.go index 8ed51f07..681e6298 100644 --- a/client/rpc_client.go +++ b/client/rpc_client.go @@ -7,6 +7,8 @@ import ( "sync" "time" + "sync/atomic" + "github.com/micro/go-micro/broker" "github.com/micro/go-micro/codec" "github.com/micro/go-micro/errors" @@ -14,7 +16,6 @@ import ( "github.com/micro/go-micro/registry" "github.com/micro/go-micro/selector" "github.com/micro/go-micro/transport" - "sync/atomic" ) type rpcClient struct { @@ -322,9 +323,9 @@ func (r *rpcClient) Call(ctx context.Context, request Request, response interfac var gerr error for i := 0; i <= callOpts.Retries; i++ { - go func() { + go func(i int) { ch <- call(i) - }() + }(i) select { case <-ctx.Done(): From ef8b5e28b0d32837974bc1204855de0b1fb5a0c3 Mon Sep 17 00:00:00 2001 From: fireyang Date: Thu, 20 Sep 2018 10:08:00 +0800 Subject: [PATCH 007/196] fix rpc client call WARNING: DATA RACE --- client/rpc_client.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/client/rpc_client.go b/client/rpc_client.go index 681e6298..d46fdcd7 100644 --- a/client/rpc_client.go +++ b/client/rpc_client.go @@ -89,7 +89,7 @@ func (r *rpcClient) call(ctx context.Context, address string, req Request, resp r.pool.release(address, c, grr) }() - seq := r.seq + seq := atomic.LoadUint64(&r.seq) atomic.AddUint64(&r.seq, 1) stream := &rpcStream{ From fd047227065e4e635942b7a2ec81f5545b6b9ccc Mon Sep 17 00:00:00 2001 From: lovelly <840635577@qq.com> Date: Tue, 9 Oct 2018 10:40:24 +0800 Subject: [PATCH 008/196] Fix tcp check no ttl error --- registry/consul_registry.go | 19 +++++++++++++++---- 1 file changed, 15 insertions(+), 4 deletions(-) diff --git a/registry/consul_registry.go b/registry/consul_registry.go index e8de9ead..6540c2a7 100644 --- a/registry/consul_registry.go +++ b/registry/consul_registry.go @@ -180,10 +180,21 @@ func (c *consulRegistry) Register(s *Service, opts ...RegisterOption) error { // if it's already registered and matches then just pass the check if ok && v == h { - // if the err is nil we're all good, bail out - // if not, we don't know what the state is, so full re-register - if err := c.Client.Agent().PassTTL("service:"+node.Id, ""); err == nil { - return nil + if options.TTL == time.Duration(0) { + services,_, err := c.Client.Health().Checks(s.Name, nil) + if err == nil { + for _, v := range services { + if v.ServiceID == node.Id { + return nil + } + } + } + }else{ + // if the err is nil we're all good, bail out + // if not, we don't know what the state is, so full re-register + if err := c.Client.Agent().PassTTL("service:"+node.Id, ""); err == nil { + return nil + } } } From 4c821baab49fcb0db9cf6d1623ef29ab4d297a97 Mon Sep 17 00:00:00 2001 From: Asim Aslam Date: Sat, 3 Nov 2018 12:17:11 +0000 Subject: [PATCH 009/196] go fmt --- registry/consul_registry.go | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/registry/consul_registry.go b/registry/consul_registry.go index 6540c2a7..6b45d112 100644 --- a/registry/consul_registry.go +++ b/registry/consul_registry.go @@ -181,7 +181,7 @@ func (c *consulRegistry) Register(s *Service, opts ...RegisterOption) error { // if it's already registered and matches then just pass the check if ok && v == h { if options.TTL == time.Duration(0) { - services,_, err := c.Client.Health().Checks(s.Name, nil) + services, _, err := c.Client.Health().Checks(s.Name, nil) if err == nil { for _, v := range services { if v.ServiceID == node.Id { @@ -189,7 +189,7 @@ func (c *consulRegistry) Register(s *Service, opts ...RegisterOption) error { } } } - }else{ + } else { // if the err is nil we're all good, bail out // if not, we don't know what the state is, so full re-register if err := c.Client.Agent().PassTTL("service:"+node.Id, ""); err == nil { @@ -219,7 +219,7 @@ func (c *consulRegistry) Register(s *Service, opts ...RegisterOption) error { deregTTL := getDeregisterTTL(options.TTL) check = &consul.AgentServiceCheck{ - TTL: fmt.Sprintf("%v", options.TTL), + TTL: fmt.Sprintf("%v", options.TTL), DeregisterCriticalServiceAfter: fmt.Sprintf("%v", deregTTL), } } From 4006d9f1023ed9fc17f6657013abd23f57543edd Mon Sep 17 00:00:00 2001 From: Mikhail Grachev Date: Tue, 13 Nov 2018 11:56:21 +0300 Subject: [PATCH 010/196] Add errors check --- broker/http_broker.go | 6 +++--- codec/jsonrpc/jsonrpc.go | 3 ++- codec/protorpc/protorpc.go | 11 ++++++++--- 3 files changed, 13 insertions(+), 7 deletions(-) diff --git a/broker/http_broker.go b/broker/http_broker.go index 48a110c6..a3e814fe 100644 --- a/broker/http_broker.go +++ b/broker/http_broker.go @@ -176,7 +176,7 @@ func (h *httpBroker) unsubscribe(s *httpSubscriber) error { for _, sub := range h.subscribers[s.topic] { // deregister and skip forward if sub.id == s.id { - h.r.Deregister(sub.svc) + _ = h.r.Deregister(sub.svc) continue } // keep subscriber @@ -200,7 +200,7 @@ func (h *httpBroker) run(l net.Listener) { h.RLock() for _, subs := range h.subscribers { for _, sub := range subs { - h.r.Register(sub.svc, registry.RegisterTTL(registerTTL)) + _ = h.r.Register(sub.svc, registry.RegisterTTL(registerTTL)) } } h.RUnlock() @@ -210,7 +210,7 @@ func (h *httpBroker) run(l net.Listener) { h.RLock() for _, subs := range h.subscribers { for _, sub := range subs { - h.r.Deregister(sub.svc) + _ = h.r.Deregister(sub.svc) } } h.RUnlock() diff --git a/codec/jsonrpc/jsonrpc.go b/codec/jsonrpc/jsonrpc.go index e73c35c6..0a22aeb6 100644 --- a/codec/jsonrpc/jsonrpc.go +++ b/codec/jsonrpc/jsonrpc.go @@ -54,7 +54,8 @@ func (j *jsonCodec) ReadHeader(m *codec.Message, mt codec.MessageType) error { case codec.Response: return j.c.ReadHeader(m) case codec.Publication: - io.Copy(j.buf, j.rwc) + _, err := io.Copy(j.buf, j.rwc) + return err default: return fmt.Errorf("Unrecognised message type: %v", mt) } diff --git a/codec/protorpc/protorpc.go b/codec/protorpc/protorpc.go index 22eecd7f..c2b63433 100644 --- a/codec/protorpc/protorpc.go +++ b/codec/protorpc/protorpc.go @@ -55,7 +55,9 @@ func (c *protoCodec) Write(m *codec.Message, b interface{}) error { return err } if flusher, ok := c.rwc.(flusher); ok { - err = flusher.Flush() + if err = flusher.Flush(); err != nil { + return err + } } case codec.Response: c.Lock() @@ -82,7 +84,9 @@ func (c *protoCodec) Write(m *codec.Message, b interface{}) error { return err } if flusher, ok := c.rwc.(flusher); ok { - err = flusher.Flush() + if err = flusher.Flush(); err != nil { + return err + } } case codec.Publication: data, err := proto.Marshal(b.(proto.Message)) @@ -127,7 +131,8 @@ func (c *protoCodec) ReadHeader(m *codec.Message, mt codec.MessageType) error { m.Id = rtmp.GetSeq() m.Error = rtmp.GetError() case codec.Publication: - io.Copy(c.buf, c.rwc) + _, err := io.Copy(c.buf, c.rwc) + return err default: return fmt.Errorf("Unrecognised message type: %v", mt) } From 25e6dcc9b6343cdf18dc50687533a6b99bf6933d Mon Sep 17 00:00:00 2001 From: Mikhail Grachev Date: Tue, 13 Nov 2018 11:57:42 +0300 Subject: [PATCH 011/196] Fix some linter issues --- selector/cache/cache.go | 2 -- selector/default.go | 2 -- selector/filter_test.go | 4 ++-- server/rpc_service.go | 2 +- 4 files changed, 3 insertions(+), 7 deletions(-) diff --git a/selector/cache/cache.go b/selector/cache/cache.go index 529ae65a..482c068b 100644 --- a/selector/cache/cache.go +++ b/selector/cache/cache.go @@ -366,11 +366,9 @@ func (c *cacheSelector) Select(service string, opts ...selector.SelectOption) (s } func (c *cacheSelector) Mark(service string, node *registry.Node, err error) { - return } func (c *cacheSelector) Reset(service string) { - return } // Close stops the watcher and destroys the cache diff --git a/selector/default.go b/selector/default.go index 4a35c00a..72abfc1b 100644 --- a/selector/default.go +++ b/selector/default.go @@ -48,11 +48,9 @@ func (r *defaultSelector) Select(service string, opts ...SelectOption) (Next, er } func (r *defaultSelector) Mark(service string, node *registry.Node, err error) { - return } func (r *defaultSelector) Reset(service string) { - return } func (r *defaultSelector) Close() error { diff --git a/selector/filter_test.go b/selector/filter_test.go index 9b3c27a9..5a3e9c0d 100644 --- a/selector/filter_test.go +++ b/selector/filter_test.go @@ -80,7 +80,7 @@ func TestFilterEndpoint(t *testing.T) { } } - if seen == false && data.count > 0 { + if !seen && data.count > 0 { t.Fatalf("Expected %d services but seen is %t; result %+v", data.count, seen, services) } } @@ -232,7 +232,7 @@ func TestFilterVersion(t *testing.T) { seen = true } - if seen == false && data.count > 0 { + if !seen && data.count > 0 { t.Fatalf("Expected %d services but seen is %t; result %+v", data.count, seen, services) } } diff --git a/server/rpc_service.go b/server/rpc_service.go index 776f4441..14b667c9 100644 --- a/server/rpc_service.go +++ b/server/rpc_service.go @@ -199,7 +199,7 @@ func (server *server) register(rcvr interface{}) error { return nil } -func (server *server) sendResponse(sending *sync.Mutex, req *request, reply interface{}, codec serverCodec, errmsg string, last bool) (err error) { +func (server *server) sendResponse(sending sync.Locker, req *request, reply interface{}, codec serverCodec, errmsg string, last bool) (err error) { resp := server.getResponse() // Encode the response header resp.ServiceMethod = req.ServiceMethod From 302ab42a9772a697cf8634489df4ea440b98ed5a Mon Sep 17 00:00:00 2001 From: Asim Aslam Date: Wed, 14 Nov 2018 15:18:13 +0000 Subject: [PATCH 012/196] strip down readme --- README.md | 426 +----------------------------------------------------- 1 file changed, 2 insertions(+), 424 deletions(-) diff --git a/README.md b/README.md index 368d6cea..8ffe795c 100644 --- a/README.md +++ b/README.md @@ -20,436 +20,14 @@ Go Micro abstracts away the details of distributed systems. Here are the main fe Go Micro supports both the Service and Function programming models. Read on to learn more. -## Docs +## Getting Started -For more detailed information on the architecture, installation and use of go-micro checkout the [docs](https://micro.mu/docs). +For detailed information on the architecture, installation and use of go-micro checkout the [docs](https://micro.mu/docs). ## Learn By Example An example service can be found in [**examples/service**](https://github.com/micro/examples/tree/master/service) and function in [**examples/function**](https://github.com/micro/examples/tree/master/function). -The [**examples**](https://github.com/micro/examples) directory contains examples for using things such as middleware/wrappers, selector filters, pub/sub, grpc, plugins and much more. For the complete greeter example look at [**examples/greeter**](https://github.com/micro/examples/tree/master/greeter). Other examples can be found throughout the GitHub repository. - -Watch the [Golang UK Conf 2016](https://www.youtube.com/watch?v=xspaDovwk34) video for a high level overview. - -## Getting started - -- [Install Protobuf](#install-protobuf) -- [Service Discovery](#service-discovery) -- [Writing a Service](#writing-a-service) -- [Writing a Function](#writing-a-function) -- [Publish & Subscribe](#publish--subscribe) -- [Plugins](#plugins) -- [Wrappers](#wrappers) - -## Install Protobuf - -Protobuf is required for code generation - -You'll need to install: - -- [protoc-gen-micro](https://github.com/micro/protoc-gen-micro) - -## Service Discovery - -Service discovery is used to resolve service names to addresses. - -### Consul - -[Consul](https://www.consul.io/) is used as the default service discovery system. - -Discovery is pluggable. Find plugins for etcd, kubernetes, zookeeper and more in the [micro/go-plugins](https://github.com/micro/go-plugins) repo. - -[Install guide](https://www.consul.io/intro/getting-started/install.html) - -### Multicast DNS - -[Multicast DNS](https://en.wikipedia.org/wiki/Multicast_DNS) is a built in service discovery plugin for a zero dependency configuration. - -Pass `--registry=mdns` to any command or the enviroment variable `MICRO_REGISTRY=mdns` - -``` -MICRO_REGISTRY=mdns go run main.go -``` - -## Writing a service - -This is a simple greeter RPC service example - -Find this example at [examples/service](https://github.com/micro/examples/tree/master/service). - -### Create service proto - -One of the key requirements of microservices is strongly defined interfaces. Micro uses protobuf to achieve this. - -Here we define the Greeter handler with the method Hello. It takes a HelloRequest and HelloResponse both with one string arguments. - -```proto -syntax = "proto3"; - -service Greeter { - rpc Hello(HelloRequest) returns (HelloResponse) {} -} - -message HelloRequest { - string name = 1; -} - -message HelloResponse { - string greeting = 2; -} -``` - -### Generate the proto - -After writing the proto definition we must compile it using protoc with the micro plugin. - -```shell -protoc --proto_path=$GOPATH/src:. --micro_out=. --go_out=. path/to/greeter.proto -``` - -### Write the service - -Below is the code for the greeter service. - -It does the following: - -1. Implements the interface defined for the Greeter handler -2. Initialises a micro.Service -3. Registers the Greeter handler -4. Runs the service - -```go -package main - -import ( - "context" - "fmt" - - micro "github.com/micro/go-micro" - proto "github.com/micro/examples/service/proto" -) - -type Greeter struct{} - -func (g *Greeter) Hello(ctx context.Context, req *proto.HelloRequest, rsp *proto.HelloResponse) error { - rsp.Greeting = "Hello " + req.Name - return nil -} - -func main() { - // Create a new service. Optionally include some options here. - service := micro.NewService( - micro.Name("greeter"), - ) - - // Init will parse the command line flags. - service.Init() - - // Register handler - proto.RegisterGreeterHandler(service.Server(), new(Greeter)) - - // Run the server - if err := service.Run(); err != nil { - fmt.Println(err) - } -} -``` - -### Run service -``` -go run examples/service/main.go -``` - -Output -``` -2016/03/14 10:59:14 Listening on [::]:50137 -2016/03/14 10:59:14 Broker Listening on [::]:50138 -2016/03/14 10:59:14 Registering node: greeter-ca62b017-e9d3-11e5-9bbb-68a86d0d36b6 -``` - -### Define a client - -Below is the client code to query the greeter service. - -The generated proto includes a greeter client to reduce boilerplate code. - -```go -package main - -import ( - "context" - "fmt" - - micro "github.com/micro/go-micro" - proto "github.com/micro/examples/service/proto" -) - - -func main() { - // Create a new service. Optionally include some options here. - service := micro.NewService(micro.Name("greeter.client")) - service.Init() - - // Create new greeter client - greeter := proto.NewGreeterService("greeter", service.Client()) - - // Call the greeter - rsp, err := greeter.Hello(context.TODO(), &proto.HelloRequest{Name: "John"}) - if err != nil { - fmt.Println(err) - } - - // Print response - fmt.Println(rsp.Greeting) -} -``` - -### Run the client - -```shell -go run client.go -``` - -Output -``` -Hello John -``` - -## Writing a Function - -Go Micro includes the Function programming model. - -A Function is a one time executing Service which exits after completing a request. - -### Defining a Function - -```go -package main - -import ( - "context" - - proto "github.com/micro/examples/function/proto" - "github.com/micro/go-micro" -) - -type Greeter struct{} - -func (g *Greeter) Hello(ctx context.Context, req *proto.HelloRequest, rsp *proto.HelloResponse) error { - rsp.Greeting = "Hello " + req.Name - return nil -} - -func main() { - // create a new function - fnc := micro.NewFunction( - micro.Name("greeter"), - ) - - // init the command line - fnc.Init() - - // register a handler - fnc.Handle(new(Greeter)) - - // run the function - fnc.Run() -} -``` - -It's that simple. - -## Publish & Subscribe - -Go-micro has a built in message broker interface for event driven architectures. - -PubSub operates on the same protobuf generated messages as RPC. They are encoded/decoded automatically and sent via the broker. -By default go-micro includes a point-to-point http broker but this can be swapped out via go-plugins. - -### Publish - - -Create a new publisher with a `topic` name and service client - -```go -p := micro.NewPublisher("events", service.Client()) -``` - -Publish a proto message - -```go -p.Publish(context.TODO(), &proto.Event{Name: "event"}) -``` - -### Subscribe - -Create a message handler. It's signature should be `func(context.Context, v interface{}) error`. - -```go -func ProcessEvent(ctx context.Context, event *proto.Event) error { - fmt.Printf("Got event %+v\n", event) - return nil -} -``` - -Register the message handler with a `topic` - -```go -micro.RegisterSubscriber("events", ProcessEvent) -``` - -See [examples/pubsub](https://github.com/micro/examples/tree/master/pubsub) for a complete example. - -## Plugins - -By default go-micro only provides a few implementation of each interface at the core but it's completely pluggable. There's already dozens of plugins which are available at [github.com/micro/go-plugins](https://github.com/micro/go-plugins). Contributions are welcome! - -### Build with plugins - -If you want to integrate plugins simply link them in a separate file and rebuild - -Create a plugins.go file - -```go -import ( - // etcd v3 registry - _ "github.com/micro/go-plugins/registry/etcdv3" - // nats transport - _ "github.com/micro/go-plugins/transport/nats" - // kafka broker - _ "github.com/micro/go-plugins/broker/kafka" -) -``` - -Build binary - -```shell -// For local use -go build -i -o service ./main.go ./plugins.go -``` - -Flag usage of plugins -```shell -service --registry=etcdv3 --transport=nats --broker=kafka -``` - -### Plugin as option - -Alternatively you can set the plugin as an option to a service - -```go - -import ( - "github.com/micro/go-micro" - // etcd v3 registry - "github.com/micro/go-plugins/registry/etcdv3" - // nats transport - "github.com/micro/go-plugins/transport/nats" - // kafka broker - "github.com/micro/go-plugins/broker/kafka" -) - -func main() { - registry := etcdv3.NewRegistry() - broker := kafka.NewBroker() - transport := nats.NewTransport() - - service := micro.NewService( - micro.Name("greeter"), - micro.Registry(registry), - micro.Broker(broker), - micro.Transport(transport), - ) - - service.Init() - service.Run() -} -``` - -### Write plugins - -Plugins are a concept built on Go's interface. Each package maintains a high level interface abstraction. -Simply implement the interface and pass it in as an option to the service. - -The service discovery interface is called [Registry](https://godoc.org/github.com/micro/go-micro/registry#Registry). -Anything which implements this interface can be used as a registry. The same applies to the other packages. - -```go -type Registry interface { - Register(*Service, ...RegisterOption) error - Deregister(*Service) error - GetService(string) ([]*Service, error) - ListServices() ([]*Service, error) - Watch() (Watcher, error) - String() string -} -``` - -Browse [go-plugins](https://github.com/micro/go-plugins) to get a better idea of implementation details. - -## Wrappers - -Go-micro includes the notion of middleware as wrappers. The client or handlers can be wrapped using the decorator pattern. - -### Handler - -Here's an example service handler wrapper which logs the incoming request - -```go -// implements the server.HandlerWrapper -func logWrapper(fn server.HandlerFunc) server.HandlerFunc { - return func(ctx context.Context, req server.Request, rsp interface{}) error { - fmt.Printf("[%v] server request: %s", time.Now(), req.Method()) - return fn(ctx, req, rsp) - } -} -``` - -It can be initialised when creating the service - -```go -service := micro.NewService( - micro.Name("greeter"), - // wrap the handler - micro.WrapHandler(logWrapper), -) -``` - -### Client - -Here's an example of a client wrapper which logs requests made - -```go -type logWrapper struct { - client.Client -} - -func (l *logWrapper) Call(ctx context.Context, req client.Request, rsp interface{}, opts ...client.CallOption) error { - fmt.Printf("[wrapper] client request to service: %s method: %s\n", req.Service(), req.Method()) - return l.Client.Call(ctx, req, rsp) -} - -// implements client.Wrapper as logWrapper -func logWrap(c client.Client) client.Client { - return &logWrapper{c} -} -``` - -It can be initialised when creating the service - -```go -service := micro.NewService( - micro.Name("greeter"), - // wrap the client - micro.WrapClient(logWrap), -) -``` - -## Other Languages - -Check out [ja-micro](https://github.com/Sixt/ja-micro) to write services in Java - ## Sponsors Sixt is an Enterprise Sponsor of Micro From a082c151f0bdbf9b21081363606713bc3a8b1af0 Mon Sep 17 00:00:00 2001 From: Asim Aslam Date: Wed, 14 Nov 2018 15:18:47 +0000 Subject: [PATCH 013/196] remove example section --- README.md | 4 ---- 1 file changed, 4 deletions(-) diff --git a/README.md b/README.md index 8ffe795c..345aae25 100644 --- a/README.md +++ b/README.md @@ -24,10 +24,6 @@ Go Micro supports both the Service and Function programming models. Read on to l For detailed information on the architecture, installation and use of go-micro checkout the [docs](https://micro.mu/docs). -## Learn By Example - -An example service can be found in [**examples/service**](https://github.com/micro/examples/tree/master/service) and function in [**examples/function**](https://github.com/micro/examples/tree/master/function). - ## Sponsors Sixt is an Enterprise Sponsor of Micro From a0b257b57241eac3ef64ced1eb58750946183d56 Mon Sep 17 00:00:00 2001 From: Asim Aslam Date: Wed, 14 Nov 2018 15:19:23 +0000 Subject: [PATCH 014/196] remove line --- README.md | 2 -- 1 file changed, 2 deletions(-) diff --git a/README.md b/README.md index 345aae25..a5ae1122 100644 --- a/README.md +++ b/README.md @@ -18,8 +18,6 @@ Go Micro abstracts away the details of distributed systems. Here are the main fe - **Sync Streaming** - RPC based communication with support for bidirectional streaming - **Async Messaging** - Native PubSub messaging built in for event driven architectures -Go Micro supports both the Service and Function programming models. Read on to learn more. - ## Getting Started For detailed information on the architecture, installation and use of go-micro checkout the [docs](https://micro.mu/docs). From 71bacf699149dfb3c11955a2876f067c6b3a69cf Mon Sep 17 00:00:00 2001 From: Asim Aslam Date: Wed, 14 Nov 2018 19:41:13 +0000 Subject: [PATCH 015/196] add local/remote ip to socket --- transport/http_transport.go | 40 +++++++++++++++++++++++++++++++------ transport/mock/mock.go | 31 ++++++++++++++++++++-------- transport/transport.go | 2 ++ 3 files changed, 59 insertions(+), 14 deletions(-) diff --git a/transport/http_transport.go b/transport/http_transport.go index e2ee8344..514287b7 100644 --- a/transport/http_transport.go +++ b/transport/http_transport.go @@ -40,6 +40,10 @@ type httpTransportClient struct { r chan *http.Request bl []*http.Request buff *bufio.Reader + + // local/remote ip + local string + remote string } type httpTransportSocket struct { @@ -51,6 +55,10 @@ type httpTransportSocket struct { conn net.Conn // for the first request ch chan *http.Request + + // local/remote ip + local string + remote string } type httpTransportListener struct { @@ -62,6 +70,14 @@ func (b *buffer) Close() error { return nil } +func (h *httpTransportClient) Local() string { + return h.local +} + +func (h *httpTransportClient) Remote() string { + return h.remote +} + func (h *httpTransportClient) Send(m *Message) error { header := make(http.Header) @@ -173,6 +189,14 @@ func (h *httpTransportClient) Close() error { return err } +func (h *httpTransportSocket) Local() string { + return h.local +} + +func (h *httpTransportSocket) Remote() string { + return h.remote +} + func (h *httpTransportSocket) Recv(m *Message) error { if m == nil { return errors.New("message passed in is nil") @@ -368,12 +392,14 @@ func (h *httpTransportListener) Accept(fn func(Socket)) error { ch <- r fn(&httpTransportSocket{ - ht: h.ht, - w: w, - r: r, - rw: buf, - ch: ch, - conn: con, + ht: h.ht, + w: w, + r: r, + rw: buf, + ch: ch, + conn: con, + local: h.Addr(), + remote: r.RemoteAddr, }) }) @@ -430,6 +456,8 @@ func (h *httpTransport) Dial(addr string, opts ...DialOption) (Client, error) { buff: bufio.NewReader(conn), dialOpts: dopts, r: make(chan *http.Request, 1), + local: conn.LocalAddr().String(), + remote: conn.RemoteAddr().String(), }, nil } diff --git a/transport/mock/mock.go b/transport/mock/mock.go index 594af71f..c522c1cd 100644 --- a/transport/mock/mock.go +++ b/transport/mock/mock.go @@ -18,6 +18,9 @@ type mockSocket struct { exit chan bool // listener exit lexit chan bool + + local string + remote string } type mockClient struct { @@ -51,6 +54,14 @@ func (ms *mockSocket) Recv(m *transport.Message) error { return nil } +func (ms *mockSocket) Local() string { + return ms.local +} + +func (ms *mockSocket) Remote() string { + return ms.remote +} + func (ms *mockSocket) Send(m *transport.Message) error { select { case <-ms.exit: @@ -93,10 +104,12 @@ func (m *mockListener) Accept(fn func(transport.Socket)) error { return nil case c := <-m.conn: go fn(&mockSocket{ - lexit: c.lexit, - exit: c.exit, - send: c.recv, - recv: c.send, + lexit: c.lexit, + exit: c.exit, + send: c.recv, + recv: c.send, + local: c.Remote(), + remote: c.Local(), }) } } @@ -118,10 +131,12 @@ func (m *mockTransport) Dial(addr string, opts ...transport.DialOption) (transpo client := &mockClient{ &mockSocket{ - send: make(chan *transport.Message), - recv: make(chan *transport.Message), - exit: make(chan bool), - lexit: listener.exit, + send: make(chan *transport.Message), + recv: make(chan *transport.Message), + exit: make(chan bool), + lexit: listener.exit, + local: addr, + remote: addr, }, options, } diff --git a/transport/transport.go b/transport/transport.go index 313a4196..bee330d4 100644 --- a/transport/transport.go +++ b/transport/transport.go @@ -11,6 +11,8 @@ type Message struct { } type Socket interface { + Local() string + Remote() string Recv(*Message) error Send(*Message) error Close() error From c6a2c8de6c2bcea52ef123d518f4eb071eb81571 Mon Sep 17 00:00:00 2001 From: Asim Aslam Date: Wed, 14 Nov 2018 19:45:46 +0000 Subject: [PATCH 016/196] add local/remote to testsocket --- server/rpc_codec_test.go | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/server/rpc_codec_test.go b/server/rpc_codec_test.go index 76f5094e..9ef8e7fa 100644 --- a/server/rpc_codec_test.go +++ b/server/rpc_codec_test.go @@ -15,6 +15,8 @@ type testCodec struct { } type testSocket struct { + local string + remote string } // TestCodecWriteError simulates what happens when a codec is unable @@ -87,6 +89,14 @@ func (c *testCodec) String() string { return "string" } +func (s testSocket) Local() string { + return s.local +} + +func (s testSocket) Remote() string { + return s.remote +} + func (s testSocket) Recv(message *transport.Message) error { return nil } From 881cb570d57f30b7ba6539580f755d5c49311220 Mon Sep 17 00:00:00 2001 From: Asim Aslam Date: Wed, 14 Nov 2018 19:49:04 +0000 Subject: [PATCH 017/196] reorder --- transport/transport.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/transport/transport.go b/transport/transport.go index bee330d4..4967c81a 100644 --- a/transport/transport.go +++ b/transport/transport.go @@ -11,11 +11,11 @@ type Message struct { } type Socket interface { - Local() string - Remote() string Recv(*Message) error Send(*Message) error Close() error + Local() string + Remote() string } type Client interface { From 0672b051cc1535a910bdf8396a0d45ce2fb6657f Mon Sep 17 00:00:00 2001 From: Asim Aslam Date: Wed, 14 Nov 2018 20:27:58 +0000 Subject: [PATCH 018/196] Add Local/Remote ip to metadata --- server/rpc_server.go | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/server/rpc_server.go b/server/rpc_server.go index a725bf29..76393391 100644 --- a/server/rpc_server.go +++ b/server/rpc_server.go @@ -97,6 +97,10 @@ func (s *rpcServer) accept(sock transport.Socket) { delete(hdr, "Content-Type") delete(hdr, "Timeout") + // set local/remote ips + hdr["Local"] = sock.Local() + hdr["Remote"] = sock.Remote() + ctx := metadata.NewContext(context.Background(), hdr) // set the timeout if we have it From 45f18042b7146079a11d463341e86f25a0cda2aa Mon Sep 17 00:00:00 2001 From: Asim Aslam Date: Thu, 15 Nov 2018 19:55:13 +0000 Subject: [PATCH 019/196] make accept loop --- server/rpc_server.go | 25 ++++++++++++++++++++++++- 1 file changed, 24 insertions(+), 1 deletion(-) diff --git a/server/rpc_server.go b/server/rpc_server.go index 76393391..c55908ab 100644 --- a/server/rpc_server.go +++ b/server/rpc_server.go @@ -397,11 +397,34 @@ func (s *rpcServer) Start() error { s.opts.Address = ts.Addr() s.Unlock() - go ts.Accept(s.accept) + exit := make(chan bool, 1) + + go func() { + for { + err := ts.Accept(s.accept) + + // check if we're supposed to exit + select { + case <-exit: + return + default: + } + + // check the error and backoff + if err != nil { + log.Logf("Accept error: %v", err) + time.Sleep(time.Second) + } + + // no error just exit + return + } + }() go func() { // wait for exit ch := <-s.exit + exit <- true // wait for requests to finish if wait(s.opts.Context) { From e69413b7637fced894570f94d03eafdca317f090 Mon Sep 17 00:00:00 2001 From: Asim Aslam Date: Thu, 15 Nov 2018 21:13:33 +0000 Subject: [PATCH 020/196] add continue --- server/rpc_server.go | 1 + 1 file changed, 1 insertion(+) diff --git a/server/rpc_server.go b/server/rpc_server.go index c55908ab..bd6b04fa 100644 --- a/server/rpc_server.go +++ b/server/rpc_server.go @@ -414,6 +414,7 @@ func (s *rpcServer) Start() error { if err != nil { log.Logf("Accept error: %v", err) time.Sleep(time.Second) + continue } // no error just exit From 1d8047a272ef38ef42b6de4852e7629fe5ebfc83 Mon Sep 17 00:00:00 2001 From: Asim Aslam Date: Sun, 18 Nov 2018 16:32:53 +0000 Subject: [PATCH 021/196] add option to set http handlers --- transport/http/http.go | 2 ++ transport/http/options.go | 23 +++++++++++++++++++++++ transport/http_transport.go | 12 ++++++++++++ 3 files changed, 37 insertions(+) create mode 100644 transport/http/options.go diff --git a/transport/http/http.go b/transport/http/http.go index bafc0bb3..672db54c 100644 --- a/transport/http/http.go +++ b/transport/http/http.go @@ -1,9 +1,11 @@ +// Package http returns a http2 transport using net/http package http import ( "github.com/micro/go-micro/transport" ) +// NewTransport returns a new http transport using net/http and supporting http2 func NewTransport(opts ...transport.Option) transport.Transport { return transport.NewTransport(opts...) } diff --git a/transport/http/options.go b/transport/http/options.go new file mode 100644 index 00000000..2a6e56c5 --- /dev/null +++ b/transport/http/options.go @@ -0,0 +1,23 @@ +package http + +import ( + "context" + "net/http" + + "github.com/micro/go-micro/transport" +) + +// Handle registers the handler for the given pattern. +func Handle(pattern string, handler http.Handler) transport.Option { + return func(o *transport.Options) { + if o.Context == nil { + o.Context = context.Background() + } + handlers, ok := o.Context.Value("http_handlers").(map[string]http.Handler) + if !ok { + handlers = make(map[string]http.Handler) + } + handlers[pattern] = handler + o.Context = context.WithValue(o.Context, "http_handlers", handlers) + } +} diff --git a/transport/http_transport.go b/transport/http_transport.go index 514287b7..76eb6318 100644 --- a/transport/http_transport.go +++ b/transport/http_transport.go @@ -357,6 +357,8 @@ func (h *httpTransportListener) Close() error { func (h *httpTransportListener) Accept(fn func(Socket)) error { // create handler mux mux := http.NewServeMux() + + // register our transport handler mux.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) { var buf *bufio.ReadWriter var con net.Conn @@ -403,6 +405,16 @@ func (h *httpTransportListener) Accept(fn func(Socket)) error { }) }) + // get optional handlers + if h.ht.opts.Context != nil { + handlers, ok := h.ht.opts.Context.Value("http_handlers").(map[string]http.Handler) + if ok { + for pattern, handler := range handlers { + mux.Handle(pattern, handler) + } + } + } + // default http2 server srv := &http.Server{ Handler: mux, From d9fc2c922d578b3220cddf043902b86962f07d77 Mon Sep 17 00:00:00 2001 From: Asim Aslam Date: Sun, 18 Nov 2018 18:38:46 +0000 Subject: [PATCH 022/196] update package comment --- transport/transport.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/transport/transport.go b/transport/transport.go index 4967c81a..6e11e341 100644 --- a/transport/transport.go +++ b/transport/transport.go @@ -1,4 +1,4 @@ -// Package is an interface for synchronous communication +// Package transport is an interface for synchronous communication package transport import ( From 1cb40831a4ef52e974fd5175c537ea04cbd30d91 Mon Sep 17 00:00:00 2001 From: Asim Aslam Date: Sun, 18 Nov 2018 20:40:43 +0000 Subject: [PATCH 023/196] add http handler option for broker --- broker/http/http.go | 2 ++ broker/http/options.go | 23 +++++++++++++++++++++++ broker/http_broker.go | 12 ++++++++++++ 3 files changed, 37 insertions(+) create mode 100644 broker/http/options.go diff --git a/broker/http/http.go b/broker/http/http.go index d54d2f38..7d09986a 100644 --- a/broker/http/http.go +++ b/broker/http/http.go @@ -1,9 +1,11 @@ +// Package http provides a http based message broker package http import ( "github.com/micro/go-micro/broker" ) +// NewBroker returns a new http broker func NewBroker(opts ...broker.Option) broker.Broker { return broker.NewBroker(opts...) } diff --git a/broker/http/options.go b/broker/http/options.go new file mode 100644 index 00000000..03240c42 --- /dev/null +++ b/broker/http/options.go @@ -0,0 +1,23 @@ +package http + +import ( + "context" + "net/http" + + "github.com/micro/go-micro/broker" +) + +// Handle registers the handler for the given pattern. +func Handle(pattern string, handler http.Handler) broker.Option { + return func(o *broker.Options) { + if o.Context == nil { + o.Context = context.Background() + } + handlers, ok := o.Context.Value("http_handlers").(map[string]http.Handler) + if !ok { + handlers = make(map[string]http.Handler) + } + handlers[pattern] = handler + o.Context = context.WithValue(o.Context, "http_handlers", handlers) + } +} diff --git a/broker/http_broker.go b/broker/http_broker.go index a3e814fe..c43d85be 100644 --- a/broker/http_broker.go +++ b/broker/http_broker.go @@ -126,7 +126,19 @@ func newHttpBroker(opts ...Option) Broker { mux: http.NewServeMux(), } + // specify the message handler h.mux.Handle(DefaultSubPath, h) + + // get optional handlers + if h.opts.Context != nil { + handlers, ok := h.opts.Context.Value("http_handlers").(map[string]http.Handler) + if ok { + for pattern, handler := range handlers { + h.mux.Handle(pattern, handler) + } + } + } + return h } From 54f58a15d3ac2d1902eddbd26b16aae756ce0482 Mon Sep 17 00:00:00 2001 From: Asim Aslam Date: Mon, 19 Nov 2018 12:29:26 +0000 Subject: [PATCH 024/196] update readme --- README.md | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/README.md b/README.md index a5ae1122..0efacb35 100644 --- a/README.md +++ b/README.md @@ -1,9 +1,8 @@ # Go Micro [![License](https://img.shields.io/:license-apache-blue.svg)](https://opensource.org/licenses/Apache-2.0) [![GoDoc](https://godoc.org/github.com/micro/go-micro?status.svg)](https://godoc.org/github.com/micro/go-micro) [![Travis CI](https://api.travis-ci.org/micro/go-micro.svg?branch=master)](https://travis-ci.org/micro/go-micro) [![Go Report Card](https://goreportcard.com/badge/micro/go-micro)](https://goreportcard.com/report/github.com/micro/go-micro) -Go Micro is a pluggable RPC framework for distributed systems development. - -The **micro** philosophy is sane defaults with a pluggable architecture. We provide defaults to get you started quickly but everything can be easily swapped out. It comes with built in support for {json,proto}-rpc encoding, consul or multicast dns for service discovery, http for communication and random hashed client side load balancing. +Go Micro is a pluggable framework for microservice development. +The **micro** philosophy is sane defaults with a pluggable architecture. We provide defaults to get you started quickly but everything can be swapped out. Plugins are available at [github.com/micro/go-plugins](https://github.com/micro/go-plugins). Follow us on [Twitter](https://twitter.com/microhq) or join the [Slack](http://slack.micro.mu/) community. @@ -15,8 +14,8 @@ Go Micro abstracts away the details of distributed systems. Here are the main fe - **Service Discovery** - Automatic service registration and name resolution - **Load Balancing** - Client side load balancing built on discovery - **Message Encoding** - Dynamic encoding based on content-type with protobuf and json support -- **Sync Streaming** - RPC based communication with support for bidirectional streaming -- **Async Messaging** - Native PubSub messaging built in for event driven architectures +- **Sync Streaming** - RPC based request/response with support for bidirectional streaming +- **Async Messaging** - Native pubsub messaging built in for event driven architectures ## Getting Started From 3f7152a4f5fe02cc04912e05545dfe16accbfcf2 Mon Sep 17 00:00:00 2001 From: Asim Aslam Date: Mon, 19 Nov 2018 12:30:23 +0000 Subject: [PATCH 025/196] update doc link --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 0efacb35..24eb2f20 100644 --- a/README.md +++ b/README.md @@ -19,7 +19,7 @@ Go Micro abstracts away the details of distributed systems. Here are the main fe ## Getting Started -For detailed information on the architecture, installation and use of go-micro checkout the [docs](https://micro.mu/docs). +For detailed information on the architecture, installation and use of go-micro checkout the [docs](https://micro.mu/docs/go-micro.html). ## Sponsors From 48c068d88dea3411556cbc1d040f8cba4407b040 Mon Sep 17 00:00:00 2001 From: Asim Aslam Date: Tue, 20 Nov 2018 10:06:13 +0000 Subject: [PATCH 026/196] add codec package comments --- codec/jsonrpc/jsonrpc.go | 1 + codec/protorpc/protorpc.go | 1 + 2 files changed, 2 insertions(+) diff --git a/codec/jsonrpc/jsonrpc.go b/codec/jsonrpc/jsonrpc.go index 0a22aeb6..9f9cd6a2 100644 --- a/codec/jsonrpc/jsonrpc.go +++ b/codec/jsonrpc/jsonrpc.go @@ -1,3 +1,4 @@ +// Package jsonrpc provides a json-rpc 1.0 codec package jsonrpc import ( diff --git a/codec/protorpc/protorpc.go b/codec/protorpc/protorpc.go index c2b63433..111026c2 100644 --- a/codec/protorpc/protorpc.go +++ b/codec/protorpc/protorpc.go @@ -1,3 +1,4 @@ +// Protorpc provides a net/rpc proto-rpc codec. See envelope.proto for the format. package protorpc import ( From 172ffee8c38d915f2a4198d9202658a4c0765d16 Mon Sep 17 00:00:00 2001 From: Asim Aslam Date: Tue, 20 Nov 2018 10:30:53 +0000 Subject: [PATCH 027/196] add rpc package comments --- client/rpc/rpc.go | 2 ++ server/rpc/rpc.go | 2 ++ 2 files changed, 4 insertions(+) diff --git a/client/rpc/rpc.go b/client/rpc/rpc.go index 5efff382..70371c05 100644 --- a/client/rpc/rpc.go +++ b/client/rpc/rpc.go @@ -1,9 +1,11 @@ +// Package rpc provides an rpc client package rpc import ( "github.com/micro/go-micro/client" ) +// NewClient returns a new micro client interface func NewClient(opts ...client.Option) client.Client { return client.NewClient(opts...) } diff --git a/server/rpc/rpc.go b/server/rpc/rpc.go index 98e1de1c..38278ffb 100644 --- a/server/rpc/rpc.go +++ b/server/rpc/rpc.go @@ -1,9 +1,11 @@ +// Package rpc provides an rpc server package rpc import ( "github.com/micro/go-micro/server" ) +// NewServer returns a micro server interface func NewServer(opts ...server.Option) server.Server { return server.NewServer(opts...) } From 415fb3a730349252f0f048e01989a5397c6a8e72 Mon Sep 17 00:00:00 2001 From: Shulhan Date: Wed, 21 Nov 2018 17:13:03 +0700 Subject: [PATCH 028/196] all: replace "pborman/uuid" with "google/uuid" Internally, "pborman/uuid.NewUUID()" is calling "google/uuid.New()" that return nil when there is an error [1]. Both package use the same license. [1] https://github.com/pborman/uuid/blob/master/version1.go#L17 --- broker/http_broker.go | 8 ++++---- broker/http_broker_test.go | 6 +++--- broker/mock/mock.go | 4 ++-- server/mock/mock.go | 4 ++-- server/server.go | 4 ++-- 5 files changed, 13 insertions(+), 13 deletions(-) diff --git a/broker/http_broker.go b/broker/http_broker.go index c43d85be..3ff42aa2 100644 --- a/broker/http_broker.go +++ b/broker/http_broker.go @@ -18,6 +18,7 @@ import ( "sync" "time" + "github.com/google/uuid" "github.com/micro/go-log" "github.com/micro/go-micro/broker/codec/json" merr "github.com/micro/go-micro/errors" @@ -26,7 +27,6 @@ import ( maddr "github.com/micro/util/go/lib/addr" mnet "github.com/micro/util/go/lib/net" mls "github.com/micro/util/go/lib/tls" - "github.com/pborman/uuid" ) // HTTP Broker is a point to point async broker @@ -116,7 +116,7 @@ func newHttpBroker(opts ...Option) Broker { } h := &httpBroker{ - id: "broker-" + uuid.NewUUID().String(), + id: "broker-" + uuid.New().String(), address: addr, opts: options, r: reg, @@ -413,7 +413,7 @@ func (h *httpBroker) Init(opts ...Option) error { } if len(h.id) == 0 { - h.id = "broker-" + uuid.NewUUID().String() + h.id = "broker-" + uuid.New().String() } // get registry @@ -520,7 +520,7 @@ func (h *httpBroker) Subscribe(topic string, handler Handler, opts ...SubscribeO } // create unique id - id := h.id + "." + uuid.NewUUID().String() + id := h.id + "." + uuid.New().String() var secure bool diff --git a/broker/http_broker_test.go b/broker/http_broker_test.go index 9a84db29..e987835d 100644 --- a/broker/http_broker_test.go +++ b/broker/http_broker_test.go @@ -5,15 +5,15 @@ import ( "testing" "time" + "github.com/google/uuid" "github.com/micro/go-micro/registry/mock" - "github.com/pborman/uuid" ) func sub(be *testing.B, c int) { be.StopTimer() m := mock.NewRegistry() b := NewBroker(Registry(m)) - topic := uuid.NewUUID().String() + topic := uuid.New().String() if err := b.Init(); err != nil { be.Fatalf("Unexpected init error: %v", err) @@ -72,7 +72,7 @@ func pub(be *testing.B, c int) { be.StopTimer() m := mock.NewRegistry() b := NewBroker(Registry(m)) - topic := uuid.NewUUID().String() + topic := uuid.New().String() if err := b.Init(); err != nil { be.Fatalf("Unexpected init error: %v", err) diff --git a/broker/mock/mock.go b/broker/mock/mock.go index 5a9a323a..842906a2 100644 --- a/broker/mock/mock.go +++ b/broker/mock/mock.go @@ -4,8 +4,8 @@ import ( "errors" "sync" + "github.com/google/uuid" "github.com/micro/go-micro/broker" - "github.com/pborman/uuid" ) type mockBroker struct { @@ -112,7 +112,7 @@ func (m *mockBroker) Subscribe(topic string, handler broker.Handler, opts ...bro sub := &mockSubscriber{ exit: make(chan bool, 1), - id: uuid.NewUUID().String(), + id: uuid.New().String(), topic: topic, handler: handler, opts: options, diff --git a/server/mock/mock.go b/server/mock/mock.go index f853b905..ce2a4671 100644 --- a/server/mock/mock.go +++ b/server/mock/mock.go @@ -4,8 +4,8 @@ import ( "errors" "sync" + "github.com/google/uuid" "github.com/micro/go-micro/server" - "github.com/pborman/uuid" ) type MockServer struct { @@ -69,7 +69,7 @@ func (m *MockServer) NewHandler(h interface{}, opts ...server.HandlerOption) ser } return &MockHandler{ - Id: uuid.NewUUID().String(), + Id: uuid.New().String(), Hdlr: h, Opts: options, } diff --git a/server/server.go b/server/server.go index a320fe8f..6a661266 100644 --- a/server/server.go +++ b/server/server.go @@ -7,8 +7,8 @@ import ( "os/signal" "syscall" + "github.com/google/uuid" "github.com/micro/go-log" - "github.com/pborman/uuid" ) type Server interface { @@ -63,7 +63,7 @@ var ( DefaultAddress = ":0" DefaultName = "go-server" DefaultVersion = "1.0.0" - DefaultId = uuid.NewUUID().String() + DefaultId = uuid.New().String() DefaultServer Server = newRpcServer() ) From edc8a8b771dade6f1bdc83dd41068123520bfd87 Mon Sep 17 00:00:00 2001 From: Asim Aslam Date: Wed, 21 Nov 2018 11:15:34 +0000 Subject: [PATCH 029/196] nitpick --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 24eb2f20..9c6ec0e3 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,6 @@ # Go Micro [![License](https://img.shields.io/:license-apache-blue.svg)](https://opensource.org/licenses/Apache-2.0) [![GoDoc](https://godoc.org/github.com/micro/go-micro?status.svg)](https://godoc.org/github.com/micro/go-micro) [![Travis CI](https://api.travis-ci.org/micro/go-micro.svg?branch=master)](https://travis-ci.org/micro/go-micro) [![Go Report Card](https://goreportcard.com/badge/micro/go-micro)](https://goreportcard.com/report/github.com/micro/go-micro) -Go Micro is a pluggable framework for microservice development. +Go Micro is a pluggable framework for distributed systems development. The **micro** philosophy is sane defaults with a pluggable architecture. We provide defaults to get you started quickly but everything can be swapped out. Plugins are available at [github.com/micro/go-plugins](https://github.com/micro/go-plugins). From 5fd7da9de7fff3f7b5d0d3eecce5b6802f6dd255 Mon Sep 17 00:00:00 2001 From: Asim Aslam Date: Wed, 21 Nov 2018 13:10:09 +0000 Subject: [PATCH 030/196] update readme --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 9c6ec0e3..db33ff13 100644 --- a/README.md +++ b/README.md @@ -19,7 +19,7 @@ Go Micro abstracts away the details of distributed systems. Here are the main fe ## Getting Started -For detailed information on the architecture, installation and use of go-micro checkout the [docs](https://micro.mu/docs/go-micro.html). +See the [docs](https://micro.mu/docs/go-micro.html) for detailed information on the architecture, installation and use of go-micro. ## Sponsors From e3a2fe52cdeeb038f3b752e333fc81759a377e60 Mon Sep 17 00:00:00 2001 From: Blair McMillan Date: Thu, 22 Nov 2018 13:34:08 +1000 Subject: [PATCH 031/196] Only check if the service is in Consul once every deregister interval --- registry/consul_registry.go | 21 ++++++++++++++++----- 1 file changed, 16 insertions(+), 5 deletions(-) diff --git a/registry/consul_registry.go b/registry/consul_registry.go index 6b45d112..af5d0adf 100644 --- a/registry/consul_registry.go +++ b/registry/consul_registry.go @@ -24,6 +24,8 @@ type consulRegistry struct { sync.Mutex register map[string]uint64 + // lastChecked tracks when a node was last checked as existing in Consul + lastChecked map[string]time.Time } func getDeregisterTTL(t time.Duration) time.Duration { @@ -118,8 +120,9 @@ func configure(c *consulRegistry, opts ...Option) { func newConsulRegistry(opts ...Option) Registry { cr := &consulRegistry{ - opts: Options{}, - register: make(map[string]uint64), + opts: Options{}, + register: make(map[string]uint64), + lastChecked: make(map[string]time.Time), } configure(cr, opts...) return cr @@ -135,9 +138,10 @@ func (c *consulRegistry) Deregister(s *Service) error { return errors.New("Require at least one node") } - // delete our hash of the service + // delete our hash and time check of the service c.Lock() delete(c.register, s.Name) + delete(c.lastChecked, s.Name) c.Unlock() node := s.Nodes[0] @@ -181,7 +185,13 @@ func (c *consulRegistry) Register(s *Service, opts ...RegisterOption) error { // if it's already registered and matches then just pass the check if ok && v == h { if options.TTL == time.Duration(0) { - services, _, err := c.Client.Health().Checks(s.Name, nil) + // ensure that our service hasn't been deregistered by Consul + if time.Since(c.lastChecked[s.Name]) <= getDeregisterTTL(regInterval) { + return nil + } + services, _, err := c.Client.Health().Checks(s.Name, &consul.QueryOptions{ + AllowStale: true, + }) if err == nil { for _, v := range services { if v.ServiceID == node.Id { @@ -245,9 +255,10 @@ func (c *consulRegistry) Register(s *Service, opts ...RegisterOption) error { return err } - // save our hash of the service + // save our hash and time check of the service c.Lock() c.register[s.Name] = h + c.lastChecked[s.Name] = time.Now() c.Unlock() // if the TTL is 0 we don't mess with the checks From f1984650f473fa7ecd4ffcb421f3cdf2f8815b49 Mon Sep 17 00:00:00 2001 From: Asim Aslam Date: Thu, 22 Nov 2018 10:39:36 +0000 Subject: [PATCH 032/196] use the request header --- transport/http_transport.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/transport/http_transport.go b/transport/http_transport.go index 76eb6318..b9b37a72 100644 --- a/transport/http_transport.go +++ b/transport/http_transport.go @@ -238,7 +238,7 @@ func (h *httpTransportSocket) Recv(m *Message) error { m.Body = b // set headers - for k, v := range h.r.Header { + for k, v := range r.Header { if len(v) > 0 { m.Header[k] = v[0] } else { From 7171c00e426d5c4f735903ab380d4e1b1f9cd5f8 Mon Sep 17 00:00:00 2001 From: Blair McMillan Date: Fri, 23 Nov 2018 17:11:37 +1000 Subject: [PATCH 033/196] Add ability to specify Consul options and default to AllowStale for all gets --- registry/consul/options.go | 34 ++++++++++++++++++++++++++++++++ registry/consul_registry.go | 23 +++++++++++++++------ registry/consul_registry_test.go | 12 ++++++++--- 3 files changed, 60 insertions(+), 9 deletions(-) diff --git a/registry/consul/options.go b/registry/consul/options.go index 335cb57e..29bc3ee5 100644 --- a/registry/consul/options.go +++ b/registry/consul/options.go @@ -27,6 +27,40 @@ func Config(c *consul.Config) registry.Option { } } +// AllowStale sets whether any Consul server (non-leader) can service +// a read. This allows for lower latency and higher throughput +// at the cost of potentially stale data. +// Works similar to Consul DNS Config option [1]. +// Defaults to true. +// +// [1] https://www.consul.io/docs/agent/options.html#allow_stale +// +func AllowStale(v bool) registry.Option { + return func(o *registry.Options) { + if o.Context == nil { + o.Context = context.Background() + } + o.Context = context.WithValue(o.Context, "consul_allow_stale", v) + } +} + +// QueryOptions specifies the QueryOptions to be used when calling +// Consul. See `Consul API` for more information [1]. +// +// [1] https://godoc.org/github.com/hashicorp/consul/api#QueryOptions +// +func QueryOptions(q *consul.QueryOptions) registry.Option { + return func(o *registry.Options) { + if q == nil { + return + } + if o.Context == nil { + o.Context = context.Background() + } + o.Context = context.WithValue(o.Context, "consul_query_options", q) + } +} + // // TCPCheck will tell the service provider to check the service address // and port every `t` interval. It will enabled only if `t` is greater than 0. diff --git a/registry/consul_registry.go b/registry/consul_registry.go index af5d0adf..52ccf759 100644 --- a/registry/consul_registry.go +++ b/registry/consul_registry.go @@ -22,6 +22,8 @@ type consulRegistry struct { // connect enabled connect bool + queryOptions *consul.QueryOptions + sync.Mutex register map[string]uint64 // lastChecked tracks when a node was last checked as existing in Consul @@ -80,6 +82,14 @@ func configure(c *consulRegistry, opts ...Option) { if cn, ok := c.opts.Context.Value("consul_connect").(bool); ok { c.connect = cn } + + // Use the consul query options passed in the options, if available + if qo, ok := c.opts.Context.Value("consul_query_options").(*consul.QueryOptions); ok && qo != nil { + c.queryOptions = qo + } + if as, ok := c.opts.Context.Value("consul_allow_stale").(bool); ok { + c.queryOptions.AllowStale = as + } } // check if there are any addrs @@ -123,6 +133,9 @@ func newConsulRegistry(opts ...Option) Registry { opts: Options{}, register: make(map[string]uint64), lastChecked: make(map[string]time.Time), + queryOptions: &consul.QueryOptions{ + AllowStale: true, + }, } configure(cr, opts...) return cr @@ -189,9 +202,7 @@ func (c *consulRegistry) Register(s *Service, opts ...RegisterOption) error { if time.Since(c.lastChecked[s.Name]) <= getDeregisterTTL(regInterval) { return nil } - services, _, err := c.Client.Health().Checks(s.Name, &consul.QueryOptions{ - AllowStale: true, - }) + services, _, err := c.Client.Health().Checks(s.Name, c.queryOptions) if err == nil { for _, v := range services { if v.ServiceID == node.Id { @@ -276,9 +287,9 @@ func (c *consulRegistry) GetService(name string) ([]*Service, error) { // if we're connect enabled only get connect services if c.connect { - rsp, _, err = c.Client.Health().Connect(name, "", false, nil) + rsp, _, err = c.Client.Health().Connect(name, "", false, c.queryOptions) } else { - rsp, _, err = c.Client.Health().Service(name, "", false, nil) + rsp, _, err = c.Client.Health().Service(name, "", false, c.queryOptions) } if err != nil { return nil, err @@ -347,7 +358,7 @@ func (c *consulRegistry) GetService(name string) ([]*Service, error) { } func (c *consulRegistry) ListServices() ([]*Service, error) { - rsp, _, err := c.Client.Catalog().Services(nil) + rsp, _, err := c.Client.Catalog().Services(c.queryOptions) if err != nil { return nil, err } diff --git a/registry/consul_registry_test.go b/registry/consul_registry_test.go index 425a5b26..1758cfaa 100644 --- a/registry/consul_registry_test.go +++ b/registry/consul_registry_test.go @@ -7,6 +7,7 @@ import ( "net" "net/http" "testing" + "time" consul "github.com/hashicorp/consul/api" ) @@ -53,9 +54,14 @@ func newConsulTestRegistry(r *mockRegistry) (*consulRegistry, func()) { go newMockServer(r, l) return &consulRegistry{ - Address: cfg.Address, - Client: cl, - register: make(map[string]uint64), + Address: cfg.Address, + Client: cl, + opts: Options{}, + register: make(map[string]uint64), + lastChecked: make(map[string]time.Time), + queryOptions: &consul.QueryOptions{ + AllowStale: true, + }, }, func() { l.Close() } From 34ed5235a3d701c9dd7139a5096357e2db9f8d8d Mon Sep 17 00:00:00 2001 From: Asim Aslam Date: Fri, 23 Nov 2018 20:05:31 +0000 Subject: [PATCH 034/196] rename rpc codec --- server/rpc_codec.go | 14 +++++++------- server/rpc_codec_test.go | 2 +- server/rpc_server.go | 2 +- 3 files changed, 9 insertions(+), 9 deletions(-) diff --git a/server/rpc_codec.go b/server/rpc_codec.go index 7ce3c15d..87a32795 100644 --- a/server/rpc_codec.go +++ b/server/rpc_codec.go @@ -10,7 +10,7 @@ import ( "github.com/pkg/errors" ) -type rpcPlusCodec struct { +type rpcCodec struct { socket transport.Socket codec codec.Codec @@ -47,12 +47,12 @@ func (rwc *readWriteCloser) Close() error { return nil } -func newRpcPlusCodec(req *transport.Message, socket transport.Socket, c codec.NewCodec) serverCodec { +func newRpcCodec(req *transport.Message, socket transport.Socket, c codec.NewCodec) serverCodec { rwc := &readWriteCloser{ rbuf: bytes.NewBuffer(req.Body), wbuf: bytes.NewBuffer(nil), } - r := &rpcPlusCodec{ + r := &rpcCodec{ buf: rwc, codec: c(rwc), req: req, @@ -61,7 +61,7 @@ func newRpcPlusCodec(req *transport.Message, socket transport.Socket, c codec.Ne return r } -func (c *rpcPlusCodec) ReadRequestHeader(r *request, first bool) error { +func (c *rpcCodec) ReadRequestHeader(r *request, first bool) error { m := codec.Message{Header: c.req.Header} if !first { @@ -83,11 +83,11 @@ func (c *rpcPlusCodec) ReadRequestHeader(r *request, first bool) error { return err } -func (c *rpcPlusCodec) ReadRequestBody(b interface{}) error { +func (c *rpcCodec) ReadRequestBody(b interface{}) error { return c.codec.ReadBody(b) } -func (c *rpcPlusCodec) WriteResponse(r *response, body interface{}, last bool) error { +func (c *rpcCodec) WriteResponse(r *response, body interface{}, last bool) error { c.buf.wbuf.Reset() m := &codec.Message{ Method: r.ServiceMethod, @@ -111,7 +111,7 @@ func (c *rpcPlusCodec) WriteResponse(r *response, body interface{}, last bool) e }) } -func (c *rpcPlusCodec) Close() error { +func (c *rpcCodec) Close() error { c.buf.Close() c.codec.Close() return c.socket.Close() diff --git a/server/rpc_codec_test.go b/server/rpc_codec_test.go index 9ef8e7fa..d2aec28a 100644 --- a/server/rpc_codec_test.go +++ b/server/rpc_codec_test.go @@ -38,7 +38,7 @@ func TestCodecWriteError(t *testing.T) { wbuf: new(bytes.Buffer), } - c := rpcPlusCodec{ + c := rpcCodec{ buf: &rwc, codec: &testCodec{ buf: rwc.wbuf, diff --git a/server/rpc_server.go b/server/rpc_server.go index bd6b04fa..171848b0 100644 --- a/server/rpc_server.go +++ b/server/rpc_server.go @@ -87,7 +87,7 @@ func (s *rpcServer) accept(sock transport.Socket) { return } - codec := newRpcPlusCodec(&msg, sock, cf) + codec := newRpcCodec(&msg, sock, cf) // strip our headers hdr := make(map[string]string) From 45c05c4e2b3494e53feb95316d9fe4a245e7a66a Mon Sep 17 00:00:00 2001 From: Asim Aslam Date: Sun, 25 Nov 2018 09:41:28 +0000 Subject: [PATCH 035/196] Add timeout error --- client/rpc_client.go | 12 ++++++------ errors/errors.go | 18 ++++++++++++++---- 2 files changed, 20 insertions(+), 10 deletions(-) diff --git a/client/rpc_client.go b/client/rpc_client.go index d46fdcd7..7b44d7c5 100644 --- a/client/rpc_client.go +++ b/client/rpc_client.go @@ -132,7 +132,7 @@ func (r *rpcClient) call(ctx context.Context, address string, req Request, resp return err case <-ctx.Done(): grr = ctx.Err() - return errors.New("go.micro.client", fmt.Sprintf("request timeout: %v", ctx.Err()), 408) + return errors.Timeout("go.micro.client", fmt.Sprintf("%v", ctx.Err())) } } @@ -192,7 +192,7 @@ func (r *rpcClient) stream(ctx context.Context, address string, req Request, opt case err := <-ch: grr = err case <-ctx.Done(): - grr = errors.New("go.micro.client", fmt.Sprintf("request timeout: %v", ctx.Err()), 408) + grr = errors.Timeout("go.micro.client", fmt.Sprintf("%v", ctx.Err())) } if grr != nil { @@ -274,7 +274,7 @@ func (r *rpcClient) Call(ctx context.Context, request Request, response interfac // should we noop right here? select { case <-ctx.Done(): - return errors.New("go.micro.client", fmt.Sprintf("%v", ctx.Err()), 408) + return errors.Timeout("go.micro.client", fmt.Sprintf("%v", ctx.Err())) default: } @@ -329,7 +329,7 @@ func (r *rpcClient) Call(ctx context.Context, request Request, response interfac select { case <-ctx.Done(): - return errors.New("go.micro.client", fmt.Sprintf("call timeout: %v", ctx.Err()), 408) + return errors.Timeout("go.micro.client", fmt.Sprintf("call timeout: %v", ctx.Err())) case err := <-ch: // if the call succeeded lets bail early if err == nil { @@ -367,7 +367,7 @@ func (r *rpcClient) Stream(ctx context.Context, request Request, opts ...CallOpt // should we noop right here? select { case <-ctx.Done(): - return nil, errors.New("go.micro.client", fmt.Sprintf("%v", ctx.Err()), 408) + return nil, errors.Timeout("go.micro.client", fmt.Sprintf("%v", ctx.Err())) default: } @@ -416,7 +416,7 @@ func (r *rpcClient) Stream(ctx context.Context, request Request, opts ...CallOpt select { case <-ctx.Done(): - return nil, errors.New("go.micro.client", fmt.Sprintf("call timeout: %v", ctx.Err()), 408) + return nil, errors.Timeout("go.micro.client", fmt.Sprintf("call timeout: %v", ctx.Err())) case rsp := <-ch: // if the call succeeded lets bail early if rsp.err == nil { diff --git a/errors/errors.go b/errors/errors.go index 78e06c98..61d340e4 100644 --- a/errors/errors.go +++ b/errors/errors.go @@ -92,13 +92,13 @@ func MethodNotAllowed(id, format string, a ...interface{}) error { } } -// InternalServerError generates a 500 error. -func InternalServerError(id, format string, a ...interface{}) error { +// Timeout generates a 408 error. +func Timeout(id, format string, a ...interface{}) error { return &Error{ Id: id, - Code: 500, + Code: 408, Detail: fmt.Sprintf(format, a...), - Status: http.StatusText(500), + Status: http.StatusText(408), } } @@ -111,3 +111,13 @@ func Conflict(id, format string, a ...interface{}) error { Status: http.StatusText(409), } } + +// InternalServerError generates a 500 error. +func InternalServerError(id, format string, a ...interface{}) error { + return &Error{ + Id: id, + Code: 500, + Detail: fmt.Sprintf(format, a...), + Status: http.StatusText(500), + } +} From 0d917bbf37e76e9b6c3b9da043ac96d075f21aba Mon Sep 17 00:00:00 2001 From: Asim Aslam Date: Mon, 26 Nov 2018 14:51:42 +0000 Subject: [PATCH 036/196] move location of handler --- server/handler.go | 32 -------------------------------- server/server.go | 34 +++++++++++++++++++++++++++++++++- 2 files changed, 33 insertions(+), 33 deletions(-) diff --git a/server/handler.go b/server/handler.go index 5e81e5c3..336b6107 100644 --- a/server/handler.go +++ b/server/handler.go @@ -1,37 +1,5 @@ package server -import ( - "github.com/micro/go-micro/registry" -) - -// Handler interface represents a Service request handler. It's generated -// by passing any type of public concrete object with methods into server.NewHandler. -// Most will pass in a struct. -// -// Example: -// -// type Service struct {} -// -// func (s *Service) Method(context, request, response) error { -// return nil -// } -// -type Handler interface { - Name() string - Handler() interface{} - Endpoints() []*registry.Endpoint - Options() HandlerOptions -} - -// Subscriber interface represents a subscription to a given topic using -// a specific subscriber function or object with methods. -type Subscriber interface { - Topic() string - Subscriber() interface{} - Endpoints() []*registry.Endpoint - Options() SubscriberOptions -} - type HandlerOptions struct { Internal bool Metadata map[string]map[string]string diff --git a/server/server.go b/server/server.go index 6a661266..cdbb4fca 100644 --- a/server/server.go +++ b/server/server.go @@ -9,8 +9,10 @@ import ( "github.com/google/uuid" "github.com/micro/go-log" + "github.com/micro/go-micro/registry" ) +// Server is a simple micro server abstraction type Server interface { Options() Options Init(...Option) error @@ -25,12 +27,14 @@ type Server interface { String() string } +// Message is an async message interface type Message interface { Topic() string Payload() interface{} ContentType() string } +// Request is a synchronous request interface type Request interface { Service() string Method() string @@ -43,7 +47,7 @@ type Request interface { // Stream represents a stream established with a client. // A stream can be bidirectional which is indicated by the request. // The last error will be left in Error(). -// EOF indicated end of the stream. +// EOF indicates end of the stream. type Stream interface { Context() context.Context Request() Request @@ -53,6 +57,34 @@ type Stream interface { Close() error } +// Handler interface represents a request handler. It's generated +// by passing any type of public concrete object with methods into server.NewHandler. +// Most will pass in a struct. +// +// Example: +// +// type Greeter struct {} +// +// func (g *Greeter) Hello(context, request, response) error { +// return nil +// } +// +type Handler interface { + Name() string + Handler() interface{} + Endpoints() []*registry.Endpoint + Options() HandlerOptions +} + +// Subscriber interface represents a subscription to a given topic using +// a specific subscriber function or object with methods. +type Subscriber interface { + Topic() string + Subscriber() interface{} + Endpoints() []*registry.Endpoint + Options() SubscriberOptions +} + type Option func(*Options) type HandlerOption func(*HandlerOptions) From 29bb63b71719a33daeb85a8f82bc8af498490518 Mon Sep 17 00:00:00 2001 From: Asim Aslam Date: Mon, 26 Nov 2018 16:13:17 +0000 Subject: [PATCH 037/196] add mdns package comment --- registry/mdns/mdns.go | 1 + 1 file changed, 1 insertion(+) diff --git a/registry/mdns/mdns.go b/registry/mdns/mdns.go index 6ff6ad10..920df3fa 100644 --- a/registry/mdns/mdns.go +++ b/registry/mdns/mdns.go @@ -1,3 +1,4 @@ +// Package mdns is a multicast dns registry package mdns /* From bc404c9a82581baa0180bd11e21adb5824efdb79 Mon Sep 17 00:00:00 2001 From: Asim Aslam Date: Tue, 27 Nov 2018 19:43:57 +0000 Subject: [PATCH 038/196] update readme --- README.md | 17 ++++++++++++++++- 1 file changed, 16 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index db33ff13..43333c91 100644 --- a/README.md +++ b/README.md @@ -2,7 +2,12 @@ Go Micro is a pluggable framework for distributed systems development. -The **micro** philosophy is sane defaults with a pluggable architecture. We provide defaults to get you started quickly but everything can be swapped out. +## Overview + +Go Micro provides the core requirements for distributed systems development including RPC and Event driven communication. +The **micro** philosophy is sane defaults with a pluggable architecture. We provide defaults to get you started quickly +but everything can be easily swapped out. + Plugins are available at [github.com/micro/go-plugins](https://github.com/micro/go-plugins). Follow us on [Twitter](https://twitter.com/microhq) or join the [Slack](http://slack.micro.mu/) community. @@ -17,6 +22,16 @@ Go Micro abstracts away the details of distributed systems. Here are the main fe - **Sync Streaming** - RPC based request/response with support for bidirectional streaming - **Async Messaging** - Native pubsub messaging built in for event driven architectures +## Defaults + +We provide simple defaults to get you started. + +- Service Discovery - consul or mdns +- Load Balancing - client side random hashed +- Message Encoding - protobuf and json-rpc +- Request/Response - http and http2 +- PubSub Messaging - point to point http + ## Getting Started See the [docs](https://micro.mu/docs/go-micro.html) for detailed information on the architecture, installation and use of go-micro. From 16e97cce9bbe36ad0af0fee279cdacd1ebc2c5f8 Mon Sep 17 00:00:00 2001 From: Asim Aslam Date: Tue, 27 Nov 2018 19:46:00 +0000 Subject: [PATCH 039/196] update readme --- README.md | 20 +++++--------------- 1 file changed, 5 insertions(+), 15 deletions(-) diff --git a/README.md b/README.md index 43333c91..bb5153de 100644 --- a/README.md +++ b/README.md @@ -16,21 +16,11 @@ Follow us on [Twitter](https://twitter.com/microhq) or join the [Slack](http://s Go Micro abstracts away the details of distributed systems. Here are the main features. -- **Service Discovery** - Automatic service registration and name resolution -- **Load Balancing** - Client side load balancing built on discovery -- **Message Encoding** - Dynamic encoding based on content-type with protobuf and json support -- **Sync Streaming** - RPC based request/response with support for bidirectional streaming -- **Async Messaging** - Native pubsub messaging built in for event driven architectures - -## Defaults - -We provide simple defaults to get you started. - -- Service Discovery - consul or mdns -- Load Balancing - client side random hashed -- Message Encoding - protobuf and json-rpc -- Request/Response - http and http2 -- PubSub Messaging - point to point http +- **Service Discovery** - Automatic service registration and name resolution (default: consul or mdns) +- **Load Balancing** - Client side load balancing built on discovery (default: random hashed) +- **Message Encoding** - Dynamic encoding based on content-type (default: protobuf and json-rpc) +- **Sync Streaming** - RPC based request/response with support for bidirectional streaming (default: http/1.1 and http2) +- **Async Messaging** - Native pubsub messaging built in for event driven architectures (default: point to point http) ## Getting Started From f1817c9c6b02732aeaa1ad02feaff065a7c34255 Mon Sep 17 00:00:00 2001 From: Asim Aslam Date: Thu, 29 Nov 2018 09:02:15 +0000 Subject: [PATCH 040/196] Add image to readme --- README.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/README.md b/README.md index bb5153de..8b6faa43 100644 --- a/README.md +++ b/README.md @@ -8,6 +8,8 @@ Go Micro provides the core requirements for distributed systems development incl The **micro** philosophy is sane defaults with a pluggable architecture. We provide defaults to get you started quickly but everything can be easily swapped out. + + Plugins are available at [github.com/micro/go-plugins](https://github.com/micro/go-plugins). Follow us on [Twitter](https://twitter.com/microhq) or join the [Slack](http://slack.micro.mu/) community. From c622f3a8d608622e94f9119a13dc8d41ebc9bd09 Mon Sep 17 00:00:00 2001 From: Asim Aslam Date: Thu, 29 Nov 2018 12:10:33 +0000 Subject: [PATCH 041/196] Force http2 usage of broker client --- broker/http_broker.go | 18 +++++++++++++++++- 1 file changed, 17 insertions(+), 1 deletion(-) diff --git a/broker/http_broker.go b/broker/http_broker.go index 3ff42aa2..dad8ed6c 100644 --- a/broker/http_broker.go +++ b/broker/http_broker.go @@ -27,6 +27,7 @@ import ( maddr "github.com/micro/util/go/lib/addr" mnet "github.com/micro/util/go/lib/net" mls "github.com/micro/util/go/lib/tls" + "golang.org/x/net/http2" ) // HTTP Broker is a point to point async broker @@ -78,6 +79,10 @@ func newTransport(config *tls.Config) *http.Transport { } } + dialTLS := func(network string, addr string) (net.Conn, error) { + return tls.Dial(network, addr, config) + } + t := &http.Transport{ Proxy: http.ProxyFromEnvironment, Dial: (&net.Dialer{ @@ -85,11 +90,15 @@ func newTransport(config *tls.Config) *http.Transport { KeepAlive: 30 * time.Second, }).Dial, TLSHandshakeTimeout: 10 * time.Second, - TLSClientConfig: config, + DialTLS: dialTLS, } runtime.SetFinalizer(&t, func(tr **http.Transport) { (*tr).CloseIdleConnections() }) + + // setup http2 + http2.ConfigureTransport(t) + return t } @@ -430,6 +439,13 @@ func (h *httpBroker) Init(opts ...Option) error { // set registry h.r = rcache.New(reg) + // reconfigure tls config + if c := h.opts.TLSConfig; c != nil { + h.c = &http.Client{ + Transport: newTransport(c), + } + } + return nil } From 92082ac9271477895e3d793f82d95578b1b7f51d Mon Sep 17 00:00:00 2001 From: Asim Aslam Date: Fri, 30 Nov 2018 17:32:48 +0000 Subject: [PATCH 042/196] NewSubscribeOptions --- broker/http_broker.go | 2 +- broker/options.go | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/broker/http_broker.go b/broker/http_broker.go index dad8ed6c..a761a197 100644 --- a/broker/http_broker.go +++ b/broker/http_broker.go @@ -523,7 +523,7 @@ func (h *httpBroker) Publish(topic string, msg *Message, opts ...PublishOption) } func (h *httpBroker) Subscribe(topic string, handler Handler, opts ...SubscribeOption) (Subscriber, error) { - options := newSubscribeOptions(opts...) + options := NewSubscribeOptions(opts...) // parse address for host, port parts := strings.Split(h.Address(), ":") diff --git a/broker/options.go b/broker/options.go index 46136ac9..ae55ede1 100644 --- a/broker/options.go +++ b/broker/options.go @@ -50,7 +50,7 @@ var ( registryKey = contextKeyT("github.com/micro/go-micro/registry") ) -func newSubscribeOptions(opts ...SubscribeOption) SubscribeOptions { +func NewSubscribeOptions(opts ...SubscribeOption) SubscribeOptions { opt := SubscribeOptions{ AutoAck: true, } From 1be0e8776ffaa99a51a8bc3fb1e97a62513b40d8 Mon Sep 17 00:00:00 2001 From: Asim Aslam Date: Sat, 1 Dec 2018 11:10:37 +0000 Subject: [PATCH 043/196] add wrap call comment --- options.go | 1 + 1 file changed, 1 insertion(+) diff --git a/options.go b/options.go index 2eb2c316..ae2008a2 100644 --- a/options.go +++ b/options.go @@ -174,6 +174,7 @@ func RegisterInterval(t time.Duration) Option { // WrapClient is a convenience method for wrapping a Client with // some middleware component. A list of wrappers can be provided. +// Wrappers are applied in reverse order so the last is executed first. func WrapClient(w ...client.Wrapper) Option { return func(o *Options) { // apply in reverse From a1665ab37a56634bd9838a5ef26ef69b9b05e9b8 Mon Sep 17 00:00:00 2001 From: Asim Aslam Date: Sat, 1 Dec 2018 12:54:46 +0000 Subject: [PATCH 044/196] Add consul package comment --- registry/consul/consul.go | 2 ++ 1 file changed, 2 insertions(+) diff --git a/registry/consul/consul.go b/registry/consul/consul.go index c0cc2699..03bc8d89 100644 --- a/registry/consul/consul.go +++ b/registry/consul/consul.go @@ -1,9 +1,11 @@ +// Package consul provides a consul based registry and is the default discovery system package consul import ( "github.com/micro/go-micro/registry" ) +// NewRegistry returns a new consul registry func NewRegistry(opts ...registry.Option) registry.Registry { return registry.NewRegistry(opts...) } From 9c2689301c3a70bb9f79d60a757ac1f23f1b47f3 Mon Sep 17 00:00:00 2001 From: Asim Aslam Date: Sat, 1 Dec 2018 12:56:21 +0000 Subject: [PATCH 045/196] add mock package comments --- broker/mock/mock.go | 1 + client/mock/mock.go | 1 + registry/mock/mock.go | 1 + 3 files changed, 3 insertions(+) diff --git a/broker/mock/mock.go b/broker/mock/mock.go index 842906a2..76c80e5a 100644 --- a/broker/mock/mock.go +++ b/broker/mock/mock.go @@ -1,3 +1,4 @@ +// Package mock provides a mock broker for testing package mock import ( diff --git a/client/mock/mock.go b/client/mock/mock.go index 9a0fd61d..db267530 100644 --- a/client/mock/mock.go +++ b/client/mock/mock.go @@ -1,3 +1,4 @@ +// Package mock provides a mock client for testing package mock import ( diff --git a/registry/mock/mock.go b/registry/mock/mock.go index bd467be6..da690893 100644 --- a/registry/mock/mock.go +++ b/registry/mock/mock.go @@ -1,3 +1,4 @@ +// Package mock provides a mock registry for testing package mock import ( From 519f091fe84b5b528fe054b2c4f74c122da604a2 Mon Sep 17 00:00:00 2001 From: Asim Aslam Date: Sun, 2 Dec 2018 10:23:19 +0000 Subject: [PATCH 046/196] update --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 8b6faa43..0c72db5d 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,6 @@ # Go Micro [![License](https://img.shields.io/:license-apache-blue.svg)](https://opensource.org/licenses/Apache-2.0) [![GoDoc](https://godoc.org/github.com/micro/go-micro?status.svg)](https://godoc.org/github.com/micro/go-micro) [![Travis CI](https://api.travis-ci.org/micro/go-micro.svg?branch=master)](https://travis-ci.org/micro/go-micro) [![Go Report Card](https://goreportcard.com/badge/micro/go-micro)](https://goreportcard.com/report/github.com/micro/go-micro) -Go Micro is a pluggable framework for distributed systems development. +Go Micro is a pluggable framework for micro service development. ## Overview From a07150b6dd8de4f9e6c0014c100adddc34416858 Mon Sep 17 00:00:00 2001 From: Asim Aslam Date: Sun, 2 Dec 2018 13:23:46 +0000 Subject: [PATCH 047/196] update --- README.md | 24 +++++++++++++++++++----- 1 file changed, 19 insertions(+), 5 deletions(-) diff --git a/README.md b/README.md index 0c72db5d..be4294a3 100644 --- a/README.md +++ b/README.md @@ -18,11 +18,25 @@ Follow us on [Twitter](https://twitter.com/microhq) or join the [Slack](http://s Go Micro abstracts away the details of distributed systems. Here are the main features. -- **Service Discovery** - Automatic service registration and name resolution (default: consul or mdns) -- **Load Balancing** - Client side load balancing built on discovery (default: random hashed) -- **Message Encoding** - Dynamic encoding based on content-type (default: protobuf and json-rpc) -- **Sync Streaming** - RPC based request/response with support for bidirectional streaming (default: http/1.1 and http2) -- **Async Messaging** - Native pubsub messaging built in for event driven architectures (default: point to point http) +- **Service Discovery** - Automatic service registration and name resolution. Service discovery is at the core of micro service +development. When service A needs to speak to service B it needs the location of that service. Consul is the default discovery +system with multicast DNS being a local option. + +- **Load Balancing** - Client side load balancing built on service discovery. Once we have the addresses of any number of instances +of a service we now need a way to decide which node to route to. We use random hashed load balancing to provide even distribution +across the services and retry a different node if there's a problem. + +- **Message Encoding** - Dynamic message encoding based on content-type. The client and server will use codecs along with content-type +to seamlessly encode and decode Go types for you. Any variety of messages could be encoded and sent from different clients. The client +and server handle this by default. This includes proto-rpc and json-rpc by default. + +- **Sync Streaming** - RPC based request/response with support for bidirectional streaming. We provide an abstraction for synchronous +communication. A request made to a service will be automatically resolved, load balanced, dialled and streamed. The default +transport is http/1.1 or http2 when tls is enabled. + +- **Async Messaging** - PubSub is built in as a first class citizen for asynchronous communication and event driven architectures. +Event notifications are a core pattern in micro service development. The default messaging is point-to-point http/1.1 or http2 when tls +is enabled. ## Getting Started From d0d8db7c45575dee275b370492dfbd67026d050e Mon Sep 17 00:00:00 2001 From: Asim Aslam Date: Sun, 2 Dec 2018 13:26:38 +0000 Subject: [PATCH 048/196] update --- README.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/README.md b/README.md index be4294a3..96aa622c 100644 --- a/README.md +++ b/README.md @@ -38,6 +38,10 @@ transport is http/1.1 or http2 when tls is enabled. Event notifications are a core pattern in micro service development. The default messaging is point-to-point http/1.1 or http2 when tls is enabled. +- **Pluggable Interfaces** - Go Micro makes use of Go interfaces for each distributed system abstraction. Because of this these interfaces +are pluggable and allows Go Micro to be runtime agnostic. You can plugin any underlying technology. Find plugins in +[github.com/micro/go-plugins](https://github.com/micro/go-plugins). + ## Getting Started See the [docs](https://micro.mu/docs/go-micro.html) for detailed information on the architecture, installation and use of go-micro. From a9593bad66fe0c0983b71378d6028c92b05af62c Mon Sep 17 00:00:00 2001 From: Blair McMillan Date: Mon, 3 Dec 2018 14:59:31 +1000 Subject: [PATCH 049/196] Prevent read/write map concurrency issue --- registry/consul_registry.go | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/registry/consul_registry.go b/registry/consul_registry.go index 52ccf759..02725b5d 100644 --- a/registry/consul_registry.go +++ b/registry/consul_registry.go @@ -190,16 +190,17 @@ func (c *consulRegistry) Register(s *Service, opts ...RegisterOption) error { // use first node node := s.Nodes[0] - // get existing hash + // get existing hash and last checked time c.Lock() v, ok := c.register[s.Name] + lastChecked := c.lastChecked[s.Name] c.Unlock() // if it's already registered and matches then just pass the check if ok && v == h { if options.TTL == time.Duration(0) { // ensure that our service hasn't been deregistered by Consul - if time.Since(c.lastChecked[s.Name]) <= getDeregisterTTL(regInterval) { + if time.Since(lastChecked) <= getDeregisterTTL(regInterval) { return nil } services, _, err := c.Client.Health().Checks(s.Name, c.queryOptions) From 57dcba666e43710c3afd27d630872b7141a5274b Mon Sep 17 00:00:00 2001 From: Asim Aslam Date: Tue, 4 Dec 2018 16:41:40 +0000 Subject: [PATCH 050/196] gossip registry --- registry/gossip/gossip.go | 375 ++++++++++++++++++++++++++ registry/gossip/proto/gossip.micro.go | 28 ++ registry/gossip/proto/gossip.pb.go | 118 ++++++++ registry/gossip/proto/gossip.proto | 19 ++ registry/gossip/util.go | 109 ++++++++ registry/gossip/util_test.go | 78 ++++++ registry/gossip/watcher.go | 40 +++ registry/gossip/watcher_test.go | 5 + registry/registry.go | 3 + 9 files changed, 775 insertions(+) create mode 100644 registry/gossip/gossip.go create mode 100644 registry/gossip/proto/gossip.micro.go create mode 100644 registry/gossip/proto/gossip.pb.go create mode 100644 registry/gossip/proto/gossip.proto create mode 100644 registry/gossip/util.go create mode 100644 registry/gossip/util_test.go create mode 100644 registry/gossip/watcher.go create mode 100644 registry/gossip/watcher_test.go diff --git a/registry/gossip/gossip.go b/registry/gossip/gossip.go new file mode 100644 index 00000000..4e35d873 --- /dev/null +++ b/registry/gossip/gossip.go @@ -0,0 +1,375 @@ +// Package gossip provides a zero dependency registry using the gossip protocol SWIM +package gossip + +import ( + "encoding/json" + "os" + "strings" + "sync" + "time" + + "github.com/golang/protobuf/proto" + "github.com/google/uuid" + "github.com/hashicorp/memberlist" + "github.com/micro/go-log" + "github.com/micro/go-micro/registry" + pb "github.com/micro/go-micro/registry/gossip/proto" +) + +type gossipRegistry struct { + opts registry.Options + queue *memberlist.TransmitLimitedQueue + memberlist *memberlist.Memberlist + delegate *delegate + + sync.RWMutex + services map[string][]*registry.Service + watchers map[string]*watcher +} + +var ( + defaultPort = 8118 +) + +type broadcast struct { + update *pb.Update + notify chan<- struct{} +} + +type delegate struct { + queue *memberlist.TransmitLimitedQueue + registry *gossipRegistry +} + +func (b *broadcast) Invalidates(other memberlist.Broadcast) bool { + up := new(pb.Update) + if err := proto.Unmarshal(other.Message(), up); err != nil { + return false + } + + // ids do not match + if b.update.Id == up.Id { + return false + } + + // timestamps do not match + if b.update.Timestamp != up.Timestamp { + return false + } + + // type does not match + if b.update.Type != up.Type { + return false + } + + // invalidates + return true +} + +func (b *broadcast) Message() []byte { + up, err := proto.Marshal(b.update) + if err != nil { + return nil + } + return up +} + +func (b *broadcast) Finished() { + if b.notify != nil { + close(b.notify) + } +} + +func (d *delegate) NodeMeta(limit int) []byte { + return []byte{} +} + +func (d *delegate) NotifyMsg(b []byte) { + if len(b) == 0 { + return + } + + up := new(pb.Update) + if err := proto.Unmarshal(b, up); err != nil { + return + } + + // only process service action + if up.Type != "service" { + return + } + + var service *registry.Service + + switch up.Metadata["Content-Type"] { + case "application/json": + if err := json.Unmarshal(up.Data, &service); err != nil { + return + } + // no other content type + default: + return + } + + d.registry.Lock() + defer d.registry.Unlock() + + // get existing service + s := d.registry.services[service.Name] + + // save update + switch up.Action { + case "update": + d.registry.services[service.Name] = addServices(s, []*registry.Service{service}) + case "delete": + services := delServices(s, []*registry.Service{service}) + if len(services) == 0 { + delete(d.registry.services, service.Name) + return + } + d.registry.services[service.Name] = services + default: + return + } + + // notify watchers + for _, w := range d.registry.watchers { + select { + case w.ch <- ®istry.Result{Action: up.Action, Service: service}: + default: + } + } +} + +func (d *delegate) GetBroadcasts(overhead, limit int) [][]byte { + return d.queue.GetBroadcasts(overhead, limit) +} + +func (d *delegate) LocalState(join bool) []byte { + d.registry.RLock() + b, _ := json.Marshal(d.registry.services) + d.registry.RUnlock() + return b +} + +func (d *delegate) MergeRemoteState(buf []byte, join bool) { + if len(buf) == 0 { + return + } + if !join { + return + } + var services map[string][]*registry.Service + if err := json.Unmarshal(buf, &services); err != nil { + return + } + + d.registry.Lock() + for k, v := range services { + d.registry.services[k] = addServices(d.registry.services[k], v) + } + d.registry.Unlock() +} + +func (g *gossipRegistry) Init(opts ...registry.Option) error { + addrs := g.opts.Addrs + for _, o := range opts { + o(&g.opts) + } + + // if we have memberlist join it + if len(addrs) != len(g.opts.Addrs) { + _, err := g.memberlist.Join(g.opts.Addrs) + if err != nil { + return err + } + } + + return nil +} + +func (g *gossipRegistry) Options() registry.Options { + return g.opts +} + +func (g *gossipRegistry) Register(s *registry.Service, opts ...registry.RegisterOption) error { + b, err := json.Marshal(s) + if err != nil { + return err + } + + g.Lock() + g.services[s.Name] = addServices(g.services[s.Name], []*registry.Service{s}) + g.Unlock() + + up := &pb.Update{ + Id: uuid.New().String(), + Timestamp: uint64(time.Now().UnixNano()), + Action: "update", + Type: "service", + Metadata: map[string]string{ + "Content-Type": "application/json", + }, + Data: b, + } + + g.queue.QueueBroadcast(&broadcast{ + update: up, + notify: nil, + }) + + return nil +} + +func (g *gossipRegistry) Deregister(s *registry.Service) error { + b, err := json.Marshal(s) + if err != nil { + return err + } + + g.Lock() + g.services[s.Name] = delServices(g.services[s.Name], []*registry.Service{s}) + g.Unlock() + + up := &pb.Update{ + Id: uuid.New().String(), + Timestamp: uint64(time.Now().UnixNano()), + Action: "delete", + Type: "service", + Metadata: map[string]string{ + "Content-Type": "application/json", + }, + Data: b, + } + + g.queue.QueueBroadcast(&broadcast{ + update: up, + notify: nil, + }) + + return nil +} + +func (g *gossipRegistry) GetService(name string) ([]*registry.Service, error) { + g.RLock() + if s, ok := g.services[name]; ok { + service := cp(s) + g.RUnlock() + return service, nil + } + g.RUnlock() + return nil, registry.ErrNotFound +} + +func (g *gossipRegistry) ListServices() ([]*registry.Service, error) { + var services []*registry.Service + g.RLock() + for name, _ := range g.services { + services = append(services, ®istry.Service{Name: name}) + } + g.RUnlock() + return services, nil +} + +func (g *gossipRegistry) Watch(opts ...registry.WatchOption) (registry.Watcher, error) { + var options registry.WatchOptions + for _, o := range opts { + o(&options) + } + + // watcher id + id := uuid.New().String() + + // create watcher + w := &watcher{ + ch: make(chan *registry.Result, 1), + exit: make(chan bool), + id: id, + // filter service + srv: options.Service, + // delete self + fn: func() { + g.Lock() + delete(g.watchers, id) + g.Unlock() + }, + } + + // save watcher + g.Lock() + g.watchers[w.id] = w + g.Unlock() + + return w, nil +} + +func (g *gossipRegistry) String() string { + return "gossip" +} + +func (g *gossipRegistry) run() error { + hostname, _ := os.Hostname() + + // delegates + d := new(delegate) + + // create a new default config + c := memberlist.DefaultLocalConfig() + + // assign the delegate + c.Delegate = d + + // Set the bind port + c.BindPort = defaultPort + + // set the name + c.Name = strings.Join([]string{"micro", hostname, uuid.New().String()}, "-") + + // TODO: set advertise addr to advertise behind nat + + // create the memberlist + m, err := memberlist.Create(c) + if err != nil { + return err + } + + // if we have memberlist join it + if len(g.opts.Addrs) > 0 { + _, err := m.Join(g.opts.Addrs) + if err != nil { + return err + } + } + + // Set the broadcast limit and number of nodes + d.queue = &memberlist.TransmitLimitedQueue{ + NumNodes: func() int { + return m.NumMembers() + }, + RetransmitMult: 3, + } + + g.memberlist = m + g.delegate = d + d.registry = g + + return nil +} + +// NewRegistry returns a new gossip registry +func NewRegistry(opts ...registry.Option) registry.Registry { + var options registry.Options + for _, o := range opts { + o(&options) + } + + g := &gossipRegistry{ + opts: options, + } + if err := g.run(); err != nil { + log.Fatal(err) + } + + // return gossip registry + return g +} diff --git a/registry/gossip/proto/gossip.micro.go b/registry/gossip/proto/gossip.micro.go new file mode 100644 index 00000000..fe9796d9 --- /dev/null +++ b/registry/gossip/proto/gossip.micro.go @@ -0,0 +1,28 @@ +// Code generated by protoc-gen-micro. DO NOT EDIT. +// source: github.com/micro/go-micro/registry/gossip/proto/gossip.proto + +/* +Package gossip is a generated protocol buffer package. + +It is generated from these files: + github.com/micro/go-micro/registry/gossip/proto/gossip.proto + +It has these top-level messages: + Update +*/ +package gossip + +import proto "github.com/golang/protobuf/proto" +import fmt "fmt" +import math "math" + +// Reference imports to suppress errors if they are not otherwise used. +var _ = proto.Marshal +var _ = fmt.Errorf +var _ = math.Inf + +// This is a compile-time assertion to ensure that this generated file +// is compatible with the proto package it is being compiled against. +// A compilation error at this line likely means your copy of the +// proto package needs to be updated. +const _ = proto.ProtoPackageIsVersion2 // please upgrade the proto package diff --git a/registry/gossip/proto/gossip.pb.go b/registry/gossip/proto/gossip.pb.go new file mode 100644 index 00000000..8f2d651c --- /dev/null +++ b/registry/gossip/proto/gossip.pb.go @@ -0,0 +1,118 @@ +// Code generated by protoc-gen-go. DO NOT EDIT. +// source: github.com/micro/go-micro/registry/gossip/proto/gossip.proto + +/* +Package gossip is a generated protocol buffer package. + +It is generated from these files: + github.com/micro/go-micro/registry/gossip/proto/gossip.proto + +It has these top-level messages: + Update +*/ +package gossip + +import proto "github.com/golang/protobuf/proto" +import fmt "fmt" +import math "math" + +// Reference imports to suppress errors if they are not otherwise used. +var _ = proto.Marshal +var _ = fmt.Errorf +var _ = math.Inf + +// This is a compile-time assertion to ensure that this generated file +// is compatible with the proto package it is being compiled against. +// A compilation error at this line likely means your copy of the +// proto package needs to be updated. +const _ = proto.ProtoPackageIsVersion2 // please upgrade the proto package + +// Update is the message broadcast +type Update struct { + // unique id of update + Id string `protobuf:"bytes,1,opt,name=id" json:"id,omitempty"` + // unix nano timestamp of update + Timestamp uint64 `protobuf:"varint,2,opt,name=timestamp" json:"timestamp,omitempty"` + // type of update; service + Type string `protobuf:"bytes,3,opt,name=type" json:"type,omitempty"` + // what action is taken; add, del, put + Action string `protobuf:"bytes,4,opt,name=action" json:"action,omitempty"` + // any other associated metadata about the data + Metadata map[string]string `protobuf:"bytes,5,rep,name=metadata" json:"metadata,omitempty" protobuf_key:"bytes,1,opt,name=key" protobuf_val:"bytes,2,opt,name=value"` + // the payload data; + Data []byte `protobuf:"bytes,6,opt,name=data,proto3" json:"data,omitempty"` +} + +func (m *Update) Reset() { *m = Update{} } +func (m *Update) String() string { return proto.CompactTextString(m) } +func (*Update) ProtoMessage() {} +func (*Update) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{0} } + +func (m *Update) GetId() string { + if m != nil { + return m.Id + } + return "" +} + +func (m *Update) GetTimestamp() uint64 { + if m != nil { + return m.Timestamp + } + return 0 +} + +func (m *Update) GetType() string { + if m != nil { + return m.Type + } + return "" +} + +func (m *Update) GetAction() string { + if m != nil { + return m.Action + } + return "" +} + +func (m *Update) GetMetadata() map[string]string { + if m != nil { + return m.Metadata + } + return nil +} + +func (m *Update) GetData() []byte { + if m != nil { + return m.Data + } + return nil +} + +func init() { + proto.RegisterType((*Update)(nil), "gossip.Update") +} + +func init() { + proto.RegisterFile("github.com/micro/go-micro/registry/gossip/proto/gossip.proto", fileDescriptor0) +} + +var fileDescriptor0 = []byte{ + // 237 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x54, 0x8f, 0xcf, 0x4a, 0xc4, 0x30, + 0x10, 0xc6, 0x49, 0xdb, 0x0d, 0x76, 0xfc, 0x83, 0x0c, 0x22, 0x41, 0xf6, 0x50, 0x3c, 0xf5, 0x62, + 0x0b, 0x7a, 0x59, 0xd4, 0xab, 0x47, 0x2f, 0x01, 0x1f, 0x20, 0xdb, 0x86, 0x1a, 0x34, 0x9b, 0x90, + 0xce, 0x0a, 0x7d, 0x68, 0xdf, 0x41, 0x9a, 0x04, 0xc5, 0xdb, 0xef, 0x37, 0xf9, 0xc2, 0x7c, 0x03, + 0xcf, 0x93, 0xa1, 0xf7, 0xe3, 0xbe, 0x1b, 0x9c, 0xed, 0xad, 0x19, 0x82, 0xeb, 0x27, 0x77, 0x97, + 0x20, 0xe8, 0xc9, 0xcc, 0x14, 0x96, 0x7e, 0x72, 0xf3, 0x6c, 0x7c, 0xef, 0x83, 0x23, 0x97, 0xa5, + 0x8b, 0x82, 0x3c, 0xd9, 0xed, 0x37, 0x03, 0xfe, 0xe6, 0x47, 0x45, 0x1a, 0x2f, 0xa0, 0x30, 0xa3, + 0x60, 0x0d, 0x6b, 0x6b, 0x59, 0x98, 0x11, 0xb7, 0x50, 0x93, 0xb1, 0x7a, 0x26, 0x65, 0xbd, 0x28, + 0x1a, 0xd6, 0x56, 0xf2, 0x6f, 0x80, 0x08, 0x15, 0x2d, 0x5e, 0x8b, 0x32, 0xe6, 0x23, 0xe3, 0x35, + 0x70, 0x35, 0x90, 0x71, 0x07, 0x51, 0xc5, 0x69, 0x36, 0xdc, 0xc1, 0x89, 0xd5, 0xa4, 0x46, 0x45, + 0x4a, 0x6c, 0x9a, 0xb2, 0x3d, 0xbd, 0xdf, 0x76, 0xb9, 0x4d, 0xda, 0xdd, 0xbd, 0xe6, 0xe7, 0x97, + 0x03, 0x85, 0x45, 0xfe, 0xa6, 0xd7, 0x2d, 0xf1, 0x17, 0x6f, 0x58, 0x7b, 0x26, 0x23, 0xdf, 0x3c, + 0xc1, 0xf9, 0xbf, 0x38, 0x5e, 0x42, 0xf9, 0xa1, 0x97, 0xdc, 0x7c, 0x45, 0xbc, 0x82, 0xcd, 0x97, + 0xfa, 0x3c, 0xea, 0x58, 0xbb, 0x96, 0x49, 0x1e, 0x8b, 0x1d, 0xdb, 0xf3, 0x78, 0xfe, 0xc3, 0x4f, + 0x00, 0x00, 0x00, 0xff, 0xff, 0xf0, 0x49, 0xa9, 0xd7, 0x3e, 0x01, 0x00, 0x00, +} diff --git a/registry/gossip/proto/gossip.proto b/registry/gossip/proto/gossip.proto new file mode 100644 index 00000000..75e39cd0 --- /dev/null +++ b/registry/gossip/proto/gossip.proto @@ -0,0 +1,19 @@ +syntax = "proto3"; + +package gossip; + +// Update is the message broadcast +message Update { + // unique id of update + string id = 1; + // unix nano timestamp of update + uint64 timestamp = 2; + // type of update; service + string type = 3; + // what action is taken; add, del, put + string action = 4; + // any other associated metadata about the data + map metadata = 5; + // the payload data; + bytes data = 6; +} diff --git a/registry/gossip/util.go b/registry/gossip/util.go new file mode 100644 index 00000000..67635957 --- /dev/null +++ b/registry/gossip/util.go @@ -0,0 +1,109 @@ +package gossip + +import ( + "github.com/micro/go-micro/registry" +) + +func cp(current []*registry.Service) []*registry.Service { + var services []*registry.Service + + for _, service := range current { + // copy service + s := new(registry.Service) + *s = *service + + // copy nodes + var nodes []*registry.Node + for _, node := range service.Nodes { + n := new(registry.Node) + *n = *node + nodes = append(nodes, n) + } + s.Nodes = nodes + + // copy endpoints + var eps []*registry.Endpoint + for _, ep := range service.Endpoints { + e := new(registry.Endpoint) + *e = *ep + eps = append(eps, e) + } + s.Endpoints = eps + + // append service + services = append(services, s) + } + + return services +} + +func addNodes(old, neu []*registry.Node) []*registry.Node { + for _, n := range neu { + var seen bool + for i, o := range old { + if o.Id == n.Id { + seen = true + old[i] = n + break + } + } + if !seen { + old = append(old, n) + } + } + return old +} + +func addServices(old, neu []*registry.Service) []*registry.Service { + for _, s := range neu { + var seen bool + for i, o := range old { + if o.Version == s.Version { + s.Nodes = addNodes(o.Nodes, s.Nodes) + seen = true + old[i] = s + break + } + } + if !seen { + old = append(old, s) + } + } + return old +} + +func delNodes(old, del []*registry.Node) []*registry.Node { + var nodes []*registry.Node + for _, o := range old { + var rem bool + for _, n := range del { + if o.Id == n.Id { + rem = true + break + } + } + if !rem { + nodes = append(nodes, o) + } + } + return nodes +} + +func delServices(old, del []*registry.Service) []*registry.Service { + var services []*registry.Service + for i, o := range old { + var rem bool + for _, s := range del { + if o.Version == s.Version { + old[i].Nodes = delNodes(o.Nodes, s.Nodes) + if len(old[i].Nodes) == 0 { + rem = true + } + } + } + if !rem { + services = append(services, o) + } + } + return services +} diff --git a/registry/gossip/util_test.go b/registry/gossip/util_test.go new file mode 100644 index 00000000..a77dda52 --- /dev/null +++ b/registry/gossip/util_test.go @@ -0,0 +1,78 @@ +package gossip + +import ( + "testing" + + "github.com/micro/go-micro/registry" +) + +func TestDelServices(t *testing.T) { + services := []*registry.Service{ + { + Name: "foo", + Version: "1.0.0", + Nodes: []*registry.Node{ + { + Id: "foo-123", + Address: "localhost", + Port: 9999, + }, + }, + }, + { + Name: "foo", + Version: "1.0.0", + Nodes: []*registry.Node{ + { + Id: "foo-123", + Address: "localhost", + Port: 6666, + }, + }, + }, + } + + servs := delServices([]*registry.Service{services[0]}, []*registry.Service{services[1]}) + if i := len(servs); i > 0 { + t.Errorf("Expected 0 nodes, got %d: %+v", i, servs) + } + t.Logf("Services %+v", servs) +} + +func TestDelNodes(t *testing.T) { + services := []*registry.Service{ + { + Name: "foo", + Version: "1.0.0", + Nodes: []*registry.Node{ + { + Id: "foo-123", + Address: "localhost", + Port: 9999, + }, + { + Id: "foo-321", + Address: "localhost", + Port: 6666, + }, + }, + }, + { + Name: "foo", + Version: "1.0.0", + Nodes: []*registry.Node{ + { + Id: "foo-123", + Address: "localhost", + Port: 6666, + }, + }, + }, + } + + nodes := delNodes(services[0].Nodes, services[1].Nodes) + if i := len(nodes); i != 1 { + t.Errorf("Expected only 1 node, got %d: %+v", i, nodes) + } + t.Logf("Nodes %+v", nodes) +} diff --git a/registry/gossip/watcher.go b/registry/gossip/watcher.go new file mode 100644 index 00000000..b936ab2f --- /dev/null +++ b/registry/gossip/watcher.go @@ -0,0 +1,40 @@ +package gossip + +import ( + "github.com/micro/go-micro/registry" +) + +type watcher struct { + id string + srv string + ch chan *registry.Result + exit chan bool + fn func() +} + +func (w *watcher) Next() (*registry.Result, error) { + for { + select { + case r := <-w.ch: + if r.Service == nil { + continue + } + if len(w.srv) > 0 && (r.Service.Name != w.srv) { + continue + } + return r, nil + case <-w.exit: + return nil, registry.ErrWatcherStopped + } + } +} + +func (w *watcher) Stop() { + select { + case <-w.exit: + return + default: + close(w.exit) + w.fn() + } +} diff --git a/registry/gossip/watcher_test.go b/registry/gossip/watcher_test.go new file mode 100644 index 00000000..d4efa10b --- /dev/null +++ b/registry/gossip/watcher_test.go @@ -0,0 +1,5 @@ +package gossip + +func TestWatcher(t *testing.T) { + w := newWatcher() +} diff --git a/registry/registry.go b/registry/registry.go index 8cce18db..db13823e 100644 --- a/registry/registry.go +++ b/registry/registry.go @@ -28,7 +28,10 @@ type WatchOption func(*WatchOptions) var ( DefaultRegistry = newConsulRegistry() + // Not found error when GetService is called ErrNotFound = errors.New("not found") + // Watcher stopped error when watcher is stopped + ErrWatcherStopped = errors.New("watcher stopped") ) func NewRegistry(opts ...Option) Registry { From 8706aa4a4614c1bbbbb86a80e2e684d46f697a0f Mon Sep 17 00:00:00 2001 From: Asim Aslam Date: Tue, 4 Dec 2018 16:43:05 +0000 Subject: [PATCH 051/196] Remove file --- registry/gossip/watcher_test.go | 5 ----- 1 file changed, 5 deletions(-) delete mode 100644 registry/gossip/watcher_test.go diff --git a/registry/gossip/watcher_test.go b/registry/gossip/watcher_test.go deleted file mode 100644 index d4efa10b..00000000 --- a/registry/gossip/watcher_test.go +++ /dev/null @@ -1,5 +0,0 @@ -package gossip - -func TestWatcher(t *testing.T) { - w := newWatcher() -} From 72d8dc89fbc4be633a1f4194a812ca8275efbc54 Mon Sep 17 00:00:00 2001 From: Asim Aslam Date: Tue, 4 Dec 2018 17:22:20 +0000 Subject: [PATCH 052/196] add cmd and bug fix --- cmd/cmd.go | 2 ++ registry/gossip/gossip.go | 8 ++++++-- 2 files changed, 8 insertions(+), 2 deletions(-) diff --git a/cmd/cmd.go b/cmd/cmd.go index 2ed2954a..4f23743d 100644 --- a/cmd/cmd.go +++ b/cmd/cmd.go @@ -20,6 +20,7 @@ import ( // registries "github.com/micro/go-micro/registry" "github.com/micro/go-micro/registry/consul" + "github.com/micro/go-micro/registry/gossip" "github.com/micro/go-micro/registry/mdns" // selectors @@ -171,6 +172,7 @@ var ( DefaultRegistries = map[string]func(...registry.Option) registry.Registry{ "consul": consul.NewRegistry, + "gossip": gossip.NewRegistry, "mdns": mdns.NewRegistry, } diff --git a/registry/gossip/gossip.go b/registry/gossip/gossip.go index 4e35d873..27240416 100644 --- a/registry/gossip/gossip.go +++ b/registry/gossip/gossip.go @@ -28,7 +28,8 @@ type gossipRegistry struct { } var ( - defaultPort = 8118 + // defaults to random port + defaultPort = 0 ) type broadcast struct { @@ -349,6 +350,7 @@ func (g *gossipRegistry) run() error { RetransmitMult: 3, } + g.queue = d.queue g.memberlist = m g.delegate = d d.registry = g @@ -364,12 +366,14 @@ func NewRegistry(opts ...registry.Option) registry.Registry { } g := &gossipRegistry{ - opts: options, + opts: options, + services: make(map[string][]*registry.Service), } if err := g.run(); err != nil { log.Fatal(err) } + log.Logf("Registry gossiping at %s", g.memberlist.LocalNode().Address()) // return gossip registry return g } From 1ed2b589a241317eed004a0b9073d28b7456d24d Mon Sep 17 00:00:00 2001 From: Asim Aslam Date: Tue, 4 Dec 2018 17:33:11 +0000 Subject: [PATCH 053/196] log to dev null --- registry/gossip/gossip.go | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/registry/gossip/gossip.go b/registry/gossip/gossip.go index 27240416..71f55a7a 100644 --- a/registry/gossip/gossip.go +++ b/registry/gossip/gossip.go @@ -3,6 +3,7 @@ package gossip import ( "encoding/json" + "io/ioutil" "os" "strings" "sync" @@ -326,6 +327,9 @@ func (g *gossipRegistry) run() error { // set the name c.Name = strings.Join([]string{"micro", hostname, uuid.New().String()}, "-") + // log to dev null + c.LogOutput = ioutil.Discard + // TODO: set advertise addr to advertise behind nat // create the memberlist @@ -373,7 +377,7 @@ func NewRegistry(opts ...registry.Option) registry.Registry { log.Fatal(err) } - log.Logf("Registry gossiping at %s", g.memberlist.LocalNode().Address()) + log.Logf("Registry Listening on %s", g.memberlist.LocalNode().Address()) // return gossip registry return g } From b343420af671836ef7d9570d1fdea7914232a5c9 Mon Sep 17 00:00:00 2001 From: Asim Aslam Date: Thu, 6 Dec 2018 18:19:05 +0000 Subject: [PATCH 054/196] update the gossiper --- cmd/cmd.go | 30 +- registry/gossip/gossip.go | 554 +++++++++++++++++++---------- registry/gossip/options.go | 17 + registry/gossip/proto/gossip.pb.go | 109 +++--- registry/gossip/proto/gossip.proto | 10 +- registry/gossip/watcher.go | 43 ++- 6 files changed, 509 insertions(+), 254 deletions(-) create mode 100644 registry/gossip/options.go diff --git a/cmd/cmd.go b/cmd/cmd.go index 4f23743d..8c1aae19 100644 --- a/cmd/cmd.go +++ b/cmd/cmd.go @@ -10,6 +10,7 @@ import ( "time" "github.com/micro/cli" + "github.com/micro/go-log" "github.com/micro/go-micro/client" "github.com/micro/go-micro/server" @@ -301,10 +302,15 @@ func (c *cmd) Before(ctx *cli.Context) error { serverOpts = append(serverOpts, server.Registry(*c.opts.Registry)) clientOpts = append(clientOpts, client.Registry(*c.opts.Registry)) - (*c.opts.Selector).Init(selector.Registry(*c.opts.Registry)) + if err := (*c.opts.Selector).Init(selector.Registry(*c.opts.Registry)); err != nil { + log.Fatalf("Error configuring registry: %v", err) + } + clientOpts = append(clientOpts, client.Selector(*c.opts.Selector)) - (*c.opts.Broker).Init(broker.Registry(*c.opts.Registry)) + if err := (*c.opts.Broker).Init(broker.Registry(*c.opts.Registry)); err != nil { + log.Fatalf("Error configuring broker: %v", err) + } } // Set the selector @@ -349,15 +355,21 @@ func (c *cmd) Before(ctx *cli.Context) error { } if len(ctx.String("broker_address")) > 0 { - (*c.opts.Broker).Init(broker.Addrs(strings.Split(ctx.String("broker_address"), ",")...)) + if err := (*c.opts.Broker).Init(broker.Addrs(strings.Split(ctx.String("broker_address"), ",")...)); err != nil { + log.Fatalf("Error configuring broker: %v", err) + } } if len(ctx.String("registry_address")) > 0 { - (*c.opts.Registry).Init(registry.Addrs(strings.Split(ctx.String("registry_address"), ",")...)) + if err := (*c.opts.Registry).Init(registry.Addrs(strings.Split(ctx.String("registry_address"), ",")...)); err != nil { + log.Fatalf("Error configuring registry: %v", err) + } } if len(ctx.String("transport_address")) > 0 { - (*c.opts.Transport).Init(transport.Addrs(strings.Split(ctx.String("transport_address"), ",")...)) + if err := (*c.opts.Transport).Init(transport.Addrs(strings.Split(ctx.String("transport_address"), ",")...)); err != nil { + log.Fatalf("Error configuring transport: %v", err) + } } if len(ctx.String("server_name")) > 0 { @@ -412,12 +424,16 @@ func (c *cmd) Before(ctx *cli.Context) error { // We have some command line opts for the server. // Lets set it up if len(serverOpts) > 0 { - (*c.opts.Server).Init(serverOpts...) + if err := (*c.opts.Server).Init(serverOpts...); err != nil { + log.Fatalf("Error configuring server: %v", err) + } } // Use an init option? if len(clientOpts) > 0 { - (*c.opts.Client).Init(clientOpts...) + if err := (*c.opts.Client).Init(clientOpts...); err != nil { + log.Fatalf("Error configuring client: %v", err) + } } return nil diff --git a/registry/gossip/gossip.go b/registry/gossip/gossip.go index 71f55a7a..99972a24 100644 --- a/registry/gossip/gossip.go +++ b/registry/gossip/gossip.go @@ -1,4 +1,4 @@ -// Package gossip provides a zero dependency registry using the gossip protocol SWIM +// Package Gossip provides a gossip registry based on hashicorp/memberlist package gossip import ( @@ -15,22 +15,13 @@ import ( "github.com/micro/go-log" "github.com/micro/go-micro/registry" pb "github.com/micro/go-micro/registry/gossip/proto" + "github.com/mitchellh/hashstructure" ) -type gossipRegistry struct { - opts registry.Options - queue *memberlist.TransmitLimitedQueue - memberlist *memberlist.Memberlist - delegate *delegate - - sync.RWMutex - services map[string][]*registry.Service - watchers map[string]*watcher -} - -var ( - // defaults to random port - defaultPort = 0 +const ( + addAction = "update" + delAction = "delete" + syncAction = "sync" ) type broadcast struct { @@ -39,8 +30,134 @@ type broadcast struct { } type delegate struct { + queue *memberlist.TransmitLimitedQueue + updates chan *update +} + +type gossipRegistry struct { queue *memberlist.TransmitLimitedQueue - registry *gossipRegistry + updates chan *update + options registry.Options + member *memberlist.Memberlist + interval time.Duration + + sync.RWMutex + services map[string][]*registry.Service + + s sync.RWMutex + watchers map[string]chan *registry.Result +} + +type update struct { + Update *pb.Update + Service *registry.Service + sync chan *registry.Service +} + +var ( + // You should change this if using secure + DefaultSecret = []byte("gossip") + ExpiryTick = time.Second * 5 +) + +func configure(g *gossipRegistry, opts ...registry.Option) error { + // loop through address list and get valid entries + addrs := func(curAddrs []string) []string { + var newAddrs []string + for _, addr := range curAddrs { + if trimAddr := strings.TrimSpace(addr); len(trimAddr) > 0 { + newAddrs = append(newAddrs, trimAddr) + } + } + return newAddrs + } + + // current address list + curAddrs := addrs(g.options.Addrs) + + // parse options + for _, o := range opts { + o(&g.options) + } + + // new address list + newAddrs := addrs(g.options.Addrs) + + // no new nodes and existing member. no configure + if (len(newAddrs) == len(curAddrs)) && g.member != nil { + return nil + } + + // shutdown old member + if g.member != nil { + g.member.Shutdown() + } + + // replace addresses + curAddrs = newAddrs + + // create a queue + queue := &memberlist.TransmitLimitedQueue{ + NumNodes: func() int { + return len(curAddrs) + }, + RetransmitMult: 3, + } + + // machine hostname + hostname, _ := os.Hostname() + + // create a new default config + c := memberlist.DefaultLocalConfig() + + // set bind to random port + c.BindPort = 0 + + // set the name + c.Name = strings.Join([]string{"micro", hostname, uuid.New().String()}, "-") + + // set the delegate + c.Delegate = &delegate{ + updates: g.updates, + queue: queue, + } + + // log to dev null + c.LogOutput = ioutil.Discard + + // set a secret key if secure + if g.options.Secure { + k, ok := g.options.Context.Value(contextSecretKey{}).([]byte) + if !ok { + // use the default secret + k = DefaultSecret + } + c.SecretKey = k + } + + // TODO: set advertise addr to advertise behind nat + + // create the memberlist + m, err := memberlist.Create(c) + if err != nil { + return err + } + + // join the memberlist + if len(curAddrs) > 0 { + _, err := m.Join(curAddrs) + if err != nil { + return err + } + } + + // set internals + g.queue = queue + g.member = m + g.interval = c.GossipInterval + + log.Logf("Registry Listening on %s", m.LocalNode().Address()) + return nil } func (b *broadcast) Invalidates(other memberlist.Broadcast) bool { @@ -91,56 +208,35 @@ func (d *delegate) NotifyMsg(b []byte) { return } - up := new(pb.Update) - if err := proto.Unmarshal(b, up); err != nil { - return - } - - // only process service action - if up.Type != "service" { - return - } - - var service *registry.Service - - switch up.Metadata["Content-Type"] { - case "application/json": - if err := json.Unmarshal(up.Data, &service); err != nil { + go func() { + up := new(pb.Update) + if err := proto.Unmarshal(b, up); err != nil { return } - // no other content type - default: - return - } - d.registry.Lock() - defer d.registry.Unlock() - - // get existing service - s := d.registry.services[service.Name] - - // save update - switch up.Action { - case "update": - d.registry.services[service.Name] = addServices(s, []*registry.Service{service}) - case "delete": - services := delServices(s, []*registry.Service{service}) - if len(services) == 0 { - delete(d.registry.services, service.Name) + // only process service action + if up.Type != "service" { return } - d.registry.services[service.Name] = services - default: - return - } - // notify watchers - for _, w := range d.registry.watchers { - select { - case w.ch <- ®istry.Result{Action: up.Action, Service: service}: + var service *registry.Service + + switch up.Metadata["Content-Type"] { + case "application/json": + if err := json.Unmarshal(up.Data, &service); err != nil { + return + } + // no other content type default: + return } - } + + // send update + d.updates <- &update{ + Update: up, + Service: service, + } + }() } func (d *delegate) GetBroadcasts(overhead, limit int) [][]byte { @@ -148,9 +244,25 @@ func (d *delegate) GetBroadcasts(overhead, limit int) [][]byte { } func (d *delegate) LocalState(join bool) []byte { - d.registry.RLock() - b, _ := json.Marshal(d.registry.services) - d.registry.RUnlock() + if !join { + return []byte{} + } + + syncCh := make(chan *registry.Service, 1) + services := map[string][]*registry.Service{} + + d.updates <- &update{ + Update: &pb.Update{ + Action: syncAction, + }, + sync: syncCh, + } + + for srv := range syncCh { + services[srv.Name] = append(services[srv.Name], srv) + } + + b, _ := json.Marshal(services) return b } @@ -161,37 +273,164 @@ func (d *delegate) MergeRemoteState(buf []byte, join bool) { if !join { return } + var services map[string][]*registry.Service if err := json.Unmarshal(buf, &services); err != nil { return } - d.registry.Lock() - for k, v := range services { - d.registry.services[k] = addServices(d.registry.services[k], v) + for _, service := range services { + for _, srv := range service { + d.updates <- &update{ + Update: &pb.Update{Action: addAction}, + Service: srv, + sync: nil, + } + } + } +} + +func (g *gossipRegistry) publish(action string, services []*registry.Service) { + g.s.RLock() + for _, sub := range g.watchers { + go func(sub chan *registry.Result) { + for _, service := range services { + sub <- ®istry.Result{Action: action, Service: service} + } + }(sub) + } + g.s.RUnlock() +} + +func (g *gossipRegistry) subscribe() (chan *registry.Result, chan bool) { + next := make(chan *registry.Result, 10) + exit := make(chan bool) + + id := uuid.New().String() + + g.s.Lock() + g.watchers[id] = next + g.s.Unlock() + + go func() { + <-exit + g.s.Lock() + delete(g.watchers, id) + close(next) + g.s.Unlock() + }() + + return next, exit +} + +func (g *gossipRegistry) run() { + var mtx sync.Mutex + updates := map[uint64]*update{} + + // expiry loop + go func() { + t := time.NewTicker(ExpiryTick) + defer t.Stop() + + for _ = range t.C { + now := uint64(time.Now().UnixNano()) + + mtx.Lock() + + // process all the updates + for k, v := range updates { + // check if expiry time has passed + if d := (v.Update.Timestamp + v.Update.Expires); d < now { + // delete from records + delete(updates, k) + // set to delete + v.Update.Action = delAction + // fire a new update + g.updates <- v + } + } + + mtx.Unlock() + } + }() + + // process the updates + for u := range g.updates { + switch u.Update.Action { + case addAction: + g.Lock() + if service, ok := g.services[u.Service.Name]; !ok { + g.services[u.Service.Name] = []*registry.Service{u.Service} + + } else { + g.services[u.Service.Name] = addServices(service, []*registry.Service{u.Service}) + } + g.Unlock() + + // publish update to watchers + go g.publish(addAction, []*registry.Service{u.Service}) + + // we need to expire the node at some point in the future + if u.Update.Expires > 0 { + // create a hash of this service + if hash, err := hashstructure.Hash(u.Service, nil); err == nil { + mtx.Lock() + updates[hash] = u + mtx.Unlock() + } + } + case delAction: + g.Lock() + if service, ok := g.services[u.Service.Name]; ok { + if services := delServices(service, []*registry.Service{u.Service}); len(services) == 0 { + delete(g.services, u.Service.Name) + } else { + g.services[u.Service.Name] = services + } + } + g.Unlock() + + // publish update to watchers + go g.publish(delAction, []*registry.Service{u.Service}) + + // delete from expiry checks + if hash, err := hashstructure.Hash(u.Service, nil); err == nil { + mtx.Lock() + delete(updates, hash) + mtx.Unlock() + } + case syncAction: + // no sync channel provided + if u.sync == nil { + continue + } + + g.RLock() + + // push all services through the sync chan + for _, service := range g.services { + for _, srv := range service { + u.sync <- srv + } + + // publish to watchers + go g.publish(addAction, service) + } + + g.RUnlock() + + // close the sync chan + close(u.sync) + } } - d.registry.Unlock() } func (g *gossipRegistry) Init(opts ...registry.Option) error { - addrs := g.opts.Addrs - for _, o := range opts { - o(&g.opts) - } - - // if we have memberlist join it - if len(addrs) != len(g.opts.Addrs) { - _, err := g.memberlist.Join(g.opts.Addrs) - if err != nil { - return err - } - } - - return nil + return configure(g, opts...) } func (g *gossipRegistry) Options() registry.Options { - return g.opts + return g.options } func (g *gossipRegistry) Register(s *registry.Service, opts ...registry.RegisterOption) error { @@ -201,12 +440,22 @@ func (g *gossipRegistry) Register(s *registry.Service, opts ...registry.Register } g.Lock() - g.services[s.Name] = addServices(g.services[s.Name], []*registry.Service{s}) + if service, ok := g.services[s.Name]; !ok { + g.services[s.Name] = []*registry.Service{s} + } else { + g.services[s.Name] = addServices(service, []*registry.Service{s}) + } g.Unlock() + var options registry.RegisterOptions + for _, o := range opts { + o(&options) + } + up := &pb.Update{ Id: uuid.New().String(), Timestamp: uint64(time.Now().UnixNano()), + Expires: uint64(options.TTL.Nanoseconds()), Action: "update", Type: "service", Metadata: map[string]string{ @@ -220,6 +469,9 @@ func (g *gossipRegistry) Register(s *registry.Service, opts ...registry.Register notify: nil, }) + // wait + <-time.After(g.interval * 2) + return nil } @@ -230,7 +482,13 @@ func (g *gossipRegistry) Deregister(s *registry.Service) error { } g.Lock() - g.services[s.Name] = delServices(g.services[s.Name], []*registry.Service{s}) + if service, ok := g.services[s.Name]; ok { + if services := delServices(service, []*registry.Service{s}); len(services) == 0 { + delete(g.services, s.Name) + } else { + g.services[s.Name] = services + } + } g.Unlock() up := &pb.Update{ @@ -249,135 +507,59 @@ func (g *gossipRegistry) Deregister(s *registry.Service) error { notify: nil, }) + // wait + <-time.After(g.interval * 2) + return nil } func (g *gossipRegistry) GetService(name string) ([]*registry.Service, error) { g.RLock() - if s, ok := g.services[name]; ok { - service := cp(s) - g.RUnlock() - return service, nil - } + service, ok := g.services[name] g.RUnlock() - return nil, registry.ErrNotFound + if !ok { + return nil, registry.ErrNotFound + } + return service, nil } func (g *gossipRegistry) ListServices() ([]*registry.Service, error) { var services []*registry.Service g.RLock() - for name, _ := range g.services { - services = append(services, ®istry.Service{Name: name}) + for _, service := range g.services { + services = append(services, service...) } g.RUnlock() return services, nil } func (g *gossipRegistry) Watch(opts ...registry.WatchOption) (registry.Watcher, error) { - var options registry.WatchOptions - for _, o := range opts { - o(&options) - } - - // watcher id - id := uuid.New().String() - - // create watcher - w := &watcher{ - ch: make(chan *registry.Result, 1), - exit: make(chan bool), - id: id, - // filter service - srv: options.Service, - // delete self - fn: func() { - g.Lock() - delete(g.watchers, id) - g.Unlock() - }, - } - - // save watcher - g.Lock() - g.watchers[w.id] = w - g.Unlock() - - return w, nil + n, e := g.subscribe() + return newGossipWatcher(n, e, opts...) } func (g *gossipRegistry) String() string { return "gossip" } -func (g *gossipRegistry) run() error { - hostname, _ := os.Hostname() - - // delegates - d := new(delegate) - - // create a new default config - c := memberlist.DefaultLocalConfig() - - // assign the delegate - c.Delegate = d - - // Set the bind port - c.BindPort = defaultPort - - // set the name - c.Name = strings.Join([]string{"micro", hostname, uuid.New().String()}, "-") - - // log to dev null - c.LogOutput = ioutil.Discard - - // TODO: set advertise addr to advertise behind nat - - // create the memberlist - m, err := memberlist.Create(c) - if err != nil { - return err - } - - // if we have memberlist join it - if len(g.opts.Addrs) > 0 { - _, err := m.Join(g.opts.Addrs) - if err != nil { - return err - } - } - - // Set the broadcast limit and number of nodes - d.queue = &memberlist.TransmitLimitedQueue{ - NumNodes: func() int { - return m.NumMembers() - }, - RetransmitMult: 3, - } - - g.queue = d.queue - g.memberlist = m - g.delegate = d - d.registry = g - - return nil -} - -// NewRegistry returns a new gossip registry func NewRegistry(opts ...registry.Option) registry.Registry { - var options registry.Options - for _, o := range opts { - o(&options) - } - - g := &gossipRegistry{ - opts: options, + gossip := &gossipRegistry{ + options: registry.Options{}, + updates: make(chan *update, 100), services: make(map[string][]*registry.Service), - } - if err := g.run(); err != nil { - log.Fatal(err) + watchers: make(map[string]chan *registry.Result), } - log.Logf("Registry Listening on %s", g.memberlist.LocalNode().Address()) - // return gossip registry - return g + // configure the gossiper + if err := configure(gossip, opts...); err != nil { + log.Fatal("Error configuring registry: %v", err) + } + + // run the updater + go gossip.run() + + // wait for setup + <-time.After(gossip.interval * 2) + + return gossip } diff --git a/registry/gossip/options.go b/registry/gossip/options.go new file mode 100644 index 00000000..26e8cd9f --- /dev/null +++ b/registry/gossip/options.go @@ -0,0 +1,17 @@ +package gossip + +import ( + "context" + + "github.com/micro/go-micro/registry" +) + +type contextSecretKey struct{} + +// Secret specifies an encryption key. The value should be either +// 16, 24, or 32 bytes to select AES-128, AES-192, or AES-256. +func Secret(k []byte) registry.Option { + return func(o *registry.Options) { + o.Context = context.WithValue(o.Context, contextSecretKey{}, k) + } +} diff --git a/registry/gossip/proto/gossip.pb.go b/registry/gossip/proto/gossip.pb.go index 8f2d651c..89bdca55 100644 --- a/registry/gossip/proto/gossip.pb.go +++ b/registry/gossip/proto/gossip.pb.go @@ -1,20 +1,13 @@ // Code generated by protoc-gen-go. DO NOT EDIT. // source: github.com/micro/go-micro/registry/gossip/proto/gossip.proto -/* -Package gossip is a generated protocol buffer package. - -It is generated from these files: - github.com/micro/go-micro/registry/gossip/proto/gossip.proto - -It has these top-level messages: - Update -*/ package gossip -import proto "github.com/golang/protobuf/proto" -import fmt "fmt" -import math "math" +import ( + fmt "fmt" + proto "github.com/golang/protobuf/proto" + math "math" +) // Reference imports to suppress errors if they are not otherwise used. var _ = proto.Marshal @@ -25,28 +18,53 @@ var _ = math.Inf // is compatible with the proto package it is being compiled against. // A compilation error at this line likely means your copy of the // proto package needs to be updated. -const _ = proto.ProtoPackageIsVersion2 // please upgrade the proto package +const _ = proto.ProtoPackageIsVersion3 // please upgrade the proto package // Update is the message broadcast type Update struct { // unique id of update - Id string `protobuf:"bytes,1,opt,name=id" json:"id,omitempty"` + Id string `protobuf:"bytes,1,opt,name=id,proto3" json:"id,omitempty"` // unix nano timestamp of update - Timestamp uint64 `protobuf:"varint,2,opt,name=timestamp" json:"timestamp,omitempty"` + Timestamp uint64 `protobuf:"varint,2,opt,name=timestamp,proto3" json:"timestamp,omitempty"` + // time to live for entry + Expires uint64 `protobuf:"varint,3,opt,name=expires,proto3" json:"expires,omitempty"` // type of update; service - Type string `protobuf:"bytes,3,opt,name=type" json:"type,omitempty"` + Type string `protobuf:"bytes,4,opt,name=type,proto3" json:"type,omitempty"` // what action is taken; add, del, put - Action string `protobuf:"bytes,4,opt,name=action" json:"action,omitempty"` + Action string `protobuf:"bytes,5,opt,name=action,proto3" json:"action,omitempty"` // any other associated metadata about the data - Metadata map[string]string `protobuf:"bytes,5,rep,name=metadata" json:"metadata,omitempty" protobuf_key:"bytes,1,opt,name=key" protobuf_val:"bytes,2,opt,name=value"` + Metadata map[string]string `protobuf:"bytes,6,rep,name=metadata,proto3" json:"metadata,omitempty" protobuf_key:"bytes,1,opt,name=key,proto3" protobuf_val:"bytes,2,opt,name=value,proto3"` // the payload data; - Data []byte `protobuf:"bytes,6,opt,name=data,proto3" json:"data,omitempty"` + Data []byte `protobuf:"bytes,7,opt,name=data,proto3" json:"data,omitempty"` + XXX_NoUnkeyedLiteral struct{} `json:"-"` + XXX_unrecognized []byte `json:"-"` + XXX_sizecache int32 `json:"-"` } -func (m *Update) Reset() { *m = Update{} } -func (m *Update) String() string { return proto.CompactTextString(m) } -func (*Update) ProtoMessage() {} -func (*Update) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{0} } +func (m *Update) Reset() { *m = Update{} } +func (m *Update) String() string { return proto.CompactTextString(m) } +func (*Update) ProtoMessage() {} +func (*Update) Descriptor() ([]byte, []int) { + return fileDescriptor_18cba623e76e57f3, []int{0} +} + +func (m *Update) XXX_Unmarshal(b []byte) error { + return xxx_messageInfo_Update.Unmarshal(m, b) +} +func (m *Update) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + return xxx_messageInfo_Update.Marshal(b, m, deterministic) +} +func (m *Update) XXX_Merge(src proto.Message) { + xxx_messageInfo_Update.Merge(m, src) +} +func (m *Update) XXX_Size() int { + return xxx_messageInfo_Update.Size(m) +} +func (m *Update) XXX_DiscardUnknown() { + xxx_messageInfo_Update.DiscardUnknown(m) +} + +var xxx_messageInfo_Update proto.InternalMessageInfo func (m *Update) GetId() string { if m != nil { @@ -62,6 +80,13 @@ func (m *Update) GetTimestamp() uint64 { return 0 } +func (m *Update) GetExpires() uint64 { + if m != nil { + return m.Expires + } + return 0 +} + func (m *Update) GetType() string { if m != nil { return m.Type @@ -92,27 +117,29 @@ func (m *Update) GetData() []byte { func init() { proto.RegisterType((*Update)(nil), "gossip.Update") + proto.RegisterMapType((map[string]string)(nil), "gossip.Update.MetadataEntry") } func init() { - proto.RegisterFile("github.com/micro/go-micro/registry/gossip/proto/gossip.proto", fileDescriptor0) + proto.RegisterFile("github.com/micro/go-micro/registry/gossip/proto/gossip.proto", fileDescriptor_18cba623e76e57f3) } -var fileDescriptor0 = []byte{ - // 237 bytes of a gzipped FileDescriptorProto - 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x54, 0x8f, 0xcf, 0x4a, 0xc4, 0x30, - 0x10, 0xc6, 0x49, 0xdb, 0x0d, 0x76, 0xfc, 0x83, 0x0c, 0x22, 0x41, 0xf6, 0x50, 0x3c, 0xf5, 0x62, - 0x0b, 0x7a, 0x59, 0xd4, 0xab, 0x47, 0x2f, 0x01, 0x1f, 0x20, 0xdb, 0x86, 0x1a, 0x34, 0x9b, 0x90, - 0xce, 0x0a, 0x7d, 0x68, 0xdf, 0x41, 0x9a, 0x04, 0xc5, 0xdb, 0xef, 0x37, 0xf9, 0xc2, 0x7c, 0x03, - 0xcf, 0x93, 0xa1, 0xf7, 0xe3, 0xbe, 0x1b, 0x9c, 0xed, 0xad, 0x19, 0x82, 0xeb, 0x27, 0x77, 0x97, - 0x20, 0xe8, 0xc9, 0xcc, 0x14, 0x96, 0x7e, 0x72, 0xf3, 0x6c, 0x7c, 0xef, 0x83, 0x23, 0x97, 0xa5, - 0x8b, 0x82, 0x3c, 0xd9, 0xed, 0x37, 0x03, 0xfe, 0xe6, 0x47, 0x45, 0x1a, 0x2f, 0xa0, 0x30, 0xa3, - 0x60, 0x0d, 0x6b, 0x6b, 0x59, 0x98, 0x11, 0xb7, 0x50, 0x93, 0xb1, 0x7a, 0x26, 0x65, 0xbd, 0x28, - 0x1a, 0xd6, 0x56, 0xf2, 0x6f, 0x80, 0x08, 0x15, 0x2d, 0x5e, 0x8b, 0x32, 0xe6, 0x23, 0xe3, 0x35, - 0x70, 0x35, 0x90, 0x71, 0x07, 0x51, 0xc5, 0x69, 0x36, 0xdc, 0xc1, 0x89, 0xd5, 0xa4, 0x46, 0x45, - 0x4a, 0x6c, 0x9a, 0xb2, 0x3d, 0xbd, 0xdf, 0x76, 0xb9, 0x4d, 0xda, 0xdd, 0xbd, 0xe6, 0xe7, 0x97, - 0x03, 0x85, 0x45, 0xfe, 0xa6, 0xd7, 0x2d, 0xf1, 0x17, 0x6f, 0x58, 0x7b, 0x26, 0x23, 0xdf, 0x3c, - 0xc1, 0xf9, 0xbf, 0x38, 0x5e, 0x42, 0xf9, 0xa1, 0x97, 0xdc, 0x7c, 0x45, 0xbc, 0x82, 0xcd, 0x97, - 0xfa, 0x3c, 0xea, 0x58, 0xbb, 0x96, 0x49, 0x1e, 0x8b, 0x1d, 0xdb, 0xf3, 0x78, 0xfe, 0xc3, 0x4f, - 0x00, 0x00, 0x00, 0xff, 0xff, 0xf0, 0x49, 0xa9, 0xd7, 0x3e, 0x01, 0x00, 0x00, +var fileDescriptor_18cba623e76e57f3 = []byte{ + // 251 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x54, 0x90, 0xcf, 0x4a, 0xc4, 0x30, + 0x10, 0x87, 0x69, 0xb6, 0x9b, 0xb5, 0xe3, 0x1f, 0x64, 0x10, 0x09, 0xb2, 0x87, 0xe2, 0xa9, 0x17, + 0x5b, 0xd0, 0xcb, 0xa2, 0x5e, 0x3d, 0x7a, 0x09, 0xf8, 0x00, 0xd9, 0x36, 0xd4, 0xa0, 0xd9, 0x84, + 0x64, 0x56, 0xec, 0x13, 0xf8, 0xda, 0xb2, 0x69, 0x54, 0xbc, 0x7d, 0xdf, 0xcc, 0x24, 0x99, 0x5f, + 0xe0, 0x71, 0x34, 0xf4, 0xba, 0xdf, 0xb6, 0xbd, 0xb3, 0x9d, 0x35, 0x7d, 0x70, 0xdd, 0xe8, 0x6e, + 0x66, 0x08, 0x7a, 0x34, 0x91, 0xc2, 0xd4, 0x8d, 0x2e, 0x46, 0xe3, 0x3b, 0x1f, 0x1c, 0xb9, 0x2c, + 0x6d, 0x12, 0xe4, 0xb3, 0x5d, 0x7f, 0x31, 0xe0, 0x2f, 0x7e, 0x50, 0xa4, 0xf1, 0x0c, 0x98, 0x19, + 0x44, 0x51, 0x17, 0x4d, 0x25, 0x99, 0x19, 0x70, 0x0d, 0x15, 0x19, 0xab, 0x23, 0x29, 0xeb, 0x05, + 0xab, 0x8b, 0xa6, 0x94, 0x7f, 0x05, 0x14, 0xb0, 0xd2, 0x9f, 0xde, 0x04, 0x1d, 0xc5, 0x22, 0xf5, + 0x7e, 0x14, 0x11, 0x4a, 0x9a, 0xbc, 0x16, 0x65, 0xba, 0x29, 0x31, 0x5e, 0x02, 0x57, 0x3d, 0x19, + 0xb7, 0x13, 0xcb, 0x54, 0xcd, 0x86, 0x1b, 0x38, 0xb2, 0x9a, 0xd4, 0xa0, 0x48, 0x09, 0x5e, 0x2f, + 0x9a, 0xe3, 0xdb, 0x75, 0x9b, 0xf7, 0x9c, 0xb7, 0x6a, 0x9f, 0x73, 0xfb, 0x69, 0x47, 0x61, 0x92, + 0xbf, 0xd3, 0x87, 0x57, 0xd2, 0xa9, 0x55, 0x5d, 0x34, 0x27, 0x32, 0xf1, 0xd5, 0x03, 0x9c, 0xfe, + 0x1b, 0xc7, 0x73, 0x58, 0xbc, 0xe9, 0x29, 0x67, 0x3a, 0x20, 0x5e, 0xc0, 0xf2, 0x43, 0xbd, 0xef, + 0x75, 0x0a, 0x54, 0xc9, 0x59, 0xee, 0xd9, 0xa6, 0xd8, 0xf2, 0xf4, 0x31, 0x77, 0xdf, 0x01, 0x00, + 0x00, 0xff, 0xff, 0x06, 0x6e, 0x00, 0x3c, 0x58, 0x01, 0x00, 0x00, } diff --git a/registry/gossip/proto/gossip.proto b/registry/gossip/proto/gossip.proto index 75e39cd0..5ab9fd39 100644 --- a/registry/gossip/proto/gossip.proto +++ b/registry/gossip/proto/gossip.proto @@ -8,12 +8,14 @@ message Update { string id = 1; // unix nano timestamp of update uint64 timestamp = 2; + // time to live for entry + uint64 expires = 3; // type of update; service - string type = 3; + string type = 4; // what action is taken; add, del, put - string action = 4; + string action = 5; // any other associated metadata about the data - map metadata = 5; + map metadata = 6; // the payload data; - bytes data = 6; + bytes data = 7; } diff --git a/registry/gossip/watcher.go b/registry/gossip/watcher.go index b936ab2f..a43d875e 100644 --- a/registry/gossip/watcher.go +++ b/registry/gossip/watcher.go @@ -4,37 +4,48 @@ import ( "github.com/micro/go-micro/registry" ) -type watcher struct { - id string - srv string - ch chan *registry.Result - exit chan bool - fn func() +type gossipWatcher struct { + wo registry.WatchOptions + next chan *registry.Result + stop chan bool } -func (w *watcher) Next() (*registry.Result, error) { +func newGossipWatcher(ch chan *registry.Result, stop chan bool, opts ...registry.WatchOption) (registry.Watcher, error) { + var wo registry.WatchOptions + for _, o := range opts { + o(&wo) + } + + return &gossipWatcher{ + wo: wo, + next: ch, + stop: stop, + }, nil +} + +func (m *gossipWatcher) Next() (*registry.Result, error) { for { select { - case r := <-w.ch: - if r.Service == nil { - continue + case r, ok := <-m.next: + if !ok { + return nil, registry.ErrWatcherStopped } - if len(w.srv) > 0 && (r.Service.Name != w.srv) { + // check watch options + if len(m.wo.Service) > 0 && r.Service.Name != m.wo.Service { continue } return r, nil - case <-w.exit: + case <-m.stop: return nil, registry.ErrWatcherStopped } } } -func (w *watcher) Stop() { +func (m *gossipWatcher) Stop() { select { - case <-w.exit: + case <-m.stop: return default: - close(w.exit) - w.fn() + close(m.stop) } } From b02e1e04fc4ca50593a65f59a518847a98b5a1b5 Mon Sep 17 00:00:00 2001 From: Asim Aslam Date: Thu, 6 Dec 2018 18:26:51 +0000 Subject: [PATCH 055/196] Add gossip readme --- registry/gossip/README.md | 24 ++++++++++++++++++++++++ 1 file changed, 24 insertions(+) create mode 100644 registry/gossip/README.md diff --git a/registry/gossip/README.md b/registry/gossip/README.md new file mode 100644 index 00000000..fbf204f5 --- /dev/null +++ b/registry/gossip/README.md @@ -0,0 +1,24 @@ +# Gossip Registry + +Gossip is a zero dependency registry which uses hashicorp/memberlist to broadcast registry information +via the SWIM protocol. + +## Usage + +Start with the registry flag or env var + +```bash +MICRO_REGISTRY=gossip go run service.go +``` + +On startup you'll see something like + +```bash +2018/12/06 18:17:48 Registry Listening on 192.168.1.65:56390 +``` + +To join this gossip ring set the registry address using flag or env var + +```bash +MICRO_REGISTRY_ADDRESS= 192.168.1.65:56390 +``` From c2cc03a47266763aba03ae7980765a2177d1ee6b Mon Sep 17 00:00:00 2001 From: Asim Aslam Date: Thu, 6 Dec 2018 18:46:02 +0000 Subject: [PATCH 056/196] update readme --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 96aa622c..3b149f89 100644 --- a/README.md +++ b/README.md @@ -20,7 +20,7 @@ Go Micro abstracts away the details of distributed systems. Here are the main fe - **Service Discovery** - Automatic service registration and name resolution. Service discovery is at the core of micro service development. When service A needs to speak to service B it needs the location of that service. Consul is the default discovery -system with multicast DNS being a local option. +system with multicast DNS (mdns) as a local option or the SWIM protocol (gossip) for zero dependency p2p networks. - **Load Balancing** - Client side load balancing built on service discovery. Once we have the addresses of any number of instances of a service we now need a way to decide which node to route to. We use random hashed load balancing to provide even distribution From 770c16a66d008f4e33af5efbade73c55e87c4310 Mon Sep 17 00:00:00 2001 From: Asim Aslam Date: Tue, 18 Dec 2018 16:51:42 +0000 Subject: [PATCH 057/196] move to using rwmutex for selector --- selector/cache/cache.go | 49 ++++++++++++++++++++++++++++++++--------- 1 file changed, 38 insertions(+), 11 deletions(-) diff --git a/selector/cache/cache.go b/selector/cache/cache.go index 482c068b..b89a9bef 100644 --- a/selector/cache/cache.go +++ b/selector/cache/cache.go @@ -15,7 +15,7 @@ type cacheSelector struct { ttl time.Duration // registry cache - sync.Mutex + sync.RWMutex cache map[string][]*registry.Service ttls map[string]time.Time @@ -81,13 +81,12 @@ func (c *cacheSelector) del(service string) { } func (c *cacheSelector) get(service string) ([]*registry.Service, error) { - c.Lock() - defer c.Unlock() + // read lock for the duration + c.RLock() // watch service if not watched if _, ok := c.watched[service]; !ok { go c.run(service) - c.watched[service] = true } // get does the actual request for a service @@ -100,15 +99,24 @@ func (c *cacheSelector) get(service string) ([]*registry.Service, error) { } // cache results + c.Lock() c.set(service, c.cp(services)) + c.Unlock() + return services, nil } // check the cache first services, ok := c.cache[service] + // make a copy + cp := c.cp(services) // cache miss or no services if !ok || len(services) == 0 { + // unlock the read + c.RUnlock() + + // get and return services return get(service) } @@ -117,15 +125,22 @@ func (c *cacheSelector) get(service string) ([]*registry.Service, error) { // within ttl so return cache if kk && time.Since(ttl) < c.ttl { - return c.cp(services), nil + // unlock the read + c.RUnlock() + + // return servics + return cp, nil } - // expired entry so get service - services, err := get(service) + // unlock read + c.RUnlock() - // no error then return error + // expired entry so get service + rservices, err := get(service) + + // no error then return services if err == nil { - return services, nil + return rservices, nil } // not found error then return @@ -135,8 +150,8 @@ func (c *cacheSelector) get(service string) ([]*registry.Service, error) { // other error - // return expired cache as last resort - return c.cp(services), nil + // return expired cache copy as last resort + return cp, nil } func (c *cacheSelector) set(service string, services []*registry.Service) { @@ -257,6 +272,18 @@ func (c *cacheSelector) update(res *registry.Result) { // reloads the watcher if Init is called // and returns when Close is called func (c *cacheSelector) run(name string) { + // set watcher + c.Lock() + c.watched[name] = true + c.Unlock() + + // delete watcher on exit + defer func() { + c.Lock() + delete(c.watched, name) + c.Unlock() + }() + for { // exit early if already dead if c.quit() { From 67d10e5f39a473cae345ad49d40ca0395f8bff31 Mon Sep 17 00:00:00 2001 From: Asim Aslam Date: Tue, 18 Dec 2018 18:06:34 +0000 Subject: [PATCH 058/196] simplify get code --- selector/cache/cache.go | 69 +++++++++++++---------------------------- 1 file changed, 21 insertions(+), 48 deletions(-) diff --git a/selector/cache/cache.go b/selector/cache/cache.go index b89a9bef..4947d95c 100644 --- a/selector/cache/cache.go +++ b/selector/cache/cache.go @@ -81,16 +81,25 @@ func (c *cacheSelector) del(service string) { } func (c *cacheSelector) get(service string) ([]*registry.Service, error) { - // read lock for the duration + // read lock c.RLock() - // watch service if not watched - if _, ok := c.watched[service]; !ok { - go c.run(service) + // check the cache first + services, ok := c.cache[service] + // get cache ttl + ttl, kk := c.ttls[service] + + // got services && within ttl so return cache + if ok && kk && time.Since(ttl) < c.ttl { + // make a copy + cp := c.cp(services) + // unlock the read + c.RUnlock() + // return servics + return cp, nil } - // get does the actual request for a service - // it also caches it + // get does the actual request for a service and cache it get := func(service string) ([]*registry.Service, error) { // ask the registry services, err := c.so.Registry.GetService(service) @@ -106,52 +115,16 @@ func (c *cacheSelector) get(service string) ([]*registry.Service, error) { return services, nil } - // check the cache first - services, ok := c.cache[service] - // make a copy - cp := c.cp(services) - - // cache miss or no services - if !ok || len(services) == 0 { - // unlock the read - c.RUnlock() - - // get and return services - return get(service) + // watch service if not watched + if _, ok := c.watched[service]; !ok { + go c.run(service) } - // got cache but lets check ttl - ttl, kk := c.ttls[service] - - // within ttl so return cache - if kk && time.Since(ttl) < c.ttl { - // unlock the read - c.RUnlock() - - // return servics - return cp, nil - } - - // unlock read + // unlock the read lock c.RUnlock() - // expired entry so get service - rservices, err := get(service) - - // no error then return services - if err == nil { - return rservices, nil - } - - // not found error then return - if err == registry.ErrNotFound { - return nil, selector.ErrNotFound - } - - // other error - - // return expired cache copy as last resort - return cp, nil + // get and return services + return get(service) } func (c *cacheSelector) set(service string, services []*registry.Service) { From 5bcdf189ded3a14312e2618007786865ee88df2e Mon Sep 17 00:00:00 2001 From: Vasiliy Tolstov Date: Wed, 19 Dec 2018 00:57:16 +0300 Subject: [PATCH 059/196] implement some gossip options Signed-off-by: Vasiliy Tolstov --- registry/gossip/gossip.go | 51 ++++++++++++++++++++++++++++++-------- registry/gossip/options.go | 28 +++++++++++++++++++++ 2 files changed, 69 insertions(+), 10 deletions(-) diff --git a/registry/gossip/gossip.go b/registry/gossip/gossip.go index 99972a24..de2c66dd 100644 --- a/registry/gossip/gossip.go +++ b/registry/gossip/gossip.go @@ -2,9 +2,12 @@ package gossip import ( + "context" "encoding/json" "io/ioutil" + "net" "os" + "strconv" "strings" "sync" "time" @@ -12,7 +15,7 @@ import ( "github.com/golang/protobuf/proto" "github.com/google/uuid" "github.com/hashicorp/memberlist" - "github.com/micro/go-log" + log "github.com/micro/go-log" "github.com/micro/go-micro/registry" pb "github.com/micro/go-micro/registry/gossip/proto" "github.com/mitchellh/hashstructure" @@ -56,7 +59,7 @@ type update struct { var ( // You should change this if using secure - DefaultSecret = []byte("gossip") + DefaultSecret = []byte("micro-gossip-key") // exactly 16 bytes ExpiryTick = time.Second * 5 ) @@ -104,14 +107,40 @@ func configure(g *gossipRegistry, opts ...registry.Option) error { RetransmitMult: 3, } - // machine hostname - hostname, _ := os.Hostname() - // create a new default config c := memberlist.DefaultLocalConfig() - // set bind to random port - c.BindPort = 0 + if optConfig, ok := g.options.Context.Value(contextConfig{}).(*memberlist.Config); ok && optConfig != nil { + c = optConfig + } + + if hostport, ok := g.options.Context.Value(contextAddress{}).(string); ok { + host, port, err := net.SplitHostPort(hostport) + if err == nil { + pn, err := strconv.Atoi(port) + if err == nil { + c.BindPort = pn + } + c.BindAddr = host + } + } else { + // set bind to random port + c.BindPort = 0 + } + + if hostport, ok := g.options.Context.Value(contextAdvertise{}).(string); ok { + host, port, err := net.SplitHostPort(hostport) + if err == nil { + pn, err := strconv.Atoi(port) + if err == nil { + c.AdvertisePort = pn + } + c.AdvertiseAddr = host + } + } + + // machine hostname + hostname, _ := os.Hostname() // set the name c.Name = strings.Join([]string{"micro", hostname, uuid.New().String()}, "-") @@ -135,8 +164,6 @@ func configure(g *gossipRegistry, opts ...registry.Option) error { c.SecretKey = k } - // TODO: set advertise addr to advertise behind nat - // create the memberlist m, err := memberlist.Create(c) if err != nil { @@ -550,9 +577,13 @@ func NewRegistry(opts ...registry.Option) registry.Registry { watchers: make(map[string]chan *registry.Result), } + if gossip.options.Context == nil { + gossip.options.Context = context.Background() + } + // configure the gossiper if err := configure(gossip, opts...); err != nil { - log.Fatal("Error configuring registry: %v", err) + log.Fatalf("Error configuring registry: %v", err) } // run the updater diff --git a/registry/gossip/options.go b/registry/gossip/options.go index 26e8cd9f..cee50ee5 100644 --- a/registry/gossip/options.go +++ b/registry/gossip/options.go @@ -3,6 +3,7 @@ package gossip import ( "context" + "github.com/hashicorp/memberlist" "github.com/micro/go-micro/registry" ) @@ -15,3 +16,30 @@ func Secret(k []byte) registry.Option { o.Context = context.WithValue(o.Context, contextSecretKey{}, k) } } + +type contextAddress struct{} + +// Address to bind to - host:port +func Address(a string) registry.Option { + return func(o *registry.Options) { + o.Context = context.WithValue(o.Context, contextAddress{}, a) + } +} + +type contextConfig struct{} + +// Config allow to inject a *memberlist.Config struct for configuring gossip +func Config(c *memberlist.Config) registry.Option { + return func(o *registry.Options) { + o.Context = context.WithValue(o.Context, contextConfig{}, c) + } +} + +type contextAdvertise struct{} + +// The address to advertise for other gossip members - host:port +func Advertise(a string) registry.Option { + return func(o *registry.Options) { + o.Context = context.WithValue(o.Context, contextAdvertise{}, a) + } +} From fae8c5eb4c089f3af97d5fca7f0a2ed41247cfc7 Mon Sep 17 00:00:00 2001 From: Asim Aslam Date: Wed, 19 Dec 2018 09:27:53 +0000 Subject: [PATCH 060/196] fix context --- registry/gossip/gossip.go | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/registry/gossip/gossip.go b/registry/gossip/gossip.go index de2c66dd..a48ac0ca 100644 --- a/registry/gossip/gossip.go +++ b/registry/gossip/gossip.go @@ -571,16 +571,14 @@ func (g *gossipRegistry) String() string { func NewRegistry(opts ...registry.Option) registry.Registry { gossip := &gossipRegistry{ - options: registry.Options{}, + options: registry.Options{ + Context: context.Background(), + }, updates: make(chan *update, 100), services: make(map[string][]*registry.Service), watchers: make(map[string]chan *registry.Result), } - if gossip.options.Context == nil { - gossip.options.Context = context.Background() - } - // configure the gossiper if err := configure(gossip, opts...); err != nil { log.Fatalf("Error configuring registry: %v", err) From 8b54a850f75dce75583179e45352606383830d5a Mon Sep 17 00:00:00 2001 From: Asim Aslam Date: Wed, 19 Dec 2018 19:04:44 +0000 Subject: [PATCH 061/196] run gossip updater first --- registry/gossip/gossip.go | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/registry/gossip/gossip.go b/registry/gossip/gossip.go index a48ac0ca..5a4a0c40 100644 --- a/registry/gossip/gossip.go +++ b/registry/gossip/gossip.go @@ -579,14 +579,14 @@ func NewRegistry(opts ...registry.Option) registry.Registry { watchers: make(map[string]chan *registry.Result), } + // run the updater + go gossip.run() + // configure the gossiper if err := configure(gossip, opts...); err != nil { log.Fatalf("Error configuring registry: %v", err) } - // run the updater - go gossip.run() - // wait for setup <-time.After(gossip.interval * 2) From 5f2ce6fac4736df5ceaac1b58363ba28a3b6562d Mon Sep 17 00:00:00 2001 From: Asim Aslam Date: Wed, 26 Dec 2018 12:03:08 +0000 Subject: [PATCH 062/196] nitpick readme --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 3b149f89..5f441b26 100644 --- a/README.md +++ b/README.md @@ -28,7 +28,7 @@ across the services and retry a different node if there's a problem. - **Message Encoding** - Dynamic message encoding based on content-type. The client and server will use codecs along with content-type to seamlessly encode and decode Go types for you. Any variety of messages could be encoded and sent from different clients. The client -and server handle this by default. This includes proto-rpc and json-rpc by default. +and server handle this by default. This includes protobuf and json by default. - **Sync Streaming** - RPC based request/response with support for bidirectional streaming. We provide an abstraction for synchronous communication. A request made to a service will be automatically resolved, load balanced, dialled and streamed. The default From 28324412a403d56b31470ca221bd041412893f75 Mon Sep 17 00:00:00 2001 From: Asim Aslam Date: Wed, 26 Dec 2018 14:46:15 +0000 Subject: [PATCH 063/196] Add X-Micro-Target header --- client/rpc_codec.go | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/client/rpc_codec.go b/client/rpc_codec.go index 820cc7e0..87f6a4bd 100644 --- a/client/rpc_codec.go +++ b/client/rpc_codec.go @@ -105,12 +105,15 @@ func newRpcPlusCodec(req *transport.Message, client transport.Client, c codec.Ne func (c *rpcPlusCodec) WriteRequest(req *request, body interface{}) error { c.buf.wbuf.Reset() + m := &codec.Message{ Id: req.Seq, Target: req.Service, Method: req.ServiceMethod, Type: codec.Request, - Header: map[string]string{}, + Header: map[string]string{ + "X-Micro-Target": req.Service, + }, } if err := c.codec.Write(m, body); err != nil { return errors.InternalServerError("go.micro.client.codec", err.Error()) From ff982b5fd17dfa82517481e3a3438fdb1792e378 Mon Sep 17 00:00:00 2001 From: Asim Aslam Date: Fri, 28 Dec 2018 21:27:08 +0000 Subject: [PATCH 064/196] add method --- client/rpc_codec.go | 1 + 1 file changed, 1 insertion(+) diff --git a/client/rpc_codec.go b/client/rpc_codec.go index 87f6a4bd..ea71f2df 100644 --- a/client/rpc_codec.go +++ b/client/rpc_codec.go @@ -113,6 +113,7 @@ func (c *rpcPlusCodec) WriteRequest(req *request, body interface{}) error { Type: codec.Request, Header: map[string]string{ "X-Micro-Target": req.Service, + "X-Micro-Method": req.ServiceMethod, }, } if err := c.codec.Write(m, body); err != nil { From 5cae3307321c568b16227353aca554be49f4db87 Mon Sep 17 00:00:00 2001 From: Asim Aslam Date: Sat, 29 Dec 2018 15:44:51 +0000 Subject: [PATCH 065/196] Update selector race, rename cache selector --- cmd/cmd.go | 4 +- registry/gossip/util.go | 47 ++- selector/cache/cache.go | 424 ------------------------ selector/cache/cache_test.go | 29 -- selector/default.go | 378 ++++++++++++++++++++- selector/default_test.go | 10 +- selector/{cache => registry}/options.go | 8 +- selector/registry/registry.go | 11 + selector/selector.go | 6 +- 9 files changed, 416 insertions(+), 501 deletions(-) delete mode 100644 selector/cache/cache.go delete mode 100644 selector/cache/cache_test.go rename selector/{cache => registry}/options.go (66%) create mode 100644 selector/registry/registry.go diff --git a/cmd/cmd.go b/cmd/cmd.go index 8c1aae19..7d41b452 100644 --- a/cmd/cmd.go +++ b/cmd/cmd.go @@ -26,7 +26,6 @@ import ( // selectors "github.com/micro/go-micro/selector" - "github.com/micro/go-micro/selector/cache" // transports "github.com/micro/go-micro/transport" @@ -149,7 +148,6 @@ var ( Name: "selector", EnvVar: "MICRO_SELECTOR", Usage: "Selector used to pick nodes for querying", - Value: "cache", }, cli.StringFlag{ Name: "transport", @@ -179,7 +177,7 @@ var ( DefaultSelectors = map[string]func(...selector.Option) selector.Selector{ "default": selector.NewSelector, - "cache": cache.NewSelector, + "cache": selector.NewSelector, } DefaultServers = map[string]func(...server.Option) server.Server{ diff --git a/registry/gossip/util.go b/registry/gossip/util.go index 67635957..5d0160a7 100644 --- a/registry/gossip/util.go +++ b/registry/gossip/util.go @@ -38,20 +38,35 @@ func cp(current []*registry.Service) []*registry.Service { } func addNodes(old, neu []*registry.Node) []*registry.Node { + var nodes []*registry.Node + + // add all new nodes for _, n := range neu { - var seen bool - for i, o := range old { + node := *n + nodes = append(nodes, &node) + } + + // look at old nodes + for _, o := range old { + var exists bool + + // check against new nodes + for _, n := range nodes { + // ids match then skip if o.Id == n.Id { - seen = true - old[i] = n + exists = true break } } - if !seen { - old = append(old, n) + + // keep old node + if !exists { + node := *o + nodes = append(nodes, &node) } } - return old + + return nodes } func addServices(old, neu []*registry.Service) []*registry.Service { @@ -91,19 +106,27 @@ func delNodes(old, del []*registry.Node) []*registry.Node { func delServices(old, del []*registry.Service) []*registry.Service { var services []*registry.Service - for i, o := range old { + + for _, o := range old { + srv := new(registry.Service) + *srv = *o + var rem bool + for _, s := range del { - if o.Version == s.Version { - old[i].Nodes = delNodes(o.Nodes, s.Nodes) - if len(old[i].Nodes) == 0 { + if srv.Version == s.Version { + srv.Nodes = delNodes(srv.Nodes, s.Nodes) + + if len(srv.Nodes) == 0 { rem = true } } } + if !rem { - services = append(services, o) + services = append(services, srv) } } + return services } diff --git a/selector/cache/cache.go b/selector/cache/cache.go deleted file mode 100644 index 4947d95c..00000000 --- a/selector/cache/cache.go +++ /dev/null @@ -1,424 +0,0 @@ -// Package cache is a caching selector. It uses the registry watcher. -package cache - -import ( - "sync" - "time" - - "github.com/micro/go-log" - "github.com/micro/go-micro/registry" - "github.com/micro/go-micro/selector" -) - -type cacheSelector struct { - so selector.Options - ttl time.Duration - - // registry cache - sync.RWMutex - cache map[string][]*registry.Service - ttls map[string]time.Time - - watched map[string]bool - - // used to close or reload watcher - reload chan bool - exit chan bool -} - -var ( - DefaultTTL = time.Minute -) - -func (c *cacheSelector) quit() bool { - select { - case <-c.exit: - return true - default: - return false - } -} - -// cp copies a service. Because we're caching handing back pointers would -// create a race condition, so we do this instead -// its fast enough -func (c *cacheSelector) cp(current []*registry.Service) []*registry.Service { - var services []*registry.Service - - for _, service := range current { - // copy service - s := new(registry.Service) - *s = *service - - // copy nodes - var nodes []*registry.Node - for _, node := range service.Nodes { - n := new(registry.Node) - *n = *node - nodes = append(nodes, n) - } - s.Nodes = nodes - - // copy endpoints - var eps []*registry.Endpoint - for _, ep := range service.Endpoints { - e := new(registry.Endpoint) - *e = *ep - eps = append(eps, e) - } - s.Endpoints = eps - - // append service - services = append(services, s) - } - - return services -} - -func (c *cacheSelector) del(service string) { - delete(c.cache, service) - delete(c.ttls, service) -} - -func (c *cacheSelector) get(service string) ([]*registry.Service, error) { - // read lock - c.RLock() - - // check the cache first - services, ok := c.cache[service] - // get cache ttl - ttl, kk := c.ttls[service] - - // got services && within ttl so return cache - if ok && kk && time.Since(ttl) < c.ttl { - // make a copy - cp := c.cp(services) - // unlock the read - c.RUnlock() - // return servics - return cp, nil - } - - // get does the actual request for a service and cache it - get := func(service string) ([]*registry.Service, error) { - // ask the registry - services, err := c.so.Registry.GetService(service) - if err != nil { - return nil, err - } - - // cache results - c.Lock() - c.set(service, c.cp(services)) - c.Unlock() - - return services, nil - } - - // watch service if not watched - if _, ok := c.watched[service]; !ok { - go c.run(service) - } - - // unlock the read lock - c.RUnlock() - - // get and return services - return get(service) -} - -func (c *cacheSelector) set(service string, services []*registry.Service) { - c.cache[service] = services - c.ttls[service] = time.Now().Add(c.ttl) -} - -func (c *cacheSelector) update(res *registry.Result) { - if res == nil || res.Service == nil { - return - } - - c.Lock() - defer c.Unlock() - - services, ok := c.cache[res.Service.Name] - if !ok { - // we're not going to cache anything - // unless there was already a lookup - return - } - - if len(res.Service.Nodes) == 0 { - switch res.Action { - case "delete": - c.del(res.Service.Name) - } - return - } - - // existing service found - var service *registry.Service - var index int - for i, s := range services { - if s.Version == res.Service.Version { - service = s - index = i - } - } - - switch res.Action { - case "create", "update": - if service == nil { - c.set(res.Service.Name, append(services, res.Service)) - return - } - - // append old nodes to new service - for _, cur := range service.Nodes { - var seen bool - for _, node := range res.Service.Nodes { - if cur.Id == node.Id { - seen = true - break - } - } - if !seen { - res.Service.Nodes = append(res.Service.Nodes, cur) - } - } - - services[index] = res.Service - c.set(res.Service.Name, services) - case "delete": - if service == nil { - return - } - - var nodes []*registry.Node - - // filter cur nodes to remove the dead one - for _, cur := range service.Nodes { - var seen bool - for _, del := range res.Service.Nodes { - if del.Id == cur.Id { - seen = true - break - } - } - if !seen { - nodes = append(nodes, cur) - } - } - - // still got nodes, save and return - if len(nodes) > 0 { - service.Nodes = nodes - services[index] = service - c.set(service.Name, services) - return - } - - // zero nodes left - - // only have one thing to delete - // nuke the thing - if len(services) == 1 { - c.del(service.Name) - return - } - - // still have more than 1 service - // check the version and keep what we know - var srvs []*registry.Service - for _, s := range services { - if s.Version != service.Version { - srvs = append(srvs, s) - } - } - - // save - c.set(service.Name, srvs) - } -} - -// run starts the cache watcher loop -// it creates a new watcher if there's a problem -// reloads the watcher if Init is called -// and returns when Close is called -func (c *cacheSelector) run(name string) { - // set watcher - c.Lock() - c.watched[name] = true - c.Unlock() - - // delete watcher on exit - defer func() { - c.Lock() - delete(c.watched, name) - c.Unlock() - }() - - for { - // exit early if already dead - if c.quit() { - return - } - - // create new watcher - w, err := c.so.Registry.Watch( - registry.WatchService(name), - ) - if err != nil { - if c.quit() { - return - } - log.Log(err) - time.Sleep(time.Second) - continue - } - - // watch for events - if err := c.watch(w); err != nil { - if c.quit() { - return - } - log.Log(err) - continue - } - } -} - -// watch loops the next event and calls update -// it returns if there's an error -func (c *cacheSelector) watch(w registry.Watcher) error { - defer w.Stop() - - // manage this loop - go func() { - // wait for exit or reload signal - select { - case <-c.exit: - case <-c.reload: - } - - // stop the watcher - w.Stop() - }() - - for { - res, err := w.Next() - if err != nil { - return err - } - c.update(res) - } -} - -func (c *cacheSelector) Init(opts ...selector.Option) error { - for _, o := range opts { - o(&c.so) - } - - // reload the watcher - go func() { - select { - case <-c.exit: - return - default: - c.reload <- true - } - }() - - return nil -} - -func (c *cacheSelector) Options() selector.Options { - return c.so -} - -func (c *cacheSelector) Select(service string, opts ...selector.SelectOption) (selector.Next, error) { - sopts := selector.SelectOptions{ - Strategy: c.so.Strategy, - } - - for _, opt := range opts { - opt(&sopts) - } - - // get the service - // try the cache first - // if that fails go directly to the registry - services, err := c.get(service) - if err != nil { - return nil, err - } - - // apply the filters - for _, filter := range sopts.Filters { - services = filter(services) - } - - // if there's nothing left, return - if len(services) == 0 { - return nil, selector.ErrNoneAvailable - } - - return sopts.Strategy(services), nil -} - -func (c *cacheSelector) Mark(service string, node *registry.Node, err error) { -} - -func (c *cacheSelector) Reset(service string) { -} - -// Close stops the watcher and destroys the cache -func (c *cacheSelector) Close() error { - c.Lock() - c.cache = make(map[string][]*registry.Service) - c.watched = make(map[string]bool) - c.Unlock() - - select { - case <-c.exit: - return nil - default: - close(c.exit) - } - return nil -} - -func (c *cacheSelector) String() string { - return "cache" -} - -func NewSelector(opts ...selector.Option) selector.Selector { - sopts := selector.Options{ - Strategy: selector.Random, - } - - for _, opt := range opts { - opt(&sopts) - } - - if sopts.Registry == nil { - sopts.Registry = registry.DefaultRegistry - } - - ttl := DefaultTTL - - if sopts.Context != nil { - if t, ok := sopts.Context.Value(ttlKey{}).(time.Duration); ok { - ttl = t - } - } - - return &cacheSelector{ - so: sopts, - ttl: ttl, - watched: make(map[string]bool), - cache: make(map[string][]*registry.Service), - ttls: make(map[string]time.Time), - reload: make(chan bool, 1), - exit: make(chan bool), - } -} diff --git a/selector/cache/cache_test.go b/selector/cache/cache_test.go deleted file mode 100644 index 931e3801..00000000 --- a/selector/cache/cache_test.go +++ /dev/null @@ -1,29 +0,0 @@ -package cache - -import ( - "testing" - - "github.com/micro/go-micro/registry/mock" - "github.com/micro/go-micro/selector" -) - -func TestCacheSelector(t *testing.T) { - counts := map[string]int{} - - cache := NewSelector(selector.Registry(mock.NewRegistry())) - - next, err := cache.Select("foo") - if err != nil { - t.Errorf("Unexpected error calling cache select: %v", err) - } - - for i := 0; i < 100; i++ { - node, err := next() - if err != nil { - t.Errorf("Expected node err, got err: %v", err) - } - counts[node.Id]++ - } - - t.Logf("Cache Counts %v", counts) -} diff --git a/selector/default.go b/selector/default.go index 72abfc1b..e0bd3672 100644 --- a/selector/default.go +++ b/selector/default.go @@ -1,27 +1,341 @@ package selector import ( + "sync" + "time" + + "github.com/micro/go-log" "github.com/micro/go-micro/registry" ) -type defaultSelector struct { - so Options +type registrySelector struct { + so Options + ttl time.Duration + + // registry cache + sync.RWMutex + cache map[string][]*registry.Service + ttls map[string]time.Time + + watched map[string]bool + + // used to close or reload watcher + reload chan bool + exit chan bool } -func (r *defaultSelector) Init(opts ...Option) error { - for _, o := range opts { - o(&r.so) +var ( + DefaultTTL = time.Minute +) + +func (c *registrySelector) quit() bool { + select { + case <-c.exit: + return true + default: + return false } +} + +// cp copies a service. Because we're caching handing back pointers would +// create a race condition, so we do this instead +// its fast enough +func (c *registrySelector) cp(current []*registry.Service) []*registry.Service { + var services []*registry.Service + + for _, service := range current { + // copy service + s := new(registry.Service) + *s = *service + + // copy nodes + var nodes []*registry.Node + for _, node := range service.Nodes { + n := new(registry.Node) + *n = *node + nodes = append(nodes, n) + } + s.Nodes = nodes + + // copy endpoints + var eps []*registry.Endpoint + for _, ep := range service.Endpoints { + e := new(registry.Endpoint) + *e = *ep + eps = append(eps, e) + } + s.Endpoints = eps + + // append service + services = append(services, s) + } + + return services +} + +func (c *registrySelector) del(service string) { + delete(c.cache, service) + delete(c.ttls, service) +} + +func (c *registrySelector) get(service string) ([]*registry.Service, error) { + // read lock + c.RLock() + + // check the cache first + services, ok := c.cache[service] + // get cache ttl + ttl, kk := c.ttls[service] + + // got services && within ttl so return cache + if ok && kk && time.Since(ttl) < c.ttl { + // make a copy + cp := c.cp(services) + // unlock the read + c.RUnlock() + // return servics + return cp, nil + } + + // get does the actual request for a service and cache it + get := func(service string) ([]*registry.Service, error) { + // ask the registry + services, err := c.so.Registry.GetService(service) + if err != nil { + return nil, err + } + + // cache results + c.Lock() + c.set(service, c.cp(services)) + c.Unlock() + + return services, nil + } + + // watch service if not watched + if _, ok := c.watched[service]; !ok { + go c.run(service) + } + + // unlock the read lock + c.RUnlock() + + // get and return services + return get(service) +} + +func (c *registrySelector) set(service string, services []*registry.Service) { + c.cache[service] = services + c.ttls[service] = time.Now().Add(c.ttl) +} + +func (c *registrySelector) update(res *registry.Result) { + if res == nil || res.Service == nil { + return + } + + c.Lock() + defer c.Unlock() + + services, ok := c.cache[res.Service.Name] + if !ok { + // we're not going to cache anything + // unless there was already a lookup + return + } + + if len(res.Service.Nodes) == 0 { + switch res.Action { + case "delete": + c.del(res.Service.Name) + } + return + } + + // existing service found + var service *registry.Service + var index int + for i, s := range services { + if s.Version == res.Service.Version { + service = s + index = i + } + } + + switch res.Action { + case "create", "update": + if service == nil { + c.set(res.Service.Name, append(services, res.Service)) + return + } + + // append old nodes to new service + for _, cur := range service.Nodes { + var seen bool + for _, node := range res.Service.Nodes { + if cur.Id == node.Id { + seen = true + break + } + } + if !seen { + res.Service.Nodes = append(res.Service.Nodes, cur) + } + } + + services[index] = res.Service + c.set(res.Service.Name, services) + case "delete": + if service == nil { + return + } + + var nodes []*registry.Node + + // filter cur nodes to remove the dead one + for _, cur := range service.Nodes { + var seen bool + for _, del := range res.Service.Nodes { + if del.Id == cur.Id { + seen = true + break + } + } + if !seen { + nodes = append(nodes, cur) + } + } + + // still got nodes, save and return + if len(nodes) > 0 { + service.Nodes = nodes + services[index] = service + c.set(service.Name, services) + return + } + + // zero nodes left + + // only have one thing to delete + // nuke the thing + if len(services) == 1 { + c.del(service.Name) + return + } + + // still have more than 1 service + // check the version and keep what we know + var srvs []*registry.Service + for _, s := range services { + if s.Version != service.Version { + srvs = append(srvs, s) + } + } + + // save + c.set(service.Name, srvs) + } +} + +// run starts the cache watcher loop +// it creates a new watcher if there's a problem +// reloads the watcher if Init is called +// and returns when Close is called +func (c *registrySelector) run(name string) { + // set watcher + c.Lock() + c.watched[name] = true + c.Unlock() + + // delete watcher on exit + defer func() { + c.Lock() + delete(c.watched, name) + c.Unlock() + }() + + for { + // exit early if already dead + if c.quit() { + return + } + + // create new watcher + w, err := c.so.Registry.Watch( + registry.WatchService(name), + ) + if err != nil { + if c.quit() { + return + } + log.Log(err) + time.Sleep(time.Second) + continue + } + + // watch for events + if err := c.watch(w); err != nil { + if c.quit() { + return + } + log.Log(err) + continue + } + } +} + +// watch loops the next event and calls update +// it returns if there's an error +func (c *registrySelector) watch(w registry.Watcher) error { + defer w.Stop() + + // manage this loop + go func() { + // wait for exit or reload signal + select { + case <-c.exit: + case <-c.reload: + } + + // stop the watcher + w.Stop() + }() + + for { + res, err := w.Next() + if err != nil { + return err + } + c.update(res) + } +} + +func (c *registrySelector) Init(opts ...Option) error { + for _, o := range opts { + o(&c.so) + } + + // reload the watcher + go func() { + select { + case <-c.exit: + return + default: + c.reload <- true + } + }() + return nil } -func (r *defaultSelector) Options() Options { - return r.so +func (c *registrySelector) Options() Options { + return c.so } -func (r *defaultSelector) Select(service string, opts ...SelectOption) (Next, error) { +func (c *registrySelector) Select(service string, opts ...SelectOption) (Next, error) { sopts := SelectOptions{ - Strategy: r.so.Strategy, + Strategy: c.so.Strategy, } for _, opt := range opts { @@ -29,7 +343,9 @@ func (r *defaultSelector) Select(service string, opts ...SelectOption) (Next, er } // get the service - services, err := r.so.Registry.GetService(service) + // try the cache first + // if that fails go directly to the registry + services, err := c.get(service) if err != nil { return nil, err } @@ -47,21 +363,33 @@ func (r *defaultSelector) Select(service string, opts ...SelectOption) (Next, er return sopts.Strategy(services), nil } -func (r *defaultSelector) Mark(service string, node *registry.Node, err error) { +func (c *registrySelector) Mark(service string, node *registry.Node, err error) { } -func (r *defaultSelector) Reset(service string) { +func (c *registrySelector) Reset(service string) { } -func (r *defaultSelector) Close() error { +// Close stops the watcher and destroys the cache +func (c *registrySelector) Close() error { + c.Lock() + c.cache = make(map[string][]*registry.Service) + c.watched = make(map[string]bool) + c.Unlock() + + select { + case <-c.exit: + return nil + default: + close(c.exit) + } return nil } -func (r *defaultSelector) String() string { - return "default" +func (c *registrySelector) String() string { + return "registry" } -func newDefaultSelector(opts ...Option) Selector { +func NewSelector(opts ...Option) Selector { sopts := Options{ Strategy: Random, } @@ -74,7 +402,21 @@ func newDefaultSelector(opts ...Option) Selector { sopts.Registry = registry.DefaultRegistry } - return &defaultSelector{ - so: sopts, + ttl := DefaultTTL + + if sopts.Context != nil { + if t, ok := sopts.Context.Value("selector_ttl").(time.Duration); ok { + ttl = t + } + } + + return ®istrySelector{ + so: sopts, + ttl: ttl, + watched: make(map[string]bool), + cache: make(map[string][]*registry.Service), + ttls: make(map[string]time.Time), + reload: make(chan bool, 1), + exit: make(chan bool), } } diff --git a/selector/default_test.go b/selector/default_test.go index e0a8ec22..68d5c850 100644 --- a/selector/default_test.go +++ b/selector/default_test.go @@ -6,14 +6,14 @@ import ( "github.com/micro/go-micro/registry/mock" ) -func TestDefaultSelector(t *testing.T) { +func TestRegistrySelector(t *testing.T) { counts := map[string]int{} - rs := newDefaultSelector(Registry(mock.NewRegistry())) + cache := NewSelector(Registry(mock.NewRegistry())) - next, err := rs.Select("foo") + next, err := cache.Select("foo") if err != nil { - t.Errorf("Unexpected error calling default select: %v", err) + t.Errorf("Unexpected error calling cache select: %v", err) } for i := 0; i < 100; i++ { @@ -24,5 +24,5 @@ func TestDefaultSelector(t *testing.T) { counts[node.Id]++ } - t.Logf("Default Counts %v", counts) + t.Logf("Selector Counts %v", counts) } diff --git a/selector/cache/options.go b/selector/registry/options.go similarity index 66% rename from selector/cache/options.go rename to selector/registry/options.go index e32e1b59..90aaf802 100644 --- a/selector/cache/options.go +++ b/selector/registry/options.go @@ -1,4 +1,4 @@ -package cache +package registry import ( "context" @@ -7,14 +7,12 @@ import ( "github.com/micro/go-micro/selector" ) -type ttlKey struct{} - -// Set the cache ttl +// Set the registry cache ttl func TTL(t time.Duration) selector.Option { return func(o *selector.Options) { if o.Context == nil { o.Context = context.Background() } - o.Context = context.WithValue(o.Context, ttlKey{}, t) + o.Context = context.WithValue(o.Context, "selector_ttl", t) } } diff --git a/selector/registry/registry.go b/selector/registry/registry.go new file mode 100644 index 00000000..20f219e8 --- /dev/null +++ b/selector/registry/registry.go @@ -0,0 +1,11 @@ +// Package registry is uses the go-micro registry for selection +package registry + +import ( + "github.com/micro/go-micro/selector" +) + +// NewSelector returns a new registry selector +func NewSelector(opts ...selector.Option) selector.Selector { + return selector.NewSelector(opts...) +} diff --git a/selector/selector.go b/selector/selector.go index dab26de2..ae80915a 100644 --- a/selector/selector.go +++ b/selector/selector.go @@ -35,12 +35,8 @@ type Filter func([]*registry.Service) []*registry.Service type Strategy func([]*registry.Service) Next var ( - DefaultSelector = newDefaultSelector() + DefaultSelector = NewSelector() ErrNotFound = errors.New("not found") ErrNoneAvailable = errors.New("none available") ) - -func NewSelector(opts ...Option) Selector { - return newDefaultSelector(opts...) -} From 460fb3e70ceeb5edd8d35c8003455d4deadb86e1 Mon Sep 17 00:00:00 2001 From: Asim Aslam Date: Sat, 29 Dec 2018 16:18:05 +0000 Subject: [PATCH 066/196] update package comments --- selector/registry/registry.go | 2 +- selector/selector.go | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/selector/registry/registry.go b/selector/registry/registry.go index 20f219e8..b6d8600d 100644 --- a/selector/registry/registry.go +++ b/selector/registry/registry.go @@ -1,4 +1,4 @@ -// Package registry is uses the go-micro registry for selection +// Package registry uses the go-micro registry for selection package registry import ( diff --git a/selector/selector.go b/selector/selector.go index ae80915a..5c9a2499 100644 --- a/selector/selector.go +++ b/selector/selector.go @@ -1,4 +1,4 @@ -// Package selector is a way to load balance service nodes +// Package selector is a way to pick a list of service nodes package selector import ( From dcf7a56f9b44c0082825313dee6cdbad4b6bd245 Mon Sep 17 00:00:00 2001 From: Asim Aslam Date: Mon, 31 Dec 2018 17:28:19 +0000 Subject: [PATCH 067/196] rename codec --- client/rpc_codec.go | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/client/rpc_codec.go b/client/rpc_codec.go index ea71f2df..58c24fd2 100644 --- a/client/rpc_codec.go +++ b/client/rpc_codec.go @@ -28,7 +28,7 @@ var ( errShutdown = errs.New("connection is shut down") ) -type rpcPlusCodec struct { +type rpcCodec struct { client transport.Client codec codec.Codec @@ -89,12 +89,12 @@ func (rwc *readWriteCloser) Close() error { return nil } -func newRpcPlusCodec(req *transport.Message, client transport.Client, c codec.NewCodec) *rpcPlusCodec { +func newRpcPlusCodec(req *transport.Message, client transport.Client, c codec.NewCodec) *rpcCodec { rwc := &readWriteCloser{ wbuf: bytes.NewBuffer(nil), rbuf: bytes.NewBuffer(nil), } - r := &rpcPlusCodec{ + r := &rpcCodec{ buf: rwc, client: client, codec: c(rwc), @@ -103,7 +103,7 @@ func newRpcPlusCodec(req *transport.Message, client transport.Client, c codec.Ne return r } -func (c *rpcPlusCodec) WriteRequest(req *request, body interface{}) error { +func (c *rpcCodec) WriteRequest(req *request, body interface{}) error { c.buf.wbuf.Reset() m := &codec.Message{ @@ -129,7 +129,7 @@ func (c *rpcPlusCodec) WriteRequest(req *request, body interface{}) error { return nil } -func (c *rpcPlusCodec) ReadResponseHeader(r *response) error { +func (c *rpcCodec) ReadResponseHeader(r *response) error { var m transport.Message if err := c.client.Recv(&m); err != nil { return errors.InternalServerError("go.micro.client.transport", err.Error()) @@ -147,14 +147,14 @@ func (c *rpcPlusCodec) ReadResponseHeader(r *response) error { return nil } -func (c *rpcPlusCodec) ReadResponseBody(b interface{}) error { +func (c *rpcCodec) ReadResponseBody(b interface{}) error { if err := c.codec.ReadBody(b); err != nil { return errors.InternalServerError("go.micro.client.codec", err.Error()) } return nil } -func (c *rpcPlusCodec) Close() error { +func (c *rpcCodec) Close() error { c.buf.Close() c.codec.Close() if err := c.client.Close(); err != nil { From 386ced576af24fc65c45ae0d7049d58a8cd39059 Mon Sep 17 00:00:00 2001 From: Asim Aslam Date: Mon, 31 Dec 2018 17:53:16 +0000 Subject: [PATCH 068/196] Process header/body in one call --- client/rpc_codec.go | 17 ++++++++++------- client/rpc_stream.go | 10 ++-------- 2 files changed, 12 insertions(+), 15 deletions(-) diff --git a/client/rpc_codec.go b/client/rpc_codec.go index 58c24fd2..01fe9208 100644 --- a/client/rpc_codec.go +++ b/client/rpc_codec.go @@ -43,9 +43,7 @@ type readWriteCloser struct { type clientCodec interface { WriteRequest(*request, interface{}) error - ReadResponseHeader(*response) error - ReadResponseBody(interface{}) error - + ReadResponse(*response, interface{}) error Close() error } @@ -129,28 +127,33 @@ func (c *rpcCodec) WriteRequest(req *request, body interface{}) error { return nil } -func (c *rpcCodec) ReadResponseHeader(r *response) error { +func (c *rpcCodec) ReadResponse(r *response, b interface{}) error { var m transport.Message if err := c.client.Recv(&m); err != nil { return errors.InternalServerError("go.micro.client.transport", err.Error()) } c.buf.rbuf.Reset() c.buf.rbuf.Write(m.Body) + var me codec.Message + // set headers + me.Header = m.Header + + // read header err := c.codec.ReadHeader(&me, codec.Response) r.ServiceMethod = me.Method r.Seq = me.Id r.Error = me.Error + if err != nil { return errors.InternalServerError("go.micro.client.codec", err.Error()) } - return nil -} -func (c *rpcCodec) ReadResponseBody(b interface{}) error { + // read body if err := c.codec.ReadBody(b); err != nil { return errors.InternalServerError("go.micro.client.codec", err.Error()) } + return nil } diff --git a/client/rpc_stream.go b/client/rpc_stream.go index e5a27033..eda78d47 100644 --- a/client/rpc_stream.go +++ b/client/rpc_stream.go @@ -68,7 +68,8 @@ func (r *rpcStream) Recv(msg interface{}) error { } var resp response - if err := r.codec.ReadResponseHeader(&resp); err != nil { + + if err := r.codec.ReadResponse(&resp, msg); err != nil { if err == io.EOF && !r.isClosed() { r.err = io.ErrUnexpectedEOF return io.ErrUnexpectedEOF @@ -87,13 +88,6 @@ func (r *rpcStream) Recv(msg interface{}) error { } else { r.err = io.EOF } - if err := r.codec.ReadResponseBody(nil); err != nil { - r.err = err - } - default: - if err := r.codec.ReadResponseBody(msg); err != nil { - r.err = err - } } return r.err From b3b4bc6059f0d9f3d30b82c0396abdf6588dcdf8 Mon Sep 17 00:00:00 2001 From: Asim Aslam Date: Mon, 31 Dec 2018 20:51:22 +0000 Subject: [PATCH 069/196] remove Plus --- client/rpc_client.go | 4 ++-- client/rpc_codec.go | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/client/rpc_client.go b/client/rpc_client.go index 7b44d7c5..2b84d5dd 100644 --- a/client/rpc_client.go +++ b/client/rpc_client.go @@ -96,7 +96,7 @@ func (r *rpcClient) call(ctx context.Context, address string, req Request, resp context: ctx, request: req, closed: make(chan bool), - codec: newRpcPlusCodec(msg, c, cf), + codec: newRpcCodec(msg, c, cf), seq: seq, } defer stream.Close() @@ -177,7 +177,7 @@ func (r *rpcClient) stream(ctx context.Context, address string, req Request, opt context: ctx, request: req, closed: make(chan bool), - codec: newRpcPlusCodec(msg, c, cf), + codec: newRpcCodec(msg, c, cf), } ch := make(chan error, 1) diff --git a/client/rpc_codec.go b/client/rpc_codec.go index 01fe9208..95ff1da1 100644 --- a/client/rpc_codec.go +++ b/client/rpc_codec.go @@ -87,7 +87,7 @@ func (rwc *readWriteCloser) Close() error { return nil } -func newRpcPlusCodec(req *transport.Message, client transport.Client, c codec.NewCodec) *rpcCodec { +func newRpcCodec(req *transport.Message, client transport.Client, c codec.NewCodec) *rpcCodec { rwc := &readWriteCloser{ wbuf: bytes.NewBuffer(nil), rbuf: bytes.NewBuffer(nil), From e2623d8ef5f9fe243fdca2a5253c3efef178f18c Mon Sep 17 00:00:00 2001 From: Asim Aslam Date: Mon, 31 Dec 2018 22:01:16 +0000 Subject: [PATCH 070/196] Make json/protobuf codecs --- client/rpc_codec.go | 8 +++++--- codec/json/json.go | 43 ++++++++++++++++++++++++++++++++++++++ codec/proto/proto.go | 49 ++++++++++++++++++++++++++++++++++++++++++++ server/rpc_codec.go | 10 +++++++-- 4 files changed, 105 insertions(+), 5 deletions(-) create mode 100644 codec/json/json.go create mode 100644 codec/proto/proto.go diff --git a/client/rpc_codec.go b/client/rpc_codec.go index 95ff1da1..f5c9401f 100644 --- a/client/rpc_codec.go +++ b/client/rpc_codec.go @@ -5,6 +5,8 @@ import ( errs "errors" "github.com/micro/go-micro/codec" + "github.com/micro/go-micro/codec/json" + "github.com/micro/go-micro/codec/proto" "github.com/micro/go-micro/codec/jsonrpc" "github.com/micro/go-micro/codec/protorpc" "github.com/micro/go-micro/errors" @@ -65,9 +67,9 @@ var ( defaultContentType = "application/octet-stream" defaultCodecs = map[string]codec.NewCodec{ - "application/json": jsonrpc.NewCodec, + "application/protobuf": proto.NewCodec, + "application/json": json.NewCodec, "application/json-rpc": jsonrpc.NewCodec, - "application/protobuf": protorpc.NewCodec, "application/proto-rpc": protorpc.NewCodec, "application/octet-stream": protorpc.NewCodec, } @@ -110,7 +112,7 @@ func (c *rpcCodec) WriteRequest(req *request, body interface{}) error { Method: req.ServiceMethod, Type: codec.Request, Header: map[string]string{ - "X-Micro-Target": req.Service, + "X-Micro-Service": req.Service, "X-Micro-Method": req.ServiceMethod, }, } diff --git a/codec/json/json.go b/codec/json/json.go new file mode 100644 index 00000000..6389541c --- /dev/null +++ b/codec/json/json.go @@ -0,0 +1,43 @@ +// Package json provides a json codec +package json + +import ( + "encoding/json" + "io" + + "github.com/micro/go-micro/codec" +) + +type Codec struct { + Conn io.ReadWriteCloser + Encoder *json.Encoder + Decoder *json.Decoder +} + +func (c *Codec) ReadHeader(m *codec.Message, t codec.MessageType) error { + return nil +} + +func (c *Codec) ReadBody(b interface{}) error { + return c.Decoder.Decode(b) +} + +func (c *Codec) Write(m *codec.Message, b interface{}) error { + return c.Encoder.Encode(b) +} + +func (c *Codec) Close() error { + return c.Conn.Close() +} + +func (c *Codec) String() string { + return "json" +} + +func NewCodec(c io.ReadWriteCloser) codec.Codec { + return &Codec{ + Conn: c, + Decoder: json.NewDecoder(c), + Encoder: json.NewEncoder(c), + } +} diff --git a/codec/proto/proto.go b/codec/proto/proto.go new file mode 100644 index 00000000..339c08c1 --- /dev/null +++ b/codec/proto/proto.go @@ -0,0 +1,49 @@ +// Package proto provides a proto codec +package proto + +import ( + "io" + "io/ioutil" + + "github.com/golang/protobuf/proto" + "github.com/micro/go-micro/codec" +) + +type Codec struct { + Conn io.ReadWriteCloser +} + +func (c *Codec) ReadHeader(m *codec.Message, t codec.MessageType) error { + return nil +} + +func (c *Codec) ReadBody(b interface{}) error { + buf, err := ioutil.ReadAll(c.Conn) + if err != nil { + return err + } + return proto.Unmarshal(buf, b.(proto.Message)) +} + +func (c *Codec) Write(m *codec.Message, b interface{}) error { + buf, err := proto.Marshal(b.(proto.Message)) + if err != nil { + return err + } + _, err = c.Conn.Write(buf) + return err +} + +func (c *Codec) Close() error { + return c.Conn.Close() +} + +func (c *Codec) String() string { + return "proto" +} + +func NewCodec(c io.ReadWriteCloser) codec.Codec { + return &Codec{ + Conn: c, + } +} diff --git a/server/rpc_codec.go b/server/rpc_codec.go index 87a32795..fee01940 100644 --- a/server/rpc_codec.go +++ b/server/rpc_codec.go @@ -4,6 +4,8 @@ import ( "bytes" "github.com/micro/go-micro/codec" + "github.com/micro/go-micro/codec/json" + "github.com/micro/go-micro/codec/proto" "github.com/micro/go-micro/codec/jsonrpc" "github.com/micro/go-micro/codec/protorpc" "github.com/micro/go-micro/transport" @@ -25,9 +27,9 @@ type readWriteCloser struct { var ( defaultCodecs = map[string]codec.NewCodec{ - "application/json": jsonrpc.NewCodec, + "application/json": json.NewCodec, "application/json-rpc": jsonrpc.NewCodec, - "application/protobuf": protorpc.NewCodec, + "application/protobuf": proto.NewCodec, "application/proto-rpc": protorpc.NewCodec, "application/octet-stream": protorpc.NewCodec, } @@ -77,6 +79,10 @@ func (c *rpcCodec) ReadRequestHeader(r *request, first bool) error { m.Header = tm.Header } + // set some internal things + m.Target = m.Header["X-Micro-Service"] + m.Method = m.Header["X-Micro-Method"] + err := c.codec.ReadHeader(&m, codec.Request) r.ServiceMethod = m.Method r.Seq = m.Id From 7cf94162b87624b62eefda22801fc4d7bc9f44be Mon Sep 17 00:00:00 2001 From: Asim Aslam Date: Wed, 2 Jan 2019 12:50:25 +0000 Subject: [PATCH 071/196] remove fmt comment --- transport/http_transport.go | 1 - 1 file changed, 1 deletion(-) diff --git a/transport/http_transport.go b/transport/http_transport.go index b9b37a72..653b74b9 100644 --- a/transport/http_transport.go +++ b/transport/http_transport.go @@ -1,7 +1,6 @@ package transport import ( - //"fmt" "bufio" "bytes" "crypto/tls" From ed580204a822dfdabc4e36d79fa66d50ba1380fd Mon Sep 17 00:00:00 2001 From: Asim Aslam Date: Wed, 2 Jan 2019 12:55:06 +0000 Subject: [PATCH 072/196] Add grpc codec --- client/rpc_codec.go | 4 +- codec/grpc/grpc.go | 119 ++++++++++++++++++++++++++++++++++++ codec/grpc/util.go | 70 +++++++++++++++++++++ server/rpc_codec.go | 8 ++- transport/http_transport.go | 6 ++ 5 files changed, 203 insertions(+), 4 deletions(-) create mode 100644 codec/grpc/grpc.go create mode 100644 codec/grpc/util.go diff --git a/client/rpc_codec.go b/client/rpc_codec.go index f5c9401f..67959b6a 100644 --- a/client/rpc_codec.go +++ b/client/rpc_codec.go @@ -6,8 +6,8 @@ import ( "github.com/micro/go-micro/codec" "github.com/micro/go-micro/codec/json" - "github.com/micro/go-micro/codec/proto" "github.com/micro/go-micro/codec/jsonrpc" + "github.com/micro/go-micro/codec/proto" "github.com/micro/go-micro/codec/protorpc" "github.com/micro/go-micro/errors" "github.com/micro/go-micro/transport" @@ -113,7 +113,7 @@ func (c *rpcCodec) WriteRequest(req *request, body interface{}) error { Type: codec.Request, Header: map[string]string{ "X-Micro-Service": req.Service, - "X-Micro-Method": req.ServiceMethod, + "X-Micro-Method": req.ServiceMethod, }, } if err := c.codec.Write(m, body); err != nil { diff --git a/codec/grpc/grpc.go b/codec/grpc/grpc.go new file mode 100644 index 00000000..f3703840 --- /dev/null +++ b/codec/grpc/grpc.go @@ -0,0 +1,119 @@ +// Package grpc provides a grpc codec +package grpc + +import ( + "encoding/json" + "errors" + "io" + "strings" + + "github.com/golang/protobuf/proto" + "github.com/micro/go-micro/codec" +) + +type Codec struct { + Conn io.ReadWriteCloser + ContentType string +} + +func (c *Codec) ReadHeader(m *codec.Message, t codec.MessageType) error { + if ct := m.Header["Content-Type"]; len(ct) > 0 { + c.ContentType = ct + } + + if ct := m.Header["content-type"]; len(ct) > 0 { + c.ContentType = ct + } + + // service method + path := m.Header[":path"] + if len(path) == 0 || path[0] != '/' { + m.Target = m.Header["X-Micro-Service"] + m.Method = m.Header["X-Micro-Method"] + } else { + // [ , a.package.Foo, Bar] + parts := strings.Split(path, "/") + if len(parts) != 3 { + return errors.New("Unknown request path") + } + service := strings.Split(parts[1], ".") + m.Method = strings.Join([]string{service[len(service)-1], parts[2]}, ".") + m.Target = strings.Join(service[:len(service)-1], ".") + } + + return nil +} + +func (c *Codec) ReadBody(b interface{}) error { + // no body + if b == nil { + return nil + } + + _, buf, err := decode(c.Conn) + if err != nil { + return err + } + + switch c.ContentType { + case "application/grpc+json": + return json.Unmarshal(buf, b) + case "application/grpc+proto", "application/grpc": + return proto.Unmarshal(buf, b.(proto.Message)) + } + + return errors.New("Unsupported Content-Type") +} + +func (c *Codec) Write(m *codec.Message, b interface{}) error { + var buf []byte + var err error + + if ct := m.Header["Content-Type"]; len(ct) > 0 { + c.ContentType = ct + } + + if ct := m.Header["content-type"]; len(ct) > 0 { + c.ContentType = ct + } + + m.Header["Trailer"] = "grpc-status, grpc-message" + + switch c.ContentType { + case "application/grpc+json": + buf, err = json.Marshal(b) + case "application/grpc+proto", "application/grpc": + pb, ok := b.(proto.Message) + if ok { + buf, err = proto.Marshal(pb) + } + default: + err = errors.New("Unsupported Content-Type") + } + + if err != nil { + m.Header["grpc-status"] = "8" + m.Header["grpc-message"] = err.Error() + return err + } + + m.Header["grpc-status"] = "0" + m.Header["grpc-message"] = "" + + return encode(0, buf, c.Conn) +} + +func (c *Codec) Close() error { + return c.Conn.Close() +} + +func (c *Codec) String() string { + return "grpc" +} + +func NewCodec(c io.ReadWriteCloser) codec.Codec { + return &Codec{ + Conn: c, + ContentType: "application/grpc", + } +} diff --git a/codec/grpc/util.go b/codec/grpc/util.go new file mode 100644 index 00000000..04c5ee38 --- /dev/null +++ b/codec/grpc/util.go @@ -0,0 +1,70 @@ +package grpc + +import ( + "encoding/binary" + "fmt" + "io" +) + +var ( + maxMessageSize = 1024 * 1024 * 4 + maxInt = int(^uint(0) >> 1) +) + +func decode(r io.Reader) (uint8, []byte, error) { + header := make([]byte, 5) + + // read the header + if _, err := r.Read(header[:]); err != nil { + return uint8(0), nil, err + } + + // get encoding format e.g compressed + cf := uint8(header[0]) + + // get message length + length := binary.BigEndian.Uint32(header[1:]) + + // no encoding format + if length == 0 { + return cf, nil, nil + } + + // + if int64(length) > int64(maxInt) { + return cf, nil, fmt.Errorf("grpc: received message larger than max length allowed on current machine (%d vs. %d)", length, maxInt) + } + if int(length) > maxMessageSize { + return cf, nil, fmt.Errorf("grpc: received message larger than max (%d vs. %d)", length, maxMessageSize) + } + + msg := make([]byte, int(length)) + + if _, err := r.Read(msg); err != nil { + if err == io.EOF { + err = io.ErrUnexpectedEOF + } + return cf, nil, err + } + + return cf, msg, nil +} + +func encode(cf uint8, buf []byte, w io.Writer) error { + header := make([]byte, 5) + + // set compression + header[0] = byte(cf) + + // write length as header + binary.BigEndian.PutUint32(header[1:], uint32(len(buf))) + + // read the header + if _, err := w.Write(header[:]); err != nil { + return err + } + + // write the buffer + _, err := w.Write(buf) + return err +} diff --git a/server/rpc_codec.go b/server/rpc_codec.go index fee01940..f19b2782 100644 --- a/server/rpc_codec.go +++ b/server/rpc_codec.go @@ -4,9 +4,10 @@ import ( "bytes" "github.com/micro/go-micro/codec" - "github.com/micro/go-micro/codec/json" - "github.com/micro/go-micro/codec/proto" + "github.com/micro/go-micro/codec/grpc" + "github.com/micro/go-micro/codec/json" "github.com/micro/go-micro/codec/jsonrpc" + "github.com/micro/go-micro/codec/proto" "github.com/micro/go-micro/codec/protorpc" "github.com/micro/go-micro/transport" "github.com/pkg/errors" @@ -27,6 +28,9 @@ type readWriteCloser struct { var ( defaultCodecs = map[string]codec.NewCodec{ + "application/grpc": grpc.NewCodec, + "application/grpc+json": grpc.NewCodec, + "application/grpc+proto": grpc.NewCodec, "application/json": json.NewCodec, "application/json-rpc": jsonrpc.NewCodec, "application/protobuf": proto.NewCodec, diff --git a/transport/http_transport.go b/transport/http_transport.go index 653b74b9..206bdec5 100644 --- a/transport/http_transport.go +++ b/transport/http_transport.go @@ -245,6 +245,9 @@ func (h *httpTransportSocket) Recv(m *Message) error { } } + // set path + m.Header[":path"] = h.r.URL.Path + // return early early return nil } @@ -276,6 +279,9 @@ func (h *httpTransportSocket) Recv(m *Message) error { } } + // set path + m.Header[":path"] = h.r.URL.Path + return nil } From 2761b8e0f59c4462a8e7b9d398cb69c661b868cd Mon Sep 17 00:00:00 2001 From: Asim Aslam Date: Wed, 2 Jan 2019 15:24:17 +0000 Subject: [PATCH 073/196] Add support for http proxy --- transport/http_proxy.go | 109 ++++++++++++++++++++++++++++++++++++ transport/http_transport.go | 8 ++- 2 files changed, 115 insertions(+), 2 deletions(-) create mode 100644 transport/http_proxy.go diff --git a/transport/http_proxy.go b/transport/http_proxy.go new file mode 100644 index 00000000..567dd739 --- /dev/null +++ b/transport/http_proxy.go @@ -0,0 +1,109 @@ +package transport + +import ( + "bufio" + "encoding/base64" + "fmt" + "io" + "net" + "net/http" + "net/http/httputil" + "net/url" +) + +const ( + proxyAuthHeader = "Proxy-Authorization" +) + +func getURL(addr string) (*url.URL, error) { + r := &http.Request{ + URL: &url.URL{ + Scheme: "https", + Host: addr, + }, + } + return http.ProxyFromEnvironment(r) +} + +type pbuffer struct { + net.Conn + r io.Reader +} + +func (p *pbuffer) Read(b []byte) (int, error) { + return p.r.Read(b) +} + +func proxyDial(conn net.Conn, addr string, proxyURL *url.URL) (_ net.Conn, err error) { + defer func() { + if err != nil { + conn.Close() + } + }() + + r := &http.Request{ + Method: http.MethodConnect, + URL: &url.URL{Host: addr}, + Header: map[string][]string{"User-Agent": {"micro/latest"}}, + } + + if user := proxyURL.User; user != nil { + u := user.Username() + p, _ := user.Password() + auth := []byte(u + ":" + p) + basicAuth := base64.StdEncoding.EncodeToString(auth) + r.Header.Add(proxyAuthHeader, "Basic "+basicAuth) + } + + if err := r.Write(conn); err != nil { + return nil, fmt.Errorf("failed to write the HTTP request: %v", err) + } + + br := bufio.NewReader(conn) + rsp, err := http.ReadResponse(br, r) + if err != nil { + return nil, fmt.Errorf("reading server HTTP response: %v", err) + } + defer rsp.Body.Close() + if rsp.StatusCode != http.StatusOK { + dump, err := httputil.DumpResponse(rsp, true) + if err != nil { + return nil, fmt.Errorf("failed to do connect handshake, status code: %s", rsp.Status) + } + return nil, fmt.Errorf("failed to do connect handshake, response: %q", dump) + } + + return &pbuffer{Conn: conn, r: br}, nil +} + +// Creates a new connection +func newConn(dial func(string) (net.Conn, error)) func(string) (net.Conn, error) { + return func(addr string) (net.Conn, error) { + // get the proxy url + proxyURL, err := getURL(addr) + if err != nil { + return nil, err + } + + // set to addr + callAddr := addr + + // got proxy + if proxyURL != nil { + callAddr = proxyURL.Host + } + + // dial the addr + c, err := dial(callAddr) + if err != nil { + return nil, err + } + + // do proxy connect if we have proxy url + if proxyURL != nil { + c, err = proxyDial(c, addr, proxyURL) + } + + return c, err + } +} diff --git a/transport/http_transport.go b/transport/http_transport.go index b9b37a72..4128404c 100644 --- a/transport/http_transport.go +++ b/transport/http_transport.go @@ -452,9 +452,13 @@ func (h *httpTransport) Dial(addr string, opts ...DialOption) (Client, error) { InsecureSkipVerify: true, } } - conn, err = tls.DialWithDialer(&net.Dialer{Timeout: dopts.Timeout}, "tcp", addr, config) + conn, err = newConn(func(addr string) (net.Conn, error) { + return tls.DialWithDialer(&net.Dialer{Timeout: dopts.Timeout}, "tcp", addr, config) + })(addr) } else { - conn, err = net.DialTimeout("tcp", addr, dopts.Timeout) + conn, err = newConn(func(addr string) (net.Conn, error) { + return net.DialTimeout("tcp", addr, dopts.Timeout) + })(addr) } if err != nil { From abbeb6d0688645a1cf2bd7899023225d096f102d Mon Sep 17 00:00:00 2001 From: Asim Aslam Date: Wed, 2 Jan 2019 19:27:46 +0000 Subject: [PATCH 074/196] add inbox feature to http broker --- broker/http_broker.go | 138 +++++++++++++++++++++++++++++++++--------- 1 file changed, 109 insertions(+), 29 deletions(-) diff --git a/broker/http_broker.go b/broker/http_broker.go index a761a197..901d4f4c 100644 --- a/broker/http_broker.go +++ b/broker/http_broker.go @@ -45,6 +45,10 @@ type httpBroker struct { subscribers map[string][]*httpSubscriber running bool exit chan chan error + + // offline message inbox + mtx sync.RWMutex + inbox map[string][][]byte } type httpSubscriber struct { @@ -133,6 +137,7 @@ func newHttpBroker(opts ...Option) Broker { subscribers: make(map[string][]*httpSubscriber), exit: make(chan chan error), mux: http.NewServeMux(), + inbox: make(map[string][][]byte), } // specify the message handler @@ -175,6 +180,49 @@ func (h *httpSubscriber) Unsubscribe() error { return h.hb.unsubscribe(h) } +func (h *httpBroker) saveMessage(topic string, msg []byte) { + h.mtx.Lock() + defer h.mtx.Unlock() + + // get messages + c := h.inbox[topic] + + // save message + c = append(c, msg) + + // max length 64 + if len(c) > 64 { + c = c[:64] + } + + // save inbox + h.inbox[topic] = c +} + +func (h *httpBroker) getMessage(topic string, num int) [][]byte { + h.mtx.Lock() + defer h.mtx.Unlock() + + // get messages + c, ok := h.inbox[topic] + if !ok { + return nil + } + + // more message than requests + if len(c) >= num { + msg := c[:num] + h.inbox[topic] = c[num:] + return msg + } + + // reset inbox + h.inbox[topic] = nil + + // return all messages + return c +} + func (h *httpBroker) subscribe(s *httpSubscriber) error { h.Lock() defer h.Unlock() @@ -454,14 +502,7 @@ func (h *httpBroker) Options() Options { } func (h *httpBroker) Publish(topic string, msg *Message, opts ...PublishOption) error { - h.RLock() - s, err := h.r.GetService("topic:" + topic) - if err != nil { - h.RUnlock() - return err - } - h.RUnlock() - + // create the message first m := &Message{ Header: make(map[string]string), Body: msg.Body, @@ -473,12 +514,26 @@ func (h *httpBroker) Publish(topic string, msg *Message, opts ...PublishOption) m.Header[":topic"] = topic + // encode the message b, err := h.opts.Codec.Marshal(m) if err != nil { return err } - pub := func(node *registry.Node, b []byte) { + // save the message + h.saveMessage(topic, b) + + // now attempt to get the service + h.RLock() + s, err := h.r.GetService("topic:" + topic) + if err != nil { + h.RUnlock() + // ignore error + return nil + } + h.RUnlock() + + pub := func(node *registry.Node, t string, b []byte) { scheme := "http" // check if secure is added in metadata @@ -491,34 +546,59 @@ func (h *httpBroker) Publish(topic string, msg *Message, opts ...PublishOption) uri := fmt.Sprintf("%s://%s:%d%s?%s", scheme, node.Address, node.Port, DefaultSubPath, vals.Encode()) r, err := h.c.Post(uri, "application/json", bytes.NewReader(b)) - if err == nil { - io.Copy(ioutil.Discard, r.Body) - r.Body.Close() + if err != nil { + // save on error + h.saveMessage(t, b) + return } + + // discard response body + io.Copy(ioutil.Discard, r.Body) + r.Body.Close() } - for _, service := range s { - // only process if we have nodes - if len(service.Nodes) == 0 { - continue - } - - switch service.Version { - // broadcast version means broadcast to all nodes - case broadcastVersion: - for _, node := range service.Nodes { - // publish async - go pub(node, b) + srv := func(s []*registry.Service, b []byte) { + for _, service := range s { + // only process if we have nodes + if len(service.Nodes) == 0 { + continue } - default: - // select node to publish to - node := service.Nodes[rand.Int()%len(service.Nodes)] - // publish async - go pub(node, b) + switch service.Version { + // broadcast version means broadcast to all nodes + case broadcastVersion: + for _, node := range service.Nodes { + // publish async + pub(node, topic, b) + } + default: + // select node to publish to + node := service.Nodes[rand.Int()%len(service.Nodes)] + + // publish async + pub(node, topic, b) + } } } + // do the rest async + go func() { + // get a third of the backlog + messages := h.getMessage(topic, 8) + delay := (len(messages) > 1) + + // publish all the messages + for _, msg := range messages { + // serialize here + srv(s, msg) + + // sending a backlog of messages + if delay { + time.Sleep(time.Millisecond * 100) + } + } + }() + return nil } From 7c2cbe2ad29d79363e265a5bc973c85b284a8bf9 Mon Sep 17 00:00:00 2001 From: Asim Aslam Date: Thu, 3 Jan 2019 11:23:06 +0000 Subject: [PATCH 075/196] better error handling --- broker/http_broker.go | 26 +++++++++++++++++++------- 1 file changed, 19 insertions(+), 7 deletions(-) diff --git a/broker/http_broker.go b/broker/http_broker.go index 901d4f4c..3e842b3c 100644 --- a/broker/http_broker.go +++ b/broker/http_broker.go @@ -533,7 +533,7 @@ func (h *httpBroker) Publish(topic string, msg *Message, opts ...PublishOption) } h.RUnlock() - pub := func(node *registry.Node, t string, b []byte) { + pub := func(node *registry.Node, t string, b []byte) error { scheme := "http" // check if secure is added in metadata @@ -547,14 +547,13 @@ func (h *httpBroker) Publish(topic string, msg *Message, opts ...PublishOption) uri := fmt.Sprintf("%s://%s:%d%s?%s", scheme, node.Address, node.Port, DefaultSubPath, vals.Encode()) r, err := h.c.Post(uri, "application/json", bytes.NewReader(b)) if err != nil { - // save on error - h.saveMessage(t, b) - return + return err } // discard response body io.Copy(ioutil.Discard, r.Body) r.Body.Close() + return nil } srv := func(s []*registry.Service, b []byte) { @@ -567,16 +566,29 @@ func (h *httpBroker) Publish(topic string, msg *Message, opts ...PublishOption) switch service.Version { // broadcast version means broadcast to all nodes case broadcastVersion: + var success bool + + // publish to all nodes for _, node := range service.Nodes { // publish async - pub(node, topic, b) + if err := pub(node, topic, b); err == nil { + success = true + } + } + + // save if it failed to publish at least once + if !success { + h.saveMessage(topic, b) } default: // select node to publish to node := service.Nodes[rand.Int()%len(service.Nodes)] - // publish async - pub(node, topic, b) + // publish async to one node + if err := pub(node, topic, b); err != nil { + // if failed save it + h.saveMessage(topic, b) + } } } } From 4adc31e62dca752b17c18577fe89dbe8ba00e3e3 Mon Sep 17 00:00:00 2001 From: Asim Aslam Date: Fri, 4 Jan 2019 14:07:16 +0000 Subject: [PATCH 076/196] add bytes codec, still unused --- codec/bytes/bytes.go | 58 ++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 58 insertions(+) create mode 100644 codec/bytes/bytes.go diff --git a/codec/bytes/bytes.go b/codec/bytes/bytes.go new file mode 100644 index 00000000..b2604df2 --- /dev/null +++ b/codec/bytes/bytes.go @@ -0,0 +1,58 @@ +// Package bytes provides a bytes codec which does not encode or decode anything +package bytes + +import ( + "fmt" + "io" + "io/ioutil" + + "github.com/micro/go-micro/codec" +) + +type Codec struct { + Conn io.ReadWriteCloser +} + +func (c *Codec) ReadHeader(m *codec.Message, t codec.MessageType) error { + return nil +} + +func (c *Codec) ReadBody(b interface{}) error { + v, ok := b.(*[]byte) + if !ok { + return fmt.Errorf("failed to read body: %v is not type of *[]byte", b) + } + + // read bytes + buf, err := ioutil.ReadAll(c.Conn) + if err != nil { + return err + } + + // set bytes + *v = buf + return nil +} + +func (c *Codec) Write(m *codec.Message, b interface{}) error { + v, ok := b.(*[]byte) + if !ok { + return fmt.Errorf("failed to write: %v is not type of *[]byte", b) + } + _, err := c.Conn.Write(*v) + return err +} + +func (c *Codec) Close() error { + return c.Conn.Close() +} + +func (c *Codec) String() string { + return "bytes" +} + +func NewCodec(c io.ReadWriteCloser) codec.Codec { + return &Codec{ + Conn: c, + } +} From 4692af43931275ec3da0cfc03170adda3c1f5f74 Mon Sep 17 00:00:00 2001 From: Asim Aslam Date: Sun, 6 Jan 2019 21:12:02 +0000 Subject: [PATCH 077/196] Add static selector --- cmd/cmd.go | 2 ++ selector/static/static.go | 71 +++++++++++++++++++++++++++++++++++++++ 2 files changed, 73 insertions(+) create mode 100644 selector/static/static.go diff --git a/cmd/cmd.go b/cmd/cmd.go index 7d41b452..91a821c7 100644 --- a/cmd/cmd.go +++ b/cmd/cmd.go @@ -26,6 +26,7 @@ import ( // selectors "github.com/micro/go-micro/selector" + "github.com/micro/go-micro/selector/static" // transports "github.com/micro/go-micro/transport" @@ -178,6 +179,7 @@ var ( DefaultSelectors = map[string]func(...selector.Option) selector.Selector{ "default": selector.NewSelector, "cache": selector.NewSelector, + "static": static.NewSelector, } DefaultServers = map[string]func(...server.Option) server.Server{ diff --git a/selector/static/static.go b/selector/static/static.go new file mode 100644 index 00000000..11c2c9cf --- /dev/null +++ b/selector/static/static.go @@ -0,0 +1,71 @@ +// Package static provides a static resolver which returns the name/ip passed in without any change +package static + +import ( + "net" + "strconv" + + "github.com/micro/go-micro/registry" + "github.com/micro/go-micro/selector" +) + +// staticSelector is a static selector +type staticSelector struct { + opts selector.Options +} + +func (s *staticSelector) Init(opts ...selector.Option) error { + for _, o := range opts { + o(&s.opts) + } + return nil +} + +func (s *staticSelector) Options() selector.Options { + return s.opts +} + +func (s *staticSelector) Select(service string, opts ...selector.SelectOption) (selector.Next, error) { + var port int + addr, pt, err := net.SplitHostPort(service) + if err != nil { + addr = service + port = 0 + } else { + port, _ = strconv.Atoi(pt) + } + + return func() (*registry.Node, error) { + return ®istry.Node{ + Id: service, + Address: addr, + Port: port, + }, nil + }, nil +} + +func (s *staticSelector) Mark(service string, node *registry.Node, err error) { + return +} + +func (s *staticSelector) Reset(service string) { + return +} + +func (s *staticSelector) Close() error { + return nil +} + +func (s *staticSelector) String() string { + return "static" +} + +func NewSelector(opts ...selector.Option) selector.Selector { + var options selector.Options + for _, o := range opts { + o(&options) + } + return &staticSelector{ + opts: options, + } +} From f9da55e8a9d4fa6ca54984170fe647248185e266 Mon Sep 17 00:00:00 2001 From: Asim Aslam Date: Mon, 7 Jan 2019 07:41:26 +0000 Subject: [PATCH 078/196] Add dns selector --- cmd/cmd.go | 2 + selector/dns/dns.go | 100 ++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 102 insertions(+) create mode 100644 selector/dns/dns.go diff --git a/cmd/cmd.go b/cmd/cmd.go index 7d41b452..5793b48f 100644 --- a/cmd/cmd.go +++ b/cmd/cmd.go @@ -26,6 +26,7 @@ import ( // selectors "github.com/micro/go-micro/selector" + "github.com/micro/go-micro/selector/dns" // transports "github.com/micro/go-micro/transport" @@ -177,6 +178,7 @@ var ( DefaultSelectors = map[string]func(...selector.Option) selector.Selector{ "default": selector.NewSelector, + "dns": dns.NewSelector, "cache": selector.NewSelector, } diff --git a/selector/dns/dns.go b/selector/dns/dns.go new file mode 100644 index 00000000..05f493cc --- /dev/null +++ b/selector/dns/dns.go @@ -0,0 +1,100 @@ +// Package dns provides a dns SRV selector +package dns + +import ( + "net" + + "github.com/micro/go-micro/registry" + "github.com/micro/go-micro/selector" +) + +type dnsSelector struct { + options selector.Options + domain string +} + +var ( + DefaultDomain = "local" +) + +func (d *dnsSelector) Init(opts ...selector.Option) error { + for _, o := range opts { + o(&d.options) + } + return nil +} + +func (d *dnsSelector) Options() selector.Options { + return d.options +} + +func (d *dnsSelector) Select(service string, opts ...selector.SelectOption) (selector.Next, error) { + _, srv, err := net.LookupSRV(service, "tcp", d.domain) + if err != nil { + return nil, err + } + + var nodes []*registry.Node + for _, node := range srv { + nodes = append(nodes, ®istry.Node{ + Id: node.Target, + Address: node.Target, + Port: int(node.Port), + }) + } + + services := []*registry.Service{ + ®istry.Service{ + Name: service, + Nodes: nodes, + }, + } + + sopts := selector.SelectOptions{ + Strategy: d.options.Strategy, + } + + for _, opt := range opts { + opt(&sopts) + } + + // apply the filters + for _, filter := range sopts.Filters { + services = filter(services) + } + + // if there's nothing left, return + if len(services) == 0 { + return nil, selector.ErrNoneAvailable + } + + return sopts.Strategy(services), nil +} + +func (d *dnsSelector) Mark(service string, node *registry.Node, err error) { + return +} + +func (d *dnsSelector) Reset(service string) { + return +} + +func (d *dnsSelector) Close() error { + return nil +} + +func (d *dnsSelector) String() string { + return "dns" +} + +func NewSelector(opts ...selector.Option) selector.Selector { + options := selector.Options{ + Strategy: selector.Random, + } + + for _, o := range opts { + o(&options) + } + + return &dnsSelector{options: options, domain: DefaultDomain} +} From 5aeb28dfee621f449560d3f2a6a8f25a92421b5a Mon Sep 17 00:00:00 2001 From: Asim Aslam Date: Mon, 7 Jan 2019 09:11:36 +0000 Subject: [PATCH 079/196] Add error header --- client/rpc_codec.go | 18 ++++++++++++++++++ server/rpc_codec.go | 17 ++++++++++++++++- 2 files changed, 34 insertions(+), 1 deletion(-) diff --git a/client/rpc_codec.go b/client/rpc_codec.go index 67959b6a..1a341a7c 100644 --- a/client/rpc_codec.go +++ b/client/rpc_codec.go @@ -3,6 +3,8 @@ package client import ( "bytes" errs "errors" + "fmt" + "strconv" "github.com/micro/go-micro/codec" "github.com/micro/go-micro/codec/json" @@ -112,6 +114,7 @@ func (c *rpcCodec) WriteRequest(req *request, body interface{}) error { Method: req.ServiceMethod, Type: codec.Request, Header: map[string]string{ + "X-Micro-Id": fmt.Sprintf("%d", req.Seq), "X-Micro-Service": req.Service, "X-Micro-Method": req.ServiceMethod, }, @@ -147,6 +150,21 @@ func (c *rpcCodec) ReadResponse(r *response, b interface{}) error { r.Seq = me.Id r.Error = me.Error + // check error in header + if len(me.Error) == 0 { + r.Error = me.Header["X-Micro-Error"] + } + + // check method in header + if len(me.Method) == 0 { + r.ServiceMethod = me.Header["X-Micro-Method"] + } + + if me.Id == 0 && len(me.Header["X-Micro-Id"]) > 0 { + id, _ := strconv.ParseInt(me.Header["X-Micro-Id"], 10, 64) + r.Seq = uint64(id) + } + if err != nil { return errors.InternalServerError("go.micro.client.codec", err.Error()) } diff --git a/server/rpc_codec.go b/server/rpc_codec.go index f19b2782..6afc4e4b 100644 --- a/server/rpc_codec.go +++ b/server/rpc_codec.go @@ -2,6 +2,8 @@ package server import ( "bytes" + "fmt" + "strconv" "github.com/micro/go-micro/codec" "github.com/micro/go-micro/codec/grpc" @@ -87,9 +89,17 @@ func (c *rpcCodec) ReadRequestHeader(r *request, first bool) error { m.Target = m.Header["X-Micro-Service"] m.Method = m.Header["X-Micro-Method"] + // set id + if len(m.Header["X-Micro-Id"]) > 0 { + id, _ := strconv.ParseInt(m.Header["X-Micro-Id"], 10, 64) + m.Id = uint64(id) + } + + // read header via codec err := c.codec.ReadHeader(&m, codec.Request) r.ServiceMethod = m.Method r.Seq = m.Id + return err } @@ -104,11 +114,16 @@ func (c *rpcCodec) WriteResponse(r *response, body interface{}, last bool) error Id: r.Seq, Error: r.Error, Type: codec.Response, - Header: map[string]string{}, + Header: map[string]string{ + "X-Micro-Id": fmt.Sprintf("%d", r.Seq), + "X-Micro-Method": r.ServiceMethod, + "X-Micro-Error": r.Error, + }, } if err := c.codec.Write(m, body); err != nil { c.buf.wbuf.Reset() m.Error = errors.Wrapf(err, "Unable to encode body").Error() + m.Header["X-Micro-Error"] = m.Error if err := c.codec.Write(m, nil); err != nil { return err } From d6a5ff432cf3df2db63a00e28d1875c86138e843 Mon Sep 17 00:00:00 2001 From: Asim Aslam Date: Mon, 7 Jan 2019 09:34:07 +0000 Subject: [PATCH 080/196] add net.LookupHost for dns --- selector/dns/dns.go | 32 ++++++++++++++++++++++++++++++-- 1 file changed, 30 insertions(+), 2 deletions(-) diff --git a/selector/dns/dns.go b/selector/dns/dns.go index 05f493cc..d3882ac1 100644 --- a/selector/dns/dns.go +++ b/selector/dns/dns.go @@ -3,6 +3,7 @@ package dns import ( "net" + "strconv" "github.com/micro/go-micro/registry" "github.com/micro/go-micro/selector" @@ -29,9 +30,36 @@ func (d *dnsSelector) Options() selector.Options { } func (d *dnsSelector) Select(service string, opts ...selector.SelectOption) (selector.Next, error) { - _, srv, err := net.LookupSRV(service, "tcp", d.domain) + var srv []*net.SRV + + // check if its host:port + host, port, err := net.SplitHostPort(service) + // not host:port if err != nil { - return nil, err + // lookup the SRV record + _, srvs, err := net.LookupSRV(service, "tcp", d.domain) + if err != nil { + return nil, err + } + // set SRV records + srv = srvs + // got host:port + } else { + p, _ := strconv.Atoi(port) + + // lookup the A record + ips, err := net.LookupHost(host) + if err != nil { + return nil, err + } + + // create SRV records + for _, ip := range ips { + srv = append(srv, &net.SRV{ + Target: ip, + Port: uint16(p), + }) + } } var nodes []*registry.Node From d179c971af13b5c9b810db7905a0deae78222c9b Mon Sep 17 00:00:00 2001 From: Asim Aslam Date: Mon, 7 Jan 2019 13:48:38 +0000 Subject: [PATCH 081/196] Switch default codec and add default codec for server --- client/options.go | 2 +- client/rpc_client.go | 2 +- client/rpc_codec.go | 7 ++++--- server/rpc_codec.go | 7 +++++-- server/rpc_server.go | 9 +++++++-- 5 files changed, 18 insertions(+), 9 deletions(-) diff --git a/client/options.go b/client/options.go index 8b924038..aa65381e 100644 --- a/client/options.go +++ b/client/options.go @@ -99,7 +99,7 @@ func newOptions(options ...Option) Options { } if len(opts.ContentType) == 0 { - opts.ContentType = defaultContentType + opts.ContentType = DefaultContentType } if opts.Broker == nil { diff --git a/client/rpc_client.go b/client/rpc_client.go index 2b84d5dd..f229b495 100644 --- a/client/rpc_client.go +++ b/client/rpc_client.go @@ -49,7 +49,7 @@ func (r *rpcClient) newCodec(contentType string) (codec.NewCodec, error) { if c, ok := r.opts.Codecs[contentType]; ok { return c, nil } - if cf, ok := defaultCodecs[contentType]; ok { + if cf, ok := DefaultCodecs[contentType]; ok { return cf, nil } return nil, fmt.Errorf("Unsupported Content-Type: %s", contentType) diff --git a/client/rpc_codec.go b/client/rpc_codec.go index 1a341a7c..310548a4 100644 --- a/client/rpc_codec.go +++ b/client/rpc_codec.go @@ -7,6 +7,7 @@ import ( "strconv" "github.com/micro/go-micro/codec" + raw "github.com/micro/go-micro/codec/bytes" "github.com/micro/go-micro/codec/json" "github.com/micro/go-micro/codec/jsonrpc" "github.com/micro/go-micro/codec/proto" @@ -66,14 +67,14 @@ type response struct { } var ( - defaultContentType = "application/octet-stream" + DefaultContentType = "application/protobuf" - defaultCodecs = map[string]codec.NewCodec{ + DefaultCodecs = map[string]codec.NewCodec{ "application/protobuf": proto.NewCodec, "application/json": json.NewCodec, "application/json-rpc": jsonrpc.NewCodec, "application/proto-rpc": protorpc.NewCodec, - "application/octet-stream": protorpc.NewCodec, + "application/octet-stream": raw.NewCodec, } ) diff --git a/server/rpc_codec.go b/server/rpc_codec.go index 6afc4e4b..4543b0b5 100644 --- a/server/rpc_codec.go +++ b/server/rpc_codec.go @@ -6,6 +6,7 @@ import ( "strconv" "github.com/micro/go-micro/codec" + raw "github.com/micro/go-micro/codec/bytes" "github.com/micro/go-micro/codec/grpc" "github.com/micro/go-micro/codec/json" "github.com/micro/go-micro/codec/jsonrpc" @@ -29,7 +30,9 @@ type readWriteCloser struct { } var ( - defaultCodecs = map[string]codec.NewCodec{ + DefaultContentType = "application/protobuf" + + DefaultCodecs = map[string]codec.NewCodec{ "application/grpc": grpc.NewCodec, "application/grpc+json": grpc.NewCodec, "application/grpc+proto": grpc.NewCodec, @@ -37,7 +40,7 @@ var ( "application/json-rpc": jsonrpc.NewCodec, "application/protobuf": proto.NewCodec, "application/proto-rpc": protorpc.NewCodec, - "application/octet-stream": protorpc.NewCodec, + "application/octet-stream": raw.NewCodec, } ) diff --git a/server/rpc_server.go b/server/rpc_server.go index 171848b0..5528521c 100644 --- a/server/rpc_server.go +++ b/server/rpc_server.go @@ -74,8 +74,13 @@ func (s *rpcServer) accept(sock transport.Socket) { // we use this Content-Type header to identify the codec needed ct := msg.Header["Content-Type"] - cf, err := s.newCodec(ct) + // no content type + if len(ct) == 0 { + ct = DefaultContentType + } + // TODO: needs better error handling + cf, err := s.newCodec(ct) if err != nil { sock.Send(&transport.Message{ Header: map[string]string{ @@ -124,7 +129,7 @@ func (s *rpcServer) newCodec(contentType string) (codec.NewCodec, error) { if cf, ok := s.opts.Codecs[contentType]; ok { return cf, nil } - if cf, ok := defaultCodecs[contentType]; ok { + if cf, ok := DefaultCodecs[contentType]; ok { return cf, nil } return nil, fmt.Errorf("Unsupported Content-Type: %s", contentType) From 46ece968d4b69b4cb988e29135bf802e06bc52d9 Mon Sep 17 00:00:00 2001 From: Asim Aslam Date: Mon, 7 Jan 2019 14:44:40 +0000 Subject: [PATCH 082/196] rename service to router --- server/{rpc_service.go => rpc_router.go} | 118 ++++++++++++----------- server/rpc_server.go | 28 +++--- server/server.go | 6 ++ 3 files changed, 81 insertions(+), 71 deletions(-) rename server/{rpc_service.go => rpc_router.go} (81%) diff --git a/server/rpc_service.go b/server/rpc_router.go similarity index 81% rename from server/rpc_service.go rename to server/rpc_router.go index 14b667c9..6e67265a 100644 --- a/server/rpc_service.go +++ b/server/rpc_router.go @@ -60,8 +60,8 @@ type response struct { next *response // for free list in Server } -// server represents an RPC Server. -type server struct { +// router represents an RPC router. +type router struct { name string mu sync.Mutex // protects the serviceMap serviceMap map[string]*service @@ -72,6 +72,14 @@ type server struct { hdlrWrappers []HandlerWrapper } +func newRpcRouter(opts Options) *router { + return &router{ + name: opts.Name, + hdlrWrappers: opts.HdlrWrappers, + serviceMap: make(map[string]*service), + } +} + // Is this an exported - upper case - name? func isExported(name string) bool { rune, _ := utf8.DecodeRuneInString(name) @@ -158,11 +166,11 @@ func prepareMethod(method reflect.Method) *methodType { return &methodType{method: method, ArgType: argType, ReplyType: replyType, ContextType: contextType, stream: stream} } -func (server *server) register(rcvr interface{}) error { - server.mu.Lock() - defer server.mu.Unlock() - if server.serviceMap == nil { - server.serviceMap = make(map[string]*service) +func (router *router) register(rcvr interface{}) error { + router.mu.Lock() + defer router.mu.Unlock() + if router.serviceMap == nil { + router.serviceMap = make(map[string]*service) } s := new(service) s.typ = reflect.TypeOf(rcvr) @@ -176,7 +184,7 @@ func (server *server) register(rcvr interface{}) error { log.Log(s) return errors.New(s) } - if _, present := server.serviceMap[sname]; present { + if _, present := router.serviceMap[sname]; present { return errors.New("rpc: service already defined: " + sname) } s.name = sname @@ -195,12 +203,12 @@ func (server *server) register(rcvr interface{}) error { log.Log(s) return errors.New(s) } - server.serviceMap[s.name] = s + router.serviceMap[s.name] = s return nil } -func (server *server) sendResponse(sending sync.Locker, req *request, reply interface{}, codec serverCodec, errmsg string, last bool) (err error) { - resp := server.getResponse() +func (router *router) sendResponse(sending sync.Locker, req *request, reply interface{}, codec serverCodec, errmsg string, last bool) (err error) { + resp := router.getResponse() // Encode the response header resp.ServiceMethod = req.ServiceMethod if errmsg != "" { @@ -211,16 +219,16 @@ func (server *server) sendResponse(sending sync.Locker, req *request, reply inte sending.Lock() err = codec.WriteResponse(resp, reply, last) sending.Unlock() - server.freeResponse(resp) + router.freeResponse(resp) return err } -func (s *service) call(ctx context.Context, server *server, sending *sync.Mutex, mtype *methodType, req *request, argv, replyv reflect.Value, codec serverCodec, ct string) { +func (s *service) call(ctx context.Context, router *router, sending *sync.Mutex, mtype *methodType, req *request, argv, replyv reflect.Value, codec serverCodec, ct string) { function := mtype.method.Func var returnValues []reflect.Value r := &rpcRequest{ - service: server.name, + service: router.name, contentType: ct, method: req.ServiceMethod, } @@ -239,8 +247,8 @@ func (s *service) call(ctx context.Context, server *server, sending *sync.Mutex, return nil } - for i := len(server.hdlrWrappers); i > 0; i-- { - fn = server.hdlrWrappers[i-1](fn) + for i := len(router.hdlrWrappers); i > 0; i-- { + fn = router.hdlrWrappers[i-1](fn) } errmsg := "" @@ -249,11 +257,11 @@ func (s *service) call(ctx context.Context, server *server, sending *sync.Mutex, errmsg = err.Error() } - err = server.sendResponse(sending, req, replyv.Interface(), codec, errmsg, true) + err = router.sendResponse(sending, req, replyv.Interface(), codec, errmsg, true) if err != nil { log.Log("rpc call: unable to send response: ", err) } - server.freeRequest(req) + router.freeRequest(req) return } @@ -284,8 +292,8 @@ func (s *service) call(ctx context.Context, server *server, sending *sync.Mutex, } } - for i := len(server.hdlrWrappers); i > 0; i-- { - fn = server.hdlrWrappers[i-1](fn) + for i := len(router.hdlrWrappers); i > 0; i-- { + fn = router.hdlrWrappers[i-1](fn) } // client.Stream request @@ -299,8 +307,8 @@ func (s *service) call(ctx context.Context, server *server, sending *sync.Mutex, // this is the last packet, we don't do anything with // the error here (well sendStreamResponse will log it // already) - server.sendResponse(sending, req, nil, codec, errmsg, true) - server.freeRequest(req) + router.sendResponse(sending, req, nil, codec, errmsg, true) + router.freeRequest(req) } func (m *methodType) prepareContext(ctx context.Context) reflect.Value { @@ -310,66 +318,66 @@ func (m *methodType) prepareContext(ctx context.Context) reflect.Value { return reflect.Zero(m.ContextType) } -func (server *server) serveRequest(ctx context.Context, codec serverCodec, ct string) error { +func (router *router) serveRequest(ctx context.Context, codec serverCodec, ct string) error { sending := new(sync.Mutex) - service, mtype, req, argv, replyv, keepReading, err := server.readRequest(codec) + service, mtype, req, argv, replyv, keepReading, err := router.readRequest(codec) if err != nil { if !keepReading { return err } // send a response if we actually managed to read a header. if req != nil { - server.sendResponse(sending, req, invalidRequest, codec, err.Error(), true) - server.freeRequest(req) + router.sendResponse(sending, req, invalidRequest, codec, err.Error(), true) + router.freeRequest(req) } return err } - service.call(ctx, server, sending, mtype, req, argv, replyv, codec, ct) + service.call(ctx, router, sending, mtype, req, argv, replyv, codec, ct) return nil } -func (server *server) getRequest() *request { - server.reqLock.Lock() - req := server.freeReq +func (router *router) getRequest() *request { + router.reqLock.Lock() + req := router.freeReq if req == nil { req = new(request) } else { - server.freeReq = req.next + router.freeReq = req.next *req = request{} } - server.reqLock.Unlock() + router.reqLock.Unlock() return req } -func (server *server) freeRequest(req *request) { - server.reqLock.Lock() - req.next = server.freeReq - server.freeReq = req - server.reqLock.Unlock() +func (router *router) freeRequest(req *request) { + router.reqLock.Lock() + req.next = router.freeReq + router.freeReq = req + router.reqLock.Unlock() } -func (server *server) getResponse() *response { - server.respLock.Lock() - resp := server.freeResp +func (router *router) getResponse() *response { + router.respLock.Lock() + resp := router.freeResp if resp == nil { resp = new(response) } else { - server.freeResp = resp.next + router.freeResp = resp.next *resp = response{} } - server.respLock.Unlock() + router.respLock.Unlock() return resp } -func (server *server) freeResponse(resp *response) { - server.respLock.Lock() - resp.next = server.freeResp - server.freeResp = resp - server.respLock.Unlock() +func (router *router) freeResponse(resp *response) { + router.respLock.Lock() + resp.next = router.freeResp + router.freeResp = resp + router.respLock.Unlock() } -func (server *server) readRequest(codec serverCodec) (service *service, mtype *methodType, req *request, argv, replyv reflect.Value, keepReading bool, err error) { - service, mtype, req, keepReading, err = server.readRequestHeader(codec) +func (router *router) readRequest(codec serverCodec) (service *service, mtype *methodType, req *request, argv, replyv reflect.Value, keepReading bool, err error) { + service, mtype, req, keepReading, err = router.readRequestHeader(codec) if err != nil { if !keepReading { return @@ -406,16 +414,16 @@ func (server *server) readRequest(codec serverCodec) (service *service, mtype *m return } -func (server *server) readRequestHeader(codec serverCodec) (service *service, mtype *methodType, req *request, keepReading bool, err error) { +func (router *router) readRequestHeader(codec serverCodec) (service *service, mtype *methodType, req *request, keepReading bool, err error) { // Grab the request header. - req = server.getRequest() + req = router.getRequest() err = codec.ReadRequestHeader(req, true) if err != nil { req = nil if err == io.EOF || err == io.ErrUnexpectedEOF { return } - err = errors.New("rpc: server cannot decode request: " + err.Error()) + err = errors.New("rpc: router cannot decode request: " + err.Error()) return } @@ -429,9 +437,9 @@ func (server *server) readRequestHeader(codec serverCodec) (service *service, mt return } // Look up the request. - server.mu.Lock() - service = server.serviceMap[serviceMethod[0]] - server.mu.Unlock() + router.mu.Lock() + service = router.serviceMap[serviceMethod[0]] + router.mu.Unlock() if service == nil { err = errors.New("rpc: can't find service " + req.ServiceMethod) return diff --git a/server/rpc_server.go b/server/rpc_server.go index 171848b0..984e2b70 100644 --- a/server/rpc_server.go +++ b/server/rpc_server.go @@ -21,8 +21,8 @@ import ( ) type rpcServer struct { - rpc *server - exit chan chan error + router *router + exit chan chan error sync.RWMutex opts Options @@ -37,12 +37,8 @@ type rpcServer struct { func newRpcServer(opts ...Option) Server { options := newOptions(opts...) return &rpcServer{ - opts: options, - rpc: &server{ - name: options.Name, - serviceMap: make(map[string]*service), - hdlrWrappers: options.HdlrWrappers, - }, + opts: options, + router: newRpcRouter(options), handlers: make(map[string]Handler), subscribers: make(map[*subscriber][]broker.Subscriber), exit: make(chan chan error), @@ -111,7 +107,7 @@ func (s *rpcServer) accept(sock transport.Socket) { } // TODO: needs better error handling - if err := s.rpc.serveRequest(ctx, codec, ct); err != nil { + if err := s.router.serveRequest(ctx, codec, ct); err != nil { s.wg.Done() log.Logf("Unexpected error serving request, closing socket: %v", err) return @@ -142,12 +138,12 @@ func (s *rpcServer) Init(opts ...Option) error { for _, opt := range opts { opt(&s.opts) } - // update internal server - s.rpc = &server{ - name: s.opts.Name, - serviceMap: s.rpc.serviceMap, - hdlrWrappers: s.opts.HdlrWrappers, - } + + // update router + r := newRpcRouter(s.opts) + r.serviceMap = s.router.serviceMap + s.router = r + s.Unlock() return nil } @@ -160,7 +156,7 @@ func (s *rpcServer) Handle(h Handler) error { s.Lock() defer s.Unlock() - if err := s.rpc.register(h.Handler()); err != nil { + if err := s.router.register(h.Handler()); err != nil { return err } diff --git a/server/server.go b/server/server.go index cdbb4fca..da839f9c 100644 --- a/server/server.go +++ b/server/server.go @@ -27,6 +27,11 @@ type Server interface { String() string } +// Router handle serving messages +type Router interface { + ServeRequest(context.Context, Stream) error +} + // Message is an async message interface type Message interface { Topic() string @@ -97,6 +102,7 @@ var ( DefaultVersion = "1.0.0" DefaultId = uuid.New().String() DefaultServer Server = newRpcServer() + DefaultRouter = newRpcRouter(newOptions()) ) // DefaultOptions returns config options for the default service From c717af21acf0328473da73c4cb771655af0af012 Mon Sep 17 00:00:00 2001 From: Asim Aslam Date: Mon, 7 Jan 2019 17:17:06 +0000 Subject: [PATCH 083/196] Some router changes --- server/rpc_router.go | 42 +++++++++++++++++++++++++----------------- server/rpc_server.go | 6 +++--- 2 files changed, 28 insertions(+), 20 deletions(-) diff --git a/server/rpc_router.go b/server/rpc_router.go index 6e67265a..94e72a33 100644 --- a/server/rpc_router.go +++ b/server/rpc_router.go @@ -166,28 +166,35 @@ func prepareMethod(method reflect.Method) *methodType { return &methodType{method: method, ArgType: argType, ReplyType: replyType, ContextType: contextType, stream: stream} } -func (router *router) register(rcvr interface{}) error { +func (router *router) NewHandler(h interface{}, opts ...HandlerOption) Handler { + return newRpcHandler(h, opts...) +} + +func (router *router) Handle(h Handler) error { router.mu.Lock() defer router.mu.Unlock() if router.serviceMap == nil { router.serviceMap = make(map[string]*service) } + + if len(h.Name()) == 0 { + return errors.New("rpc.Handle: handler has no name") + } + if !isExported(h.Name()) { + return errors.New("rpc.Handle: type " + h.Name() + " is not exported") + } + + rcvr := h.Handler() s := new(service) s.typ = reflect.TypeOf(rcvr) s.rcvr = reflect.ValueOf(rcvr) - sname := reflect.Indirect(s.rcvr).Type().Name() - if sname == "" { - log.Fatal("rpc: no service name for type", s.typ.String()) + + // check name + if _, present := router.serviceMap[h.Name()]; present { + return errors.New("rpc.Handle: service already defined: " + h.Name()) } - if !isExported(sname) { - s := "rpc Register: type " + sname + " is not exported" - log.Log(s) - return errors.New(s) - } - if _, present := router.serviceMap[sname]; present { - return errors.New("rpc: service already defined: " + sname) - } - s.name = sname + + s.name = h.Name() s.method = make(map[string]*methodType) // Install the methods @@ -198,11 +205,12 @@ func (router *router) register(rcvr interface{}) error { } } + // Check there are methods if len(s.method) == 0 { - s := "rpc Register: type " + sname + " has no exported methods of suitable type" - log.Log(s) - return errors.New(s) + return errors.New("rpc Register: type " + s.name + " has no exported methods of suitable type") } + + // save handler router.serviceMap[s.name] = s return nil } @@ -318,7 +326,7 @@ func (m *methodType) prepareContext(ctx context.Context) reflect.Value { return reflect.Zero(m.ContextType) } -func (router *router) serveRequest(ctx context.Context, codec serverCodec, ct string) error { +func (router *router) ServeRequest(ctx context.Context, codec serverCodec, ct string) error { sending := new(sync.Mutex) service, mtype, req, argv, replyv, keepReading, err := router.readRequest(codec) if err != nil { diff --git a/server/rpc_server.go b/server/rpc_server.go index 984e2b70..1272c36b 100644 --- a/server/rpc_server.go +++ b/server/rpc_server.go @@ -107,7 +107,7 @@ func (s *rpcServer) accept(sock transport.Socket) { } // TODO: needs better error handling - if err := s.router.serveRequest(ctx, codec, ct); err != nil { + if err := s.router.ServeRequest(ctx, codec, ct); err != nil { s.wg.Done() log.Logf("Unexpected error serving request, closing socket: %v", err) return @@ -149,14 +149,14 @@ func (s *rpcServer) Init(opts ...Option) error { } func (s *rpcServer) NewHandler(h interface{}, opts ...HandlerOption) Handler { - return newRpcHandler(h, opts...) + return s.router.NewHandler(h, opts...) } func (s *rpcServer) Handle(h Handler) error { s.Lock() defer s.Unlock() - if err := s.router.register(h.Handler()); err != nil { + if err := s.router.Handle(h); err != nil { return err } From e8b431c5ffeb9ee26f5eae52804b10a2fd0815f1 Mon Sep 17 00:00:00 2001 From: Asim Aslam Date: Mon, 7 Jan 2019 18:17:13 +0000 Subject: [PATCH 084/196] rename codec interface --- client/rpc_codec.go | 8 ++++---- client/rpc_stream.go | 6 +++--- 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/client/rpc_codec.go b/client/rpc_codec.go index 310548a4..7b0a8628 100644 --- a/client/rpc_codec.go +++ b/client/rpc_codec.go @@ -47,8 +47,8 @@ type readWriteCloser struct { } type clientCodec interface { - WriteRequest(*request, interface{}) error - ReadResponse(*response, interface{}) error + Write(*request, interface{}) error + Read(*response, interface{}) error Close() error } @@ -106,7 +106,7 @@ func newRpcCodec(req *transport.Message, client transport.Client, c codec.NewCod return r } -func (c *rpcCodec) WriteRequest(req *request, body interface{}) error { +func (c *rpcCodec) Write(req *request, body interface{}) error { c.buf.wbuf.Reset() m := &codec.Message{ @@ -133,7 +133,7 @@ func (c *rpcCodec) WriteRequest(req *request, body interface{}) error { return nil } -func (c *rpcCodec) ReadResponse(r *response, b interface{}) error { +func (c *rpcCodec) Read(r *response, b interface{}) error { var m transport.Message if err := c.client.Recv(&m); err != nil { return errors.InternalServerError("go.micro.client.transport", err.Error()) diff --git a/client/rpc_stream.go b/client/rpc_stream.go index eda78d47..3ad9bccf 100644 --- a/client/rpc_stream.go +++ b/client/rpc_stream.go @@ -51,7 +51,7 @@ func (r *rpcStream) Send(msg interface{}) error { ServiceMethod: r.request.Method(), } - if err := r.codec.WriteRequest(&req, msg); err != nil { + if err := r.codec.Write(&req, msg); err != nil { r.err = err return err } @@ -69,7 +69,7 @@ func (r *rpcStream) Recv(msg interface{}) error { var resp response - if err := r.codec.ReadResponse(&resp, msg); err != nil { + if err := r.codec.Read(&resp, msg); err != nil { if err == io.EOF && !r.isClosed() { r.err = io.ErrUnexpectedEOF return io.ErrUnexpectedEOF @@ -81,7 +81,7 @@ func (r *rpcStream) Recv(msg interface{}) error { switch { case len(resp.Error) > 0: // We've got an error response. Give this to the request; - // any subsequent requests will get the ReadResponseBody + // any subsequent requests will get the ReadBody // error if there is one. if resp.Error != lastStreamResponseError { r.err = serverError(resp.Error) From c9963cb8704d6c4627f2a39c000efdc0cab3183f Mon Sep 17 00:00:00 2001 From: Asim Aslam Date: Mon, 7 Jan 2019 18:20:47 +0000 Subject: [PATCH 085/196] rename --- server/rpc_codec.go | 13 ++++++++++--- server/rpc_codec_test.go | 4 ++-- server/rpc_router.go | 18 +++++------------ server/rpc_server.go | 42 ++++++++++++++++++++-------------------- server/rpc_stream.go | 8 ++++---- server/server.go | 3 ++- 6 files changed, 44 insertions(+), 44 deletions(-) diff --git a/server/rpc_codec.go b/server/rpc_codec.go index 4543b0b5..a9e5e0b7 100644 --- a/server/rpc_codec.go +++ b/server/rpc_codec.go @@ -29,6 +29,13 @@ type readWriteCloser struct { rbuf *bytes.Buffer } +type serverCodec interface { + ReadHeader(*request, bool) error + ReadBody(interface{}) error + Write(*response, interface{}, bool) error + Close() error +} + var ( DefaultContentType = "application/protobuf" @@ -72,7 +79,7 @@ func newRpcCodec(req *transport.Message, socket transport.Socket, c codec.NewCod return r } -func (c *rpcCodec) ReadRequestHeader(r *request, first bool) error { +func (c *rpcCodec) ReadHeader(r *request, first bool) error { m := codec.Message{Header: c.req.Header} if !first { @@ -106,11 +113,11 @@ func (c *rpcCodec) ReadRequestHeader(r *request, first bool) error { return err } -func (c *rpcCodec) ReadRequestBody(b interface{}) error { +func (c *rpcCodec) ReadBody(b interface{}) error { return c.codec.ReadBody(b) } -func (c *rpcCodec) WriteResponse(r *response, body interface{}, last bool) error { +func (c *rpcCodec) Write(r *response, body interface{}, last bool) error { c.buf.wbuf.Reset() m := &codec.Message{ Method: r.ServiceMethod, diff --git a/server/rpc_codec_test.go b/server/rpc_codec_test.go index d2aec28a..977c27c0 100644 --- a/server/rpc_codec_test.go +++ b/server/rpc_codec_test.go @@ -47,7 +47,7 @@ func TestCodecWriteError(t *testing.T) { socket: socket, } - err := c.WriteResponse(&response{ + err := c.Write(&response{ ServiceMethod: "Service.Method", Seq: 0, Error: "", @@ -55,7 +55,7 @@ func TestCodecWriteError(t *testing.T) { }, "body", false) if err != nil { - t.Fatalf(`Expected WriteResponse to fail; got "%+v" instead`, err) + t.Fatalf(`Expected Write to fail; got "%+v" instead`, err) } const expectedError = "Unable to encode body: simulating a codec write failure" diff --git a/server/rpc_router.go b/server/rpc_router.go index 94e72a33..ce0e8597 100644 --- a/server/rpc_router.go +++ b/server/rpc_router.go @@ -225,7 +225,7 @@ func (router *router) sendResponse(sending sync.Locker, req *request, reply inte } resp.Seq = req.Seq sending.Lock() - err = codec.WriteResponse(resp, reply, last) + err = codec.Write(resp, reply, last) sending.Unlock() router.freeResponse(resp) return err @@ -391,12 +391,12 @@ func (router *router) readRequest(codec serverCodec) (service *service, mtype *m return } // discard body - codec.ReadRequestBody(nil) + codec.ReadBody(nil) return } // is it a streaming request? then we don't read the body if mtype.stream { - codec.ReadRequestBody(nil) + codec.ReadBody(nil) return } @@ -409,7 +409,7 @@ func (router *router) readRequest(codec serverCodec) (service *service, mtype *m argIsValue = true } // argv guaranteed to be a pointer now. - if err = codec.ReadRequestBody(argv.Interface()); err != nil { + if err = codec.ReadBody(argv.Interface()); err != nil { return } if argIsValue { @@ -425,7 +425,7 @@ func (router *router) readRequest(codec serverCodec) (service *service, mtype *m func (router *router) readRequestHeader(codec serverCodec) (service *service, mtype *methodType, req *request, keepReading bool, err error) { // Grab the request header. req = router.getRequest() - err = codec.ReadRequestHeader(req, true) + err = codec.ReadHeader(req, true) if err != nil { req = nil if err == io.EOF || err == io.ErrUnexpectedEOF { @@ -458,11 +458,3 @@ func (router *router) readRequestHeader(codec serverCodec) (service *service, mt } return } - -type serverCodec interface { - ReadRequestHeader(*request, bool) error - ReadRequestBody(interface{}) error - WriteResponse(*response, interface{}, bool) error - - Close() error -} diff --git a/server/rpc_server.go b/server/rpc_server.go index 021b0503..adbb0b0e 100644 --- a/server/rpc_server.go +++ b/server/rpc_server.go @@ -70,6 +70,26 @@ func (s *rpcServer) accept(sock transport.Socket) { // we use this Content-Type header to identify the codec needed ct := msg.Header["Content-Type"] + // strip our headers + hdr := make(map[string]string) + for k, v := range msg.Header { + hdr[k] = v + } + + // set local/remote ips + hdr["Local"] = sock.Local() + hdr["Remote"] = sock.Remote() + + // create new context + ctx := metadata.NewContext(context.Background(), hdr) + + // set the timeout if we have it + if len(to) > 0 { + if n, err := strconv.ParseUint(to, 10, 64); err == nil { + ctx, _ = context.WithTimeout(ctx, time.Duration(n)) + } + } + // no content type if len(ct) == 0 { ct = DefaultContentType @@ -88,29 +108,9 @@ func (s *rpcServer) accept(sock transport.Socket) { return } + // create the internal server codec codec := newRpcCodec(&msg, sock, cf) - // strip our headers - hdr := make(map[string]string) - for k, v := range msg.Header { - hdr[k] = v - } - delete(hdr, "Content-Type") - delete(hdr, "Timeout") - - // set local/remote ips - hdr["Local"] = sock.Local() - hdr["Remote"] = sock.Remote() - - ctx := metadata.NewContext(context.Background(), hdr) - - // set the timeout if we have it - if len(to) > 0 { - if n, err := strconv.ParseUint(to, 10, 64); err == nil { - ctx, _ = context.WithTimeout(ctx, time.Duration(n)) - } - } - // TODO: needs better error handling if err := s.router.ServeRequest(ctx, codec, ct); err != nil { s.wg.Done() diff --git a/server/rpc_stream.go b/server/rpc_stream.go index 97afe0e4..645f288a 100644 --- a/server/rpc_stream.go +++ b/server/rpc_stream.go @@ -33,7 +33,7 @@ func (r *rpcStream) Send(msg interface{}) error { Seq: r.seq, } - return r.codec.WriteResponse(&resp, msg, false) + return r.codec.Write(&resp, msg, false) } func (r *rpcStream) Recv(msg interface{}) error { @@ -42,15 +42,15 @@ func (r *rpcStream) Recv(msg interface{}) error { req := request{} - if err := r.codec.ReadRequestHeader(&req, false); err != nil { + if err := r.codec.ReadHeader(&req, false); err != nil { // discard body - r.codec.ReadRequestBody(nil) + r.codec.ReadBody(nil) return err } // we need to stay up to date with sequence numbers r.seq = req.Seq - return r.codec.ReadRequestBody(msg) + return r.codec.ReadBody(msg) } func (r *rpcStream) Error() error { diff --git a/server/server.go b/server/server.go index da839f9c..3e72b6a4 100644 --- a/server/server.go +++ b/server/server.go @@ -9,6 +9,7 @@ import ( "github.com/google/uuid" "github.com/micro/go-log" + "github.com/micro/go-micro/codec" "github.com/micro/go-micro/registry" ) @@ -29,7 +30,7 @@ type Server interface { // Router handle serving messages type Router interface { - ServeRequest(context.Context, Stream) error + ServeCodec(context.Context, codec.Codec) error } // Message is an async message interface From 216dbb771ace2fdfb753338ce01507e60720df4d Mon Sep 17 00:00:00 2001 From: Asim Aslam Date: Mon, 7 Jan 2019 18:25:31 +0000 Subject: [PATCH 086/196] rename requestHeader --- server/rpc_router.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/server/rpc_router.go b/server/rpc_router.go index ce0e8597..a3ab1fe6 100644 --- a/server/rpc_router.go +++ b/server/rpc_router.go @@ -385,7 +385,7 @@ func (router *router) freeResponse(resp *response) { } func (router *router) readRequest(codec serverCodec) (service *service, mtype *methodType, req *request, argv, replyv reflect.Value, keepReading bool, err error) { - service, mtype, req, keepReading, err = router.readRequestHeader(codec) + service, mtype, req, keepReading, err = router.readHeader(codec) if err != nil { if !keepReading { return @@ -422,7 +422,7 @@ func (router *router) readRequest(codec serverCodec) (service *service, mtype *m return } -func (router *router) readRequestHeader(codec serverCodec) (service *service, mtype *methodType, req *request, keepReading bool, err error) { +func (router *router) readHeader(codec serverCodec) (service *service, mtype *methodType, req *request, keepReading bool, err error) { // Grab the request header. req = router.getRequest() err = codec.ReadHeader(req, true) From 4cb41721f15a1e8fe4eda35aaabc21b76bc48e7d Mon Sep 17 00:00:00 2001 From: Asim Aslam Date: Tue, 8 Jan 2019 15:38:25 +0000 Subject: [PATCH 087/196] further codec changes --- client/rpc_client.go | 2 +- client/rpc_codec.go | 12 +++---- client/rpc_stream.go | 2 +- cmd/cmd.go | 2 +- codec/codec.go | 2 +- codec/jsonrpc/client.go | 10 +++--- codec/jsonrpc/server.go | 46 +++++++------------------- codec/proto/proto.go | 9 +++++- codec/protorpc/protorpc.go | 18 ++++++++--- server/rpc_codec.go | 58 +++++++++++++++++++++------------ server/rpc_codec_test.go | 11 +++---- server/rpc_router.go | 66 +++++++++++++++++++++----------------- server/rpc_stream.go | 22 +++++++------ 13 files changed, 139 insertions(+), 121 deletions(-) diff --git a/client/rpc_client.go b/client/rpc_client.go index f229b495..04be269e 100644 --- a/client/rpc_client.go +++ b/client/rpc_client.go @@ -97,7 +97,7 @@ func (r *rpcClient) call(ctx context.Context, address string, req Request, resp request: req, closed: make(chan bool), codec: newRpcCodec(msg, c, cf), - seq: seq, + seq: fmt.Sprintf("%v", seq), } defer stream.Close() diff --git a/client/rpc_codec.go b/client/rpc_codec.go index 7b0a8628..d4ca0702 100644 --- a/client/rpc_codec.go +++ b/client/rpc_codec.go @@ -4,7 +4,6 @@ import ( "bytes" errs "errors" "fmt" - "strconv" "github.com/micro/go-micro/codec" raw "github.com/micro/go-micro/codec/bytes" @@ -55,13 +54,13 @@ type clientCodec interface { type request struct { Service string ServiceMethod string // format: "Service.Method" - Seq uint64 // sequence number chosen by client + Seq string // sequence number chosen by client next *request // for free list in Server } type response struct { ServiceMethod string // echoes that of the Request - Seq uint64 // echoes that of the request + Seq string // echoes that of the request Error string // error, if any. next *response // for free list in Server } @@ -115,7 +114,7 @@ func (c *rpcCodec) Write(req *request, body interface{}) error { Method: req.ServiceMethod, Type: codec.Request, Header: map[string]string{ - "X-Micro-Id": fmt.Sprintf("%d", req.Seq), + "X-Micro-Id": fmt.Sprintf("%v", req.Seq), "X-Micro-Service": req.Service, "X-Micro-Method": req.ServiceMethod, }, @@ -161,9 +160,8 @@ func (c *rpcCodec) Read(r *response, b interface{}) error { r.ServiceMethod = me.Header["X-Micro-Method"] } - if me.Id == 0 && len(me.Header["X-Micro-Id"]) > 0 { - id, _ := strconv.ParseInt(me.Header["X-Micro-Id"], 10, 64) - r.Seq = uint64(id) + if len(me.Id) == 0 { + r.Seq = me.Header["X-Micro-Id"] } if err != nil { diff --git a/client/rpc_stream.go b/client/rpc_stream.go index 3ad9bccf..275d9133 100644 --- a/client/rpc_stream.go +++ b/client/rpc_stream.go @@ -9,7 +9,7 @@ import ( // Implements the streamer interface type rpcStream struct { sync.RWMutex - seq uint64 + seq string closed chan bool err error request Request diff --git a/cmd/cmd.go b/cmd/cmd.go index 12cbb874..7f08ffd7 100644 --- a/cmd/cmd.go +++ b/cmd/cmd.go @@ -181,7 +181,7 @@ var ( "default": selector.NewSelector, "dns": dns.NewSelector, "cache": selector.NewSelector, - "static": static.NewSelector, + "static": static.NewSelector, } DefaultServers = map[string]func(...server.Option) server.Server{ diff --git a/codec/codec.go b/codec/codec.go index edc659ff..7909d3f8 100644 --- a/codec/codec.go +++ b/codec/codec.go @@ -34,7 +34,7 @@ type Codec interface { // the communication, likely followed by the body. // In the case of an error, body may be nil. type Message struct { - Id uint64 + Id string Type MessageType Target string Method string diff --git a/codec/jsonrpc/client.go b/codec/jsonrpc/client.go index ebf8be91..f5ec5636 100644 --- a/codec/jsonrpc/client.go +++ b/codec/jsonrpc/client.go @@ -19,17 +19,17 @@ type clientCodec struct { resp clientResponse sync.Mutex - pending map[uint64]string + pending map[interface{}]string } type clientRequest struct { Method string `json:"method"` Params [1]interface{} `json:"params"` - ID uint64 `json:"id"` + ID interface{} `json:"id"` } type clientResponse struct { - ID uint64 `json:"id"` + ID interface{} `json:"id"` Result *json.RawMessage `json:"result"` Error interface{} `json:"error"` } @@ -39,7 +39,7 @@ func newClientCodec(conn io.ReadWriteCloser) *clientCodec { dec: json.NewDecoder(conn), enc: json.NewEncoder(conn), c: conn, - pending: make(map[uint64]string), + pending: make(map[interface{}]string), } } @@ -71,7 +71,7 @@ func (c *clientCodec) ReadHeader(m *codec.Message) error { c.Unlock() m.Error = "" - m.Id = c.resp.ID + m.Id = fmt.Sprintf("%v", c.resp.ID) if c.resp.Error != nil { x, ok := c.resp.Error.(string) if !ok { diff --git a/codec/jsonrpc/server.go b/codec/jsonrpc/server.go index bf78ca43..53f681ef 100644 --- a/codec/jsonrpc/server.go +++ b/codec/jsonrpc/server.go @@ -2,9 +2,8 @@ package jsonrpc import ( "encoding/json" - "errors" + "fmt" "io" - "sync" "github.com/micro/go-micro/codec" ) @@ -17,30 +16,25 @@ type serverCodec struct { // temporary work space req serverRequest resp serverResponse - - sync.Mutex - seq uint64 - pending map[uint64]*json.RawMessage } type serverRequest struct { Method string `json:"method"` Params *json.RawMessage `json:"params"` - ID *json.RawMessage `json:"id"` + ID interface{} `json:"id"` } type serverResponse struct { - ID *json.RawMessage `json:"id"` - Result interface{} `json:"result"` - Error interface{} `json:"error"` + ID interface{} `json:"id"` + Result interface{} `json:"result"` + Error interface{} `json:"error"` } func newServerCodec(conn io.ReadWriteCloser) *serverCodec { return &serverCodec{ - dec: json.NewDecoder(conn), - enc: json.NewEncoder(conn), - c: conn, - pending: make(map[uint64]*json.RawMessage), + dec: json.NewDecoder(conn), + enc: json.NewEncoder(conn), + c: conn, } } @@ -50,7 +44,7 @@ func (r *serverRequest) reset() { *r.Params = (*r.Params)[0:0] } if r.ID != nil { - *r.ID = (*r.ID)[0:0] + r.ID = nil } } @@ -60,14 +54,8 @@ func (c *serverCodec) ReadHeader(m *codec.Message) error { return err } m.Method = c.req.Method - - c.Lock() - c.seq++ - c.pending[c.seq] = c.req.ID + m.Id = fmt.Sprintf("%v", c.req.ID) c.req.ID = nil - m.Id = c.seq - c.Unlock() - return nil } @@ -84,19 +72,7 @@ var null = json.RawMessage([]byte("null")) func (c *serverCodec) Write(m *codec.Message, x interface{}) error { var resp serverResponse - c.Lock() - b, ok := c.pending[m.Id] - if !ok { - c.Unlock() - return errors.New("invalid sequence number in response") - } - c.Unlock() - - if b == nil { - // Invalid request so no id. Use JSON null. - b = &null - } - resp.ID = b + resp.ID = m.Id resp.Result = x if m.Error == "" { resp.Error = nil diff --git a/codec/proto/proto.go b/codec/proto/proto.go index 339c08c1..b70b4c84 100644 --- a/codec/proto/proto.go +++ b/codec/proto/proto.go @@ -22,11 +22,18 @@ func (c *Codec) ReadBody(b interface{}) error { if err != nil { return err } + if b == nil { + return nil + } return proto.Unmarshal(buf, b.(proto.Message)) } func (c *Codec) Write(m *codec.Message, b interface{}) error { - buf, err := proto.Marshal(b.(proto.Message)) + p, ok := b.(proto.Message) + if !ok { + return nil + } + buf, err := proto.Marshal(p) if err != nil { return err } diff --git a/codec/protorpc/protorpc.go b/codec/protorpc/protorpc.go index 111026c2..de05552f 100644 --- a/codec/protorpc/protorpc.go +++ b/codec/protorpc/protorpc.go @@ -5,6 +5,7 @@ import ( "bytes" "fmt" "io" + "strconv" "sync" "github.com/golang/protobuf/proto" @@ -31,13 +32,22 @@ func (c *protoCodec) String() string { return "proto-rpc" } +func id(id string) *uint64 { + p, err := strconv.ParseInt(id, 10, 64) + if err != nil { + p = 0 + } + i := uint64(p) + return &i +} + func (c *protoCodec) Write(m *codec.Message, b interface{}) error { switch m.Type { case codec.Request: c.Lock() defer c.Unlock() // This is protobuf, of course we copy it. - pbr := &Request{ServiceMethod: &m.Method, Seq: &m.Id} + pbr := &Request{ServiceMethod: &m.Method, Seq: id(m.Id)} data, err := proto.Marshal(pbr) if err != nil { return err @@ -63,7 +73,7 @@ func (c *protoCodec) Write(m *codec.Message, b interface{}) error { case codec.Response: c.Lock() defer c.Unlock() - rtmp := &Response{ServiceMethod: &m.Method, Seq: &m.Id, Error: &m.Error} + rtmp := &Response{ServiceMethod: &m.Method, Seq: id(m.Id), Error: &m.Error} data, err := proto.Marshal(rtmp) if err != nil { return err @@ -117,7 +127,7 @@ func (c *protoCodec) ReadHeader(m *codec.Message, mt codec.MessageType) error { return err } m.Method = rtmp.GetServiceMethod() - m.Id = rtmp.GetSeq() + m.Id = fmt.Sprintf("%d", rtmp.GetSeq()) case codec.Response: data, err := ReadNetString(c.rwc) if err != nil { @@ -129,7 +139,7 @@ func (c *protoCodec) ReadHeader(m *codec.Message, mt codec.MessageType) error { return err } m.Method = rtmp.GetServiceMethod() - m.Id = rtmp.GetSeq() + m.Id = fmt.Sprintf("%d", rtmp.GetSeq()) m.Error = rtmp.GetError() case codec.Publication: _, err := io.Copy(c.buf, c.rwc) diff --git a/server/rpc_codec.go b/server/rpc_codec.go index a9e5e0b7..a4392445 100644 --- a/server/rpc_codec.go +++ b/server/rpc_codec.go @@ -2,8 +2,6 @@ package server import ( "bytes" - "fmt" - "strconv" "github.com/micro/go-micro/codec" raw "github.com/micro/go-micro/codec/bytes" @@ -19,6 +17,7 @@ import ( type rpcCodec struct { socket transport.Socket codec codec.Codec + first bool req *transport.Message buf *readWriteCloser @@ -65,12 +64,13 @@ func (rwc *readWriteCloser) Close() error { return nil } -func newRpcCodec(req *transport.Message, socket transport.Socket, c codec.NewCodec) serverCodec { +func newRpcCodec(req *transport.Message, socket transport.Socket, c codec.NewCodec) codec.Codec { rwc := &readWriteCloser{ rbuf: bytes.NewBuffer(req.Body), wbuf: bytes.NewBuffer(nil), } r := &rpcCodec{ + first: true, buf: rwc, codec: c(rwc), req: req, @@ -79,36 +79,43 @@ func newRpcCodec(req *transport.Message, socket transport.Socket, c codec.NewCod return r } -func (c *rpcCodec) ReadHeader(r *request, first bool) error { +func (c *rpcCodec) ReadHeader(r *codec.Message, t codec.MessageType) error { m := codec.Message{Header: c.req.Header} - if !first { + // if its a follow on request read it + if !c.first { var tm transport.Message + + // read off the socket if err := c.socket.Recv(&tm); err != nil { return err } + // reset the read buffer c.buf.rbuf.Reset() + + // write the body to the buffer if _, err := c.buf.rbuf.Write(tm.Body); err != nil { return err } + // set the message header m.Header = tm.Header } + // no longer first read + c.first = false + // set some internal things m.Target = m.Header["X-Micro-Service"] m.Method = m.Header["X-Micro-Method"] - - // set id - if len(m.Header["X-Micro-Id"]) > 0 { - id, _ := strconv.ParseInt(m.Header["X-Micro-Id"], 10, 64) - m.Id = uint64(id) - } + m.Id = m.Header["X-Micro-Id"] // read header via codec err := c.codec.ReadHeader(&m, codec.Request) - r.ServiceMethod = m.Method - r.Seq = m.Id + + // set the method/id + r.Method = m.Method + r.Id = m.Id return err } @@ -117,21 +124,28 @@ func (c *rpcCodec) ReadBody(b interface{}) error { return c.codec.ReadBody(b) } -func (c *rpcCodec) Write(r *response, body interface{}, last bool) error { +func (c *rpcCodec) Write(r *codec.Message, body interface{}) error { c.buf.wbuf.Reset() + + // create a new message m := &codec.Message{ - Method: r.ServiceMethod, - Id: r.Seq, + Method: r.Method, + Id: r.Id, Error: r.Error, - Type: codec.Response, + Type: r.Type, Header: map[string]string{ - "X-Micro-Id": fmt.Sprintf("%d", r.Seq), - "X-Micro-Method": r.ServiceMethod, + "X-Micro-Id": r.Id, + "X-Micro-Method": r.Method, "X-Micro-Error": r.Error, + "Content-Type": c.req.Header["Content-Type"], }, } + + // write to the body if err := c.codec.Write(m, body); err != nil { c.buf.wbuf.Reset() + + // write an error if it failed m.Error = errors.Wrapf(err, "Unable to encode body").Error() m.Header["X-Micro-Error"] = m.Error if err := c.codec.Write(m, nil); err != nil { @@ -139,7 +153,7 @@ func (c *rpcCodec) Write(r *response, body interface{}, last bool) error { } } - m.Header["Content-Type"] = c.req.Header["Content-Type"] + // send on the socket return c.socket.Send(&transport.Message{ Header: m.Header, Body: c.buf.wbuf.Bytes(), @@ -151,3 +165,7 @@ func (c *rpcCodec) Close() error { c.codec.Close() return c.socket.Close() } + +func (c *rpcCodec) String() string { + return "rpc" +} diff --git a/server/rpc_codec_test.go b/server/rpc_codec_test.go index 977c27c0..59035e3e 100644 --- a/server/rpc_codec_test.go +++ b/server/rpc_codec_test.go @@ -47,12 +47,11 @@ func TestCodecWriteError(t *testing.T) { socket: socket, } - err := c.Write(&response{ - ServiceMethod: "Service.Method", - Seq: 0, - Error: "", - next: nil, - }, "body", false) + err := c.Write(&codec.Message{ + Method: "Service.Method", + Id: "0", + Error: "", + }, "body") if err != nil { t.Fatalf(`Expected Write to fail; got "%+v" instead`, err) diff --git a/server/rpc_router.go b/server/rpc_router.go index a3ab1fe6..fa38fb79 100644 --- a/server/rpc_router.go +++ b/server/rpc_router.go @@ -17,6 +17,7 @@ import ( "unicode/utf8" "github.com/micro/go-log" + "github.com/micro/go-micro/codec" ) var ( @@ -48,16 +49,13 @@ type service struct { } type request struct { - ServiceMethod string // format: "Service.Method" - Seq uint64 // sequence number chosen by client - next *request // for free list in Server + msg *codec.Message + next *request // for free list in Server } type response struct { - ServiceMethod string // echoes that of the Request - Seq uint64 // echoes that of the request - Error string // error, if any. - next *response // for free list in Server + msg *codec.Message + next *response // for free list in Server } // router represents an RPC router. @@ -215,30 +213,34 @@ func (router *router) Handle(h Handler) error { return nil } -func (router *router) sendResponse(sending sync.Locker, req *request, reply interface{}, codec serverCodec, errmsg string, last bool) (err error) { +func (router *router) sendResponse(sending sync.Locker, req *request, reply interface{}, cc codec.Codec, errmsg string, last bool) (err error) { + msg := new(codec.Message) + msg.Type = codec.Response resp := router.getResponse() + resp.msg = msg + // Encode the response header - resp.ServiceMethod = req.ServiceMethod + resp.msg.Method = req.msg.Method if errmsg != "" { - resp.Error = errmsg + resp.msg.Error = errmsg reply = invalidRequest } - resp.Seq = req.Seq + resp.msg.Id = req.msg.Id sending.Lock() - err = codec.Write(resp, reply, last) + err = cc.Write(resp.msg, reply) sending.Unlock() router.freeResponse(resp) return err } -func (s *service) call(ctx context.Context, router *router, sending *sync.Mutex, mtype *methodType, req *request, argv, replyv reflect.Value, codec serverCodec, ct string) { +func (s *service) call(ctx context.Context, router *router, sending *sync.Mutex, mtype *methodType, req *request, argv, replyv reflect.Value, codec codec.Codec, ct string) { function := mtype.method.Func var returnValues []reflect.Value r := &rpcRequest{ service: router.name, contentType: ct, - method: req.ServiceMethod, + method: req.msg.Method, } if !mtype.stream { @@ -282,7 +284,7 @@ func (s *service) call(ctx context.Context, router *router, sending *sync.Mutex, context: ctx, codec: codec, request: r, - seq: req.Seq, + id: req.msg.Id, } // Invoke the method, providing a new value for the reply. @@ -326,21 +328,21 @@ func (m *methodType) prepareContext(ctx context.Context) reflect.Value { return reflect.Zero(m.ContextType) } -func (router *router) ServeRequest(ctx context.Context, codec serverCodec, ct string) error { +func (router *router) ServeRequest(ctx context.Context, cc codec.Codec, ct string) error { sending := new(sync.Mutex) - service, mtype, req, argv, replyv, keepReading, err := router.readRequest(codec) + service, mtype, req, argv, replyv, keepReading, err := router.readRequest(cc) if err != nil { if !keepReading { return err } // send a response if we actually managed to read a header. if req != nil { - router.sendResponse(sending, req, invalidRequest, codec, err.Error(), true) + router.sendResponse(sending, req, invalidRequest, cc, err.Error(), true) router.freeRequest(req) } return err } - service.call(ctx, router, sending, mtype, req, argv, replyv, codec, ct) + service.call(ctx, router, sending, mtype, req, argv, replyv, cc, ct) return nil } @@ -384,19 +386,19 @@ func (router *router) freeResponse(resp *response) { router.respLock.Unlock() } -func (router *router) readRequest(codec serverCodec) (service *service, mtype *methodType, req *request, argv, replyv reflect.Value, keepReading bool, err error) { - service, mtype, req, keepReading, err = router.readHeader(codec) +func (router *router) readRequest(cc codec.Codec) (service *service, mtype *methodType, req *request, argv, replyv reflect.Value, keepReading bool, err error) { + service, mtype, req, keepReading, err = router.readHeader(cc) if err != nil { if !keepReading { return } // discard body - codec.ReadBody(nil) + cc.ReadBody(nil) return } // is it a streaming request? then we don't read the body if mtype.stream { - codec.ReadBody(nil) + cc.ReadBody(nil) return } @@ -409,7 +411,7 @@ func (router *router) readRequest(codec serverCodec) (service *service, mtype *m argIsValue = true } // argv guaranteed to be a pointer now. - if err = codec.ReadBody(argv.Interface()); err != nil { + if err = cc.ReadBody(argv.Interface()); err != nil { return } if argIsValue { @@ -422,10 +424,14 @@ func (router *router) readRequest(codec serverCodec) (service *service, mtype *m return } -func (router *router) readHeader(codec serverCodec) (service *service, mtype *methodType, req *request, keepReading bool, err error) { +func (router *router) readHeader(cc codec.Codec) (service *service, mtype *methodType, req *request, keepReading bool, err error) { // Grab the request header. + msg := new(codec.Message) + msg.Type = codec.Request req = router.getRequest() - err = codec.ReadHeader(req, true) + req.msg = msg + + err = cc.ReadHeader(msg, msg.Type) if err != nil { req = nil if err == io.EOF || err == io.ErrUnexpectedEOF { @@ -439,9 +445,9 @@ func (router *router) readHeader(codec serverCodec) (service *service, mtype *me // we can still recover and move on to the next request. keepReading = true - serviceMethod := strings.Split(req.ServiceMethod, ".") + serviceMethod := strings.Split(req.msg.Method, ".") if len(serviceMethod) != 2 { - err = errors.New("rpc: service/method request ill-formed: " + req.ServiceMethod) + err = errors.New("rpc: service/method request ill-formed: " + req.msg.Method) return } // Look up the request. @@ -449,12 +455,12 @@ func (router *router) readHeader(codec serverCodec) (service *service, mtype *me service = router.serviceMap[serviceMethod[0]] router.mu.Unlock() if service == nil { - err = errors.New("rpc: can't find service " + req.ServiceMethod) + err = errors.New("rpc: can't find service " + req.msg.Method) return } mtype = service.method[serviceMethod[1]] if mtype == nil { - err = errors.New("rpc: can't find method " + req.ServiceMethod) + err = errors.New("rpc: can't find method " + req.msg.Method) } return } diff --git a/server/rpc_stream.go b/server/rpc_stream.go index 645f288a..efbf0d55 100644 --- a/server/rpc_stream.go +++ b/server/rpc_stream.go @@ -3,16 +3,18 @@ package server import ( "context" "sync" + + "github.com/micro/go-micro/codec" ) // Implements the Streamer interface type rpcStream struct { sync.RWMutex - seq uint64 + id string closed bool err error request Request - codec serverCodec + codec codec.Codec context context.Context } @@ -28,28 +30,30 @@ func (r *rpcStream) Send(msg interface{}) error { r.Lock() defer r.Unlock() - resp := response{ - ServiceMethod: r.request.Method(), - Seq: r.seq, + resp := codec.Message{ + Method: r.request.Method(), + Id: r.id, + Type: codec.Response, } - return r.codec.Write(&resp, msg, false) + return r.codec.Write(&resp, msg) } func (r *rpcStream) Recv(msg interface{}) error { r.Lock() defer r.Unlock() - req := request{} + req := new(codec.Message) + req.Type = codec.Request - if err := r.codec.ReadHeader(&req, false); err != nil { + if err := r.codec.ReadHeader(req, req.Type); err != nil { // discard body r.codec.ReadBody(nil) return err } // we need to stay up to date with sequence numbers - r.seq = req.Seq + r.id = req.Id return r.codec.ReadBody(msg) } From f46828be33834dd683f995e7a0b3fed2f1facf44 Mon Sep 17 00:00:00 2001 From: Asim Aslam Date: Tue, 8 Jan 2019 20:32:47 +0000 Subject: [PATCH 088/196] Add Router interface --- server/options.go | 11 +++++++++++ server/rpc_router.go | 8 ++++---- server/rpc_server.go | 16 +++++++++++++--- server/server.go | 2 +- 4 files changed, 29 insertions(+), 8 deletions(-) diff --git a/server/options.go b/server/options.go index 5b9aa98e..f1355122 100644 --- a/server/options.go +++ b/server/options.go @@ -25,8 +25,12 @@ type Options struct { HdlrWrappers []HandlerWrapper SubWrappers []SubscriberWrapper + // The register expiry time RegisterTTL time.Duration + // The router for requests + Router Router + // Debug Handler which can be set by a user DebugHandler debug.DebugHandler @@ -164,6 +168,13 @@ func RegisterTTL(t time.Duration) Option { } } +// WithRouter sets the request router +func WithRouter(r Router) Option { + return func(o *Options) { + o.Router = r + } +} + // Wait tells the server to wait for requests to finish before exiting func Wait(b bool) Option { return func(o *Options) { diff --git a/server/rpc_router.go b/server/rpc_router.go index fa38fb79..cd25994f 100644 --- a/server/rpc_router.go +++ b/server/rpc_router.go @@ -233,13 +233,13 @@ func (router *router) sendResponse(sending sync.Locker, req *request, reply inte return err } -func (s *service) call(ctx context.Context, router *router, sending *sync.Mutex, mtype *methodType, req *request, argv, replyv reflect.Value, codec codec.Codec, ct string) { +func (s *service) call(ctx context.Context, router *router, sending *sync.Mutex, mtype *methodType, req *request, argv, replyv reflect.Value, codec codec.Codec) { function := mtype.method.Func var returnValues []reflect.Value r := &rpcRequest{ service: router.name, - contentType: ct, + contentType: req.msg.Header["Content-Type"], method: req.msg.Method, } @@ -328,7 +328,7 @@ func (m *methodType) prepareContext(ctx context.Context) reflect.Value { return reflect.Zero(m.ContextType) } -func (router *router) ServeRequest(ctx context.Context, cc codec.Codec, ct string) error { +func (router *router) ServeRequest(ctx context.Context, cc codec.Codec) error { sending := new(sync.Mutex) service, mtype, req, argv, replyv, keepReading, err := router.readRequest(cc) if err != nil { @@ -342,7 +342,7 @@ func (router *router) ServeRequest(ctx context.Context, cc codec.Codec, ct strin } return err } - service.call(ctx, router, sending, mtype, req, argv, replyv, cc, ct) + service.call(ctx, router, sending, mtype, req, argv, replyv, cc) return nil } diff --git a/server/rpc_server.go b/server/rpc_server.go index adbb0b0e..6d73f63b 100644 --- a/server/rpc_server.go +++ b/server/rpc_server.go @@ -45,7 +45,8 @@ func newRpcServer(opts ...Option) Server { } } -func (s *rpcServer) accept(sock transport.Socket) { +// ServeConn serves a single connection +func (s *rpcServer) ServeConn(sock transport.Socket) { defer func() { // close socket sock.Close() @@ -92,6 +93,7 @@ func (s *rpcServer) accept(sock transport.Socket) { // no content type if len(ct) == 0 { + msg.Header["Content-Type"] = DefaultContentType ct = DefaultContentType } @@ -111,8 +113,16 @@ func (s *rpcServer) accept(sock transport.Socket) { // create the internal server codec codec := newRpcCodec(&msg, sock, cf) + // set router + var r Router + r = s.router + + if s.opts.Router != nil { + r = s.opts.Router + } + // TODO: needs better error handling - if err := s.router.ServeRequest(ctx, codec, ct); err != nil { + if err := r.ServeRequest(ctx, codec); err != nil { s.wg.Done() log.Logf("Unexpected error serving request, closing socket: %v", err) return @@ -402,7 +412,7 @@ func (s *rpcServer) Start() error { go func() { for { - err := ts.Accept(s.accept) + err := ts.Accept(s.ServeConn) // check if we're supposed to exit select { diff --git a/server/server.go b/server/server.go index 3e72b6a4..5e454824 100644 --- a/server/server.go +++ b/server/server.go @@ -30,7 +30,7 @@ type Server interface { // Router handle serving messages type Router interface { - ServeCodec(context.Context, codec.Codec) error + ServeRequest(context.Context, codec.Codec) error } // Message is an async message interface From 453ce2fcbe049c106ca3fc49c54ee3202f163e83 Mon Sep 17 00:00:00 2001 From: "xinfei.wu" Date: Wed, 9 Jan 2019 14:24:12 +0800 Subject: [PATCH 089/196] add locker --- registry/mock/mock.go | 19 ++++++++++++++++++- 1 file changed, 18 insertions(+), 1 deletion(-) diff --git a/registry/mock/mock.go b/registry/mock/mock.go index da690893..11a145af 100644 --- a/registry/mock/mock.go +++ b/registry/mock/mock.go @@ -1,11 +1,13 @@ -// Package mock provides a mock registry for testing package mock import ( + "sync" + "github.com/micro/go-micro/registry" ) type mockRegistry struct { + sync.RWMutex Services map[string][]*registry.Service } @@ -55,11 +57,17 @@ var ( ) func (m *mockRegistry) init() { + m.Lock() + defer m.Unlock() + // add some mock data m.Services = mockData } func (m *mockRegistry) GetService(service string) ([]*registry.Service, error) { + m.Lock() + defer m.Unlock() + s, ok := m.Services[service] if !ok || len(s) == 0 { return nil, registry.ErrNotFound @@ -69,6 +77,9 @@ func (m *mockRegistry) GetService(service string) ([]*registry.Service, error) { } func (m *mockRegistry) ListServices() ([]*registry.Service, error) { + m.Lock() + defer m.Unlock() + var services []*registry.Service for _, service := range m.Services { services = append(services, service...) @@ -77,12 +88,18 @@ func (m *mockRegistry) ListServices() ([]*registry.Service, error) { } func (m *mockRegistry) Register(s *registry.Service, opts ...registry.RegisterOption) error { + m.Lock() + defer m.Unlock() + services := addServices(m.Services[s.Name], []*registry.Service{s}) m.Services[s.Name] = services return nil } func (m *mockRegistry) Deregister(s *registry.Service) error { + m.Lock() + defer m.Unlock() + services := delServices(m.Services[s.Name], []*registry.Service{s}) m.Services[s.Name] = services return nil From eec1726f1d2475bc34c5f5162b825b7ccb563be7 Mon Sep 17 00:00:00 2001 From: "xinfei.wu" Date: Wed, 9 Jan 2019 16:31:23 +0800 Subject: [PATCH 090/196] add package comment --- registry/mock/mock.go | 1 + 1 file changed, 1 insertion(+) diff --git a/registry/mock/mock.go b/registry/mock/mock.go index 11a145af..6b193ad6 100644 --- a/registry/mock/mock.go +++ b/registry/mock/mock.go @@ -1,3 +1,4 @@ +// Package mock provides a mock registry for testing package mock import ( From 7a1f7358258f548624b40b2ac11add368d6de534 Mon Sep 17 00:00:00 2001 From: Asim Aslam Date: Wed, 9 Jan 2019 09:02:30 +0000 Subject: [PATCH 091/196] remove server codec --- server/rpc_codec.go | 7 ------- 1 file changed, 7 deletions(-) diff --git a/server/rpc_codec.go b/server/rpc_codec.go index a4392445..8cf209dd 100644 --- a/server/rpc_codec.go +++ b/server/rpc_codec.go @@ -28,13 +28,6 @@ type readWriteCloser struct { rbuf *bytes.Buffer } -type serverCodec interface { - ReadHeader(*request, bool) error - ReadBody(interface{}) error - Write(*response, interface{}, bool) error - Close() error -} - var ( DefaultContentType = "application/protobuf" From ee380c6b7a7db7aefbc9d370e4a5ec789eb44dcf Mon Sep 17 00:00:00 2001 From: Asim Aslam Date: Wed, 9 Jan 2019 09:06:30 +0000 Subject: [PATCH 092/196] reorder --- server/rpc_router.go | 134 +++++++++++++++++++++---------------------- 1 file changed, 67 insertions(+), 67 deletions(-) diff --git a/server/rpc_router.go b/server/rpc_router.go index cd25994f..291e3bac 100644 --- a/server/rpc_router.go +++ b/server/rpc_router.go @@ -164,55 +164,6 @@ func prepareMethod(method reflect.Method) *methodType { return &methodType{method: method, ArgType: argType, ReplyType: replyType, ContextType: contextType, stream: stream} } -func (router *router) NewHandler(h interface{}, opts ...HandlerOption) Handler { - return newRpcHandler(h, opts...) -} - -func (router *router) Handle(h Handler) error { - router.mu.Lock() - defer router.mu.Unlock() - if router.serviceMap == nil { - router.serviceMap = make(map[string]*service) - } - - if len(h.Name()) == 0 { - return errors.New("rpc.Handle: handler has no name") - } - if !isExported(h.Name()) { - return errors.New("rpc.Handle: type " + h.Name() + " is not exported") - } - - rcvr := h.Handler() - s := new(service) - s.typ = reflect.TypeOf(rcvr) - s.rcvr = reflect.ValueOf(rcvr) - - // check name - if _, present := router.serviceMap[h.Name()]; present { - return errors.New("rpc.Handle: service already defined: " + h.Name()) - } - - s.name = h.Name() - s.method = make(map[string]*methodType) - - // Install the methods - for m := 0; m < s.typ.NumMethod(); m++ { - method := s.typ.Method(m) - if mt := prepareMethod(method); mt != nil { - s.method[method.Name] = mt - } - } - - // Check there are methods - if len(s.method) == 0 { - return errors.New("rpc Register: type " + s.name + " has no exported methods of suitable type") - } - - // save handler - router.serviceMap[s.name] = s - return nil -} - func (router *router) sendResponse(sending sync.Locker, req *request, reply interface{}, cc codec.Codec, errmsg string, last bool) (err error) { msg := new(codec.Message) msg.Type = codec.Response @@ -328,24 +279,6 @@ func (m *methodType) prepareContext(ctx context.Context) reflect.Value { return reflect.Zero(m.ContextType) } -func (router *router) ServeRequest(ctx context.Context, cc codec.Codec) error { - sending := new(sync.Mutex) - service, mtype, req, argv, replyv, keepReading, err := router.readRequest(cc) - if err != nil { - if !keepReading { - return err - } - // send a response if we actually managed to read a header. - if req != nil { - router.sendResponse(sending, req, invalidRequest, cc, err.Error(), true) - router.freeRequest(req) - } - return err - } - service.call(ctx, router, sending, mtype, req, argv, replyv, cc) - return nil -} - func (router *router) getRequest() *request { router.reqLock.Lock() req := router.freeReq @@ -464,3 +397,70 @@ func (router *router) readHeader(cc codec.Codec) (service *service, mtype *metho } return } + +func (router *router) NewHandler(h interface{}, opts ...HandlerOption) Handler { + return newRpcHandler(h, opts...) +} + +func (router *router) Handle(h Handler) error { + router.mu.Lock() + defer router.mu.Unlock() + if router.serviceMap == nil { + router.serviceMap = make(map[string]*service) + } + + if len(h.Name()) == 0 { + return errors.New("rpc.Handle: handler has no name") + } + if !isExported(h.Name()) { + return errors.New("rpc.Handle: type " + h.Name() + " is not exported") + } + + rcvr := h.Handler() + s := new(service) + s.typ = reflect.TypeOf(rcvr) + s.rcvr = reflect.ValueOf(rcvr) + + // check name + if _, present := router.serviceMap[h.Name()]; present { + return errors.New("rpc.Handle: service already defined: " + h.Name()) + } + + s.name = h.Name() + s.method = make(map[string]*methodType) + + // Install the methods + for m := 0; m < s.typ.NumMethod(); m++ { + method := s.typ.Method(m) + if mt := prepareMethod(method); mt != nil { + s.method[method.Name] = mt + } + } + + // Check there are methods + if len(s.method) == 0 { + return errors.New("rpc Register: type " + s.name + " has no exported methods of suitable type") + } + + // save handler + router.serviceMap[s.name] = s + return nil +} + +func (router *router) ServeRequest(ctx context.Context, cc codec.Codec) error { + sending := new(sync.Mutex) + service, mtype, req, argv, replyv, keepReading, err := router.readRequest(cc) + if err != nil { + if !keepReading { + return err + } + // send a response if we actually managed to read a header. + if req != nil { + router.sendResponse(sending, req, invalidRequest, cc, err.Error(), true) + router.freeRequest(req) + } + return err + } + service.call(ctx, router, sending, mtype, req, argv, replyv, cc) + return nil +} From d004c9624b76e048425523ee7e2ddef15c59b1c6 Mon Sep 17 00:00:00 2001 From: Asim Aslam Date: Wed, 9 Jan 2019 16:20:57 +0000 Subject: [PATCH 093/196] Add router modifications --- codec/codec.go | 3 +++ server/rpc_codec.go | 27 ++++++++++++++++++++++----- server/rpc_request.go | 15 ++++++++++++--- server/rpc_router.go | 25 ++++++++++++++----------- server/rpc_server.go | 13 ++++++++++--- server/server.go | 14 +++++++++++--- 6 files changed, 72 insertions(+), 25 deletions(-) diff --git a/codec/codec.go b/codec/codec.go index 7909d3f8..c41cfaa9 100644 --- a/codec/codec.go +++ b/codec/codec.go @@ -39,5 +39,8 @@ type Message struct { Target string Method string Error string + + // The values read from the socket Header map[string]string + Body []byte } diff --git a/server/rpc_codec.go b/server/rpc_codec.go index 8cf209dd..abceda03 100644 --- a/server/rpc_codec.go +++ b/server/rpc_codec.go @@ -73,7 +73,11 @@ func newRpcCodec(req *transport.Message, socket transport.Socket, c codec.NewCod } func (c *rpcCodec) ReadHeader(r *codec.Message, t codec.MessageType) error { - m := codec.Message{Header: c.req.Header} + // the initieal message + m := codec.Message{ + Header: c.req.Header, + Body: c.req.Body, + } // if its a follow on request read it if !c.first { @@ -93,6 +97,8 @@ func (c *rpcCodec) ReadHeader(r *codec.Message, t codec.MessageType) error { // set the message header m.Header = tm.Header + // set the message body + m.Body = tm.Body } // no longer first read @@ -117,7 +123,7 @@ func (c *rpcCodec) ReadBody(b interface{}) error { return c.codec.ReadBody(b) } -func (c *rpcCodec) Write(r *codec.Message, body interface{}) error { +func (c *rpcCodec) Write(r *codec.Message, b interface{}) error { c.buf.wbuf.Reset() // create a new message @@ -134,22 +140,33 @@ func (c *rpcCodec) Write(r *codec.Message, body interface{}) error { }, } - // write to the body - if err := c.codec.Write(m, body); err != nil { + // the body being sent + var body []byte + + // if we have encoded data just send it + if len(r.Body) > 0 { + body = r.Body + // write to the body + } else if err := c.codec.Write(m, b); err != nil { c.buf.wbuf.Reset() // write an error if it failed m.Error = errors.Wrapf(err, "Unable to encode body").Error() m.Header["X-Micro-Error"] = m.Error + // no body to write if err := c.codec.Write(m, nil); err != nil { return err } + // write the body + } else { + // set the body + body = c.buf.wbuf.Bytes() } // send on the socket return c.socket.Send(&transport.Message{ Header: m.Header, - Body: c.buf.wbuf.Bytes(), + Body: body, }) } diff --git a/server/rpc_request.go b/server/rpc_request.go index b96286c2..d01de930 100644 --- a/server/rpc_request.go +++ b/server/rpc_request.go @@ -1,10 +1,15 @@ package server +import ( + "github.com/micro/go-micro/codec" +) + type rpcRequest struct { service string method string contentType string - request interface{} + codec codec.Codec + body []byte stream bool } @@ -14,6 +19,10 @@ type rpcMessage struct { payload interface{} } +func (r *rpcRequest) Codec() codec.Codec { + return r.codec +} + func (r *rpcRequest) ContentType() string { return r.contentType } @@ -26,8 +35,8 @@ func (r *rpcRequest) Method() string { return r.method } -func (r *rpcRequest) Request() interface{} { - return r.request +func (r *rpcRequest) Body() []byte { + return r.body } func (r *rpcRequest) Stream() bool { diff --git a/server/rpc_router.go b/server/rpc_router.go index 291e3bac..477d5acb 100644 --- a/server/rpc_router.go +++ b/server/rpc_router.go @@ -18,6 +18,7 @@ import ( "github.com/micro/go-log" "github.com/micro/go-micro/codec" + "github.com/micro/go-micro/transport" ) var ( @@ -184,21 +185,20 @@ func (router *router) sendResponse(sending sync.Locker, req *request, reply inte return err } -func (s *service) call(ctx context.Context, router *router, sending *sync.Mutex, mtype *methodType, req *request, argv, replyv reflect.Value, codec codec.Codec) { +func (s *service) call(ctx context.Context, router *router, sending *sync.Mutex, mtype *methodType, req *request, argv, replyv reflect.Value, cc codec.Codec) { function := mtype.method.Func var returnValues []reflect.Value r := &rpcRequest{ - service: router.name, + service: req.msg.Target, contentType: req.msg.Header["Content-Type"], method: req.msg.Method, + body: req.msg.Body, } if !mtype.stream { - r.request = argv.Interface() - fn := func(ctx context.Context, req Request, rsp interface{}) error { - returnValues = function.Call([]reflect.Value{s.rcvr, mtype.prepareContext(ctx), reflect.ValueOf(req.Request()), reflect.ValueOf(rsp)}) + returnValues = function.Call([]reflect.Value{s.rcvr, mtype.prepareContext(ctx), reflect.ValueOf(argv.Interface()), reflect.ValueOf(rsp)}) // The return value for the method is an error. if err := returnValues[0].Interface(); err != nil { @@ -218,7 +218,7 @@ func (s *service) call(ctx context.Context, router *router, sending *sync.Mutex, errmsg = err.Error() } - err = router.sendResponse(sending, req, replyv.Interface(), codec, errmsg, true) + err = router.sendResponse(sending, req, replyv.Interface(), cc, errmsg, true) if err != nil { log.Log("rpc call: unable to send response: ", err) } @@ -233,7 +233,7 @@ func (s *service) call(ctx context.Context, router *router, sending *sync.Mutex, stream := &rpcStream{ context: ctx, - codec: codec, + codec: cc, request: r, id: req.msg.Id, } @@ -268,7 +268,7 @@ func (s *service) call(ctx context.Context, router *router, sending *sync.Mutex, // this is the last packet, we don't do anything with // the error here (well sendStreamResponse will log it // already) - router.sendResponse(sending, req, nil, codec, errmsg, true) + router.sendResponse(sending, req, nil, cc, errmsg, true) router.freeRequest(req) } @@ -319,7 +319,9 @@ func (router *router) freeResponse(resp *response) { router.respLock.Unlock() } -func (router *router) readRequest(cc codec.Codec) (service *service, mtype *methodType, req *request, argv, replyv reflect.Value, keepReading bool, err error) { +func (router *router) readRequest(r Request) (service *service, mtype *methodType, req *request, argv, replyv reflect.Value, keepReading bool, err error) { + cc := r.Codec() + service, mtype, req, keepReading, err = router.readHeader(cc) if err != nil { if !keepReading { @@ -447,9 +449,10 @@ func (router *router) Handle(h Handler) error { return nil } -func (router *router) ServeRequest(ctx context.Context, cc codec.Codec) error { +func (router *router) ServeRequest(ctx context.Context, r Request, s transport.Socket) error { + cc := r.Codec() sending := new(sync.Mutex) - service, mtype, req, argv, replyv, keepReading, err := router.readRequest(cc) + service, mtype, req, argv, replyv, keepReading, err := router.readRequest(r) if err != nil { if !keepReading { return err diff --git a/server/rpc_server.go b/server/rpc_server.go index 6d73f63b..d0ed7715 100644 --- a/server/rpc_server.go +++ b/server/rpc_server.go @@ -110,8 +110,15 @@ func (s *rpcServer) ServeConn(sock transport.Socket) { return } - // create the internal server codec - codec := newRpcCodec(&msg, sock, cf) + // internal request + request := &rpcRequest{ + service: msg.Header["X-Micro-Service"], + method: msg.Header["X-Micro-Method"], + contentType: ct, + codec: newRpcCodec(&msg, sock, cf), + body: msg.Body, + stream: true, + } // set router var r Router @@ -122,7 +129,7 @@ func (s *rpcServer) ServeConn(sock transport.Socket) { } // TODO: needs better error handling - if err := r.ServeRequest(ctx, codec); err != nil { + if err := r.ServeRequest(ctx, request, sock); err != nil { s.wg.Done() log.Logf("Unexpected error serving request, closing socket: %v", err) return diff --git a/server/server.go b/server/server.go index 5e454824..2bc4a99a 100644 --- a/server/server.go +++ b/server/server.go @@ -11,6 +11,7 @@ import ( "github.com/micro/go-log" "github.com/micro/go-micro/codec" "github.com/micro/go-micro/registry" + "github.com/micro/go-micro/transport" ) // Server is a simple micro server abstraction @@ -30,7 +31,8 @@ type Server interface { // Router handle serving messages type Router interface { - ServeRequest(context.Context, codec.Codec) error + // ServeRequest processes a request to completion + ServeRequest(context.Context, Request, transport.Socket) error } // Message is an async message interface @@ -42,11 +44,17 @@ type Message interface { // Request is a synchronous request interface type Request interface { + // Service name requested Service() string + // Method name requested Method() string + // The initial request body + Body() []byte + // Content type provided ContentType() string - Request() interface{} - // indicates whether the request will be streamed + // The codec for encoding/decoding messages + Codec() codec.Codec + // Indicates whether its a stream Stream() bool } From 1561ccbc1402ffdaad19149823f6df5fc9e302f2 Mon Sep 17 00:00:00 2001 From: Asim Aslam Date: Wed, 9 Jan 2019 17:33:28 +0000 Subject: [PATCH 094/196] remove clientCodec --- client/rpc_codec.go | 6 ------ client/rpc_stream.go | 2 +- 2 files changed, 1 insertion(+), 7 deletions(-) diff --git a/client/rpc_codec.go b/client/rpc_codec.go index d4ca0702..d269392f 100644 --- a/client/rpc_codec.go +++ b/client/rpc_codec.go @@ -45,12 +45,6 @@ type readWriteCloser struct { rbuf *bytes.Buffer } -type clientCodec interface { - Write(*request, interface{}) error - Read(*response, interface{}) error - Close() error -} - type request struct { Service string ServiceMethod string // format: "Service.Method" diff --git a/client/rpc_stream.go b/client/rpc_stream.go index 275d9133..334b1fc0 100644 --- a/client/rpc_stream.go +++ b/client/rpc_stream.go @@ -13,7 +13,7 @@ type rpcStream struct { closed chan bool err error request Request - codec clientCodec + codec *rpcCodec context context.Context } From 873fc6d6639d1fd380136f969a5ee21c76c98ca3 Mon Sep 17 00:00:00 2001 From: Asim Aslam Date: Wed, 9 Jan 2019 19:11:47 +0000 Subject: [PATCH 095/196] rewriting a lot --- server/rpc_request.go | 25 +++++++++++++++++++++++-- server/rpc_response.go | 29 +++++++++++++++++++++++++++++ server/rpc_router.go | 3 +-- server/rpc_server.go | 18 ++++++++++++------ server/server.go | 19 ++++++++++++++----- 5 files changed, 79 insertions(+), 15 deletions(-) create mode 100644 server/rpc_response.go diff --git a/server/rpc_request.go b/server/rpc_request.go index d01de930..31e2bb80 100644 --- a/server/rpc_request.go +++ b/server/rpc_request.go @@ -2,13 +2,16 @@ package server import ( "github.com/micro/go-micro/codec" + "github.com/micro/go-micro/transport" ) type rpcRequest struct { service string method string contentType string + socket transport.Socket codec codec.Codec + header map[string]string body []byte stream bool } @@ -35,8 +38,26 @@ func (r *rpcRequest) Method() string { return r.method } -func (r *rpcRequest) Body() []byte { - return r.body +func (r *rpcRequest) Header() map[string]string { + return r.header +} + +func (r *rpcRequest) Read() ([]byte, error) { + // got a body + if r.body != nil { + b := r.body + r.body = nil + return b, nil + } + + var msg transport.Message + err := r.socket.Recv(&msg) + if err != nil { + return nil, err + } + r.header = msg.Header + + return msg.Body, nil } func (r *rpcRequest) Stream() bool { diff --git a/server/rpc_response.go b/server/rpc_response.go new file mode 100644 index 00000000..92f974a1 --- /dev/null +++ b/server/rpc_response.go @@ -0,0 +1,29 @@ +package server + +import ( + "net/http" + + "github.com/micro/go-micro/transport" +) + +type rpcResponse struct { + header map[string]string + socket transport.Socket +} + +func (r *rpcResponse) WriteHeader(hdr map[string]string) { + for k, v := range hdr { + r.header[k] = v + } +} + +func (r *rpcResponse) Write(b []byte) error { + if _, ok := r.header["Content-Type"]; !ok { + r.header["Content-Type"] = http.DetectContentType(b) + } + + return r.socket.Send(&transport.Message{ + Header: r.header, + Body: b, + }) +} diff --git a/server/rpc_router.go b/server/rpc_router.go index 477d5acb..67db4f20 100644 --- a/server/rpc_router.go +++ b/server/rpc_router.go @@ -18,7 +18,6 @@ import ( "github.com/micro/go-log" "github.com/micro/go-micro/codec" - "github.com/micro/go-micro/transport" ) var ( @@ -449,7 +448,7 @@ func (router *router) Handle(h Handler) error { return nil } -func (router *router) ServeRequest(ctx context.Context, r Request, s transport.Socket) error { +func (router *router) ServeRequest(ctx context.Context, r Request, rsp Response) error { cc := r.Codec() sending := new(sync.Mutex) service, mtype, req, argv, replyv, keepReading, err := router.readRequest(r) diff --git a/server/rpc_server.go b/server/rpc_server.go index d0ed7715..1fc445a6 100644 --- a/server/rpc_server.go +++ b/server/rpc_server.go @@ -116,20 +116,26 @@ func (s *rpcServer) ServeConn(sock transport.Socket) { method: msg.Header["X-Micro-Method"], contentType: ct, codec: newRpcCodec(&msg, sock, cf), + header: msg.Header, body: msg.Body, + socket: sock, stream: true, } - // set router - var r Router - r = s.router + // internal response + response := &rpcResponse{ + header: make(map[string]string), + socket: sock, + } - if s.opts.Router != nil { - r = s.opts.Router + // set router + r := s.opts.Router + if s.opts.Router == nil { + r = s.router } // TODO: needs better error handling - if err := r.ServeRequest(ctx, request, sock); err != nil { + if err := r.ServeRequest(ctx, request, response); err != nil { s.wg.Done() log.Logf("Unexpected error serving request, closing socket: %v", err) return diff --git a/server/server.go b/server/server.go index 2bc4a99a..4b390f0a 100644 --- a/server/server.go +++ b/server/server.go @@ -11,7 +11,6 @@ import ( "github.com/micro/go-log" "github.com/micro/go-micro/codec" "github.com/micro/go-micro/registry" - "github.com/micro/go-micro/transport" ) // Server is a simple micro server abstraction @@ -32,7 +31,7 @@ type Server interface { // Router handle serving messages type Router interface { // ServeRequest processes a request to completion - ServeRequest(context.Context, Request, transport.Socket) error + ServeRequest(context.Context, Request, Response) error } // Message is an async message interface @@ -48,16 +47,26 @@ type Request interface { Service() string // Method name requested Method() string - // The initial request body - Body() []byte // Content type provided ContentType() string - // The codec for encoding/decoding messages + // Header of the request + Header() map[string]string + // Read the undecoded request body + Read() ([]byte, error) + // The encoded message stream Codec() codec.Codec // Indicates whether its a stream Stream() bool } +// Response is the response writer for unencoded messages +type Response interface { + // Write the header + WriteHeader(map[string]string) + // write a response directly to the client + Write([]byte) error +} + // Stream represents a stream established with a client. // A stream can be bidirectional which is indicated by the request. // The last error will be left in Error(). From 6e0e4a684c447755a1a4133b3ec84242f9aa3249 Mon Sep 17 00:00:00 2001 From: Asim Aslam Date: Wed, 9 Jan 2019 19:28:13 +0000 Subject: [PATCH 096/196] Further crufting --- codec/codec.go | 16 ++++++++++++---- server/rpc_request.go | 2 +- server/rpc_response.go | 6 ++++++ server/rpc_router.go | 13 ++++++------- server/rpc_server.go | 5 ++++- server/server.go | 4 +++- 6 files changed, 32 insertions(+), 14 deletions(-) diff --git a/codec/codec.go b/codec/codec.go index c41cfaa9..8277cf51 100644 --- a/codec/codec.go +++ b/codec/codec.go @@ -23,13 +23,21 @@ type NewCodec func(io.ReadWriteCloser) Codec // connection. ReadBody may be called with a nil argument to force the // body to be read and discarded. type Codec interface { - ReadHeader(*Message, MessageType) error - ReadBody(interface{}) error - Write(*Message, interface{}) error + Reader + Writer Close() error String() string } +type Reader interface { + ReadHeader(*Message, MessageType) error + ReadBody(interface{}) error +} + +type Writer interface { + Write(*Message, interface{}) error +} + // Message represents detailed information about // the communication, likely followed by the body. // In the case of an error, body may be nil. @@ -42,5 +50,5 @@ type Message struct { // The values read from the socket Header map[string]string - Body []byte + Body []byte } diff --git a/server/rpc_request.go b/server/rpc_request.go index 31e2bb80..cbc4179d 100644 --- a/server/rpc_request.go +++ b/server/rpc_request.go @@ -22,7 +22,7 @@ type rpcMessage struct { payload interface{} } -func (r *rpcRequest) Codec() codec.Codec { +func (r *rpcRequest) Codec() codec.Reader { return r.codec } diff --git a/server/rpc_response.go b/server/rpc_response.go index 92f974a1..d89fa0b6 100644 --- a/server/rpc_response.go +++ b/server/rpc_response.go @@ -3,12 +3,18 @@ package server import ( "net/http" + "github.com/micro/go-micro/codec" "github.com/micro/go-micro/transport" ) type rpcResponse struct { header map[string]string socket transport.Socket + codec codec.Codec +} + +func (r *rpcResponse) Codec() codec.Writer { + return r.codec } func (r *rpcResponse) WriteHeader(hdr map[string]string) { diff --git a/server/rpc_router.go b/server/rpc_router.go index 67db4f20..1043036b 100644 --- a/server/rpc_router.go +++ b/server/rpc_router.go @@ -164,7 +164,7 @@ func prepareMethod(method reflect.Method) *methodType { return &methodType{method: method, ArgType: argType, ReplyType: replyType, ContextType: contextType, stream: stream} } -func (router *router) sendResponse(sending sync.Locker, req *request, reply interface{}, cc codec.Codec, errmsg string, last bool) (err error) { +func (router *router) sendResponse(sending sync.Locker, req *request, reply interface{}, cc codec.Writer, errmsg string, last bool) (err error) { msg := new(codec.Message) msg.Type = codec.Response resp := router.getResponse() @@ -184,7 +184,7 @@ func (router *router) sendResponse(sending sync.Locker, req *request, reply inte return err } -func (s *service) call(ctx context.Context, router *router, sending *sync.Mutex, mtype *methodType, req *request, argv, replyv reflect.Value, cc codec.Codec) { +func (s *service) call(ctx context.Context, router *router, sending *sync.Mutex, mtype *methodType, req *request, argv, replyv reflect.Value, cc codec.Writer) { function := mtype.method.Func var returnValues []reflect.Value @@ -232,7 +232,7 @@ func (s *service) call(ctx context.Context, router *router, sending *sync.Mutex, stream := &rpcStream{ context: ctx, - codec: cc, + codec: cc.(codec.Codec), request: r, id: req.msg.Id, } @@ -358,7 +358,7 @@ func (router *router) readRequest(r Request) (service *service, mtype *methodTyp return } -func (router *router) readHeader(cc codec.Codec) (service *service, mtype *methodType, req *request, keepReading bool, err error) { +func (router *router) readHeader(cc codec.Reader) (service *service, mtype *methodType, req *request, keepReading bool, err error) { // Grab the request header. msg := new(codec.Message) msg.Type = codec.Request @@ -449,7 +449,6 @@ func (router *router) Handle(h Handler) error { } func (router *router) ServeRequest(ctx context.Context, r Request, rsp Response) error { - cc := r.Codec() sending := new(sync.Mutex) service, mtype, req, argv, replyv, keepReading, err := router.readRequest(r) if err != nil { @@ -458,11 +457,11 @@ func (router *router) ServeRequest(ctx context.Context, r Request, rsp Response) } // send a response if we actually managed to read a header. if req != nil { - router.sendResponse(sending, req, invalidRequest, cc, err.Error(), true) + router.sendResponse(sending, req, invalidRequest, rsp.Codec(), err.Error(), true) router.freeRequest(req) } return err } - service.call(ctx, router, sending, mtype, req, argv, replyv, cc) + service.call(ctx, router, sending, mtype, req, argv, replyv, rsp.Codec()) return nil } diff --git a/server/rpc_server.go b/server/rpc_server.go index 1fc445a6..4481d9bb 100644 --- a/server/rpc_server.go +++ b/server/rpc_server.go @@ -110,12 +110,14 @@ func (s *rpcServer) ServeConn(sock transport.Socket) { return } + codec := newRpcCodec(&msg, sock, cf) + // internal request request := &rpcRequest{ service: msg.Header["X-Micro-Service"], method: msg.Header["X-Micro-Method"], contentType: ct, - codec: newRpcCodec(&msg, sock, cf), + codec: codec, header: msg.Header, body: msg.Body, socket: sock, @@ -126,6 +128,7 @@ func (s *rpcServer) ServeConn(sock transport.Socket) { response := &rpcResponse{ header: make(map[string]string), socket: sock, + codec: codec, } // set router diff --git a/server/server.go b/server/server.go index 4b390f0a..fbfacd0d 100644 --- a/server/server.go +++ b/server/server.go @@ -54,13 +54,15 @@ type Request interface { // Read the undecoded request body Read() ([]byte, error) // The encoded message stream - Codec() codec.Codec + Codec() codec.Reader // Indicates whether its a stream Stream() bool } // Response is the response writer for unencoded messages type Response interface { + // Encoded writer + Codec() codec.Writer // Write the header WriteHeader(map[string]string) // write a response directly to the client From c086c33bb3cdf7abc3d7d7f16c021ddf1b2e3b6a Mon Sep 17 00:00:00 2001 From: Asim Aslam Date: Thu, 10 Jan 2019 09:42:02 +0000 Subject: [PATCH 097/196] remove codecs --- broker/codec/codec.go | 10 ---------- broker/codec/json/json.go | 25 ------------------------ broker/codec/noop/noop.go | 35 --------------------------------- broker/http_broker.go | 4 ++-- broker/options.go | 6 +++--- codec/bytes/marshaler.go | 38 ++++++++++++++++++++++++++++++++++++ codec/codec.go | 9 +++++++++ codec/json/marshaler.go | 19 ++++++++++++++++++ codec/proto/marshaler.go | 19 ++++++++++++++++++ transport/codec/codec.go | 10 ---------- transport/codec/json/json.go | 25 ------------------------ transport/codec/noop/noop.go | 35 --------------------------------- transport/options.go | 6 +++--- 13 files changed, 93 insertions(+), 148 deletions(-) delete mode 100644 broker/codec/codec.go delete mode 100644 broker/codec/json/json.go delete mode 100644 broker/codec/noop/noop.go create mode 100644 codec/bytes/marshaler.go create mode 100644 codec/json/marshaler.go create mode 100644 codec/proto/marshaler.go delete mode 100644 transport/codec/codec.go delete mode 100644 transport/codec/json/json.go delete mode 100644 transport/codec/noop/noop.go diff --git a/broker/codec/codec.go b/broker/codec/codec.go deleted file mode 100644 index 5ebd05f1..00000000 --- a/broker/codec/codec.go +++ /dev/null @@ -1,10 +0,0 @@ -package codec - -// Codec is used for encoding where the broker doesn't natively support -// headers in the message type. In this case the entire message is -// encoded as the payload -type Codec interface { - Marshal(interface{}) ([]byte, error) - Unmarshal([]byte, interface{}) error - String() string -} diff --git a/broker/codec/json/json.go b/broker/codec/json/json.go deleted file mode 100644 index 25d2ab20..00000000 --- a/broker/codec/json/json.go +++ /dev/null @@ -1,25 +0,0 @@ -package json - -import ( - "encoding/json" - - "github.com/micro/go-micro/broker/codec" -) - -type jsonCodec struct{} - -func (j jsonCodec) Marshal(v interface{}) ([]byte, error) { - return json.Marshal(v) -} - -func (j jsonCodec) Unmarshal(d []byte, v interface{}) error { - return json.Unmarshal(d, v) -} - -func (j jsonCodec) String() string { - return "json" -} - -func NewCodec() codec.Codec { - return jsonCodec{} -} diff --git a/broker/codec/noop/noop.go b/broker/codec/noop/noop.go deleted file mode 100644 index 82633a24..00000000 --- a/broker/codec/noop/noop.go +++ /dev/null @@ -1,35 +0,0 @@ -package noop - -import ( - "errors" - - "github.com/micro/go-micro/broker" - "github.com/micro/go-micro/broker/codec" -) - -type noopCodec struct{} - -func (n noopCodec) Marshal(v interface{}) ([]byte, error) { - msg, ok := v.(*broker.Message) - if !ok { - return nil, errors.New("invalid message") - } - return msg.Body, nil -} - -func (n noopCodec) Unmarshal(d []byte, v interface{}) error { - msg, ok := v.(*broker.Message) - if !ok { - return errors.New("invalid message") - } - msg.Body = d - return nil -} - -func (n noopCodec) String() string { - return "noop" -} - -func NewCodec() codec.Codec { - return noopCodec{} -} diff --git a/broker/http_broker.go b/broker/http_broker.go index 3e842b3c..c04f47eb 100644 --- a/broker/http_broker.go +++ b/broker/http_broker.go @@ -20,7 +20,7 @@ import ( "github.com/google/uuid" "github.com/micro/go-log" - "github.com/micro/go-micro/broker/codec/json" + "github.com/micro/go-micro/codec/json" merr "github.com/micro/go-micro/errors" "github.com/micro/go-micro/registry" "github.com/micro/go-rcache" @@ -108,7 +108,7 @@ func newTransport(config *tls.Config) *http.Transport { func newHttpBroker(opts ...Option) Broker { options := Options{ - Codec: json.NewCodec(), + Codec: json.Marshaler{}, Context: context.TODO(), } diff --git a/broker/options.go b/broker/options.go index ae55ede1..0a909f79 100644 --- a/broker/options.go +++ b/broker/options.go @@ -4,14 +4,14 @@ import ( "context" "crypto/tls" - "github.com/micro/go-micro/broker/codec" + "github.com/micro/go-micro/codec" "github.com/micro/go-micro/registry" ) type Options struct { Addrs []string Secure bool - Codec codec.Codec + Codec codec.Marshaler TLSConfig *tls.Config // Other options for implementations of the interface // can be stored in a context @@ -71,7 +71,7 @@ func Addrs(addrs ...string) Option { // Codec sets the codec used for encoding/decoding used where // a broker does not support headers -func Codec(c codec.Codec) Option { +func Codec(c codec.Marshaler) Option { return func(o *Options) { o.Codec = c } diff --git a/codec/bytes/marshaler.go b/codec/bytes/marshaler.go new file mode 100644 index 00000000..8f8d188f --- /dev/null +++ b/codec/bytes/marshaler.go @@ -0,0 +1,38 @@ +package bytes + +import ( + "errors" +) + +type Marshaler struct{} + +type Message struct { + Header map[string]string + Body []byte +} + +func (n Marshaler) Marshal(v interface{}) ([]byte, error) { + switch v.(type) { + case []byte: + return v.([]byte), nil + case *Message: + return v.(*Message).Body, nil + } + return nil, errors.New("invalid message") +} + +func (n Marshaler) Unmarshal(d []byte, v interface{}) error { + switch v.(type) { + case *[]byte: + ve := v.(*[]byte) + *ve = d + case *Message: + ve := v.(*Message) + ve.Body = d + } + return errors.New("invalid message") +} + +func (n Marshaler) String() string { + return "bytes" +} diff --git a/codec/codec.go b/codec/codec.go index 8277cf51..9f4cbde6 100644 --- a/codec/codec.go +++ b/codec/codec.go @@ -38,6 +38,15 @@ type Writer interface { Write(*Message, interface{}) error } + +// Marshaler is a simple encoding interface used for the broker/transport +// where headers are not supported by the underlying implementation. +type Marshaler interface { + Marshal(interface{}) ([]byte, error) + Unmarshal([]byte, interface{}) error + String() string +} + // Message represents detailed information about // the communication, likely followed by the body. // In the case of an error, body may be nil. diff --git a/codec/json/marshaler.go b/codec/json/marshaler.go new file mode 100644 index 00000000..b9d0be28 --- /dev/null +++ b/codec/json/marshaler.go @@ -0,0 +1,19 @@ +package json + +import ( + "encoding/json" +) + +type Marshaler struct{} + +func (j Marshaler) Marshal(v interface{}) ([]byte, error) { + return json.Marshal(v) +} + +func (j Marshaler) Unmarshal(d []byte, v interface{}) error { + return json.Unmarshal(d, v) +} + +func (j Marshaler) String() string { + return "json" +} diff --git a/codec/proto/marshaler.go b/codec/proto/marshaler.go new file mode 100644 index 00000000..e2889fa7 --- /dev/null +++ b/codec/proto/marshaler.go @@ -0,0 +1,19 @@ +package proto + +import ( + "github.com/golang/protobuf/proto" +) + +type Marshaler struct{} + +func (Marshaler) Marshal(v interface{}) ([]byte, error) { + return proto.Marshal(v.(proto.Message)) +} + +func (Marshaler) Unmarshal(data []byte, v interface{}) error { + return proto.Unmarshal(data, v.(proto.Message)) +} + +func (Marshaler) Name() string { + return "proto" +} diff --git a/transport/codec/codec.go b/transport/codec/codec.go deleted file mode 100644 index 85e89320..00000000 --- a/transport/codec/codec.go +++ /dev/null @@ -1,10 +0,0 @@ -package codec - -// Codec is used for encoding where the transport doesn't natively support -// headers in the message type. In this case the entire message is -// encoded as the payload -type Codec interface { - Marshal(interface{}) ([]byte, error) - Unmarshal([]byte, interface{}) error - String() string -} diff --git a/transport/codec/json/json.go b/transport/codec/json/json.go deleted file mode 100644 index 0adaab04..00000000 --- a/transport/codec/json/json.go +++ /dev/null @@ -1,25 +0,0 @@ -package json - -import ( - "encoding/json" - - "github.com/micro/go-micro/transport/codec" -) - -type jsonCodec struct{} - -func (j jsonCodec) Marshal(v interface{}) ([]byte, error) { - return json.Marshal(v) -} - -func (j jsonCodec) Unmarshal(d []byte, v interface{}) error { - return json.Unmarshal(d, v) -} - -func (j jsonCodec) String() string { - return "json" -} - -func NewCodec() codec.Codec { - return jsonCodec{} -} diff --git a/transport/codec/noop/noop.go b/transport/codec/noop/noop.go deleted file mode 100644 index 44ac91a1..00000000 --- a/transport/codec/noop/noop.go +++ /dev/null @@ -1,35 +0,0 @@ -package noop - -import ( - "errors" - - "github.com/micro/go-micro/transport" - "github.com/micro/go-micro/transport/codec" -) - -type noopCodec struct{} - -func (n noopCodec) Marshal(v interface{}) ([]byte, error) { - msg, ok := v.(*transport.Message) - if !ok { - return nil, errors.New("invalid message") - } - return msg.Body, nil -} - -func (n noopCodec) Unmarshal(d []byte, v interface{}) error { - msg, ok := v.(*transport.Message) - if !ok { - return errors.New("invalid message") - } - msg.Body = d - return nil -} - -func (n noopCodec) String() string { - return "noop" -} - -func NewCodec() codec.Codec { - return noopCodec{} -} diff --git a/transport/options.go b/transport/options.go index a62d1194..5aaebe4b 100644 --- a/transport/options.go +++ b/transport/options.go @@ -5,12 +5,12 @@ import ( "crypto/tls" "time" - "github.com/micro/go-micro/transport/codec" + "github.com/micro/go-micro/codec" ) type Options struct { Addrs []string - Codec codec.Codec + Codec codec.Marshaler Secure bool TLSConfig *tls.Config // Timeout sets the timeout for Send/Recv @@ -50,7 +50,7 @@ func Addrs(addrs ...string) Option { // Codec sets the codec used for encoding where the transport // does not support message headers -func Codec(c codec.Codec) Option { +func Codec(c codec.Marshaler) Option { return func(o *Options) { o.Codec = c } From bb31480f1acfa869194aac7a88c7b8c6cd70faea Mon Sep 17 00:00:00 2001 From: Asim Aslam Date: Thu, 10 Jan 2019 10:57:04 +0000 Subject: [PATCH 098/196] downgrade code generated stuff --- registry/gossip/proto/gossip.pb.go | 21 +++++++++------------ 1 file changed, 9 insertions(+), 12 deletions(-) diff --git a/registry/gossip/proto/gossip.pb.go b/registry/gossip/proto/gossip.pb.go index 89bdca55..bc7c0700 100644 --- a/registry/gossip/proto/gossip.pb.go +++ b/registry/gossip/proto/gossip.pb.go @@ -3,11 +3,9 @@ package gossip -import ( - fmt "fmt" - proto "github.com/golang/protobuf/proto" - math "math" -) +import proto "github.com/golang/protobuf/proto" +import fmt "fmt" +import math "math" // Reference imports to suppress errors if they are not otherwise used. var _ = proto.Marshal @@ -18,7 +16,7 @@ var _ = math.Inf // is compatible with the proto package it is being compiled against. // A compilation error at this line likely means your copy of the // proto package needs to be updated. -const _ = proto.ProtoPackageIsVersion3 // please upgrade the proto package +const _ = proto.ProtoPackageIsVersion2 // please upgrade the proto package // Update is the message broadcast type Update struct { @@ -45,17 +43,16 @@ func (m *Update) Reset() { *m = Update{} } func (m *Update) String() string { return proto.CompactTextString(m) } func (*Update) ProtoMessage() {} func (*Update) Descriptor() ([]byte, []int) { - return fileDescriptor_18cba623e76e57f3, []int{0} + return fileDescriptor_gossip_fd1eb378131a5d12, []int{0} } - func (m *Update) XXX_Unmarshal(b []byte) error { return xxx_messageInfo_Update.Unmarshal(m, b) } func (m *Update) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { return xxx_messageInfo_Update.Marshal(b, m, deterministic) } -func (m *Update) XXX_Merge(src proto.Message) { - xxx_messageInfo_Update.Merge(m, src) +func (dst *Update) XXX_Merge(src proto.Message) { + xxx_messageInfo_Update.Merge(dst, src) } func (m *Update) XXX_Size() int { return xxx_messageInfo_Update.Size(m) @@ -121,10 +118,10 @@ func init() { } func init() { - proto.RegisterFile("github.com/micro/go-micro/registry/gossip/proto/gossip.proto", fileDescriptor_18cba623e76e57f3) + proto.RegisterFile("github.com/micro/go-micro/registry/gossip/proto/gossip.proto", fileDescriptor_gossip_fd1eb378131a5d12) } -var fileDescriptor_18cba623e76e57f3 = []byte{ +var fileDescriptor_gossip_fd1eb378131a5d12 = []byte{ // 251 bytes of a gzipped FileDescriptorProto 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x54, 0x90, 0xcf, 0x4a, 0xc4, 0x30, 0x10, 0x87, 0x69, 0xb6, 0x9b, 0xb5, 0xe3, 0x1f, 0x64, 0x10, 0x09, 0xb2, 0x87, 0xe2, 0xa9, 0x17, From 648da5494fa94ca586d60d94b1df7df3efd67371 Mon Sep 17 00:00:00 2001 From: Asim Aslam Date: Thu, 10 Jan 2019 11:39:39 +0000 Subject: [PATCH 099/196] Change a few things --- client/client.go | 25 ++++++++++++++++++- client/rpc_client.go | 6 ++--- client/rpc_codec.go | 56 ++++++++++++++++++++++++++++--------------- client/rpc_request.go | 17 +++++++++---- client/rpc_stream.go | 31 +++++++++++++++--------- 5 files changed, 97 insertions(+), 38 deletions(-) diff --git a/client/client.go b/client/client.go index 74ec51be..32cb9a6b 100644 --- a/client/client.go +++ b/client/client.go @@ -4,6 +4,8 @@ package client import ( "context" "time" + + "github.com/micro/go-micro/codec" ) // Client is the interface used to make requests to services. @@ -20,6 +22,11 @@ type Client interface { String() string } +// Router manages request routing +type Router interface { + SendRequest(context.Context, Request) (Response, error) +} + // Message is the interface for publishing asynchronously type Message interface { Topic() string @@ -29,14 +36,30 @@ type Message interface { // Request is the interface for a synchronous request used by Call or Stream type Request interface { + // The service to call Service() string + // The method to call Method() string + // The content type ContentType() string - Request() interface{} + // The unencoded request body + Body() interface{} + // Write to the encoded request writer. This is nil before a call is made + Codec() codec.Writer // indicates whether the request will be a streaming one rather than unary Stream() bool } +// Response is the response received from a service +type Response interface { + // Read the response + Codec() codec.Reader + // read the header + Header() map[string]string + // Read the undecoded response + Read() ([]byte, error) +} + // Stream is the inteface for a bidirectional synchronous stream type Stream interface { Context() context.Context diff --git a/client/rpc_client.go b/client/rpc_client.go index 04be269e..336dd34f 100644 --- a/client/rpc_client.go +++ b/client/rpc_client.go @@ -97,7 +97,7 @@ func (r *rpcClient) call(ctx context.Context, address string, req Request, resp request: req, closed: make(chan bool), codec: newRpcCodec(msg, c, cf), - seq: fmt.Sprintf("%v", seq), + id: fmt.Sprintf("%v", seq), } defer stream.Close() @@ -111,7 +111,7 @@ func (r *rpcClient) call(ctx context.Context, address string, req Request, resp }() // send request - if err := stream.Send(req.Request()); err != nil { + if err := stream.Send(req.Body()); err != nil { ch <- err return } @@ -183,7 +183,7 @@ func (r *rpcClient) stream(ctx context.Context, address string, req Request, opt ch := make(chan error, 1) go func() { - ch <- stream.Send(req.Request()) + ch <- stream.Send(req.Body()) }() var grr error diff --git a/client/rpc_codec.go b/client/rpc_codec.go index d269392f..fe694380 100644 --- a/client/rpc_codec.go +++ b/client/rpc_codec.go @@ -3,7 +3,6 @@ package client import ( "bytes" errs "errors" - "fmt" "github.com/micro/go-micro/codec" raw "github.com/micro/go-micro/codec/bytes" @@ -85,7 +84,7 @@ func (rwc *readWriteCloser) Close() error { return nil } -func newRpcCodec(req *transport.Message, client transport.Client, c codec.NewCodec) *rpcCodec { +func newRpcCodec(req *transport.Message, client transport.Client, c codec.NewCodec) codec.Codec { rwc := &readWriteCloser{ wbuf: bytes.NewBuffer(nil), rbuf: bytes.NewBuffer(nil), @@ -99,34 +98,45 @@ func newRpcCodec(req *transport.Message, client transport.Client, c codec.NewCod return r } -func (c *rpcCodec) Write(req *request, body interface{}) error { +func (c *rpcCodec) Write(wm *codec.Message, body interface{}) error { c.buf.wbuf.Reset() m := &codec.Message{ - Id: req.Seq, - Target: req.Service, - Method: req.ServiceMethod, + Id: wm.Id, + Target: wm.Target, + Method: wm.Method, Type: codec.Request, Header: map[string]string{ - "X-Micro-Id": fmt.Sprintf("%v", req.Seq), - "X-Micro-Service": req.Service, - "X-Micro-Method": req.ServiceMethod, + "X-Micro-Id": wm.Id, + "X-Micro-Service": wm.Target, + "X-Micro-Method": wm.Method, }, } + if err := c.codec.Write(m, body); err != nil { return errors.InternalServerError("go.micro.client.codec", err.Error()) } - c.req.Body = c.buf.wbuf.Bytes() + + // set body + if len(wm.Body) > 0 { + c.req.Body = wm.Body + } else { + c.req.Body = c.buf.wbuf.Bytes() + } + + // set header for k, v := range m.Header { c.req.Header[k] = v } + + // send the request if err := c.client.Send(c.req); err != nil { return errors.InternalServerError("go.micro.client.transport", err.Error()) } return nil } -func (c *rpcCodec) Read(r *response, b interface{}) error { +func (c *rpcCodec) ReadHeader(wm *codec.Message, r codec.MessageType) error { var m transport.Message if err := c.client.Recv(&m); err != nil { return errors.InternalServerError("go.micro.client.transport", err.Error()) @@ -139,34 +149,38 @@ func (c *rpcCodec) Read(r *response, b interface{}) error { me.Header = m.Header // read header - err := c.codec.ReadHeader(&me, codec.Response) - r.ServiceMethod = me.Method - r.Seq = me.Id - r.Error = me.Error + err := c.codec.ReadHeader(&me, r) + wm.Method = me.Method + wm.Id = me.Id + wm.Error = me.Error // check error in header if len(me.Error) == 0 { - r.Error = me.Header["X-Micro-Error"] + wm.Error = me.Header["X-Micro-Error"] } // check method in header if len(me.Method) == 0 { - r.ServiceMethod = me.Header["X-Micro-Method"] + wm.Method = me.Header["X-Micro-Method"] } if len(me.Id) == 0 { - r.Seq = me.Header["X-Micro-Id"] + wm.Id = me.Header["X-Micro-Id"] } + // return header error if err != nil { return errors.InternalServerError("go.micro.client.codec", err.Error()) } + return nil +} + +func (c *rpcCodec) ReadBody(b interface{}) error { // read body if err := c.codec.ReadBody(b); err != nil { return errors.InternalServerError("go.micro.client.codec", err.Error()) } - return nil } @@ -178,3 +192,7 @@ func (c *rpcCodec) Close() error { } return nil } + +func (c *rpcCodec) String() string { + return "rpc" +} diff --git a/client/rpc_request.go b/client/rpc_request.go index 04ce490a..b7f9695e 100644 --- a/client/rpc_request.go +++ b/client/rpc_request.go @@ -1,10 +1,15 @@ package client +import ( + "github.com/micro/go-micro/codec" +) + type rpcRequest struct { service string method string contentType string - request interface{} + codec codec.Codec + body interface{} opts RequestOptions } @@ -23,7 +28,7 @@ func newRequest(service, method string, request interface{}, contentType string, return &rpcRequest{ service: service, method: method, - request: request, + body: request, contentType: contentType, opts: opts, } @@ -41,8 +46,12 @@ func (r *rpcRequest) Method() string { return r.method } -func (r *rpcRequest) Request() interface{} { - return r.request +func (r *rpcRequest) Body() interface{} { + return r.body +} + +func (r *rpcRequest) Codec() codec.Writer { + return r.codec } func (r *rpcRequest) Stream() bool { diff --git a/client/rpc_stream.go b/client/rpc_stream.go index 334b1fc0..838172d4 100644 --- a/client/rpc_stream.go +++ b/client/rpc_stream.go @@ -4,16 +4,18 @@ import ( "context" "io" "sync" + + "github.com/micro/go-micro/codec" ) // Implements the streamer interface type rpcStream struct { sync.RWMutex - seq string + id string closed chan bool err error request Request - codec *rpcCodec + codec codec.Codec context context.Context } @@ -43,18 +45,18 @@ func (r *rpcStream) Send(msg interface{}) error { return errShutdown } - seq := r.seq - - req := request{ - Service: r.request.Service(), - Seq: seq, - ServiceMethod: r.request.Method(), + req := codec.Message{ + Id: r.id, + Target: r.request.Service(), + Method: r.request.Method(), + Type: codec.Request, } if err := r.codec.Write(&req, msg); err != nil { r.err = err return err } + return nil } @@ -67,9 +69,9 @@ func (r *rpcStream) Recv(msg interface{}) error { return errShutdown } - var resp response + var resp codec.Message - if err := r.codec.Read(&resp, msg); err != nil { + if err := r.codec.ReadHeader(&resp, codec.Response); err != nil { if err == io.EOF && !r.isClosed() { r.err = io.ErrUnexpectedEOF return io.ErrUnexpectedEOF @@ -81,13 +83,20 @@ func (r *rpcStream) Recv(msg interface{}) error { switch { case len(resp.Error) > 0: // We've got an error response. Give this to the request; - // any subsequent requests will get the ReadBody + // any subsequent requests will get the ReadResponseBody // error if there is one. if resp.Error != lastStreamResponseError { r.err = serverError(resp.Error) } else { r.err = io.EOF } + if err := r.codec.ReadBody(nil); err != nil { + r.err = err + } + default: + if err := r.codec.ReadBody(msg); err != nil { + r.err = err + } } return r.err From 59d82b0abe8549ade46a28939e9f0780c9f1fad8 Mon Sep 17 00:00:00 2001 From: Asim Aslam Date: Thu, 10 Jan 2019 11:43:36 +0000 Subject: [PATCH 100/196] Add response --- client/rpc_response.go | 35 +++++++++++++++++++++++++++++++++++ 1 file changed, 35 insertions(+) create mode 100644 client/rpc_response.go diff --git a/client/rpc_response.go b/client/rpc_response.go new file mode 100644 index 00000000..d5c4e894 --- /dev/null +++ b/client/rpc_response.go @@ -0,0 +1,35 @@ +package client + +import ( + "github.com/micro/go-micro/codec" + "github.com/micro/go-micro/transport" +) + +type rpcResponse struct { + header map[string]string + body []byte + socket transport.Socket + codec codec.Codec +} + +func (r *rpcResponse) Codec() codec.Writer { + return r.codec +} + +func (r *rpcResponse) Header() map[string]string { + return r.header +} + +func (r *rpcResponse) Read() ([]byte, error) { + var msg transport.Message + + if err := r.socket.Recv(&msg); err != nil { + return nil, err + } + + // set internals + r.header = msg.Header + r.body = msg.Body + + return msg.Body, nil +} From 40ff5b749b8f2b12652e73828ed5bd01c40026af Mon Sep 17 00:00:00 2001 From: Asim Aslam Date: Thu, 10 Jan 2019 20:35:10 +0000 Subject: [PATCH 101/196] Set topic header --- client/rpc_client.go | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/client/rpc_client.go b/client/rpc_client.go index 336dd34f..b85e76b7 100644 --- a/client/rpc_client.go +++ b/client/rpc_client.go @@ -9,6 +9,7 @@ import ( "sync/atomic" + "github.com/google/uuid" "github.com/micro/go-micro/broker" "github.com/micro/go-micro/codec" "github.com/micro/go-micro/errors" @@ -444,7 +445,11 @@ func (r *rpcClient) Publish(ctx context.Context, msg Message, opts ...PublishOpt if !ok { md = make(map[string]string) } + + id := uuid.New().String() md["Content-Type"] = msg.ContentType() + md["X-Micro-Topic"] = msg.Topic() + md["X-Micro-Id"] = id // encode message body cf, err := r.newCodec(msg.ContentType()) @@ -452,7 +457,13 @@ func (r *rpcClient) Publish(ctx context.Context, msg Message, opts ...PublishOpt return errors.InternalServerError("go.micro.client", err.Error()) } b := &buffer{bytes.NewBuffer(nil)} - if err := cf(b).Write(&codec.Message{Type: codec.Publication}, msg.Payload()); err != nil { + if err := cf(b).Write(&codec.Message{ + Type: codec.Publication, + Header: map[string]string{ + "X-Micro-Id": id, + "X-Micro-Topic": msg.Topic(), + }, + }, msg.Payload()); err != nil { return errors.InternalServerError("go.micro.client", err.Error()) } r.once.Do(func() { From f853f88bcd8c5d7ea588be0c98a8b02f1dcc222d Mon Sep 17 00:00:00 2001 From: Asim Aslam Date: Thu, 10 Jan 2019 20:35:20 +0000 Subject: [PATCH 102/196] gofmt --- codec/codec.go | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/codec/codec.go b/codec/codec.go index 9f4cbde6..f4d4f295 100644 --- a/codec/codec.go +++ b/codec/codec.go @@ -38,8 +38,7 @@ type Writer interface { Write(*Message, interface{}) error } - -// Marshaler is a simple encoding interface used for the broker/transport +// Marshaler is a simple encoding interface used for the broker/transport // where headers are not supported by the underlying implementation. type Marshaler interface { Marshal(interface{}) ([]byte, error) From 9adebfcf1e144749b5c6afcf509478d181e84e7b Mon Sep 17 00:00:00 2001 From: Asim Aslam Date: Thu, 10 Jan 2019 21:25:31 +0000 Subject: [PATCH 103/196] rename method to endpoint --- client/client.go | 10 +++++----- client/mock/mock.go | 10 +++++----- client/mock/mock_test.go | 12 ++++++------ client/rpc_client.go | 3 ++- client/rpc_client_test.go | 20 ++++++++++---------- client/rpc_codec.go | 20 ++++++++++---------- client/rpc_request.go | 10 +++++----- client/rpc_request_test.go | 12 ++++++------ client/rpc_stream.go | 8 ++++---- codec/codec.go | 10 +++++----- codec/grpc/grpc.go | 4 ++-- codec/jsonrpc/client.go | 6 +++--- codec/jsonrpc/server.go | 2 +- codec/protorpc/protorpc.go | 8 ++++---- server/rpc_codec.go | 20 ++++++++++---------- server/rpc_codec_test.go | 6 +++--- server/rpc_request.go | 6 +++--- server/rpc_router.go | 12 ++++++------ server/rpc_server.go | 2 +- server/rpc_stream.go | 6 +++--- server/server.go | 10 +++++----- 21 files changed, 99 insertions(+), 98 deletions(-) diff --git a/client/client.go b/client/client.go index 32cb9a6b..4cfe0bc8 100644 --- a/client/client.go +++ b/client/client.go @@ -15,7 +15,7 @@ type Client interface { Init(...Option) error Options() Options NewMessage(topic string, msg interface{}, opts ...MessageOption) Message - NewRequest(service, method string, req interface{}, reqOpts ...RequestOption) Request + NewRequest(service, endpoint string, req interface{}, reqOpts ...RequestOption) Request Call(ctx context.Context, req Request, rsp interface{}, opts ...CallOption) error Stream(ctx context.Context, req Request, opts ...CallOption) (Stream, error) Publish(ctx context.Context, msg Message, opts ...PublishOption) error @@ -38,8 +38,8 @@ type Message interface { type Request interface { // The service to call Service() string - // The method to call - Method() string + // The endpoint to call + Endpoint() string // The content type ContentType() string // The unencoded request body @@ -125,8 +125,8 @@ func NewClient(opt ...Option) Client { // Creates a new request using the default client. Content Type will // be set to the default within options and use the appropriate codec -func NewRequest(service, method string, request interface{}, reqOpts ...RequestOption) Request { - return DefaultClient.NewRequest(service, method, request, reqOpts...) +func NewRequest(service, endpoint string, request interface{}, reqOpts ...RequestOption) Request { + return DefaultClient.NewRequest(service, endpoint, request, reqOpts...) } // Creates a streaming connection with a service and returns responses on the diff --git a/client/mock/mock.go b/client/mock/mock.go index db267530..e9022c71 100644 --- a/client/mock/mock.go +++ b/client/mock/mock.go @@ -16,7 +16,7 @@ var ( ) type MockResponse struct { - Method string + Endpoint string Response interface{} Error error } @@ -54,8 +54,8 @@ func (m *MockClient) NewMessage(topic string, msg interface{}, opts ...client.Me return m.Client.NewMessage(topic, msg, opts...) } -func (m *MockClient) NewRequest(service, method string, req interface{}, reqOpts ...client.RequestOption) client.Request { - return m.Client.NewRequest(service, method, req, reqOpts...) +func (m *MockClient) NewRequest(service, endpoint string, req interface{}, reqOpts ...client.RequestOption) client.Request { + return m.Client.NewRequest(service, endpoint, req, reqOpts...) } func (m *MockClient) Call(ctx context.Context, req client.Request, rsp interface{}, opts ...client.CallOption) error { @@ -68,7 +68,7 @@ func (m *MockClient) Call(ctx context.Context, req client.Request, rsp interface } for _, r := range response { - if r.Method != req.Method() { + if r.Endpoint != req.Endpoint() { continue } @@ -91,7 +91,7 @@ func (m *MockClient) Call(ctx context.Context, req client.Request, rsp interface return nil } - return fmt.Errorf("rpc: can't find service %s", req.Method()) + return fmt.Errorf("rpc: can't find service %s", req.Endpoint()) } func (m *MockClient) Stream(ctx context.Context, req client.Request, opts ...client.CallOption) (client.Stream, error) { diff --git a/client/mock/mock_test.go b/client/mock/mock_test.go index db9c1289..5dc5de1b 100644 --- a/client/mock/mock_test.go +++ b/client/mock/mock_test.go @@ -13,17 +13,17 @@ func TestClient(t *testing.T) { } response := []MockResponse{ - {Method: "Foo.Bar", Response: map[string]interface{}{"foo": "bar"}}, - {Method: "Foo.Struct", Response: &TestResponse{Param: "aparam"}}, - {Method: "Foo.Fail", Error: errors.InternalServerError("go.mock", "failed")}, - {Method: "Foo.Func", Response: func() string { return "string" }}, - {Method: "Foo.FuncStruct", Response: func() *TestResponse { return &TestResponse{Param: "aparam"} }}, + {Endpoint: "Foo.Bar", Response: map[string]interface{}{"foo": "bar"}}, + {Endpoint: "Foo.Struct", Response: &TestResponse{Param: "aparam"}}, + {Endpoint: "Foo.Fail", Error: errors.InternalServerError("go.mock", "failed")}, + {Endpoint: "Foo.Func", Response: func() string { return "string" }}, + {Endpoint: "Foo.FuncStruct", Response: func() *TestResponse { return &TestResponse{Param: "aparam"} }}, } c := NewClient(Response("go.mock", response)) for _, r := range response { - req := c.NewRequest("go.mock", r.Method, map[string]interface{}{"foo": "bar"}) + req := c.NewRequest("go.mock", r.Endpoint, map[string]interface{}{"foo": "bar"}) var rsp interface{} err := c.Call(context.TODO(), req, &rsp) diff --git a/client/rpc_client.go b/client/rpc_client.go index b85e76b7..34fd8671 100644 --- a/client/rpc_client.go +++ b/client/rpc_client.go @@ -458,7 +458,8 @@ func (r *rpcClient) Publish(ctx context.Context, msg Message, opts ...PublishOpt } b := &buffer{bytes.NewBuffer(nil)} if err := cf(b).Write(&codec.Message{ - Type: codec.Publication, + Target: msg.Topic(), + Type: codec.Publication, Header: map[string]string{ "X-Micro-Id": id, "X-Micro-Topic": msg.Topic(), diff --git a/client/rpc_client_test.go b/client/rpc_client_test.go index 6bafbdf5..72140711 100644 --- a/client/rpc_client_test.go +++ b/client/rpc_client_test.go @@ -14,7 +14,7 @@ import ( func TestCallAddress(t *testing.T) { var called bool service := "test.service" - method := "Test.Method" + endpoint := "Test.Endpoint" address := "10.1.10.1:8080" wrap := func(cf CallFunc) CallFunc { @@ -25,8 +25,8 @@ func TestCallAddress(t *testing.T) { return fmt.Errorf("expected service: %s got %s", service, req.Service()) } - if req.Method() != method { - return fmt.Errorf("expected service: %s got %s", method, req.Method()) + if req.Endpoint() != endpoint { + return fmt.Errorf("expected service: %s got %s", endpoint, req.Endpoint()) } if addr != address { @@ -45,7 +45,7 @@ func TestCallAddress(t *testing.T) { ) c.Options().Selector.Init(selector.Registry(r)) - req := c.NewRequest(service, method, nil) + req := c.NewRequest(service, endpoint, nil) // test calling remote address if err := c.Call(context.Background(), req, nil, WithAddress(address)); err != nil { @@ -60,7 +60,7 @@ func TestCallAddress(t *testing.T) { func TestCallRetry(t *testing.T) { service := "test.service" - method := "Test.Method" + endpoint := "Test.Endpoint" address := "10.1.10.1:8080" var called int @@ -84,7 +84,7 @@ func TestCallRetry(t *testing.T) { ) c.Options().Selector.Init(selector.Registry(r)) - req := c.NewRequest(service, method, nil) + req := c.NewRequest(service, endpoint, nil) // test calling remote address if err := c.Call(context.Background(), req, nil, WithAddress(address)); err != nil { @@ -101,7 +101,7 @@ func TestCallWrapper(t *testing.T) { var called bool id := "test.1" service := "test.service" - method := "Test.Method" + endpoint := "Test.Endpoint" host := "10.1.10.1" port := 8080 address := "10.1.10.1:8080" @@ -114,8 +114,8 @@ func TestCallWrapper(t *testing.T) { return fmt.Errorf("expected service: %s got %s", service, req.Service()) } - if req.Method() != method { - return fmt.Errorf("expected service: %s got %s", method, req.Method()) + if req.Endpoint() != endpoint { + return fmt.Errorf("expected service: %s got %s", endpoint, req.Endpoint()) } if addr != address { @@ -146,7 +146,7 @@ func TestCallWrapper(t *testing.T) { }, }) - req := c.NewRequest(service, method, nil) + req := c.NewRequest(service, endpoint, nil) if err := c.Call(context.Background(), req, nil); err != nil { t.Fatal("call wrapper error", err) } diff --git a/client/rpc_codec.go b/client/rpc_codec.go index fe694380..aaa01569 100644 --- a/client/rpc_codec.go +++ b/client/rpc_codec.go @@ -102,14 +102,14 @@ func (c *rpcCodec) Write(wm *codec.Message, body interface{}) error { c.buf.wbuf.Reset() m := &codec.Message{ - Id: wm.Id, - Target: wm.Target, - Method: wm.Method, - Type: codec.Request, + Id: wm.Id, + Target: wm.Target, + Endpoint: wm.Endpoint, + Type: codec.Request, Header: map[string]string{ - "X-Micro-Id": wm.Id, - "X-Micro-Service": wm.Target, - "X-Micro-Method": wm.Method, + "X-Micro-Id": wm.Id, + "X-Micro-Service": wm.Target, + "X-Micro-Endpoint": wm.Endpoint, }, } @@ -150,7 +150,7 @@ func (c *rpcCodec) ReadHeader(wm *codec.Message, r codec.MessageType) error { // read header err := c.codec.ReadHeader(&me, r) - wm.Method = me.Method + wm.Endpoint = me.Endpoint wm.Id = me.Id wm.Error = me.Error @@ -160,8 +160,8 @@ func (c *rpcCodec) ReadHeader(wm *codec.Message, r codec.MessageType) error { } // check method in header - if len(me.Method) == 0 { - wm.Method = me.Header["X-Micro-Method"] + if len(me.Endpoint) == 0 { + wm.Endpoint = me.Header["X-Micro-Endpoint"] } if len(me.Id) == 0 { diff --git a/client/rpc_request.go b/client/rpc_request.go index b7f9695e..746b4be5 100644 --- a/client/rpc_request.go +++ b/client/rpc_request.go @@ -6,14 +6,14 @@ import ( type rpcRequest struct { service string - method string + endpoint string contentType string codec codec.Codec body interface{} opts RequestOptions } -func newRequest(service, method string, request interface{}, contentType string, reqOpts ...RequestOption) Request { +func newRequest(service, endpoint string, request interface{}, contentType string, reqOpts ...RequestOption) Request { var opts RequestOptions for _, o := range reqOpts { @@ -27,7 +27,7 @@ func newRequest(service, method string, request interface{}, contentType string, return &rpcRequest{ service: service, - method: method, + endpoint: endpoint, body: request, contentType: contentType, opts: opts, @@ -42,8 +42,8 @@ func (r *rpcRequest) Service() string { return r.service } -func (r *rpcRequest) Method() string { - return r.method +func (r *rpcRequest) Endpoint() string { + return r.endpoint } func (r *rpcRequest) Body() interface{} { diff --git a/client/rpc_request_test.go b/client/rpc_request_test.go index bca3dd2f..e3516794 100644 --- a/client/rpc_request_test.go +++ b/client/rpc_request_test.go @@ -5,19 +5,19 @@ import ( ) func TestRequestOptions(t *testing.T) { - r := newRequest("service", "method", nil, "application/json") + r := newRequest("service", "endpoint", nil, "application/json") if r.Service() != "service" { t.Fatalf("expected 'service' got %s", r.Service()) } - if r.Method() != "method" { - t.Fatalf("expected 'method' got %s", r.Method()) + if r.Endpoint() != "endpoint" { + t.Fatalf("expected 'endpoint' got %s", r.Endpoint()) } if r.ContentType() != "application/json" { - t.Fatalf("expected 'method' got %s", r.ContentType()) + t.Fatalf("expected 'endpoint' got %s", r.ContentType()) } - r2 := newRequest("service", "method", nil, "application/json", WithContentType("application/protobuf")) + r2 := newRequest("service", "endpoint", nil, "application/json", WithContentType("application/protobuf")) if r2.ContentType() != "application/protobuf" { - t.Fatalf("expected 'method' got %s", r2.ContentType()) + t.Fatalf("expected 'endpoint' got %s", r2.ContentType()) } } diff --git a/client/rpc_stream.go b/client/rpc_stream.go index 838172d4..627d2099 100644 --- a/client/rpc_stream.go +++ b/client/rpc_stream.go @@ -46,10 +46,10 @@ func (r *rpcStream) Send(msg interface{}) error { } req := codec.Message{ - Id: r.id, - Target: r.request.Service(), - Method: r.request.Method(), - Type: codec.Request, + Id: r.id, + Target: r.request.Service(), + Endpoint: r.request.Endpoint(), + Type: codec.Request, } if err := r.codec.Write(&req, msg); err != nil { diff --git a/codec/codec.go b/codec/codec.go index f4d4f295..868d2dd1 100644 --- a/codec/codec.go +++ b/codec/codec.go @@ -50,11 +50,11 @@ type Marshaler interface { // the communication, likely followed by the body. // In the case of an error, body may be nil. type Message struct { - Id string - Type MessageType - Target string - Method string - Error string + Id string + Type MessageType + Target string + Endpoint string + Error string // The values read from the socket Header map[string]string diff --git a/codec/grpc/grpc.go b/codec/grpc/grpc.go index f3703840..79c30f4b 100644 --- a/codec/grpc/grpc.go +++ b/codec/grpc/grpc.go @@ -29,7 +29,7 @@ func (c *Codec) ReadHeader(m *codec.Message, t codec.MessageType) error { path := m.Header[":path"] if len(path) == 0 || path[0] != '/' { m.Target = m.Header["X-Micro-Service"] - m.Method = m.Header["X-Micro-Method"] + m.Endpoint = m.Header["X-Micro-Endpoint"] } else { // [ , a.package.Foo, Bar] parts := strings.Split(path, "/") @@ -37,7 +37,7 @@ func (c *Codec) ReadHeader(m *codec.Message, t codec.MessageType) error { return errors.New("Unknown request path") } service := strings.Split(parts[1], ".") - m.Method = strings.Join([]string{service[len(service)-1], parts[2]}, ".") + m.Endpoint = strings.Join([]string{service[len(service)-1], parts[2]}, ".") m.Target = strings.Join(service[:len(service)-1], ".") } diff --git a/codec/jsonrpc/client.go b/codec/jsonrpc/client.go index f5ec5636..768e297d 100644 --- a/codec/jsonrpc/client.go +++ b/codec/jsonrpc/client.go @@ -45,9 +45,9 @@ func newClientCodec(conn io.ReadWriteCloser) *clientCodec { func (c *clientCodec) Write(m *codec.Message, b interface{}) error { c.Lock() - c.pending[m.Id] = m.Method + c.pending[m.Id] = m.Endpoint c.Unlock() - c.req.Method = m.Method + c.req.Method = m.Endpoint c.req.Params[0] = b c.req.ID = m.Id return c.enc.Encode(&c.req) @@ -66,7 +66,7 @@ func (c *clientCodec) ReadHeader(m *codec.Message) error { } c.Lock() - m.Method = c.pending[c.resp.ID] + m.Endpoint = c.pending[c.resp.ID] delete(c.pending, c.resp.ID) c.Unlock() diff --git a/codec/jsonrpc/server.go b/codec/jsonrpc/server.go index 53f681ef..a56b3468 100644 --- a/codec/jsonrpc/server.go +++ b/codec/jsonrpc/server.go @@ -53,7 +53,7 @@ func (c *serverCodec) ReadHeader(m *codec.Message) error { if err := c.dec.Decode(&c.req); err != nil { return err } - m.Method = c.req.Method + m.Endpoint = c.req.Method m.Id = fmt.Sprintf("%v", c.req.ID) c.req.ID = nil return nil diff --git a/codec/protorpc/protorpc.go b/codec/protorpc/protorpc.go index de05552f..a7d8ba79 100644 --- a/codec/protorpc/protorpc.go +++ b/codec/protorpc/protorpc.go @@ -47,7 +47,7 @@ func (c *protoCodec) Write(m *codec.Message, b interface{}) error { c.Lock() defer c.Unlock() // This is protobuf, of course we copy it. - pbr := &Request{ServiceMethod: &m.Method, Seq: id(m.Id)} + pbr := &Request{ServiceMethod: &m.Endpoint, Seq: id(m.Id)} data, err := proto.Marshal(pbr) if err != nil { return err @@ -73,7 +73,7 @@ func (c *protoCodec) Write(m *codec.Message, b interface{}) error { case codec.Response: c.Lock() defer c.Unlock() - rtmp := &Response{ServiceMethod: &m.Method, Seq: id(m.Id), Error: &m.Error} + rtmp := &Response{ServiceMethod: &m.Endpoint, Seq: id(m.Id), Error: &m.Error} data, err := proto.Marshal(rtmp) if err != nil { return err @@ -126,7 +126,7 @@ func (c *protoCodec) ReadHeader(m *codec.Message, mt codec.MessageType) error { if err != nil { return err } - m.Method = rtmp.GetServiceMethod() + m.Endpoint = rtmp.GetServiceMethod() m.Id = fmt.Sprintf("%d", rtmp.GetSeq()) case codec.Response: data, err := ReadNetString(c.rwc) @@ -138,7 +138,7 @@ func (c *protoCodec) ReadHeader(m *codec.Message, mt codec.MessageType) error { if err != nil { return err } - m.Method = rtmp.GetServiceMethod() + m.Endpoint = rtmp.GetServiceMethod() m.Id = fmt.Sprintf("%d", rtmp.GetSeq()) m.Error = rtmp.GetError() case codec.Publication: diff --git a/server/rpc_codec.go b/server/rpc_codec.go index abceda03..b229ba11 100644 --- a/server/rpc_codec.go +++ b/server/rpc_codec.go @@ -106,14 +106,14 @@ func (c *rpcCodec) ReadHeader(r *codec.Message, t codec.MessageType) error { // set some internal things m.Target = m.Header["X-Micro-Service"] - m.Method = m.Header["X-Micro-Method"] + m.Endpoint = m.Header["X-Micro-Endpoint"] m.Id = m.Header["X-Micro-Id"] // read header via codec err := c.codec.ReadHeader(&m, codec.Request) // set the method/id - r.Method = m.Method + r.Endpoint = m.Endpoint r.Id = m.Id return err @@ -128,15 +128,15 @@ func (c *rpcCodec) Write(r *codec.Message, b interface{}) error { // create a new message m := &codec.Message{ - Method: r.Method, - Id: r.Id, - Error: r.Error, - Type: r.Type, + Endpoint: r.Endpoint, + Id: r.Id, + Error: r.Error, + Type: r.Type, Header: map[string]string{ - "X-Micro-Id": r.Id, - "X-Micro-Method": r.Method, - "X-Micro-Error": r.Error, - "Content-Type": c.req.Header["Content-Type"], + "X-Micro-Id": r.Id, + "X-Micro-Endpoint": r.Endpoint, + "X-Micro-Error": r.Error, + "Content-Type": c.req.Header["Content-Type"], }, } diff --git a/server/rpc_codec_test.go b/server/rpc_codec_test.go index 59035e3e..1088af01 100644 --- a/server/rpc_codec_test.go +++ b/server/rpc_codec_test.go @@ -48,9 +48,9 @@ func TestCodecWriteError(t *testing.T) { } err := c.Write(&codec.Message{ - Method: "Service.Method", - Id: "0", - Error: "", + Endpoint: "Service.Endpoint", + Id: "0", + Error: "", }, "body") if err != nil { diff --git a/server/rpc_request.go b/server/rpc_request.go index cbc4179d..17ede91b 100644 --- a/server/rpc_request.go +++ b/server/rpc_request.go @@ -7,7 +7,7 @@ import ( type rpcRequest struct { service string - method string + endpoint string contentType string socket transport.Socket codec codec.Codec @@ -34,8 +34,8 @@ func (r *rpcRequest) Service() string { return r.service } -func (r *rpcRequest) Method() string { - return r.method +func (r *rpcRequest) Endpoint() string { + return r.endpoint } func (r *rpcRequest) Header() map[string]string { diff --git a/server/rpc_router.go b/server/rpc_router.go index 1043036b..782fb55b 100644 --- a/server/rpc_router.go +++ b/server/rpc_router.go @@ -171,7 +171,7 @@ func (router *router) sendResponse(sending sync.Locker, req *request, reply inte resp.msg = msg // Encode the response header - resp.msg.Method = req.msg.Method + resp.msg.Endpoint = req.msg.Endpoint if errmsg != "" { resp.msg.Error = errmsg reply = invalidRequest @@ -191,7 +191,7 @@ func (s *service) call(ctx context.Context, router *router, sending *sync.Mutex, r := &rpcRequest{ service: req.msg.Target, contentType: req.msg.Header["Content-Type"], - method: req.msg.Method, + endpoint: req.msg.Endpoint, body: req.msg.Body, } @@ -379,9 +379,9 @@ func (router *router) readHeader(cc codec.Reader) (service *service, mtype *meth // we can still recover and move on to the next request. keepReading = true - serviceMethod := strings.Split(req.msg.Method, ".") + serviceMethod := strings.Split(req.msg.Endpoint, ".") if len(serviceMethod) != 2 { - err = errors.New("rpc: service/method request ill-formed: " + req.msg.Method) + err = errors.New("rpc: service/method request ill-formed: " + req.msg.Endpoint) return } // Look up the request. @@ -389,12 +389,12 @@ func (router *router) readHeader(cc codec.Reader) (service *service, mtype *meth service = router.serviceMap[serviceMethod[0]] router.mu.Unlock() if service == nil { - err = errors.New("rpc: can't find service " + req.msg.Method) + err = errors.New("rpc: can't find service " + req.msg.Endpoint) return } mtype = service.method[serviceMethod[1]] if mtype == nil { - err = errors.New("rpc: can't find method " + req.msg.Method) + err = errors.New("rpc: can't find method " + req.msg.Endpoint) } return } diff --git a/server/rpc_server.go b/server/rpc_server.go index 4481d9bb..c1510905 100644 --- a/server/rpc_server.go +++ b/server/rpc_server.go @@ -115,7 +115,7 @@ func (s *rpcServer) ServeConn(sock transport.Socket) { // internal request request := &rpcRequest{ service: msg.Header["X-Micro-Service"], - method: msg.Header["X-Micro-Method"], + endpoint: msg.Header["X-Micro-Endpoint"], contentType: ct, codec: codec, header: msg.Header, diff --git a/server/rpc_stream.go b/server/rpc_stream.go index efbf0d55..2f74049a 100644 --- a/server/rpc_stream.go +++ b/server/rpc_stream.go @@ -31,9 +31,9 @@ func (r *rpcStream) Send(msg interface{}) error { defer r.Unlock() resp := codec.Message{ - Method: r.request.Method(), - Id: r.id, - Type: codec.Response, + Endpoint: r.request.Endpoint(), + Id: r.id, + Type: codec.Response, } return r.codec.Write(&resp, msg) diff --git a/server/server.go b/server/server.go index fbfacd0d..b4ddcaa9 100644 --- a/server/server.go +++ b/server/server.go @@ -45,8 +45,8 @@ type Message interface { type Request interface { // Service name requested Service() string - // Method name requested - Method() string + // Endpoint name requested + Endpoint() string // Content type provided ContentType() string // Header of the request @@ -83,7 +83,7 @@ type Stream interface { } // Handler interface represents a request handler. It's generated -// by passing any type of public concrete object with methods into server.NewHandler. +// by passing any type of public concrete object with endpoints into server.NewHandler. // Most will pass in a struct. // // Example: @@ -102,7 +102,7 @@ type Handler interface { } // Subscriber interface represents a subscription to a given topic using -// a specific subscriber function or object with methods. +// a specific subscriber function or object with endpoints. type Subscriber interface { Topic() string Subscriber() interface{} @@ -151,7 +151,7 @@ func NewSubscriber(topic string, h interface{}, opts ...SubscriberOption) Subscr // NewHandler creates a new handler interface using the default server // Handlers are required to be a public object with public -// methods. Call to a service method such as Foo.Bar expects +// endpoints. Call to a service endpoint such as Foo.Bar expects // the type: // // type Foo struct {} From 3043841cf5297feec41f050ccf1e8476f7f852ea Mon Sep 17 00:00:00 2001 From: Asim Aslam Date: Thu, 10 Jan 2019 22:14:32 +0000 Subject: [PATCH 104/196] Don't process nil --- codec/json/json.go | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/codec/json/json.go b/codec/json/json.go index 6389541c..42de4a4d 100644 --- a/codec/json/json.go +++ b/codec/json/json.go @@ -19,10 +19,16 @@ func (c *Codec) ReadHeader(m *codec.Message, t codec.MessageType) error { } func (c *Codec) ReadBody(b interface{}) error { + if b == nil { + return nil + } return c.Decoder.Decode(b) } func (c *Codec) Write(m *codec.Message, b interface{}) error { + if b == nil { + return nil + } return c.Encoder.Encode(b) } From 36788487a76b9ace04d334f68f18d5cf82b8a7a3 Mon Sep 17 00:00:00 2001 From: Asim Aslam Date: Fri, 11 Jan 2019 13:44:47 +0000 Subject: [PATCH 105/196] set headers as appropriate --- server/rpc_codec.go | 31 +++++++++++++++++++++++++------ server/rpc_router.go | 6 +++--- 2 files changed, 28 insertions(+), 9 deletions(-) diff --git a/server/rpc_codec.go b/server/rpc_codec.go index b229ba11..82a8a45f 100644 --- a/server/rpc_codec.go +++ b/server/rpc_codec.go @@ -132,12 +132,26 @@ func (c *rpcCodec) Write(r *codec.Message, b interface{}) error { Id: r.Id, Error: r.Error, Type: r.Type, - Header: map[string]string{ - "X-Micro-Id": r.Id, - "X-Micro-Endpoint": r.Endpoint, - "X-Micro-Error": r.Error, - "Content-Type": c.req.Header["Content-Type"], - }, + Header: map[string]string{}, + } + + // set request id + if len(r.Id) > 0 { + m.Header["X-Micro-Id"] = r.Id + } + + // set target + if len(r.Target) > 0 { + m.Header["X-Micro-Service"] = r.Target + } + + // set request endpoint + if len(r.Endpoint) > 0 { + m.Header["X-Micro-Endpoint"] = r.Endpoint + } + + if len(r.Error) > 0 { + m.Header["X-Micro-Error"] = r.Error } // the body being sent @@ -163,6 +177,11 @@ func (c *rpcCodec) Write(r *codec.Message, b interface{}) error { body = c.buf.wbuf.Bytes() } + // Set content type if theres content + if len(body) > 0 { + m.Header["Content-Type"] = c.req.Header["Content-Type"] + } + // send on the socket return c.socket.Send(&transport.Message{ Header: m.Header, diff --git a/server/rpc_router.go b/server/rpc_router.go index 782fb55b..4d27fee6 100644 --- a/server/rpc_router.go +++ b/server/rpc_router.go @@ -381,7 +381,7 @@ func (router *router) readHeader(cc codec.Reader) (service *service, mtype *meth serviceMethod := strings.Split(req.msg.Endpoint, ".") if len(serviceMethod) != 2 { - err = errors.New("rpc: service/method request ill-formed: " + req.msg.Endpoint) + err = errors.New("rpc: service/endpoint request ill-formed: " + req.msg.Endpoint) return } // Look up the request. @@ -389,12 +389,12 @@ func (router *router) readHeader(cc codec.Reader) (service *service, mtype *meth service = router.serviceMap[serviceMethod[0]] router.mu.Unlock() if service == nil { - err = errors.New("rpc: can't find service " + req.msg.Endpoint) + err = errors.New("rpc: can't find service " + serviceMethod[0]) return } mtype = service.method[serviceMethod[1]] if mtype == nil { - err = errors.New("rpc: can't find method " + req.msg.Endpoint) + err = errors.New("rpc: can't find method " + serviceMethod[1]) } return } From 9897c630ae2f326714331ddf8cd7497e83f72a6b Mon Sep 17 00:00:00 2001 From: Asim Aslam Date: Fri, 11 Jan 2019 14:04:37 +0000 Subject: [PATCH 106/196] remove request/response --- client/rpc_codec.go | 14 -------------- 1 file changed, 14 deletions(-) diff --git a/client/rpc_codec.go b/client/rpc_codec.go index aaa01569..647d044b 100644 --- a/client/rpc_codec.go +++ b/client/rpc_codec.go @@ -44,20 +44,6 @@ type readWriteCloser struct { rbuf *bytes.Buffer } -type request struct { - Service string - ServiceMethod string // format: "Service.Method" - Seq string // sequence number chosen by client - next *request // for free list in Server -} - -type response struct { - ServiceMethod string // echoes that of the Request - Seq string // echoes that of the request - Error string // error, if any. - next *response // for free list in Server -} - var ( DefaultContentType = "application/protobuf" From bfd341a26923a17d8e1e28676c4e080e4470b94c Mon Sep 17 00:00:00 2001 From: Asim Aslam Date: Fri, 11 Jan 2019 15:49:54 +0000 Subject: [PATCH 107/196] Execute wrappers before router --- server/rpc_router.go | 14 ++------------ server/rpc_server.go | 21 +++++++++++++++++---- server/server.go | 2 +- server/subscriber.go | 14 +++++++++++++- 4 files changed, 33 insertions(+), 18 deletions(-) diff --git a/server/rpc_router.go b/server/rpc_router.go index 4d27fee6..dee976e8 100644 --- a/server/rpc_router.go +++ b/server/rpc_router.go @@ -70,11 +70,9 @@ type router struct { hdlrWrappers []HandlerWrapper } -func newRpcRouter(opts Options) *router { +func newRpcRouter() *router { return &router{ - name: opts.Name, - hdlrWrappers: opts.HdlrWrappers, - serviceMap: make(map[string]*service), + serviceMap: make(map[string]*service), } } @@ -207,10 +205,6 @@ func (s *service) call(ctx context.Context, router *router, sending *sync.Mutex, return nil } - for i := len(router.hdlrWrappers); i > 0; i-- { - fn = router.hdlrWrappers[i-1](fn) - } - errmsg := "" err := fn(ctx, r, replyv.Interface()) if err != nil { @@ -252,10 +246,6 @@ func (s *service) call(ctx context.Context, router *router, sending *sync.Mutex, } } - for i := len(router.hdlrWrappers); i > 0; i-- { - fn = router.hdlrWrappers[i-1](fn) - } - // client.Stream request r.stream = true diff --git a/server/rpc_server.go b/server/rpc_server.go index c1510905..cd7a5edb 100644 --- a/server/rpc_server.go +++ b/server/rpc_server.go @@ -38,7 +38,7 @@ func newRpcServer(opts ...Option) Server { options := newOptions(opts...) return &rpcServer{ opts: options, - router: newRpcRouter(options), + router: newRpcRouter(), handlers: make(map[string]Handler), subscribers: make(map[*subscriber][]broker.Subscriber), exit: make(chan chan error), @@ -133,16 +133,29 @@ func (s *rpcServer) ServeConn(sock transport.Socket) { // set router r := s.opts.Router + + // if nil use default router if s.opts.Router == nil { r = s.router } - // TODO: needs better error handling - if err := r.ServeRequest(ctx, request, response); err != nil { + // create a wrapped function + handler := func(ctx context.Context, req Request, rsp interface{}) error { + return r.ServeRequest(ctx, req, rsp.(Response)) + } + + for i := len(s.opts.HdlrWrappers); i > 0; i-- { + handler = s.opts.HdlrWrappers[i-1](handler) + } + + // TODO: handle error better + if err := handler(ctx, request, response); err != nil { s.wg.Done() log.Logf("Unexpected error serving request, closing socket: %v", err) return } + + // done s.wg.Done() } } @@ -171,7 +184,7 @@ func (s *rpcServer) Init(opts ...Option) error { } // update router - r := newRpcRouter(s.opts) + r := newRpcRouter() r.serviceMap = s.router.serviceMap s.router = r diff --git a/server/server.go b/server/server.go index b4ddcaa9..6f7c2712 100644 --- a/server/server.go +++ b/server/server.go @@ -122,7 +122,7 @@ var ( DefaultVersion = "1.0.0" DefaultId = uuid.New().String() DefaultServer Server = newRpcServer() - DefaultRouter = newRpcRouter(newOptions()) + DefaultRouter = newRpcRouter() ) // DefaultOptions returns config options for the default service diff --git a/server/subscriber.go b/server/subscriber.go index 9f2100c5..a02bc222 100644 --- a/server/subscriber.go +++ b/server/subscriber.go @@ -164,17 +164,29 @@ func validateSubscriber(sub Subscriber) error { func (s *rpcServer) createSubHandler(sb *subscriber, opts Options) broker.Handler { return func(p broker.Publication) error { msg := p.Message() + + // get codec ct := msg.Header["Content-Type"] + + // default content type + if len(ct) == 0 { + msg.Header["Content-Type"] = DefaultContentType + ct = DefaultContentType + } + + // get codec cf, err := s.newCodec(ct) if err != nil { return err } + // copy headers hdr := make(map[string]string) for k, v := range msg.Header { hdr[k] = v } - delete(hdr, "Content-Type") + + // create context ctx := metadata.NewContext(context.Background(), hdr) results := make(chan error, len(sb.handlers)) From 01f6683035362f055d6240d97926d29df2d757ab Mon Sep 17 00:00:00 2001 From: Asim Aslam Date: Sun, 13 Jan 2019 12:15:13 +0000 Subject: [PATCH 108/196] Add router option --- client/options.go | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/client/options.go b/client/options.go index aa65381e..dca251c6 100644 --- a/client/options.go +++ b/client/options.go @@ -22,6 +22,9 @@ type Options struct { Selector selector.Selector Transport transport.Transport + // Router sets the router + Router Router + // Connection Pool PoolSize int PoolTTL time.Duration @@ -306,3 +309,10 @@ func StreamingRequest() RequestOption { o.Stream = true } } + +// WithRouter sets the client router +func WithRouter(r Router) Option { + return func(o *Options) { + o.Router = r + } +} From e1bc240a140bb19489f0afcb2ffbe7f4ae992c70 Mon Sep 17 00:00:00 2001 From: Asim Aslam Date: Sun, 13 Jan 2019 12:15:35 +0000 Subject: [PATCH 109/196] Respond with error type --- codec/jsonrpc/jsonrpc.go | 2 +- codec/protorpc/protorpc.go | 2 +- server/rpc_server.go | 14 ++++++++++---- transport/http_transport.go | 3 --- 4 files changed, 12 insertions(+), 9 deletions(-) diff --git a/codec/jsonrpc/jsonrpc.go b/codec/jsonrpc/jsonrpc.go index 9f9cd6a2..8f0c2c4f 100644 --- a/codec/jsonrpc/jsonrpc.go +++ b/codec/jsonrpc/jsonrpc.go @@ -31,7 +31,7 @@ func (j *jsonCodec) Write(m *codec.Message, b interface{}) error { switch m.Type { case codec.Request: return j.c.Write(m, b) - case codec.Response: + case codec.Response, codec.Error: return j.s.Write(m, b) case codec.Publication: data, err := json.Marshal(b) diff --git a/codec/protorpc/protorpc.go b/codec/protorpc/protorpc.go index a7d8ba79..f207e5ae 100644 --- a/codec/protorpc/protorpc.go +++ b/codec/protorpc/protorpc.go @@ -70,7 +70,7 @@ func (c *protoCodec) Write(m *codec.Message, b interface{}) error { return err } } - case codec.Response: + case codec.Response, codec.Error: c.Lock() defer c.Unlock() rtmp := &Response{ServiceMethod: &m.Endpoint, Seq: id(m.Id), Error: &m.Error} diff --git a/server/rpc_server.go b/server/rpc_server.go index cd7a5edb..93b49d4d 100644 --- a/server/rpc_server.go +++ b/server/rpc_server.go @@ -110,14 +110,14 @@ func (s *rpcServer) ServeConn(sock transport.Socket) { return } - codec := newRpcCodec(&msg, sock, cf) + rcodec := newRpcCodec(&msg, sock, cf) // internal request request := &rpcRequest{ service: msg.Header["X-Micro-Service"], endpoint: msg.Header["X-Micro-Endpoint"], contentType: ct, - codec: codec, + codec: rcodec, header: msg.Header, body: msg.Body, socket: sock, @@ -128,7 +128,7 @@ func (s *rpcServer) ServeConn(sock transport.Socket) { response := &rpcResponse{ header: make(map[string]string), socket: sock, - codec: codec, + codec: rcodec, } // set router @@ -150,8 +150,14 @@ func (s *rpcServer) ServeConn(sock transport.Socket) { // TODO: handle error better if err := handler(ctx, request, response); err != nil { + // write an error response + rcodec.Write(&codec.Message{ + Header: msg.Header, + Error: err.Error(), + Type: codec.Error, + }, nil) + s.wg.Done() - log.Logf("Unexpected error serving request, closing socket: %v", err) return } diff --git a/transport/http_transport.go b/transport/http_transport.go index 885459aa..154448da 100644 --- a/transport/http_transport.go +++ b/transport/http_transport.go @@ -245,9 +245,6 @@ func (h *httpTransportSocket) Recv(m *Message) error { } } - // set path - m.Header[":path"] = h.r.URL.Path - // return early early return nil } From c17d0fcc0f5d4f06b953f42202b2818dc692303c Mon Sep 17 00:00:00 2001 From: Asim Aslam Date: Sun, 13 Jan 2019 19:54:07 +0000 Subject: [PATCH 110/196] grpc request --- client/rpc_codec.go | 4 ++++ codec/grpc/grpc.go | 23 ++++++++++++++++++----- server/rpc_server.go | 4 ++-- 3 files changed, 24 insertions(+), 7 deletions(-) diff --git a/client/rpc_codec.go b/client/rpc_codec.go index 647d044b..a7e9dada 100644 --- a/client/rpc_codec.go +++ b/client/rpc_codec.go @@ -6,6 +6,7 @@ import ( "github.com/micro/go-micro/codec" raw "github.com/micro/go-micro/codec/bytes" + "github.com/micro/go-micro/codec/grpc" "github.com/micro/go-micro/codec/json" "github.com/micro/go-micro/codec/jsonrpc" "github.com/micro/go-micro/codec/proto" @@ -48,6 +49,9 @@ var ( DefaultContentType = "application/protobuf" DefaultCodecs = map[string]codec.NewCodec{ + "application/grpc": grpc.NewCodec, + "application/grpc+json": grpc.NewCodec, + "application/grpc+proto": grpc.NewCodec, "application/protobuf": proto.NewCodec, "application/json": json.NewCodec, "application/json-rpc": jsonrpc.NewCodec, diff --git a/codec/grpc/grpc.go b/codec/grpc/grpc.go index 79c30f4b..732f0356 100644 --- a/codec/grpc/grpc.go +++ b/codec/grpc/grpc.go @@ -4,6 +4,7 @@ package grpc import ( "encoding/json" "errors" + "fmt" "io" "strings" @@ -77,8 +78,23 @@ func (c *Codec) Write(m *codec.Message, b interface{}) error { c.ContentType = ct } - m.Header["Trailer"] = "grpc-status, grpc-message" + switch m.Type { + case codec.Request: + parts := strings.Split(m.Endpoint, ".") + m.Header[":method"] = "POST" + m.Header[":path"] = fmt.Sprintf("/%s.%s/%s", m.Target, parts[0], parts[1]) + m.Header[":proto"] = "HTTP/2.0" + m.Header["te"] = "trailers" + m.Header["user-agent"] = "grpc-go/1.0.0" + m.Header[":authority"] = m.Target + m.Header["content-type"] = c.ContentType + case codec.Response: + m.Header["Trailer"] = "grpc-status, grpc-message" + m.Header["grpc-status"] = "0" + m.Header["grpc-message"] = "" + } + // marshal content switch c.ContentType { case "application/grpc+json": buf, err = json.Marshal(b) @@ -90,16 +106,13 @@ func (c *Codec) Write(m *codec.Message, b interface{}) error { default: err = errors.New("Unsupported Content-Type") } - + // check error if err != nil { m.Header["grpc-status"] = "8" m.Header["grpc-message"] = err.Error() return err } - m.Header["grpc-status"] = "0" - m.Header["grpc-message"] = "" - return encode(0, buf, c.Conn) } diff --git a/server/rpc_server.go b/server/rpc_server.go index 93b49d4d..d02e8421 100644 --- a/server/rpc_server.go +++ b/server/rpc_server.go @@ -153,8 +153,8 @@ func (s *rpcServer) ServeConn(sock transport.Socket) { // write an error response rcodec.Write(&codec.Message{ Header: msg.Header, - Error: err.Error(), - Type: codec.Error, + Error: err.Error(), + Type: codec.Error, }, nil) s.wg.Done() From 39c24baca9bb9961c110293fcdd1c0511ad0b4b0 Mon Sep 17 00:00:00 2001 From: Asim Aslam Date: Mon, 14 Jan 2019 15:27:25 +0000 Subject: [PATCH 111/196] rename mock things to memory --- broker/http_broker_test.go | 20 ++++-- broker/{mock/mock.go => memory/memory.go} | 52 ++++++++-------- .../mock_test.go => memory/memory_test.go} | 4 +- client/rpc_client_test.go | 14 +++-- client/rpc_pool_test.go | 4 +- cmd/cmd.go | 10 ++- function_test.go | 7 ++- registry/{mock => memory}/helper.go | 2 +- registry/{mock => memory}/helper_test.go | 2 +- registry/{mock/mock.go => memory/memory.go} | 44 ++++++------- .../mock_test.go => memory/memory_test.go} | 7 ++- .../memory_watcher.go} | 8 +-- selector/default_test.go | 6 +- service_test.go | 7 ++- transport/{mock/mock.go => memory/memory.go} | 61 ++++++++++--------- .../mock_test.go => memory/memory_test.go} | 4 +- 16 files changed, 142 insertions(+), 110 deletions(-) rename broker/{mock/mock.go => memory/memory.go} (59%) rename broker/{mock/mock_test.go => memory/memory_test.go} (94%) rename registry/{mock => memory}/helper.go (98%) rename registry/{mock => memory}/helper_test.go (98%) rename registry/{mock/mock.go => memory/memory.go} (61%) rename registry/{mock/mock_test.go => memory/memory_test.go} (96%) rename registry/{mock/mock_watcher.go => memory/memory_watcher.go} (68%) rename transport/{mock/mock.go => memory/memory.go} (66%) rename transport/{mock/mock_test.go => memory/memory_test.go} (96%) diff --git a/broker/http_broker_test.go b/broker/http_broker_test.go index e987835d..fad91311 100644 --- a/broker/http_broker_test.go +++ b/broker/http_broker_test.go @@ -6,12 +6,20 @@ import ( "time" "github.com/google/uuid" - "github.com/micro/go-micro/registry/mock" + "github.com/micro/go-micro/registry/memory" ) +func newTestRegistry() *memory.Registry { + r := memory.NewRegistry() + m := r.(*memory.Registry) + m.Setup() + return m +} + func sub(be *testing.B, c int) { be.StopTimer() - m := mock.NewRegistry() + m := newTestRegistry() + b := NewBroker(Registry(m)) topic := uuid.New().String() @@ -70,7 +78,7 @@ func sub(be *testing.B, c int) { func pub(be *testing.B, c int) { be.StopTimer() - m := mock.NewRegistry() + m := newTestRegistry() b := NewBroker(Registry(m)) topic := uuid.New().String() @@ -139,7 +147,7 @@ func pub(be *testing.B, c int) { } func TestBroker(t *testing.T) { - m := mock.NewRegistry() + m := newTestRegistry() b := NewBroker(Registry(m)) if err := b.Init(); err != nil { @@ -186,7 +194,7 @@ func TestBroker(t *testing.T) { } func TestConcurrentSubBroker(t *testing.T) { - m := mock.NewRegistry() + m := newTestRegistry() b := NewBroker(Registry(m)) if err := b.Init(); err != nil { @@ -243,7 +251,7 @@ func TestConcurrentSubBroker(t *testing.T) { } func TestConcurrentPubBroker(t *testing.T) { - m := mock.NewRegistry() + m := newTestRegistry() b := NewBroker(Registry(m)) if err := b.Init(); err != nil { diff --git a/broker/mock/mock.go b/broker/memory/memory.go similarity index 59% rename from broker/mock/mock.go rename to broker/memory/memory.go index 76c80e5a..7446bb21 100644 --- a/broker/mock/mock.go +++ b/broker/memory/memory.go @@ -1,5 +1,5 @@ -// Package mock provides a mock broker for testing -package mock +// Package memory provides a memory broker +package memory import ( "errors" @@ -9,20 +9,20 @@ import ( "github.com/micro/go-micro/broker" ) -type mockBroker struct { +type memoryBroker struct { opts broker.Options sync.RWMutex connected bool - Subscribers map[string][]*mockSubscriber + Subscribers map[string][]*memorySubscriber } -type mockPublication struct { +type memoryPublication struct { topic string message *broker.Message } -type mockSubscriber struct { +type memorySubscriber struct { id string topic string exit chan bool @@ -30,15 +30,15 @@ type mockSubscriber struct { opts broker.SubscribeOptions } -func (m *mockBroker) Options() broker.Options { +func (m *memoryBroker) Options() broker.Options { return m.opts } -func (m *mockBroker) Address() string { +func (m *memoryBroker) Address() string { return "" } -func (m *mockBroker) Connect() error { +func (m *memoryBroker) Connect() error { m.Lock() defer m.Unlock() @@ -51,7 +51,7 @@ func (m *mockBroker) Connect() error { return nil } -func (m *mockBroker) Disconnect() error { +func (m *memoryBroker) Disconnect() error { m.Lock() defer m.Unlock() @@ -64,14 +64,14 @@ func (m *mockBroker) Disconnect() error { return nil } -func (m *mockBroker) Init(opts ...broker.Option) error { +func (m *memoryBroker) Init(opts ...broker.Option) error { for _, o := range opts { o(&m.opts) } return nil } -func (m *mockBroker) Publish(topic string, message *broker.Message, opts ...broker.PublishOption) error { +func (m *memoryBroker) Publish(topic string, message *broker.Message, opts ...broker.PublishOption) error { m.Lock() defer m.Unlock() @@ -84,7 +84,7 @@ func (m *mockBroker) Publish(topic string, message *broker.Message, opts ...brok return nil } - p := &mockPublication{ + p := &memoryPublication{ topic: topic, message: message, } @@ -98,7 +98,7 @@ func (m *mockBroker) Publish(topic string, message *broker.Message, opts ...brok return nil } -func (m *mockBroker) Subscribe(topic string, handler broker.Handler, opts ...broker.SubscribeOption) (broker.Subscriber, error) { +func (m *memoryBroker) Subscribe(topic string, handler broker.Handler, opts ...broker.SubscribeOption) (broker.Subscriber, error) { m.Lock() defer m.Unlock() @@ -111,7 +111,7 @@ func (m *mockBroker) Subscribe(topic string, handler broker.Handler, opts ...bro o(&options) } - sub := &mockSubscriber{ + sub := &memorySubscriber{ exit: make(chan bool, 1), id: uuid.New().String(), topic: topic, @@ -124,7 +124,7 @@ func (m *mockBroker) Subscribe(topic string, handler broker.Handler, opts ...bro go func() { <-sub.exit m.Lock() - var newSubscribers []*mockSubscriber + var newSubscribers []*memorySubscriber for _, sb := range m.Subscribers[topic] { if sb.id == sub.id { continue @@ -138,31 +138,31 @@ func (m *mockBroker) Subscribe(topic string, handler broker.Handler, opts ...bro return sub, nil } -func (m *mockBroker) String() string { - return "mock" +func (m *memoryBroker) String() string { + return "memory" } -func (m *mockPublication) Topic() string { +func (m *memoryPublication) Topic() string { return m.topic } -func (m *mockPublication) Message() *broker.Message { +func (m *memoryPublication) Message() *broker.Message { return m.message } -func (m *mockPublication) Ack() error { +func (m *memoryPublication) Ack() error { return nil } -func (m *mockSubscriber) Options() broker.SubscribeOptions { +func (m *memorySubscriber) Options() broker.SubscribeOptions { return m.opts } -func (m *mockSubscriber) Topic() string { +func (m *memorySubscriber) Topic() string { return m.topic } -func (m *mockSubscriber) Unsubscribe() error { +func (m *memorySubscriber) Unsubscribe() error { m.exit <- true return nil } @@ -173,8 +173,8 @@ func NewBroker(opts ...broker.Option) broker.Broker { o(&options) } - return &mockBroker{ + return &memoryBroker{ opts: options, - Subscribers: make(map[string][]*mockSubscriber), + Subscribers: make(map[string][]*memorySubscriber), } } diff --git a/broker/mock/mock_test.go b/broker/memory/memory_test.go similarity index 94% rename from broker/mock/mock_test.go rename to broker/memory/memory_test.go index 16513b40..5c0021b1 100644 --- a/broker/mock/mock_test.go +++ b/broker/memory/memory_test.go @@ -1,4 +1,4 @@ -package mock +package memory import ( "fmt" @@ -7,7 +7,7 @@ import ( "github.com/micro/go-micro/broker" ) -func TestBroker(t *testing.T) { +func TestMemoryBroker(t *testing.T) { b := NewBroker() if err := b.Connect(); err != nil { diff --git a/client/rpc_client_test.go b/client/rpc_client_test.go index 72140711..33b5a493 100644 --- a/client/rpc_client_test.go +++ b/client/rpc_client_test.go @@ -7,10 +7,16 @@ import ( "github.com/micro/go-micro/errors" "github.com/micro/go-micro/registry" - "github.com/micro/go-micro/registry/mock" + "github.com/micro/go-micro/registry/memory" "github.com/micro/go-micro/selector" ) +func newTestRegistry() registry.Registry { + r := memory.NewRegistry() + r.(*memory.Registry).Setup() + return r +} + func TestCallAddress(t *testing.T) { var called bool service := "test.service" @@ -38,7 +44,7 @@ func TestCallAddress(t *testing.T) { } } - r := mock.NewRegistry() + r := newTestRegistry() c := NewClient( Registry(r), WrapCall(wrap), @@ -77,7 +83,7 @@ func TestCallRetry(t *testing.T) { } } - r := mock.NewRegistry() + r := newTestRegistry() c := NewClient( Registry(r), WrapCall(wrap), @@ -127,7 +133,7 @@ func TestCallWrapper(t *testing.T) { } } - r := mock.NewRegistry() + r := newTestRegistry() c := NewClient( Registry(r), WrapCall(wrap), diff --git a/client/rpc_pool_test.go b/client/rpc_pool_test.go index d9fd8931..6c5875f1 100644 --- a/client/rpc_pool_test.go +++ b/client/rpc_pool_test.go @@ -5,7 +5,7 @@ import ( "time" "github.com/micro/go-micro/transport" - "github.com/micro/go-micro/transport/mock" + "github.com/micro/go-micro/transport/memory" ) func testPool(t *testing.T, size int, ttl time.Duration) { @@ -13,7 +13,7 @@ func testPool(t *testing.T, size int, ttl time.Duration) { p := newPool(size, ttl) // mock transport - tr := mock.NewTransport() + tr := memory.NewTransport() // listen l, err := tr.Listen(":0") diff --git a/cmd/cmd.go b/cmd/cmd.go index 7f08ffd7..3ef6ac8e 100644 --- a/cmd/cmd.go +++ b/cmd/cmd.go @@ -17,12 +17,14 @@ import ( // brokers "github.com/micro/go-micro/broker" "github.com/micro/go-micro/broker/http" + "github.com/micro/go-micro/broker/memory" // registries "github.com/micro/go-micro/registry" "github.com/micro/go-micro/registry/consul" "github.com/micro/go-micro/registry/gossip" "github.com/micro/go-micro/registry/mdns" + rmem "github.com/micro/go-micro/registry/memory" // selectors "github.com/micro/go-micro/selector" @@ -32,6 +34,7 @@ import ( // transports "github.com/micro/go-micro/transport" thttp "github.com/micro/go-micro/transport/http" + tmem "github.com/micro/go-micro/transport/memory" ) type Cmd interface { @@ -164,7 +167,8 @@ var ( } DefaultBrokers = map[string]func(...broker.Option) broker.Broker{ - "http": http.NewBroker, + "http": http.NewBroker, + "memory": memory.NewBroker, } DefaultClients = map[string]func(...client.Option) client.Client{ @@ -175,6 +179,7 @@ var ( "consul": consul.NewRegistry, "gossip": gossip.NewRegistry, "mdns": mdns.NewRegistry, + "memory": rmem.NewRegistry, } DefaultSelectors = map[string]func(...selector.Option) selector.Selector{ @@ -189,7 +194,8 @@ var ( } DefaultTransports = map[string]func(...transport.Option) transport.Transport{ - "http": thttp.NewTransport, + "memory": tmem.NewTransport, + "http": thttp.NewTransport, } // used for default selection as the fall back diff --git a/function_test.go b/function_test.go index f2e83733..49454929 100644 --- a/function_test.go +++ b/function_test.go @@ -5,7 +5,7 @@ import ( "sync" "testing" - "github.com/micro/go-micro/registry/mock" + "github.com/micro/go-micro/registry/memory" proto "github.com/micro/go-micro/server/debug/proto" ) @@ -13,9 +13,12 @@ func TestFunction(t *testing.T) { var wg sync.WaitGroup wg.Add(1) + r := memory.NewRegistry() + r.(*memory.Registry).Setup() + // create service fn := NewFunction( - Registry(mock.NewRegistry()), + Registry(r), Name("test.function"), AfterStart(func() error { wg.Done() diff --git a/registry/mock/helper.go b/registry/memory/helper.go similarity index 98% rename from registry/mock/helper.go rename to registry/memory/helper.go index aadb3839..2308dde7 100644 --- a/registry/mock/helper.go +++ b/registry/memory/helper.go @@ -1,4 +1,4 @@ -package mock +package memory import ( "github.com/micro/go-micro/registry" diff --git a/registry/mock/helper_test.go b/registry/memory/helper_test.go similarity index 98% rename from registry/mock/helper_test.go rename to registry/memory/helper_test.go index a9571d1a..f19d1c52 100644 --- a/registry/mock/helper_test.go +++ b/registry/memory/helper_test.go @@ -1,4 +1,4 @@ -package mock +package memory import ( "testing" diff --git a/registry/mock/mock.go b/registry/memory/memory.go similarity index 61% rename from registry/mock/mock.go rename to registry/memory/memory.go index 6b193ad6..f516720a 100644 --- a/registry/mock/mock.go +++ b/registry/memory/memory.go @@ -1,5 +1,5 @@ -// Package mock provides a mock registry for testing -package mock +// Package memory provides an in-memory registry +package memory import ( "sync" @@ -7,13 +7,14 @@ import ( "github.com/micro/go-micro/registry" ) -type mockRegistry struct { +type Registry struct { sync.RWMutex Services map[string][]*registry.Service } var ( - mockData = map[string][]*registry.Service{ + // mock data + Data = map[string][]*registry.Service{ "foo": []*registry.Service{ { Name: "foo", @@ -57,15 +58,16 @@ var ( } ) -func (m *mockRegistry) init() { +// Setup sets mock data +func (m *Registry) Setup() { m.Lock() defer m.Unlock() - // add some mock data - m.Services = mockData + // add some memory data + m.Services = Data } -func (m *mockRegistry) GetService(service string) ([]*registry.Service, error) { +func (m *Registry) GetService(service string) ([]*registry.Service, error) { m.Lock() defer m.Unlock() @@ -77,7 +79,7 @@ func (m *mockRegistry) GetService(service string) ([]*registry.Service, error) { } -func (m *mockRegistry) ListServices() ([]*registry.Service, error) { +func (m *Registry) ListServices() ([]*registry.Service, error) { m.Lock() defer m.Unlock() @@ -88,7 +90,7 @@ func (m *mockRegistry) ListServices() ([]*registry.Service, error) { return services, nil } -func (m *mockRegistry) Register(s *registry.Service, opts ...registry.RegisterOption) error { +func (m *Registry) Register(s *registry.Service, opts ...registry.RegisterOption) error { m.Lock() defer m.Unlock() @@ -97,7 +99,7 @@ func (m *mockRegistry) Register(s *registry.Service, opts ...registry.RegisterOp return nil } -func (m *mockRegistry) Deregister(s *registry.Service) error { +func (m *Registry) Deregister(s *registry.Service) error { m.Lock() defer m.Unlock() @@ -106,28 +108,28 @@ func (m *mockRegistry) Deregister(s *registry.Service) error { return nil } -func (m *mockRegistry) Watch(opts ...registry.WatchOption) (registry.Watcher, error) { +func (m *Registry) Watch(opts ...registry.WatchOption) (registry.Watcher, error) { var wopts registry.WatchOptions for _, o := range opts { o(&wopts) } - return &mockWatcher{exit: make(chan bool), opts: wopts}, nil + return &memoryWatcher{exit: make(chan bool), opts: wopts}, nil } -func (m *mockRegistry) String() string { - return "mock" +func (m *Registry) String() string { + return "memory" } -func (m *mockRegistry) Init(opts ...registry.Option) error { +func (m *Registry) Init(opts ...registry.Option) error { return nil } -func (m *mockRegistry) Options() registry.Options { +func (m *Registry) Options() registry.Options { return registry.Options{} } -func NewRegistry(opts ...registry.Options) registry.Registry { - m := &mockRegistry{Services: make(map[string][]*registry.Service)} - m.init() - return m +func NewRegistry(opts ...registry.Option) registry.Registry { + return &Registry{ + Services: make(map[string][]*registry.Service), + } } diff --git a/registry/mock/mock_test.go b/registry/memory/memory_test.go similarity index 96% rename from registry/mock/mock_test.go rename to registry/memory/memory_test.go index 212599d7..2eb21009 100644 --- a/registry/mock/mock_test.go +++ b/registry/memory/memory_test.go @@ -1,4 +1,4 @@ -package mock +package memory import ( "testing" @@ -82,6 +82,7 @@ var ( func TestMockRegistry(t *testing.T) { m := NewRegistry() + m.(*Registry).Setup() fn := func(k string, v []*registry.Service) { services, err := m.GetService(k) @@ -107,8 +108,8 @@ func TestMockRegistry(t *testing.T) { } } - // test existing mock data - for k, v := range mockData { + // test existing memory data + for k, v := range Data { fn(k, v) } diff --git a/registry/mock/mock_watcher.go b/registry/memory/memory_watcher.go similarity index 68% rename from registry/mock/mock_watcher.go rename to registry/memory/memory_watcher.go index 11e3a881..3ec2071b 100644 --- a/registry/mock/mock_watcher.go +++ b/registry/memory/memory_watcher.go @@ -1,4 +1,4 @@ -package mock +package memory import ( "errors" @@ -6,12 +6,12 @@ import ( "github.com/micro/go-micro/registry" ) -type mockWatcher struct { +type memoryWatcher struct { exit chan bool opts registry.WatchOptions } -func (m *mockWatcher) Next() (*registry.Result, error) { +func (m *memoryWatcher) Next() (*registry.Result, error) { // not implement so we just block until exit select { case <-m.exit: @@ -19,7 +19,7 @@ func (m *mockWatcher) Next() (*registry.Result, error) { } } -func (m *mockWatcher) Stop() { +func (m *memoryWatcher) Stop() { select { case <-m.exit: return diff --git a/selector/default_test.go b/selector/default_test.go index 68d5c850..53f8859d 100644 --- a/selector/default_test.go +++ b/selector/default_test.go @@ -3,13 +3,15 @@ package selector import ( "testing" - "github.com/micro/go-micro/registry/mock" + "github.com/micro/go-micro/registry/memory" ) func TestRegistrySelector(t *testing.T) { counts := map[string]int{} - cache := NewSelector(Registry(mock.NewRegistry())) + r := memory.NewRegistry() + r.(*memory.Registry).Setup() + cache := NewSelector(Registry(r)) next, err := cache.Select("foo") if err != nil { diff --git a/service_test.go b/service_test.go index 047f5d31..db4d8c42 100644 --- a/service_test.go +++ b/service_test.go @@ -5,7 +5,7 @@ import ( "sync" "testing" - "github.com/micro/go-micro/registry/mock" + "github.com/micro/go-micro/registry/memory" proto "github.com/micro/go-micro/server/debug/proto" ) @@ -16,11 +16,14 @@ func TestService(t *testing.T) { // cancellation context ctx, cancel := context.WithCancel(context.Background()) + r := memory.NewRegistry() + r.(*memory.Registry).Setup() + // create service service := NewService( Name("test.service"), Context(ctx), - Registry(mock.NewRegistry()), + Registry(r), AfterStart(func() error { wg.Done() return nil diff --git a/transport/mock/mock.go b/transport/memory/memory.go similarity index 66% rename from transport/mock/mock.go rename to transport/memory/memory.go index c522c1cd..ed00ce69 100644 --- a/transport/mock/mock.go +++ b/transport/memory/memory.go @@ -1,4 +1,5 @@ -package mock +// Package memory is an in-memory transport +package memory import ( "errors" @@ -11,7 +12,7 @@ import ( "github.com/micro/go-micro/transport" ) -type mockSocket struct { +type memorySocket struct { recv chan *transport.Message send chan *transport.Message // sock exit @@ -23,26 +24,26 @@ type mockSocket struct { remote string } -type mockClient struct { - *mockSocket +type memoryClient struct { + *memorySocket opts transport.DialOptions } -type mockListener struct { +type memoryListener struct { addr string exit chan bool - conn chan *mockSocket + conn chan *memorySocket opts transport.ListenOptions } -type mockTransport struct { +type memoryTransport struct { opts transport.Options sync.Mutex - listeners map[string]*mockListener + listeners map[string]*memoryListener } -func (ms *mockSocket) Recv(m *transport.Message) error { +func (ms *memorySocket) Recv(m *transport.Message) error { select { case <-ms.exit: return errors.New("connection closed") @@ -54,15 +55,15 @@ func (ms *mockSocket) Recv(m *transport.Message) error { return nil } -func (ms *mockSocket) Local() string { +func (ms *memorySocket) Local() string { return ms.local } -func (ms *mockSocket) Remote() string { +func (ms *memorySocket) Remote() string { return ms.remote } -func (ms *mockSocket) Send(m *transport.Message) error { +func (ms *memorySocket) Send(m *transport.Message) error { select { case <-ms.exit: return errors.New("connection closed") @@ -73,7 +74,7 @@ func (ms *mockSocket) Send(m *transport.Message) error { return nil } -func (ms *mockSocket) Close() error { +func (ms *memorySocket) Close() error { select { case <-ms.exit: return nil @@ -83,11 +84,11 @@ func (ms *mockSocket) Close() error { return nil } -func (m *mockListener) Addr() string { +func (m *memoryListener) Addr() string { return m.addr } -func (m *mockListener) Close() error { +func (m *memoryListener) Close() error { select { case <-m.exit: return nil @@ -97,13 +98,13 @@ func (m *mockListener) Close() error { return nil } -func (m *mockListener) Accept(fn func(transport.Socket)) error { +func (m *memoryListener) Accept(fn func(transport.Socket)) error { for { select { case <-m.exit: return nil case c := <-m.conn: - go fn(&mockSocket{ + go fn(&memorySocket{ lexit: c.lexit, exit: c.exit, send: c.recv, @@ -115,7 +116,7 @@ func (m *mockListener) Accept(fn func(transport.Socket)) error { } } -func (m *mockTransport) Dial(addr string, opts ...transport.DialOption) (transport.Client, error) { +func (m *memoryTransport) Dial(addr string, opts ...transport.DialOption) (transport.Client, error) { m.Lock() defer m.Unlock() @@ -129,8 +130,8 @@ func (m *mockTransport) Dial(addr string, opts ...transport.DialOption) (transpo o(&options) } - client := &mockClient{ - &mockSocket{ + client := &memoryClient{ + &memorySocket{ send: make(chan *transport.Message), recv: make(chan *transport.Message), exit: make(chan bool), @@ -145,13 +146,13 @@ func (m *mockTransport) Dial(addr string, opts ...transport.DialOption) (transpo select { case <-listener.exit: return nil, errors.New("connection error") - case listener.conn <- client.mockSocket: + case listener.conn <- client.memorySocket: } return client, nil } -func (m *mockTransport) Listen(addr string, opts ...transport.ListenOption) (transport.Listener, error) { +func (m *memoryTransport) Listen(addr string, opts ...transport.ListenOption) (transport.Listener, error) { m.Lock() defer m.Unlock() @@ -174,10 +175,10 @@ func (m *mockTransport) Listen(addr string, opts ...transport.ListenOption) (tra return nil, errors.New("already listening on " + addr) } - listener := &mockListener{ + listener := &memoryListener{ opts: options, addr: addr, - conn: make(chan *mockSocket), + conn: make(chan *memorySocket), exit: make(chan bool), } @@ -186,19 +187,19 @@ func (m *mockTransport) Listen(addr string, opts ...transport.ListenOption) (tra return listener, nil } -func (m *mockTransport) Init(opts ...transport.Option) error { +func (m *memoryTransport) Init(opts ...transport.Option) error { for _, o := range opts { o(&m.opts) } return nil } -func (m *mockTransport) Options() transport.Options { +func (m *memoryTransport) Options() transport.Options { return m.opts } -func (m *mockTransport) String() string { - return "mock" +func (m *memoryTransport) String() string { + return "memory" } func NewTransport(opts ...transport.Option) transport.Transport { @@ -207,8 +208,8 @@ func NewTransport(opts ...transport.Option) transport.Transport { o(&options) } - return &mockTransport{ + return &memoryTransport{ opts: options, - listeners: make(map[string]*mockListener), + listeners: make(map[string]*memoryListener), } } diff --git a/transport/mock/mock_test.go b/transport/memory/memory_test.go similarity index 96% rename from transport/mock/mock_test.go rename to transport/memory/memory_test.go index 193d575a..72952e09 100644 --- a/transport/mock/mock_test.go +++ b/transport/memory/memory_test.go @@ -1,4 +1,4 @@ -package mock +package memory import ( "testing" @@ -6,7 +6,7 @@ import ( "github.com/micro/go-micro/transport" ) -func TestTransport(t *testing.T) { +func TestMemoryTransport(t *testing.T) { tr := NewTransport() // bind / listen From f2ac73eae56cc29a173d9d97299a8afd2b966a5e Mon Sep 17 00:00:00 2001 From: Asim Aslam Date: Mon, 14 Jan 2019 16:09:51 +0000 Subject: [PATCH 112/196] only log error if its plus 3 --- selector/default.go | 19 +++++++++++++++++-- 1 file changed, 17 insertions(+), 2 deletions(-) diff --git a/selector/default.go b/selector/default.go index e0bd3672..66fa332b 100644 --- a/selector/default.go +++ b/selector/default.go @@ -255,6 +255,9 @@ func (c *registrySelector) run(name string) { c.Unlock() }() + // error counter + var cerr int + for { // exit early if already dead if c.quit() { @@ -265,11 +268,16 @@ func (c *registrySelector) run(name string) { w, err := c.so.Registry.Watch( registry.WatchService(name), ) + if err != nil { if c.quit() { return } - log.Log(err) + cerr++ + if cerr > 3 { + log.Log(err) + cerr = 0 + } time.Sleep(time.Second) continue } @@ -279,9 +287,16 @@ func (c *registrySelector) run(name string) { if c.quit() { return } - log.Log(err) + cerr++ + if cerr > 3 { + cerr = 0 + log.Log(err) + } continue } + + // reset err counter + cerr = 0 } } From c1d02373709705b4251475b200424c4fafc9789b Mon Sep 17 00:00:00 2001 From: Asim Aslam Date: Mon, 14 Jan 2019 21:30:43 +0000 Subject: [PATCH 113/196] Add client response --- client/client.go | 8 ++++++ client/rpc_client.go | 33 ++++++++++++++++------- client/rpc_codec.go | 57 ++++++++++++++++++++++++---------------- client/rpc_response.go | 2 +- client/rpc_stream.go | 17 +++++++----- codec/bytes/bytes.go | 14 +++++++--- codec/bytes/marshaler.go | 3 +++ server/rpc_codec.go | 15 +++++++++-- 8 files changed, 105 insertions(+), 44 deletions(-) diff --git a/client/client.go b/client/client.go index 4cfe0bc8..5703fd31 100644 --- a/client/client.go +++ b/client/client.go @@ -62,11 +62,19 @@ type Response interface { // Stream is the inteface for a bidirectional synchronous stream type Stream interface { + // Context for the stream Context() context.Context + // The request made Request() Request + // The response read + Response() Response + // Send will encode and send a request Send(interface{}) error + // Recv will decode and read a response Recv(interface{}) error + // Error returns the stream error Error() error + // Close closes the stream Close() error } diff --git a/client/rpc_client.go b/client/rpc_client.go index 34fd8671..16db46cf 100644 --- a/client/rpc_client.go +++ b/client/rpc_client.go @@ -92,13 +92,20 @@ func (r *rpcClient) call(ctx context.Context, address string, req Request, resp seq := atomic.LoadUint64(&r.seq) atomic.AddUint64(&r.seq, 1) + codec := newRpcCodec(msg, c, cf) + + rsp := &rpcResponse{ + socket: c, + codec: codec, + } stream := &rpcStream{ - context: ctx, - request: req, - closed: make(chan bool), - codec: newRpcCodec(msg, c, cf), - id: fmt.Sprintf("%v", seq), + context: ctx, + request: req, + response: rsp, + codec: codec, + closed: make(chan bool), + id: fmt.Sprintf("%v", seq), } defer stream.Close() @@ -174,11 +181,19 @@ func (r *rpcClient) stream(ctx context.Context, address string, req Request, opt return nil, errors.InternalServerError("go.micro.client", "connection error: %v", err) } + codec := newRpcCodec(msg, c, cf) + + rsp := &rpcResponse{ + socket: c, + codec: codec, + } + stream := &rpcStream{ - context: ctx, - request: req, - closed: make(chan bool), - codec: newRpcCodec(msg, c, cf), + context: ctx, + request: req, + response: rsp, + closed: make(chan bool), + codec: newRpcCodec(msg, c, cf), } ch := make(chan error, 1) diff --git a/client/rpc_codec.go b/client/rpc_codec.go index a7e9dada..84be5b77 100644 --- a/client/rpc_codec.go +++ b/client/rpc_codec.go @@ -88,41 +88,54 @@ func newRpcCodec(req *transport.Message, client transport.Client, c codec.NewCod return r } -func (c *rpcCodec) Write(wm *codec.Message, body interface{}) error { +func (c *rpcCodec) Write(m *codec.Message, body interface{}) error { c.buf.wbuf.Reset() - m := &codec.Message{ - Id: wm.Id, - Target: wm.Target, - Endpoint: wm.Endpoint, - Type: codec.Request, - Header: map[string]string{ - "X-Micro-Id": wm.Id, - "X-Micro-Service": wm.Target, - "X-Micro-Endpoint": wm.Endpoint, - }, + // create header + if m.Header == nil { + m.Header = map[string]string{} } - if err := c.codec.Write(m, body); err != nil { - return errors.InternalServerError("go.micro.client.codec", err.Error()) + // copy original header + for k, v := range c.req.Header { + m.Header[k] = v } - // set body - if len(wm.Body) > 0 { - c.req.Body = wm.Body - } else { - c.req.Body = c.buf.wbuf.Bytes() + // set the mucp headers + m.Header["X-Micro-Id"] = m.Id + m.Header["X-Micro-Service"] = m.Target + m.Header["X-Micro-Endpoint"] = m.Endpoint + + // if body is bytes don't encode + if body != nil { + b, ok := body.([]byte) + if ok { + // set body + m.Body = b + body = nil + } } - // set header - for k, v := range m.Header { - c.req.Header[k] = v + if len(m.Body) == 0 { + // write to codec + if err := c.codec.Write(m, body); err != nil { + return errors.InternalServerError("go.micro.client.codec", err.Error()) + } + // set body + m.Body = c.buf.wbuf.Bytes() + } + + // create new transport message + msg := transport.Message{ + Header: m.Header, + Body: m.Body, } // send the request - if err := c.client.Send(c.req); err != nil { + if err := c.client.Send(&msg); err != nil { return errors.InternalServerError("go.micro.client.transport", err.Error()) } + return nil } diff --git a/client/rpc_response.go b/client/rpc_response.go index d5c4e894..08aaa84d 100644 --- a/client/rpc_response.go +++ b/client/rpc_response.go @@ -12,7 +12,7 @@ type rpcResponse struct { codec codec.Codec } -func (r *rpcResponse) Codec() codec.Writer { +func (r *rpcResponse) Codec() codec.Reader { return r.codec } diff --git a/client/rpc_stream.go b/client/rpc_stream.go index 627d2099..39e82fe4 100644 --- a/client/rpc_stream.go +++ b/client/rpc_stream.go @@ -11,12 +11,13 @@ import ( // Implements the streamer interface type rpcStream struct { sync.RWMutex - id string - closed chan bool - err error - request Request - codec codec.Codec - context context.Context + id string + closed chan bool + err error + request Request + response Response + codec codec.Codec + context context.Context } func (r *rpcStream) isClosed() bool { @@ -36,6 +37,10 @@ func (r *rpcStream) Request() Request { return r.request } +func (r *rpcStream) Response() Response { + return r.response +} + func (r *rpcStream) Send(msg interface{}) error { r.Lock() defer r.Unlock() diff --git a/codec/bytes/bytes.go b/codec/bytes/bytes.go index b2604df2..f912fe34 100644 --- a/codec/bytes/bytes.go +++ b/codec/bytes/bytes.go @@ -35,11 +35,17 @@ func (c *Codec) ReadBody(b interface{}) error { } func (c *Codec) Write(m *codec.Message, b interface{}) error { - v, ok := b.(*[]byte) - if !ok { - return fmt.Errorf("failed to write: %v is not type of *[]byte", b) + var v []byte + switch b.(type) { + case *[]byte: + ve := b.(*[]byte) + v = *ve + case []byte: + v = b.([]byte) + default: + return fmt.Errorf("failed to write: %v is not type of *[]byte or []byte", b) } - _, err := c.Conn.Write(*v) + _, err := c.Conn.Write(v) return err } diff --git a/codec/bytes/marshaler.go b/codec/bytes/marshaler.go index 8f8d188f..76599b65 100644 --- a/codec/bytes/marshaler.go +++ b/codec/bytes/marshaler.go @@ -13,6 +13,9 @@ type Message struct { func (n Marshaler) Marshal(v interface{}) ([]byte, error) { switch v.(type) { + case *[]byte: + ve := v.(*[]byte) + return *ve, nil case []byte: return v.([]byte), nil case *Message: diff --git a/server/rpc_codec.go b/server/rpc_codec.go index 82a8a45f..da2e35ce 100644 --- a/server/rpc_codec.go +++ b/server/rpc_codec.go @@ -99,6 +99,9 @@ func (c *rpcCodec) ReadHeader(r *codec.Message, t codec.MessageType) error { m.Header = tm.Header // set the message body m.Body = tm.Body + + // set req + c.req = &tm } // no longer first read @@ -120,6 +123,10 @@ func (c *rpcCodec) ReadHeader(r *codec.Message, t codec.MessageType) error { } func (c *rpcCodec) ReadBody(b interface{}) error { + // don't read empty body + if len(c.req.Body) == 0 { + return nil + } return c.codec.ReadBody(b) } @@ -132,7 +139,11 @@ func (c *rpcCodec) Write(r *codec.Message, b interface{}) error { Id: r.Id, Error: r.Error, Type: r.Type, - Header: map[string]string{}, + Header: r.Header, + } + + if m.Header == nil { + m.Header = map[string]string{} } // set request id @@ -160,7 +171,7 @@ func (c *rpcCodec) Write(r *codec.Message, b interface{}) error { // if we have encoded data just send it if len(r.Body) > 0 { body = r.Body - // write to the body + // write the body to codec } else if err := c.codec.Write(m, b); err != nil { c.buf.wbuf.Reset() From e362466e8a0f60d777729ce656e474278d50dd2c Mon Sep 17 00:00:00 2001 From: Asim Aslam Date: Mon, 14 Jan 2019 21:45:43 +0000 Subject: [PATCH 114/196] use default router --- server/rpc_server.go | 8 +------- 1 file changed, 1 insertion(+), 7 deletions(-) diff --git a/server/rpc_server.go b/server/rpc_server.go index d02e8421..eb4be8a5 100644 --- a/server/rpc_server.go +++ b/server/rpc_server.go @@ -38,7 +38,7 @@ func newRpcServer(opts ...Option) Server { options := newOptions(opts...) return &rpcServer{ opts: options, - router: newRpcRouter(), + router: DefaultRouter, handlers: make(map[string]Handler), subscribers: make(map[*subscriber][]broker.Subscriber), exit: make(chan chan error), @@ -188,12 +188,6 @@ func (s *rpcServer) Init(opts ...Option) error { for _, opt := range opts { opt(&s.opts) } - - // update router - r := newRpcRouter() - r.serviceMap = s.router.serviceMap - s.router = r - s.Unlock() return nil } From 00661f8a99ba55727dfe9969dc471cff2eb5a765 Mon Sep 17 00:00:00 2001 From: Asim Aslam Date: Tue, 15 Jan 2019 15:17:30 +0000 Subject: [PATCH 115/196] Clarify log message --- server/rpc_server.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/server/rpc_server.go b/server/rpc_server.go index eb4be8a5..f2a7042c 100644 --- a/server/rpc_server.go +++ b/server/rpc_server.go @@ -430,7 +430,7 @@ func (s *rpcServer) Start() error { return err } - log.Logf("Listening on %s", ts.Addr()) + log.Logf("Transport Listening on %s", ts.Addr()) s.Lock() // swap address addr := s.opts.Address From 7314af347ba63486288f060ca8886682c568b6f6 Mon Sep 17 00:00:00 2001 From: Asim Aslam Date: Tue, 15 Jan 2019 16:50:37 +0000 Subject: [PATCH 116/196] Set MDNS as default registry --- cmd/cmd.go | 4 +- registry/consul/consul.go | 384 ++++++++++++++++- registry/consul/encoding.go | 170 ++++++++ registry/consul/encoding_test.go | 147 +++++++ .../registry_test.go} | 5 +- .../{consul_watcher.go => consul/watcher.go} | 45 +- .../watcher_test.go} | 7 +- registry/consul_registry.go | 386 ------------------ registry/encoding.go | 179 ++------ registry/encoding_test.go | 175 +++----- registry/mdns/encoding.go | 73 ---- registry/mdns/encoding_test.go | 67 --- registry/mdns/mdns.go | 334 +-------------- registry/mdns_registry.go | 332 +++++++++++++++ registry/{mdns => }/mdns_test.go | 24 +- registry/{mdns/watcher.go => mdns_watcher.go} | 13 +- registry/registry.go | 6 +- registry/{mdns => }/watcher_test.go | 26 +- 18 files changed, 1183 insertions(+), 1194 deletions(-) create mode 100644 registry/consul/encoding.go create mode 100644 registry/consul/encoding_test.go rename registry/{consul_registry_test.go => consul/registry_test.go} (98%) rename registry/{consul_watcher.go => consul/watcher.go} (80%) rename registry/{consul_watcher_test.go => consul/watcher_test.go} (93%) delete mode 100644 registry/consul_registry.go delete mode 100644 registry/mdns/encoding.go delete mode 100644 registry/mdns/encoding_test.go create mode 100644 registry/mdns_registry.go rename registry/{mdns => }/mdns_test.go (88%) rename registry/{mdns/watcher.go => mdns_watcher.go} (82%) rename registry/{mdns => }/watcher_test.go (86%) diff --git a/cmd/cmd.go b/cmd/cmd.go index 3ef6ac8e..41dcdc43 100644 --- a/cmd/cmd.go +++ b/cmd/cmd.go @@ -202,8 +202,8 @@ var ( defaultClient = "rpc" defaultServer = "rpc" defaultBroker = "http" - defaultRegistry = "consul" - defaultSelector = "cache" + defaultRegistry = "mdns" + defaultSelector = "registry" defaultTransport = "http" ) diff --git a/registry/consul/consul.go b/registry/consul/consul.go index 03bc8d89..7e9cf794 100644 --- a/registry/consul/consul.go +++ b/registry/consul/consul.go @@ -1,11 +1,387 @@ -// Package consul provides a consul based registry and is the default discovery system package consul import ( + "crypto/tls" + "errors" + "fmt" + "net" + "net/http" + "runtime" + "sync" + "time" + + consul "github.com/hashicorp/consul/api" "github.com/micro/go-micro/registry" + hash "github.com/mitchellh/hashstructure" ) -// NewRegistry returns a new consul registry -func NewRegistry(opts ...registry.Option) registry.Registry { - return registry.NewRegistry(opts...) +type consulRegistry struct { + Address string + Client *consul.Client + opts registry.Options + + // connect enabled + connect bool + + queryOptions *consul.QueryOptions + + sync.Mutex + register map[string]uint64 + // lastChecked tracks when a node was last checked as existing in Consul + lastChecked map[string]time.Time +} + +func getDeregisterTTL(t time.Duration) time.Duration { + // splay slightly for the watcher? + splay := time.Second * 5 + deregTTL := t + splay + + // consul has a minimum timeout on deregistration of 1 minute. + if t < time.Minute { + deregTTL = time.Minute + splay + } + + return deregTTL +} + +func newTransport(config *tls.Config) *http.Transport { + if config == nil { + config = &tls.Config{ + InsecureSkipVerify: true, + } + } + + t := &http.Transport{ + Proxy: http.ProxyFromEnvironment, + Dial: (&net.Dialer{ + Timeout: 30 * time.Second, + KeepAlive: 30 * time.Second, + }).Dial, + TLSHandshakeTimeout: 10 * time.Second, + TLSClientConfig: config, + } + runtime.SetFinalizer(&t, func(tr **http.Transport) { + (*tr).CloseIdleConnections() + }) + return t +} + +func configure(c *consulRegistry, opts ...registry.Option) { + // set opts + for _, o := range opts { + o(&c.opts) + } + + // use default config + config := consul.DefaultConfig() + + if c.opts.Context != nil { + // Use the consul config passed in the options, if available + if co, ok := c.opts.Context.Value("consul_config").(*consul.Config); ok { + config = co + } + if cn, ok := c.opts.Context.Value("consul_connect").(bool); ok { + c.connect = cn + } + + // Use the consul query options passed in the options, if available + if qo, ok := c.opts.Context.Value("consul_query_options").(*consul.QueryOptions); ok && qo != nil { + c.queryOptions = qo + } + if as, ok := c.opts.Context.Value("consul_allow_stale").(bool); ok { + c.queryOptions.AllowStale = as + } + } + + // check if there are any addrs + if len(c.opts.Addrs) > 0 { + addr, port, err := net.SplitHostPort(c.opts.Addrs[0]) + if ae, ok := err.(*net.AddrError); ok && ae.Err == "missing port in address" { + port = "8500" + addr = c.opts.Addrs[0] + config.Address = fmt.Sprintf("%s:%s", addr, port) + } else if err == nil { + config.Address = fmt.Sprintf("%s:%s", addr, port) + } + } + + // requires secure connection? + if c.opts.Secure || c.opts.TLSConfig != nil { + if config.HttpClient == nil { + config.HttpClient = new(http.Client) + } + + config.Scheme = "https" + // We're going to support InsecureSkipVerify + config.HttpClient.Transport = newTransport(c.opts.TLSConfig) + } + + // set timeout + if c.opts.Timeout > 0 { + config.HttpClient.Timeout = c.opts.Timeout + } + + // create the client + client, _ := consul.NewClient(config) + + // set address/client + c.Address = config.Address + c.Client = client +} + +func (c *consulRegistry) Init(opts ...registry.Option) error { + configure(c, opts...) + return nil +} + +func (c *consulRegistry) Deregister(s *registry.Service) error { + if len(s.Nodes) == 0 { + return errors.New("Require at least one node") + } + + // delete our hash and time check of the service + c.Lock() + delete(c.register, s.Name) + delete(c.lastChecked, s.Name) + c.Unlock() + + node := s.Nodes[0] + return c.Client.Agent().ServiceDeregister(node.Id) +} + +func (c *consulRegistry) Register(s *registry.Service, opts ...registry.RegisterOption) error { + if len(s.Nodes) == 0 { + return errors.New("Require at least one node") + } + + var regTCPCheck bool + var regInterval time.Duration + + var options registry.RegisterOptions + for _, o := range opts { + o(&options) + } + + if c.opts.Context != nil { + if tcpCheckInterval, ok := c.opts.Context.Value("consul_tcp_check").(time.Duration); ok { + regTCPCheck = true + regInterval = tcpCheckInterval + } + } + + // create hash of service; uint64 + h, err := hash.Hash(s, nil) + if err != nil { + return err + } + + // use first node + node := s.Nodes[0] + + // get existing hash and last checked time + c.Lock() + v, ok := c.register[s.Name] + lastChecked := c.lastChecked[s.Name] + c.Unlock() + + // if it's already registered and matches then just pass the check + if ok && v == h { + if options.TTL == time.Duration(0) { + // ensure that our service hasn't been deregistered by Consul + if time.Since(lastChecked) <= getDeregisterTTL(regInterval) { + return nil + } + services, _, err := c.Client.Health().Checks(s.Name, c.queryOptions) + if err == nil { + for _, v := range services { + if v.ServiceID == node.Id { + return nil + } + } + } + } else { + // if the err is nil we're all good, bail out + // if not, we don't know what the state is, so full re-register + if err := c.Client.Agent().PassTTL("service:"+node.Id, ""); err == nil { + return nil + } + } + } + + // encode the tags + tags := encodeMetadata(node.Metadata) + tags = append(tags, encodeEndpoints(s.Endpoints)...) + tags = append(tags, encodeVersion(s.Version)...) + + var check *consul.AgentServiceCheck + + if regTCPCheck { + deregTTL := getDeregisterTTL(regInterval) + + check = &consul.AgentServiceCheck{ + TCP: fmt.Sprintf("%s:%d", node.Address, node.Port), + Interval: fmt.Sprintf("%v", regInterval), + DeregisterCriticalServiceAfter: fmt.Sprintf("%v", deregTTL), + } + + // if the TTL is greater than 0 create an associated check + } else if options.TTL > time.Duration(0) { + deregTTL := getDeregisterTTL(options.TTL) + + check = &consul.AgentServiceCheck{ + TTL: fmt.Sprintf("%v", options.TTL), + DeregisterCriticalServiceAfter: fmt.Sprintf("%v", deregTTL), + } + } + + // register the service + asr := &consul.AgentServiceRegistration{ + ID: node.Id, + Name: s.Name, + Tags: tags, + Port: node.Port, + Address: node.Address, + Check: check, + } + + // Specify consul connect + if c.connect { + asr.Connect = &consul.AgentServiceConnect{ + Native: true, + } + } + + if err := c.Client.Agent().ServiceRegister(asr); err != nil { + return err + } + + // save our hash and time check of the service + c.Lock() + c.register[s.Name] = h + c.lastChecked[s.Name] = time.Now() + c.Unlock() + + // if the TTL is 0 we don't mess with the checks + if options.TTL == time.Duration(0) { + return nil + } + + // pass the healthcheck + return c.Client.Agent().PassTTL("service:"+node.Id, "") +} + +func (c *consulRegistry) GetService(name string) ([]*registry.Service, error) { + var rsp []*consul.ServiceEntry + var err error + + // if we're connect enabled only get connect services + if c.connect { + rsp, _, err = c.Client.Health().Connect(name, "", false, c.queryOptions) + } else { + rsp, _, err = c.Client.Health().Service(name, "", false, c.queryOptions) + } + if err != nil { + return nil, err + } + + serviceMap := map[string]*registry.Service{} + + for _, s := range rsp { + if s.Service.Service != name { + continue + } + + // version is now a tag + version, _ := decodeVersion(s.Service.Tags) + // service ID is now the node id + id := s.Service.ID + // key is always the version + key := version + + // address is service address + address := s.Service.Address + + // use node address + if len(address) == 0 { + address = s.Node.Address + } + + svc, ok := serviceMap[key] + if !ok { + svc = ®istry.Service{ + Endpoints: decodeEndpoints(s.Service.Tags), + Name: s.Service.Service, + Version: version, + } + serviceMap[key] = svc + } + + var del bool + + for _, check := range s.Checks { + // delete the node if the status is critical + if check.Status == "critical" { + del = true + break + } + } + + // if delete then skip the node + if del { + continue + } + + svc.Nodes = append(svc.Nodes, ®istry.Node{ + Id: id, + Address: address, + Port: s.Service.Port, + Metadata: decodeMetadata(s.Service.Tags), + }) + } + + var services []*registry.Service + for _, service := range serviceMap { + services = append(services, service) + } + return services, nil +} + +func (c *consulRegistry) ListServices() ([]*registry.Service, error) { + rsp, _, err := c.Client.Catalog().Services(c.queryOptions) + if err != nil { + return nil, err + } + + var services []*registry.Service + + for service := range rsp { + services = append(services, ®istry.Service{Name: service}) + } + + return services, nil +} + +func (c *consulRegistry) Watch(opts ...registry.WatchOption) (registry.Watcher, error) { + return newConsulWatcher(c, opts...) +} + +func (c *consulRegistry) String() string { + return "consul" +} + +func (c *consulRegistry) Options() registry.Options { + return c.opts +} + +func NewRegistry(opts ...registry.Option) registry.Registry { + cr := &consulRegistry{ + opts: registry.Options{}, + register: make(map[string]uint64), + lastChecked: make(map[string]time.Time), + queryOptions: &consul.QueryOptions{ + AllowStale: true, + }, + } + configure(cr, opts...) + return cr } diff --git a/registry/consul/encoding.go b/registry/consul/encoding.go new file mode 100644 index 00000000..8a152683 --- /dev/null +++ b/registry/consul/encoding.go @@ -0,0 +1,170 @@ +package consul + +import ( + "bytes" + "compress/zlib" + "encoding/hex" + "encoding/json" + "io/ioutil" + + "github.com/micro/go-micro/registry" +) + +func encode(buf []byte) string { + var b bytes.Buffer + defer b.Reset() + + w := zlib.NewWriter(&b) + if _, err := w.Write(buf); err != nil { + return "" + } + w.Close() + + return hex.EncodeToString(b.Bytes()) +} + +func decode(d string) []byte { + hr, err := hex.DecodeString(d) + if err != nil { + return nil + } + + br := bytes.NewReader(hr) + zr, err := zlib.NewReader(br) + if err != nil { + return nil + } + + rbuf, err := ioutil.ReadAll(zr) + if err != nil { + return nil + } + + return rbuf +} + +func encodeEndpoints(en []*registry.Endpoint) []string { + var tags []string + for _, e := range en { + if b, err := json.Marshal(e); err == nil { + tags = append(tags, "e-"+encode(b)) + } + } + return tags +} + +func decodeEndpoints(tags []string) []*registry.Endpoint { + var en []*registry.Endpoint + + // use the first format you find + var ver byte + + for _, tag := range tags { + if len(tag) == 0 || tag[0] != 'e' { + continue + } + + // check version + if ver > 0 && tag[1] != ver { + continue + } + + var e *registry.Endpoint + var buf []byte + + // Old encoding was plain + if tag[1] == '=' { + buf = []byte(tag[2:]) + } + + // New encoding is hex + if tag[1] == '-' { + buf = decode(tag[2:]) + } + + if err := json.Unmarshal(buf, &e); err == nil { + en = append(en, e) + } + + // set version + ver = tag[1] + } + return en +} + +func encodeMetadata(md map[string]string) []string { + var tags []string + for k, v := range md { + if b, err := json.Marshal(map[string]string{ + k: v, + }); err == nil { + // new encoding + tags = append(tags, "t-"+encode(b)) + } + } + return tags +} + +func decodeMetadata(tags []string) map[string]string { + md := make(map[string]string) + + var ver byte + + for _, tag := range tags { + if len(tag) == 0 || tag[0] != 't' { + continue + } + + // check version + if ver > 0 && tag[1] != ver { + continue + } + + var kv map[string]string + var buf []byte + + // Old encoding was plain + if tag[1] == '=' { + buf = []byte(tag[2:]) + } + + // New encoding is hex + if tag[1] == '-' { + buf = decode(tag[2:]) + } + + // Now unmarshal + if err := json.Unmarshal(buf, &kv); err == nil { + for k, v := range kv { + md[k] = v + } + } + + // set version + ver = tag[1] + } + return md +} + +func encodeVersion(v string) []string { + return []string{"v-" + encode([]byte(v))} +} + +func decodeVersion(tags []string) (string, bool) { + for _, tag := range tags { + if len(tag) < 2 || tag[0] != 'v' { + continue + } + + // Old encoding was plain + if tag[1] == '=' { + return tag[2:], true + } + + // New encoding is hex + if tag[1] == '-' { + return string(decode(tag[2:])), true + } + } + return "", false +} diff --git a/registry/consul/encoding_test.go b/registry/consul/encoding_test.go new file mode 100644 index 00000000..7f511174 --- /dev/null +++ b/registry/consul/encoding_test.go @@ -0,0 +1,147 @@ +package consul + +import ( + "encoding/json" + "testing" + + "github.com/micro/go-micro/registry" +) + +func TestEncodingEndpoints(t *testing.T) { + eps := []*registry.Endpoint{ + ®istry.Endpoint{ + Name: "endpoint1", + Request: ®istry.Value{ + Name: "request", + Type: "request", + }, + Response: ®istry.Value{ + Name: "response", + Type: "response", + }, + Metadata: map[string]string{ + "foo1": "bar1", + }, + }, + ®istry.Endpoint{ + Name: "endpoint2", + Request: ®istry.Value{ + Name: "request", + Type: "request", + }, + Response: ®istry.Value{ + Name: "response", + Type: "response", + }, + Metadata: map[string]string{ + "foo2": "bar2", + }, + }, + ®istry.Endpoint{ + Name: "endpoint3", + Request: ®istry.Value{ + Name: "request", + Type: "request", + }, + Response: ®istry.Value{ + Name: "response", + Type: "response", + }, + Metadata: map[string]string{ + "foo3": "bar3", + }, + }, + } + + testEp := func(ep *registry.Endpoint, enc string) { + // encode endpoint + e := encodeEndpoints([]*registry.Endpoint{ep}) + + // check there are two tags; old and new + if len(e) != 1 { + t.Fatalf("Expected 1 encoded tags, got %v", e) + } + + // check old encoding + var seen bool + + for _, en := range e { + if en == enc { + seen = true + break + } + } + + if !seen { + t.Fatalf("Expected %s but not found", enc) + } + + // decode + d := decodeEndpoints([]string{enc}) + if len(d) == 0 { + t.Fatalf("Expected %v got %v", ep, d) + } + + // check name + if d[0].Name != ep.Name { + t.Fatalf("Expected ep %s got %s", ep.Name, d[0].Name) + } + + // check all the metadata exists + for k, v := range ep.Metadata { + if gv := d[0].Metadata[k]; gv != v { + t.Fatalf("Expected key %s val %s got val %s", k, v, gv) + } + } + } + + for _, ep := range eps { + // JSON encoded + jencoded, err := json.Marshal(ep) + if err != nil { + t.Fatal(err) + } + + // HEX encoded + hencoded := encode(jencoded) + // endpoint tag + hepTag := "e-" + hencoded + testEp(ep, hepTag) + } +} + +func TestEncodingVersion(t *testing.T) { + testData := []struct { + decoded string + encoded string + }{ + {"1.0.0", "v-789c32d433d03300040000ffff02ce00ee"}, + {"latest", "v-789cca492c492d2e01040000ffff08cc028e"}, + } + + for _, data := range testData { + e := encodeVersion(data.decoded) + + if e[0] != data.encoded { + t.Fatalf("Expected %s got %s", data.encoded, e) + } + + d, ok := decodeVersion(e) + if !ok { + t.Fatalf("Unexpected %t for %s", ok, data.encoded) + } + + if d != data.decoded { + t.Fatalf("Expected %s got %s", data.decoded, d) + } + + d, ok = decodeVersion([]string{data.encoded}) + if !ok { + t.Fatalf("Unexpected %t for %s", ok, data.encoded) + } + + if d != data.decoded { + t.Fatalf("Expected %s got %s", data.decoded, d) + } + } +} diff --git a/registry/consul_registry_test.go b/registry/consul/registry_test.go similarity index 98% rename from registry/consul_registry_test.go rename to registry/consul/registry_test.go index 1758cfaa..37eabd17 100644 --- a/registry/consul_registry_test.go +++ b/registry/consul/registry_test.go @@ -1,4 +1,4 @@ -package registry +package consul import ( "bytes" @@ -10,6 +10,7 @@ import ( "time" consul "github.com/hashicorp/consul/api" + "github.com/micro/go-micro/registry" ) type mockRegistry struct { @@ -56,7 +57,7 @@ func newConsulTestRegistry(r *mockRegistry) (*consulRegistry, func()) { return &consulRegistry{ Address: cfg.Address, Client: cl, - opts: Options{}, + opts: registry.Options{}, register: make(map[string]uint64), lastChecked: make(map[string]time.Time), queryOptions: &consul.QueryOptions{ diff --git a/registry/consul_watcher.go b/registry/consul/watcher.go similarity index 80% rename from registry/consul_watcher.go rename to registry/consul/watcher.go index 0df0ec73..60957bb1 100644 --- a/registry/consul_watcher.go +++ b/registry/consul/watcher.go @@ -1,4 +1,4 @@ -package registry +package consul import ( "errors" @@ -6,23 +6,24 @@ import ( "github.com/hashicorp/consul/api" "github.com/hashicorp/consul/watch" + "github.com/micro/go-micro/registry" ) type consulWatcher struct { r *consulRegistry - wo WatchOptions + wo registry.WatchOptions wp *watch.Plan watchers map[string]*watch.Plan - next chan *Result + next chan *registry.Result exit chan bool sync.RWMutex - services map[string][]*Service + services map[string][]*registry.Service } -func newConsulWatcher(cr *consulRegistry, opts ...WatchOption) (Watcher, error) { - var wo WatchOptions +func newConsulWatcher(cr *consulRegistry, opts ...registry.WatchOption) (registry.Watcher, error) { + var wo registry.WatchOptions for _, o := range opts { o(&wo) } @@ -31,9 +32,9 @@ func newConsulWatcher(cr *consulRegistry, opts ...WatchOption) (Watcher, error) r: cr, wo: wo, exit: make(chan bool), - next: make(chan *Result, 10), + next: make(chan *registry.Result, 10), watchers: make(map[string]*watch.Plan), - services: make(map[string][]*Service), + services: make(map[string][]*registry.Service), } wp, err := watch.Parse(map[string]interface{}{"type": "services"}) @@ -54,7 +55,7 @@ func (cw *consulWatcher) serviceHandler(idx uint64, data interface{}) { return } - serviceMap := map[string]*Service{} + serviceMap := map[string]*registry.Service{} serviceName := "" for _, e := range entries { @@ -75,7 +76,7 @@ func (cw *consulWatcher) serviceHandler(idx uint64, data interface{}) { svc, ok := serviceMap[key] if !ok { - svc = &Service{ + svc = ®istry.Service{ Endpoints: decodeEndpoints(e.Service.Tags), Name: e.Service.Service, Version: version, @@ -98,7 +99,7 @@ func (cw *consulWatcher) serviceHandler(idx uint64, data interface{}) { continue } - svc.Nodes = append(svc.Nodes, &Node{ + svc.Nodes = append(svc.Nodes, ®istry.Node{ Id: id, Address: address, Port: e.Service.Port, @@ -108,13 +109,13 @@ func (cw *consulWatcher) serviceHandler(idx uint64, data interface{}) { cw.RLock() // make a copy - rservices := make(map[string][]*Service) + rservices := make(map[string][]*registry.Service) for k, v := range cw.services { rservices[k] = v } cw.RUnlock() - var newServices []*Service + var newServices []*registry.Service // serviceMap is the new set of services keyed by name+version for _, newService := range serviceMap { @@ -125,7 +126,7 @@ func (cw *consulWatcher) serviceHandler(idx uint64, data interface{}) { oldServices, ok := rservices[serviceName] if !ok { // does not exist? then we're creating brand new entries - cw.next <- &Result{Action: "create", Service: newService} + cw.next <- ®istry.Result{Action: "create", Service: newService} continue } @@ -142,7 +143,7 @@ func (cw *consulWatcher) serviceHandler(idx uint64, data interface{}) { // yes? then it's an update action = "update" - var nodes []*Node + var nodes []*registry.Node // check the old nodes to see if they've been deleted for _, oldNode := range oldService.Nodes { var seen bool @@ -163,11 +164,11 @@ func (cw *consulWatcher) serviceHandler(idx uint64, data interface{}) { if len(nodes) > 0 { delService := oldService delService.Nodes = nodes - cw.next <- &Result{Action: "delete", Service: delService} + cw.next <- ®istry.Result{Action: "delete", Service: delService} } } - cw.next <- &Result{Action: action, Service: newService} + cw.next <- ®istry.Result{Action: action, Service: newService} } // Now check old versions that may not be in new services map @@ -175,7 +176,7 @@ func (cw *consulWatcher) serviceHandler(idx uint64, data interface{}) { // old version does not exist in new version map // kill it with fire! if _, ok := serviceMap[old.Version]; !ok { - cw.next <- &Result{Action: "delete", Service: old} + cw.next <- ®istry.Result{Action: "delete", Service: old} } } @@ -209,13 +210,13 @@ func (cw *consulWatcher) handle(idx uint64, data interface{}) { wp.Handler = cw.serviceHandler go wp.Run(cw.r.Address) cw.watchers[service] = wp - cw.next <- &Result{Action: "create", Service: &Service{Name: service}} + cw.next <- ®istry.Result{Action: "create", Service: ®istry.Service{Name: service}} } } cw.RLock() // make a copy - rservices := make(map[string][]*Service) + rservices := make(map[string][]*registry.Service) for k, v := range cw.services { rservices[k] = v } @@ -235,12 +236,12 @@ func (cw *consulWatcher) handle(idx uint64, data interface{}) { if _, ok := services[service]; !ok { w.Stop() delete(cw.watchers, service) - cw.next <- &Result{Action: "delete", Service: &Service{Name: service}} + cw.next <- ®istry.Result{Action: "delete", Service: ®istry.Service{Name: service}} } } } -func (cw *consulWatcher) Next() (*Result, error) { +func (cw *consulWatcher) Next() (*registry.Result, error) { select { case <-cw.exit: return nil, errors.New("result chan closed") diff --git a/registry/consul_watcher_test.go b/registry/consul/watcher_test.go similarity index 93% rename from registry/consul_watcher_test.go rename to registry/consul/watcher_test.go index 1b6bae89..19e0cb80 100644 --- a/registry/consul_watcher_test.go +++ b/registry/consul/watcher_test.go @@ -1,9 +1,10 @@ -package registry +package consul import ( "testing" "github.com/hashicorp/consul/api" + "github.com/micro/go-micro/registry" ) func TestHealthyServiceHandler(t *testing.T) { @@ -58,8 +59,8 @@ func TestUnhealthyNodeServiceHandler(t *testing.T) { func newWatcher() *consulWatcher { return &consulWatcher{ exit: make(chan bool), - next: make(chan *Result, 10), - services: make(map[string][]*Service), + next: make(chan *registry.Result, 10), + services: make(map[string][]*registry.Service), } } diff --git a/registry/consul_registry.go b/registry/consul_registry.go deleted file mode 100644 index 02725b5d..00000000 --- a/registry/consul_registry.go +++ /dev/null @@ -1,386 +0,0 @@ -package registry - -import ( - "crypto/tls" - "errors" - "fmt" - "net" - "net/http" - "runtime" - "sync" - "time" - - consul "github.com/hashicorp/consul/api" - hash "github.com/mitchellh/hashstructure" -) - -type consulRegistry struct { - Address string - Client *consul.Client - opts Options - - // connect enabled - connect bool - - queryOptions *consul.QueryOptions - - sync.Mutex - register map[string]uint64 - // lastChecked tracks when a node was last checked as existing in Consul - lastChecked map[string]time.Time -} - -func getDeregisterTTL(t time.Duration) time.Duration { - // splay slightly for the watcher? - splay := time.Second * 5 - deregTTL := t + splay - - // consul has a minimum timeout on deregistration of 1 minute. - if t < time.Minute { - deregTTL = time.Minute + splay - } - - return deregTTL -} - -func newTransport(config *tls.Config) *http.Transport { - if config == nil { - config = &tls.Config{ - InsecureSkipVerify: true, - } - } - - t := &http.Transport{ - Proxy: http.ProxyFromEnvironment, - Dial: (&net.Dialer{ - Timeout: 30 * time.Second, - KeepAlive: 30 * time.Second, - }).Dial, - TLSHandshakeTimeout: 10 * time.Second, - TLSClientConfig: config, - } - runtime.SetFinalizer(&t, func(tr **http.Transport) { - (*tr).CloseIdleConnections() - }) - return t -} - -func configure(c *consulRegistry, opts ...Option) { - // set opts - for _, o := range opts { - o(&c.opts) - } - - // use default config - config := consul.DefaultConfig() - - if c.opts.Context != nil { - // Use the consul config passed in the options, if available - if co, ok := c.opts.Context.Value("consul_config").(*consul.Config); ok { - config = co - } - if cn, ok := c.opts.Context.Value("consul_connect").(bool); ok { - c.connect = cn - } - - // Use the consul query options passed in the options, if available - if qo, ok := c.opts.Context.Value("consul_query_options").(*consul.QueryOptions); ok && qo != nil { - c.queryOptions = qo - } - if as, ok := c.opts.Context.Value("consul_allow_stale").(bool); ok { - c.queryOptions.AllowStale = as - } - } - - // check if there are any addrs - if len(c.opts.Addrs) > 0 { - addr, port, err := net.SplitHostPort(c.opts.Addrs[0]) - if ae, ok := err.(*net.AddrError); ok && ae.Err == "missing port in address" { - port = "8500" - addr = c.opts.Addrs[0] - config.Address = fmt.Sprintf("%s:%s", addr, port) - } else if err == nil { - config.Address = fmt.Sprintf("%s:%s", addr, port) - } - } - - // requires secure connection? - if c.opts.Secure || c.opts.TLSConfig != nil { - if config.HttpClient == nil { - config.HttpClient = new(http.Client) - } - - config.Scheme = "https" - // We're going to support InsecureSkipVerify - config.HttpClient.Transport = newTransport(c.opts.TLSConfig) - } - - // set timeout - if c.opts.Timeout > 0 { - config.HttpClient.Timeout = c.opts.Timeout - } - - // create the client - client, _ := consul.NewClient(config) - - // set address/client - c.Address = config.Address - c.Client = client -} - -func newConsulRegistry(opts ...Option) Registry { - cr := &consulRegistry{ - opts: Options{}, - register: make(map[string]uint64), - lastChecked: make(map[string]time.Time), - queryOptions: &consul.QueryOptions{ - AllowStale: true, - }, - } - configure(cr, opts...) - return cr -} - -func (c *consulRegistry) Init(opts ...Option) error { - configure(c, opts...) - return nil -} - -func (c *consulRegistry) Deregister(s *Service) error { - if len(s.Nodes) == 0 { - return errors.New("Require at least one node") - } - - // delete our hash and time check of the service - c.Lock() - delete(c.register, s.Name) - delete(c.lastChecked, s.Name) - c.Unlock() - - node := s.Nodes[0] - return c.Client.Agent().ServiceDeregister(node.Id) -} - -func (c *consulRegistry) Register(s *Service, opts ...RegisterOption) error { - if len(s.Nodes) == 0 { - return errors.New("Require at least one node") - } - - var regTCPCheck bool - var regInterval time.Duration - - var options RegisterOptions - for _, o := range opts { - o(&options) - } - - if c.opts.Context != nil { - if tcpCheckInterval, ok := c.opts.Context.Value("consul_tcp_check").(time.Duration); ok { - regTCPCheck = true - regInterval = tcpCheckInterval - } - } - - // create hash of service; uint64 - h, err := hash.Hash(s, nil) - if err != nil { - return err - } - - // use first node - node := s.Nodes[0] - - // get existing hash and last checked time - c.Lock() - v, ok := c.register[s.Name] - lastChecked := c.lastChecked[s.Name] - c.Unlock() - - // if it's already registered and matches then just pass the check - if ok && v == h { - if options.TTL == time.Duration(0) { - // ensure that our service hasn't been deregistered by Consul - if time.Since(lastChecked) <= getDeregisterTTL(regInterval) { - return nil - } - services, _, err := c.Client.Health().Checks(s.Name, c.queryOptions) - if err == nil { - for _, v := range services { - if v.ServiceID == node.Id { - return nil - } - } - } - } else { - // if the err is nil we're all good, bail out - // if not, we don't know what the state is, so full re-register - if err := c.Client.Agent().PassTTL("service:"+node.Id, ""); err == nil { - return nil - } - } - } - - // encode the tags - tags := encodeMetadata(node.Metadata) - tags = append(tags, encodeEndpoints(s.Endpoints)...) - tags = append(tags, encodeVersion(s.Version)...) - - var check *consul.AgentServiceCheck - - if regTCPCheck { - deregTTL := getDeregisterTTL(regInterval) - - check = &consul.AgentServiceCheck{ - TCP: fmt.Sprintf("%s:%d", node.Address, node.Port), - Interval: fmt.Sprintf("%v", regInterval), - DeregisterCriticalServiceAfter: fmt.Sprintf("%v", deregTTL), - } - - // if the TTL is greater than 0 create an associated check - } else if options.TTL > time.Duration(0) { - deregTTL := getDeregisterTTL(options.TTL) - - check = &consul.AgentServiceCheck{ - TTL: fmt.Sprintf("%v", options.TTL), - DeregisterCriticalServiceAfter: fmt.Sprintf("%v", deregTTL), - } - } - - // register the service - asr := &consul.AgentServiceRegistration{ - ID: node.Id, - Name: s.Name, - Tags: tags, - Port: node.Port, - Address: node.Address, - Check: check, - } - - // Specify consul connect - if c.connect { - asr.Connect = &consul.AgentServiceConnect{ - Native: true, - } - } - - if err := c.Client.Agent().ServiceRegister(asr); err != nil { - return err - } - - // save our hash and time check of the service - c.Lock() - c.register[s.Name] = h - c.lastChecked[s.Name] = time.Now() - c.Unlock() - - // if the TTL is 0 we don't mess with the checks - if options.TTL == time.Duration(0) { - return nil - } - - // pass the healthcheck - return c.Client.Agent().PassTTL("service:"+node.Id, "") -} - -func (c *consulRegistry) GetService(name string) ([]*Service, error) { - var rsp []*consul.ServiceEntry - var err error - - // if we're connect enabled only get connect services - if c.connect { - rsp, _, err = c.Client.Health().Connect(name, "", false, c.queryOptions) - } else { - rsp, _, err = c.Client.Health().Service(name, "", false, c.queryOptions) - } - if err != nil { - return nil, err - } - - serviceMap := map[string]*Service{} - - for _, s := range rsp { - if s.Service.Service != name { - continue - } - - // version is now a tag - version, _ := decodeVersion(s.Service.Tags) - // service ID is now the node id - id := s.Service.ID - // key is always the version - key := version - - // address is service address - address := s.Service.Address - - // use node address - if len(address) == 0 { - address = s.Node.Address - } - - svc, ok := serviceMap[key] - if !ok { - svc = &Service{ - Endpoints: decodeEndpoints(s.Service.Tags), - Name: s.Service.Service, - Version: version, - } - serviceMap[key] = svc - } - - var del bool - - for _, check := range s.Checks { - // delete the node if the status is critical - if check.Status == "critical" { - del = true - break - } - } - - // if delete then skip the node - if del { - continue - } - - svc.Nodes = append(svc.Nodes, &Node{ - Id: id, - Address: address, - Port: s.Service.Port, - Metadata: decodeMetadata(s.Service.Tags), - }) - } - - var services []*Service - for _, service := range serviceMap { - services = append(services, service) - } - return services, nil -} - -func (c *consulRegistry) ListServices() ([]*Service, error) { - rsp, _, err := c.Client.Catalog().Services(c.queryOptions) - if err != nil { - return nil, err - } - - var services []*Service - - for service := range rsp { - services = append(services, &Service{Name: service}) - } - - return services, nil -} - -func (c *consulRegistry) Watch(opts ...WatchOption) (Watcher, error) { - return newConsulWatcher(c, opts...) -} - -func (c *consulRegistry) String() string { - return "consul" -} - -func (c *consulRegistry) Options() Options { - return c.opts -} diff --git a/registry/encoding.go b/registry/encoding.go index b5bb9d6c..750f88f8 100644 --- a/registry/encoding.go +++ b/registry/encoding.go @@ -6,163 +6,68 @@ import ( "encoding/hex" "encoding/json" "io/ioutil" + "strings" ) -func encode(buf []byte) string { - var b bytes.Buffer - defer b.Reset() +func encode(txt *mdnsTxt) ([]string, error) { + b, err := json.Marshal(txt) + if err != nil { + return nil, err + } - w := zlib.NewWriter(&b) - if _, err := w.Write(buf); err != nil { - return "" + var buf bytes.Buffer + defer buf.Reset() + + w := zlib.NewWriter(&buf) + if _, err := w.Write(b); err != nil { + return nil, err } w.Close() - return hex.EncodeToString(b.Bytes()) + encoded := hex.EncodeToString(buf.Bytes()) + + // individual txt limit + if len(encoded) <= 255 { + return []string{encoded}, nil + } + + // split encoded string + var record []string + + for len(encoded) > 255 { + record = append(record, encoded[:255]) + encoded = encoded[255:] + } + + record = append(record, encoded) + + return record, nil } -func decode(d string) []byte { - hr, err := hex.DecodeString(d) +func decode(record []string) (*mdnsTxt, error) { + encoded := strings.Join(record, "") + + hr, err := hex.DecodeString(encoded) if err != nil { - return nil + return nil, err } br := bytes.NewReader(hr) zr, err := zlib.NewReader(br) if err != nil { - return nil + return nil, err } rbuf, err := ioutil.ReadAll(zr) if err != nil { - return nil + return nil, err } - return rbuf -} + var txt *mdnsTxt -func encodeEndpoints(en []*Endpoint) []string { - var tags []string - for _, e := range en { - if b, err := json.Marshal(e); err == nil { - tags = append(tags, "e-"+encode(b)) - } + if err := json.Unmarshal(rbuf, &txt); err != nil { + return nil, err } - return tags -} - -func decodeEndpoints(tags []string) []*Endpoint { - var en []*Endpoint - - // use the first format you find - var ver byte - - for _, tag := range tags { - if len(tag) == 0 || tag[0] != 'e' { - continue - } - - // check version - if ver > 0 && tag[1] != ver { - continue - } - - var e *Endpoint - var buf []byte - - // Old encoding was plain - if tag[1] == '=' { - buf = []byte(tag[2:]) - } - - // New encoding is hex - if tag[1] == '-' { - buf = decode(tag[2:]) - } - - if err := json.Unmarshal(buf, &e); err == nil { - en = append(en, e) - } - - // set version - ver = tag[1] - } - return en -} - -func encodeMetadata(md map[string]string) []string { - var tags []string - for k, v := range md { - if b, err := json.Marshal(map[string]string{ - k: v, - }); err == nil { - // new encoding - tags = append(tags, "t-"+encode(b)) - } - } - return tags -} - -func decodeMetadata(tags []string) map[string]string { - md := make(map[string]string) - - var ver byte - - for _, tag := range tags { - if len(tag) == 0 || tag[0] != 't' { - continue - } - - // check version - if ver > 0 && tag[1] != ver { - continue - } - - var kv map[string]string - var buf []byte - - // Old encoding was plain - if tag[1] == '=' { - buf = []byte(tag[2:]) - } - - // New encoding is hex - if tag[1] == '-' { - buf = decode(tag[2:]) - } - - // Now unmarshal - if err := json.Unmarshal(buf, &kv); err == nil { - for k, v := range kv { - md[k] = v - } - } - - // set version - ver = tag[1] - } - return md -} - -func encodeVersion(v string) []string { - return []string{"v-" + encode([]byte(v))} -} - -func decodeVersion(tags []string) (string, bool) { - for _, tag := range tags { - if len(tag) < 2 || tag[0] != 'v' { - continue - } - - // Old encoding was plain - if tag[1] == '=' { - return tag[2:], true - } - - // New encoding is hex - if tag[1] == '-' { - return string(decode(tag[2:])), true - } - } - return "", false + + return txt, nil } diff --git a/registry/encoding_test.go b/registry/encoding_test.go index ba62111e..89acd980 100644 --- a/registry/encoding_test.go +++ b/registry/encoding_test.go @@ -1,146 +1,65 @@ package registry import ( - "encoding/json" - "testing" ) -func TestEncodingEndpoints(t *testing.T) { - eps := []*Endpoint{ - &Endpoint{ - Name: "endpoint1", - Request: &Value{ - Name: "request", - Type: "request", - }, - Response: &Value{ - Name: "response", - Type: "response", - }, +func TestEncoding(t *testing.T) { + testData := []*mdnsTxt{ + &mdnsTxt{ + Version: "1.0.0", Metadata: map[string]string{ - "foo1": "bar1", + "foo": "bar", }, - }, - &Endpoint{ - Name: "endpoint2", - Request: &Value{ - Name: "request", - Type: "request", - }, - Response: &Value{ - Name: "response", - Type: "response", - }, - Metadata: map[string]string{ - "foo2": "bar2", - }, - }, - &Endpoint{ - Name: "endpoint3", - Request: &Value{ - Name: "request", - Type: "request", - }, - Response: &Value{ - Name: "response", - Type: "response", - }, - Metadata: map[string]string{ - "foo3": "bar3", + Endpoints: []*Endpoint{ + &Endpoint{ + Name: "endpoint1", + Request: &Value{ + Name: "request", + Type: "request", + }, + Response: &Value{ + Name: "response", + Type: "response", + }, + Metadata: map[string]string{ + "foo1": "bar1", + }, + }, }, }, } - testEp := func(ep *Endpoint, enc string) { - // encode endpoint - e := encodeEndpoints([]*Endpoint{ep}) - - // check there are two tags; old and new - if len(e) != 1 { - t.Fatalf("Expected 1 encoded tags, got %v", e) - } - - // check old encoding - var seen bool - - for _, en := range e { - if en == enc { - seen = true - break - } - } - - if !seen { - t.Fatalf("Expected %s but not found", enc) - } - - // decode - d := decodeEndpoints([]string{enc}) - if len(d) == 0 { - t.Fatalf("Expected %v got %v", ep, d) - } - - // check name - if d[0].Name != ep.Name { - t.Fatalf("Expected ep %s got %s", ep.Name, d[0].Name) - } - - // check all the metadata exists - for k, v := range ep.Metadata { - if gv := d[0].Metadata[k]; gv != v { - t.Fatalf("Expected key %s val %s got val %s", k, v, gv) - } - } - } - - for _, ep := range eps { - // JSON encoded - jencoded, err := json.Marshal(ep) + for _, d := range testData { + encoded, err := encode(d) if err != nil { t.Fatal(err) } - // HEX encoded - hencoded := encode(jencoded) - // endpoint tag - hepTag := "e-" + hencoded - testEp(ep, hepTag) - } -} - -func TestEncodingVersion(t *testing.T) { - testData := []struct { - decoded string - encoded string - }{ - {"1.0.0", "v-789c32d433d03300040000ffff02ce00ee"}, - {"latest", "v-789cca492c492d2e01040000ffff08cc028e"}, - } - - for _, data := range testData { - e := encodeVersion(data.decoded) - - if e[0] != data.encoded { - t.Fatalf("Expected %s got %s", data.encoded, e) - } - - d, ok := decodeVersion(e) - if !ok { - t.Fatalf("Unexpected %t for %s", ok, data.encoded) - } - - if d != data.decoded { - t.Fatalf("Expected %s got %s", data.decoded, d) - } - - d, ok = decodeVersion([]string{data.encoded}) - if !ok { - t.Fatalf("Unexpected %t for %s", ok, data.encoded) - } - - if d != data.decoded { - t.Fatalf("Expected %s got %s", data.decoded, d) - } + for _, txt := range encoded { + if len(txt) > 255 { + t.Fatalf("One of parts for txt is %d characters", len(txt)) + } + } + + decoded, err := decode(encoded) + if err != nil { + t.Fatal(err) + } + + if decoded.Version != d.Version { + t.Fatalf("Expected version %s got %s", d.Version, decoded.Version) + } + + if len(decoded.Endpoints) != len(d.Endpoints) { + t.Fatalf("Expected %d endpoints, got %d", len(d.Endpoints), len(decoded.Endpoints)) + } + + for k, v := range d.Metadata { + if val := decoded.Metadata[k]; val != v { + t.Fatalf("Expected %s=%s got %s=%s", k, v, k, val) + } + } } + } diff --git a/registry/mdns/encoding.go b/registry/mdns/encoding.go deleted file mode 100644 index d7323daf..00000000 --- a/registry/mdns/encoding.go +++ /dev/null @@ -1,73 +0,0 @@ -package mdns - -import ( - "bytes" - "compress/zlib" - "encoding/hex" - "encoding/json" - "io/ioutil" - "strings" -) - -func encode(txt *mdnsTxt) ([]string, error) { - b, err := json.Marshal(txt) - if err != nil { - return nil, err - } - - var buf bytes.Buffer - defer buf.Reset() - - w := zlib.NewWriter(&buf) - if _, err := w.Write(b); err != nil { - return nil, err - } - w.Close() - - encoded := hex.EncodeToString(buf.Bytes()) - - // individual txt limit - if len(encoded) <= 255 { - return []string{encoded}, nil - } - - // split encoded string - var record []string - - for len(encoded) > 255 { - record = append(record, encoded[:255]) - encoded = encoded[255:] - } - - record = append(record, encoded) - - return record, nil -} - -func decode(record []string) (*mdnsTxt, error) { - encoded := strings.Join(record, "") - - hr, err := hex.DecodeString(encoded) - if err != nil { - return nil, err - } - - br := bytes.NewReader(hr) - zr, err := zlib.NewReader(br) - if err != nil { - return nil, err - } - - rbuf, err := ioutil.ReadAll(zr) - if err != nil { - return nil, err - } - - var txt *mdnsTxt - - if err := json.Unmarshal(rbuf, &txt); err != nil { - return nil, err - } - - return txt, nil -} diff --git a/registry/mdns/encoding_test.go b/registry/mdns/encoding_test.go deleted file mode 100644 index baea1c59..00000000 --- a/registry/mdns/encoding_test.go +++ /dev/null @@ -1,67 +0,0 @@ -package mdns - -import ( - "testing" - - "github.com/micro/go-micro/registry" -) - -func TestEncoding(t *testing.T) { - testData := []*mdnsTxt{ - &mdnsTxt{ - Version: "1.0.0", - Metadata: map[string]string{ - "foo": "bar", - }, - Endpoints: []*registry.Endpoint{ - ®istry.Endpoint{ - Name: "endpoint1", - Request: ®istry.Value{ - Name: "request", - Type: "request", - }, - Response: ®istry.Value{ - Name: "response", - Type: "response", - }, - Metadata: map[string]string{ - "foo1": "bar1", - }, - }, - }, - }, - } - - for _, d := range testData { - encoded, err := encode(d) - if err != nil { - t.Fatal(err) - } - - for _, txt := range encoded { - if len(txt) > 255 { - t.Fatalf("One of parts for txt is %d characters", len(txt)) - } - } - - decoded, err := decode(encoded) - if err != nil { - t.Fatal(err) - } - - if decoded.Version != d.Version { - t.Fatalf("Expected version %s got %s", d.Version, decoded.Version) - } - - if len(decoded.Endpoints) != len(d.Endpoints) { - t.Fatalf("Expected %d endpoints, got %d", len(d.Endpoints), len(decoded.Endpoints)) - } - - for k, v := range d.Metadata { - if val := decoded.Metadata[k]; val != v { - t.Fatalf("Expected %s=%s got %s=%s", k, v, k, val) - } - } - } - -} diff --git a/registry/mdns/mdns.go b/registry/mdns/mdns.go index 920df3fa..6739c694 100644 --- a/registry/mdns/mdns.go +++ b/registry/mdns/mdns.go @@ -1,339 +1,11 @@ -// Package mdns is a multicast dns registry +// Package mdns provides a multicast dns registry package mdns -/* - MDNS is a multicast dns registry for service discovery - This creates a zero dependency system which is great - where multicast dns is available. This usually depends - on the ability to leverage udp and multicast/broadcast. -*/ - import ( - "net" - "strings" - "sync" - "time" - "github.com/micro/go-micro/registry" - "github.com/micro/mdns" - hash "github.com/mitchellh/hashstructure" ) -type mdnsTxt struct { - Service string - Version string - Endpoints []*registry.Endpoint - Metadata map[string]string -} - -type mdnsEntry struct { - hash uint64 - id string - node *mdns.Server -} - -type mdnsRegistry struct { - opts registry.Options - - sync.Mutex - services map[string][]*mdnsEntry -} - -func newRegistry(opts ...registry.Option) registry.Registry { - options := registry.Options{ - Timeout: time.Millisecond * 100, - } - - return &mdnsRegistry{ - opts: options, - services: make(map[string][]*mdnsEntry), - } -} - -func (m *mdnsRegistry) Init(opts ...registry.Option) error { - for _, o := range opts { - o(&m.opts) - } - return nil -} - -func (m *mdnsRegistry) Options() registry.Options { - return m.opts -} - -func (m *mdnsRegistry) Register(service *registry.Service, opts ...registry.RegisterOption) error { - m.Lock() - defer m.Unlock() - - entries, ok := m.services[service.Name] - // first entry, create wildcard used for list queries - if !ok { - s, err := mdns.NewMDNSService( - service.Name, - "_services", - "", - "", - 9999, - []net.IP{net.ParseIP("0.0.0.0")}, - nil, - ) - if err != nil { - return err - } - - srv, err := mdns.NewServer(&mdns.Config{Zone: &mdns.DNSSDService{s}}) - if err != nil { - return err - } - - // append the wildcard entry - entries = append(entries, &mdnsEntry{id: "*", node: srv}) - } - - var gerr error - - for _, node := range service.Nodes { - // create hash of service; uint64 - h, err := hash.Hash(node, nil) - if err != nil { - gerr = err - continue - } - - var seen bool - var e *mdnsEntry - - for _, entry := range entries { - if node.Id == entry.id { - seen = true - e = entry - break - } - } - - // already registered, continue - if seen && e.hash == h { - continue - // hash doesn't match, shutdown - } else if seen { - e.node.Shutdown() - // doesn't exist - } else { - e = &mdnsEntry{hash: h} - } - - txt, err := encode(&mdnsTxt{ - Service: service.Name, - Version: service.Version, - Endpoints: service.Endpoints, - Metadata: node.Metadata, - }) - - if err != nil { - gerr = err - continue - } - - // we got here, new node - s, err := mdns.NewMDNSService( - node.Id, - service.Name, - "", - "", - node.Port, - []net.IP{net.ParseIP(node.Address)}, - txt, - ) - if err != nil { - gerr = err - continue - } - - srv, err := mdns.NewServer(&mdns.Config{Zone: s}) - if err != nil { - gerr = err - continue - } - - e.id = node.Id - e.node = srv - entries = append(entries, e) - } - - // save - m.services[service.Name] = entries - - return gerr -} - -func (m *mdnsRegistry) Deregister(service *registry.Service) error { - m.Lock() - defer m.Unlock() - - var newEntries []*mdnsEntry - - // loop existing entries, check if any match, shutdown those that do - for _, entry := range m.services[service.Name] { - var remove bool - - for _, node := range service.Nodes { - if node.Id == entry.id { - entry.node.Shutdown() - remove = true - break - } - } - - // keep it? - if !remove { - newEntries = append(newEntries, entry) - } - } - - // last entry is the wildcard for list queries. Remove it. - if len(newEntries) == 1 && newEntries[0].id == "*" { - newEntries[0].node.Shutdown() - delete(m.services, service.Name) - } else { - m.services[service.Name] = newEntries - } - - return nil -} - -func (m *mdnsRegistry) GetService(service string) ([]*registry.Service, error) { - p := mdns.DefaultParams(service) - p.Timeout = m.opts.Timeout - entryCh := make(chan *mdns.ServiceEntry, 10) - p.Entries = entryCh - - exit := make(chan bool) - defer close(exit) - - serviceMap := make(map[string]*registry.Service) - - go func() { - for { - select { - case e := <-entryCh: - // list record so skip - if p.Service == "_services" { - continue - } - - if e.TTL == 0 { - continue - } - - txt, err := decode(e.InfoFields) - if err != nil { - continue - } - - if txt.Service != service { - continue - } - - s, ok := serviceMap[txt.Version] - if !ok { - s = ®istry.Service{ - Name: txt.Service, - Version: txt.Version, - Endpoints: txt.Endpoints, - } - } - - s.Nodes = append(s.Nodes, ®istry.Node{ - Id: strings.TrimSuffix(e.Name, "."+p.Service+"."+p.Domain+"."), - Address: e.AddrV4.String(), - Port: e.Port, - Metadata: txt.Metadata, - }) - - serviceMap[txt.Version] = s - case <-exit: - return - } - } - }() - - if err := mdns.Query(p); err != nil { - return nil, err - } - - // create list and return - var services []*registry.Service - - for _, service := range serviceMap { - services = append(services, service) - } - - return services, nil -} - -func (m *mdnsRegistry) ListServices() ([]*registry.Service, error) { - p := mdns.DefaultParams("_services") - p.Timeout = m.opts.Timeout - entryCh := make(chan *mdns.ServiceEntry, 10) - p.Entries = entryCh - - exit := make(chan bool) - defer close(exit) - - serviceMap := make(map[string]bool) - var services []*registry.Service - - go func() { - for { - select { - case e := <-entryCh: - if e.TTL == 0 { - continue - } - - name := strings.TrimSuffix(e.Name, "."+p.Service+"."+p.Domain+".") - if !serviceMap[name] { - serviceMap[name] = true - services = append(services, ®istry.Service{Name: name}) - } - case <-exit: - return - } - } - }() - - if err := mdns.Query(p); err != nil { - return nil, err - } - - return services, nil -} - -func (m *mdnsRegistry) Watch(opts ...registry.WatchOption) (registry.Watcher, error) { - var wo registry.WatchOptions - for _, o := range opts { - o(&wo) - } - - md := &mdnsWatcher{ - wo: wo, - ch: make(chan *mdns.ServiceEntry, 32), - exit: make(chan struct{}), - } - - go func() { - if err := mdns.Listen(md.ch, md.exit); err != nil { - md.Stop() - } - }() - - return md, nil -} - -func (m *mdnsRegistry) String() string { - return "mdns" -} - +// NewRegistry returns a new mdns registry func NewRegistry(opts ...registry.Option) registry.Registry { - return newRegistry(opts...) + return registry.NewRegistry(opts...) } diff --git a/registry/mdns_registry.go b/registry/mdns_registry.go new file mode 100644 index 00000000..70f42736 --- /dev/null +++ b/registry/mdns_registry.go @@ -0,0 +1,332 @@ +// Package mdns is a multicast dns registry +package registry + +import ( + "net" + "strings" + "sync" + "time" + + "github.com/micro/mdns" + hash "github.com/mitchellh/hashstructure" +) + +type mdnsTxt struct { + Service string + Version string + Endpoints []*Endpoint + Metadata map[string]string +} + +type mdnsEntry struct { + hash uint64 + id string + node *mdns.Server +} + +type mdnsRegistry struct { + opts Options + + sync.Mutex + services map[string][]*mdnsEntry +} + +func newRegistry(opts ...Option) Registry { + options := Options{ + Timeout: time.Millisecond * 100, + } + + return &mdnsRegistry{ + opts: options, + services: make(map[string][]*mdnsEntry), + } +} + +func (m *mdnsRegistry) Init(opts ...Option) error { + for _, o := range opts { + o(&m.opts) + } + return nil +} + +func (m *mdnsRegistry) Options() Options { + return m.opts +} + +func (m *mdnsRegistry) Register(service *Service, opts ...RegisterOption) error { + m.Lock() + defer m.Unlock() + + entries, ok := m.services[service.Name] + // first entry, create wildcard used for list queries + if !ok { + s, err := mdns.NewMDNSService( + service.Name, + "_services", + "", + "", + 9999, + []net.IP{net.ParseIP("0.0.0.0")}, + nil, + ) + if err != nil { + return err + } + + srv, err := mdns.NewServer(&mdns.Config{Zone: &mdns.DNSSDService{s}}) + if err != nil { + return err + } + + // append the wildcard entry + entries = append(entries, &mdnsEntry{id: "*", node: srv}) + } + + var gerr error + + for _, node := range service.Nodes { + // create hash of service; uint64 + h, err := hash.Hash(node, nil) + if err != nil { + gerr = err + continue + } + + var seen bool + var e *mdnsEntry + + for _, entry := range entries { + if node.Id == entry.id { + seen = true + e = entry + break + } + } + + // already registered, continue + if seen && e.hash == h { + continue + // hash doesn't match, shutdown + } else if seen { + e.node.Shutdown() + // doesn't exist + } else { + e = &mdnsEntry{hash: h} + } + + txt, err := encode(&mdnsTxt{ + Service: service.Name, + Version: service.Version, + Endpoints: service.Endpoints, + Metadata: node.Metadata, + }) + + if err != nil { + gerr = err + continue + } + + // we got here, new node + s, err := mdns.NewMDNSService( + node.Id, + service.Name, + "", + "", + node.Port, + []net.IP{net.ParseIP(node.Address)}, + txt, + ) + if err != nil { + gerr = err + continue + } + + srv, err := mdns.NewServer(&mdns.Config{Zone: s}) + if err != nil { + gerr = err + continue + } + + e.id = node.Id + e.node = srv + entries = append(entries, e) + } + + // save + m.services[service.Name] = entries + + return gerr +} + +func (m *mdnsRegistry) Deregister(service *Service) error { + m.Lock() + defer m.Unlock() + + var newEntries []*mdnsEntry + + // loop existing entries, check if any match, shutdown those that do + for _, entry := range m.services[service.Name] { + var remove bool + + for _, node := range service.Nodes { + if node.Id == entry.id { + entry.node.Shutdown() + remove = true + break + } + } + + // keep it? + if !remove { + newEntries = append(newEntries, entry) + } + } + + // last entry is the wildcard for list queries. Remove it. + if len(newEntries) == 1 && newEntries[0].id == "*" { + newEntries[0].node.Shutdown() + delete(m.services, service.Name) + } else { + m.services[service.Name] = newEntries + } + + return nil +} + +func (m *mdnsRegistry) GetService(service string) ([]*Service, error) { + p := mdns.DefaultParams(service) + p.Timeout = m.opts.Timeout + entryCh := make(chan *mdns.ServiceEntry, 10) + p.Entries = entryCh + + exit := make(chan bool) + defer close(exit) + + serviceMap := make(map[string]*Service) + + go func() { + for { + select { + case e := <-entryCh: + // list record so skip + if p.Service == "_services" { + continue + } + + if e.TTL == 0 { + continue + } + + txt, err := decode(e.InfoFields) + if err != nil { + continue + } + + if txt.Service != service { + continue + } + + s, ok := serviceMap[txt.Version] + if !ok { + s = &Service{ + Name: txt.Service, + Version: txt.Version, + Endpoints: txt.Endpoints, + } + } + + s.Nodes = append(s.Nodes, &Node{ + Id: strings.TrimSuffix(e.Name, "."+p.Service+"."+p.Domain+"."), + Address: e.AddrV4.String(), + Port: e.Port, + Metadata: txt.Metadata, + }) + + serviceMap[txt.Version] = s + case <-exit: + return + } + } + }() + + if err := mdns.Query(p); err != nil { + return nil, err + } + + // create list and return + var services []*Service + + for _, service := range serviceMap { + services = append(services, service) + } + + return services, nil +} + +func (m *mdnsRegistry) ListServices() ([]*Service, error) { + p := mdns.DefaultParams("_services") + p.Timeout = m.opts.Timeout + entryCh := make(chan *mdns.ServiceEntry, 10) + p.Entries = entryCh + + exit := make(chan bool) + defer close(exit) + + serviceMap := make(map[string]bool) + var services []*Service + + go func() { + for { + select { + case e := <-entryCh: + if e.TTL == 0 { + continue + } + + name := strings.TrimSuffix(e.Name, "."+p.Service+"."+p.Domain+".") + if !serviceMap[name] { + serviceMap[name] = true + services = append(services, &Service{Name: name}) + } + case <-exit: + return + } + } + }() + + if err := mdns.Query(p); err != nil { + return nil, err + } + + return services, nil +} + +func (m *mdnsRegistry) Watch(opts ...WatchOption) (Watcher, error) { + var wo WatchOptions + for _, o := range opts { + o(&wo) + } + + md := &mdnsWatcher{ + wo: wo, + ch: make(chan *mdns.ServiceEntry, 32), + exit: make(chan struct{}), + } + + go func() { + if err := mdns.Listen(md.ch, md.exit); err != nil { + md.Stop() + } + }() + + return md, nil +} + +func (m *mdnsRegistry) String() string { + return "mdns" +} + +// NewRegistry returns a new default registry which is mdns +func NewRegistry(opts ...Option) Registry { + return newRegistry(opts...) +} diff --git a/registry/mdns/mdns_test.go b/registry/mdns_test.go similarity index 88% rename from registry/mdns/mdns_test.go rename to registry/mdns_test.go index bdf557f6..5690fe39 100644 --- a/registry/mdns/mdns_test.go +++ b/registry/mdns_test.go @@ -1,19 +1,17 @@ -package mdns +package registry import ( "testing" "time" - - "github.com/micro/go-micro/registry" ) func TestMDNS(t *testing.T) { - testData := []*registry.Service{ - ®istry.Service{ + testData := []*Service{ + &Service{ Name: "test1", Version: "1.0.1", - Nodes: []*registry.Node{ - ®istry.Node{ + Nodes: []*Node{ + &Node{ Id: "test1-1", Address: "10.0.0.1", Port: 10001, @@ -23,11 +21,11 @@ func TestMDNS(t *testing.T) { }, }, }, - ®istry.Service{ + &Service{ Name: "test2", Version: "1.0.2", - Nodes: []*registry.Node{ - ®istry.Node{ + Nodes: []*Node{ + &Node{ Id: "test2-1", Address: "10.0.0.2", Port: 10002, @@ -37,11 +35,11 @@ func TestMDNS(t *testing.T) { }, }, }, - ®istry.Service{ + &Service{ Name: "test3", Version: "1.0.3", - Nodes: []*registry.Node{ - ®istry.Node{ + Nodes: []*Node{ + &Node{ Id: "test3-1", Address: "10.0.0.3", Port: 10003, diff --git a/registry/mdns/watcher.go b/registry/mdns_watcher.go similarity index 82% rename from registry/mdns/watcher.go rename to registry/mdns_watcher.go index 952816d2..7ccb6e80 100644 --- a/registry/mdns/watcher.go +++ b/registry/mdns_watcher.go @@ -1,20 +1,19 @@ -package mdns +package registry import ( "errors" "strings" - "github.com/micro/go-micro/registry" "github.com/micro/mdns" ) type mdnsWatcher struct { - wo registry.WatchOptions + wo WatchOptions ch chan *mdns.ServiceEntry exit chan struct{} } -func (m *mdnsWatcher) Next() (*registry.Result, error) { +func (m *mdnsWatcher) Next() (*Result, error) { for { select { case e := <-m.ch: @@ -41,7 +40,7 @@ func (m *mdnsWatcher) Next() (*registry.Result, error) { action = "create" } - service := ®istry.Service{ + service := &Service{ Name: txt.Service, Version: txt.Version, Endpoints: txt.Endpoints, @@ -52,14 +51,14 @@ func (m *mdnsWatcher) Next() (*registry.Result, error) { continue } - service.Nodes = append(service.Nodes, ®istry.Node{ + service.Nodes = append(service.Nodes, &Node{ Id: strings.TrimSuffix(e.Name, "."+service.Name+".local."), Address: e.AddrV4.String(), Port: e.Port, Metadata: txt.Metadata, }) - return ®istry.Result{ + return &Result{ Action: action, Service: service, }, nil diff --git a/registry/registry.go b/registry/registry.go index db13823e..a4df9ba2 100644 --- a/registry/registry.go +++ b/registry/registry.go @@ -26,7 +26,7 @@ type RegisterOption func(*RegisterOptions) type WatchOption func(*WatchOptions) var ( - DefaultRegistry = newConsulRegistry() + DefaultRegistry = NewRegistry() // Not found error when GetService is called ErrNotFound = errors.New("not found") @@ -34,10 +34,6 @@ var ( ErrWatcherStopped = errors.New("watcher stopped") ) -func NewRegistry(opts ...Option) Registry { - return newConsulRegistry(opts...) -} - // Register a service node. Additionally supply options such as TTL. func Register(s *Service, opts ...RegisterOption) error { return DefaultRegistry.Register(s, opts...) diff --git a/registry/mdns/watcher_test.go b/registry/watcher_test.go similarity index 86% rename from registry/mdns/watcher_test.go rename to registry/watcher_test.go index f9ff62c3..41b606b2 100644 --- a/registry/mdns/watcher_test.go +++ b/registry/watcher_test.go @@ -1,18 +1,16 @@ -package mdns +package registry import ( "testing" - - "github.com/micro/go-micro/registry" ) func TestWatcher(t *testing.T) { - testData := []*registry.Service{ - ®istry.Service{ + testData := []*Service{ + &Service{ Name: "test1", Version: "1.0.1", - Nodes: []*registry.Node{ - ®istry.Node{ + Nodes: []*Node{ + &Node{ Id: "test1-1", Address: "10.0.0.1", Port: 10001, @@ -22,11 +20,11 @@ func TestWatcher(t *testing.T) { }, }, }, - ®istry.Service{ + &Service{ Name: "test2", Version: "1.0.2", - Nodes: []*registry.Node{ - ®istry.Node{ + Nodes: []*Node{ + &Node{ Id: "test2-1", Address: "10.0.0.2", Port: 10002, @@ -36,11 +34,11 @@ func TestWatcher(t *testing.T) { }, }, }, - ®istry.Service{ + &Service{ Name: "test3", Version: "1.0.3", - Nodes: []*registry.Node{ - ®istry.Node{ + Nodes: []*Node{ + &Node{ Id: "test3-1", Address: "10.0.0.3", Port: 10003, @@ -52,7 +50,7 @@ func TestWatcher(t *testing.T) { }, } - testFn := func(service, s *registry.Service) { + testFn := func(service, s *Service) { if s == nil { t.Fatalf("Expected one result for %s got nil", service.Name) From a9c0b95603dbc14742ed65f215e0f9c44c7a8d58 Mon Sep 17 00:00:00 2001 From: Asim Aslam Date: Wed, 16 Jan 2019 13:12:21 +0000 Subject: [PATCH 117/196] update readme --- README.md | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 5f441b26..cb758113 100644 --- a/README.md +++ b/README.md @@ -19,8 +19,9 @@ Follow us on [Twitter](https://twitter.com/microhq) or join the [Slack](http://s Go Micro abstracts away the details of distributed systems. Here are the main features. - **Service Discovery** - Automatic service registration and name resolution. Service discovery is at the core of micro service -development. When service A needs to speak to service B it needs the location of that service. Consul is the default discovery -system with multicast DNS (mdns) as a local option or the SWIM protocol (gossip) for zero dependency p2p networks. +development. When service A needs to speak to service B it needs the location of that service. The default discovery mechanism is +multicast DNS (mdns), a zeroconf system. You can optionally set gossip using the SWIM protocol for p2p networks or consul for a +resilient cloud-native setup. - **Load Balancing** - Client side load balancing built on service discovery. Once we have the addresses of any number of instances of a service we now need a way to decide which node to route to. We use random hashed load balancing to provide even distribution From 784a89b4881e57b7f06591f240d8fce31f413ce6 Mon Sep 17 00:00:00 2001 From: Asim Aslam Date: Wed, 16 Jan 2019 15:27:57 +0000 Subject: [PATCH 118/196] Allow bytes.Frame to be set to sent just bytes --- client/rpc_codec.go | 6 +++--- codec/bytes/bytes.go | 25 ++++++++++++++++++------- server/rpc_codec.go | 14 +++++++++++--- 3 files changed, 32 insertions(+), 13 deletions(-) diff --git a/client/rpc_codec.go b/client/rpc_codec.go index 84be5b77..3853479d 100644 --- a/client/rpc_codec.go +++ b/client/rpc_codec.go @@ -106,12 +106,12 @@ func (c *rpcCodec) Write(m *codec.Message, body interface{}) error { m.Header["X-Micro-Service"] = m.Target m.Header["X-Micro-Endpoint"] = m.Endpoint - // if body is bytes don't encode + // if body is bytes Frame don't encode if body != nil { - b, ok := body.([]byte) + b, ok := body.(*raw.Frame) if ok { // set body - m.Body = b + m.Body = b.Data body = nil } } diff --git a/codec/bytes/bytes.go b/codec/bytes/bytes.go index f912fe34..67ff4038 100644 --- a/codec/bytes/bytes.go +++ b/codec/bytes/bytes.go @@ -13,30 +13,41 @@ type Codec struct { Conn io.ReadWriteCloser } +// Frame gives us the ability to define raw data to send over the pipes +type Frame struct { + Data []byte +} + func (c *Codec) ReadHeader(m *codec.Message, t codec.MessageType) error { return nil } func (c *Codec) ReadBody(b interface{}) error { - v, ok := b.(*[]byte) - if !ok { - return fmt.Errorf("failed to read body: %v is not type of *[]byte", b) - } - // read bytes buf, err := ioutil.ReadAll(c.Conn) if err != nil { return err } - // set bytes - *v = buf + switch b.(type) { + case *[]byte: + v := b.(*[]byte) + *v = buf + case *Frame: + v := b.(*Frame) + v.Data = buf + default: + return fmt.Errorf("failed to read body: %v is not type of *[]byte", b) + } + return nil } func (c *Codec) Write(m *codec.Message, b interface{}) error { var v []byte switch b.(type) { + case *Frame: + v = b.(*Frame).Data case *[]byte: ve := b.(*[]byte) v = *ve diff --git a/server/rpc_codec.go b/server/rpc_codec.go index da2e35ce..107ab2c9 100644 --- a/server/rpc_codec.go +++ b/server/rpc_codec.go @@ -127,6 +127,12 @@ func (c *rpcCodec) ReadBody(b interface{}) error { if len(c.req.Body) == 0 { return nil } + // read raw data + if v, ok := b.(*raw.Frame); ok { + v.Data = c.req.Body + return nil + } + // decode the usual way return c.codec.ReadBody(b) } @@ -168,8 +174,11 @@ func (c *rpcCodec) Write(r *codec.Message, b interface{}) error { // the body being sent var body []byte - // if we have encoded data just send it - if len(r.Body) > 0 { + // is it a raw frame? + if v, ok := b.(*raw.Frame); ok { + body = v.Data + // if we have encoded data just send it + } else if len(r.Body) > 0 { body = r.Body // write the body to codec } else if err := c.codec.Write(m, b); err != nil { @@ -182,7 +191,6 @@ func (c *rpcCodec) Write(r *codec.Message, b interface{}) error { if err := c.codec.Write(m, nil); err != nil { return err } - // write the body } else { // set the body body = c.buf.wbuf.Bytes() From cc5629fb6beffba98946b58b0333364076b9643a Mon Sep 17 00:00:00 2001 From: Asim Aslam Date: Wed, 16 Jan 2019 15:41:37 +0000 Subject: [PATCH 119/196] Don't return zero length services --- selector/default.go | 23 ++++++++++++++++++++++- 1 file changed, 22 insertions(+), 1 deletion(-) diff --git a/selector/default.go b/selector/default.go index 66fa332b..fbb6ca43 100644 --- a/selector/default.go +++ b/selector/default.go @@ -28,6 +28,27 @@ var ( DefaultTTL = time.Minute ) +// isValid checks if the service is valid +func (c *registrySelector) isValid(services []*registry.Service, ttl time.Time) bool { + // no services exist + if len(services) == 0 { + return false + } + + // ttl is invalid + if ttl.IsZero() { + return false + } + + // time since ttl is longer than timeout + if time.Since(ttl) > c.ttl { + return false + } + + // ok + return true +} + func (c *registrySelector) quit() bool { select { case <-c.exit: @@ -88,7 +109,7 @@ func (c *registrySelector) get(service string) ([]*registry.Service, error) { ttl, kk := c.ttls[service] // got services && within ttl so return cache - if ok && kk && time.Since(ttl) < c.ttl { + if ok && kk && c.isValid(services, ttl) { // make a copy cp := c.cp(services) // unlock the read From 082f57fcad7e092e934a7e3f240e4c4e83db7c1f Mon Sep 17 00:00:00 2001 From: Asim Aslam Date: Wed, 16 Jan 2019 15:42:42 +0000 Subject: [PATCH 120/196] We can just check nil vals --- selector/default.go | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/selector/default.go b/selector/default.go index fbb6ca43..1d4424a8 100644 --- a/selector/default.go +++ b/selector/default.go @@ -104,12 +104,12 @@ func (c *registrySelector) get(service string) ([]*registry.Service, error) { c.RLock() // check the cache first - services, ok := c.cache[service] + services := c.cache[service] // get cache ttl - ttl, kk := c.ttls[service] + ttl := c.ttls[service] // got services && within ttl so return cache - if ok && kk && c.isValid(services, ttl) { + if c.isValid(services, ttl) { // make a copy cp := c.cp(services) // unlock the read From 5b95ce7f2658296be1bf3f5dae322db8b5dd94a6 Mon Sep 17 00:00:00 2001 From: Asim Aslam Date: Wed, 16 Jan 2019 18:54:04 +0000 Subject: [PATCH 121/196] Silence broker during tests --- broker/http_broker_test.go | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/broker/http_broker_test.go b/broker/http_broker_test.go index fad91311..a2aabdd5 100644 --- a/broker/http_broker_test.go +++ b/broker/http_broker_test.go @@ -5,7 +5,9 @@ import ( "testing" "time" + glog "github.com/go-log/log" "github.com/google/uuid" + "github.com/micro/go-log" "github.com/micro/go-micro/registry/memory" ) @@ -17,6 +19,9 @@ func newTestRegistry() *memory.Registry { } func sub(be *testing.B, c int) { + // set no op logger + log.SetLogger(glog.DefaultLogger) + be.StopTimer() m := newTestRegistry() @@ -77,6 +82,9 @@ func sub(be *testing.B, c int) { } func pub(be *testing.B, c int) { + // set no op logger + log.SetLogger(glog.DefaultLogger) + be.StopTimer() m := newTestRegistry() b := NewBroker(Registry(m)) From e2e426b90c3cbd2d1ebb4b6636300799d1677aa8 Mon Sep 17 00:00:00 2001 From: Asim Aslam Date: Wed, 16 Jan 2019 18:54:32 +0000 Subject: [PATCH 122/196] Increase default pool size --- client/client.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/client/client.go b/client/client.go index 5703fd31..494d579d 100644 --- a/client/client.go +++ b/client/client.go @@ -105,7 +105,7 @@ var ( // DefaultRequestTimeout is the default request timeout DefaultRequestTimeout = time.Second * 5 // DefaultPoolSize sets the connection pool size - DefaultPoolSize = 1 + DefaultPoolSize = 100 // DefaultPoolTTL sets the connection pool ttl DefaultPoolTTL = time.Minute ) From 7b89b36e37979adf36c34efd4c0351edd75f1be7 Mon Sep 17 00:00:00 2001 From: Asim Aslam Date: Wed, 16 Jan 2019 18:54:43 +0000 Subject: [PATCH 123/196] add benchmarks --- service_test.go | 166 ++++++++++++++++++++++++++++++++++++++++-------- 1 file changed, 140 insertions(+), 26 deletions(-) diff --git a/service_test.go b/service_test.go index db4d8c42..5c2dba3f 100644 --- a/service_test.go +++ b/service_test.go @@ -2,65 +2,179 @@ package micro import ( "context" + "errors" "sync" "testing" + glog "github.com/go-log/log" + "github.com/micro/go-log" + "github.com/micro/go-micro/client" "github.com/micro/go-micro/registry/memory" proto "github.com/micro/go-micro/server/debug/proto" ) -func TestService(t *testing.T) { - var wg sync.WaitGroup +func testShutdown(wg *sync.WaitGroup, cancel func()) { + // add 1 wg.Add(1) + // shutdown the service + cancel() + // wait for stop + wg.Wait() +} - // cancellation context - ctx, cancel := context.WithCancel(context.Background()) +func testService(ctx context.Context, wg *sync.WaitGroup, name string) Service { + // set no op logger + log.SetLogger(glog.DefaultLogger) + + // add self + wg.Add(1) r := memory.NewRegistry() r.(*memory.Registry).Setup() // create service - service := NewService( - Name("test.service"), + return NewService( + Name(name), Context(ctx), Registry(r), AfterStart(func() error { wg.Done() return nil }), + AfterStop(func() error { + wg.Done() + return nil + }), + ) +} + +func testRequest(ctx context.Context, c client.Client, name string) error { + // test call debug + req := c.NewRequest( + name, + "Debug.Health", + new(proto.HealthRequest), ) - // we can't test service.Init as it parses the command line - // service.Init() + rsp := new(proto.HealthResponse) + + err := c.Call(context.TODO(), req, rsp) + if err != nil { + return err + } + + if rsp.Status != "ok" { + return errors.New("service response: " + rsp.Status) + } + + return nil +} + +// TestService tests running and calling a service +func TestService(t *testing.T) { + // waitgroup for server start + var wg sync.WaitGroup + + // cancellation context + ctx, cancel := context.WithCancel(context.Background()) + + // start test server + service := testService(ctx, &wg, "test.service") - // run service go func() { - // wait for start + // wait for service to start wg.Wait() - // test call debug - req := service.Client().NewRequest( - "test.service", - "Debug.Health", - new(proto.HealthRequest), - ) - - rsp := new(proto.HealthResponse) - - err := service.Client().Call(context.TODO(), req, rsp) - if err != nil { + // make a test call + if err := testRequest(ctx, service.Client(), "test.service"); err != nil { t.Fatal(err) } - if rsp.Status != "ok" { - t.Fatalf("service response: %s", rsp.Status) - } - // shutdown the service - cancel() + testShutdown(&wg, cancel) }() + // start service if err := service.Run(); err != nil { t.Fatal(err) } } + +func benchmarkService(b *testing.B, n int, name string) { + // stop the timer + b.StopTimer() + + // waitgroup for server start + var wg sync.WaitGroup + + // cancellation context + ctx, cancel := context.WithCancel(context.Background()) + + // create test server + service := testService(ctx, &wg, name) + + // start the server + go func() { + if err := service.Run(); err != nil { + b.Fatal(err) + } + }() + + // wait for service to start + wg.Wait() + + // make a test call to warm the cache + for i := 0; i < 10; i++ { + if err := testRequest(ctx, service.Client(), name); err != nil { + b.Fatal(err) + } + } + + // start the timer + b.StartTimer() + + // number of iterations + for i := 0; i < b.N; i++ { + // for concurrency + for j := 0; j < n; j++ { + wg.Add(1) + + go func() { + err := testRequest(ctx, service.Client(), name) + wg.Done() + if err != nil { + b.Fatal(err) + } + }() + } + + // wait for test completion + wg.Wait() + } + + // stop the timer + b.StopTimer() + + // shutdown service + testShutdown(&wg, cancel) +} + +func BenchmarkService1(b *testing.B) { + benchmarkService(b, 1, "test.service.1") +} + +func BenchmarkService8(b *testing.B) { + benchmarkService(b, 8, "test.service.8") +} + +func BenchmarkService16(b *testing.B) { + benchmarkService(b, 16, "test.service.16") +} + +func BenchmarkService32(b *testing.B) { + benchmarkService(b, 32, "test.service.32") +} + +func BenchmarkService64(b *testing.B) { + benchmarkService(b, 64, "test.service.64") +} From 617db003d40469d6b2d7847a85e1d96a787c3c16 Mon Sep 17 00:00:00 2001 From: Asim Aslam Date: Thu, 17 Jan 2019 09:40:49 +0000 Subject: [PATCH 124/196] Copy metadata --- metadata/metadata.go | 8 ++++++++ metadata/metadata_test.go | 15 +++++++++++++++ wrapper.go | 12 ++++-------- 3 files changed, 27 insertions(+), 8 deletions(-) diff --git a/metadata/metadata.go b/metadata/metadata.go index 63284bcc..3ae6ba85 100644 --- a/metadata/metadata.go +++ b/metadata/metadata.go @@ -12,6 +12,14 @@ type metaKey struct{} // from Transport headers. type Metadata map[string]string +func Copy(md Metadata) Metadata { + cmd := make(Metadata) + for k, v := range md { + cmd[k] = v + } + return cmd +} + func FromContext(ctx context.Context) (Metadata, bool) { md, ok := ctx.Value(metaKey{}).(Metadata) return md, ok diff --git a/metadata/metadata_test.go b/metadata/metadata_test.go index 4a6fd2c4..9b5545eb 100644 --- a/metadata/metadata_test.go +++ b/metadata/metadata_test.go @@ -5,6 +5,21 @@ import ( "testing" ) +func TestMetadataCopy(t *testing.T) { + md := Metadata{ + "foo": "bar", + "bar": "baz", + } + + cp := Copy(md) + + for k, v := range md { + if cv := cp[k]; cv != v { + t.Fatalf("Got %s:%s for %s:%s", k, cv, k, v) + } + } +} + func TestMetadataContext(t *testing.T) { md := Metadata{ "foo": "bar", diff --git a/wrapper.go b/wrapper.go index b7c59f04..e4977397 100644 --- a/wrapper.go +++ b/wrapper.go @@ -13,15 +13,11 @@ type clientWrapper struct { } func (c *clientWrapper) setHeaders(ctx context.Context) context.Context { - md := make(metadata.Metadata) - - if mda, ok := metadata.FromContext(ctx); ok { - // make copy of metadata - for k, v := range mda { - md[k] = v - } - } + // copy metadata + mda, _ := metadata.FromContext(ctx) + md := metadata.Copy(mda) + // set headers for k, v := range c.headers { if _, ok := md[k]; !ok { md[k] = v From 9ce9977d2183a6c01b23b5aeee4a20f9f43abd43 Mon Sep 17 00:00:00 2001 From: Asim Aslam Date: Thu, 17 Jan 2019 12:09:04 +0000 Subject: [PATCH 125/196] Don't read unless we have b --- codec/proto/proto.go | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/codec/proto/proto.go b/codec/proto/proto.go index b70b4c84..d79d5166 100644 --- a/codec/proto/proto.go +++ b/codec/proto/proto.go @@ -18,13 +18,13 @@ func (c *Codec) ReadHeader(m *codec.Message, t codec.MessageType) error { } func (c *Codec) ReadBody(b interface{}) error { + if b == nil { + return nil + } buf, err := ioutil.ReadAll(c.Conn) if err != nil { return err } - if b == nil { - return nil - } return proto.Unmarshal(buf, b.(proto.Message)) } From 2cd2258731b7b0a7ea9d3d150677e101487db020 Mon Sep 17 00:00:00 2001 From: Asim Aslam Date: Fri, 18 Jan 2019 10:12:57 +0000 Subject: [PATCH 126/196] For the legacy --- client/client.go | 4 +++- client/rpc_codec.go | 9 +++++++- client/rpc_request.go | 6 ++++++ client/rpc_stream.go | 1 + codec/codec.go | 1 + codec/jsonrpc/client.go | 6 +++--- codec/jsonrpc/server.go | 2 +- codec/protorpc/protorpc.go | 8 +++---- server/rpc_codec.go | 44 ++++++++++++++++++++++++++++++++++++++ server/rpc_request.go | 5 +++++ server/rpc_router.go | 1 + server/rpc_server.go | 29 +++++++++++++++---------- server/rpc_stream.go | 2 ++ server/server.go | 2 ++ 14 files changed, 99 insertions(+), 21 deletions(-) diff --git a/client/client.go b/client/client.go index 494d579d..80d7f49b 100644 --- a/client/client.go +++ b/client/client.go @@ -38,7 +38,9 @@ type Message interface { type Request interface { // The service to call Service() string - // The endpoint to call + // The action to take + Method() string + // The endpoint to invoke Endpoint() string // The content type ContentType() string diff --git a/client/rpc_codec.go b/client/rpc_codec.go index 3853479d..ece77f05 100644 --- a/client/rpc_codec.go +++ b/client/rpc_codec.go @@ -104,6 +104,7 @@ func (c *rpcCodec) Write(m *codec.Message, body interface{}) error { // set the mucp headers m.Header["X-Micro-Id"] = m.Id m.Header["X-Micro-Service"] = m.Target + m.Header["X-Micro-Method"] = m.Method m.Header["X-Micro-Endpoint"] = m.Endpoint // if body is bytes Frame don't encode @@ -154,6 +155,7 @@ func (c *rpcCodec) ReadHeader(wm *codec.Message, r codec.MessageType) error { // read header err := c.codec.ReadHeader(&me, r) wm.Endpoint = me.Endpoint + wm.Method = me.Method wm.Id = me.Id wm.Error = me.Error @@ -162,11 +164,16 @@ func (c *rpcCodec) ReadHeader(wm *codec.Message, r codec.MessageType) error { wm.Error = me.Header["X-Micro-Error"] } - // check method in header + // check endpoint in header if len(me.Endpoint) == 0 { wm.Endpoint = me.Header["X-Micro-Endpoint"] } + // check method in header + if len(me.Method) == 0 { + wm.Method = me.Header["X-Micro-Method"] + } + if len(me.Id) == 0 { wm.Id = me.Header["X-Micro-Id"] } diff --git a/client/rpc_request.go b/client/rpc_request.go index 746b4be5..d23855f0 100644 --- a/client/rpc_request.go +++ b/client/rpc_request.go @@ -6,6 +6,7 @@ import ( type rpcRequest struct { service string + method string endpoint string contentType string codec codec.Codec @@ -27,6 +28,7 @@ func newRequest(service, endpoint string, request interface{}, contentType strin return &rpcRequest{ service: service, + method: endpoint, endpoint: endpoint, body: request, contentType: contentType, @@ -42,6 +44,10 @@ func (r *rpcRequest) Service() string { return r.service } +func (r *rpcRequest) Method() string { + return r.method +} + func (r *rpcRequest) Endpoint() string { return r.endpoint } diff --git a/client/rpc_stream.go b/client/rpc_stream.go index 39e82fe4..21b2d2b3 100644 --- a/client/rpc_stream.go +++ b/client/rpc_stream.go @@ -53,6 +53,7 @@ func (r *rpcStream) Send(msg interface{}) error { req := codec.Message{ Id: r.id, Target: r.request.Service(), + Method: r.request.Method(), Endpoint: r.request.Endpoint(), Type: codec.Request, } diff --git a/codec/codec.go b/codec/codec.go index 868d2dd1..092caa05 100644 --- a/codec/codec.go +++ b/codec/codec.go @@ -53,6 +53,7 @@ type Message struct { Id string Type MessageType Target string + Method string Endpoint string Error string diff --git a/codec/jsonrpc/client.go b/codec/jsonrpc/client.go index 768e297d..f5ec5636 100644 --- a/codec/jsonrpc/client.go +++ b/codec/jsonrpc/client.go @@ -45,9 +45,9 @@ func newClientCodec(conn io.ReadWriteCloser) *clientCodec { func (c *clientCodec) Write(m *codec.Message, b interface{}) error { c.Lock() - c.pending[m.Id] = m.Endpoint + c.pending[m.Id] = m.Method c.Unlock() - c.req.Method = m.Endpoint + c.req.Method = m.Method c.req.Params[0] = b c.req.ID = m.Id return c.enc.Encode(&c.req) @@ -66,7 +66,7 @@ func (c *clientCodec) ReadHeader(m *codec.Message) error { } c.Lock() - m.Endpoint = c.pending[c.resp.ID] + m.Method = c.pending[c.resp.ID] delete(c.pending, c.resp.ID) c.Unlock() diff --git a/codec/jsonrpc/server.go b/codec/jsonrpc/server.go index a56b3468..53f681ef 100644 --- a/codec/jsonrpc/server.go +++ b/codec/jsonrpc/server.go @@ -53,7 +53,7 @@ func (c *serverCodec) ReadHeader(m *codec.Message) error { if err := c.dec.Decode(&c.req); err != nil { return err } - m.Endpoint = c.req.Method + m.Method = c.req.Method m.Id = fmt.Sprintf("%v", c.req.ID) c.req.ID = nil return nil diff --git a/codec/protorpc/protorpc.go b/codec/protorpc/protorpc.go index f207e5ae..4732b98e 100644 --- a/codec/protorpc/protorpc.go +++ b/codec/protorpc/protorpc.go @@ -47,7 +47,7 @@ func (c *protoCodec) Write(m *codec.Message, b interface{}) error { c.Lock() defer c.Unlock() // This is protobuf, of course we copy it. - pbr := &Request{ServiceMethod: &m.Endpoint, Seq: id(m.Id)} + pbr := &Request{ServiceMethod: &m.Method, Seq: id(m.Id)} data, err := proto.Marshal(pbr) if err != nil { return err @@ -73,7 +73,7 @@ func (c *protoCodec) Write(m *codec.Message, b interface{}) error { case codec.Response, codec.Error: c.Lock() defer c.Unlock() - rtmp := &Response{ServiceMethod: &m.Endpoint, Seq: id(m.Id), Error: &m.Error} + rtmp := &Response{ServiceMethod: &m.Method, Seq: id(m.Id), Error: &m.Error} data, err := proto.Marshal(rtmp) if err != nil { return err @@ -126,7 +126,7 @@ func (c *protoCodec) ReadHeader(m *codec.Message, mt codec.MessageType) error { if err != nil { return err } - m.Endpoint = rtmp.GetServiceMethod() + m.Method = rtmp.GetServiceMethod() m.Id = fmt.Sprintf("%d", rtmp.GetSeq()) case codec.Response: data, err := ReadNetString(c.rwc) @@ -138,7 +138,7 @@ func (c *protoCodec) ReadHeader(m *codec.Message, mt codec.MessageType) error { if err != nil { return err } - m.Endpoint = rtmp.GetServiceMethod() + m.Method = rtmp.GetServiceMethod() m.Id = fmt.Sprintf("%d", rtmp.GetSeq()) m.Error = rtmp.GetError() case codec.Publication: diff --git a/server/rpc_codec.go b/server/rpc_codec.go index 107ab2c9..847c5ae9 100644 --- a/server/rpc_codec.go +++ b/server/rpc_codec.go @@ -41,6 +41,15 @@ var ( "application/proto-rpc": protorpc.NewCodec, "application/octet-stream": raw.NewCodec, } + + // TODO: remove legacy codec list + defaultCodecs = map[string]codec.NewCodec{ + "application/json": jsonrpc.NewCodec, + "application/json-rpc": jsonrpc.NewCodec, + "application/protobuf": protorpc.NewCodec, + "application/proto-rpc": protorpc.NewCodec, + "application/octet-stream": protorpc.NewCodec, + } ) func (rwc *readWriteCloser) Read(p []byte) (n int, err error) { @@ -57,6 +66,33 @@ func (rwc *readWriteCloser) Close() error { return nil } +// setupProtocol sets up the old protocol +func setupProtocol(msg *transport.Message) codec.NewCodec { + // if the protocol exists do nothing + if len(msg.Header["X-Micro-Protocol"]) > 0 { + return nil + } + + // if 0.17 - 0.21 + if len(msg.Header["X-Micro-Service"]) > 0 { + // set method to endpoint + if len(msg.Header["X-Micro-Method"]) == 0 { + msg.Header["X-Micro-Method"] = msg.Header["X-Micro-Endpoint"] + } + + // set endpoint to method + if len(msg.Header["X-Micro-Endpoint"]) == 0 { + msg.Header["X-Micro-Endpoint"] = msg.Header["X-Micro-Method"] + } + + // done + return nil + } + + // old ways + return defaultCodecs[msg.Header["Content-Type"]] +} + func newRpcCodec(req *transport.Message, socket transport.Socket, c codec.NewCodec) codec.Codec { rwc := &readWriteCloser{ rbuf: bytes.NewBuffer(req.Body), @@ -109,6 +145,7 @@ func (c *rpcCodec) ReadHeader(r *codec.Message, t codec.MessageType) error { // set some internal things m.Target = m.Header["X-Micro-Service"] + m.Method = m.Header["X-Micro-Method"] m.Endpoint = m.Header["X-Micro-Endpoint"] m.Id = m.Header["X-Micro-Id"] @@ -141,6 +178,8 @@ func (c *rpcCodec) Write(r *codec.Message, b interface{}) error { // create a new message m := &codec.Message{ + Target: r.Target, + Method: r.Method, Endpoint: r.Endpoint, Id: r.Id, Error: r.Error, @@ -162,6 +201,11 @@ func (c *rpcCodec) Write(r *codec.Message, b interface{}) error { m.Header["X-Micro-Service"] = r.Target } + // set request method + if len(r.Method) > 0 { + m.Header["X-Micro-Method"] = r.Method + } + // set request endpoint if len(r.Endpoint) > 0 { m.Header["X-Micro-Endpoint"] = r.Endpoint diff --git a/server/rpc_request.go b/server/rpc_request.go index 17ede91b..6496bc52 100644 --- a/server/rpc_request.go +++ b/server/rpc_request.go @@ -7,6 +7,7 @@ import ( type rpcRequest struct { service string + method string endpoint string contentType string socket transport.Socket @@ -34,6 +35,10 @@ func (r *rpcRequest) Service() string { return r.service } +func (r *rpcRequest) Method() string { + return r.method +} + func (r *rpcRequest) Endpoint() string { return r.endpoint } diff --git a/server/rpc_router.go b/server/rpc_router.go index dee976e8..111b3fde 100644 --- a/server/rpc_router.go +++ b/server/rpc_router.go @@ -189,6 +189,7 @@ func (s *service) call(ctx context.Context, router *router, sending *sync.Mutex, r := &rpcRequest{ service: req.msg.Target, contentType: req.msg.Header["Content-Type"], + method: req.msg.Method, endpoint: req.msg.Endpoint, body: req.msg.Body, } diff --git a/server/rpc_server.go b/server/rpc_server.go index f2a7042c..757c90ad 100644 --- a/server/rpc_server.go +++ b/server/rpc_server.go @@ -97,17 +97,23 @@ func (s *rpcServer) ServeConn(sock transport.Socket) { ct = DefaultContentType } - // TODO: needs better error handling - cf, err := s.newCodec(ct) - if err != nil { - sock.Send(&transport.Message{ - Header: map[string]string{ - "Content-Type": "text/plain", - }, - Body: []byte(err.Error()), - }) - s.wg.Done() - return + // setup old protocol + cf := setupProtocol(&msg) + + // no old codec + if cf == nil { + // TODO: needs better error handling + var err error + if cf, err = s.newCodec(ct); err != nil { + sock.Send(&transport.Message{ + Header: map[string]string{ + "Content-Type": "text/plain", + }, + Body: []byte(err.Error()), + }) + s.wg.Done() + return + } } rcodec := newRpcCodec(&msg, sock, cf) @@ -115,6 +121,7 @@ func (s *rpcServer) ServeConn(sock transport.Socket) { // internal request request := &rpcRequest{ service: msg.Header["X-Micro-Service"], + method: msg.Header["X-Micro-Method"], endpoint: msg.Header["X-Micro-Endpoint"], contentType: ct, codec: rcodec, diff --git a/server/rpc_stream.go b/server/rpc_stream.go index 2f74049a..dc49b18a 100644 --- a/server/rpc_stream.go +++ b/server/rpc_stream.go @@ -31,6 +31,8 @@ func (r *rpcStream) Send(msg interface{}) error { defer r.Unlock() resp := codec.Message{ + Target: r.request.Service(), + Method: r.request.Method(), Endpoint: r.request.Endpoint(), Id: r.id, Type: codec.Response, diff --git a/server/server.go b/server/server.go index 6f7c2712..82113843 100644 --- a/server/server.go +++ b/server/server.go @@ -45,6 +45,8 @@ type Message interface { type Request interface { // Service name requested Service() string + // The action requested + Method() string // Endpoint name requested Endpoint() string // Content type provided From f41be53ff8f51295eddec13d1a71bcfa27165cc1 Mon Sep 17 00:00:00 2001 From: Asim Aslam Date: Fri, 18 Jan 2019 10:23:36 +0000 Subject: [PATCH 127/196] Add ability to process legacy requests --- server/rpc_codec.go | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/server/rpc_codec.go b/server/rpc_codec.go index 847c5ae9..a06c3c3c 100644 --- a/server/rpc_codec.go +++ b/server/rpc_codec.go @@ -153,9 +153,15 @@ func (c *rpcCodec) ReadHeader(r *codec.Message, t codec.MessageType) error { err := c.codec.ReadHeader(&m, codec.Request) // set the method/id + r.Method = m.Method r.Endpoint = m.Endpoint r.Id = m.Id + // TODO: remove the old legacy cruft + if len(r.Endpoint) == 0 { + r.Endpoint = r.Method + } + return err } From 9bd32645be7090d20c68c941b9f7891f525513d3 Mon Sep 17 00:00:00 2001 From: Asim Aslam Date: Fri, 18 Jan 2019 10:43:41 +0000 Subject: [PATCH 128/196] Account for old target --- server/rpc_codec.go | 45 +++++++++++++++++++++++++++------------------ 1 file changed, 27 insertions(+), 18 deletions(-) diff --git a/server/rpc_codec.go b/server/rpc_codec.go index a06c3c3c..261b5fd1 100644 --- a/server/rpc_codec.go +++ b/server/rpc_codec.go @@ -68,29 +68,38 @@ func (rwc *readWriteCloser) Close() error { // setupProtocol sets up the old protocol func setupProtocol(msg *transport.Message) codec.NewCodec { - // if the protocol exists do nothing - if len(msg.Header["X-Micro-Protocol"]) > 0 { + service := msg.Header["X-Micro-Service"] + method := msg.Header["X-Micro-Method"] + endpoint := msg.Header["X-Micro-Endpoint"] + protocol := msg.Header["X-Micro-Protocol"] + target := msg.Header["X-Micro-Target"] + + // if the protocol exists (mucp) do nothing + if len(protocol) > 0 { return nil } - // if 0.17 - 0.21 - if len(msg.Header["X-Micro-Service"]) > 0 { - // set method to endpoint - if len(msg.Header["X-Micro-Method"]) == 0 { - msg.Header["X-Micro-Method"] = msg.Header["X-Micro-Endpoint"] - } - - // set endpoint to method - if len(msg.Header["X-Micro-Endpoint"]) == 0 { - msg.Header["X-Micro-Endpoint"] = msg.Header["X-Micro-Method"] - } - - // done - return nil + // if no service/method/endpoint then it's the old protocol + if len(service) == 0 && len(method) == 0 && len(endpoint) == 0 { + return defaultCodecs[msg.Header["Content-Type"]] } - // old ways - return defaultCodecs[msg.Header["Content-Type"]] + // old target method specified + if len(target) > 0 { + return defaultCodecs[msg.Header["Content-Type"]] + } + + // no method then set to endpoint + if len(method) == 0 { + msg.Header["X-Micro-Method"] = method + } + + // no endpoint then set to method + if len(endpoint) == 0 { + msg.Header["X-Micro-Endpoint"] = method + } + + return nil } func newRpcCodec(req *transport.Message, socket transport.Socket, c codec.NewCodec) codec.Codec { From 6468733d98f1084c188e4c523dd8e63b7f8eb076 Mon Sep 17 00:00:00 2001 From: Asim Aslam Date: Fri, 18 Jan 2019 12:30:39 +0000 Subject: [PATCH 129/196] Use protocol from node metadata --- client/rpc_client.go | 72 ++++++++++++++++++++++++++------------- client/rpc_client_test.go | 30 +++++++++------- client/rpc_codec.go | 31 +++++++++++++++++ client/rpc_request.go | 4 +-- client/rpc_stream.go | 2 +- client/wrapper.go | 4 ++- server/rpc_server.go | 1 + 7 files changed, 103 insertions(+), 41 deletions(-) diff --git a/client/rpc_client.go b/client/rpc_client.go index 16db46cf..3028d366 100644 --- a/client/rpc_client.go +++ b/client/rpc_client.go @@ -4,10 +4,11 @@ import ( "bytes" "context" "fmt" + "net" + "strconv" "sync" - "time" - "sync/atomic" + "time" "github.com/google/uuid" "github.com/micro/go-micro/broker" @@ -56,7 +57,12 @@ func (r *rpcClient) newCodec(contentType string) (codec.NewCodec, error) { return nil, fmt.Errorf("Unsupported Content-Type: %s", contentType) } -func (r *rpcClient) call(ctx context.Context, address string, req Request, resp interface{}, opts CallOptions) error { +func (r *rpcClient) call(ctx context.Context, node *registry.Node, req Request, resp interface{}, opts CallOptions) error { + address := node.Address + if node.Port > 0 { + address = fmt.Sprintf("%s:%d", address, node.Port) + } + msg := &transport.Message{ Header: make(map[string]string), } @@ -75,9 +81,16 @@ func (r *rpcClient) call(ctx context.Context, address string, req Request, resp // set the accept header msg.Header["Accept"] = req.ContentType() - cf, err := r.newCodec(req.ContentType()) - if err != nil { - return errors.InternalServerError("go.micro.client", err.Error()) + // setup old protocol + cf := setupProtocol(msg, node) + + // no codec specified + if cf == nil { + var err error + cf, err = r.newCodec(req.ContentType()) + if err != nil { + return errors.InternalServerError("go.micro.client", err.Error()) + } } var grr error @@ -144,7 +157,12 @@ func (r *rpcClient) call(ctx context.Context, address string, req Request, resp } } -func (r *rpcClient) stream(ctx context.Context, address string, req Request, opts CallOptions) (Stream, error) { +func (r *rpcClient) stream(ctx context.Context, node *registry.Node, req Request, opts CallOptions) (Stream, error) { + address := node.Address + if node.Port > 0 { + address = fmt.Sprintf("%s:%d", address, node.Port) + } + msg := &transport.Message{ Header: make(map[string]string), } @@ -163,9 +181,16 @@ func (r *rpcClient) stream(ctx context.Context, address string, req Request, opt // set the accept header msg.Header["Accept"] = req.ContentType() - cf, err := r.newCodec(req.ContentType()) - if err != nil { - return nil, errors.InternalServerError("go.micro.client", err.Error()) + // set old codecs + cf := setupProtocol(msg, node) + + // no codec specified + if cf == nil { + var err error + cf, err = r.newCodec(req.ContentType()) + if err != nil { + return nil, errors.InternalServerError("go.micro.client", err.Error()) + } } dOpts := []transport.DialOption{ @@ -245,9 +270,19 @@ func (r *rpcClient) Options() Options { func (r *rpcClient) next(request Request, opts CallOptions) (selector.Next, error) { // return remote address if len(opts.Address) > 0 { + address := opts.Address + port := 0 + + host, sport, err := net.SplitHostPort(opts.Address) + if err == nil { + address = host + port, _ = strconv.Atoi(sport) + } + return func() (*registry.Node, error) { return ®istry.Node{ - Address: opts.Address, + Address: address, + Port: port, }, nil }, nil } @@ -323,14 +358,8 @@ func (r *rpcClient) Call(ctx context.Context, request Request, response interfac return errors.InternalServerError("go.micro.client", "error getting next %s node: %v", request.Service(), err.Error()) } - // set the address - address := node.Address - if node.Port > 0 { - address = fmt.Sprintf("%s:%d", address, node.Port) - } - // make the call - err = rcall(ctx, address, request, response, callOpts) + err = rcall(ctx, node, request, response, callOpts) r.opts.Selector.Mark(request.Service(), node, err) return err } @@ -406,12 +435,7 @@ func (r *rpcClient) Stream(ctx context.Context, request Request, opts ...CallOpt return nil, errors.InternalServerError("go.micro.client", "error getting next %s node: %v", request.Service(), err.Error()) } - address := node.Address - if node.Port > 0 { - address = fmt.Sprintf("%s:%d", address, node.Port) - } - - stream, err := r.stream(ctx, address, request, callOpts) + stream, err := r.stream(ctx, node, request, callOpts) r.opts.Selector.Mark(request.Service(), node, err) return stream, err } diff --git a/client/rpc_client_test.go b/client/rpc_client_test.go index 33b5a493..26fa1e77 100644 --- a/client/rpc_client_test.go +++ b/client/rpc_client_test.go @@ -21,10 +21,11 @@ func TestCallAddress(t *testing.T) { var called bool service := "test.service" endpoint := "Test.Endpoint" - address := "10.1.10.1:8080" + address := "10.1.10.1" + port := 8080 wrap := func(cf CallFunc) CallFunc { - return func(ctx context.Context, addr string, req Request, rsp interface{}, opts CallOptions) error { + return func(ctx context.Context, node *registry.Node, req Request, rsp interface{}, opts CallOptions) error { called = true if req.Service() != service { @@ -35,8 +36,12 @@ func TestCallAddress(t *testing.T) { return fmt.Errorf("expected service: %s got %s", endpoint, req.Endpoint()) } - if addr != address { - return fmt.Errorf("expected address: %s got %s", address, addr) + if node.Address != address { + return fmt.Errorf("expected address: %s got %s", address, node.Address) + } + + if node.Port != port { + return fmt.Errorf("expected address: %d got %d", port, node.Port) } // don't do the call @@ -54,7 +59,7 @@ func TestCallAddress(t *testing.T) { req := c.NewRequest(service, endpoint, nil) // test calling remote address - if err := c.Call(context.Background(), req, nil, WithAddress(address)); err != nil { + if err := c.Call(context.Background(), req, nil, WithAddress(fmt.Sprintf("%s:%d", address, port))); err != nil { t.Fatal("call with address error", err) } @@ -67,12 +72,12 @@ func TestCallAddress(t *testing.T) { func TestCallRetry(t *testing.T) { service := "test.service" endpoint := "Test.Endpoint" - address := "10.1.10.1:8080" + address := "10.1.10.1" var called int wrap := func(cf CallFunc) CallFunc { - return func(ctx context.Context, addr string, req Request, rsp interface{}, opts CallOptions) error { + return func(ctx context.Context, node *registry.Node, req Request, rsp interface{}, opts CallOptions) error { called++ if called == 1 { return errors.InternalServerError("test.error", "retry request") @@ -108,12 +113,11 @@ func TestCallWrapper(t *testing.T) { id := "test.1" service := "test.service" endpoint := "Test.Endpoint" - host := "10.1.10.1" + address := "10.1.10.1" port := 8080 - address := "10.1.10.1:8080" wrap := func(cf CallFunc) CallFunc { - return func(ctx context.Context, addr string, req Request, rsp interface{}, opts CallOptions) error { + return func(ctx context.Context, node *registry.Node, req Request, rsp interface{}, opts CallOptions) error { called = true if req.Service() != service { @@ -124,8 +128,8 @@ func TestCallWrapper(t *testing.T) { return fmt.Errorf("expected service: %s got %s", endpoint, req.Endpoint()) } - if addr != address { - return fmt.Errorf("expected address: %s got %s", address, addr) + if node.Address != address { + return fmt.Errorf("expected address: %s got %s", address, node.Address) } // don't do the call @@ -146,7 +150,7 @@ func TestCallWrapper(t *testing.T) { Nodes: []*registry.Node{ ®istry.Node{ Id: id, - Address: host, + Address: address, Port: port, }, }, diff --git a/client/rpc_codec.go b/client/rpc_codec.go index ece77f05..35f64e41 100644 --- a/client/rpc_codec.go +++ b/client/rpc_codec.go @@ -12,6 +12,7 @@ import ( "github.com/micro/go-micro/codec/proto" "github.com/micro/go-micro/codec/protorpc" "github.com/micro/go-micro/errors" + "github.com/micro/go-micro/registry" "github.com/micro/go-micro/transport" ) @@ -58,6 +59,15 @@ var ( "application/proto-rpc": protorpc.NewCodec, "application/octet-stream": raw.NewCodec, } + + // TODO: remove legacy codec list + defaultCodecs = map[string]codec.NewCodec{ + "application/json": jsonrpc.NewCodec, + "application/json-rpc": jsonrpc.NewCodec, + "application/protobuf": protorpc.NewCodec, + "application/proto-rpc": protorpc.NewCodec, + "application/octet-stream": protorpc.NewCodec, + } ) func (rwc *readWriteCloser) Read(p []byte) (n int, err error) { @@ -74,6 +84,27 @@ func (rwc *readWriteCloser) Close() error { return nil } +// setupProtocol sets up the old protocol +func setupProtocol(msg *transport.Message, node *registry.Node) codec.NewCodec { + protocol := node.Metadata["protocol"] + + // got protocol + if len(protocol) > 0 { + return nil + } + + // no protocol use old codecs + switch msg.Header["Content-Type"] { + case "application/json": + msg.Header["Content-Type"] = "application/json-rpc" + case "application/protobuf": + msg.Header["Content-Type"] = "application/proto-rpc" + } + + // now return codec + return defaultCodecs[msg.Header["Content-Type"]] +} + func newRpcCodec(req *transport.Message, client transport.Client, c codec.NewCodec) codec.Codec { rwc := &readWriteCloser{ wbuf: bytes.NewBuffer(nil), diff --git a/client/rpc_request.go b/client/rpc_request.go index d23855f0..7fd5762b 100644 --- a/client/rpc_request.go +++ b/client/rpc_request.go @@ -6,7 +6,7 @@ import ( type rpcRequest struct { service string - method string + method string endpoint string contentType string codec codec.Codec @@ -28,7 +28,7 @@ func newRequest(service, endpoint string, request interface{}, contentType strin return &rpcRequest{ service: service, - method: endpoint, + method: endpoint, endpoint: endpoint, body: request, contentType: contentType, diff --git a/client/rpc_stream.go b/client/rpc_stream.go index 21b2d2b3..f605c11e 100644 --- a/client/rpc_stream.go +++ b/client/rpc_stream.go @@ -53,7 +53,7 @@ func (r *rpcStream) Send(msg interface{}) error { req := codec.Message{ Id: r.id, Target: r.request.Service(), - Method: r.request.Method(), + Method: r.request.Method(), Endpoint: r.request.Endpoint(), Type: codec.Request, } diff --git a/client/wrapper.go b/client/wrapper.go index aacb5ae5..ab86dcd1 100644 --- a/client/wrapper.go +++ b/client/wrapper.go @@ -2,10 +2,12 @@ package client import ( "context" + + "github.com/micro/go-micro/registry" ) // CallFunc represents the individual call func -type CallFunc func(ctx context.Context, address string, req Request, rsp interface{}, opts CallOptions) error +type CallFunc func(ctx context.Context, node *registry.Node, req Request, rsp interface{}, opts CallOptions) error // CallWrapper is a low level wrapper for the CallFunc type CallWrapper func(CallFunc) CallFunc diff --git a/server/rpc_server.go b/server/rpc_server.go index 757c90ad..1afeff6e 100644 --- a/server/rpc_server.go +++ b/server/rpc_server.go @@ -283,6 +283,7 @@ func (s *rpcServer) Register() error { node.Metadata["broker"] = config.Broker.String() node.Metadata["server"] = s.String() node.Metadata["registry"] = config.Registry.String() + node.Metadata["protocol"] = "mucp" s.RLock() // Maps are ordered randomly, sort the keys for consistency From 48b80dd051787fa0749f061d07a422b33effe915 Mon Sep 17 00:00:00 2001 From: Asim Aslam Date: Fri, 18 Jan 2019 17:29:17 +0000 Subject: [PATCH 130/196] replace memory registry --- registry/memory/data.go | 51 +++++++++++ registry/memory/memory.go | 157 ++++++++++++++++++-------------- registry/memory/memory_test.go | 9 +- registry/memory/options.go | 27 ++++++ registry/memory/watcher.go | 37 ++++++++ registry/memory/watcher_test.go | 30 ++++++ 6 files changed, 237 insertions(+), 74 deletions(-) create mode 100644 registry/memory/data.go create mode 100644 registry/memory/options.go create mode 100644 registry/memory/watcher.go create mode 100644 registry/memory/watcher_test.go diff --git a/registry/memory/data.go b/registry/memory/data.go new file mode 100644 index 00000000..7999fea8 --- /dev/null +++ b/registry/memory/data.go @@ -0,0 +1,51 @@ +package memory + +import ( + "github.com/micro/go-micro/registry" +) + +var ( + // mock data + Data = map[string][]*registry.Service{ + "foo": []*registry.Service{ + { + Name: "foo", + Version: "1.0.0", + Nodes: []*registry.Node{ + { + Id: "foo-1.0.0-123", + Address: "localhost", + Port: 9999, + }, + { + Id: "foo-1.0.0-321", + Address: "localhost", + Port: 9999, + }, + }, + }, + { + Name: "foo", + Version: "1.0.1", + Nodes: []*registry.Node{ + { + Id: "foo-1.0.1-321", + Address: "localhost", + Port: 6666, + }, + }, + }, + { + Name: "foo", + Version: "1.0.3", + Nodes: []*registry.Node{ + { + Id: "foo-1.0.3-345", + Address: "localhost", + Port: 8888, + }, + }, + }, + }, + } +) diff --git a/registry/memory/memory.go b/registry/memory/memory.go index f516720a..64b7d4ca 100644 --- a/registry/memory/memory.go +++ b/registry/memory/memory.go @@ -2,60 +2,24 @@ package memory import ( + "context" "sync" + "time" + "github.com/google/uuid" "github.com/micro/go-micro/registry" ) type Registry struct { + options registry.Options + sync.RWMutex Services map[string][]*registry.Service + Watchers map[string]*Watcher } var ( - // mock data - Data = map[string][]*registry.Service{ - "foo": []*registry.Service{ - { - Name: "foo", - Version: "1.0.0", - Nodes: []*registry.Node{ - { - Id: "foo-1.0.0-123", - Address: "localhost", - Port: 9999, - }, - { - Id: "foo-1.0.0-321", - Address: "localhost", - Port: 9999, - }, - }, - }, - { - Name: "foo", - Version: "1.0.1", - Nodes: []*registry.Node{ - { - Id: "foo-1.0.1-321", - Address: "localhost", - Port: 6666, - }, - }, - }, - { - Name: "foo", - Version: "1.0.3", - Nodes: []*registry.Node{ - { - Id: "foo-1.0.3-345", - Address: "localhost", - Port: 8888, - }, - }, - }, - }, - } + timeout = time.Millisecond * 10 ) // Setup sets mock data @@ -67,69 +31,130 @@ func (m *Registry) Setup() { m.Services = Data } -func (m *Registry) GetService(service string) ([]*registry.Service, error) { - m.Lock() - defer m.Unlock() +func (m *Registry) watch(r *registry.Result) { + var watchers []*Watcher + m.RLock() + for _, w := range m.Watchers { + watchers = append(watchers, w) + } + m.RUnlock() + + for _, w := range watchers { + select { + case <-w.exit: + m.Lock() + delete(m.Watchers, w.id) + m.Unlock() + default: + select { + case w.res <- r: + case <-time.After(timeout): + } + } + } +} + +func (m *Registry) Init(opts ...registry.Option) error { + for _, o := range opts { + o(&m.options) + } + + // add services + m.Lock() + for k, v := range getServices(m.options.Context) { + s := m.Services[k] + m.Services[k] = addServices(s, v) + } + m.Unlock() + return nil +} + +func (m *Registry) Options() registry.Options { + return m.options +} + +func (m *Registry) GetService(service string) ([]*registry.Service, error) { + m.RLock() s, ok := m.Services[service] if !ok || len(s) == 0 { + m.RUnlock() return nil, registry.ErrNotFound } + m.RUnlock() return s, nil - } func (m *Registry) ListServices() ([]*registry.Service, error) { - m.Lock() - defer m.Unlock() - + m.RLock() var services []*registry.Service for _, service := range m.Services { services = append(services, service...) } + m.RUnlock() return services, nil } func (m *Registry) Register(s *registry.Service, opts ...registry.RegisterOption) error { - m.Lock() - defer m.Unlock() + go m.watch(®istry.Result{Action: "update", Service: s}) + m.Lock() services := addServices(m.Services[s.Name], []*registry.Service{s}) m.Services[s.Name] = services + m.Unlock() return nil } func (m *Registry) Deregister(s *registry.Service) error { - m.Lock() - defer m.Unlock() + go m.watch(®istry.Result{Action: "delete", Service: s}) + m.Lock() services := delServices(m.Services[s.Name], []*registry.Service{s}) m.Services[s.Name] = services + m.Unlock() return nil } func (m *Registry) Watch(opts ...registry.WatchOption) (registry.Watcher, error) { - var wopts registry.WatchOptions + var wo registry.WatchOptions for _, o := range opts { - o(&wopts) + o(&wo) } - return &memoryWatcher{exit: make(chan bool), opts: wopts}, nil + + w := &Watcher{ + exit: make(chan bool), + res: make(chan *registry.Result), + id: uuid.New().String(), + wo: wo, + } + + m.Lock() + m.Watchers[w.id] = w + m.Unlock() + return w, nil } func (m *Registry) String() string { return "memory" } -func (m *Registry) Init(opts ...registry.Option) error { - return nil -} - -func (m *Registry) Options() registry.Options { - return registry.Options{} -} - func NewRegistry(opts ...registry.Option) registry.Registry { + options := registry.Options{ + Context: context.Background(), + } + + for _, o := range opts { + o(&options) + } + + services := getServices(options.Context) + if services == nil { + services = make(map[string][]*registry.Service) + } + return &Registry{ - Services: make(map[string][]*registry.Service), + options: options, + Services: services, + Watchers: make(map[string]*Watcher), } } diff --git a/registry/memory/memory_test.go b/registry/memory/memory_test.go index 2eb21009..3b5cd8be 100644 --- a/registry/memory/memory_test.go +++ b/registry/memory/memory_test.go @@ -80,9 +80,8 @@ var ( } ) -func TestMockRegistry(t *testing.T) { +func TestMemoryRegistry(t *testing.T) { m := NewRegistry() - m.(*Registry).Setup() fn := func(k string, v []*registry.Service) { services, err := m.GetService(k) @@ -108,11 +107,6 @@ func TestMockRegistry(t *testing.T) { } } - // test existing memory data - for k, v := range Data { - fn(k, v) - } - // register data for _, v := range testData { for _, service := range v { @@ -124,7 +118,6 @@ func TestMockRegistry(t *testing.T) { // using test data for k, v := range testData { - fn(k, v) } diff --git a/registry/memory/options.go b/registry/memory/options.go new file mode 100644 index 00000000..64680fdc --- /dev/null +++ b/registry/memory/options.go @@ -0,0 +1,27 @@ +package memory + +import ( + "context" + + "github.com/micro/go-micro/registry" +) + +type servicesKey struct{} + +func getServices(ctx context.Context) map[string][]*registry.Service { + s, ok := ctx.Value(servicesKey{}).(map[string][]*registry.Service) + if !ok { + return nil + } + return s +} + +// Services is an option that preloads service data +func Services(s map[string][]*registry.Service) registry.Option { + return func(o *registry.Options) { + if o.Context == nil { + o.Context = context.Background() + } + o.Context = context.WithValue(o.Context, servicesKey{}, s) + } +} diff --git a/registry/memory/watcher.go b/registry/memory/watcher.go new file mode 100644 index 00000000..c1a7067c --- /dev/null +++ b/registry/memory/watcher.go @@ -0,0 +1,37 @@ +package memory + +import ( + "errors" + + "github.com/micro/go-micro/registry" +) + +type Watcher struct { + id string + wo registry.WatchOptions + res chan *registry.Result + exit chan bool +} + +func (m *Watcher) Next() (*registry.Result, error) { + for { + select { + case r := <-m.res: + if len(m.wo.Service) > 0 && m.wo.Service != r.Service.Name { + continue + } + return r, nil + case <-m.exit: + return nil, errors.New("watcher stopped") + } + } +} + +func (m *Watcher) Stop() { + select { + case <-m.exit: + return + default: + close(m.exit) + } +} diff --git a/registry/memory/watcher_test.go b/registry/memory/watcher_test.go new file mode 100644 index 00000000..1df468fd --- /dev/null +++ b/registry/memory/watcher_test.go @@ -0,0 +1,30 @@ +package memory + +import ( + "testing" + + "github.com/micro/go-micro/registry" +) + +func TestWatcher(t *testing.T) { + w := &Watcher{ + id: "test", + res: make(chan *registry.Result), + exit: make(chan bool), + } + + go func() { + w.res <- ®istry.Result{} + }() + + _, err := w.Next() + if err != nil { + t.Fatal("unexpected err", err) + } + + w.Stop() + + if _, err := w.Next(); err == nil { + t.Fatal("expected error on Next()") + } +} From 1321782785e4d51fef756cb0c4071bf757737e63 Mon Sep 17 00:00:00 2001 From: Asim Aslam Date: Sat, 19 Jan 2019 10:20:16 +0000 Subject: [PATCH 131/196] in case of reload return nil --- selector/default.go | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/selector/default.go b/selector/default.go index 1d4424a8..452fa17c 100644 --- a/selector/default.go +++ b/selector/default.go @@ -326,12 +326,16 @@ func (c *registrySelector) run(name string) { func (c *registrySelector) watch(w registry.Watcher) error { defer w.Stop() + // reload chan + reload := make(chan bool, 1) + // manage this loop go func() { // wait for exit or reload signal select { case <-c.exit: case <-c.reload: + reload <- true } // stop the watcher @@ -341,7 +345,12 @@ func (c *registrySelector) watch(w registry.Watcher) error { for { res, err := w.Next() if err != nil { - return err + select { + case <-reload: + return nil + default: + return err + } } c.update(res) } From d8ba18deff7268981363422127836b36561cdc6d Mon Sep 17 00:00:00 2001 From: Asim Aslam Date: Tue, 22 Jan 2019 12:18:33 +0000 Subject: [PATCH 132/196] change logging --- broker/http_broker.go | 2 -- server/rpc_server.go | 10 ++++++++-- 2 files changed, 8 insertions(+), 4 deletions(-) diff --git a/broker/http_broker.go b/broker/http_broker.go index c04f47eb..fefeed4d 100644 --- a/broker/http_broker.go +++ b/broker/http_broker.go @@ -19,7 +19,6 @@ import ( "time" "github.com/google/uuid" - "github.com/micro/go-log" "github.com/micro/go-micro/codec/json" merr "github.com/micro/go-micro/errors" "github.com/micro/go-micro/registry" @@ -397,7 +396,6 @@ func (h *httpBroker) Connect() error { return err } - log.Logf("Broker Listening on %s", l.Addr().String()) addr := h.address h.address = l.Addr().String() diff --git a/server/rpc_server.go b/server/rpc_server.go index 1afeff6e..469a4bc4 100644 --- a/server/rpc_server.go +++ b/server/rpc_server.go @@ -438,7 +438,8 @@ func (s *rpcServer) Start() error { return err } - log.Logf("Transport Listening on %s", ts.Addr()) + log.Logf("Transport [%s] Listening on %s", config.Transport.String(), ts.Addr()) + s.Lock() // swap address addr := s.opts.Address @@ -493,7 +494,12 @@ func (s *rpcServer) Start() error { }() // TODO: subscribe to cruft - return config.Broker.Connect() + if err := config.Broker.Connect(); err != nil { + return err + } + + log.Logf("Broker [%s] Listening on %s", config.Broker.String(), config.Broker.Address()) + return nil } func (s *rpcServer) Stop() error { From 2ed676acf4011368a16c54629e817a9e929965fd Mon Sep 17 00:00:00 2001 From: Asim Aslam Date: Tue, 22 Jan 2019 13:52:18 +0000 Subject: [PATCH 133/196] handle errors differently --- server/rpc_router.go | 40 ++++++++++++++-------------------------- 1 file changed, 14 insertions(+), 26 deletions(-) diff --git a/server/rpc_router.go b/server/rpc_router.go index 111b3fde..5d23d5b8 100644 --- a/server/rpc_router.go +++ b/server/rpc_router.go @@ -162,27 +162,23 @@ func prepareMethod(method reflect.Method) *methodType { return &methodType{method: method, ArgType: argType, ReplyType: replyType, ContextType: contextType, stream: stream} } -func (router *router) sendResponse(sending sync.Locker, req *request, reply interface{}, cc codec.Writer, errmsg string, last bool) (err error) { +func (router *router) sendResponse(sending sync.Locker, req *request, reply interface{}, cc codec.Writer, last bool) error { msg := new(codec.Message) msg.Type = codec.Response resp := router.getResponse() resp.msg = msg - // Encode the response header - resp.msg.Endpoint = req.msg.Endpoint - if errmsg != "" { - resp.msg.Error = errmsg - reply = invalidRequest - } resp.msg.Id = req.msg.Id sending.Lock() - err = cc.Write(resp.msg, reply) + err := cc.Write(resp.msg, reply) sending.Unlock() router.freeResponse(resp) return err } -func (s *service) call(ctx context.Context, router *router, sending *sync.Mutex, mtype *methodType, req *request, argv, replyv reflect.Value, cc codec.Writer) { +func (s *service) call(ctx context.Context, router *router, sending *sync.Mutex, mtype *methodType, req *request, argv, replyv reflect.Value, cc codec.Writer) error { + defer router.freeRequest(req) + function := mtype.method.Func var returnValues []reflect.Value @@ -206,18 +202,13 @@ func (s *service) call(ctx context.Context, router *router, sending *sync.Mutex, return nil } - errmsg := "" - err := fn(ctx, r, replyv.Interface()) - if err != nil { - errmsg = err.Error() + // execute handler + if err := fn(ctx, r, replyv.Interface()); err != nil { + return err } - err = router.sendResponse(sending, req, replyv.Interface(), cc, errmsg, true) - if err != nil { - log.Log("rpc call: unable to send response: ", err) - } - router.freeRequest(req) - return + // send response + return router.sendResponse(sending, req, replyv.Interface(), cc, true) } // declare a local error to see if we errored out already @@ -250,16 +241,15 @@ func (s *service) call(ctx context.Context, router *router, sending *sync.Mutex, // client.Stream request r.stream = true - errmsg := "" + // execute handler if err := fn(ctx, r, stream); err != nil { - errmsg = err.Error() + return err } // this is the last packet, we don't do anything with // the error here (well sendStreamResponse will log it // already) - router.sendResponse(sending, req, nil, cc, errmsg, true) - router.freeRequest(req) + return router.sendResponse(sending, req, nil, cc, true) } func (m *methodType) prepareContext(ctx context.Context) reflect.Value { @@ -448,11 +438,9 @@ func (router *router) ServeRequest(ctx context.Context, r Request, rsp Response) } // send a response if we actually managed to read a header. if req != nil { - router.sendResponse(sending, req, invalidRequest, rsp.Codec(), err.Error(), true) router.freeRequest(req) } return err } - service.call(ctx, router, sending, mtype, req, argv, replyv, rsp.Codec()) - return nil + return service.call(ctx, router, sending, mtype, req, argv, replyv, rsp.Codec()) } From 8a0d5f0489f2de449d70f6b03b35c1389794ac06 Mon Sep 17 00:00:00 2001 From: Asim Aslam Date: Tue, 22 Jan 2019 13:55:04 +0000 Subject: [PATCH 134/196] log if we can't even respond --- server/rpc_server.go | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/server/rpc_server.go b/server/rpc_server.go index 469a4bc4..41462723 100644 --- a/server/rpc_server.go +++ b/server/rpc_server.go @@ -158,12 +158,15 @@ func (s *rpcServer) ServeConn(sock transport.Socket) { // TODO: handle error better if err := handler(ctx, request, response); err != nil { // write an error response - rcodec.Write(&codec.Message{ + err = rcodec.Write(&codec.Message{ Header: msg.Header, Error: err.Error(), Type: codec.Error, }, nil) - + // could not write the error response + if err != nil { + log.Logf("rpc: unable to write error response: %v", err) + } s.wg.Done() return } From 13de868b21d93d0f2b0020b4cbf474d7d752335b Mon Sep 17 00:00:00 2001 From: Asim Aslam Date: Wed, 23 Jan 2019 18:14:36 +0000 Subject: [PATCH 135/196] Rename --- go-micro.go => micro.go | 0 go-micro.png => micro.png | Bin 2 files changed, 0 insertions(+), 0 deletions(-) rename go-micro.go => micro.go (100%) rename go-micro.png => micro.png (100%) diff --git a/go-micro.go b/micro.go similarity index 100% rename from go-micro.go rename to micro.go diff --git a/go-micro.png b/micro.png similarity index 100% rename from go-micro.png rename to micro.png From 7542aafd29c3548b9df1c239f21e79461bd85a44 Mon Sep 17 00:00:00 2001 From: Asim Aslam Date: Wed, 23 Jan 2019 18:15:17 +0000 Subject: [PATCH 136/196] Update package comment --- micro.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/micro.go b/micro.go index 127924ab..be9ee3ca 100644 --- a/micro.go +++ b/micro.go @@ -1,4 +1,4 @@ -// Package micro is a pluggable RPC framework for microservices +// Package micro is a pluggable framework for microservices package micro import ( From 8090f9968d27f67f5d999cd2c4803bc814203189 Mon Sep 17 00:00:00 2001 From: Asim Aslam Date: Thu, 24 Jan 2019 10:11:02 +0000 Subject: [PATCH 137/196] Update headers to remove X- prefix --- client/rpc_client.go | 8 +-- client/rpc_codec.go | 90 ++++++++++++++++++++-------------- codec/grpc/grpc.go | 4 +- micro.go | 2 +- server/rpc_codec.go | 113 +++++++++++++++++++++++++------------------ server/rpc_server.go | 6 +-- 6 files changed, 132 insertions(+), 91 deletions(-) diff --git a/client/rpc_client.go b/client/rpc_client.go index 3028d366..77c546cb 100644 --- a/client/rpc_client.go +++ b/client/rpc_client.go @@ -487,8 +487,8 @@ func (r *rpcClient) Publish(ctx context.Context, msg Message, opts ...PublishOpt id := uuid.New().String() md["Content-Type"] = msg.ContentType() - md["X-Micro-Topic"] = msg.Topic() - md["X-Micro-Id"] = id + md["Micro-Topic"] = msg.Topic() + md["Micro-Id"] = id // encode message body cf, err := r.newCodec(msg.ContentType()) @@ -500,8 +500,8 @@ func (r *rpcClient) Publish(ctx context.Context, msg Message, opts ...PublishOpt Target: msg.Topic(), Type: codec.Publication, Header: map[string]string{ - "X-Micro-Id": id, - "X-Micro-Topic": msg.Topic(), + "Micro-Id": id, + "Micro-Topic": msg.Topic(), }, }, msg.Payload()); err != nil { return errors.InternalServerError("go.micro.client", err.Error()) diff --git a/client/rpc_codec.go b/client/rpc_codec.go index 35f64e41..53588ab9 100644 --- a/client/rpc_codec.go +++ b/client/rpc_codec.go @@ -84,6 +84,47 @@ func (rwc *readWriteCloser) Close() error { return nil } +func getHeaders(m *codec.Message) { + get := func(hdr string) string { + if hd := m.Header[hdr]; len(hd) > 0 { + return hd + } + // old + return m.Header["X-"+hdr] + } + + // check error in header + if len(m.Error) == 0 { + m.Error = get("Micro-Error") + } + + // check endpoint in header + if len(m.Endpoint) == 0 { + m.Endpoint = get("Micro-Endpoint") + } + + // check method in header + if len(m.Method) == 0 { + m.Method = get("Micro-Method") + } + + if len(m.Id) == 0 { + m.Id = get("Micro-Id") + } +} + +func setHeaders(m *codec.Message) { + set := func(hdr, v string) { + m.Header[hdr] = v + m.Header["X-"+hdr] = v + } + + set("Micro-Id", m.Id) + set("Micro-Service", m.Target) + set("Micro-Method", m.Method) + set("Micro-Endpoint", m.Endpoint) +} + // setupProtocol sets up the old protocol func setupProtocol(msg *transport.Message, node *registry.Node) codec.NewCodec { protocol := node.Metadata["protocol"] @@ -133,10 +174,7 @@ func (c *rpcCodec) Write(m *codec.Message, body interface{}) error { } // set the mucp headers - m.Header["X-Micro-Id"] = m.Id - m.Header["X-Micro-Service"] = m.Target - m.Header["X-Micro-Method"] = m.Method - m.Header["X-Micro-Endpoint"] = m.Endpoint + setHeaders(m) // if body is bytes Frame don't encode if body != nil { @@ -171,43 +209,25 @@ func (c *rpcCodec) Write(m *codec.Message, body interface{}) error { return nil } -func (c *rpcCodec) ReadHeader(wm *codec.Message, r codec.MessageType) error { - var m transport.Message - if err := c.client.Recv(&m); err != nil { +func (c *rpcCodec) ReadHeader(m *codec.Message, r codec.MessageType) error { + var tm transport.Message + + // read message from transport + if err := c.client.Recv(&tm); err != nil { return errors.InternalServerError("go.micro.client.transport", err.Error()) } - c.buf.rbuf.Reset() - c.buf.rbuf.Write(m.Body) - var me codec.Message - // set headers - me.Header = m.Header + c.buf.rbuf.Reset() + c.buf.rbuf.Write(tm.Body) + + // set headers from transport + m.Header = tm.Header // read header - err := c.codec.ReadHeader(&me, r) - wm.Endpoint = me.Endpoint - wm.Method = me.Method - wm.Id = me.Id - wm.Error = me.Error + err := c.codec.ReadHeader(m, r) - // check error in header - if len(me.Error) == 0 { - wm.Error = me.Header["X-Micro-Error"] - } - - // check endpoint in header - if len(me.Endpoint) == 0 { - wm.Endpoint = me.Header["X-Micro-Endpoint"] - } - - // check method in header - if len(me.Method) == 0 { - wm.Method = me.Header["X-Micro-Method"] - } - - if len(me.Id) == 0 { - wm.Id = me.Header["X-Micro-Id"] - } + // get headers + getHeaders(m) // return header error if err != nil { diff --git a/codec/grpc/grpc.go b/codec/grpc/grpc.go index 732f0356..d347c31d 100644 --- a/codec/grpc/grpc.go +++ b/codec/grpc/grpc.go @@ -29,8 +29,8 @@ func (c *Codec) ReadHeader(m *codec.Message, t codec.MessageType) error { // service method path := m.Header[":path"] if len(path) == 0 || path[0] != '/' { - m.Target = m.Header["X-Micro-Service"] - m.Endpoint = m.Header["X-Micro-Endpoint"] + m.Target = m.Header["Micro-Service"] + m.Endpoint = m.Header["Micro-Endpoint"] } else { // [ , a.package.Foo, Bar] parts := strings.Split(path, "/") diff --git a/micro.go b/micro.go index be9ee3ca..44bc52fc 100644 --- a/micro.go +++ b/micro.go @@ -42,7 +42,7 @@ type Publisher interface { type Option func(*Options) var ( - HeaderPrefix = "X-Micro-" + HeaderPrefix = "Micro-" ) // NewService creates and returns a new Service based on the packages within. diff --git a/server/rpc_codec.go b/server/rpc_codec.go index 261b5fd1..ef2a169f 100644 --- a/server/rpc_codec.go +++ b/server/rpc_codec.go @@ -66,13 +66,63 @@ func (rwc *readWriteCloser) Close() error { return nil } +func getHeader(hdr string, md map[string]string) string { + if hd := md[hdr]; len(hd) > 0 { + return hd + } + return md["X-"+hdr] +} + +func getHeaders(m *codec.Message) { + get := func(hdr, v string) string { + if len(v) > 0 { + return v + } + + if hd := m.Header[hdr]; len(hd) > 0 { + return hd + } + + // old + return m.Header["X-"+hdr] + } + + m.Id = get("Micro-Id", m.Id) + m.Error = get("Micro-Error", m.Error) + m.Endpoint = get("Micro-Endpoint", m.Endpoint) + m.Method = get("Micro-Method", m.Method) + m.Target = get("Micro-Service", m.Target) + + // TODO: remove this cruft + if len(m.Endpoint) == 0 { + m.Endpoint = m.Method + } +} + +func setHeaders(m, r *codec.Message) { + set := func(hdr, v string) { + if len(v) == 0 { + return + } + m.Header[hdr] = v + m.Header["X-"+hdr] = v + } + + // set headers + set("Micro-Id", r.Id) + set("Micro-Service", r.Target) + set("Micro-Method", r.Method) + set("Micro-Endpoint", r.Endpoint) + set("Micro-Error", r.Error) +} + // setupProtocol sets up the old protocol func setupProtocol(msg *transport.Message) codec.NewCodec { - service := msg.Header["X-Micro-Service"] - method := msg.Header["X-Micro-Method"] - endpoint := msg.Header["X-Micro-Endpoint"] - protocol := msg.Header["X-Micro-Protocol"] - target := msg.Header["X-Micro-Target"] + service := getHeader("Micro-Service", msg.Header) + method := getHeader("Micro-Method", msg.Header) + endpoint := getHeader("Micro-Endpoint", msg.Header) + protocol := getHeader("Micro-Protocol", msg.Header) + target := getHeader("Micro-Target", msg.Header) // if the protocol exists (mucp) do nothing if len(protocol) > 0 { @@ -91,12 +141,12 @@ func setupProtocol(msg *transport.Message) codec.NewCodec { // no method then set to endpoint if len(method) == 0 { - msg.Header["X-Micro-Method"] = method + msg.Header["Micro-Method"] = endpoint } // no endpoint then set to method if len(endpoint) == 0 { - msg.Header["X-Micro-Endpoint"] = method + msg.Header["Micro-Endpoint"] = method } return nil @@ -118,7 +168,7 @@ func newRpcCodec(req *transport.Message, socket transport.Socket, c codec.NewCod } func (c *rpcCodec) ReadHeader(r *codec.Message, t codec.MessageType) error { - // the initieal message + // the initial message m := codec.Message{ Header: c.req.Header, Body: c.req.Body, @@ -153,25 +203,17 @@ func (c *rpcCodec) ReadHeader(r *codec.Message, t codec.MessageType) error { c.first = false // set some internal things - m.Target = m.Header["X-Micro-Service"] - m.Method = m.Header["X-Micro-Method"] - m.Endpoint = m.Header["X-Micro-Endpoint"] - m.Id = m.Header["X-Micro-Id"] + getHeaders(&m) // read header via codec - err := c.codec.ReadHeader(&m, codec.Request) - - // set the method/id - r.Method = m.Method - r.Endpoint = m.Endpoint - r.Id = m.Id - - // TODO: remove the old legacy cruft - if len(r.Endpoint) == 0 { - r.Endpoint = r.Method + if err := c.codec.ReadHeader(&m, codec.Request); err != nil { + return err } - return err + // set message + *r = m + + return nil } func (c *rpcCodec) ReadBody(b interface{}) error { @@ -206,29 +248,7 @@ func (c *rpcCodec) Write(r *codec.Message, b interface{}) error { m.Header = map[string]string{} } - // set request id - if len(r.Id) > 0 { - m.Header["X-Micro-Id"] = r.Id - } - - // set target - if len(r.Target) > 0 { - m.Header["X-Micro-Service"] = r.Target - } - - // set request method - if len(r.Method) > 0 { - m.Header["X-Micro-Method"] = r.Method - } - - // set request endpoint - if len(r.Endpoint) > 0 { - m.Header["X-Micro-Endpoint"] = r.Endpoint - } - - if len(r.Error) > 0 { - m.Header["X-Micro-Error"] = r.Error - } + setHeaders(m, r) // the body being sent var body []byte @@ -246,6 +266,7 @@ func (c *rpcCodec) Write(r *codec.Message, b interface{}) error { // write an error if it failed m.Error = errors.Wrapf(err, "Unable to encode body").Error() m.Header["X-Micro-Error"] = m.Error + m.Header["Micro-Error"] = m.Error // no body to write if err := c.codec.Write(m, nil); err != nil { return err diff --git a/server/rpc_server.go b/server/rpc_server.go index 41462723..0ba11836 100644 --- a/server/rpc_server.go +++ b/server/rpc_server.go @@ -120,9 +120,9 @@ func (s *rpcServer) ServeConn(sock transport.Socket) { // internal request request := &rpcRequest{ - service: msg.Header["X-Micro-Service"], - method: msg.Header["X-Micro-Method"], - endpoint: msg.Header["X-Micro-Endpoint"], + service: getHeader("Micro-Service", msg.Header), + method: getHeader("Micro-Method", msg.Header), + endpoint: getHeader("Micro-Endpoint", msg.Header), contentType: ct, codec: rcodec, header: msg.Header, From ac1afea7fc129903433833da39e5faae9ca31ce5 Mon Sep 17 00:00:00 2001 From: Vasiliy Tolstov Date: Thu, 24 Jan 2019 00:46:26 +0300 Subject: [PATCH 138/196] add context to server.SubscriberOptions and broker.SubscribeOption Signed-off-by: Vasiliy Tolstov --- broker/options.go | 7 +++++++ server/handler.go | 25 +++++++++++++++++++++++++ server/rpc_server.go | 5 ++++- server/server.go | 4 ---- 4 files changed, 36 insertions(+), 5 deletions(-) diff --git a/broker/options.go b/broker/options.go index 0a909f79..15084e49 100644 --- a/broker/options.go +++ b/broker/options.go @@ -111,3 +111,10 @@ func TLSConfig(t *tls.Config) Option { o.TLSConfig = t } } + +// SubscribeContext set context +func SubscribeContext(ctx context.Context) SubscribeOption { + return func(o *SubscribeOptions) { + o.Context = ctx + } +} diff --git a/server/handler.go b/server/handler.go index 336b6107..ffa0865d 100644 --- a/server/handler.go +++ b/server/handler.go @@ -1,13 +1,20 @@ package server +import "context" + +type HandlerOption func(*HandlerOptions) + type HandlerOptions struct { Internal bool Metadata map[string]map[string]string } +type SubscriberOption func(*SubscriberOptions) + type SubscriberOptions struct { Queue string Internal bool + Context context.Context } // EndpointMetadata is a Handler option that allows metadata to be added to @@ -34,6 +41,17 @@ func InternalSubscriber(b bool) SubscriberOption { o.Internal = b } } +func NewSubscriberOptions(opts ...SubscriberOption) SubscriberOptions { + opt := SubscriberOptions{ + Context: context.Background(), + } + + for _, o := range opts { + o(&opt) + } + + return opt +} // Shared queue name distributed messages across subscribers func SubscriberQueue(n string) SubscriberOption { @@ -41,3 +59,10 @@ func SubscriberQueue(n string) SubscriberOption { o.Queue = n } } + +// SubscriberContext set context options to allow broker SubscriberOption passed +func SubscriberContext(ctx context.Context) SubscriberOption { + return func(o *SubscriberOptions) { + o.Context = ctx + } +} diff --git a/server/rpc_server.go b/server/rpc_server.go index 41462723..c9f13fe2 100644 --- a/server/rpc_server.go +++ b/server/rpc_server.go @@ -10,7 +10,7 @@ import ( "sync" "time" - "github.com/micro/go-log" + log "github.com/micro/go-log" "github.com/micro/go-micro/broker" "github.com/micro/go-micro/codec" "github.com/micro/go-micro/metadata" @@ -357,6 +357,9 @@ func (s *rpcServer) Register() error { if queue := sb.Options().Queue; len(queue) > 0 { opts = append(opts, broker.Queue(queue)) } + if cx := sb.Options().Context; cx != nil { + opts = append(opts, broker.SubscribeContext(cx)) + } sub, err := config.Broker.Subscribe(sb.Topic(), handler, opts...) if err != nil { return err diff --git a/server/server.go b/server/server.go index 82113843..4240628b 100644 --- a/server/server.go +++ b/server/server.go @@ -114,10 +114,6 @@ type Subscriber interface { type Option func(*Options) -type HandlerOption func(*HandlerOptions) - -type SubscriberOption func(*SubscriberOptions) - var ( DefaultAddress = ":0" DefaultName = "go-server" From 539b8c1a3b5e4ac2cee45166e7ab4e24beb202f1 Mon Sep 17 00:00:00 2001 From: Asim Aslam Date: Thu, 24 Jan 2019 13:22:17 +0000 Subject: [PATCH 139/196] Move RegisterInterval into the server --- cmd/cmd.go | 4 +++ options.go | 5 +-- server/options.go | 9 +++++ server/rpc_server.go | 79 +++++++++++++++++++++++++++++++++----------- server/server.go | 20 ----------- service.go | 55 +----------------------------- 6 files changed, 74 insertions(+), 98 deletions(-) diff --git a/cmd/cmd.go b/cmd/cmd.go index 41dcdc43..f1e80a4a 100644 --- a/cmd/cmd.go +++ b/cmd/cmd.go @@ -404,6 +404,10 @@ func (c *cmd) Before(ctx *cli.Context) error { serverOpts = append(serverOpts, server.RegisterTTL(ttl*time.Second)) } + if val := time.Duration(ctx.GlobalInt("register_interval")); val > 0 { + serverOpts = append(serverOpts, server.RegisterInterval(val*time.Second)) + } + // client opts if r := ctx.Int("client_retries"); r >= 0 { clientOpts = append(clientOpts, client.Retries(r)) diff --git a/options.go b/options.go index ae2008a2..9afb7085 100644 --- a/options.go +++ b/options.go @@ -22,9 +22,6 @@ type Options struct { Registry registry.Registry Transport transport.Transport - // Register loop interval - RegisterInterval time.Duration - // Before and After funcs BeforeStart []func() error BeforeStop []func() error @@ -168,7 +165,7 @@ func RegisterTTL(t time.Duration) Option { // RegisterInterval specifies the interval on which to re-register func RegisterInterval(t time.Duration) Option { return func(o *Options) { - o.RegisterInterval = t + o.Server.Init(server.RegisterInterval(t)) } } diff --git a/server/options.go b/server/options.go index f1355122..6acb5960 100644 --- a/server/options.go +++ b/server/options.go @@ -27,6 +27,8 @@ type Options struct { // The register expiry time RegisterTTL time.Duration + // The interval on which to register + RegisterInterval time.Duration // The router for requests Router Router @@ -168,6 +170,13 @@ func RegisterTTL(t time.Duration) Option { } } +// Register the service with at interval +func RegisterInterval(t time.Duration) Option { + return func(o *Options) { + o.RegisterInterval = t + } +} + // WithRouter sets the request router func WithRouter(r Router) Option { return func(o *Options) { diff --git a/server/rpc_server.go b/server/rpc_server.go index 0ba11836..13638c67 100644 --- a/server/rpc_server.go +++ b/server/rpc_server.go @@ -436,6 +436,7 @@ func (s *rpcServer) Start() error { registerDebugHandler(s) config := s.Options() + // start listening on the transport ts, err := config.Transport.Listen(config.Address) if err != nil { return err @@ -443,30 +444,45 @@ func (s *rpcServer) Start() error { log.Logf("Transport [%s] Listening on %s", config.Transport.String(), ts.Addr()) - s.Lock() // swap address + s.Lock() addr := s.opts.Address s.opts.Address = ts.Addr() s.Unlock() - exit := make(chan bool, 1) + // connect to the broker + if err := config.Broker.Connect(); err != nil { + return err + } + + log.Logf("Broker [%s] Listening on %s", config.Broker.String(), config.Broker.Address()) + + // announce self to the world + if err := s.Register(); err != nil { + log.Log("Server register error: ", err) + } + + exit := make(chan bool) go func() { for { + // listen for connections err := ts.Accept(s.ServeConn) - // check if we're supposed to exit + // TODO: listen for messages + // msg := broker.Exchange(service).Consume() + select { + // check if we're supposed to exit case <-exit: return - default: - } - // check the error and backoff - if err != nil { - log.Logf("Accept error: %v", err) - time.Sleep(time.Second) - continue + default: + if err != nil { + log.Logf("Accept error: %v", err) + time.Sleep(time.Second) + continue + } } // no error just exit @@ -475,9 +491,38 @@ func (s *rpcServer) Start() error { }() go func() { - // wait for exit - ch := <-s.exit - exit <- true + + // new ticker + t := time.NewTicker(s.opts.RegisterInterval) + + // only process if it exists + if s.opts.RegisterInterval <= time.Duration(0) { + t.C = nil + } + + // return error chan + var ch chan error + + Loop: + for { + select { + // register self on interval + case <-t.C: + if err := s.Register(); err != nil { + log.Log("Server register error: ", err) + } + // wait for exit + case ch = <-s.exit: + t.Stop() + close(exit) + break Loop + } + } + + // deregister self + if err := s.Deregister(); err != nil { + log.Log("Server deregister error: ", err) + } // wait for requests to finish if wait(s.opts.Context) { @@ -490,18 +535,12 @@ func (s *rpcServer) Start() error { // disconnect the broker config.Broker.Disconnect() - s.Lock() // swap back address + s.Lock() s.opts.Address = addr s.Unlock() }() - // TODO: subscribe to cruft - if err := config.Broker.Connect(); err != nil { - return err - } - - log.Logf("Broker [%s] Listening on %s", config.Broker.String(), config.Broker.Address()) return nil } diff --git a/server/server.go b/server/server.go index 82113843..74d9146e 100644 --- a/server/server.go +++ b/server/server.go @@ -21,8 +21,6 @@ type Server interface { NewHandler(interface{}, ...HandlerOption) Handler NewSubscriber(string, interface{}, ...SubscriberOption) Subscriber Subscribe(Subscriber) error - Register() error - Deregister() error Start() error Stop() error String() string @@ -177,16 +175,6 @@ func Subscribe(s Subscriber) error { return DefaultServer.Subscribe(s) } -// Register registers the default server with the discovery system -func Register() error { - return DefaultServer.Register() -} - -// Deregister deregisters the default server from the discovery system -func Deregister() error { - return DefaultServer.Deregister() -} - // Run starts the default server and waits for a kill // signal before exiting. Also registers/deregisters the server func Run() error { @@ -194,18 +182,10 @@ func Run() error { return err } - if err := DefaultServer.Register(); err != nil { - return err - } - ch := make(chan os.Signal, 1) signal.Notify(ch, syscall.SIGTERM, syscall.SIGINT, syscall.SIGKILL) log.Logf("Received signal %s", <-ch) - if err := DefaultServer.Deregister(); err != nil { - return err - } - return Stop() } diff --git a/service.go b/service.go index e884283d..6b7c6508 100644 --- a/service.go +++ b/service.go @@ -5,10 +5,7 @@ import ( "os/signal" "sync" "syscall" - "time" - "github.com/micro/cli" - "github.com/micro/go-log" "github.com/micro/go-micro/client" "github.com/micro/go-micro/cmd" "github.com/micro/go-micro/metadata" @@ -36,27 +33,6 @@ func newService(opts ...Option) Service { } } -func (s *service) run(exit chan bool) { - if s.opts.RegisterInterval <= time.Duration(0) { - return - } - - t := time.NewTicker(s.opts.RegisterInterval) - - for { - select { - case <-t.C: - err := s.opts.Server.Register() - if err != nil { - log.Log("service run Server.Register error: ", err) - } - case <-exit: - t.Stop() - return - } - } -} - // Init initialises options. Additionally it calls cmd.Init // which parses command line flags. cmd.Init is only called // on first Init. @@ -67,20 +43,6 @@ func (s *service) Init(opts ...Option) { } s.once.Do(func() { - // save user action - action := s.opts.Cmd.App().Action - - // set service action - s.opts.Cmd.App().Action = func(c *cli.Context) { - // set register interval - if i := time.Duration(c.GlobalInt("register_interval")); i > 0 { - s.opts.RegisterInterval = i * time.Second - } - - // user action - action(c) - } - // Initialise the command flags, overriding new service _ = s.opts.Cmd.Init( cmd.Broker(&s.opts.Broker), @@ -105,7 +67,7 @@ func (s *service) Server() server.Server { } func (s *service) String() string { - return "go-micro" + return "micro" } func (s *service) Start() error { @@ -119,10 +81,6 @@ func (s *service) Start() error { return err } - if err := s.opts.Server.Register(); err != nil { - return err - } - for _, fn := range s.opts.AfterStart { if err := fn(); err != nil { return err @@ -141,10 +99,6 @@ func (s *service) Stop() error { } } - if err := s.opts.Server.Deregister(); err != nil { - return err - } - if err := s.opts.Server.Stop(); err != nil { return err } @@ -163,10 +117,6 @@ func (s *service) Run() error { return err } - // start reg loop - ex := make(chan bool) - go s.run(ex) - ch := make(chan os.Signal, 1) signal.Notify(ch, syscall.SIGTERM, syscall.SIGINT, syscall.SIGQUIT) @@ -177,8 +127,5 @@ func (s *service) Run() error { case <-s.opts.Context.Done(): } - // exit reg loop - close(ex) - return s.Stop() } From e22fa01935f531077d3d80e5d02d8a53d0d54426 Mon Sep 17 00:00:00 2001 From: Asim Aslam Date: Thu, 24 Jan 2019 16:08:04 +0000 Subject: [PATCH 140/196] fix ticker --- server/rpc_server.go | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/server/rpc_server.go b/server/rpc_server.go index 70b7fe25..de3b8fd3 100644 --- a/server/rpc_server.go +++ b/server/rpc_server.go @@ -494,13 +494,12 @@ func (s *rpcServer) Start() error { }() go func() { - - // new ticker - t := time.NewTicker(s.opts.RegisterInterval) + t := new(time.Ticker) // only process if it exists - if s.opts.RegisterInterval <= time.Duration(0) { - t.C = nil + if s.opts.RegisterInterval > time.Duration(0) { + // new ticker + t = time.NewTicker(s.opts.RegisterInterval) } // return error chan From a06cd72337446b091f71fd04c7ee8ffef38a33a1 Mon Sep 17 00:00:00 2001 From: Asim Aslam Date: Tue, 29 Jan 2019 09:08:14 +0000 Subject: [PATCH 141/196] update image --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index cb758113..50fc3179 100644 --- a/README.md +++ b/README.md @@ -8,7 +8,7 @@ Go Micro provides the core requirements for distributed systems development incl The **micro** philosophy is sane defaults with a pluggable architecture. We provide defaults to get you started quickly but everything can be easily swapped out. - + Plugins are available at [github.com/micro/go-plugins](https://github.com/micro/go-plugins). From 89c8e1f4a750716e6988a4acdc651593c1b00a68 Mon Sep 17 00:00:00 2001 From: Asim Aslam Date: Tue, 29 Jan 2019 09:20:34 +0000 Subject: [PATCH 142/196] update readme --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 50fc3179..32ac3765 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,6 @@ # Go Micro [![License](https://img.shields.io/:license-apache-blue.svg)](https://opensource.org/licenses/Apache-2.0) [![GoDoc](https://godoc.org/github.com/micro/go-micro?status.svg)](https://godoc.org/github.com/micro/go-micro) [![Travis CI](https://api.travis-ci.org/micro/go-micro.svg?branch=master)](https://travis-ci.org/micro/go-micro) [![Go Report Card](https://goreportcard.com/badge/micro/go-micro)](https://goreportcard.com/report/github.com/micro/go-micro) -Go Micro is a pluggable framework for micro service development. +Go Micro is a framework for micro service development. ## Overview From 107b5710199ed8d6278dc52a2a5328b5859e5ff8 Mon Sep 17 00:00:00 2001 From: Asim Aslam Date: Wed, 30 Jan 2019 11:43:40 +0000 Subject: [PATCH 143/196] Add go mod --- go.mod | 17 ++++++++++ go.sum | 101 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 118 insertions(+) create mode 100644 go.mod create mode 100644 go.sum diff --git a/go.mod b/go.mod new file mode 100644 index 00000000..bbcd27fb --- /dev/null +++ b/go.mod @@ -0,0 +1,17 @@ +module github.com/micro/go-micro + +require ( + github.com/golang/protobuf v1.2.0 + github.com/google/uuid v1.1.0 + github.com/hashicorp/consul v1.4.2 + github.com/hashicorp/memberlist v0.1.3 + github.com/micro/cli v0.1.0 + github.com/micro/go-log v0.1.0 + github.com/micro/go-rcache v0.1.0 + github.com/micro/h2c v1.0.0 + github.com/micro/mdns v0.1.0 + github.com/micro/util v0.1.0 + github.com/mitchellh/hashstructure v1.0.0 + github.com/pkg/errors v0.8.1 + golang.org/x/net v0.0.0-20190125091013-d26f9f9a57f3 +) diff --git a/go.sum b/go.sum new file mode 100644 index 00000000..cccff5f9 --- /dev/null +++ b/go.sum @@ -0,0 +1,101 @@ +github.com/armon/circbuf v0.0.0-20150827004946-bbbad097214e/go.mod h1:3U/XgcO3hCbHZ8TKRvWD2dDTCfh9M9ya+I9JpbB7O8o= +github.com/armon/go-metrics v0.0.0-20180917152333-f0300d1749da h1:8GUt8eRujhVEGZFFEjBj46YV4rDjvGrNxb0KMWYkL2I= +github.com/armon/go-metrics v0.0.0-20180917152333-f0300d1749da/go.mod h1:Q73ZrmVTwzkszR9V5SSuryQ31EELlFMUz1kKyl939pY= +github.com/armon/go-radix v0.0.0-20180808171621-7fddfc383310/go.mod h1:ufUuZ+zHj4x4TnLV4JWEpy2hxWSpsRywHrMgIH9cCH8= +github.com/bgentry/speakeasy v0.1.0/go.mod h1:+zsyZBPWlz7T6j88CTgSN5bM796AkVf0kBD4zp0CCIs= +github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/fatih/color v1.7.0/go.mod h1:Zm6kSWBoL9eyXnKyktHP6abPY2pDugNf5KwzbycvMj4= +github.com/go-log/log v0.1.0 h1:wudGTNsiGzrD5ZjgIkVZ517ugi2XRe9Q/xRCzwEO4/U= +github.com/go-log/log v0.1.0/go.mod h1:4mBwpdRMFLiuXZDCwU2lKQFsoSCo72j3HqBK9d81N2M= +github.com/golang/protobuf v1.2.0 h1:P3YflyNX/ehuJFLhxviNdFxQPkGK5cDcApsge1SqnvM= +github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= +github.com/google/btree v0.0.0-20180813153112-4030bb1f1f0c h1:964Od4U6p2jUkFxvCydnIczKteheJEzHRToSGK3Bnlw= +github.com/google/btree v0.0.0-20180813153112-4030bb1f1f0c/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ= +github.com/google/uuid v1.1.0 h1:Jf4mxPC/ziBnoPIdpQdPJ9OeiomAUHLvxmPRSPH9m4s= +github.com/google/uuid v1.1.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= +github.com/hashicorp/consul v1.4.2 h1:D9iJoJb8Ehe/Zmr+UEE3U3FjOLZ4LUxqFMl4O43BM1U= +github.com/hashicorp/consul v1.4.2/go.mod h1:mFrjN1mfidgJfYP1xrJCF+AfRhr6Eaqhb2+sfyn/OOI= +github.com/hashicorp/errwrap v1.0.0 h1:hLrqtEDnRye3+sgx6z4qVLNuviH3MR5aQ0ykNJa/UYA= +github.com/hashicorp/errwrap v1.0.0/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4= +github.com/hashicorp/go-cleanhttp v0.5.0 h1:wvCrVc9TjDls6+YGAF2hAifE1E5U1+b4tH6KdvN3Gig= +github.com/hashicorp/go-cleanhttp v0.5.0/go.mod h1:JpRdi6/HCYpAwUzNwuwqhbovhLtngrth3wmdIIUrZ80= +github.com/hashicorp/go-immutable-radix v1.0.0 h1:AKDB1HM5PWEA7i4nhcpwOrO2byshxBjXVn/J/3+z5/0= +github.com/hashicorp/go-immutable-radix v1.0.0/go.mod h1:0y9vanUI8NX6FsYoO3zeMjhV/C5i9g4Q3DwcSNZ4P60= +github.com/hashicorp/go-msgpack v0.5.3 h1:zKjpN5BK/P5lMYrLmBHdBULWbJ0XpYR+7NGzqkZzoD4= +github.com/hashicorp/go-msgpack v0.5.3/go.mod h1:ahLV/dePpqEmjfWmKiqvPkv/twdG7iPBM1vqhUKIvfM= +github.com/hashicorp/go-multierror v1.0.0 h1:iVjPR7a6H0tWELX5NxNe7bYopibicUzc7uPribsnS6o= +github.com/hashicorp/go-multierror v1.0.0/go.mod h1:dHtQlpGsu+cZNNAkkCN/P3hoUDHhCYQXV3UM06sGGrk= +github.com/hashicorp/go-rootcerts v1.0.0 h1:ueI78wUjYExhCvMLow4icJnayNNFRgy0d9EGs/a1T44= +github.com/hashicorp/go-rootcerts v1.0.0/go.mod h1:K6zTfqpRlCUIjkwsN4Z+hiSfzSTQa6eBIzfwKfwNnHU= +github.com/hashicorp/go-sockaddr v1.0.0 h1:GeH6tui99pF4NJgfnhp+L6+FfobzVW3Ah46sLo0ICXs= +github.com/hashicorp/go-sockaddr v1.0.0/go.mod h1:7Xibr9yA9JjQq1JpNB2Vw7kxv8xerXegt+ozgdvDeDU= +github.com/hashicorp/go-syslog v1.0.0/go.mod h1:qPfqrKkXGihmCqbJM2mZgkZGvKG1dFdvsLplgctolz4= +github.com/hashicorp/go-uuid v1.0.0/go.mod h1:6SBZvOh/SIDV7/2o3Jml5SYk/TvGqwFJ/bN7x4byOro= +github.com/hashicorp/go-uuid v1.0.1/go.mod h1:6SBZvOh/SIDV7/2o3Jml5SYk/TvGqwFJ/bN7x4byOro= +github.com/hashicorp/go.net v0.0.1/go.mod h1:hjKkEWcCURg++eb33jQU7oqQcI9XDCnUzHA0oac0k90= +github.com/hashicorp/golang-lru v0.5.0 h1:CL2msUPvZTLb5O648aiLNJw3hnBxN2+1Jq8rCOH9wdo= +github.com/hashicorp/golang-lru v0.5.0/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8= +github.com/hashicorp/logutils v1.0.0/go.mod h1:QIAnNjmIWmVIIkWDTG1z5v++HQmx9WQRO+LraFDTW64= +github.com/hashicorp/mdns v1.0.0/go.mod h1:tL+uN++7HEJ6SQLQ2/p+z2pH24WQKWjBPkE0mNTz8vQ= +github.com/hashicorp/memberlist v0.1.3 h1:EmmoJme1matNzb+hMpDuR/0sbJSUisxyqBGG676r31M= +github.com/hashicorp/memberlist v0.1.3/go.mod h1:ajVTdAv/9Im8oMAAj5G31PhhMCZJV2pPBoIllUwCN7I= +github.com/hashicorp/serf v0.8.2 h1:YZ7UKsJv+hKjqGVUUbtE3HNj79Eln2oQ75tniF6iPt0= +github.com/hashicorp/serf v0.8.2/go.mod h1:6hOLApaqBFA1NXqRQAsxw9QxuDEvNxSQRwA/JwenrHc= +github.com/mattn/go-colorable v0.0.9/go.mod h1:9vuHe8Xs5qXnSaW/c/ABM9alt+Vo+STaOChaDxuIBZU= +github.com/mattn/go-isatty v0.0.3/go.mod h1:M+lRXTBqGeGNdLjl/ufCoiOlB5xdOkqRJdNxMWT7Zi4= +github.com/micro/cli v0.0.0-20181223203424-1b0c9793c300/go.mod h1:x9x6qy+tXv17jzYWQup462+j3SIUgDa6vVTzU4IXy/w= +github.com/micro/cli v0.1.0 h1:5DT+QdbAPPQvB3gYTgwze7tFO1m+7DU1sz9XfQczbsc= +github.com/micro/cli v0.1.0/go.mod h1:jRT9gmfVKWSS6pkKcXQ8YhUyj6bzwxK8Fp5b0Y7qNnk= +github.com/micro/go-log v0.1.0 h1:szYSR+yyTsomZM2jyinJC5562DlqffSjHmTZFaeZ2vY= +github.com/micro/go-log v0.1.0/go.mod h1:qaFBF6d6Jk01Gz4cbMkCA2vVuLk3FSaLLjmEGrMCreA= +github.com/micro/go-micro v0.23.0/go.mod h1:3z3lfMkNU9Sr1L/CxL++8pVJmQapRo0N6kNjwYDtOVs= +github.com/micro/go-rcache v0.1.0 h1:YTIgANVHgBe1XOQ/yLICL+s2gbZCAdW+c2ckhekjkuc= +github.com/micro/go-rcache v0.1.0/go.mod h1:INzyZjXO5M+PmN2A33YxD4TaOY61xjFIM4CfSHv+At8= +github.com/micro/h2c v1.0.0 h1:ejw6MS5+WaUoMHRtqkVCCrrVzLMzOFEH52rEyd8Fl2I= +github.com/micro/h2c v1.0.0/go.mod h1:54sOOQW/GRlHhH43vKwOhUb+kHaXhVxR0d3CJhn9alE= +github.com/micro/mdns v0.0.0-20181201230301-9c3770d4057a/go.mod h1:SQG6o/94RinohLuB5noHSevg2Iqg2wXLDUn4lj2LWWo= +github.com/micro/mdns v0.1.0 h1:fuLybUsfynbigJmCot/54i+gwe0hpc/vtCMvWt2WfDI= +github.com/micro/mdns v0.1.0/go.mod h1:KJ0dW7KmicXU2BV++qkLlmHYcVv7/hHnbtguSWt9Aoc= +github.com/micro/util v0.1.0 h1:ghhF5KKRNlKMexzK+cWo6W6uRAZdKy1UKG/9O74NCYc= +github.com/micro/util v0.1.0/go.mod h1:MZgOs0nwxzv9k4xQo4fpF9IwZGF2O96F5/phP9X4/Sw= +github.com/miekg/dns v1.0.14/go.mod h1:W1PPwlIAgtquWBMBEV9nkV9Cazfe8ScdGz/Lj7v3Nrg= +github.com/miekg/dns v1.1.3 h1:1g0r1IvskvgL8rR+AcHzUA+oFmGcQlaIm4IqakufeMM= +github.com/miekg/dns v1.1.3/go.mod h1:W1PPwlIAgtquWBMBEV9nkV9Cazfe8ScdGz/Lj7v3Nrg= +github.com/mitchellh/cli v1.0.0/go.mod h1:hNIlj7HEI86fIcpObd7a0FcrxTWetlwJDGcceTlRvqc= +github.com/mitchellh/go-homedir v1.0.0 h1:vKb8ShqSby24Yrqr/yDYkuFz8d0WUjys40rvnGC8aR0= +github.com/mitchellh/go-homedir v1.0.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0= +github.com/mitchellh/gox v0.4.0/go.mod h1:Sd9lOJ0+aimLBi73mGofS1ycjY8lL3uZM3JPS42BGNg= +github.com/mitchellh/hashstructure v1.0.0 h1:ZkRJX1CyOoTkar7p/mLS5TZU4nJ1Rn/F8u9dGS02Q3Y= +github.com/mitchellh/hashstructure v1.0.0/go.mod h1:QjSHrPWS+BGUVBYkbTZWEnOh3G1DutKwClXU/ABz6AQ= +github.com/mitchellh/iochan v1.0.0/go.mod h1:JwYml1nuB7xOzsp52dPpHFffvOCDupsG0QubkSMEySY= +github.com/mitchellh/mapstructure v0.0.0-20160808181253-ca63d7c062ee/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y= +github.com/mitchellh/mapstructure v1.1.2 h1:fmNYVwqnSfB9mZU6OS2O6GsXM+wcskZDuKQzvN1EDeE= +github.com/mitchellh/mapstructure v1.1.2/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y= +github.com/pascaldekloe/goe v0.0.0-20180627143212-57f6aae5913c/go.mod h1:lzWF7FIEvWOWxwDKqyGYQf6ZUaNfKdP144TG7ZOy1lc= +github.com/pkg/errors v0.8.1 h1:iURUrRGxPUNPdy5/HRSm+Yj6okJ6UtLINN0Q9M4+h3I= +github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= +github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= +github.com/posener/complete v1.1.1/go.mod h1:em0nMJCgc9GFtwrmVmEMR/ZL6WyhyjMBndrE9hABlRI= +github.com/ryanuber/columnize v0.0.0-20160712163229-9b3edd62028f/go.mod h1:sm1tb6uqfes/u+d4ooFouqFdy9/2g9QGwK3SQygK0Ts= +github.com/sean-/seed v0.0.0-20170313163322-e2103e2c3529 h1:nn5Wsu0esKSJiIVhscUtVbo7ada43DJhG55ua/hjS5I= +github.com/sean-/seed v0.0.0-20170313163322-e2103e2c3529/go.mod h1:DxrIzT+xaE7yg65j358z/aeFdxmN0P9QXhEzd20vsDc= +github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= +github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= +github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= +golang.org/x/crypto v0.0.0-20181029021203-45a5f77698d3/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= +golang.org/x/crypto v0.0.0-20190130090550-b01c7a725664 h1:YbZJ76lQ1BqNhVe7dKTSB67wDrc2VPRR75IyGyyPDX8= +golang.org/x/crypto v0.0.0-20190130090550-b01c7a725664/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= +golang.org/x/net v0.0.0-20181023162649-9b4f9f5ad519/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/net v0.0.0-20181201002055-351d144fa1fc/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/net v0.0.0-20190125091013-d26f9f9a57f3 h1:ulvT7fqt0yHWzpJwI57MezWnYDVpCAYBVuYst/L+fAY= +golang.org/x/net v0.0.0-20190125091013-d26f9f9a57f3/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sys v0.0.0-20180823144017-11551d06cbcc/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20181026203630-95b1ffbd15a5/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20190129075346-302c3dd5f1cc h1:WiYx1rIFmx8c0mXAFtv5D/mHyKe1+jmuP7PViuwqwuQ= +golang.org/x/sys v0.0.0-20190129075346-302c3dd5f1cc/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/text v0.3.0 h1:g61tztE5qeGQ89tm6NTjjM9VPIm088od1l6aSorWRWg= +golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= +gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= From b1a31134bd5840cf95d371c0ce4d06f8647083d5 Mon Sep 17 00:00:00 2001 From: Asim Aslam Date: Wed, 30 Jan 2019 18:42:11 +0000 Subject: [PATCH 144/196] Support micro proxy --- client/rpc_client.go | 26 ++++++++++++++++++++++---- client/rpc_codec.go | 5 +++-- transport/http_transport.go | 6 +++--- 3 files changed, 28 insertions(+), 9 deletions(-) diff --git a/client/rpc_client.go b/client/rpc_client.go index 77c546cb..864eaad1 100644 --- a/client/rpc_client.go +++ b/client/rpc_client.go @@ -5,6 +5,7 @@ import ( "context" "fmt" "net" + "os" "strconv" "sync" "sync/atomic" @@ -213,12 +214,17 @@ func (r *rpcClient) stream(ctx context.Context, node *registry.Node, req Request codec: codec, } + // set request codec + if r, ok := req.(*rpcRequest); ok { + r.codec = codec + } + stream := &rpcStream{ context: ctx, request: req, response: rsp, closed: make(chan bool), - codec: newRpcCodec(msg, c, cf), + codec: codec, } ch := make(chan error, 1) @@ -268,6 +274,18 @@ func (r *rpcClient) Options() Options { } func (r *rpcClient) next(request Request, opts CallOptions) (selector.Next, error) { + service := request.Service() + + // get proxy + if prx := os.Getenv("MICRO_PROXY"); len(prx) > 0 { + service = prx + } + + // get proxy address + if prx := os.Getenv("MICRO_PROXY_ADDRESS"); len(prx) > 0 { + opts.Address = prx + } + // return remote address if len(opts.Address) > 0 { address := opts.Address @@ -288,11 +306,11 @@ func (r *rpcClient) next(request Request, opts CallOptions) (selector.Next, erro } // get next nodes from the selector - next, err := r.opts.Selector.Select(request.Service(), opts.SelectOptions...) + next, err := r.opts.Selector.Select(service, opts.SelectOptions...) if err != nil && err == selector.ErrNotFound { - return nil, errors.NotFound("go.micro.client", "service %s: %v", request.Service(), err.Error()) + return nil, errors.NotFound("go.micro.client", "service %s: %v", service, err.Error()) } else if err != nil { - return nil, errors.InternalServerError("go.micro.client", "error selecting %s node: %v", request.Service(), err.Error()) + return nil, errors.InternalServerError("go.micro.client", "error selecting %s node: %v", service, err.Error()) } return next, nil diff --git a/client/rpc_codec.go b/client/rpc_codec.go index 53588ab9..6ff84a64 100644 --- a/client/rpc_codec.go +++ b/client/rpc_codec.go @@ -115,6 +115,9 @@ func getHeaders(m *codec.Message) { func setHeaders(m *codec.Message) { set := func(hdr, v string) { + if len(v) == 0 { + return + } m.Header[hdr] = v m.Header["X-"+hdr] = v } @@ -200,12 +203,10 @@ func (c *rpcCodec) Write(m *codec.Message, body interface{}) error { Header: m.Header, Body: m.Body, } - // send the request if err := c.client.Send(&msg); err != nil { return errors.InternalServerError("go.micro.client.transport", err.Error()) } - return nil } diff --git a/transport/http_transport.go b/transport/http_transport.go index 154448da..2b3619ed 100644 --- a/transport/http_transport.go +++ b/transport/http_transport.go @@ -35,7 +35,7 @@ type httpTransportClient struct { dialOpts DialOptions once sync.Once - sync.Mutex + sync.RWMutex r chan *http.Request bl []*http.Request buff *bufio.Reader @@ -133,11 +133,11 @@ func (h *httpTransportClient) Recv(m *Message) error { r = rc } - h.Lock() - defer h.Unlock() + h.RLock() if h.buff == nil { return io.EOF } + h.RUnlock() // set timeout if its greater than 0 if h.ht.opts.Timeout > time.Duration(0) { From 7888d3e13d534f918ed42ede872907f429bc8858 Mon Sep 17 00:00:00 2001 From: Asim Aslam Date: Thu, 31 Jan 2019 17:14:36 +0000 Subject: [PATCH 145/196] use official h2c server --- transport/http_transport.go | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/transport/http_transport.go b/transport/http_transport.go index 2b3619ed..ea98accc 100644 --- a/transport/http_transport.go +++ b/transport/http_transport.go @@ -13,11 +13,11 @@ import ( "sync" "time" - "github.com/micro/h2c" maddr "github.com/micro/util/go/lib/addr" mnet "github.com/micro/util/go/lib/net" mls "github.com/micro/util/go/lib/tls" "golang.org/x/net/http2" + "golang.org/x/net/http2/h2c" ) type buffer struct { @@ -424,10 +424,7 @@ func (h *httpTransportListener) Accept(fn func(Socket)) error { // insecure connection use h2c if !(h.ht.opts.Secure || h.ht.opts.TLSConfig != nil) { - srv.Handler = &h2c.HandlerH2C{ - Handler: mux, - H2Server: &http2.Server{}, - } + srv.Handler = h2c.NewHandler(mux, &http2.Server{}) } // begin serving From 652b1067f5ebdc30ec1df883fc08a847653a21cb Mon Sep 17 00:00:00 2001 From: Asim Aslam Date: Fri, 1 Feb 2019 09:05:03 +0000 Subject: [PATCH 146/196] fix data race --- registry/gossip/util.go | 19 ++++++++++++++----- 1 file changed, 14 insertions(+), 5 deletions(-) diff --git a/registry/gossip/util.go b/registry/gossip/util.go index 5d0160a7..5e44e375 100644 --- a/registry/gossip/util.go +++ b/registry/gossip/util.go @@ -70,21 +70,30 @@ func addNodes(old, neu []*registry.Node) []*registry.Node { } func addServices(old, neu []*registry.Service) []*registry.Service { + var srv []*registry.Service + for _, s := range neu { var seen bool - for i, o := range old { + for _, o := range old { if o.Version == s.Version { - s.Nodes = addNodes(o.Nodes, s.Nodes) + var sp *registry.Service + // make copy + *sp = *o + // set nodes + sp.Nodes = addNodes(o.Nodes, s.Nodes) + + // mark as seen seen = true - old[i] = s + srv = append(srv, sp) break } } if !seen { - old = append(old, s) + srv = append(srv, cp([]*registry.Service{s})...) } } - return old + + return srv } func delNodes(old, del []*registry.Node) []*registry.Node { From 88e12347d0a08167b0160dfbb52b326e571a2511 Mon Sep 17 00:00:00 2001 From: Asim Aslam Date: Fri, 1 Feb 2019 13:41:11 +0000 Subject: [PATCH 147/196] update mdns to remove race condition --- registry/mdns_registry.go | 52 ++++++++++++++++++++++++--------------- 1 file changed, 32 insertions(+), 20 deletions(-) diff --git a/registry/mdns_registry.go b/registry/mdns_registry.go index 70f42736..4a3d09ec 100644 --- a/registry/mdns_registry.go +++ b/registry/mdns_registry.go @@ -2,6 +2,7 @@ package registry import ( + "context" "net" "strings" "sync" @@ -194,20 +195,20 @@ func (m *mdnsRegistry) Deregister(service *Service) error { } func (m *mdnsRegistry) GetService(service string) ([]*Service, error) { - p := mdns.DefaultParams(service) - p.Timeout = m.opts.Timeout - entryCh := make(chan *mdns.ServiceEntry, 10) - p.Entries = entryCh - - exit := make(chan bool) - defer close(exit) - serviceMap := make(map[string]*Service) + entries := make(chan *mdns.ServiceEntry, 10) + done := make(chan bool) + + p := mdns.DefaultParams(service) + // set context with timeout + p.Context, _ = context.WithTimeout(context.Background(), m.opts.Timeout) + // set entries channel + p.Entries = entries go func() { for { select { - case e := <-entryCh: + case e := <-entries: // list record so skip if p.Service == "_services" { continue @@ -243,16 +244,21 @@ func (m *mdnsRegistry) GetService(service string) ([]*Service, error) { }) serviceMap[txt.Version] = s - case <-exit: + case <-p.Context.Done(): + close(done) return } } }() + // execute the query if err := mdns.Query(p); err != nil { return nil, err } + // wait for completion + <-done + // create list and return var services []*Service @@ -264,21 +270,22 @@ func (m *mdnsRegistry) GetService(service string) ([]*Service, error) { } func (m *mdnsRegistry) ListServices() ([]*Service, error) { - p := mdns.DefaultParams("_services") - p.Timeout = m.opts.Timeout - entryCh := make(chan *mdns.ServiceEntry, 10) - p.Entries = entryCh - - exit := make(chan bool) - defer close(exit) - serviceMap := make(map[string]bool) + entries := make(chan *mdns.ServiceEntry, 10) + done := make(chan bool) + + p := mdns.DefaultParams("_services") + // set context with timeout + p.Context, _ = context.WithTimeout(context.Background(), m.opts.Timeout) + // set entries channel + p.Entries = entries + var services []*Service go func() { for { select { - case e := <-entryCh: + case e := <-entries: if e.TTL == 0 { continue } @@ -288,16 +295,21 @@ func (m *mdnsRegistry) ListServices() ([]*Service, error) { serviceMap[name] = true services = append(services, &Service{Name: name}) } - case <-exit: + case <-p.Context.Done(): + close(done) return } } }() + // execute query if err := mdns.Query(p); err != nil { return nil, err } + // wait till done + <-done + return services, nil } From c03d935ffd28744b25473c97d2f4f84ef98c7bd7 Mon Sep 17 00:00:00 2001 From: Asim Aslam Date: Fri, 1 Feb 2019 15:57:34 +0000 Subject: [PATCH 148/196] fallback for 0.14.0 and older --- server/rpc_codec.go | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/server/rpc_codec.go b/server/rpc_codec.go index ef2a169f..797fa79c 100644 --- a/server/rpc_codec.go +++ b/server/rpc_codec.go @@ -210,6 +210,11 @@ func (c *rpcCodec) ReadHeader(r *codec.Message, t codec.MessageType) error { return err } + // fallback for 0.14 and older + if len(m.Endpoint) == 0 { + m.Endpoint = m.Method + } + // set message *r = m From cead99ac4419cb689fd6c46b57aba45a88b05753 Mon Sep 17 00:00:00 2001 From: Asim Aslam Date: Fri, 1 Feb 2019 16:01:51 +0000 Subject: [PATCH 149/196] fix nil pointer --- registry/gossip/util.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/registry/gossip/util.go b/registry/gossip/util.go index 5e44e375..0fa8116d 100644 --- a/registry/gossip/util.go +++ b/registry/gossip/util.go @@ -76,7 +76,7 @@ func addServices(old, neu []*registry.Service) []*registry.Service { var seen bool for _, o := range old { if o.Version == s.Version { - var sp *registry.Service + sp := new(registry.Service) // make copy *sp = *o // set nodes From 422e2002a014284d09ee8e80e0d6170eb5738c02 Mon Sep 17 00:00:00 2001 From: Vasiliy Tolstov Date: Wed, 30 Jan 2019 15:39:57 +0300 Subject: [PATCH 150/196] registry: gossip unify registry option passing, optimize Signed-off-by: Vasiliy Tolstov --- registry/gossip/README.md | 4 +- registry/gossip/context.go | 17 +++ registry/gossip/gossip.go | 157 ++++++++++++++--------- registry/gossip/gossip_test.go | 199 +++++++++++++++++++++++++++++ registry/gossip/options.go | 25 ++-- registry/gossip/proto/gossip.pb.go | 89 ++++++------- registry/gossip/proto/gossip.proto | 14 +- 7 files changed, 367 insertions(+), 138 deletions(-) create mode 100644 registry/gossip/context.go create mode 100644 registry/gossip/gossip_test.go diff --git a/registry/gossip/README.md b/registry/gossip/README.md index fbf204f5..bfeca969 100644 --- a/registry/gossip/README.md +++ b/registry/gossip/README.md @@ -1,6 +1,6 @@ # Gossip Registry -Gossip is a zero dependency registry which uses hashicorp/memberlist to broadcast registry information +Gossip is a zero dependency registry which uses github.com/hashicorp/memberlist to broadcast registry information via the SWIM protocol. ## Usage @@ -20,5 +20,5 @@ On startup you'll see something like To join this gossip ring set the registry address using flag or env var ```bash -MICRO_REGISTRY_ADDRESS= 192.168.1.65:56390 +MICRO_REGISTRY_ADDRESS=192.168.1.65:56390 ``` diff --git a/registry/gossip/context.go b/registry/gossip/context.go new file mode 100644 index 00000000..fd2b37cb --- /dev/null +++ b/registry/gossip/context.go @@ -0,0 +1,17 @@ +package gossip + +import ( + "context" + + "github.com/micro/go-micro/registry" +) + +// setRegistryOption returns a function to setup a context with given value +func setRegistryOption(k, v interface{}) registry.Option { + return func(o *registry.Options) { + if o.Context == nil { + o.Context = context.Background() + } + o.Context = context.WithValue(o.Context, k, v) + } +} diff --git a/registry/gossip/gossip.go b/registry/gossip/gossip.go index 5a4a0c40..05cbc425 100644 --- a/registry/gossip/gossip.go +++ b/registry/gossip/gossip.go @@ -7,9 +7,11 @@ import ( "io/ioutil" "net" "os" + "os/signal" "strconv" "strings" "sync" + "syscall" "time" "github.com/golang/protobuf/proto" @@ -21,10 +23,35 @@ import ( "github.com/mitchellh/hashstructure" ) +// use registry.Result int32 values after it switches from string to int32 types +// type actionType int32 +// type updateType int32 + const ( - addAction = "update" - delAction = "delete" - syncAction = "sync" + actionTypeInvalid int32 = iota + actionTypeCreate + actionTypeDelete + actionTypeUpdate + actionTypeSync +) + +func actionTypeString(t int32) string { + switch t { + case actionTypeCreate: + return "create" + case actionTypeDelete: + return "delete" + case actionTypeUpdate: + return "update" + case actionTypeSync: + return "sync" + } + return "invalid" +} + +const ( + updateTypeInvalid int32 = iota + updateTypeService ) type broadcast struct { @@ -93,23 +120,18 @@ func configure(g *gossipRegistry, opts ...registry.Option) error { // shutdown old member if g.member != nil { - g.member.Shutdown() + g.Stop() } // replace addresses curAddrs = newAddrs - // create a queue - queue := &memberlist.TransmitLimitedQueue{ - NumNodes: func() int { - return len(curAddrs) - }, - RetransmitMult: 3, - } - // create a new default config c := memberlist.DefaultLocalConfig() + // log to dev null + c.LogOutput = ioutil.Discard + if optConfig, ok := g.options.Context.Value(contextConfig{}).(*memberlist.Config); ok && optConfig != nil { c = optConfig } @@ -145,15 +167,6 @@ func configure(g *gossipRegistry, opts ...registry.Option) error { // set the name c.Name = strings.Join([]string{"micro", hostname, uuid.New().String()}, "-") - // set the delegate - c.Delegate = &delegate{ - updates: g.updates, - queue: queue, - } - - // log to dev null - c.LogOutput = ioutil.Discard - // set a secret key if secure if g.options.Secure { k, ok := g.options.Context.Value(contextSecretKey{}).([]byte) @@ -164,6 +177,20 @@ func configure(g *gossipRegistry, opts ...registry.Option) error { c.SecretKey = k } + // create a queue + queue := &memberlist.TransmitLimitedQueue{ + NumNodes: func() int { + return len(curAddrs) + }, + RetransmitMult: 3, + } + + // set the delegate + c.Delegate = &delegate{ + updates: g.updates, + queue: queue, + } + // create the memberlist m, err := memberlist.Create(c) if err != nil { @@ -187,29 +214,10 @@ func configure(g *gossipRegistry, opts ...registry.Option) error { return nil } +func (*broadcast) UniqueBroadcast() {} + func (b *broadcast) Invalidates(other memberlist.Broadcast) bool { - up := new(pb.Update) - if err := proto.Unmarshal(other.Message(), up); err != nil { - return false - } - - // ids do not match - if b.update.Id == up.Id { - return false - } - - // timestamps do not match - if b.update.Timestamp != up.Timestamp { - return false - } - - // type does not match - if b.update.Type != up.Type { - return false - } - - // invalidates - return true + return false } func (b *broadcast) Message() []byte { @@ -242,7 +250,7 @@ func (d *delegate) NotifyMsg(b []byte) { } // only process service action - if up.Type != "service" { + if up.Type != updateTypeService { return } @@ -280,7 +288,7 @@ func (d *delegate) LocalState(join bool) []byte { d.updates <- &update{ Update: &pb.Update{ - Action: syncAction, + Action: actionTypeSync, }, sync: syncCh, } @@ -309,7 +317,7 @@ func (d *delegate) MergeRemoteState(buf []byte, join bool) { for _, service := range services { for _, srv := range service { d.updates <- &update{ - Update: &pb.Update{Action: addAction}, + Update: &pb.Update{Action: actionTypeCreate}, Service: srv, sync: nil, } @@ -350,6 +358,31 @@ func (g *gossipRegistry) subscribe() (chan *registry.Result, chan bool) { return next, exit } +func (g *gossipRegistry) wait() { + ctx := g.options.Context + + if c, ok := ctx.Value(contextContext{}).(context.Context); ok && c != nil { + ctx = c + } + + ch := make(chan os.Signal, 1) + signal.Notify(ch, syscall.SIGTERM, syscall.SIGINT, syscall.SIGQUIT) + + select { + // wait on kill signal + case <-ch: + // wait on context cancel + case <-ctx.Done(): + } + + g.Stop() +} + +func (g *gossipRegistry) Stop() { + g.member.Leave(g.interval * 2) + g.member.Shutdown() +} + func (g *gossipRegistry) run() { var mtx sync.Mutex updates := map[uint64]*update{} @@ -367,11 +400,11 @@ func (g *gossipRegistry) run() { // process all the updates for k, v := range updates { // check if expiry time has passed - if d := (v.Update.Timestamp + v.Update.Expires); d < now { + if d := (v.Update.Expires); d < now { // delete from records delete(updates, k) // set to delete - v.Update.Action = delAction + v.Update.Action = actionTypeDelete // fire a new update g.updates <- v } @@ -384,7 +417,7 @@ func (g *gossipRegistry) run() { // process the updates for u := range g.updates { switch u.Update.Action { - case addAction: + case actionTypeCreate: g.Lock() if service, ok := g.services[u.Service.Name]; !ok { g.services[u.Service.Name] = []*registry.Service{u.Service} @@ -395,7 +428,7 @@ func (g *gossipRegistry) run() { g.Unlock() // publish update to watchers - go g.publish(addAction, []*registry.Service{u.Service}) + go g.publish(actionTypeString(actionTypeCreate), []*registry.Service{u.Service}) // we need to expire the node at some point in the future if u.Update.Expires > 0 { @@ -406,7 +439,7 @@ func (g *gossipRegistry) run() { mtx.Unlock() } } - case delAction: + case actionTypeDelete: g.Lock() if service, ok := g.services[u.Service.Name]; ok { if services := delServices(service, []*registry.Service{u.Service}); len(services) == 0 { @@ -418,7 +451,7 @@ func (g *gossipRegistry) run() { g.Unlock() // publish update to watchers - go g.publish(delAction, []*registry.Service{u.Service}) + go g.publish(actionTypeString(actionTypeDelete), []*registry.Service{u.Service}) // delete from expiry checks if hash, err := hashstructure.Hash(u.Service, nil); err == nil { @@ -426,7 +459,7 @@ func (g *gossipRegistry) run() { delete(updates, hash) mtx.Unlock() } - case syncAction: + case actionTypeSync: // no sync channel provided if u.sync == nil { continue @@ -441,7 +474,7 @@ func (g *gossipRegistry) run() { } // publish to watchers - go g.publish(addAction, service) + go g.publish(actionTypeString(actionTypeCreate), service) } g.RUnlock() @@ -480,11 +513,9 @@ func (g *gossipRegistry) Register(s *registry.Service, opts ...registry.Register } up := &pb.Update{ - Id: uuid.New().String(), - Timestamp: uint64(time.Now().UnixNano()), - Expires: uint64(options.TTL.Nanoseconds()), - Action: "update", - Type: "service", + Expires: uint64(time.Now().Add(options.TTL).UnixNano()), + Action: actionTypeCreate, + Type: updateTypeService, Metadata: map[string]string{ "Content-Type": "application/json", }, @@ -519,10 +550,8 @@ func (g *gossipRegistry) Deregister(s *registry.Service) error { g.Unlock() up := &pb.Update{ - Id: uuid.New().String(), - Timestamp: uint64(time.Now().UnixNano()), - Action: "delete", - Type: "service", + Action: actionTypeDelete, + Type: updateTypeService, Metadata: map[string]string{ "Content-Type": "application/json", }, @@ -590,5 +619,7 @@ func NewRegistry(opts ...registry.Option) registry.Registry { // wait for setup <-time.After(gossip.interval * 2) + go gossip.wait() + return gossip } diff --git a/registry/gossip/gossip_test.go b/registry/gossip/gossip_test.go new file mode 100644 index 00000000..c8989f1f --- /dev/null +++ b/registry/gossip/gossip_test.go @@ -0,0 +1,199 @@ +package gossip_test + +import ( + "context" + "os" + "sync" + "testing" + "time" + + "github.com/google/uuid" + "github.com/hashicorp/memberlist" + micro "github.com/micro/go-micro" + "github.com/micro/go-micro/client" + "github.com/micro/go-micro/registry" + "github.com/micro/go-micro/registry/gossip" + pb "github.com/micro/go-micro/registry/gossip/proto" + "github.com/micro/go-micro/selector" + "github.com/micro/go-micro/server" +) + +var ( + r1 registry.Registry + r2 registry.Registry + mu sync.Mutex +) + +func newConfig() *memberlist.Config { + wc := memberlist.DefaultLANConfig() + wc.DisableTcpPings = false + wc.GossipVerifyIncoming = false + wc.GossipVerifyOutgoing = false + wc.EnableCompression = false + wc.LogOutput = os.Stderr + wc.ProtocolVersion = 4 + wc.Name = uuid.New().String() + return wc +} + +func newRegistries() { + mu.Lock() + defer mu.Unlock() + + if r1 != nil && r2 != nil { + return + } + + wc1 := newConfig() + wc2 := newConfig() + + rops1 := []registry.Option{gossip.Config(wc1), gossip.Address("127.0.0.1:54321")} + rops2 := []registry.Option{gossip.Config(wc2), gossip.Address("127.0.0.2:54321"), registry.Addrs("127.0.0.1:54321")} + + r1 = gossip.NewRegistry(rops1...) // first started without members + r2 = gossip.NewRegistry(rops2...) // second started joining +} + +func TestRegistryBroadcast(t *testing.T) { + newRegistries() + + svc1 := ®istry.Service{Name: "r1-svc", Version: "0.0.0.1"} + svc2 := ®istry.Service{Name: "r2-svc", Version: "0.0.0.2"} + + <-time.After(1 * time.Second) + if err := r1.Register(svc1); err != nil { + t.Fatal(err) + } + <-time.After(1 * time.Second) + if err := r2.Register(svc2); err != nil { + t.Fatal(err) + } + + var found bool + + svcs, err := r1.ListServices() + if err != nil { + t.Fatal(err) + } + + for _, svc := range svcs { + if svc.Name == "r2-svc" { + found = true + } + } + if !found { + t.Fatalf("r2-svc not found in r1, broadcast not work") + } + + found = false + svcs, err = r2.ListServices() + if err != nil { + t.Fatal(err) + } + + for _, svc := range svcs { + if svc.Name == "r1-svc" { + found = true + } + } + if !found { + t.Fatalf("r1-svc not found in r2, broadcast not work") + } + + if err := r1.Deregister(svc1); err != nil { + t.Fatal(err) + } + if err := r2.Deregister(svc2); err != nil { + t.Fatal(err) + } + +} + +func TestServerRegistry(t *testing.T) { + newRegistries() + + _, err := newServer("s1", r1, t) + if err != nil { + t.Fatal(err) + } + + _, err = newServer("s2", r2, t) + if err != nil { + t.Fatal(err) + } + + svcs, err := r1.ListServices() + if err != nil { + t.Fatal(err) + } + if len(svcs) < 1 { + t.Fatalf("r1 svcs unknown %#+v\n", svcs) + } + + found := false + for _, svc := range svcs { + if svc.Name == "s2" { + found = true + } + } + if !found { + t.Fatalf("r1 does not have s2, broadcast not work") + } + + found = false + svcs, err = r2.ListServices() + if err != nil { + t.Fatal(err) + } + + for _, svc := range svcs { + if svc.Name == "s1" { + found = true + } + } + + if !found { + t.Fatalf("r2 does not have s1, broadcast not work") + } + +} + +type testServer struct{} + +func (*testServer) Test(ctx context.Context, req *pb.Update, rsp *pb.Update) error { + return nil +} + +func newServer(n string, r registry.Registry, t *testing.T) (micro.Service, error) { + h := &testServer{} + + var wg sync.WaitGroup + + wg.Add(1) + sopts := []server.Option{ + server.Name(n), + server.Registry(r), + } + + copts := []client.Option{ + client.Selector(selector.NewSelector(selector.Registry(r))), + client.Registry(r), + } + + srv := micro.NewService( + micro.Server(server.NewServer(sopts...)), + micro.Client(client.NewClient(copts...)), + micro.AfterStart(func() error { + wg.Done() + return nil + }), + ) + + srv.Server().NewHandler(h) + + go func() { + t.Fatal(srv.Run()) + }() + wg.Wait() + return srv, nil +} diff --git a/registry/gossip/options.go b/registry/gossip/options.go index cee50ee5..3188ba7c 100644 --- a/registry/gossip/options.go +++ b/registry/gossip/options.go @@ -12,34 +12,35 @@ type contextSecretKey struct{} // Secret specifies an encryption key. The value should be either // 16, 24, or 32 bytes to select AES-128, AES-192, or AES-256. func Secret(k []byte) registry.Option { - return func(o *registry.Options) { - o.Context = context.WithValue(o.Context, contextSecretKey{}, k) - } + return setRegistryOption(contextSecretKey{}, k) } type contextAddress struct{} // Address to bind to - host:port func Address(a string) registry.Option { - return func(o *registry.Options) { - o.Context = context.WithValue(o.Context, contextAddress{}, a) - } + return setRegistryOption(contextAddress{}, a) } type contextConfig struct{} // Config allow to inject a *memberlist.Config struct for configuring gossip func Config(c *memberlist.Config) registry.Option { - return func(o *registry.Options) { - o.Context = context.WithValue(o.Context, contextConfig{}, c) - } + return setRegistryOption(contextConfig{}, c) } type contextAdvertise struct{} // The address to advertise for other gossip members - host:port func Advertise(a string) registry.Option { - return func(o *registry.Options) { - o.Context = context.WithValue(o.Context, contextAdvertise{}, a) - } + return setRegistryOption(contextAdvertise{}, a) +} + +type contextContext struct{} + +// Context specifies a context for the registry. +// Can be used to signal shutdown of the registry. +// Can be used for extra option values. +func Context(ctx context.Context) registry.Option { + return setRegistryOption(contextContext{}, ctx) } diff --git a/registry/gossip/proto/gossip.pb.go b/registry/gossip/proto/gossip.pb.go index bc7c0700..e5d692fc 100644 --- a/registry/gossip/proto/gossip.pb.go +++ b/registry/gossip/proto/gossip.pb.go @@ -3,9 +3,12 @@ package gossip -import proto "github.com/golang/protobuf/proto" -import fmt "fmt" -import math "math" +import ( + fmt "fmt" + math "math" + + proto "github.com/golang/protobuf/proto" +) // Reference imports to suppress errors if they are not otherwise used. var _ = proto.Marshal @@ -20,16 +23,12 @@ const _ = proto.ProtoPackageIsVersion2 // please upgrade the proto package // Update is the message broadcast type Update struct { - // unique id of update - Id string `protobuf:"bytes,1,opt,name=id,proto3" json:"id,omitempty"` - // unix nano timestamp of update - Timestamp uint64 `protobuf:"varint,2,opt,name=timestamp,proto3" json:"timestamp,omitempty"` // time to live for entry - Expires uint64 `protobuf:"varint,3,opt,name=expires,proto3" json:"expires,omitempty"` - // type of update; service - Type string `protobuf:"bytes,4,opt,name=type,proto3" json:"type,omitempty"` - // what action is taken; add, del, put - Action string `protobuf:"bytes,5,opt,name=action,proto3" json:"action,omitempty"` + Expires uint64 `protobuf:"varint,1,opt,name=expires,proto3" json:"expires,omitempty"` + // type of update + Type int32 `protobuf:"varint,2,opt,name=type,proto3" json:"type,omitempty"` + // what action is taken + Action int32 `protobuf:"varint,3,opt,name=action,proto3" json:"action,omitempty"` // any other associated metadata about the data Metadata map[string]string `protobuf:"bytes,6,rep,name=metadata,proto3" json:"metadata,omitempty" protobuf_key:"bytes,1,opt,name=key,proto3" protobuf_val:"bytes,2,opt,name=value,proto3"` // the payload data; @@ -43,16 +42,17 @@ func (m *Update) Reset() { *m = Update{} } func (m *Update) String() string { return proto.CompactTextString(m) } func (*Update) ProtoMessage() {} func (*Update) Descriptor() ([]byte, []int) { - return fileDescriptor_gossip_fd1eb378131a5d12, []int{0} + return fileDescriptor_18cba623e76e57f3, []int{0} } + func (m *Update) XXX_Unmarshal(b []byte) error { return xxx_messageInfo_Update.Unmarshal(m, b) } func (m *Update) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { return xxx_messageInfo_Update.Marshal(b, m, deterministic) } -func (dst *Update) XXX_Merge(src proto.Message) { - xxx_messageInfo_Update.Merge(dst, src) +func (m *Update) XXX_Merge(src proto.Message) { + xxx_messageInfo_Update.Merge(m, src) } func (m *Update) XXX_Size() int { return xxx_messageInfo_Update.Size(m) @@ -63,20 +63,6 @@ func (m *Update) XXX_DiscardUnknown() { var xxx_messageInfo_Update proto.InternalMessageInfo -func (m *Update) GetId() string { - if m != nil { - return m.Id - } - return "" -} - -func (m *Update) GetTimestamp() uint64 { - if m != nil { - return m.Timestamp - } - return 0 -} - func (m *Update) GetExpires() uint64 { if m != nil { return m.Expires @@ -84,18 +70,18 @@ func (m *Update) GetExpires() uint64 { return 0 } -func (m *Update) GetType() string { +func (m *Update) GetType() int32 { if m != nil { return m.Type } - return "" + return 0 } -func (m *Update) GetAction() string { +func (m *Update) GetAction() int32 { if m != nil { return m.Action } - return "" + return 0 } func (m *Update) GetMetadata() map[string]string { @@ -118,25 +104,24 @@ func init() { } func init() { - proto.RegisterFile("github.com/micro/go-micro/registry/gossip/proto/gossip.proto", fileDescriptor_gossip_fd1eb378131a5d12) + proto.RegisterFile("github.com/micro/go-micro/registry/gossip/proto/gossip.proto", fileDescriptor_18cba623e76e57f3) } -var fileDescriptor_gossip_fd1eb378131a5d12 = []byte{ - // 251 bytes of a gzipped FileDescriptorProto - 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x54, 0x90, 0xcf, 0x4a, 0xc4, 0x30, - 0x10, 0x87, 0x69, 0xb6, 0x9b, 0xb5, 0xe3, 0x1f, 0x64, 0x10, 0x09, 0xb2, 0x87, 0xe2, 0xa9, 0x17, - 0x5b, 0xd0, 0xcb, 0xa2, 0x5e, 0x3d, 0x7a, 0x09, 0xf8, 0x00, 0xd9, 0x36, 0xd4, 0xa0, 0xd9, 0x84, - 0x64, 0x56, 0xec, 0x13, 0xf8, 0xda, 0xb2, 0x69, 0x54, 0xbc, 0x7d, 0xdf, 0xcc, 0x24, 0x99, 0x5f, - 0xe0, 0x71, 0x34, 0xf4, 0xba, 0xdf, 0xb6, 0xbd, 0xb3, 0x9d, 0x35, 0x7d, 0x70, 0xdd, 0xe8, 0x6e, - 0x66, 0x08, 0x7a, 0x34, 0x91, 0xc2, 0xd4, 0x8d, 0x2e, 0x46, 0xe3, 0x3b, 0x1f, 0x1c, 0xb9, 0x2c, - 0x6d, 0x12, 0xe4, 0xb3, 0x5d, 0x7f, 0x31, 0xe0, 0x2f, 0x7e, 0x50, 0xa4, 0xf1, 0x0c, 0x98, 0x19, - 0x44, 0x51, 0x17, 0x4d, 0x25, 0x99, 0x19, 0x70, 0x0d, 0x15, 0x19, 0xab, 0x23, 0x29, 0xeb, 0x05, - 0xab, 0x8b, 0xa6, 0x94, 0x7f, 0x05, 0x14, 0xb0, 0xd2, 0x9f, 0xde, 0x04, 0x1d, 0xc5, 0x22, 0xf5, - 0x7e, 0x14, 0x11, 0x4a, 0x9a, 0xbc, 0x16, 0x65, 0xba, 0x29, 0x31, 0x5e, 0x02, 0x57, 0x3d, 0x19, - 0xb7, 0x13, 0xcb, 0x54, 0xcd, 0x86, 0x1b, 0x38, 0xb2, 0x9a, 0xd4, 0xa0, 0x48, 0x09, 0x5e, 0x2f, - 0x9a, 0xe3, 0xdb, 0x75, 0x9b, 0xf7, 0x9c, 0xb7, 0x6a, 0x9f, 0x73, 0xfb, 0x69, 0x47, 0x61, 0x92, - 0xbf, 0xd3, 0x87, 0x57, 0xd2, 0xa9, 0x55, 0x5d, 0x34, 0x27, 0x32, 0xf1, 0xd5, 0x03, 0x9c, 0xfe, - 0x1b, 0xc7, 0x73, 0x58, 0xbc, 0xe9, 0x29, 0x67, 0x3a, 0x20, 0x5e, 0xc0, 0xf2, 0x43, 0xbd, 0xef, - 0x75, 0x0a, 0x54, 0xc9, 0x59, 0xee, 0xd9, 0xa6, 0xd8, 0xf2, 0xf4, 0x31, 0x77, 0xdf, 0x01, 0x00, - 0x00, 0xff, 0xff, 0x06, 0x6e, 0x00, 0x3c, 0x58, 0x01, 0x00, 0x00, +var fileDescriptor_18cba623e76e57f3 = []byte{ + // 227 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x54, 0x8f, 0xc1, 0x4a, 0x03, 0x31, + 0x14, 0x45, 0x49, 0xa7, 0x4d, 0xed, 0x53, 0x41, 0x1e, 0x22, 0x41, 0x5c, 0x0c, 0xae, 0x66, 0xe3, + 0x0c, 0xe8, 0xa6, 0xa8, 0x5b, 0x97, 0x6e, 0x02, 0x7e, 0x40, 0x3a, 0x0d, 0x31, 0xe8, 0x34, 0x21, + 0x79, 0x15, 0xf3, 0xa9, 0xfe, 0x8d, 0x34, 0x89, 0x42, 0x77, 0xe7, 0x24, 0x37, 0xdc, 0x1b, 0x78, + 0x36, 0x96, 0xde, 0xf7, 0x9b, 0x7e, 0x74, 0xd3, 0x30, 0xd9, 0x31, 0xb8, 0xc1, 0xb8, 0xbb, 0x02, + 0x41, 0x1b, 0x1b, 0x29, 0xa4, 0xc1, 0xb8, 0x18, 0xad, 0x1f, 0x7c, 0x70, 0xe4, 0xaa, 0xf4, 0x59, + 0x90, 0x17, 0xbb, 0xfd, 0x61, 0xc0, 0xdf, 0xfc, 0x56, 0x91, 0x46, 0x01, 0x4b, 0xfd, 0xed, 0x6d, + 0xd0, 0x51, 0xb0, 0x96, 0x75, 0x73, 0xf9, 0xa7, 0x88, 0x30, 0xa7, 0xe4, 0xb5, 0x98, 0xb5, 0xac, + 0x5b, 0xc8, 0xcc, 0x78, 0x05, 0x5c, 0x8d, 0x64, 0xdd, 0x4e, 0x34, 0xf9, 0xb4, 0x1a, 0xae, 0xe1, + 0x64, 0xd2, 0xa4, 0xb6, 0x8a, 0x94, 0xe0, 0x6d, 0xd3, 0x9d, 0xde, 0xdf, 0xf4, 0xb5, 0xb9, 0xf4, + 0xf4, 0xaf, 0xf5, 0xfa, 0x65, 0x47, 0x21, 0xc9, 0xff, 0xf4, 0xa1, 0x25, 0xbf, 0x5a, 0xb6, 0xac, + 0x3b, 0x93, 0x99, 0xaf, 0x9f, 0xe0, 0xfc, 0x28, 0x8e, 0x17, 0xd0, 0x7c, 0xe8, 0x94, 0x07, 0xae, + 0xe4, 0x01, 0xf1, 0x12, 0x16, 0x5f, 0xea, 0x73, 0x5f, 0xd6, 0xad, 0x64, 0x91, 0xc7, 0xd9, 0x9a, + 0x6d, 0x78, 0xfe, 0xea, 0xc3, 0x6f, 0x00, 0x00, 0x00, 0xff, 0xff, 0xd6, 0x63, 0x7b, 0x1b, 0x2a, + 0x01, 0x00, 0x00, } diff --git a/registry/gossip/proto/gossip.proto b/registry/gossip/proto/gossip.proto index 5ab9fd39..21acaaa5 100644 --- a/registry/gossip/proto/gossip.proto +++ b/registry/gossip/proto/gossip.proto @@ -4,16 +4,12 @@ package gossip; // Update is the message broadcast message Update { - // unique id of update - string id = 1; - // unix nano timestamp of update - uint64 timestamp = 2; // time to live for entry - uint64 expires = 3; - // type of update; service - string type = 4; - // what action is taken; add, del, put - string action = 5; + uint64 expires = 1; + // type of update + int32 type = 2; + // what action is taken + int32 action = 3; // any other associated metadata about the data map metadata = 6; // the payload data; From 6be205fd40a1530c4839dbeae7ac97776ca36d16 Mon Sep 17 00:00:00 2001 From: kuangzhiqiang Date: Sun, 3 Feb 2019 19:12:13 +0800 Subject: [PATCH 151/196] client close: rpc: unable to write error response when client close notice: "rpc: unable to write error response..." --- server/rpc_server.go | 20 +++++++++++--------- 1 file changed, 11 insertions(+), 9 deletions(-) diff --git a/server/rpc_server.go b/server/rpc_server.go index de3b8fd3..7faf26d4 100644 --- a/server/rpc_server.go +++ b/server/rpc_server.go @@ -157,15 +157,17 @@ func (s *rpcServer) ServeConn(sock transport.Socket) { // TODO: handle error better if err := handler(ctx, request, response); err != nil { - // write an error response - err = rcodec.Write(&codec.Message{ - Header: msg.Header, - Error: err.Error(), - Type: codec.Error, - }, nil) - // could not write the error response - if err != nil { - log.Logf("rpc: unable to write error response: %v", err) + if err != lastStreamResponseError { + // write an error response + err = rcodec.Write(&codec.Message{ + Header: msg.Header, + Error: err.Error(), + Type: codec.Error, + }, nil) + // could not write the error response + if err != nil { + log.Logf("rpc: unable to write error response: %v", err) + } } s.wg.Done() return From 31b6cad47b2076ba7384b62649d280d9cdd8892b Mon Sep 17 00:00:00 2001 From: Asim Aslam Date: Mon, 4 Feb 2019 10:29:10 +0000 Subject: [PATCH 152/196] make copy before writing --- server/rpc_server.go | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/server/rpc_server.go b/server/rpc_server.go index de3b8fd3..fa8aed43 100644 --- a/server/rpc_server.go +++ b/server/rpc_server.go @@ -274,12 +274,18 @@ func (s *rpcServer) Register() error { return err } + // make copy of metadata + md := make(metadata.Metadata) + for k, v := range config.Metadata { + md[k] = v + } + // register service node := ®istry.Node{ Id: config.Name + "-" + config.Id, Address: addr, Port: port, - Metadata: config.Metadata, + Metadata: md, } node.Metadata["transport"] = config.Transport.String() From 31fc8df2bae721105ec4ea3df65e80db8d130086 Mon Sep 17 00:00:00 2001 From: Asim Aslam Date: Mon, 4 Feb 2019 13:13:03 +0000 Subject: [PATCH 153/196] add server request body --- server/rpc_request.go | 5 +++++ server/server.go | 2 ++ 2 files changed, 7 insertions(+) diff --git a/server/rpc_request.go b/server/rpc_request.go index 6496bc52..b2eb20c7 100644 --- a/server/rpc_request.go +++ b/server/rpc_request.go @@ -47,6 +47,11 @@ func (r *rpcRequest) Header() map[string]string { return r.header } +func (r *rpcRequest) Body() interface{} { + // TODO: convert to interface value + return r.body +} + func (r *rpcRequest) Read() ([]byte, error) { // got a body if r.body != nil { diff --git a/server/server.go b/server/server.go index b1a34d96..ef0f619b 100644 --- a/server/server.go +++ b/server/server.go @@ -51,6 +51,8 @@ type Request interface { ContentType() string // Header of the request Header() map[string]string + // Body is the initial decoded value + Body() interface{} // Read the undecoded request body Read() ([]byte, error) // The encoded message stream From 82bcb8748e71c744732909aa79e439171b11bd36 Mon Sep 17 00:00:00 2001 From: Asim Aslam Date: Thu, 7 Feb 2019 12:42:45 +0000 Subject: [PATCH 154/196] update go modules --- go.mod | 13 ++++++++++++- go.sum | 28 ++++++++++++++++++++-------- 2 files changed, 32 insertions(+), 9 deletions(-) diff --git a/go.mod b/go.mod index bbcd27fb..b09849d4 100644 --- a/go.mod +++ b/go.mod @@ -1,17 +1,28 @@ module github.com/micro/go-micro require ( + github.com/armon/go-radix v1.0.0 // indirect github.com/golang/protobuf v1.2.0 github.com/google/uuid v1.1.0 github.com/hashicorp/consul v1.4.2 + github.com/hashicorp/go-sockaddr v1.0.1 // indirect github.com/hashicorp/memberlist v0.1.3 + github.com/mattn/go-colorable v0.1.0 // indirect + github.com/mattn/go-isatty v0.0.4 // indirect github.com/micro/cli v0.1.0 github.com/micro/go-log v0.1.0 github.com/micro/go-rcache v0.1.0 github.com/micro/h2c v1.0.0 github.com/micro/mdns v0.1.0 github.com/micro/util v0.1.0 + github.com/miekg/dns v1.1.4 // indirect + github.com/mitchellh/go-homedir v1.1.0 // indirect github.com/mitchellh/hashstructure v1.0.0 github.com/pkg/errors v0.8.1 - golang.org/x/net v0.0.0-20190125091013-d26f9f9a57f3 + github.com/posener/complete v1.2.1 // indirect + github.com/stretchr/objx v0.1.1 // indirect + golang.org/x/crypto v0.0.0-20190131182504-b8fe1690c613 // indirect + golang.org/x/net v0.0.0-20190206173232-65e2d4e15006 + golang.org/x/sys v0.0.0-20190204203706-41f3e6584952 // indirect + gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127 // indirect ) diff --git a/go.sum b/go.sum index cccff5f9..857af1e0 100644 --- a/go.sum +++ b/go.sum @@ -2,6 +2,7 @@ github.com/armon/circbuf v0.0.0-20150827004946-bbbad097214e/go.mod h1:3U/XgcO3hC github.com/armon/go-metrics v0.0.0-20180917152333-f0300d1749da h1:8GUt8eRujhVEGZFFEjBj46YV4rDjvGrNxb0KMWYkL2I= github.com/armon/go-metrics v0.0.0-20180917152333-f0300d1749da/go.mod h1:Q73ZrmVTwzkszR9V5SSuryQ31EELlFMUz1kKyl939pY= github.com/armon/go-radix v0.0.0-20180808171621-7fddfc383310/go.mod h1:ufUuZ+zHj4x4TnLV4JWEpy2hxWSpsRywHrMgIH9cCH8= +github.com/armon/go-radix v1.0.0/go.mod h1:ufUuZ+zHj4x4TnLV4JWEpy2hxWSpsRywHrMgIH9cCH8= github.com/bgentry/speakeasy v0.1.0/go.mod h1:+zsyZBPWlz7T6j88CTgSN5bM796AkVf0kBD4zp0CCIs= github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= @@ -26,10 +27,11 @@ github.com/hashicorp/go-msgpack v0.5.3 h1:zKjpN5BK/P5lMYrLmBHdBULWbJ0XpYR+7NGzqk github.com/hashicorp/go-msgpack v0.5.3/go.mod h1:ahLV/dePpqEmjfWmKiqvPkv/twdG7iPBM1vqhUKIvfM= github.com/hashicorp/go-multierror v1.0.0 h1:iVjPR7a6H0tWELX5NxNe7bYopibicUzc7uPribsnS6o= github.com/hashicorp/go-multierror v1.0.0/go.mod h1:dHtQlpGsu+cZNNAkkCN/P3hoUDHhCYQXV3UM06sGGrk= -github.com/hashicorp/go-rootcerts v1.0.0 h1:ueI78wUjYExhCvMLow4icJnayNNFRgy0d9EGs/a1T44= +github.com/hashicorp/go-rootcerts v1.0.0 h1:Rqb66Oo1X/eSV1x66xbDccZjhJigjg0+e82kpwzSwCI= github.com/hashicorp/go-rootcerts v1.0.0/go.mod h1:K6zTfqpRlCUIjkwsN4Z+hiSfzSTQa6eBIzfwKfwNnHU= -github.com/hashicorp/go-sockaddr v1.0.0 h1:GeH6tui99pF4NJgfnhp+L6+FfobzVW3Ah46sLo0ICXs= github.com/hashicorp/go-sockaddr v1.0.0/go.mod h1:7Xibr9yA9JjQq1JpNB2Vw7kxv8xerXegt+ozgdvDeDU= +github.com/hashicorp/go-sockaddr v1.0.1 h1:eCkkJ5KOOktDvwbsE9KPyiBWaOfp1ZNy2gLHgL8PSBM= +github.com/hashicorp/go-sockaddr v1.0.1/go.mod h1:rB4wwRAUzs07qva3c5SdrY/NEtAUjGlgmH/UkBUC97A= github.com/hashicorp/go-syslog v1.0.0/go.mod h1:qPfqrKkXGihmCqbJM2mZgkZGvKG1dFdvsLplgctolz4= github.com/hashicorp/go-uuid v1.0.0/go.mod h1:6SBZvOh/SIDV7/2o3Jml5SYk/TvGqwFJ/bN7x4byOro= github.com/hashicorp/go-uuid v1.0.1/go.mod h1:6SBZvOh/SIDV7/2o3Jml5SYk/TvGqwFJ/bN7x4byOro= @@ -43,7 +45,9 @@ github.com/hashicorp/memberlist v0.1.3/go.mod h1:ajVTdAv/9Im8oMAAj5G31PhhMCZJV2p github.com/hashicorp/serf v0.8.2 h1:YZ7UKsJv+hKjqGVUUbtE3HNj79Eln2oQ75tniF6iPt0= github.com/hashicorp/serf v0.8.2/go.mod h1:6hOLApaqBFA1NXqRQAsxw9QxuDEvNxSQRwA/JwenrHc= github.com/mattn/go-colorable v0.0.9/go.mod h1:9vuHe8Xs5qXnSaW/c/ABM9alt+Vo+STaOChaDxuIBZU= +github.com/mattn/go-colorable v0.1.0/go.mod h1:9vuHe8Xs5qXnSaW/c/ABM9alt+Vo+STaOChaDxuIBZU= github.com/mattn/go-isatty v0.0.3/go.mod h1:M+lRXTBqGeGNdLjl/ufCoiOlB5xdOkqRJdNxMWT7Zi4= +github.com/mattn/go-isatty v0.0.4/go.mod h1:M+lRXTBqGeGNdLjl/ufCoiOlB5xdOkqRJdNxMWT7Zi4= github.com/micro/cli v0.0.0-20181223203424-1b0c9793c300/go.mod h1:x9x6qy+tXv17jzYWQup462+j3SIUgDa6vVTzU4IXy/w= github.com/micro/cli v0.1.0 h1:5DT+QdbAPPQvB3gYTgwze7tFO1m+7DU1sz9XfQczbsc= github.com/micro/cli v0.1.0/go.mod h1:jRT9gmfVKWSS6pkKcXQ8YhUyj6bzwxK8Fp5b0Y7qNnk= @@ -52,7 +56,6 @@ github.com/micro/go-log v0.1.0/go.mod h1:qaFBF6d6Jk01Gz4cbMkCA2vVuLk3FSaLLjmEGrM github.com/micro/go-micro v0.23.0/go.mod h1:3z3lfMkNU9Sr1L/CxL++8pVJmQapRo0N6kNjwYDtOVs= github.com/micro/go-rcache v0.1.0 h1:YTIgANVHgBe1XOQ/yLICL+s2gbZCAdW+c2ckhekjkuc= github.com/micro/go-rcache v0.1.0/go.mod h1:INzyZjXO5M+PmN2A33YxD4TaOY61xjFIM4CfSHv+At8= -github.com/micro/h2c v1.0.0 h1:ejw6MS5+WaUoMHRtqkVCCrrVzLMzOFEH52rEyd8Fl2I= github.com/micro/h2c v1.0.0/go.mod h1:54sOOQW/GRlHhH43vKwOhUb+kHaXhVxR0d3CJhn9alE= github.com/micro/mdns v0.0.0-20181201230301-9c3770d4057a/go.mod h1:SQG6o/94RinohLuB5noHSevg2Iqg2wXLDUn4lj2LWWo= github.com/micro/mdns v0.1.0 h1:fuLybUsfynbigJmCot/54i+gwe0hpc/vtCMvWt2WfDI= @@ -60,11 +63,13 @@ github.com/micro/mdns v0.1.0/go.mod h1:KJ0dW7KmicXU2BV++qkLlmHYcVv7/hHnbtguSWt9A github.com/micro/util v0.1.0 h1:ghhF5KKRNlKMexzK+cWo6W6uRAZdKy1UKG/9O74NCYc= github.com/micro/util v0.1.0/go.mod h1:MZgOs0nwxzv9k4xQo4fpF9IwZGF2O96F5/phP9X4/Sw= github.com/miekg/dns v1.0.14/go.mod h1:W1PPwlIAgtquWBMBEV9nkV9Cazfe8ScdGz/Lj7v3Nrg= -github.com/miekg/dns v1.1.3 h1:1g0r1IvskvgL8rR+AcHzUA+oFmGcQlaIm4IqakufeMM= github.com/miekg/dns v1.1.3/go.mod h1:W1PPwlIAgtquWBMBEV9nkV9Cazfe8ScdGz/Lj7v3Nrg= +github.com/miekg/dns v1.1.4 h1:rCMZsU2ScVSYcAsOXgmC6+AKOK+6pmQTOcw03nfwYV0= +github.com/miekg/dns v1.1.4/go.mod h1:W1PPwlIAgtquWBMBEV9nkV9Cazfe8ScdGz/Lj7v3Nrg= github.com/mitchellh/cli v1.0.0/go.mod h1:hNIlj7HEI86fIcpObd7a0FcrxTWetlwJDGcceTlRvqc= -github.com/mitchellh/go-homedir v1.0.0 h1:vKb8ShqSby24Yrqr/yDYkuFz8d0WUjys40rvnGC8aR0= github.com/mitchellh/go-homedir v1.0.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0= +github.com/mitchellh/go-homedir v1.1.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0= +github.com/mitchellh/go-wordwrap v1.0.0/go.mod h1:ZXFpozHsX6DPmq2I0TCekCxypsnAUbP2oI0UX1GXzOo= github.com/mitchellh/gox v0.4.0/go.mod h1:Sd9lOJ0+aimLBi73mGofS1ycjY8lL3uZM3JPS42BGNg= github.com/mitchellh/hashstructure v1.0.0 h1:ZkRJX1CyOoTkar7p/mLS5TZU4nJ1Rn/F8u9dGS02Q3Y= github.com/mitchellh/hashstructure v1.0.0/go.mod h1:QjSHrPWS+BGUVBYkbTZWEnOh3G1DutKwClXU/ABz6AQ= @@ -77,25 +82,32 @@ github.com/pkg/errors v0.8.1 h1:iURUrRGxPUNPdy5/HRSm+Yj6okJ6UtLINN0Q9M4+h3I= github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= github.com/posener/complete v1.1.1/go.mod h1:em0nMJCgc9GFtwrmVmEMR/ZL6WyhyjMBndrE9hABlRI= +github.com/posener/complete v1.2.1/go.mod h1:6gapUrK/U1TAN7ciCoNRIdVC5sbdBTUh1DKN0g6uH7E= github.com/ryanuber/columnize v0.0.0-20160712163229-9b3edd62028f/go.mod h1:sm1tb6uqfes/u+d4ooFouqFdy9/2g9QGwK3SQygK0Ts= +github.com/ryanuber/columnize v2.1.0+incompatible/go.mod h1:sm1tb6uqfes/u+d4ooFouqFdy9/2g9QGwK3SQygK0Ts= github.com/sean-/seed v0.0.0-20170313163322-e2103e2c3529 h1:nn5Wsu0esKSJiIVhscUtVbo7ada43DJhG55ua/hjS5I= github.com/sean-/seed v0.0.0-20170313163322-e2103e2c3529/go.mod h1:DxrIzT+xaE7yg65j358z/aeFdxmN0P9QXhEzd20vsDc= github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= +github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= golang.org/x/crypto v0.0.0-20181029021203-45a5f77698d3/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= -golang.org/x/crypto v0.0.0-20190130090550-b01c7a725664 h1:YbZJ76lQ1BqNhVe7dKTSB67wDrc2VPRR75IyGyyPDX8= golang.org/x/crypto v0.0.0-20190130090550-b01c7a725664/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= +golang.org/x/crypto v0.0.0-20190131182504-b8fe1690c613 h1:MQ/ZZiDsUapFFiMS+vzwXkCTeEKaum+Do5rINYJDmxc= +golang.org/x/crypto v0.0.0-20190131182504-b8fe1690c613/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= golang.org/x/net v0.0.0-20181023162649-9b4f9f5ad519/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20181201002055-351d144fa1fc/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= -golang.org/x/net v0.0.0-20190125091013-d26f9f9a57f3 h1:ulvT7fqt0yHWzpJwI57MezWnYDVpCAYBVuYst/L+fAY= golang.org/x/net v0.0.0-20190125091013-d26f9f9a57f3/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/net v0.0.0-20190206173232-65e2d4e15006 h1:bfLnR+k0tq5Lqt6dflRLcZiz6UaXCMt3vhYJ1l4FQ80= +golang.org/x/net v0.0.0-20190206173232-65e2d4e15006/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sys v0.0.0-20180823144017-11551d06cbcc/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20181026203630-95b1ffbd15a5/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= -golang.org/x/sys v0.0.0-20190129075346-302c3dd5f1cc h1:WiYx1rIFmx8c0mXAFtv5D/mHyKe1+jmuP7PViuwqwuQ= golang.org/x/sys v0.0.0-20190129075346-302c3dd5f1cc/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20190204203706-41f3e6584952 h1:FDfvYgoVsA7TTZSbgiqjAbfPbK47CNHdWl3h/PJtii0= +golang.org/x/sys v0.0.0-20190204203706-41f3e6584952/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/text v0.3.0 h1:g61tztE5qeGQ89tm6NTjjM9VPIm088od1l6aSorWRWg= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= From 78b7ee90780428671660bbe9e55721b0bc4f75c9 Mon Sep 17 00:00:00 2001 From: Asim Aslam Date: Sat, 9 Feb 2019 12:25:34 +0000 Subject: [PATCH 155/196] update readme --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 32ac3765..a7fbe3f0 100644 --- a/README.md +++ b/README.md @@ -31,7 +31,7 @@ across the services and retry a different node if there's a problem. to seamlessly encode and decode Go types for you. Any variety of messages could be encoded and sent from different clients. The client and server handle this by default. This includes protobuf and json by default. -- **Sync Streaming** - RPC based request/response with support for bidirectional streaming. We provide an abstraction for synchronous +- **Request/Response** - RPC based request/response with support for bidirectional streaming. We provide an abstraction for synchronous communication. A request made to a service will be automatically resolved, load balanced, dialled and streamed. The default transport is http/1.1 or http2 when tls is enabled. From a3ecd36763e01e036c7fff47a861207ea2f45e15 Mon Sep 17 00:00:00 2001 From: Asim Aslam Date: Mon, 11 Feb 2019 18:37:25 +0000 Subject: [PATCH 156/196] add ability to set address --- options.go | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/options.go b/options.go index 9afb7085..4012bb49 100644 --- a/options.go +++ b/options.go @@ -122,6 +122,13 @@ func Transport(t transport.Transport) Option { // Convenience options +// Address sets the address of the server +func Address(addr string) Option { + return func(o *Options) { + o.Server.Init(server.Address(addr)) + } +} + // Name of the service func Name(n string) Option { return func(o *Options) { From 3580cd1b1e4bf22d3823d8ce33028bfc304eb2ef Mon Sep 17 00:00:00 2001 From: Asim Aslam Date: Mon, 11 Feb 2019 18:37:40 +0000 Subject: [PATCH 157/196] no sponsors --- README.md | 2 -- 1 file changed, 2 deletions(-) diff --git a/README.md b/README.md index a7fbe3f0..0f17836c 100644 --- a/README.md +++ b/README.md @@ -52,5 +52,3 @@ See the [docs](https://micro.mu/docs/go-micro.html) for detailed information on Sixt is an Enterprise Sponsor of Micro - -Become a sponsor by backing micro on [Patreon](https://www.patreon.com/microhq) From 36532c94b2e3da9bf9aab543cb6ca3cc68b3ec31 Mon Sep 17 00:00:00 2001 From: Vasiliy Tolstov Date: Sun, 10 Feb 2019 13:15:40 +0300 Subject: [PATCH 158/196] registry: [gossip] add ConnectRetry and ConnectTimeout Signed-off-by: Vasiliy Tolstov --- registry/gossip/gossip.go | 258 ++++++++++++++++++++++++----- registry/gossip/gossip_test.go | 292 ++++++++++++++++++--------------- registry/gossip/options.go | 16 ++ registry/options.go | 1 - 4 files changed, 387 insertions(+), 180 deletions(-) diff --git a/registry/gossip/gossip.go b/registry/gossip/gossip.go index 05cbc425..027d42e1 100644 --- a/registry/gossip/gossip.go +++ b/registry/gossip/gossip.go @@ -4,6 +4,7 @@ package gossip import ( "context" "encoding/json" + "fmt" "io/ioutil" "net" "os" @@ -35,6 +36,13 @@ const ( actionTypeSync ) +const ( + nodeActionUnknown int32 = iota + nodeActionJoin + nodeActionLeave + nodeActionUpdate +) + func actionTypeString(t int32) string { switch t { case actionTypeCreate: @@ -64,18 +72,45 @@ type delegate struct { updates chan *update } -type gossipRegistry struct { - queue *memberlist.TransmitLimitedQueue - updates chan *update - options registry.Options - member *memberlist.Memberlist - interval time.Duration +type event struct { + action int32 + node string +} +type eventDelegate struct { + events chan *event +} + +func (ed *eventDelegate) NotifyJoin(n *memberlist.Node) { + ed.events <- &event{action: nodeActionJoin, node: n.Address()} +} +func (ed *eventDelegate) NotifyLeave(n *memberlist.Node) { + ed.events <- &event{action: nodeActionLeave, node: n.Address()} +} +func (ed *eventDelegate) NotifyUpdate(n *memberlist.Node) { + ed.events <- &event{action: nodeActionUpdate, node: n.Address()} +} + +type gossipRegistry struct { + queue *memberlist.TransmitLimitedQueue + updates chan *update + events chan *event + options registry.Options + member *memberlist.Memberlist + interval time.Duration + tcpInterval time.Duration + + connectRetry bool + connectTimeout time.Duration sync.RWMutex services map[string][]*registry.Service - s sync.RWMutex watchers map[string]chan *registry.Result + + mtu int + addrs []string + members map[string]int32 + done chan struct{} } type update struct { @@ -87,9 +122,60 @@ type update struct { var ( // You should change this if using secure DefaultSecret = []byte("micro-gossip-key") // exactly 16 bytes - ExpiryTick = time.Second * 5 + ExpiryTick = time.Second * 1 // needs to be smaller than registry.RegisterTTL + MaxPacketSize = 512 ) +func (g *gossipRegistry) connect(addrs []string) error { + var err error + + if len(addrs) == 0 { + return nil + } + + timeout := make(<-chan time.Time) + if g.connectTimeout > 0 { + timeout = time.After(g.connectTimeout) + } + + ticker := time.NewTicker(1 * time.Second) + defer ticker.Stop() + + fn := func() (int, error) { + return g.member.Join(addrs) + } + + // don't wait for first try + if _, err = fn(); err == nil { + return nil + } + + // wait loop + for { + select { + // context closed + case <-g.options.Context.Done(): + return nil + // call close, don't wait anymore + case <-g.done: + return nil + // in case of timeout fail with a timeout error + case <-timeout: + return fmt.Errorf("[gossip]: timedout connect to %v", g.addrs) + // got a tick, try to connect + case <-ticker.C: + if _, err = fn(); err == nil { + log.Logf("[gossip]: success connect to %v", g.addrs) + return nil + } else { + log.Logf("[gossip]: failed connect to %v", g.addrs) + } + } + } + + return err +} + func configure(g *gossipRegistry, opts ...registry.Option) error { // loop through address list and get valid entries addrs := func(curAddrs []string) []string { @@ -129,8 +215,10 @@ func configure(g *gossipRegistry, opts ...registry.Option) error { // create a new default config c := memberlist.DefaultLocalConfig() - // log to dev null - c.LogOutput = ioutil.Discard + // sane good default options + c.LogOutput = ioutil.Discard // log to /dev/null + c.PushPullInterval = 0 // disable expensive tcp push/pull + c.ProtocolVersion = 4 // suport latest stable features if optConfig, ok := g.options.Context.Value(contextConfig{}).(*memberlist.Config); ok && optConfig != nil { c = optConfig @@ -177,6 +265,13 @@ func configure(g *gossipRegistry, opts ...registry.Option) error { c.SecretKey = k } + if v, ok := g.options.Context.Value(connectRetry{}).(bool); ok && v { + g.connectRetry = true + } + if td, ok := g.options.Context.Value(connectTimeout{}).(time.Duration); ok { + g.connectTimeout = td + } + // create a queue queue := &memberlist.TransmitLimitedQueue{ NumNodes: func() int { @@ -191,27 +286,34 @@ func configure(g *gossipRegistry, opts ...registry.Option) error { queue: queue, } + if g.connectRetry { + c.Events = &eventDelegate{ + events: g.events, + } + } + // create the memberlist m, err := memberlist.Create(c) if err != nil { return err } - // join the memberlist + // set internals + g.Lock() if len(curAddrs) > 0 { - _, err := m.Join(curAddrs) - if err != nil { - return err + for _, addr := range curAddrs { + g.members[addr] = nodeActionUnknown } } - - // set internals + g.tcpInterval = c.PushPullInterval + g.addrs = curAddrs g.queue = queue g.member = m g.interval = c.GossipInterval + g.Unlock() - log.Logf("Registry Listening on %s", m.LocalNode().Address()) - return nil + log.Logf("[gossip]: Registry Listening on %s", m.LocalNode().Address()) + return g.connect(curAddrs) } func (*broadcast) UniqueBroadcast() {} @@ -225,6 +327,9 @@ func (b *broadcast) Message() []byte { if err != nil { return nil } + if l := len(up); l > MaxPacketSize { + log.Logf("[gossip]: broadcast message size %d bigger then MaxPacketSize %d", l, MaxPacketSize) + } return up } @@ -313,7 +418,6 @@ func (d *delegate) MergeRemoteState(buf []byte, join bool) { if err := json.Unmarshal(buf, &services); err != nil { return } - for _, service := range services { for _, srv := range service { d.updates <- &update{ @@ -326,7 +430,7 @@ func (d *delegate) MergeRemoteState(buf []byte, join bool) { } func (g *gossipRegistry) publish(action string, services []*registry.Service) { - g.s.RLock() + g.RLock() for _, sub := range g.watchers { go func(sub chan *registry.Result) { for _, service := range services { @@ -334,7 +438,7 @@ func (g *gossipRegistry) publish(action string, services []*registry.Service) { } }(sub) } - g.s.RUnlock() + g.RUnlock() } func (g *gossipRegistry) subscribe() (chan *registry.Result, chan bool) { @@ -343,16 +447,16 @@ func (g *gossipRegistry) subscribe() (chan *registry.Result, chan bool) { id := uuid.New().String() - g.s.Lock() + g.Lock() g.watchers[id] = next - g.s.Unlock() + g.Unlock() go func() { <-exit - g.s.Lock() + g.Lock() delete(g.watchers, id) close(next) - g.s.Unlock() + g.Unlock() }() return next, exit @@ -378,9 +482,19 @@ func (g *gossipRegistry) wait() { g.Stop() } -func (g *gossipRegistry) Stop() { - g.member.Leave(g.interval * 2) - g.member.Shutdown() +func (g *gossipRegistry) Stop() error { + g.Lock() + if g.done != nil { + close(g.done) + g.done = nil + } + if g.member != nil { + g.member.Leave(g.interval * 2) + g.member.Shutdown() + g.member = nil + } + g.Unlock() + return nil } func (g *gossipRegistry) run() { @@ -389,31 +503,78 @@ func (g *gossipRegistry) run() { // expiry loop go func() { - t := time.NewTicker(ExpiryTick) - defer t.Stop() + ticker := time.NewTicker(ExpiryTick) + defer ticker.Stop() - for _ = range t.C { - now := uint64(time.Now().UnixNano()) + for { + select { + case <-g.done: + return + case <-ticker.C: + now := uint64(time.Now().UnixNano()) - mtx.Lock() + mtx.Lock() - // process all the updates - for k, v := range updates { - // check if expiry time has passed - if d := (v.Update.Expires); d < now { - // delete from records - delete(updates, k) - // set to delete - v.Update.Action = actionTypeDelete - // fire a new update - g.updates <- v + // process all the updates + for k, v := range updates { + // check if expiry time has passed + if d := (v.Update.Expires); d < now { + // delete from records + delete(updates, k) + // set to delete + v.Update.Action = actionTypeDelete + // fire a new update + g.updates <- v + } } - } - mtx.Unlock() + mtx.Unlock() + } } }() + go func() { + for { + select { + case <-g.done: + return + case ed := <-g.events: + // may be not block all registry? + g.Lock() + if _, ok := g.members[ed.node]; ok { + g.members[ed.node] = ed.action + } + g.Unlock() + } + } + }() + + if g.connectRetry { + go func() { + ticker := time.NewTicker(1 * time.Second) + defer ticker.Stop() + + for { + select { + case <-g.done: + return + case <-ticker.C: + var addrs []string + g.RLock() + for node, action := range g.members { + if action == nodeActionLeave && g.member.LocalNode().Address() != node { + addrs = append(addrs, node) + } + } + g.RUnlock() + if len(addrs) > 0 { + g.connect(addrs) + } + } + } + }() + } + // process the updates for u := range g.updates { switch u.Update.Action { @@ -512,6 +673,10 @@ func (g *gossipRegistry) Register(s *registry.Service, opts ...registry.Register o(&options) } + if options.TTL == 0 && g.tcpInterval == 0 { + return fmt.Errorf("must provide registry.RegisterTTL option or set PushPullInterval in *memberlist.Config") + } + up := &pb.Update{ Expires: uint64(time.Now().Add(options.TTL).UnixNano()), Action: actionTypeCreate, @@ -604,8 +769,11 @@ func NewRegistry(opts ...registry.Option) registry.Registry { Context: context.Background(), }, updates: make(chan *update, 100), + events: make(chan *event, 100), services: make(map[string][]*registry.Service), watchers: make(map[string]chan *registry.Result), + done: make(chan struct{}), + members: make(map[string]int32), } // run the updater diff --git a/registry/gossip/gossip_test.go b/registry/gossip/gossip_test.go index c8989f1f..f72b93ef 100644 --- a/registry/gossip/gossip_test.go +++ b/registry/gossip/gossip_test.go @@ -1,7 +1,6 @@ -package gossip_test +package gossip import ( - "context" "os" "sync" "testing" @@ -9,68 +8,57 @@ import ( "github.com/google/uuid" "github.com/hashicorp/memberlist" - micro "github.com/micro/go-micro" - "github.com/micro/go-micro/client" "github.com/micro/go-micro/registry" - "github.com/micro/go-micro/registry/gossip" - pb "github.com/micro/go-micro/registry/gossip/proto" - "github.com/micro/go-micro/selector" - "github.com/micro/go-micro/server" ) -var ( - r1 registry.Registry - r2 registry.Registry - mu sync.Mutex -) - -func newConfig() *memberlist.Config { - wc := memberlist.DefaultLANConfig() - wc.DisableTcpPings = false - wc.GossipVerifyIncoming = false - wc.GossipVerifyOutgoing = false - wc.EnableCompression = false - wc.LogOutput = os.Stderr - wc.ProtocolVersion = 4 - wc.Name = uuid.New().String() - return wc +func newMemberlistConfig() *memberlist.Config { + mc := memberlist.DefaultLANConfig() + mc.DisableTcpPings = false + mc.GossipVerifyIncoming = false + mc.GossipVerifyOutgoing = false + mc.EnableCompression = false + mc.PushPullInterval = 3 * time.Second + mc.LogOutput = os.Stderr + mc.ProtocolVersion = 4 + mc.Name = uuid.New().String() + return mc } -func newRegistries() { - mu.Lock() - defer mu.Unlock() - - if r1 != nil && r2 != nil { - return +func newRegistry(opts ...registry.Option) registry.Registry { + options := []registry.Option{ + ConnectRetry(true), + ConnectTimeout(60 * time.Second), } - wc1 := newConfig() - wc2 := newConfig() - - rops1 := []registry.Option{gossip.Config(wc1), gossip.Address("127.0.0.1:54321")} - rops2 := []registry.Option{gossip.Config(wc2), gossip.Address("127.0.0.2:54321"), registry.Addrs("127.0.0.1:54321")} - - r1 = gossip.NewRegistry(rops1...) // first started without members - r2 = gossip.NewRegistry(rops2...) // second started joining + options = append(options, opts...) + r := NewRegistry(options...) + return r } func TestRegistryBroadcast(t *testing.T) { - newRegistries() + mc1 := newMemberlistConfig() + r1 := newRegistry(Config(mc1), Address("127.0.0.1:54321")) + + mc2 := newMemberlistConfig() + r2 := newRegistry(Config(mc2), Address("127.0.0.2:54321"), registry.Addrs("127.0.0.1:54321")) + + defer r1.(*gossipRegistry).Stop() + defer r2.(*gossipRegistry).Stop() svc1 := ®istry.Service{Name: "r1-svc", Version: "0.0.0.1"} svc2 := ®istry.Service{Name: "r2-svc", Version: "0.0.0.2"} - <-time.After(1 * time.Second) - if err := r1.Register(svc1); err != nil { + t.Logf("register service svc1 on r1\n") + if err := r1.Register(svc1, registry.RegisterTTL(10*time.Second)); err != nil { t.Fatal(err) } - <-time.After(1 * time.Second) - if err := r2.Register(svc2); err != nil { + t.Logf("register service svc2 on r2\n") + if err := r2.Register(svc2, registry.RegisterTTL(10*time.Second)); err != nil { t.Fatal(err) } var found bool - + t.Logf("list services on r1\n") svcs, err := r1.ListServices() if err != nil { t.Fatal(err) @@ -83,6 +71,129 @@ func TestRegistryBroadcast(t *testing.T) { } if !found { t.Fatalf("r2-svc not found in r1, broadcast not work") + } else { + t.Logf("r2-svc found in r1, all ok") + } + + found = false + t.Logf("list services on r2\n") + svcs, err = r2.ListServices() + if err != nil { + t.Fatal(err) + } + + for _, svc := range svcs { + if svc.Name == "r1-svc" { + found = true + } + } + if !found { + t.Fatalf("r1-svc not found in r2, broadcast not work") + } else { + t.Logf("r1-svc found in r1, all ok") + } + + t.Logf("deregister service svc1 on r1\n") + if err := r1.Deregister(svc1); err != nil { + t.Fatal(err) + } + t.Logf("deregister service svc1 on r2\n") + if err := r2.Deregister(svc2); err != nil { + t.Fatal(err) + } + +} +func TestRegistryRetry(t *testing.T) { + mc1 := newMemberlistConfig() + r1 := newRegistry(Config(mc1), Address("127.0.0.1:54321")) + + mc2 := newMemberlistConfig() + r2 := newRegistry(Config(mc2), Address("127.0.0.2:54321"), registry.Addrs("127.0.0.1:54321")) + + defer r1.(*gossipRegistry).Stop() + defer r2.(*gossipRegistry).Stop() + + svc1 := ®istry.Service{Name: "r1-svc", Version: "0.0.0.1"} + svc2 := ®istry.Service{Name: "r2-svc", Version: "0.0.0.2"} + + var mu sync.Mutex + ch := make(chan struct{}) + ticker := time.NewTicker(1 * time.Second) + defer ticker.Stop() + + go func() { + for { + select { + case <-ticker.C: + mu.Lock() + if r1 != nil { + r1.Register(svc1, registry.RegisterTTL(2*time.Second)) + } + if r2 != nil { + r2.Register(svc2, registry.RegisterTTL(2*time.Second)) + } + if ch != nil { + close(ch) + ch = nil + } + mu.Unlock() + } + } + }() + + <-ch + var found bool + + svcs, err := r2.ListServices() + if err != nil { + t.Fatal(err) + } + + for _, svc := range svcs { + if svc.Name == "r1-svc" { + found = true + } + } + if !found { + t.Fatalf("r1-svc not found in r2, broadcast not work, retry cant test") + } + + t.Logf("stop r1\n") + if err = r1.(*gossipRegistry).Stop(); err != nil { + t.Fatalf("cant stop r1 registry %v", err) + } + + mu.Lock() + r1 = nil + mu.Unlock() + + <-time.After(3 * time.Second) + + found = false + svcs, err = r2.ListServices() + if err != nil { + t.Fatal(err) + } + + for _, svc := range svcs { + if svc.Name == "r1-svc" { + found = true + } + } + if found { + t.Fatalf("r1-svc found in r2, something wrong") + } + + t.Logf("start r1\n") + + r1 = newRegistry(Config(mc1), Address("127.0.0.1:54321")) + <-time.After(2 * time.Second) + + if tr := os.Getenv("TRAVIS"); len(tr) > 0 { + t.Logf("skip next test part, becasue it not works in travis") + t.Skip() + return + <-time.After(5 * time.Second) } found = false @@ -97,7 +208,7 @@ func TestRegistryBroadcast(t *testing.T) { } } if !found { - t.Fatalf("r1-svc not found in r2, broadcast not work") + t.Fatalf("r1-svc not found in r2, connect retry not works") } if err := r1.Deregister(svc1); err != nil { @@ -107,93 +218,6 @@ func TestRegistryBroadcast(t *testing.T) { t.Fatal(err) } -} - -func TestServerRegistry(t *testing.T) { - newRegistries() - - _, err := newServer("s1", r1, t) - if err != nil { - t.Fatal(err) - } - - _, err = newServer("s2", r2, t) - if err != nil { - t.Fatal(err) - } - - svcs, err := r1.ListServices() - if err != nil { - t.Fatal(err) - } - if len(svcs) < 1 { - t.Fatalf("r1 svcs unknown %#+v\n", svcs) - } - - found := false - for _, svc := range svcs { - if svc.Name == "s2" { - found = true - } - } - if !found { - t.Fatalf("r1 does not have s2, broadcast not work") - } - - found = false - svcs, err = r2.ListServices() - if err != nil { - t.Fatal(err) - } - - for _, svc := range svcs { - if svc.Name == "s1" { - found = true - } - } - - if !found { - t.Fatalf("r2 does not have s1, broadcast not work") - } - -} - -type testServer struct{} - -func (*testServer) Test(ctx context.Context, req *pb.Update, rsp *pb.Update) error { - return nil -} - -func newServer(n string, r registry.Registry, t *testing.T) (micro.Service, error) { - h := &testServer{} - - var wg sync.WaitGroup - - wg.Add(1) - sopts := []server.Option{ - server.Name(n), - server.Registry(r), - } - - copts := []client.Option{ - client.Selector(selector.NewSelector(selector.Registry(r))), - client.Registry(r), - } - - srv := micro.NewService( - micro.Server(server.NewServer(sopts...)), - micro.Client(client.NewClient(copts...)), - micro.AfterStart(func() error { - wg.Done() - return nil - }), - ) - - srv.Server().NewHandler(h) - - go func() { - t.Fatal(srv.Run()) - }() - wg.Wait() - return srv, nil + r1.(*gossipRegistry).Stop() + r2.(*gossipRegistry).Stop() } diff --git a/registry/gossip/options.go b/registry/gossip/options.go index 3188ba7c..0a07f304 100644 --- a/registry/gossip/options.go +++ b/registry/gossip/options.go @@ -2,6 +2,7 @@ package gossip import ( "context" + "time" "github.com/hashicorp/memberlist" "github.com/micro/go-micro/registry" @@ -44,3 +45,18 @@ type contextContext struct{} func Context(ctx context.Context) registry.Option { return setRegistryOption(contextContext{}, ctx) } + +type connectTimeout struct{} + +// ConnectTimeout specify registry connect timeout use -1 to specify infinite +func ConnectTimeout(td time.Duration) registry.Option { + return setRegistryOption(connectTimeout{}, td) +} + +type connectRetry struct{} + +// ConnectRetry enable reconnect to registry then connection closed, +// use with ConnectTimeout to specify how long retry +func ConnectRetry(v bool) registry.Option { + return setRegistryOption(connectRetry{}, v) +} diff --git a/registry/options.go b/registry/options.go index aa9c3f4f..d3a54856 100644 --- a/registry/options.go +++ b/registry/options.go @@ -11,7 +11,6 @@ type Options struct { Timeout time.Duration Secure bool TLSConfig *tls.Config - // Other options for implementations of the interface // can be stored in a context Context context.Context From a56929d1b86dae733b5d961365ec9a909fe912f6 Mon Sep 17 00:00:00 2001 From: "xinfei.wu" Date: Wed, 13 Feb 2019 17:47:31 +0800 Subject: [PATCH 159/196] reuse rcache --- selector/default.go | 395 ++------------------------------------------ 1 file changed, 17 insertions(+), 378 deletions(-) diff --git a/selector/default.go b/selector/default.go index 452fa17c..fac51e3e 100644 --- a/selector/default.go +++ b/selector/default.go @@ -1,359 +1,25 @@ package selector import ( - "sync" "time" - "github.com/micro/go-log" "github.com/micro/go-micro/registry" + "github.com/micro/go-rcache" ) type registrySelector struct { - so Options - ttl time.Duration - - // registry cache - sync.RWMutex - cache map[string][]*registry.Service - ttls map[string]time.Time - - watched map[string]bool - - // used to close or reload watcher - reload chan bool - exit chan bool + so Options + rc rcache.Cache } -var ( - DefaultTTL = time.Minute -) - -// isValid checks if the service is valid -func (c *registrySelector) isValid(services []*registry.Service, ttl time.Time) bool { - // no services exist - if len(services) == 0 { - return false - } - - // ttl is invalid - if ttl.IsZero() { - return false - } - - // time since ttl is longer than timeout - if time.Since(ttl) > c.ttl { - return false - } - - // ok - return true -} - -func (c *registrySelector) quit() bool { - select { - case <-c.exit: - return true - default: - return false - } -} - -// cp copies a service. Because we're caching handing back pointers would -// create a race condition, so we do this instead -// its fast enough -func (c *registrySelector) cp(current []*registry.Service) []*registry.Service { - var services []*registry.Service - - for _, service := range current { - // copy service - s := new(registry.Service) - *s = *service - - // copy nodes - var nodes []*registry.Node - for _, node := range service.Nodes { - n := new(registry.Node) - *n = *node - nodes = append(nodes, n) - } - s.Nodes = nodes - - // copy endpoints - var eps []*registry.Endpoint - for _, ep := range service.Endpoints { - e := new(registry.Endpoint) - *e = *ep - eps = append(eps, e) - } - s.Endpoints = eps - - // append service - services = append(services, s) - } - - return services -} - -func (c *registrySelector) del(service string) { - delete(c.cache, service) - delete(c.ttls, service) -} - -func (c *registrySelector) get(service string) ([]*registry.Service, error) { - // read lock - c.RLock() - - // check the cache first - services := c.cache[service] - // get cache ttl - ttl := c.ttls[service] - - // got services && within ttl so return cache - if c.isValid(services, ttl) { - // make a copy - cp := c.cp(services) - // unlock the read - c.RUnlock() - // return servics - return cp, nil - } - - // get does the actual request for a service and cache it - get := func(service string) ([]*registry.Service, error) { - // ask the registry - services, err := c.so.Registry.GetService(service) - if err != nil { - return nil, err - } - - // cache results - c.Lock() - c.set(service, c.cp(services)) - c.Unlock() - - return services, nil - } - - // watch service if not watched - if _, ok := c.watched[service]; !ok { - go c.run(service) - } - - // unlock the read lock - c.RUnlock() - - // get and return services - return get(service) -} - -func (c *registrySelector) set(service string, services []*registry.Service) { - c.cache[service] = services - c.ttls[service] = time.Now().Add(c.ttl) -} - -func (c *registrySelector) update(res *registry.Result) { - if res == nil || res.Service == nil { - return - } - - c.Lock() - defer c.Unlock() - - services, ok := c.cache[res.Service.Name] - if !ok { - // we're not going to cache anything - // unless there was already a lookup - return - } - - if len(res.Service.Nodes) == 0 { - switch res.Action { - case "delete": - c.del(res.Service.Name) - } - return - } - - // existing service found - var service *registry.Service - var index int - for i, s := range services { - if s.Version == res.Service.Version { - service = s - index = i +func (c *registrySelector) newRCache() rcache.Cache { + ropts := []rcache.Option{} + if c.so.Context != nil { + if t, ok := c.so.Context.Value("selector_ttl").(time.Duration); ok { + ropts = append(ropts, rcache.WithTTL(t)) } } - - switch res.Action { - case "create", "update": - if service == nil { - c.set(res.Service.Name, append(services, res.Service)) - return - } - - // append old nodes to new service - for _, cur := range service.Nodes { - var seen bool - for _, node := range res.Service.Nodes { - if cur.Id == node.Id { - seen = true - break - } - } - if !seen { - res.Service.Nodes = append(res.Service.Nodes, cur) - } - } - - services[index] = res.Service - c.set(res.Service.Name, services) - case "delete": - if service == nil { - return - } - - var nodes []*registry.Node - - // filter cur nodes to remove the dead one - for _, cur := range service.Nodes { - var seen bool - for _, del := range res.Service.Nodes { - if del.Id == cur.Id { - seen = true - break - } - } - if !seen { - nodes = append(nodes, cur) - } - } - - // still got nodes, save and return - if len(nodes) > 0 { - service.Nodes = nodes - services[index] = service - c.set(service.Name, services) - return - } - - // zero nodes left - - // only have one thing to delete - // nuke the thing - if len(services) == 1 { - c.del(service.Name) - return - } - - // still have more than 1 service - // check the version and keep what we know - var srvs []*registry.Service - for _, s := range services { - if s.Version != service.Version { - srvs = append(srvs, s) - } - } - - // save - c.set(service.Name, srvs) - } -} - -// run starts the cache watcher loop -// it creates a new watcher if there's a problem -// reloads the watcher if Init is called -// and returns when Close is called -func (c *registrySelector) run(name string) { - // set watcher - c.Lock() - c.watched[name] = true - c.Unlock() - - // delete watcher on exit - defer func() { - c.Lock() - delete(c.watched, name) - c.Unlock() - }() - - // error counter - var cerr int - - for { - // exit early if already dead - if c.quit() { - return - } - - // create new watcher - w, err := c.so.Registry.Watch( - registry.WatchService(name), - ) - - if err != nil { - if c.quit() { - return - } - cerr++ - if cerr > 3 { - log.Log(err) - cerr = 0 - } - time.Sleep(time.Second) - continue - } - - // watch for events - if err := c.watch(w); err != nil { - if c.quit() { - return - } - cerr++ - if cerr > 3 { - cerr = 0 - log.Log(err) - } - continue - } - - // reset err counter - cerr = 0 - } -} - -// watch loops the next event and calls update -// it returns if there's an error -func (c *registrySelector) watch(w registry.Watcher) error { - defer w.Stop() - - // reload chan - reload := make(chan bool, 1) - - // manage this loop - go func() { - // wait for exit or reload signal - select { - case <-c.exit: - case <-c.reload: - reload <- true - } - - // stop the watcher - w.Stop() - }() - - for { - res, err := w.Next() - if err != nil { - select { - case <-reload: - return nil - default: - return err - } - } - c.update(res) - } + return rcache.New(c.so.Registry, ropts...) } func (c *registrySelector) Init(opts ...Option) error { @@ -361,15 +27,8 @@ func (c *registrySelector) Init(opts ...Option) error { o(&c.so) } - // reload the watcher - go func() { - select { - case <-c.exit: - return - default: - c.reload <- true - } - }() + c.rc.Stop() + c.rc = c.newRCache() return nil } @@ -390,7 +49,7 @@ func (c *registrySelector) Select(service string, opts ...SelectOption) (Next, e // get the service // try the cache first // if that fails go directly to the registry - services, err := c.get(service) + services, err := c.rc.GetService(service) if err != nil { return nil, err } @@ -416,17 +75,8 @@ func (c *registrySelector) Reset(service string) { // Close stops the watcher and destroys the cache func (c *registrySelector) Close() error { - c.Lock() - c.cache = make(map[string][]*registry.Service) - c.watched = make(map[string]bool) - c.Unlock() + c.rc.Stop() - select { - case <-c.exit: - return nil - default: - close(c.exit) - } return nil } @@ -447,21 +97,10 @@ func NewSelector(opts ...Option) Selector { sopts.Registry = registry.DefaultRegistry } - ttl := DefaultTTL - - if sopts.Context != nil { - if t, ok := sopts.Context.Value("selector_ttl").(time.Duration); ok { - ttl = t - } + s := ®istrySelector{ + so: sopts, } + s.rc = s.newRCache() - return ®istrySelector{ - so: sopts, - ttl: ttl, - watched: make(map[string]bool), - cache: make(map[string][]*registry.Service), - ttls: make(map[string]time.Time), - reload: make(chan bool, 1), - exit: make(chan bool), - } + return s } From d2fdbcc742cf4f4ec5fa6e7604352400470169db Mon Sep 17 00:00:00 2001 From: Asim Aslam Date: Wed, 13 Feb 2019 13:32:55 +0000 Subject: [PATCH 160/196] Update go modules --- go.mod | 7 ++++--- go.sum | 8 ++++++++ 2 files changed, 12 insertions(+), 3 deletions(-) diff --git a/go.mod b/go.mod index b09849d4..c433312a 100644 --- a/go.mod +++ b/go.mod @@ -2,6 +2,7 @@ module github.com/micro/go-micro require ( github.com/armon/go-radix v1.0.0 // indirect + github.com/go-log/log v0.1.0 github.com/golang/protobuf v1.2.0 github.com/google/uuid v1.1.0 github.com/hashicorp/consul v1.4.2 @@ -21,8 +22,8 @@ require ( github.com/pkg/errors v0.8.1 github.com/posener/complete v1.2.1 // indirect github.com/stretchr/objx v0.1.1 // indirect - golang.org/x/crypto v0.0.0-20190131182504-b8fe1690c613 // indirect - golang.org/x/net v0.0.0-20190206173232-65e2d4e15006 - golang.org/x/sys v0.0.0-20190204203706-41f3e6584952 // indirect + golang.org/x/crypto v0.0.0-20190211182817-74369b46fc67 // indirect + golang.org/x/net v0.0.0-20190213061140-3a22650c66bd + golang.org/x/sys v0.0.0-20190213121743-983097b1a8a3 // indirect gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127 // indirect ) diff --git a/go.sum b/go.sum index 857af1e0..6d57e67c 100644 --- a/go.sum +++ b/go.sum @@ -95,17 +95,25 @@ golang.org/x/crypto v0.0.0-20181029021203-45a5f77698d3/go.mod h1:6SG95UA2DQfeDnf golang.org/x/crypto v0.0.0-20190130090550-b01c7a725664/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= golang.org/x/crypto v0.0.0-20190131182504-b8fe1690c613 h1:MQ/ZZiDsUapFFiMS+vzwXkCTeEKaum+Do5rINYJDmxc= golang.org/x/crypto v0.0.0-20190131182504-b8fe1690c613/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= +golang.org/x/crypto v0.0.0-20190211182817-74369b46fc67 h1:ng3VDlRp5/DHpSWl02R4rM9I+8M2rhmsuLwAMmkLQWE= +golang.org/x/crypto v0.0.0-20190211182817-74369b46fc67/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= golang.org/x/net v0.0.0-20181023162649-9b4f9f5ad519/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20181201002055-351d144fa1fc/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20190125091013-d26f9f9a57f3/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20190206173232-65e2d4e15006 h1:bfLnR+k0tq5Lqt6dflRLcZiz6UaXCMt3vhYJ1l4FQ80= golang.org/x/net v0.0.0-20190206173232-65e2d4e15006/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/net v0.0.0-20190213061140-3a22650c66bd h1:HuTn7WObtcDo9uEEU7rEqL0jYthdXAmZ6PP+meazmaU= +golang.org/x/net v0.0.0-20190213061140-3a22650c66bd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sys v0.0.0-20180823144017-11551d06cbcc/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20181026203630-95b1ffbd15a5/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190129075346-302c3dd5f1cc/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190204203706-41f3e6584952 h1:FDfvYgoVsA7TTZSbgiqjAbfPbK47CNHdWl3h/PJtii0= golang.org/x/sys v0.0.0-20190204203706-41f3e6584952/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20190209173611-3b5209105503 h1:5SvYFrOM3W8Mexn9/oA44Ji7vhXAZQ9hiP+1Q/DMrWg= +golang.org/x/sys v0.0.0-20190209173611-3b5209105503/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20190213121743-983097b1a8a3 h1:+KlxhGbYkFs8lMfwKn+2ojry1ID5eBSMXprS2u/wqCE= +golang.org/x/sys v0.0.0-20190213121743-983097b1a8a3/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/text v0.3.0 h1:g61tztE5qeGQ89tm6NTjjM9VPIm088od1l6aSorWRWg= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= From f961c571bdf9971a4ac29f5effd294a12adbd450 Mon Sep 17 00:00:00 2001 From: Vasiliy Tolstov Date: Wed, 13 Feb 2019 16:33:34 +0300 Subject: [PATCH 161/196] registry: [gossip] fix panic panic: runtime error: invalid memory address or nil pointer dereference [signal SIGSEGV: segmentation violation code=0x1 addr=0x88 pc=0xd1b215] goroutine 8 [running]: sync.(*RWMutex).RLock(...) /var/home/vtolstov/sdk/go1.12beta2/src/sync/rwmutex.go:48 github.com/hashicorp/memberlist.(*Memberlist).LocalNode(0x0, 0x0) /home/vtolstov/devel/projects/centralv2/vendor/github.com/hashicorp/memberlist/memberlist.go:417 +0x35 github.com/micro/go-micro/registry/gossip.(*gossipRegistry).run.func3(0xc000155880) /home/vtolstov/devel/projects/centralv2/vendor/github.com/micro/go-micro/registry/gossip/gossip.go:565 +0xf5 created by github.com/micro/go-micro/registry/gossip.(*gossipRegistry).run /home/vtolstov/devel/projects/centralv2/vendor/github.com/micro/go-micro/registry/gossip/gossip.go:553 +0xa25 Signed-off-by: Vasiliy Tolstov --- registry/gossip/gossip.go | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/registry/gossip/gossip.go b/registry/gossip/gossip.go index 027d42e1..a5e4f5a3 100644 --- a/registry/gossip/gossip.go +++ b/registry/gossip/gossip.go @@ -561,9 +561,11 @@ func (g *gossipRegistry) run() { case <-ticker.C: var addrs []string g.RLock() - for node, action := range g.members { - if action == nodeActionLeave && g.member.LocalNode().Address() != node { - addrs = append(addrs, node) + if g.member != nil { + for node, action := range g.members { + if action == nodeActionLeave && g.member.LocalNode().Address() != node { + addrs = append(addrs, node) + } } } g.RUnlock() From 7cb466359fde0fcc1bbf2d3707adefb2639d1be2 Mon Sep 17 00:00:00 2001 From: Asim Aslam Date: Wed, 13 Feb 2019 14:39:20 +0000 Subject: [PATCH 162/196] rework gossip registry --- registry/gossip/gossip.go | 409 ++++++++++++++++++--------------- registry/gossip/gossip_test.go | 63 +++-- registry/gossip/options.go | 56 +++-- 3 files changed, 272 insertions(+), 256 deletions(-) diff --git a/registry/gossip/gossip.go b/registry/gossip/gossip.go index a5e4f5a3..78fb5cdb 100644 --- a/registry/gossip/gossip.go +++ b/registry/gossip/gossip.go @@ -1,4 +1,4 @@ -// Package Gossip provides a gossip registry based on hashicorp/memberlist +// Package gossip provides a gossip registry based on hashicorp/memberlist package gossip import ( @@ -8,11 +8,9 @@ import ( "io/ioutil" "net" "os" - "os/signal" "strconv" "strings" "sync" - "syscall" "time" "github.com/golang/protobuf/proto" @@ -110,7 +108,7 @@ type gossipRegistry struct { mtu int addrs []string members map[string]int32 - done chan struct{} + done chan bool } type update struct { @@ -119,6 +117,11 @@ type update struct { sync chan *registry.Service } +type updates struct { + sync.RWMutex + services map[uint64]*update +} + var ( // You should change this if using secure DefaultSecret = []byte("micro-gossip-key") // exactly 16 bytes @@ -126,56 +129,6 @@ var ( MaxPacketSize = 512 ) -func (g *gossipRegistry) connect(addrs []string) error { - var err error - - if len(addrs) == 0 { - return nil - } - - timeout := make(<-chan time.Time) - if g.connectTimeout > 0 { - timeout = time.After(g.connectTimeout) - } - - ticker := time.NewTicker(1 * time.Second) - defer ticker.Stop() - - fn := func() (int, error) { - return g.member.Join(addrs) - } - - // don't wait for first try - if _, err = fn(); err == nil { - return nil - } - - // wait loop - for { - select { - // context closed - case <-g.options.Context.Done(): - return nil - // call close, don't wait anymore - case <-g.done: - return nil - // in case of timeout fail with a timeout error - case <-timeout: - return fmt.Errorf("[gossip]: timedout connect to %v", g.addrs) - // got a tick, try to connect - case <-ticker.C: - if _, err = fn(); err == nil { - log.Logf("[gossip]: success connect to %v", g.addrs) - return nil - } else { - log.Logf("[gossip]: failed connect to %v", g.addrs) - } - } - } - - return err -} - func configure(g *gossipRegistry, opts ...registry.Option) error { // loop through address list and get valid entries addrs := func(curAddrs []string) []string { @@ -205,9 +158,9 @@ func configure(g *gossipRegistry, opts ...registry.Option) error { } // shutdown old member - if g.member != nil { - g.Stop() - } + g.Stop() + // new done chan + g.done = make(chan bool) // replace addresses curAddrs = newAddrs @@ -220,16 +173,18 @@ func configure(g *gossipRegistry, opts ...registry.Option) error { c.PushPullInterval = 0 // disable expensive tcp push/pull c.ProtocolVersion = 4 // suport latest stable features - if optConfig, ok := g.options.Context.Value(contextConfig{}).(*memberlist.Config); ok && optConfig != nil { - c = optConfig + // set config from options + if config, ok := g.options.Context.Value(configKey{}).(*memberlist.Config); ok && config != nil { + c = config } - if hostport, ok := g.options.Context.Value(contextAddress{}).(string); ok { - host, port, err := net.SplitHostPort(hostport) + // set address + if address, ok := g.options.Context.Value(addressKey{}).(string); ok { + host, port, err := net.SplitHostPort(address) if err == nil { - pn, err := strconv.Atoi(port) + p, err := strconv.Atoi(port) if err == nil { - c.BindPort = pn + c.BindPort = p } c.BindAddr = host } @@ -238,12 +193,13 @@ func configure(g *gossipRegistry, opts ...registry.Option) error { c.BindPort = 0 } - if hostport, ok := g.options.Context.Value(contextAdvertise{}).(string); ok { - host, port, err := net.SplitHostPort(hostport) + // set the advertise address + if advertise, ok := g.options.Context.Value(advertiseKey{}).(string); ok { + host, port, err := net.SplitHostPort(advertise) if err == nil { - pn, err := strconv.Atoi(port) + p, err := strconv.Atoi(port) if err == nil { - c.AdvertisePort = pn + c.AdvertisePort = p } c.AdvertiseAddr = host } @@ -257,7 +213,7 @@ func configure(g *gossipRegistry, opts ...registry.Option) error { // set a secret key if secure if g.options.Secure { - k, ok := g.options.Context.Value(contextSecretKey{}).([]byte) + k, ok := g.options.Context.Value(secretKey{}).([]byte) if !ok { // use the default secret k = DefaultSecret @@ -265,10 +221,13 @@ func configure(g *gossipRegistry, opts ...registry.Option) error { c.SecretKey = k } - if v, ok := g.options.Context.Value(connectRetry{}).(bool); ok && v { + // set connect retry + if v, ok := g.options.Context.Value(connectRetryKey{}).(bool); ok && v { g.connectRetry = true } - if td, ok := g.options.Context.Value(connectTimeout{}).(time.Duration); ok { + + // set connect timeout + if td, ok := g.options.Context.Value(connectTimeoutKey{}).(time.Duration); ok { g.connectTimeout = td } @@ -300,19 +259,24 @@ func configure(g *gossipRegistry, opts ...registry.Option) error { // set internals g.Lock() + if len(curAddrs) > 0 { for _, addr := range curAddrs { g.members[addr] = nodeActionUnknown } } + g.tcpInterval = c.PushPullInterval g.addrs = curAddrs g.queue = queue g.member = m g.interval = c.GossipInterval + g.Unlock() - log.Logf("[gossip]: Registry Listening on %s", m.LocalNode().Address()) + log.Logf("[gossip] Registry Listening on %s", m.LocalNode().Address()) + + // try connect return g.connect(curAddrs) } @@ -328,7 +292,7 @@ func (b *broadcast) Message() []byte { return nil } if l := len(up); l > MaxPacketSize { - log.Logf("[gossip]: broadcast message size %d bigger then MaxPacketSize %d", l, MaxPacketSize) + log.Logf("[gossip] broadcast message size %d bigger then MaxPacketSize %d", l, MaxPacketSize) } return up } @@ -429,6 +393,55 @@ func (d *delegate) MergeRemoteState(buf []byte, join bool) { } } +func (g *gossipRegistry) connect(addrs []string) error { + if len(addrs) == 0 { + return nil + } + + timeout := make(<-chan time.Time) + + if g.connectTimeout > 0 { + timeout = time.After(g.connectTimeout) + } + + ticker := time.NewTicker(1 * time.Second) + defer ticker.Stop() + + fn := func() (int, error) { + return g.member.Join(addrs) + } + + // don't wait for first try + if _, err := fn(); err == nil { + return nil + } + + // wait loop + for { + select { + // context closed + case <-g.options.Context.Done(): + return nil + // call close, don't wait anymore + case <-g.done: + return nil + // in case of timeout fail with a timeout error + case <-timeout: + return fmt.Errorf("[gossip] connect timeout %v", g.addrs) + // got a tick, try to connect + case <-ticker.C: + if _, err := fn(); err == nil { + log.Logf("[gossip] connect success for %v", g.addrs) + return nil + } else { + log.Logf("[gossip] connect failed for %v", g.addrs) + } + } + } + + return nil +} + func (g *gossipRegistry) publish(action string, services []*registry.Service) { g.RLock() for _, sub := range g.watchers { @@ -462,119 +475,137 @@ func (g *gossipRegistry) subscribe() (chan *registry.Result, chan bool) { return next, exit } -func (g *gossipRegistry) wait() { - ctx := g.options.Context - - if c, ok := ctx.Value(contextContext{}).(context.Context); ok && c != nil { - ctx = c - } - - ch := make(chan os.Signal, 1) - signal.Notify(ch, syscall.SIGTERM, syscall.SIGINT, syscall.SIGQUIT) - - select { - // wait on kill signal - case <-ch: - // wait on context cancel - case <-ctx.Done(): - } - - g.Stop() -} - func (g *gossipRegistry) Stop() error { - g.Lock() - if g.done != nil { + select { + case <-g.done: + return nil + default: close(g.done) - g.done = nil + g.Lock() + if g.member != nil { + g.member.Leave(g.interval * 2) + g.member.Shutdown() + g.member = nil + } + g.Unlock() } - if g.member != nil { - g.member.Leave(g.interval * 2) - g.member.Shutdown() - g.member = nil - } - g.Unlock() return nil } +// connectLoop attempts to reconnect to the memberlist +func (g *gossipRegistry) connectLoop() { + // try every second + ticker := time.NewTicker(1 * time.Second) + defer ticker.Stop() + + for { + select { + case <-g.done: + return + case <-g.options.Context.Done(): + g.Stop() + return + case <-ticker.C: + var addrs []string + + g.RLock() + + // only process if we have a memberlist + if g.member == nil { + g.RUnlock() + continue + } + + // self + local := g.member.LocalNode().Address() + + // operate on each member + for node, action := range g.members { + switch action { + // process leave event + case nodeActionLeave: + // don't process self + if node == local { + continue + } + addrs = append(addrs, node) + } + } + + g.RUnlock() + + // connect to all the members + // TODO: only connect to new members + if len(addrs) > 0 { + g.connect(addrs) + } + } + } +} + +func (g *gossipRegistry) expiryLoop(updates *updates) { + ticker := time.NewTicker(ExpiryTick) + defer ticker.Stop() + + for { + select { + case <-g.done: + return + case <-ticker.C: + now := uint64(time.Now().UnixNano()) + + updates.Lock() + + // process all the updates + for k, v := range updates.services { + // check if expiry time has passed + if d := (v.Update.Expires); d < now { + // delete from records + delete(updates.services, k) + // set to delete + v.Update.Action = actionTypeDelete + // fire a new update + g.updates <- v + } + } + + updates.Unlock() + } + } +} + +// process member events +func (g *gossipRegistry) eventLoop() { + for { + select { + // return when done + case <-g.done: + return + case ev := <-g.events: + // TODO: nonblocking update + g.Lock() + if _, ok := g.members[ev.node]; ok { + g.members[ev.node] = ev.action + } + g.Unlock() + } + } +} + func (g *gossipRegistry) run() { - var mtx sync.Mutex - updates := map[uint64]*update{} + updates := &updates{ + services: make(map[uint64]*update), + } // expiry loop - go func() { - ticker := time.NewTicker(ExpiryTick) - defer ticker.Stop() + go g.expiryLoop(updates) - for { - select { - case <-g.done: - return - case <-ticker.C: - now := uint64(time.Now().UnixNano()) - - mtx.Lock() - - // process all the updates - for k, v := range updates { - // check if expiry time has passed - if d := (v.Update.Expires); d < now { - // delete from records - delete(updates, k) - // set to delete - v.Update.Action = actionTypeDelete - // fire a new update - g.updates <- v - } - } - - mtx.Unlock() - } - } - }() - - go func() { - for { - select { - case <-g.done: - return - case ed := <-g.events: - // may be not block all registry? - g.Lock() - if _, ok := g.members[ed.node]; ok { - g.members[ed.node] = ed.action - } - g.Unlock() - } - } - }() + // event loop + go g.eventLoop() + // connect loop if g.connectRetry { - go func() { - ticker := time.NewTicker(1 * time.Second) - defer ticker.Stop() - - for { - select { - case <-g.done: - return - case <-ticker.C: - var addrs []string - g.RLock() - if g.member != nil { - for node, action := range g.members { - if action == nodeActionLeave && g.member.LocalNode().Address() != node { - addrs = append(addrs, node) - } - } - } - g.RUnlock() - if len(addrs) > 0 { - g.connect(addrs) - } - } - } - }() + go g.connectLoop() } // process the updates @@ -597,9 +628,9 @@ func (g *gossipRegistry) run() { if u.Update.Expires > 0 { // create a hash of this service if hash, err := hashstructure.Hash(u.Service, nil); err == nil { - mtx.Lock() - updates[hash] = u - mtx.Unlock() + updates.Lock() + updates.services[hash] = u + updates.Unlock() } } case actionTypeDelete: @@ -618,9 +649,9 @@ func (g *gossipRegistry) run() { // delete from expiry checks if hash, err := hashstructure.Hash(u.Service, nil); err == nil { - mtx.Lock() - delete(updates, hash) - mtx.Unlock() + updates.Lock() + delete(updates.services, hash) + updates.Unlock() } case actionTypeSync: // no sync channel provided @@ -676,7 +707,7 @@ func (g *gossipRegistry) Register(s *registry.Service, opts ...registry.Register } if options.TTL == 0 && g.tcpInterval == 0 { - return fmt.Errorf("must provide registry.RegisterTTL option or set PushPullInterval in *memberlist.Config") + return fmt.Errorf("Require register TTL or interval for memberlist.Config") } up := &pb.Update{ @@ -766,30 +797,28 @@ func (g *gossipRegistry) String() string { } func NewRegistry(opts ...registry.Option) registry.Registry { - gossip := &gossipRegistry{ + g := &gossipRegistry{ options: registry.Options{ Context: context.Background(), }, - updates: make(chan *update, 100), + done: make(chan bool), events: make(chan *event, 100), + updates: make(chan *update, 100), services: make(map[string][]*registry.Service), watchers: make(map[string]chan *registry.Result), - done: make(chan struct{}), members: make(map[string]int32), } // run the updater - go gossip.run() + go g.run() // configure the gossiper - if err := configure(gossip, opts...); err != nil { - log.Fatalf("Error configuring registry: %v", err) + if err := configure(g, opts...); err != nil { + log.Fatalf("[gossip] Error configuring registry: %v", err) } // wait for setup - <-time.After(gossip.interval * 2) + <-time.After(g.interval * 2) - go gossip.wait() - - return gossip + return g } diff --git a/registry/gossip/gossip_test.go b/registry/gossip/gossip_test.go index f72b93ef..3c774a62 100644 --- a/registry/gossip/gossip_test.go +++ b/registry/gossip/gossip_test.go @@ -35,7 +35,7 @@ func newRegistry(opts ...registry.Option) registry.Registry { return r } -func TestRegistryBroadcast(t *testing.T) { +func TestGossipRegistryBroadcast(t *testing.T) { mc1 := newMemberlistConfig() r1 := newRegistry(Config(mc1), Address("127.0.0.1:54321")) @@ -45,65 +45,57 @@ func TestRegistryBroadcast(t *testing.T) { defer r1.(*gossipRegistry).Stop() defer r2.(*gossipRegistry).Stop() - svc1 := ®istry.Service{Name: "r1-svc", Version: "0.0.0.1"} - svc2 := ®istry.Service{Name: "r2-svc", Version: "0.0.0.2"} + svc1 := ®istry.Service{Name: "service.1", Version: "0.0.0.1"} + svc2 := ®istry.Service{Name: "service.2", Version: "0.0.0.2"} - t.Logf("register service svc1 on r1\n") if err := r1.Register(svc1, registry.RegisterTTL(10*time.Second)); err != nil { t.Fatal(err) } - t.Logf("register service svc2 on r2\n") if err := r2.Register(svc2, registry.RegisterTTL(10*time.Second)); err != nil { t.Fatal(err) } var found bool - t.Logf("list services on r1\n") svcs, err := r1.ListServices() if err != nil { t.Fatal(err) } for _, svc := range svcs { - if svc.Name == "r2-svc" { + if svc.Name == "service.2" { found = true } } if !found { - t.Fatalf("r2-svc not found in r1, broadcast not work") - } else { - t.Logf("r2-svc found in r1, all ok") + t.Fatalf("[gossip registry] service.2 not found in r1, broadcast not work") } found = false - t.Logf("list services on r2\n") + svcs, err = r2.ListServices() if err != nil { t.Fatal(err) } for _, svc := range svcs { - if svc.Name == "r1-svc" { + if svc.Name == "service.1" { found = true } } + if !found { - t.Fatalf("r1-svc not found in r2, broadcast not work") - } else { - t.Logf("r1-svc found in r1, all ok") + t.Fatalf("[gossip registry] broadcast failed: service.1 not found in r2") } - t.Logf("deregister service svc1 on r1\n") if err := r1.Deregister(svc1); err != nil { t.Fatal(err) } - t.Logf("deregister service svc1 on r2\n") if err := r2.Deregister(svc2); err != nil { t.Fatal(err) } } -func TestRegistryRetry(t *testing.T) { +func TestGossipRegistryRetry(t *testing.T) { mc1 := newMemberlistConfig() r1 := newRegistry(Config(mc1), Address("127.0.0.1:54321")) @@ -113,8 +105,8 @@ func TestRegistryRetry(t *testing.T) { defer r1.(*gossipRegistry).Stop() defer r2.(*gossipRegistry).Stop() - svc1 := ®istry.Service{Name: "r1-svc", Version: "0.0.0.1"} - svc2 := ®istry.Service{Name: "r2-svc", Version: "0.0.0.2"} + svc1 := ®istry.Service{Name: "service.1", Version: "0.0.0.1"} + svc2 := ®istry.Service{Name: "service.2", Version: "0.0.0.2"} var mu sync.Mutex ch := make(chan struct{}) @@ -150,17 +142,17 @@ func TestRegistryRetry(t *testing.T) { } for _, svc := range svcs { - if svc.Name == "r1-svc" { + if svc.Name == "service.1" { found = true } } + if !found { - t.Fatalf("r1-svc not found in r2, broadcast not work, retry cant test") + t.Fatalf("[gossip registry] broadcast failed: service.1 not found in r2") } - t.Logf("stop r1\n") if err = r1.(*gossipRegistry).Stop(); err != nil { - t.Fatalf("cant stop r1 registry %v", err) + t.Fatalf("[gossip registry] failed to stop registry: %v", err) } mu.Lock() @@ -176,26 +168,24 @@ func TestRegistryRetry(t *testing.T) { } for _, svc := range svcs { - if svc.Name == "r1-svc" { + if svc.Name == "service.1" { found = true } } + if found { - t.Fatalf("r1-svc found in r2, something wrong") + t.Fatalf("[gossip registry] service.1 found in r2") } - t.Logf("start r1\n") + if tr := os.Getenv("TRAVIS"); len(tr) > 0 { + t.Logf("[gossip registry] skip test on travis") + t.Skip() + return + } r1 = newRegistry(Config(mc1), Address("127.0.0.1:54321")) <-time.After(2 * time.Second) - if tr := os.Getenv("TRAVIS"); len(tr) > 0 { - t.Logf("skip next test part, becasue it not works in travis") - t.Skip() - return - <-time.After(5 * time.Second) - } - found = false svcs, err = r2.ListServices() if err != nil { @@ -203,12 +193,13 @@ func TestRegistryRetry(t *testing.T) { } for _, svc := range svcs { - if svc.Name == "r1-svc" { + if svc.Name == "service.1" { found = true } } + if !found { - t.Fatalf("r1-svc not found in r2, connect retry not works") + t.Fatalf("[gossip registry] connect retry failed: service.1 not found in r2") } if err := r1.Deregister(svc1); err != nil { diff --git a/registry/gossip/options.go b/registry/gossip/options.go index 0a07f304..cf9dc9dc 100644 --- a/registry/gossip/options.go +++ b/registry/gossip/options.go @@ -8,55 +8,51 @@ import ( "github.com/micro/go-micro/registry" ) -type contextSecretKey struct{} +type secretKey struct{} +type addressKey struct{} +type configKey struct{} +type advertiseKey struct{} +type connectTimeoutKey struct{} +type connectRetryKey struct{} + +// helper for setting registry options +func setRegistryOption(k, v interface{}) registry.Option { + return func(o *registry.Options) { + if o.Context == nil { + o.Context = context.Background() + } + o.Context = context.WithValue(o.Context, k, v) + } +} // Secret specifies an encryption key. The value should be either // 16, 24, or 32 bytes to select AES-128, AES-192, or AES-256. func Secret(k []byte) registry.Option { - return setRegistryOption(contextSecretKey{}, k) + return setRegistryOption(secretKey{}, k) } -type contextAddress struct{} - // Address to bind to - host:port func Address(a string) registry.Option { - return setRegistryOption(contextAddress{}, a) + return setRegistryOption(addressKey{}, a) } -type contextConfig struct{} - -// Config allow to inject a *memberlist.Config struct for configuring gossip +// Config sets *memberlist.Config for configuring gossip func Config(c *memberlist.Config) registry.Option { - return setRegistryOption(contextConfig{}, c) + return setRegistryOption(configKey{}, c) } -type contextAdvertise struct{} - -// The address to advertise for other gossip members - host:port +// The address to advertise for other gossip members to connect to - host:port func Advertise(a string) registry.Option { - return setRegistryOption(contextAdvertise{}, a) + return setRegistryOption(advertiseKey{}, a) } -type contextContext struct{} - -// Context specifies a context for the registry. -// Can be used to signal shutdown of the registry. -// Can be used for extra option values. -func Context(ctx context.Context) registry.Option { - return setRegistryOption(contextContext{}, ctx) -} - -type connectTimeout struct{} - -// ConnectTimeout specify registry connect timeout use -1 to specify infinite +// ConnectTimeout sets the registry connect timeout. Use -1 to specify infinite timeout func ConnectTimeout(td time.Duration) registry.Option { - return setRegistryOption(connectTimeout{}, td) + return setRegistryOption(connectTimeoutKey{}, td) } -type connectRetry struct{} - -// ConnectRetry enable reconnect to registry then connection closed, +// ConnectRetry enables reconnect to registry then connection closed, // use with ConnectTimeout to specify how long retry func ConnectRetry(v bool) registry.Option { - return setRegistryOption(connectRetry{}, v) + return setRegistryOption(connectRetryKey{}, v) } From f4be7d018d233d7227a2102697ac37a55d04bc43 Mon Sep 17 00:00:00 2001 From: Asim Aslam Date: Wed, 13 Feb 2019 14:39:38 +0000 Subject: [PATCH 163/196] delete context file --- registry/gossip/context.go | 17 ----------------- 1 file changed, 17 deletions(-) delete mode 100644 registry/gossip/context.go diff --git a/registry/gossip/context.go b/registry/gossip/context.go deleted file mode 100644 index fd2b37cb..00000000 --- a/registry/gossip/context.go +++ /dev/null @@ -1,17 +0,0 @@ -package gossip - -import ( - "context" - - "github.com/micro/go-micro/registry" -) - -// setRegistryOption returns a function to setup a context with given value -func setRegistryOption(k, v interface{}) registry.Option { - return func(o *registry.Options) { - if o.Context == nil { - o.Context = context.Background() - } - o.Context = context.WithValue(o.Context, k, v) - } -} From e29ca94a9358353a8b7055e8b07e5564b8bb1bd3 Mon Sep 17 00:00:00 2001 From: Asim Aslam Date: Wed, 13 Feb 2019 14:41:01 +0000 Subject: [PATCH 164/196] Update go modules --- go.mod | 13 +------------ go.sum | 2 ++ 2 files changed, 3 insertions(+), 12 deletions(-) diff --git a/go.mod b/go.mod index c433312a..69b63a56 100644 --- a/go.mod +++ b/go.mod @@ -1,29 +1,18 @@ module github.com/micro/go-micro require ( - github.com/armon/go-radix v1.0.0 // indirect github.com/go-log/log v0.1.0 github.com/golang/protobuf v1.2.0 github.com/google/uuid v1.1.0 github.com/hashicorp/consul v1.4.2 - github.com/hashicorp/go-sockaddr v1.0.1 // indirect github.com/hashicorp/memberlist v0.1.3 - github.com/mattn/go-colorable v0.1.0 // indirect - github.com/mattn/go-isatty v0.0.4 // indirect github.com/micro/cli v0.1.0 github.com/micro/go-log v0.1.0 - github.com/micro/go-rcache v0.1.0 + github.com/micro/go-rcache v0.2.0 github.com/micro/h2c v1.0.0 github.com/micro/mdns v0.1.0 github.com/micro/util v0.1.0 - github.com/miekg/dns v1.1.4 // indirect - github.com/mitchellh/go-homedir v1.1.0 // indirect github.com/mitchellh/hashstructure v1.0.0 github.com/pkg/errors v0.8.1 - github.com/posener/complete v1.2.1 // indirect - github.com/stretchr/objx v0.1.1 // indirect - golang.org/x/crypto v0.0.0-20190211182817-74369b46fc67 // indirect golang.org/x/net v0.0.0-20190213061140-3a22650c66bd - golang.org/x/sys v0.0.0-20190213121743-983097b1a8a3 // indirect - gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127 // indirect ) diff --git a/go.sum b/go.sum index 6d57e67c..c3b47f84 100644 --- a/go.sum +++ b/go.sum @@ -54,8 +54,10 @@ github.com/micro/cli v0.1.0/go.mod h1:jRT9gmfVKWSS6pkKcXQ8YhUyj6bzwxK8Fp5b0Y7qNn github.com/micro/go-log v0.1.0 h1:szYSR+yyTsomZM2jyinJC5562DlqffSjHmTZFaeZ2vY= github.com/micro/go-log v0.1.0/go.mod h1:qaFBF6d6Jk01Gz4cbMkCA2vVuLk3FSaLLjmEGrMCreA= github.com/micro/go-micro v0.23.0/go.mod h1:3z3lfMkNU9Sr1L/CxL++8pVJmQapRo0N6kNjwYDtOVs= +github.com/micro/go-micro v0.26.0/go.mod h1:CweCFO/pq8dCSIOdzVZ4ooIpUrKlyJ0AcFB269M7PgU= github.com/micro/go-rcache v0.1.0 h1:YTIgANVHgBe1XOQ/yLICL+s2gbZCAdW+c2ckhekjkuc= github.com/micro/go-rcache v0.1.0/go.mod h1:INzyZjXO5M+PmN2A33YxD4TaOY61xjFIM4CfSHv+At8= +github.com/micro/go-rcache v0.2.0/go.mod h1:EoiTwbY2ubQ6lc3ScV+SnmKbelDzeFezDxPDvF8XDxw= github.com/micro/h2c v1.0.0/go.mod h1:54sOOQW/GRlHhH43vKwOhUb+kHaXhVxR0d3CJhn9alE= github.com/micro/mdns v0.0.0-20181201230301-9c3770d4057a/go.mod h1:SQG6o/94RinohLuB5noHSevg2Iqg2wXLDUn4lj2LWWo= github.com/micro/mdns v0.1.0 h1:fuLybUsfynbigJmCot/54i+gwe0hpc/vtCMvWt2WfDI= From 0a8f9b0a622c8ba0ce545c9a87b89276b4813bfa Mon Sep 17 00:00:00 2001 From: Vasiliy Tolstov Date: Fri, 15 Feb 2019 17:20:00 +0300 Subject: [PATCH 165/196] fix race in http transport Signed-off-by: Vasiliy Tolstov --- transport/http_transport.go | 7 ------- 1 file changed, 7 deletions(-) diff --git a/transport/http_transport.go b/transport/http_transport.go index ea98accc..3aed66be 100644 --- a/transport/http_transport.go +++ b/transport/http_transport.go @@ -133,12 +133,6 @@ func (h *httpTransportClient) Recv(m *Message) error { r = rc } - h.RLock() - if h.buff == nil { - return io.EOF - } - h.RUnlock() - // set timeout if its greater than 0 if h.ht.opts.Timeout > time.Duration(0) { h.conn.SetDeadline(time.Now().Add(h.ht.opts.Timeout)) @@ -181,7 +175,6 @@ func (h *httpTransportClient) Close() error { h.once.Do(func() { h.Lock() h.buff.Reset(nil) - h.buff = nil h.Unlock() close(h.r) }) From 6819989195b1a65a970b5fb4c68cd16ea4f7daf7 Mon Sep 17 00:00:00 2001 From: Asim Aslam Date: Fri, 15 Feb 2019 16:14:41 +0000 Subject: [PATCH 166/196] change default name/version --- server/server.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/server/server.go b/server/server.go index ef0f619b..2810f253 100644 --- a/server/server.go +++ b/server/server.go @@ -116,8 +116,8 @@ type Option func(*Options) var ( DefaultAddress = ":0" - DefaultName = "go-server" - DefaultVersion = "1.0.0" + DefaultName = "server" + DefaultVersion = "latest" DefaultId = uuid.New().String() DefaultServer Server = newRpcServer() DefaultRouter = newRpcRouter() From 7db2912d90da5c8559200c60978f677ad9bdeca5 Mon Sep 17 00:00:00 2001 From: Asim Aslam Date: Fri, 15 Feb 2019 17:20:09 +0000 Subject: [PATCH 167/196] add more verbose output --- server/rpc_server.go | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/server/rpc_server.go b/server/rpc_server.go index 5551e88a..57fd0685 100644 --- a/server/rpc_server.go +++ b/server/rpc_server.go @@ -339,7 +339,7 @@ func (s *rpcServer) Register() error { s.Unlock() if !registered { - log.Logf("Registering node: %s", node.Id) + log.Logf("Registry [%s] Registering node: %s", config.Registry.String(), node.Id) } // create registry options @@ -417,7 +417,7 @@ func (s *rpcServer) Deregister() error { Nodes: []*registry.Node{node}, } - log.Logf("Deregistering node: %s", node.Id) + log.Logf("Registry [%s] Deregistering node: %s", config.Registry.String(), node.Id) if err := config.Registry.Deregister(service); err != nil { return err } @@ -466,7 +466,7 @@ func (s *rpcServer) Start() error { return err } - log.Logf("Broker [%s] Listening on %s", config.Broker.String(), config.Broker.Address()) + log.Logf("Broker [%s] Connected to %s", config.Broker.String(), config.Broker.Address()) // announce self to the world if err := s.Register(); err != nil { From 58adaef339ebeb3ba9712a44537b8d5e55bf5499 Mon Sep 17 00:00:00 2001 From: Asim Aslam Date: Sat, 23 Feb 2019 10:50:53 +0000 Subject: [PATCH 168/196] Add Exchange option --- client/options.go | 9 +++++++++ client/rpc_client.go | 17 +++++++++++++++-- 2 files changed, 24 insertions(+), 2 deletions(-) diff --git a/client/options.go b/client/options.go index dca251c6..30a6386c 100644 --- a/client/options.go +++ b/client/options.go @@ -65,6 +65,8 @@ type CallOptions struct { } type PublishOptions struct { + // Exchange is the routing exchange for the message + Exchange string // Other options for implementations of the interface // can be stored in a context Context context.Context @@ -236,6 +238,13 @@ func DialTimeout(d time.Duration) Option { // Call Options +// WithExchange sets the exchange to route a message through +func WithExchange(e string) PublishOption { + return func(o *PublishOptions) { + o.Exchange = e + } +} + // WithAddress sets the remote address to use rather than using service discovery func WithAddress(a string) CallOption { return func(o *CallOptions) { diff --git a/client/rpc_client.go b/client/rpc_client.go index 864eaad1..b50f79f9 100644 --- a/client/rpc_client.go +++ b/client/rpc_client.go @@ -498,6 +498,13 @@ func (r *rpcClient) Stream(ctx context.Context, request Request, opts ...CallOpt } func (r *rpcClient) Publish(ctx context.Context, msg Message, opts ...PublishOption) error { + options := PublishOptions{ + Context: context.Background(), + } + for _, o := range opts { + o(&options) + } + md, ok := metadata.FromContext(ctx) if !ok { md = make(map[string]string) @@ -508,6 +515,12 @@ func (r *rpcClient) Publish(ctx context.Context, msg Message, opts ...PublishOpt md["Micro-Topic"] = msg.Topic() md["Micro-Id"] = id + // get the routing exchange + topic := msg.Topic() + if len(options.Exchange) > 0 { + topic = options.Exchange + } + // encode message body cf, err := r.newCodec(msg.ContentType()) if err != nil { @@ -515,7 +528,7 @@ func (r *rpcClient) Publish(ctx context.Context, msg Message, opts ...PublishOpt } b := &buffer{bytes.NewBuffer(nil)} if err := cf(b).Write(&codec.Message{ - Target: msg.Topic(), + Target: topic, Type: codec.Publication, Header: map[string]string{ "Micro-Id": id, @@ -528,7 +541,7 @@ func (r *rpcClient) Publish(ctx context.Context, msg Message, opts ...PublishOpt r.opts.Broker.Connect() }) - return r.opts.Broker.Publish(msg.Topic(), &broker.Message{ + return r.opts.Broker.Publish(topic, &broker.Message{ Header: md, Body: b.Bytes(), }) From f1df0f6dfe369129d6389769a66d53811758782b Mon Sep 17 00:00:00 2001 From: Asim Aslam Date: Sat, 23 Feb 2019 16:29:15 +0000 Subject: [PATCH 169/196] update go modules --- go.mod | 8 ++++++-- go.sum | 13 +++++++++++++ 2 files changed, 19 insertions(+), 2 deletions(-) diff --git a/go.mod b/go.mod index 69b63a56..62629305 100644 --- a/go.mod +++ b/go.mod @@ -1,18 +1,22 @@ module github.com/micro/go-micro require ( + github.com/armon/circbuf v0.0.0-20190214190532-5111143e8da2 // indirect github.com/go-log/log v0.1.0 github.com/golang/protobuf v1.2.0 github.com/google/uuid v1.1.0 github.com/hashicorp/consul v1.4.2 github.com/hashicorp/memberlist v0.1.3 + github.com/mattn/go-colorable v0.1.1 // indirect github.com/micro/cli v0.1.0 github.com/micro/go-log v0.1.0 - github.com/micro/go-rcache v0.2.0 + github.com/micro/go-rcache v0.2.1 github.com/micro/h2c v1.0.0 github.com/micro/mdns v0.1.0 - github.com/micro/util v0.1.0 + github.com/micro/util v0.2.0 github.com/mitchellh/hashstructure v1.0.0 github.com/pkg/errors v0.8.1 + golang.org/x/crypto v0.0.0-20190222235706-ffb98f73852f // indirect golang.org/x/net v0.0.0-20190213061140-3a22650c66bd + golang.org/x/sys v0.0.0-20190222171317-cd391775e71e // indirect ) diff --git a/go.sum b/go.sum index c3b47f84..62099832 100644 --- a/go.sum +++ b/go.sum @@ -1,4 +1,5 @@ github.com/armon/circbuf v0.0.0-20150827004946-bbbad097214e/go.mod h1:3U/XgcO3hCbHZ8TKRvWD2dDTCfh9M9ya+I9JpbB7O8o= +github.com/armon/circbuf v0.0.0-20190214190532-5111143e8da2/go.mod h1:3U/XgcO3hCbHZ8TKRvWD2dDTCfh9M9ya+I9JpbB7O8o= github.com/armon/go-metrics v0.0.0-20180917152333-f0300d1749da h1:8GUt8eRujhVEGZFFEjBj46YV4rDjvGrNxb0KMWYkL2I= github.com/armon/go-metrics v0.0.0-20180917152333-f0300d1749da/go.mod h1:Q73ZrmVTwzkszR9V5SSuryQ31EELlFMUz1kKyl939pY= github.com/armon/go-radix v0.0.0-20180808171621-7fddfc383310/go.mod h1:ufUuZ+zHj4x4TnLV4JWEpy2hxWSpsRywHrMgIH9cCH8= @@ -46,8 +47,10 @@ github.com/hashicorp/serf v0.8.2 h1:YZ7UKsJv+hKjqGVUUbtE3HNj79Eln2oQ75tniF6iPt0= github.com/hashicorp/serf v0.8.2/go.mod h1:6hOLApaqBFA1NXqRQAsxw9QxuDEvNxSQRwA/JwenrHc= github.com/mattn/go-colorable v0.0.9/go.mod h1:9vuHe8Xs5qXnSaW/c/ABM9alt+Vo+STaOChaDxuIBZU= github.com/mattn/go-colorable v0.1.0/go.mod h1:9vuHe8Xs5qXnSaW/c/ABM9alt+Vo+STaOChaDxuIBZU= +github.com/mattn/go-colorable v0.1.1/go.mod h1:FuOcm+DKB9mbwrcAfNl7/TZVBZ6rcnceauSikq3lYCQ= github.com/mattn/go-isatty v0.0.3/go.mod h1:M+lRXTBqGeGNdLjl/ufCoiOlB5xdOkqRJdNxMWT7Zi4= github.com/mattn/go-isatty v0.0.4/go.mod h1:M+lRXTBqGeGNdLjl/ufCoiOlB5xdOkqRJdNxMWT7Zi4= +github.com/mattn/go-isatty v0.0.5/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hdxcsrc5s= github.com/micro/cli v0.0.0-20181223203424-1b0c9793c300/go.mod h1:x9x6qy+tXv17jzYWQup462+j3SIUgDa6vVTzU4IXy/w= github.com/micro/cli v0.1.0 h1:5DT+QdbAPPQvB3gYTgwze7tFO1m+7DU1sz9XfQczbsc= github.com/micro/cli v0.1.0/go.mod h1:jRT9gmfVKWSS6pkKcXQ8YhUyj6bzwxK8Fp5b0Y7qNnk= @@ -55,15 +58,20 @@ github.com/micro/go-log v0.1.0 h1:szYSR+yyTsomZM2jyinJC5562DlqffSjHmTZFaeZ2vY= github.com/micro/go-log v0.1.0/go.mod h1:qaFBF6d6Jk01Gz4cbMkCA2vVuLk3FSaLLjmEGrMCreA= github.com/micro/go-micro v0.23.0/go.mod h1:3z3lfMkNU9Sr1L/CxL++8pVJmQapRo0N6kNjwYDtOVs= github.com/micro/go-micro v0.26.0/go.mod h1:CweCFO/pq8dCSIOdzVZ4ooIpUrKlyJ0AcFB269M7PgU= +github.com/micro/go-micro v0.26.1/go.mod h1:Jgc5gPEmDiG1TWE5Qnzzx5qyXnU9VTXKT1FkXkfvt8g= github.com/micro/go-rcache v0.1.0 h1:YTIgANVHgBe1XOQ/yLICL+s2gbZCAdW+c2ckhekjkuc= github.com/micro/go-rcache v0.1.0/go.mod h1:INzyZjXO5M+PmN2A33YxD4TaOY61xjFIM4CfSHv+At8= github.com/micro/go-rcache v0.2.0/go.mod h1:EoiTwbY2ubQ6lc3ScV+SnmKbelDzeFezDxPDvF8XDxw= +github.com/micro/go-rcache v0.2.1 h1:hx24BZuhW4UVCyLE8p6fDrUetXrYDlOYSn5DSmqcjms= +github.com/micro/go-rcache v0.2.1/go.mod h1:aPCNY3RbjBdyd6ShLENl4MDSgpAiWIU4LyNLE9+TOEo= github.com/micro/h2c v1.0.0/go.mod h1:54sOOQW/GRlHhH43vKwOhUb+kHaXhVxR0d3CJhn9alE= github.com/micro/mdns v0.0.0-20181201230301-9c3770d4057a/go.mod h1:SQG6o/94RinohLuB5noHSevg2Iqg2wXLDUn4lj2LWWo= github.com/micro/mdns v0.1.0 h1:fuLybUsfynbigJmCot/54i+gwe0hpc/vtCMvWt2WfDI= github.com/micro/mdns v0.1.0/go.mod h1:KJ0dW7KmicXU2BV++qkLlmHYcVv7/hHnbtguSWt9Aoc= github.com/micro/util v0.1.0 h1:ghhF5KKRNlKMexzK+cWo6W6uRAZdKy1UKG/9O74NCYc= github.com/micro/util v0.1.0/go.mod h1:MZgOs0nwxzv9k4xQo4fpF9IwZGF2O96F5/phP9X4/Sw= +github.com/micro/util v0.2.0 h1:6u0cPj1TeixEk5cAR9jbcVRUWDQsmCaZvDBiM3zFZuA= +github.com/micro/util v0.2.0/go.mod h1:SgRDkxJJluC2ZNiPfINY42ObEaCAFjL3jP5a+u+qRLU= github.com/miekg/dns v1.0.14/go.mod h1:W1PPwlIAgtquWBMBEV9nkV9Cazfe8ScdGz/Lj7v3Nrg= github.com/miekg/dns v1.1.3/go.mod h1:W1PPwlIAgtquWBMBEV9nkV9Cazfe8ScdGz/Lj7v3Nrg= github.com/miekg/dns v1.1.4 h1:rCMZsU2ScVSYcAsOXgmC6+AKOK+6pmQTOcw03nfwYV0= @@ -99,6 +107,8 @@ golang.org/x/crypto v0.0.0-20190131182504-b8fe1690c613 h1:MQ/ZZiDsUapFFiMS+vzwXk golang.org/x/crypto v0.0.0-20190131182504-b8fe1690c613/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= golang.org/x/crypto v0.0.0-20190211182817-74369b46fc67 h1:ng3VDlRp5/DHpSWl02R4rM9I+8M2rhmsuLwAMmkLQWE= golang.org/x/crypto v0.0.0-20190211182817-74369b46fc67/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= +golang.org/x/crypto v0.0.0-20190222235706-ffb98f73852f h1:qWFY9ZxP3tfI37wYIs/MnIAqK0vlXp1xnYEa5HxFSSY= +golang.org/x/crypto v0.0.0-20190222235706-ffb98f73852f/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= golang.org/x/net v0.0.0-20181023162649-9b4f9f5ad519/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20181201002055-351d144fa1fc/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20190125091013-d26f9f9a57f3/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= @@ -116,6 +126,9 @@ golang.org/x/sys v0.0.0-20190209173611-3b5209105503 h1:5SvYFrOM3W8Mexn9/oA44Ji7v golang.org/x/sys v0.0.0-20190209173611-3b5209105503/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190213121743-983097b1a8a3 h1:+KlxhGbYkFs8lMfwKn+2ojry1ID5eBSMXprS2u/wqCE= golang.org/x/sys v0.0.0-20190213121743-983097b1a8a3/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20190222072716-a9d3bda3a223/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20190222171317-cd391775e71e h1:oF7qaQxUH6KzFdKN4ww7NpPdo53SZi4UlcksLrb2y/o= +golang.org/x/sys v0.0.0-20190222171317-cd391775e71e/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/text v0.3.0 h1:g61tztE5qeGQ89tm6NTjjM9VPIm088od1l6aSorWRWg= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= From b8f20924cc2107b0bde8fe8a76fd79f6a412fb6a Mon Sep 17 00:00:00 2001 From: Asim Aslam Date: Sat, 23 Feb 2019 17:06:17 +0000 Subject: [PATCH 170/196] proxy publish --- client/rpc_client.go | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/client/rpc_client.go b/client/rpc_client.go index b50f79f9..0e05dae9 100644 --- a/client/rpc_client.go +++ b/client/rpc_client.go @@ -515,8 +515,15 @@ func (r *rpcClient) Publish(ctx context.Context, msg Message, opts ...PublishOpt md["Micro-Topic"] = msg.Topic() md["Micro-Id"] = id - // get the routing exchange + // set the topic topic := msg.Topic() + + // get proxy + if prx := os.Getenv("MICRO_PROXY"); len(prx) > 0 { + options.Exchange = prx + } + + // get the exchange if len(options.Exchange) > 0 { topic = options.Exchange } From d3f447a7321f77366b0fff59d0fb60c90f3b0197 Mon Sep 17 00:00:00 2001 From: shuxian Date: Thu, 28 Feb 2019 09:56:57 +0800 Subject: [PATCH 171/196] solve NewRegistry httpclient 'nil pointer dereference' bug --- registry/consul/consul.go | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/registry/consul/consul.go b/registry/consul/consul.go index 7e9cf794..52b8b2cd 100644 --- a/registry/consul/consul.go +++ b/registry/consul/consul.go @@ -105,12 +105,13 @@ func configure(c *consulRegistry, opts ...registry.Option) { } } + if config.HttpClient == nil { + config.HttpClient = new(http.Client) + } + // requires secure connection? if c.opts.Secure || c.opts.TLSConfig != nil { - if config.HttpClient == nil { - config.HttpClient = new(http.Client) - } - + config.Scheme = "https" // We're going to support InsecureSkipVerify config.HttpClient.Transport = newTransport(c.opts.TLSConfig) From 6802de63ff0f0c2374bd27eec9315d05c9247150 Mon Sep 17 00:00:00 2001 From: shuxian Date: Thu, 28 Feb 2019 16:57:31 +0800 Subject: [PATCH 172/196] readme zh-cn version --- README.md | 2 ++ README.zh-cn.md | 41 +++++++++++++++++++++++++++++++++++++++++ 2 files changed, 43 insertions(+) create mode 100644 README.zh-cn.md diff --git a/README.md b/README.md index 0f17836c..c573afee 100644 --- a/README.md +++ b/README.md @@ -2,6 +2,8 @@ Go Micro is a framework for micro service development. +Read this in other languages: [简体中文](./README.zh-cn.md) + ## Overview Go Micro provides the core requirements for distributed systems development including RPC and Event driven communication. diff --git a/README.zh-cn.md b/README.zh-cn.md new file mode 100644 index 00000000..9e80fbaa --- /dev/null +++ b/README.zh-cn.md @@ -0,0 +1,41 @@ +# Go Micro [![License](https://img.shields.io/:license-apache-blue.svg)](https://opensource.org/licenses/Apache-2.0) [![GoDoc](https://godoc.org/github.com/micro/go-micro?status.svg)](https://godoc.org/github.com/micro/go-micro) [![Travis CI](https://api.travis-ci.org/micro/go-micro.svg?branch=master)](https://travis-ci.org/micro/go-micro) [![Go Report Card](https://goreportcard.com/badge/micro/go-micro)](https://goreportcard.com/report/github.com/micro/go-micro) + +Go Micro是基于Golang的微服务开发框架。 + +## 概览 + +Go Micro提供分布式系统开发的核心库,包含RPC与事件驱动的通信机制。 + +**micro**的设计哲学是可插拔的架构理念,她提供可快速构建系统的组件,并且可以根据自身的需求剥离默认实现并自行定制。 + + + +所有插件可在仓库[github.com/micro/go-plugins](https://github.com/micro/go-plugins)中找到。 + +可以订阅我们的[Twitter](https://twitter.com/microhq)或者加入[Slack](http://slack.micro.mu/)论坛。 + +## 特性 + +Go Micro把分布式系统的各种细节抽象出来。下面是它的主要特性。 + +- **服务发现(Service Discovery)** - 自动服务注册与名称解析。服务发现是微服务开发中的核心。当服务A要与服务B协作时,它得知道B在哪里。默认的服务发现系统是Consul,而multicast DNS (mdns,组播)机制作为本地解决方案,或者零依赖的P2P网络中的SWIM协议(gossip)。 + +- **负载均衡(Load Balancing)** - 在服务发现之上构建了负载均衡机制。当我们得到一个服务的任意多个的实例节点时,我们要一个机制去决定要路由到哪一个节点。我们使用随机处理过的哈希负载均衡机制来保证对服务请求颁发的均匀分布,并且在发生问题时进行重试。 + +- **消息编码(Message Encoding)** - 支持基于内容类型(content-type)动态编码消息。客户端和服务端会一起使用content-type的格式来对Go进行无缝编/解码。各种各样的消息被编码会发送到不同的客户端,客户端服服务端默认会处理这些消息。content-type默认包含proto-rpc和json-rpc。 + +- **Request/Response** - RPC通信基于支持双向流的请求/响应方式,我们提供有抽象的同步通信机制。请求发送到服务时,会自动解析、负载均衡、拨号、转成字节流。默认的传输协议是http/1.1,而tls下使用http2协议。 + +- **异步消息(Async Messaging)** - 发布订阅(PubSub)头等功能内置在异步通信与事件驱动架构中。事件通知在微服务开发中处于核心位置。默认的消息传送使用点到点http/1.1,激活tls时则使用http2。 + +- **可插拔接口(Pluggable Interfaces)** - Go Micro为每个分布式系统抽象出接口。因此,Go Micro的接口都是可插拔的,允许其在运行时不可知的情况下仍可支持。所以只要实现接口,可以在内部使用任何的技术。更多插件请参考:[github.com/micro/go-plugins](https://github.com/micro/go-plugins)。 + +## 快速上手 + +更多关于架构、安装的资料可以查看[文档](https://micro.mu/docs/go-micro_cn.html)。 + +## 赞助商 + +Sixt是我们的赞助商。 + + From 598de823baac011f48694725fcf9ebbcbe76fe5b Mon Sep 17 00:00:00 2001 From: shuxian Date: Sun, 3 Mar 2019 21:36:44 +0800 Subject: [PATCH 173/196] add Chinese version guide --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index c573afee..dc223950 100644 --- a/README.md +++ b/README.md @@ -2,7 +2,7 @@ Go Micro is a framework for micro service development. -Read this in other languages: [简体中文](./README.zh-cn.md) +Read this in other languages: [Simplified Chinese](./README.zh-cn.md) ## Overview From 98108d6297a3893915f556008a5fc797522c5762 Mon Sep 17 00:00:00 2001 From: Asim Aslam Date: Tue, 5 Mar 2019 13:13:56 +0000 Subject: [PATCH 174/196] Update README.md --- README.md | 2 -- 1 file changed, 2 deletions(-) diff --git a/README.md b/README.md index dc223950..0f17836c 100644 --- a/README.md +++ b/README.md @@ -2,8 +2,6 @@ Go Micro is a framework for micro service development. -Read this in other languages: [Simplified Chinese](./README.zh-cn.md) - ## Overview Go Micro provides the core requirements for distributed systems development including RPC and Event driven communication. From dbe83c0fff292f4c68e213eb4a057eacf5e32feb Mon Sep 17 00:00:00 2001 From: Asim Aslam Date: Thu, 7 Mar 2019 20:29:40 +0000 Subject: [PATCH 175/196] bump travis --- .travis.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index 96a32173..d7248d68 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,7 +1,7 @@ language: go go: -- 1.10.x - 1.11.x +- 1.12.x notifications: slack: secure: aEvhLbhujaGaKSrOokiG3//PaVHTIrc3fBpoRbCRqfZpyq6WREoapJJhF+tIpWWOwaC9GmChbD6aHo/jMUgwKXVyPSaNjiEL87YzUUpL8B2zslNp1rgfTg/LrzthOx3Q1TYwpaAl3to0fuHUVFX4yMeC2vuThq7WSXgMMxFCtbc= From ca77773fbf453ea3017b946ffd0f8de7bc9b5a5f Mon Sep 17 00:00:00 2001 From: Asim Aslam Date: Tue, 19 Mar 2019 00:21:25 +0000 Subject: [PATCH 176/196] fix json tag parsing --- server/extractor.go | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/server/extractor.go b/server/extractor.go index f33348ed..0a4297e4 100644 --- a/server/extractor.go +++ b/server/extractor.go @@ -20,6 +20,10 @@ func extractValue(v reflect.Type, d int) *registry.Value { v = v.Elem() } + if len(v.Name()) == 0 { + return nil + } + arg := ®istry.Value{ Name: v.Name(), Type: v.Name(), @@ -37,6 +41,9 @@ func extractValue(v reflect.Type, d int) *registry.Value { // if we can find a json tag use it if tags := f.Tag.Get("json"); len(tags) > 0 { parts := strings.Split(tags, ",") + if parts[0] == "-" || parts[0] == "omitempty" { + continue + } val.Name = parts[0] } @@ -45,6 +52,11 @@ func extractValue(v reflect.Type, d int) *registry.Value { val.Name = v.Field(i).Name } + // still no name then continue + if len(val.Name) == 0 { + continue + } + arg.Values = append(arg.Values, val) } case reflect.Slice: From 722a3682c854ba3fbd8b932228734f9dfe7bf887 Mon Sep 17 00:00:00 2001 From: Asim Aslam Date: Thu, 28 Mar 2019 17:01:56 +0000 Subject: [PATCH 177/196] Update go mod --- go.mod | 122 ++++++++- go.sum | 813 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++- 2 files changed, 917 insertions(+), 18 deletions(-) diff --git a/go.mod b/go.mod index 62629305..bf225bbf 100644 --- a/go.mod +++ b/go.mod @@ -1,22 +1,124 @@ module github.com/micro/go-micro require ( - github.com/armon/circbuf v0.0.0-20190214190532-5111143e8da2 // indirect + cloud.google.com/go v0.36.0 // indirect + github.com/DataDog/datadog-go v0.0.0-20190323183505-07c7c350327b // indirect + github.com/Microsoft/go-winio v0.4.12 // indirect + github.com/NYTimes/gziphandler v1.1.1 // indirect + github.com/SAP/go-hdb v0.14.1 // indirect + github.com/StackExchange/wmi v0.0.0-20181212234831-e0a55b97c705 // indirect + github.com/aliyun/alibaba-cloud-sdk-go v0.0.0-20190328075325-5887fb5d0027 // indirect + github.com/araddon/gou v0.0.0-20190110011759-c797efecbb61 // indirect + github.com/aws/aws-sdk-go v1.17.5 // indirect + github.com/boombuler/barcode v1.0.0 // indirect + github.com/briankassouf/jose v0.9.1 // indirect + github.com/cenkalti/backoff v2.1.1+incompatible // indirect + github.com/centrify/cloud-golang-sdk v0.0.0-20190214225812-119110094d0f // indirect + github.com/chrismalek/oktasdk-go v0.0.0-20181212195951-3430665dfaa0 // indirect + github.com/circonus-labs/circonus-gometrics v2.2.6+incompatible // indirect + github.com/containerd/continuity v0.0.0-20181203112020-004b46473808 // indirect + github.com/coredns/coredns v1.4.0 // indirect + github.com/coreos/etcd v3.3.12+incompatible // indirect + github.com/coreos/go-oidc v2.0.0+incompatible // indirect + github.com/coreos/go-semver v0.2.0 // indirect + github.com/coreos/pkg v0.0.0-20180928190104-399ea9e2e55f // indirect + github.com/dancannon/gorethink v4.0.0+incompatible // indirect + github.com/denisenkom/go-mssqldb v0.0.0-20190328043727-2183450503ad // indirect + github.com/dimchansky/utfbom v1.1.0 // indirect + github.com/duosecurity/duo_api_golang v0.0.0-20190308151101-6c680f768e74 // indirect + github.com/envoyproxy/go-control-plane v0.6.9 // indirect + github.com/fullsailor/pkcs7 v0.0.0-20180613152042-8306686428a5 // indirect + github.com/gammazero/deque v0.0.0-20190130191400-2afb3858e9c7 // indirect + github.com/gammazero/workerpool v0.0.0-20181230203049-86a96b5d5d92 // indirect + github.com/garyburd/redigo v1.6.0 // indirect + github.com/go-errors/errors v1.0.1 // indirect + github.com/go-ldap/ldap v3.0.2+incompatible // indirect github.com/go-log/log v0.1.0 - github.com/golang/protobuf v1.2.0 - github.com/google/uuid v1.1.0 - github.com/hashicorp/consul v1.4.2 + github.com/go-ole/go-ole v1.2.4 // indirect + github.com/go-sql-driver/mysql v1.4.1 // indirect + github.com/go-stomp/stomp v2.0.2+incompatible // indirect + github.com/gocql/gocql v0.0.0-20190325140904-fc3925ac2cbd // indirect + github.com/gogo/googleapis v1.1.0 // indirect + github.com/gogo/protobuf v1.2.1 // indirect + github.com/golang/groupcache v0.0.0-20190129154638-5b532d6fd5ef // indirect + github.com/golang/protobuf v1.3.1 + github.com/golang/snappy v0.0.1 // indirect + github.com/google/btree v1.0.0 // indirect + github.com/google/uuid v1.1.1 + github.com/gorhill/cronexpr v0.0.0-20180427100037-88b0669f7d75 // indirect + github.com/gorilla/websocket v1.4.0 // indirect + github.com/grpc-ecosystem/go-grpc-middleware v1.0.0 // indirect + github.com/grpc-ecosystem/go-grpc-prometheus v1.2.0 // indirect + github.com/grpc-ecosystem/grpc-gateway v1.8.5 // indirect + github.com/hashicorp/consul v1.4.4 + github.com/hashicorp/go-discover v0.0.0-20190319153616-61771d82ff54 // indirect + github.com/hashicorp/go-gcp-common v0.5.0 // indirect + github.com/hashicorp/go-hclog v0.8.0 // indirect + github.com/hashicorp/go-memdb v1.0.0 // indirect + github.com/hashicorp/go-plugin v1.0.0 // indirect + github.com/hashicorp/go-retryablehttp v0.5.3 // indirect + github.com/hashicorp/go-rootcerts v1.0.0 // indirect + github.com/hashicorp/go-sockaddr v1.0.2 // indirect + github.com/hashicorp/go-version v1.1.0 // indirect + github.com/hashicorp/golang-lru v0.5.1 // indirect + github.com/hashicorp/hil v0.0.0-20190212132231-97b3a9cdfa93 // indirect github.com/hashicorp/memberlist v0.1.3 - github.com/mattn/go-colorable v0.1.1 // indirect + github.com/hashicorp/net-rpc-msgpackrpc v0.0.0-20151116020338-a14192a58a69 // indirect + github.com/hashicorp/nomad v0.8.7 // indirect + github.com/hashicorp/raft-boltdb v0.0.0-20171010151810-6e5ba93211ea // indirect + github.com/hashicorp/serf v0.8.2 // indirect + github.com/hashicorp/vault v1.1.0 // indirect + github.com/hashicorp/vault-plugin-auth-alicloud v0.0.0-20190320211238-36e70c54375f // indirect + github.com/hashicorp/vault-plugin-auth-azure v0.0.0-20190320211138-f34b96803f04 // indirect + github.com/hashicorp/vault-plugin-auth-centrify v0.0.0-20190320211357-44eb061bdfd8 // indirect + github.com/hashicorp/vault-plugin-auth-gcp v0.0.0-20190320214413-e8308b5e41c9 // indirect + github.com/hashicorp/vault-plugin-auth-jwt v0.0.0-20190321042813-9474f90fb1df // indirect + github.com/hashicorp/vault-plugin-auth-kubernetes v0.0.0-20190328163920-79931ee7aad5 // indirect + github.com/hashicorp/vault-plugin-secrets-ad v0.0.0-20190327182327-ed2c3d4c3d95 // indirect + github.com/hashicorp/vault-plugin-secrets-alicloud v0.0.0-20190320213517-3307bdf683cb // indirect + github.com/hashicorp/vault-plugin-secrets-azure v0.0.0-20190320211922-2dc8a8a5e490 // indirect + github.com/hashicorp/vault-plugin-secrets-gcp v0.0.0-20190320211452-71903323ecb4 // indirect + github.com/hashicorp/vault-plugin-secrets-gcpkms v0.0.0-20190320213325-9e326a9e802d // indirect + github.com/hashicorp/vault-plugin-secrets-kv v0.0.0-20190320211621-3ccc8684cf25 // indirect + github.com/influxdata/influxdb v1.7.5 // indirect + github.com/influxdata/platform v0.0.0-20190117200541-d500d3cf5589 // indirect + github.com/jeffchao/backoff v0.0.0-20140404060208-9d7fd7aa17f2 // indirect + github.com/jefferai/jsonx v1.0.0 // indirect + github.com/jonboulle/clockwork v0.1.0 // indirect + github.com/keybase/go-crypto v0.0.0-20190312101036-b475f2ecc1fe // indirect + github.com/lyft/protoc-gen-validate v0.0.14 // indirect + github.com/mattbaird/elastigo v0.0.0-20170123220020-2fe47fd29e4b // indirect + github.com/mattn/go-isatty v0.0.7 // indirect + github.com/michaelklishin/rabbit-hole v1.5.0 // indirect github.com/micro/cli v0.1.0 github.com/micro/go-log v0.1.0 - github.com/micro/go-rcache v0.2.1 - github.com/micro/h2c v1.0.0 + github.com/micro/go-rcache v0.3.0 github.com/micro/mdns v0.1.0 github.com/micro/util v0.2.0 github.com/mitchellh/hashstructure v1.0.0 + github.com/mitchellh/pointerstructure v0.0.0-20190323210102-2db4bb651397 // indirect + github.com/ory-am/common v0.4.0 // indirect + github.com/ory/dockertest v3.3.4+incompatible // indirect + github.com/pascaldekloe/goe v0.1.0 // indirect + github.com/pborman/uuid v1.2.0 // indirect github.com/pkg/errors v0.8.1 - golang.org/x/crypto v0.0.0-20190222235706-ffb98f73852f // indirect - golang.org/x/net v0.0.0-20190213061140-3a22650c66bd - golang.org/x/sys v0.0.0-20190222171317-cd391775e71e // indirect + github.com/pquerna/cachecontrol v0.0.0-20180517163645-1555304b9b35 // indirect + github.com/pquerna/otp v1.1.0 // indirect + github.com/ryanuber/go-glob v1.0.0 // indirect + github.com/samuel/go-zookeeper v0.0.0-20180130194729-c4fab1ac1bec // indirect + github.com/shirou/gopsutil v2.18.12+incompatible // indirect + github.com/shirou/w32 v0.0.0-20160930032740-bb4de0191aa4 // indirect + github.com/soheilhy/cmux v0.1.4 // indirect + github.com/streadway/amqp v0.0.0-20190312223743-14f78b41ce6d // indirect + github.com/tmc/grpc-websocket-proxy v0.0.0-20190109142713-0ad062ec5ee5 // indirect + github.com/ugorji/go/codec v0.0.0-20190320090025-2dc34c0b8780 // indirect + github.com/xiang90/probing v0.0.0-20190116061207-43a291ad63a2 // indirect + golang.org/x/net v0.0.0-20190327214358-63eda1eb0650 + golang.org/x/time v0.0.0-20190308202827-9d24e82272b4 // indirect + google.golang.org/grpc v1.19.1 // indirect + gopkg.in/asn1-ber.v1 v1.0.0-20181015200546-f715ec2f112d // indirect + gopkg.in/gorethink/gorethink.v4 v4.1.0 // indirect + gopkg.in/ini.v1 v1.42.0 // indirect + gopkg.in/ory-am/dockertest.v2 v2.2.3 // indirect + layeh.com/radius v0.0.0-20190322222518-890bc1058917 // indirect ) diff --git a/go.sum b/go.sum index 62099832..6fa13c8c 100644 --- a/go.sum +++ b/go.sum @@ -1,56 +1,485 @@ +cloud.google.com/go v0.26.0 h1:e0WKqKTd5BnrG8aKH3J3h+QvEIQtSUcf2n5UZ5ZgLtQ= +cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= +cloud.google.com/go v0.31.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= +cloud.google.com/go v0.34.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= +cloud.google.com/go v0.36.0 h1:+aCSj7tOo2LODWVEuZDZeGCckdt6MlSF+X/rB3wUiS8= +cloud.google.com/go v0.36.0/go.mod h1:RUoy9p/M4ge0HzT8L+SDZ8jg+Q6fth0CiBuhFJpSV40= +dmitri.shuralyov.com/app/changes v0.0.0-20180602232624-0a106ad413e3/go.mod h1:Yl+fi1br7+Rr3LqpNJf1/uxUdtRUV+Tnj0o93V2B9MU= +dmitri.shuralyov.com/html/belt v0.0.0-20180602232347-f7d459c86be0/go.mod h1:JLBrvjyP0v+ecvNYvCpyZgu5/xkfAUhi6wJj28eUfSU= +dmitri.shuralyov.com/service/change v0.0.0-20181023043359-a85b471d5412/go.mod h1:a1inKt/atXimZ4Mv927x+r7UpyzRUf4emIoiiSC2TN4= +dmitri.shuralyov.com/state v0.0.0-20180228185332-28bcc343414c/go.mod h1:0PRwlb0D6DFvNNtx+9ybjezNCa8XF0xaYcETyp6rHWU= +git.apache.org/thrift.git v0.0.0-20180902110319-2566ecd5d999/go.mod h1:fPE2ZNJGynbRyZ4dJvy6G277gSllfV2HJqblrnkyeyg= +git.apache.org/thrift.git v0.12.0/go.mod h1:fPE2ZNJGynbRyZ4dJvy6G277gSllfV2HJqblrnkyeyg= +github.com/Azure/azure-sdk-for-go v16.0.0+incompatible h1:gr1qKY/Ll72VjFTZmaBwRK1yQHAxCnV25ekOKroc9ws= +github.com/Azure/azure-sdk-for-go v16.0.0+incompatible/go.mod h1:9XXNKU+eRnpl9moKnB4QOLf1HestfXbmab5FXxiDBjc= +github.com/Azure/go-ansiterm v0.0.0-20170929234023-d6e3b3328b78 h1:w+iIsaOQNcT7OZ575w+acHgRric5iCyQh+xv+KJ4HB8= +github.com/Azure/go-ansiterm v0.0.0-20170929234023-d6e3b3328b78/go.mod h1:LmzpDX56iTiv29bbRTIsUNlaFfuhWRQBWjQdVyAevI8= +github.com/Azure/go-autorest v10.7.0+incompatible h1:dB+dKSLGdJLEhU/FoZTSNSPMZuE5H4M5p5zgSct7qwM= +github.com/Azure/go-autorest v10.7.0+incompatible/go.mod h1:r+4oMnoxhatjLLJ6zxSWATqVooLgysK6ZNox3g/xq24= +github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= +github.com/DataDog/datadog-go v0.0.0-20180822151419-281ae9f2d895/go.mod h1:LButxg5PwREeZtORoXG3tL4fMGNddJ+vMq1mwgfaqoQ= +github.com/DataDog/datadog-go v0.0.0-20190323183505-07c7c350327b h1:s9I3AGSgN6M/40RePnvZnpDvHVvdpovl/TitcxZ6ExQ= +github.com/DataDog/datadog-go v0.0.0-20190323183505-07c7c350327b/go.mod h1:LButxg5PwREeZtORoXG3tL4fMGNddJ+vMq1mwgfaqoQ= +github.com/Jeffail/gabs v1.1.1 h1:V0uzR08Hj22EX8+8QMhyI9sX2hwRu+/RJhJUmnwda/E= +github.com/Jeffail/gabs v1.1.1/go.mod h1:6xMvQMK4k33lb7GUUpaAPh6nKMmemQeg5d4gn7/bOXc= +github.com/Masterminds/semver v1.4.2/go.mod h1:MB6lktGJrhw8PrUyiEoblNEGEQ+RzHPF078ddwwvV3Y= +github.com/Masterminds/sprig v2.16.0+incompatible/go.mod h1:y6hNFY5UBTIWBxnzTeuNhlNS5hqE0NB0E6fgfo2Br3o= +github.com/Microsoft/go-winio v0.4.11/go.mod h1:VhR8bwka0BXejwEJY73c50VrPtXAaKcyvVC4A4RozmA= +github.com/Microsoft/go-winio v0.4.12 h1:xAfWHN1IrQ0NJ9TBC0KBZoqLjzDTr1ML+4MywiUOryc= +github.com/Microsoft/go-winio v0.4.12/go.mod h1:VhR8bwka0BXejwEJY73c50VrPtXAaKcyvVC4A4RozmA= +github.com/NYTimes/gziphandler v1.0.1/go.mod h1:3wb06e3pkSAbeQ52E9H9iFoQsEEwGN64994WTCIhntQ= +github.com/NYTimes/gziphandler v1.1.1 h1:ZUDjpQae29j0ryrS0u/B8HZfJBtBQHjqw2rQ2cqUQ3I= +github.com/NYTimes/gziphandler v1.1.1/go.mod h1:n/CVRwUEOgIxrgPvAQhUUr9oeUtvrhMomdKFjzJNB0c= +github.com/Nvveen/Gotty v0.0.0-20120604004816-cd527374f1e5 h1:TngWCqHvy9oXAN6lEVMRuU21PR1EtLVZJmdB18Gu3Rw= +github.com/Nvveen/Gotty v0.0.0-20120604004816-cd527374f1e5/go.mod h1:lmUJ/7eu/Q8D7ML55dXQrVaamCz2vxCfdQBasLZfHKk= +github.com/OneOfOne/xxhash v1.2.2/go.mod h1:HSdplMjZKSmBqAxg5vPj2TmRDmfkzw+cTzAElWljhcU= +github.com/RoaringBitmap/roaring v0.4.16/go.mod h1:8khRDP4HmeXns4xIj9oGrKSz7XTQiJx2zgh7AcNke4w= +github.com/SAP/go-hdb v0.13.1/go.mod h1:etBT+FAi1t5k3K3tf5vQTnosgYmhDkRi8jEnQqCnxF0= +github.com/SAP/go-hdb v0.14.1 h1:hkw4ozGZ/i4eak7ZuGkY5e0hxiXFdNUBNhr4AvZVNFE= +github.com/SAP/go-hdb v0.14.1/go.mod h1:7fdQLVC2lER3urZLjZCm0AuMQfApof92n3aylBPEkMo= +github.com/SermoDigital/jose v0.9.1 h1:atYaHPD3lPICcbK1owly3aPm0iaJGSGPi0WD4vLznv8= +github.com/SermoDigital/jose v0.9.1/go.mod h1:ARgCUhI1MHQH+ONky/PAtmVHQrP5JlGY0F3poXOp/fA= +github.com/Shopify/sarama v1.19.0/go.mod h1:FVkBWblsNy7DGZRfXLU0O9RCGt5g3g3yEuWXgklEdEo= +github.com/Shopify/toxiproxy v2.1.4+incompatible/go.mod h1:OXgGpZ6Cli1/URJOF1DMxUHB2q5Ap20/P/eIdh4G0pI= +github.com/Sirupsen/logrus v1.0.6 h1:HCAGQRk48dRVPA5Y+Yh0qdCSTzPOyU1tBJ7Q9YzotII= +github.com/Sirupsen/logrus v1.0.6/go.mod h1:rmk17hk6i8ZSAJkSDa7nOxamrG+SP4P0mm+DAvExv4U= +github.com/StackExchange/wmi v0.0.0-20181212234831-e0a55b97c705 h1:UUppSQnhf4Yc6xGxSkoQpPhb7RVzuv5Nb1mwJ5VId9s= +github.com/StackExchange/wmi v0.0.0-20181212234831-e0a55b97c705/go.mod h1:3eOhrUMpNV+6aFIbp5/iudMxNCF27Vw2OZgy4xEx0Fg= +github.com/abdullin/seq v0.0.0-20160510034733-d5467c17e7af h1:DBNMBMuMiWYu0b+8KMJuWmfCkcxl09JwdlqwDZZ6U14= +github.com/abdullin/seq v0.0.0-20160510034733-d5467c17e7af/go.mod h1:5Jv4cbFiHJMsVxt52+i0Ha45fjshj6wxYr1r19tB9bw= +github.com/alcortesm/tgz v0.0.0-20161220082320-9c5fe88206d7/go.mod h1:6zEj6s6u/ghQa61ZWa/C2Aw3RkjiTBOix7dkqa1VLIs= +github.com/alecthomas/kingpin v2.2.6+incompatible/go.mod h1:59OFYbFVLKQKq+mqrL6Rw5bR0c3ACQaawgXx0QYndlE= +github.com/alecthomas/template v0.0.0-20160405071501-a0175ee3bccc/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc= +github.com/alecthomas/units v0.0.0-20151022065526-2efee857e7cf/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0= +github.com/aliyun/alibaba-cloud-sdk-go v0.0.0-20190328075325-5887fb5d0027 h1:fRCXvr84WHoAnmRZa2GDzBfxH+8B+4j7ewXCUVHRGKk= +github.com/aliyun/alibaba-cloud-sdk-go v0.0.0-20190328075325-5887fb5d0027/go.mod h1:T9M45xf79ahXVelWoOBmH0y4aC1t5kXO5BxwyakgIGA= +github.com/andreyvit/diff v0.0.0-20170406064948-c7f18ee00883/go.mod h1:rCTlJbsFo29Kk6CurOXKm700vrz8f0KW0JNfpkRJY/8= +github.com/anmitsu/go-shlex v0.0.0-20161002113705-648efa622239/go.mod h1:2FmKhYUyUczH0OGQWaF5ceTx0UBShxjsH6f8oGKYe2c= +github.com/aokoli/goutils v1.0.1/go.mod h1:SijmP0QR8LtwsmDs8Yii5Z/S4trXFGFC2oO5g9DP+DQ= +github.com/apache/arrow/go/arrow v0.0.0-20181031164735-a56c009257a7/go.mod h1:GjvccvtI06FGFvRU1In/maF7tKp3h7GBV9Sexo5rNPM= +github.com/apache/arrow/go/arrow v0.0.0-20181217213538-e9ed591db9cb/go.mod h1:GjvccvtI06FGFvRU1In/maF7tKp3h7GBV9Sexo5rNPM= +github.com/apache/thrift v0.12.0/go.mod h1:cp2SuWMxlEZw2r+iP2GNCdIi4C1qmUzdZFSVb+bacwQ= +github.com/apex/log v1.1.0/go.mod h1:yA770aXIDQrhVOIGurT/pVdfCpSq1GQV/auzMN5fzvY= +github.com/araddon/gou v0.0.0-20190110011759-c797efecbb61 h1:Xz25cuW4REGC5W5UtpMU3QItMIImag615HiQcRbxqKQ= +github.com/araddon/gou v0.0.0-20190110011759-c797efecbb61/go.mod h1:ikc1XA58M+Rx7SEbf0bLJCfBkwayZ8T5jBo5FXK8Uz8= github.com/armon/circbuf v0.0.0-20150827004946-bbbad097214e/go.mod h1:3U/XgcO3hCbHZ8TKRvWD2dDTCfh9M9ya+I9JpbB7O8o= +github.com/armon/circbuf v0.0.0-20190214190532-5111143e8da2 h1:7Ip0wMmLHLRJdrloDxZfhMm0xrLXZS8+COSu2bXmEQs= github.com/armon/circbuf v0.0.0-20190214190532-5111143e8da2/go.mod h1:3U/XgcO3hCbHZ8TKRvWD2dDTCfh9M9ya+I9JpbB7O8o= github.com/armon/go-metrics v0.0.0-20180917152333-f0300d1749da h1:8GUt8eRujhVEGZFFEjBj46YV4rDjvGrNxb0KMWYkL2I= github.com/armon/go-metrics v0.0.0-20180917152333-f0300d1749da/go.mod h1:Q73ZrmVTwzkszR9V5SSuryQ31EELlFMUz1kKyl939pY= github.com/armon/go-radix v0.0.0-20180808171621-7fddfc383310/go.mod h1:ufUuZ+zHj4x4TnLV4JWEpy2hxWSpsRywHrMgIH9cCH8= +github.com/armon/go-radix v1.0.0 h1:F4z6KzEeeQIMeLFa97iZU6vupzoecKdU5TX24SNppXI= github.com/armon/go-radix v1.0.0/go.mod h1:ufUuZ+zHj4x4TnLV4JWEpy2hxWSpsRywHrMgIH9cCH8= +github.com/asaskevich/govalidator v0.0.0-20180720115003-f9ffefc3facf h1:eg0MeVzsP1G42dRafH3vf+al2vQIJU0YHX+1Tw87oco= +github.com/asaskevich/govalidator v0.0.0-20180720115003-f9ffefc3facf/go.mod h1:lB+ZfQJz7igIIfQNfa7Ml4HSf2uFQQRzpGGRXenZAgY= +github.com/aws/aws-sdk-go v1.15.24 h1:xLAdTA/ore6xdPAljzZRed7IGqQgC+nY+ERS5vaj4Ro= +github.com/aws/aws-sdk-go v1.15.24/go.mod h1:mFuSZ37Z9YOHbQEwBWztmVzqXrEkub65tZoCYDt7FT0= +github.com/aws/aws-sdk-go v1.15.59/go.mod h1:E3/ieXAlvM0XWO57iftYVDLLvQ824smPP3ATZkfNZeM= +github.com/aws/aws-sdk-go v1.15.64/go.mod h1:E3/ieXAlvM0XWO57iftYVDLLvQ824smPP3ATZkfNZeM= +github.com/aws/aws-sdk-go v1.17.5 h1:WW9Hm3KYo48iZHpmBc+b7sgyS0h32zgCvya28SLW4BU= +github.com/aws/aws-sdk-go v1.17.5/go.mod h1:KmX6BPdI08NWTb3/sm4ZGu5ShLoqVDhKgpiN924inxo= +github.com/benbjohnson/tmpl v1.0.0/go.mod h1:igT620JFIi44B6awvU9IsDhR77IXWtFigTLil/RPdps= +github.com/beorn7/perks v0.0.0-20180321164747-3a771d992973 h1:xJ4a3vCFaGF/jqvzLMYoU8P317H5OQ+Via4RmuPwCS0= +github.com/beorn7/perks v0.0.0-20180321164747-3a771d992973/go.mod h1:Dwedo/Wpr24TaqPxmxbtue+5NUziq4I4S80YR8gNf3Q= +github.com/bgentry/speakeasy v0.1.0 h1:ByYyxL9InA1OWqxJqqp2A5pYHUrCiAL6K3J+LKSsQkY= github.com/bgentry/speakeasy v0.1.0/go.mod h1:+zsyZBPWlz7T6j88CTgSN5bM796AkVf0kBD4zp0CCIs= +github.com/bitly/go-hostpool v0.0.0-20171023180738-a3a6125de932 h1:mXoPYz/Ul5HYEDvkta6I8/rnYM5gSdSV2tJ6XbZuEtY= +github.com/bitly/go-hostpool v0.0.0-20171023180738-a3a6125de932/go.mod h1:NOuUCSz6Q9T7+igc/hlvDOUdtWKryOrtFyIVABv/p7k= +github.com/blakesmith/ar v0.0.0-20150311145944-8bd4349a67f2/go.mod h1:PkYb9DJNAwrSvRx5DYA+gUcOIgTGVMNkfSCbZM8cWpI= +github.com/bmizerany/assert v0.0.0-20160611221934-b7ed37b82869 h1:DDGfHa7BWjL4YnC6+E63dPcxHo2sUxDIu8g3QgEJdRY= +github.com/bmizerany/assert v0.0.0-20160611221934-b7ed37b82869/go.mod h1:Ekp36dRnpXw/yCqJaO+ZrUyxD+3VXMFFr56k5XYrpB4= +github.com/boltdb/bolt v1.3.1 h1:JQmyP4ZBrce+ZQu0dY660FMfatumYDLun9hBCUVIkF4= +github.com/boltdb/bolt v1.3.1/go.mod h1:clJnj/oiGkjum5o1McbSZDSLxVThjynRyGBgiAx27Ps= +github.com/boombuler/barcode v1.0.0 h1:s1TvRnXwL2xJRaccrdcBQMZxq6X7DvsMogtmJeHDdrc= +github.com/boombuler/barcode v1.0.0/go.mod h1:paBWMcWSl3LHKBqUq+rly7CNSldXjb2rDl3JlRe0mD8= +github.com/bouk/httprouter v0.0.0-20160817010721-ee8b3818a7f5/go.mod h1:CDReaxg1cmLrtcasZy43l4EYPAknXLiQSrb7tLw5zXM= +github.com/bradfitz/go-smtpd v0.0.0-20170404230938-deb6d6237625/go.mod h1:HYsPBTaaSFSlLx/70C2HPIMNZpVV8+vt/A+FMnYP11g= +github.com/briankassouf/jose v0.9.1 h1:HMeR+qpz2PBP7RgR+64nJPA9qcZI74tdkBv5NyD0Mzk= +github.com/briankassouf/jose v0.9.1/go.mod h1:HQhVmdUf7dBNwIIdBTivnCDxcf6IZY3/zrb+uKSJz6Y= +github.com/c-bata/go-prompt v0.2.2/go.mod h1:VzqtzE2ksDBcdln8G7mk2RX9QyGjH+OVqOCSiVIqS34= +github.com/caarlos0/ctrlc v1.0.0/go.mod h1:CdXpj4rmq0q/1Eb44M9zi2nKB0QraNKuRGYGrrHhcQw= +github.com/campoy/unique v0.0.0-20180121183637-88950e537e7e/go.mod h1:9IOqJGCPMSc6E5ydlp5NIonxObaeu/Iub/X03EKPVYo= +github.com/cenkalti/backoff v2.0.0+incompatible/go.mod h1:90ReRw6GdpyfrHakVjL/QHaoyV4aDUVVkXQJJJ3NXXM= +github.com/cenkalti/backoff v2.1.1+incompatible h1:tKJnvO2kl0zmb/jA5UKAt4VoEVw1qxKWjE/Bpp46npY= +github.com/cenkalti/backoff v2.1.1+incompatible/go.mod h1:90ReRw6GdpyfrHakVjL/QHaoyV4aDUVVkXQJJJ3NXXM= +github.com/centrify/cloud-golang-sdk v0.0.0-20190214225812-119110094d0f h1:gJzxrodnNd/CtPXjO3WYiakyNzHg3rtAi7rO74ejHYU= +github.com/centrify/cloud-golang-sdk v0.0.0-20190214225812-119110094d0f/go.mod h1:C0rtzmGXgN78pYR0tGJFhtHgkbAs0lIbHwkB81VxDQE= +github.com/cespare/xxhash v1.1.0/go.mod h1:XrSqR1VqqWfGrhpAt58auRo0WTKS1nRRg3ghfAqPWnc= +github.com/chrismalek/oktasdk-go v0.0.0-20181212195951-3430665dfaa0 h1:CWU8piLyqoi9qXEUwzOh5KFKGgmSU5ZhktJyYcq6ryQ= +github.com/chrismalek/oktasdk-go v0.0.0-20181212195951-3430665dfaa0/go.mod h1:5d8DqS60xkj9k3aXfL3+mXBH0DPYO0FQjcKosxl+b/Q= +github.com/circonus-labs/circonus-gometrics v2.2.5+incompatible/go.mod h1:nmEj6Dob7S7YxXgwXpfOuvO54S+tGdZdw9fuRZt25Ag= +github.com/circonus-labs/circonus-gometrics v2.2.6+incompatible h1:NoaznmtBvXxBwKGS+lQBGJSNqJQAtCTPE5ekztSSQfs= +github.com/circonus-labs/circonus-gometrics v2.2.6+incompatible/go.mod h1:nmEj6Dob7S7YxXgwXpfOuvO54S+tGdZdw9fuRZt25Ag= +github.com/circonus-labs/circonusllhist v0.1.3 h1:TJH+oke8D16535+jHExHj4nQvzlZrj7ug5D7I/orNUA= +github.com/circonus-labs/circonusllhist v0.1.3/go.mod h1:kMXHVDlOchFAehlya5ePtbp5jckzBHf4XRpQvBOLI+I= +github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw= +github.com/containerd/continuity v0.0.0-20181027224239-bea7585dbfac/go.mod h1:GL3xCUCBDV3CZiTSEKksMWbLE66hEyuu9qyDOOqM47Y= +github.com/containerd/continuity v0.0.0-20181203112020-004b46473808 h1:4BX8f882bXEDKfWIf0wa8HRvpnBoPszJJXL+TVbBw4M= +github.com/containerd/continuity v0.0.0-20181203112020-004b46473808/go.mod h1:GL3xCUCBDV3CZiTSEKksMWbLE66hEyuu9qyDOOqM47Y= +github.com/coredns/coredns v1.4.0 h1:RubBkYmkByUqZWWkjRHvNLnUHgkRVqAWgSMmRFvpE1A= +github.com/coredns/coredns v1.4.0/go.mod h1:zASH/MVDgR6XZTbxvOnsZfffS+31vg6Ackf/wo1+AM0= +github.com/coreos/bbolt v1.3.1-coreos.6 h1:uTXKg9gY70s9jMAKdfljFQcuh4e/BXOM+V+d00KFj3A= +github.com/coreos/bbolt v1.3.1-coreos.6/go.mod h1:iRUV2dpdMOn7Bo10OQBFzIJO9kkE559Wcmn+qkEiiKk= +github.com/coreos/etcd v3.3.12+incompatible h1:pAWNwdf7QiT1zfaWyqCtNZQWCLByQyA3JrSQyuYAqnQ= +github.com/coreos/etcd v3.3.12+incompatible/go.mod h1:uF7uidLiAD3TWHmW31ZFd/JWoc32PjwdhPthX9715RE= +github.com/coreos/go-oidc v2.0.0+incompatible h1:+RStIopZ8wooMx+Vs5Bt8zMXxV1ABl5LbakNExNmZIg= +github.com/coreos/go-oidc v2.0.0+incompatible/go.mod h1:CgnwVTmzoESiwO9qyAFEMiHoZ1nMCKZlZ9V6mm3/LKc= +github.com/coreos/go-semver v0.2.0 h1:3Jm3tLmsgAYcjC+4Up7hJrFBPr+n7rAqYeSw/SZazuY= +github.com/coreos/go-semver v0.2.0/go.mod h1:nnelYz7RCh+5ahJtPPxZlU+153eP4D4r3EedlOD2RNk= +github.com/coreos/go-systemd v0.0.0-20181012123002-c6f51f82210d h1:t5Wuyh53qYyg9eqn4BbnlIT+vmhyww0TatL+zT3uWgI= +github.com/coreos/go-systemd v0.0.0-20181012123002-c6f51f82210d/go.mod h1:F5haX7vjVVG0kc13fIWeqUViNPyEJxv/OmvnBo0Yme4= +github.com/coreos/pkg v0.0.0-20180928190104-399ea9e2e55f h1:lBNOc5arjvs8E5mO2tbpBpLoyyu8B6e44T7hJy6potg= +github.com/coreos/pkg v0.0.0-20180928190104-399ea9e2e55f/go.mod h1:E3G3o1h8I7cfcXa63jLwjI0eiQQMgzzUDFVpN/nH/eA= +github.com/dancannon/gorethink v4.0.0+incompatible h1:KFV7Gha3AuqT+gr0B/eKvGhbjmUv0qGF43aKCIKVE9A= +github.com/dancannon/gorethink v4.0.0+incompatible/go.mod h1:BLvkat9KmZc1efyYwhz3WnybhRZtgF1K929FD8z1avU= github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/denisenkom/go-mssqldb v0.0.0-20181014144952-4e0d7dc8888f/go.mod h1:xN/JuLBIz4bjkxNmByTiV1IbhfnYb6oo99phBn4Eqhc= +github.com/denisenkom/go-mssqldb v0.0.0-20190328043727-2183450503ad h1:pU720selZEfSLwzto57D7pucjcjMsrGRKq5xFjyruj8= +github.com/denisenkom/go-mssqldb v0.0.0-20190328043727-2183450503ad/go.mod h1:xN/JuLBIz4bjkxNmByTiV1IbhfnYb6oo99phBn4Eqhc= +github.com/denverdino/aliyungo v0.0.0-20170926055100-d3308649c661 h1:lrWnAyy/F72MbxIxFUzKmcMCdt9Oi8RzpAxzTNQHD7o= +github.com/denverdino/aliyungo v0.0.0-20170926055100-d3308649c661/go.mod h1:dV8lFg6daOBZbT6/BDGIz6Y3WFGn8juu6G+CQ6LHtl0= +github.com/dgrijalva/jwt-go v3.2.0+incompatible h1:7qlOGliEKZXTDg6OTjfoBKDXWrumCAMpl/TFQ4/5kLM= +github.com/dgrijalva/jwt-go v3.2.0+incompatible/go.mod h1:E3ru+11k8xSBh+hMPgOLZmtrrCbhqsmaPHjLKYnJCaQ= +github.com/dgryski/go-bitstream v0.0.0-20180413035011-3522498ce2c8/go.mod h1:VMaSuZ+SZcx/wljOQKvp5srsbCiKDEb6K2wC4+PiBmQ= +github.com/digitalocean/godo v1.1.1 h1:v0A7yF3xmKLjjdJGIeBbINfMufcrrRhqZsxuVQMoT+U= +github.com/digitalocean/godo v1.1.1/go.mod h1:h6faOIcZ8lWIwNQ+DN7b3CgX4Kwby5T+nbpNqkUIozU= +github.com/dimchansky/utfbom v1.1.0 h1:FcM3g+nofKgUteL8dm/UpdRXNC9KmADgTpLKsu0TRo4= +github.com/dimchansky/utfbom v1.1.0/go.mod h1:rO41eb7gLfo8SF1jd9F8HplJm1Fewwi4mQvIirEdv+8= +github.com/docker/distribution v2.6.2+incompatible/go.mod h1:J2gT2udsDAN96Uj4KfcMRqY0/ypR+oyYUYmja8H+y+w= +github.com/docker/docker v0.0.0-20180422163414-57142e89befe/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk= +github.com/docker/go-connections v0.4.0 h1:El9xVISelRB7BuFusrZozjnkIM5YnzCViNKohAFqRJQ= +github.com/docker/go-connections v0.4.0/go.mod h1:Gbd7IOopHjR8Iph03tsViu4nIes5XhDvyHbTtUxmeec= +github.com/docker/go-units v0.3.3 h1:Xk8S3Xj5sLGlG5g67hJmYMmUgXv5N4PhkjJHHqrwnTk= +github.com/docker/go-units v0.3.3/go.mod h1:fgPhTUdO+D/Jk86RDLlptpiXQzgHJF7gydDDbaIK4Dk= +github.com/duosecurity/duo_api_golang v0.0.0-20181024123116-92fea9203dbc/go.mod h1:UqXY1lYT/ERa4OEAywUqdok1T4RCRdArkhic1Opuavo= +github.com/duosecurity/duo_api_golang v0.0.0-20190308151101-6c680f768e74 h1:2MIhn2R6oXQbgW5yHfS+d6YqyMfXiu2L55rFZC4UD/M= +github.com/duosecurity/duo_api_golang v0.0.0-20190308151101-6c680f768e74/go.mod h1:UqXY1lYT/ERa4OEAywUqdok1T4RCRdArkhic1Opuavo= +github.com/dustin/go-humanize v1.0.0/go.mod h1:HtrtbFcZ19U5GC7JDqmcUSB87Iq5E25KnS6fMYU6eOk= +github.com/eapache/go-resiliency v1.1.0/go.mod h1:kFI+JgMyC7bLPUVY133qvEBtVayf5mFgVsvEsIPBvNs= +github.com/eapache/go-xerial-snappy v0.0.0-20180814174437-776d5712da21/go.mod h1:+020luEh2TKB4/GOp8oxxtq0Daoen/Cii55CzbTV6DU= +github.com/eapache/queue v1.1.0/go.mod h1:6eCeP0CKFpHLu8blIFXhExK/dRa7WDZfr6jVFPTqq+I= +github.com/elazarl/go-bindata-assetfs v1.0.0 h1:G/bYguwHIzWq9ZoyUQqrjTmJbbYn3j3CKKpKinvZLFk= +github.com/elazarl/go-bindata-assetfs v1.0.0/go.mod h1:v+YaWX3bdea5J/mo8dSETolEo7R71Vk1u8bnjau5yw4= +github.com/emirpasic/gods v1.9.0/go.mod h1:YfzfFFoVP/catgzJb4IKIqXjX78Ha8FMSDh3ymbK86o= +github.com/envoyproxy/go-control-plane v0.6.9 h1:deEH9W8ZAUGNbCdX+9iNzBOGrAOrnpJGoy0PcTqk/tE= +github.com/envoyproxy/go-control-plane v0.6.9/go.mod h1:SBwIajubJHhxtWwsL9s8ss4safvEdbitLhGGK48rN6g= +github.com/fatih/color v1.7.0 h1:DkWD4oS2D8LGGgTQ6IvwJJXSL5Vp2ffcQg58nFV38Ys= github.com/fatih/color v1.7.0/go.mod h1:Zm6kSWBoL9eyXnKyktHP6abPY2pDugNf5KwzbycvMj4= +github.com/fatih/structs v1.1.0 h1:Q7juDM0QtcnhCpeyLGQKyg4TOIghuNXrkL32pHAUMxo= +github.com/fatih/structs v1.1.0/go.mod h1:9NiDSp5zOcgEDl+j00MP/WkGVPOlPRLejGD8Ga6PJ7M= +github.com/flynn/go-shlex v0.0.0-20150515145356-3f9db97f8568/go.mod h1:xEzjJPgXI435gkrCt3MPfRiAkVrwSbHsst4LCFVfpJc= +github.com/fsnotify/fsnotify v1.4.7 h1:IXs+QLmnXW2CcXuY+8Mzv/fWEsPGWxqefPtCP5CnV9I= +github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo= +github.com/fullsailor/pkcs7 v0.0.0-20180613152042-8306686428a5 h1:v+vxrd9XS8uWIXG2RK0BHCnXc30qLVQXVqbK+IOmpXk= +github.com/fullsailor/pkcs7 v0.0.0-20180613152042-8306686428a5/go.mod h1:KnogPXtdwXqoenmZCw6S+25EAm2MkxbG0deNDu4cbSA= +github.com/gammazero/deque v0.0.0-20190130191400-2afb3858e9c7 h1:D2LrfOPgGHQprIxmsTpxtzhpmF66HoM6rXSmcqaX7h8= +github.com/gammazero/deque v0.0.0-20190130191400-2afb3858e9c7/go.mod h1:GeIq9qoE43YdGnDXURnmKTnGg15pQz4mYkXSTChbneI= +github.com/gammazero/workerpool v0.0.0-20181230203049-86a96b5d5d92 h1:EipXK6U05IQ2wtuFRn4k3h0+2lXypzItoXGVyf4r9Io= +github.com/gammazero/workerpool v0.0.0-20181230203049-86a96b5d5d92/go.mod h1:w9RqFVO2BM3xwWEcAB8Fwp0OviTBBEiRmSBDfbXnd3w= +github.com/garyburd/redigo v1.6.0 h1:0VruCpn7yAIIu7pWVClQC8wxCJEcG3nyzpMSHKi1PQc= +github.com/garyburd/redigo v1.6.0/go.mod h1:NR3MbYisc3/PwhQ00EMzDiPmrwpPxAn5GI05/YaO1SY= +github.com/getkin/kin-openapi v0.1.0/go.mod h1:+0ZtELZf+SlWH8ZdA/IeFb3L/PKOKJx8eGxAlUZ/sOU= +github.com/ghodss/yaml v1.0.0 h1:wQHKEahhL6wmXdzwWG11gIVCkOv05bNOh+Rxn0yngAk= +github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04= +github.com/gliderlabs/ssh v0.1.1/go.mod h1:U7qILu1NlMHj9FlMhZLlkCdDnU1DBEAqr0aevW3Awn0= +github.com/glycerine/go-unsnap-stream v0.0.0-20180323001048-9f0cb55181dd/go.mod h1:/20jfyN9Y5QPEAprSgKAUr+glWDY39ZiUEAYOEv5dsE= +github.com/glycerine/goconvey v0.0.0-20180728074245-46e3a41ad493/go.mod h1:Ogl1Tioa0aV7gstGFO7KhffUsb9M4ydbEbbxpcEDc24= +github.com/go-errors/errors v1.0.1 h1:LUHzmkK3GUKUrL/1gfBUxAHzcev3apQlezX/+O7ma6w= +github.com/go-errors/errors v1.0.1/go.mod h1:f4zRHt4oKfwPJE5k8C9vpYG+aDHdBFUsgrm6/TyX73Q= +github.com/go-ini/ini v1.25.4 h1:Mujh4R/dH6YL8bxuISne3xX2+qcQ9p0IxKAP6ExWoUo= +github.com/go-ini/ini v1.25.4/go.mod h1:ByCAeIL28uOIIG0E3PJtZPDL8WnHpFKFOtgjp+3Ies8= +github.com/go-kit/kit v0.8.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as= +github.com/go-ldap/ldap v2.5.1+incompatible/go.mod h1:qfd9rJvER9Q0/D/Sqn1DfHRoBp40uXYvFoEVrNEPqRc= +github.com/go-ldap/ldap v3.0.2+incompatible h1:kD5HQcAzlQ7yrhfn+h+MSABeAy/jAJhvIJ/QDllP44g= +github.com/go-ldap/ldap v3.0.2+incompatible/go.mod h1:qfd9rJvER9Q0/D/Sqn1DfHRoBp40uXYvFoEVrNEPqRc= github.com/go-log/log v0.1.0 h1:wudGTNsiGzrD5ZjgIkVZ517ugi2XRe9Q/xRCzwEO4/U= github.com/go-log/log v0.1.0/go.mod h1:4mBwpdRMFLiuXZDCwU2lKQFsoSCo72j3HqBK9d81N2M= +github.com/go-logfmt/logfmt v0.3.0/go.mod h1:Qt1PoO58o5twSAckw1HlFXLmHsOX5/0LbT9GBnD5lWE= +github.com/go-ole/go-ole v1.2.4 h1:nNBDSCOigTSiarFpYE9J/KtEA1IOW4CNeqT9TQDqCxI= +github.com/go-ole/go-ole v1.2.4/go.mod h1:XCwSNxSkXRo4vlyPy93sltvi/qJq0jqQhjqQNIwKuxM= +github.com/go-sql-driver/mysql v1.4.0/go.mod h1:zAC/RDZ24gD3HViQzih4MyKcchzm+sOG5ZlKdlhCg5w= +github.com/go-sql-driver/mysql v1.4.1 h1:g24URVg0OFbNUTx9qqY1IRZ9D9z3iPyi5zKhQZpNwpA= +github.com/go-sql-driver/mysql v1.4.1/go.mod h1:zAC/RDZ24gD3HViQzih4MyKcchzm+sOG5ZlKdlhCg5w= +github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY= +github.com/go-stomp/stomp v2.0.2+incompatible h1:0yPknMJh32lE2xiCFGW5t/KgamhUC4OgCv10wIjx5aw= +github.com/go-stomp/stomp v2.0.2+incompatible/go.mod h1:VqCtqNZv1226A1/79yh+rMiFUcfY3R109np+7ke4n0c= +github.com/go-test/deep v1.0.1 h1:UQhStjbkDClarlmv0am7OXXO4/GaPdCGiUiMTvi28sg= +github.com/go-test/deep v1.0.1/go.mod h1:wGDj63lr65AM2AQyKZd/NYHGb0R+1RLqB8NKt3aSFNA= +github.com/gocql/gocql v0.0.0-20181117210152-33c0e89ca93a/go.mod h1:4Fw1eo5iaEhDUs8XyuhSVCVy52Jq3L+/3GJgYkwc+/0= +github.com/gocql/gocql v0.0.0-20190325140904-fc3925ac2cbd h1:yub0WC7grIFfQgGPDyfOdrqoFqfRbRiwKQXbSOOHjoQ= +github.com/gocql/gocql v0.0.0-20190325140904-fc3925ac2cbd/go.mod h1:4Fw1eo5iaEhDUs8XyuhSVCVy52Jq3L+/3GJgYkwc+/0= +github.com/gogo/googleapis v1.1.0 h1:kFkMAZBNAn4j7K0GiZr8cRYzejq68VbheufiV3YuyFI= +github.com/gogo/googleapis v1.1.0/go.mod h1:gf4bu3Q80BeJ6H1S1vYPm8/ELATdvryBaNFGgqEef3s= +github.com/gogo/protobuf v1.1.1/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ= +github.com/gogo/protobuf v1.2.0/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ= +github.com/gogo/protobuf v1.2.1 h1:/s5zKNz0uPFCZ5hddgPdo2TK2TVrUNMn0OOX8/aZMTE= +github.com/gogo/protobuf v1.2.1/go.mod h1:hp+jE20tsWTFYpLwKvXlhS1hjn+gTNwPg2I6zVXpSg4= +github.com/golang/gddo v0.0.0-20181116215533-9bd4a3295021/go.mod h1:xEhNfoBDX1hzLm2Nf80qUvZ2sVwoMZ8d6IE2SrsQfh4= +github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b h1:VKtxabqXZkF25pY9ekfRL6a582T4P37/31XEstQ5p58= +github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q= +github.com/golang/groupcache v0.0.0-20190129154638-5b532d6fd5ef h1:veQD95Isof8w9/WXiA+pa3tz3fJXkt5B7QaRBrM62gk= +github.com/golang/groupcache v0.0.0-20190129154638-5b532d6fd5ef/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= +github.com/golang/lint v0.0.0-20180702182130-06c8688daad7/go.mod h1:tluoj9z5200jBnyusfRPU2LqT6J+DAorxEvtC7LHB+E= +github.com/golang/mock v1.1.1/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A= +github.com/golang/mock v1.2.0/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A= github.com/golang/protobuf v1.2.0 h1:P3YflyNX/ehuJFLhxviNdFxQPkGK5cDcApsge1SqnvM= github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= +github.com/golang/protobuf v1.3.1 h1:YF8+flBXS5eO826T4nzqPrxfhQThhXl0YzfuUPu4SBg= +github.com/golang/protobuf v1.3.1/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= +github.com/golang/snappy v0.0.0-20170215233205-553a64147049/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= +github.com/golang/snappy v0.0.0-20180518054509-2e65f85255db/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= +github.com/golang/snappy v0.0.1 h1:Qgr9rKW7uDUkrbSmQeiDsGa8SjGyCOGtuasMWwvp2P4= +github.com/golang/snappy v0.0.1/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= github.com/google/btree v0.0.0-20180813153112-4030bb1f1f0c h1:964Od4U6p2jUkFxvCydnIczKteheJEzHRToSGK3Bnlw= github.com/google/btree v0.0.0-20180813153112-4030bb1f1f0c/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ= +github.com/google/btree v1.0.0 h1:0udJVsspx3VBr5FwtLhQQtuAsVc79tTq0ocGIPAU6qo= +github.com/google/btree v1.0.0/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ= +github.com/google/go-cmp v0.2.0 h1:+dTQ8DZQJz0Mb/HjFlkptS1FeQ4cWSnN941F8aEG4SQ= +github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M= +github.com/google/go-github v17.0.0+incompatible h1:N0LgJ1j65A7kfXrZnUDaYCs/Sf4rEjNlfyDHW9dolSY= +github.com/google/go-github v17.0.0+incompatible/go.mod h1:zLgOLi98H3fifZn+44m+umXrS52loVEgC2AApnigrVQ= +github.com/google/go-querystring v0.0.0-20170111101155-53e6ce116135 h1:zLTLjkaOFEFIOxY5BWLFLwh+cL8vOBW4XJ2aqLE/Tf0= +github.com/google/go-querystring v0.0.0-20170111101155-53e6ce116135/go.mod h1:odCYkC5MyYFN7vkCjXpyrEuKhc/BUO6wN/zVPAxq5ck= +github.com/google/go-querystring v1.0.0 h1:Xkwi/a1rcvNg1PPYe5vI8GbeBY/jrVuDX5ASuANWTrk= +github.com/google/go-querystring v1.0.0/go.mod h1:odCYkC5MyYFN7vkCjXpyrEuKhc/BUO6wN/zVPAxq5ck= +github.com/google/gofuzz v0.0.0-20170612174753-24818f796faf h1:+RRA9JqSOZFfKrOeqr2z77+8R2RKyh8PG66dcu1V0ck= +github.com/google/gofuzz v0.0.0-20170612174753-24818f796faf/go.mod h1:HP5RmnzzSNb993RKQDq4+1A4ia9nllfqcQFTQJedwGI= +github.com/google/martian v2.1.0+incompatible/go.mod h1:9I4somxYTbIHy5NJKHRl3wXiIaQGbYVAs8BPL6v8lEs= +github.com/google/pprof v0.0.0-20181206194817-3ea8567a2e57/go.mod h1:zfwlbNMJ+OItoe0UupaVj+oy1omPYYDuagoSzA8v9mc= +github.com/google/uuid v1.0.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/google/uuid v1.1.0 h1:Jf4mxPC/ziBnoPIdpQdPJ9OeiomAUHLvxmPRSPH9m4s= github.com/google/uuid v1.1.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= +github.com/google/uuid v1.1.1 h1:Gkbcsh/GbpXz7lPftLA3P6TYMwjCLYm83jiFQZF/3gY= +github.com/google/uuid v1.1.1/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= +github.com/googleapis/gax-go v2.0.0+incompatible h1:j0GKcs05QVmm7yesiZq2+9cxHkNK9YM6zKx4D2qucQU= +github.com/googleapis/gax-go v2.0.0+incompatible/go.mod h1:SFVmujtThgffbyetf+mdk2eWhX2bMyUtNHzFKcPA9HY= +github.com/googleapis/gax-go/v2 v2.0.3 h1:siORttZ36U2R/WjiJuDz8znElWBiAlO9rVt+mqJt0Cc= +github.com/googleapis/gax-go/v2 v2.0.3/go.mod h1:LLvjysVCY1JZeum8Z6l8qUty8fiNwE08qbEPm1M08qg= +github.com/googleapis/gnostic v0.2.0 h1:l6N3VoaVzTncYYW+9yOz2LJJammFZGBO13sqgEhpy9g= +github.com/googleapis/gnostic v0.2.0/go.mod h1:sJBsCZ4ayReDTBIg8b9dl28c5xFWyhBTVRp3pOg5EKY= +github.com/gophercloud/gophercloud v0.0.0-20180828235145-f29afc2cceca h1:wobTb8SE189AuxzEKClyYxiI4nUGWlpVtl13eLiFlOE= +github.com/gophercloud/gophercloud v0.0.0-20180828235145-f29afc2cceca/go.mod h1:3WdhXV3rUYy9p6AUW8d94kr+HS62Y4VL9mBnFxsD8q4= +github.com/gopherjs/gopherjs v0.0.0-20180825215210-0210a2f0f73c h1:16eHWuMGvCjSfgRJKqIzapE78onvvTbdi1rMkU00lZw= +github.com/gopherjs/gopherjs v0.0.0-20180825215210-0210a2f0f73c/go.mod h1:wJfORRmW1u3UXTncJ5qlYoELFm8eSnnEO6hX4iZ3EWY= +github.com/gopherjs/gopherjs v0.0.0-20181017120253-0766667cb4d1 h1:EGx4pi6eqNxGaHF6qqu48+N2wcFQ5qg5FXgOdqsJ5d8= +github.com/gopherjs/gopherjs v0.0.0-20181017120253-0766667cb4d1/go.mod h1:wJfORRmW1u3UXTncJ5qlYoELFm8eSnnEO6hX4iZ3EWY= +github.com/goreleaser/goreleaser v0.94.0/go.mod h1:OjbYR2NhOI6AEUWCowMSBzo9nP1aRif3sYtx+rhp+Zo= +github.com/goreleaser/nfpm v0.9.7/go.mod h1:F2yzin6cBAL9gb+mSiReuXdsfTrOQwDMsuSpULof+y4= +github.com/gorhill/cronexpr v0.0.0-20180427100037-88b0669f7d75 h1:f0n1xnMSmBLzVfsMMvriDyA75NB/oBgILX2GcHXIQzY= +github.com/gorhill/cronexpr v0.0.0-20180427100037-88b0669f7d75/go.mod h1:g2644b03hfBX9Ov0ZBDgXXens4rxSxmqFBbhvKv2yVA= +github.com/gorilla/context v1.1.1/go.mod h1:kBGZzfjB9CEq2AlWe17Uuf7NDRt0dE0s8S51q0aT7Yg= +github.com/gorilla/mux v1.6.2/go.mod h1:1lud6UwP+6orDFRuTfBEV8e9/aOM/c4fVVCaMa2zaAs= +github.com/gorilla/websocket v1.4.0 h1:WDFjx/TMzVgy9VdMMQi2K2Emtwi2QcUQsztZ/zLaH/Q= +github.com/gorilla/websocket v1.4.0/go.mod h1:E7qHFY5m1UJ88s3WnNqhKjPHQ0heANvMoAMk2YaljkQ= +github.com/gotestyourself/gotestyourself v2.2.0+incompatible h1:AQwinXlbQR2HvPjQZOmDhRqsv5mZf+Jb1RnSLxcqZcI= +github.com/gotestyourself/gotestyourself v2.2.0+incompatible/go.mod h1:zZKM6oeNM8k+FRljX1mnzVYeS8wiGgQyvST1/GafPbY= +github.com/gregjones/httpcache v0.0.0-20180305231024-9cad4c3443a7 h1:pdN6V1QBWetyv/0+wjACpqVH+eVULgEjkurDLq3goeM= +github.com/gregjones/httpcache v0.0.0-20180305231024-9cad4c3443a7/go.mod h1:FecbI9+v66THATjSRHfNgh1IVFe/9kFxbXtjV0ctIMA= +github.com/grpc-ecosystem/go-grpc-middleware v1.0.0 h1:Iju5GlWwrvL6UBg4zJJt3btmonfrMlCDdsejg4CZE7c= +github.com/grpc-ecosystem/go-grpc-middleware v1.0.0/go.mod h1:FiyG127CGDf3tlThmgyCl78X/SZQqEOJBCDaAfeWzPs= +github.com/grpc-ecosystem/go-grpc-prometheus v1.2.0 h1:Ovs26xHkKqVztRpIrF/92BcuyuQ/YW4NSIpoGtfXNho= +github.com/grpc-ecosystem/go-grpc-prometheus v1.2.0/go.mod h1:8NvIoxWQoOIhqOTXgfV/d3M/q6VIi02HzZEHgUlZvzk= +github.com/grpc-ecosystem/grpc-gateway v1.5.0/go.mod h1:RSKVYQBd5MCa4OVpNdGskqpgL2+G+NZTnrVHpWWfpdw= +github.com/grpc-ecosystem/grpc-gateway v1.6.2/go.mod h1:RSKVYQBd5MCa4OVpNdGskqpgL2+G+NZTnrVHpWWfpdw= +github.com/grpc-ecosystem/grpc-gateway v1.8.5 h1:2+KSC78XiO6Qy0hIjfc1OD9H+hsaJdJlb8Kqsd41CTE= +github.com/grpc-ecosystem/grpc-gateway v1.8.5/go.mod h1:vNeuVxBJEsws4ogUvrchl83t/GYV9WGTSLVdBhOQFDY= +github.com/hailocab/go-hostpool v0.0.0-20160125115350-e80d13ce29ed h1:5upAirOpQc1Q53c0bnx2ufif5kANL7bfZWcc6VJWJd8= +github.com/hailocab/go-hostpool v0.0.0-20160125115350-e80d13ce29ed/go.mod h1:tMWxXQ9wFIaZeTI9F+hmhFiGpFmhOHzyShyFUhRm0H4= +github.com/hashicorp/consul v1.4.0/go.mod h1:mFrjN1mfidgJfYP1xrJCF+AfRhr6Eaqhb2+sfyn/OOI= github.com/hashicorp/consul v1.4.2 h1:D9iJoJb8Ehe/Zmr+UEE3U3FjOLZ4LUxqFMl4O43BM1U= github.com/hashicorp/consul v1.4.2/go.mod h1:mFrjN1mfidgJfYP1xrJCF+AfRhr6Eaqhb2+sfyn/OOI= +github.com/hashicorp/consul v1.4.4 h1:DR1+5EGgnPsd/LIsK3c9RDvajcsV5GOkGQBSNd3dpn8= +github.com/hashicorp/consul v1.4.4/go.mod h1:mFrjN1mfidgJfYP1xrJCF+AfRhr6Eaqhb2+sfyn/OOI= github.com/hashicorp/errwrap v1.0.0 h1:hLrqtEDnRye3+sgx6z4qVLNuviH3MR5aQ0ykNJa/UYA= github.com/hashicorp/errwrap v1.0.0/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4= github.com/hashicorp/go-cleanhttp v0.5.0 h1:wvCrVc9TjDls6+YGAF2hAifE1E5U1+b4tH6KdvN3Gig= github.com/hashicorp/go-cleanhttp v0.5.0/go.mod h1:JpRdi6/HCYpAwUzNwuwqhbovhLtngrth3wmdIIUrZ80= +github.com/hashicorp/go-cleanhttp v0.5.1 h1:dH3aiDG9Jvb5r5+bYHsikaOUIpcM0xvgMXVoDkXMzJM= +github.com/hashicorp/go-cleanhttp v0.5.1/go.mod h1:JpRdi6/HCYpAwUzNwuwqhbovhLtngrth3wmdIIUrZ80= +github.com/hashicorp/go-discover v0.0.0-20190319153616-61771d82ff54 h1:TfczkKkpOH9xfR0vZaSpW2FNP6hh2qm51n9yo20owBE= +github.com/hashicorp/go-discover v0.0.0-20190319153616-61771d82ff54/go.mod h1:CImRKBstQOB5m5fNKXFT/CCp5WyWCLvcYydd0kb2EaA= +github.com/hashicorp/go-gcp-common v0.5.0 h1:kkIQTjNTopn4eXQ1+lCiHYZXUtgIZvbc6YtAQkMnTos= +github.com/hashicorp/go-gcp-common v0.5.0/go.mod h1:IDGUI2N/OS3PiU4qZcXJeWKPI6O/9Y8hOrbSiMcqyYw= +github.com/hashicorp/go-hclog v0.0.0-20180709165350-ff2cf002a8dd/go.mod h1:9bjs9uLqI8l75knNv3lV1kA55veR+WUPSiKIWcQHudI= +github.com/hashicorp/go-hclog v0.0.0-20181001195459-61d530d6c27f/go.mod h1:5CU+agLiy3J7N7QjHK5d05KxGsuXiQLrjA0H7acj2lQ= +github.com/hashicorp/go-hclog v0.8.0 h1:z3ollgGRg8RjfJH6UVBaG54R70GFd++QOkvnJH3VSBY= +github.com/hashicorp/go-hclog v0.8.0/go.mod h1:5CU+agLiy3J7N7QjHK5d05KxGsuXiQLrjA0H7acj2lQ= github.com/hashicorp/go-immutable-radix v1.0.0 h1:AKDB1HM5PWEA7i4nhcpwOrO2byshxBjXVn/J/3+z5/0= github.com/hashicorp/go-immutable-radix v1.0.0/go.mod h1:0y9vanUI8NX6FsYoO3zeMjhV/C5i9g4Q3DwcSNZ4P60= +github.com/hashicorp/go-memdb v0.0.0-20181108192425-032f93b25bec/go.mod h1:kbfItVoBJwCfKXDXN4YoAXjxcFVZ7MRrJzyTX6H4giE= +github.com/hashicorp/go-memdb v1.0.0 h1:K1O4N2VPndZiTrdH3lmmf5bemr9Xw81KjVwhReIUjTQ= +github.com/hashicorp/go-memdb v1.0.0/go.mod h1:I6dKdmYhZqU0RJSheVEWgTNWdVQH5QvTgIUQ0t/t32M= +github.com/hashicorp/go-msgpack v0.0.0-20150518234257-fa3f63826f7c/go.mod h1:ahLV/dePpqEmjfWmKiqvPkv/twdG7iPBM1vqhUKIvfM= github.com/hashicorp/go-msgpack v0.5.3 h1:zKjpN5BK/P5lMYrLmBHdBULWbJ0XpYR+7NGzqkZzoD4= github.com/hashicorp/go-msgpack v0.5.3/go.mod h1:ahLV/dePpqEmjfWmKiqvPkv/twdG7iPBM1vqhUKIvfM= github.com/hashicorp/go-multierror v1.0.0 h1:iVjPR7a6H0tWELX5NxNe7bYopibicUzc7uPribsnS6o= github.com/hashicorp/go-multierror v1.0.0/go.mod h1:dHtQlpGsu+cZNNAkkCN/P3hoUDHhCYQXV3UM06sGGrk= +github.com/hashicorp/go-plugin v0.0.0-20181030172320-54b6ff97d818/go.mod h1:Ft7ju2vWzhO0ETMKUVo12XmXmII6eSUS4rsPTkY/siA= +github.com/hashicorp/go-plugin v1.0.0 h1:/gQ1sNR8/LHpoxKRQq4PmLBuacfZb4tC93e9B30o/7c= +github.com/hashicorp/go-plugin v1.0.0/go.mod h1:++UyYGoz3o5w9ZzAdZxtQKrWWP+iqPBn3cQptSMzBuY= +github.com/hashicorp/go-retryablehttp v0.5.0/go.mod h1:9B5zBasrRhHXnJnui7y6sL7es7NDiJgTc6Er0maI1Xs= +github.com/hashicorp/go-retryablehttp v0.5.3 h1:QlWt0KvWT0lq8MFppF9tsJGF+ynG7ztc2KIPhzRGk7s= +github.com/hashicorp/go-retryablehttp v0.5.3/go.mod h1:9B5zBasrRhHXnJnui7y6sL7es7NDiJgTc6Er0maI1Xs= +github.com/hashicorp/go-rootcerts v0.0.0-20160503143440-6bb64b370b90/go.mod h1:o4zcYY1e0GEZI6eSEr+43QDYmuGglw1qSO6qdHUHCgg= github.com/hashicorp/go-rootcerts v1.0.0 h1:Rqb66Oo1X/eSV1x66xbDccZjhJigjg0+e82kpwzSwCI= github.com/hashicorp/go-rootcerts v1.0.0/go.mod h1:K6zTfqpRlCUIjkwsN4Z+hiSfzSTQa6eBIzfwKfwNnHU= +github.com/hashicorp/go-sockaddr v0.0.0-20180320115054-6d291a969b86/go.mod h1:7Xibr9yA9JjQq1JpNB2Vw7kxv8xerXegt+ozgdvDeDU= github.com/hashicorp/go-sockaddr v1.0.0/go.mod h1:7Xibr9yA9JjQq1JpNB2Vw7kxv8xerXegt+ozgdvDeDU= github.com/hashicorp/go-sockaddr v1.0.1 h1:eCkkJ5KOOktDvwbsE9KPyiBWaOfp1ZNy2gLHgL8PSBM= github.com/hashicorp/go-sockaddr v1.0.1/go.mod h1:rB4wwRAUzs07qva3c5SdrY/NEtAUjGlgmH/UkBUC97A= +github.com/hashicorp/go-sockaddr v1.0.2 h1:ztczhD1jLxIRjVejw8gFomI1BQZOe2WoVOu0SyteCQc= +github.com/hashicorp/go-sockaddr v1.0.2/go.mod h1:rB4wwRAUzs07qva3c5SdrY/NEtAUjGlgmH/UkBUC97A= +github.com/hashicorp/go-syslog v1.0.0 h1:KaodqZuhUoZereWVIYmpUgZysurB1kBLX2j0MwMrUAE= github.com/hashicorp/go-syslog v1.0.0/go.mod h1:qPfqrKkXGihmCqbJM2mZgkZGvKG1dFdvsLplgctolz4= github.com/hashicorp/go-uuid v1.0.0/go.mod h1:6SBZvOh/SIDV7/2o3Jml5SYk/TvGqwFJ/bN7x4byOro= +github.com/hashicorp/go-uuid v1.0.1 h1:fv1ep09latC32wFoVwnqcnKJGnMSdBanPczbHAYm1BE= github.com/hashicorp/go-uuid v1.0.1/go.mod h1:6SBZvOh/SIDV7/2o3Jml5SYk/TvGqwFJ/bN7x4byOro= +github.com/hashicorp/go-version v1.0.0/go.mod h1:fltr4n8CU8Ke44wwGCBoEymUuxUHl09ZGVZPK5anwXA= +github.com/hashicorp/go-version v1.1.0 h1:bPIoEKD27tNdebFGGxxYwcL4nepeY4j1QP23PFRGzg0= +github.com/hashicorp/go-version v1.1.0/go.mod h1:fltr4n8CU8Ke44wwGCBoEymUuxUHl09ZGVZPK5anwXA= +github.com/hashicorp/go.net v0.0.1 h1:sNCoNyDEvN1xa+X0baata4RdcpKwcMS6DH+xwfqPgjw= github.com/hashicorp/go.net v0.0.1/go.mod h1:hjKkEWcCURg++eb33jQU7oqQcI9XDCnUzHA0oac0k90= github.com/hashicorp/golang-lru v0.5.0 h1:CL2msUPvZTLb5O648aiLNJw3hnBxN2+1Jq8rCOH9wdo= github.com/hashicorp/golang-lru v0.5.0/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8= +github.com/hashicorp/golang-lru v0.5.1 h1:0hERBMJE1eitiLkihrMvRVBYAkpHzc/J3QdDN+dAcgU= +github.com/hashicorp/golang-lru v0.5.1/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8= +github.com/hashicorp/hcl v1.0.0 h1:0Anlzjpi4vEasTeNFn2mLJgTSwt0+6sfsiTG8qcWGx4= +github.com/hashicorp/hcl v1.0.0/go.mod h1:E5yfLk+7swimpb2L/Alb/PJmXilQ/rhwaUYs4T20WEQ= +github.com/hashicorp/hil v0.0.0-20190212132231-97b3a9cdfa93 h1:T1Q6ag9tCwun16AW+XK3tAql24P4uTGUMIn1/92WsQQ= +github.com/hashicorp/hil v0.0.0-20190212132231-97b3a9cdfa93/go.mod h1:n2TSygSNwsLJ76m8qFXTSc7beTb+auJxYdqrnoqwZWE= +github.com/hashicorp/logutils v1.0.0 h1:dLEQVugN8vlakKOUE3ihGLTZJRB4j+M2cdTm/ORI65Y= github.com/hashicorp/logutils v1.0.0/go.mod h1:QIAnNjmIWmVIIkWDTG1z5v++HQmx9WQRO+LraFDTW64= +github.com/hashicorp/mdns v1.0.0 h1:WhIgCr5a7AaVH6jPUwjtRuuE7/RDufnUvzIr48smyxs= github.com/hashicorp/mdns v1.0.0/go.mod h1:tL+uN++7HEJ6SQLQ2/p+z2pH24WQKWjBPkE0mNTz8vQ= +github.com/hashicorp/memberlist v0.1.0/go.mod h1:ncdBp14cuox2iFOq3kDiquKU6fqsTBc3W6JvZwjxxsE= github.com/hashicorp/memberlist v0.1.3 h1:EmmoJme1matNzb+hMpDuR/0sbJSUisxyqBGG676r31M= github.com/hashicorp/memberlist v0.1.3/go.mod h1:ajVTdAv/9Im8oMAAj5G31PhhMCZJV2pPBoIllUwCN7I= +github.com/hashicorp/net-rpc-msgpackrpc v0.0.0-20151116020338-a14192a58a69 h1:lc3c72qGlIMDqQpQH82Y4vaglRMMFdJbziYWriR4UcE= +github.com/hashicorp/net-rpc-msgpackrpc v0.0.0-20151116020338-a14192a58a69/go.mod h1:/z+jUGRBlwVpUZfjute9jWaF6/HuhjuFQuL1YXzVD1Q= +github.com/hashicorp/nomad v0.8.7 h1:jOrmJdAoWcyhKgoG4OxHQhG5SU6RniXFjfwKg6a492U= +github.com/hashicorp/nomad v0.8.7/go.mod h1:WRaKjdO1G2iqi86TvTjIYtKTyxg4pl7NLr9InxtWaI0= +github.com/hashicorp/raft v1.0.0 h1:htBVktAOtGs4Le5Z7K8SF5H2+oWsQFYVmOgH5loro7Y= +github.com/hashicorp/raft v1.0.0/go.mod h1:DVSAWItjLjTOkVbSpWQ0j0kUADIvDaCtBxIcbNAQLkI= +github.com/hashicorp/raft-boltdb v0.0.0-20171010151810-6e5ba93211ea h1:xykPFhrBAS2J0VBzVa5e80b5ZtYuNQtgXjN40qBZlD4= +github.com/hashicorp/raft-boltdb v0.0.0-20171010151810-6e5ba93211ea/go.mod h1:pNv7Wc3ycL6F5oOWn+tPGo2gWD4a5X+yp/ntwdKLjRk= +github.com/hashicorp/serf v0.8.1/go.mod h1:h/Ru6tmZazX7WO/GDmwdpS975F019L4t5ng5IgwbNrE= github.com/hashicorp/serf v0.8.2 h1:YZ7UKsJv+hKjqGVUUbtE3HNj79Eln2oQ75tniF6iPt0= github.com/hashicorp/serf v0.8.2/go.mod h1:6hOLApaqBFA1NXqRQAsxw9QxuDEvNxSQRwA/JwenrHc= +github.com/hashicorp/vault v0.11.5/go.mod h1:KfSyffbKxoVyspOdlaGVjIuwLobi07qD1bAbosPMpP0= +github.com/hashicorp/vault v1.1.0 h1:v79NUgO5xCZnXVzUkIqFOXtP8YhpnHAi1fk3eo9cuOE= +github.com/hashicorp/vault v1.1.0/go.mod h1:KfSyffbKxoVyspOdlaGVjIuwLobi07qD1bAbosPMpP0= +github.com/hashicorp/vault-plugin-auth-alicloud v0.0.0-20190320211238-36e70c54375f h1:yGxKygXLLfXKXYMBWDVja7dxxnTNYlYz81lpx2GRh4c= +github.com/hashicorp/vault-plugin-auth-alicloud v0.0.0-20190320211238-36e70c54375f/go.mod h1:o3i5QQWgV5+SYouIn++L9D0kbhLYB3FjxNRHNf6KS+Q= +github.com/hashicorp/vault-plugin-auth-azure v0.0.0-20190320211138-f34b96803f04 h1:MzPikhU6lh/tzbS5/+aj876HM+NkPOSe6C9cP/zudlU= +github.com/hashicorp/vault-plugin-auth-azure v0.0.0-20190320211138-f34b96803f04/go.mod h1:f+VmjSQIxxO+YTeO3FbPWRPCPbd3f3lwpP6jaO/YduQ= +github.com/hashicorp/vault-plugin-auth-centrify v0.0.0-20190320211357-44eb061bdfd8 h1:t3v3tm2pkxu7fgoBrrXcv3DTsiJCZCkgwGXFpm0+be8= +github.com/hashicorp/vault-plugin-auth-centrify v0.0.0-20190320211357-44eb061bdfd8/go.mod h1:IIz+CMBKBEFyjeBeFUlpoUuMOyFb7mybOUNP6GX1xuk= +github.com/hashicorp/vault-plugin-auth-gcp v0.0.0-20190320214413-e8308b5e41c9 h1:8dbhVmPoLPBzYFXkLHl1Gp4lkO1mFwFyyXHanINstHw= +github.com/hashicorp/vault-plugin-auth-gcp v0.0.0-20190320214413-e8308b5e41c9/go.mod h1:E/E+5CuQCjOn/YGCmZ/tA7GwLey/lN1PwwJOOa9Iqy0= +github.com/hashicorp/vault-plugin-auth-jwt v0.0.0-20190321042813-9474f90fb1df h1:K1dfrdfHKd6IcOGCwmGF1/UTqI0psKnRJ1G49WKn0Zw= +github.com/hashicorp/vault-plugin-auth-jwt v0.0.0-20190321042813-9474f90fb1df/go.mod h1:j6Xmkj3dzuC63mivquwVVTlxjwDndwNxi4cJUku40J8= +github.com/hashicorp/vault-plugin-auth-kubernetes v0.0.0-20190328163920-79931ee7aad5 h1:wJzxQBOoas0YkjEpDKas+wWoDbpKBtsFYcNK3tNUP5Y= +github.com/hashicorp/vault-plugin-auth-kubernetes v0.0.0-20190328163920-79931ee7aad5/go.mod h1:PqRUU5TaQ6FwVTsHPLrJs1F+T5IjbSzlfTy9cTyGeHM= +github.com/hashicorp/vault-plugin-secrets-ad v0.0.0-20190327182327-ed2c3d4c3d95 h1:8cIHbCsHHPn85gdoslbiw5A6j3Hbh0ezCbOG9bYeI3I= +github.com/hashicorp/vault-plugin-secrets-ad v0.0.0-20190327182327-ed2c3d4c3d95/go.mod h1:4vRQzvp3JI+g4oUqzcklIEj2UKyhQnpIo+BDbh2uzYM= +github.com/hashicorp/vault-plugin-secrets-alicloud v0.0.0-20190320213517-3307bdf683cb h1:pY6UDWcA1ZBNLDHt0Q/bzXr/HwbqPV/l6UgM2P+PFt4= +github.com/hashicorp/vault-plugin-secrets-alicloud v0.0.0-20190320213517-3307bdf683cb/go.mod h1:rl8WzY7++fZMLXd6Z/k/o9wUmMbOqpTLhbtKs1loMU0= +github.com/hashicorp/vault-plugin-secrets-azure v0.0.0-20190320211922-2dc8a8a5e490 h1:JfNEC8hCXOqQ8f6ISAtLa/1Ugk0mMrOjOkt8vYtZVGU= +github.com/hashicorp/vault-plugin-secrets-azure v0.0.0-20190320211922-2dc8a8a5e490/go.mod h1:/DhLpYuRP2o00gkj6S0Gy7NvKk5AaAtP6p3f+OmxDUI= +github.com/hashicorp/vault-plugin-secrets-gcp v0.0.0-20190320211452-71903323ecb4 h1:wGqUiCrjncbZnJYmlq14wMibhDn/wwrrtvNSdUvJiQE= +github.com/hashicorp/vault-plugin-secrets-gcp v0.0.0-20190320211452-71903323ecb4/go.mod h1:IV2OZZZ9FCtSYeKDLsnO5JipMdjwachVISz9pNuQjhs= +github.com/hashicorp/vault-plugin-secrets-gcpkms v0.0.0-20190320213325-9e326a9e802d h1:MFmc9Bkmh4AF1ZgEFnOPHPmqeQu8Yebq+6VlidUWjn4= +github.com/hashicorp/vault-plugin-secrets-gcpkms v0.0.0-20190320213325-9e326a9e802d/go.mod h1:2n62quNV4DvfMY5Lxx82NJmx+9pYtv4RltLIFKxEO4E= +github.com/hashicorp/vault-plugin-secrets-kv v0.0.0-20181106190520-2236f141171e/go.mod h1:VJHHT2SC1tAPrfENQeBhLlb5FbZoKZM+oC/ROmEftz0= +github.com/hashicorp/vault-plugin-secrets-kv v0.0.0-20190320211621-3ccc8684cf25 h1:7rGkIXt39f/+4N/RnDbZVV3vEskY7Dh7vmtJew4GuyA= +github.com/hashicorp/vault-plugin-secrets-kv v0.0.0-20190320211621-3ccc8684cf25/go.mod h1:VJHHT2SC1tAPrfENQeBhLlb5FbZoKZM+oC/ROmEftz0= +github.com/hashicorp/yamux v0.0.0-20180604194846-3520598351bb/go.mod h1:+NfK9FKeTrX5uv1uIXGdwYDTeHna2qgaIlx54MXqjAM= +github.com/hashicorp/yamux v0.0.0-20181012175058-2f1d1f20f75d h1:kJCB4vdITiW1eC1vq2e6IsrXKrZit1bv/TDYFGMp4BQ= +github.com/hashicorp/yamux v0.0.0-20181012175058-2f1d1f20f75d/go.mod h1:+NfK9FKeTrX5uv1uIXGdwYDTeHna2qgaIlx54MXqjAM= +github.com/hpcloud/tail v1.0.0 h1:nfCOvKYfkgYP8hkirhJocXT2+zOD8yUNjXaWfTlyFKI= +github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU= +github.com/huandu/xstrings v1.0.0/go.mod h1:4qWG/gcEcfX4z/mBDHJ++3ReCw9ibxbsNJbcucJdbSo= +github.com/imdario/mergo v0.3.4/go.mod h1:2EnlNZ0deacrJVfApfmtdGgDfMuh/nq6Ok1EcJh5FfA= +github.com/imdario/mergo v0.3.6 h1:xTNEAn+kxVO7dTZGu0CegyqKZmoWFI0rF8UxjlB2d28= +github.com/imdario/mergo v0.3.6/go.mod h1:2EnlNZ0deacrJVfApfmtdGgDfMuh/nq6Ok1EcJh5FfA= +github.com/inconshreveable/mousetrap v1.0.0/go.mod h1:PxqpIevigyE2G7u3NXJIT2ANytuPF1OarO4DADm73n8= +github.com/influxdata/flux v0.13.0/go.mod h1:81jeDcHVn1rN5uj9aQ81S72Q8ol8If7N0zM0G8TnxTE= +github.com/influxdata/influxdb v1.7.5 h1:qEgSrvIRxsIqNQTTeI1Bv6MPh8sOODEsL3GTi9nqtTk= +github.com/influxdata/influxdb v1.7.5/go.mod h1:qZna6X/4elxqT3yI9iZYdZrWWdeFOOprn86kgg4+IzY= +github.com/influxdata/influxql v0.0.0-20180925231337-1cbfca8e56b6/go.mod h1:KpVI7okXjK6PRi3Z5B+mtKZli+R1DnZgb3N+tzevNgo= +github.com/influxdata/line-protocol v0.0.0-20180522152040-32c6aa80de5e/go.mod h1:4kt73NQhadE3daL3WhR5EJ/J2ocX0PZzwxQ0gXJ7oFE= +github.com/influxdata/platform v0.0.0-20190117200541-d500d3cf5589 h1:oN2MMxbnMD/XIlyXbSczQqN5vcrCMFuRsiQafSt2c1E= +github.com/influxdata/platform v0.0.0-20190117200541-d500d3cf5589/go.mod h1:YVhys+JOY4wmXtJvdtkzLhS2K/r/px/vPc+EAddK+pg= +github.com/influxdata/tdigest v0.0.0-20181121200506-bf2b5ad3c0a9/go.mod h1:Js0mqiSBE6Ffsg94weZZ2c+v/ciT8QRHFOap7EKDrR0= +github.com/influxdata/usage-client v0.0.0-20160829180054-6d3895376368/go.mod h1:Wbbw6tYNvwa5dlB6304Sd+82Z3f7PmVZHVKU637d4po= +github.com/jarcoal/httpmock v0.0.0-20180424175123-9c70cfe4a1da h1:FjHUJJ7oBW4G/9j1KzlHaXL09LyMVM9rupS39lncbXk= +github.com/jarcoal/httpmock v0.0.0-20180424175123-9c70cfe4a1da/go.mod h1:ks+b9deReOc7jgqp+e7LuFiCBH6Rm5hL32cLcEAArb4= +github.com/jbenet/go-context v0.0.0-20150711004518-d14ea06fba99/go.mod h1:1lJo3i6rXxKeerYnT8Nvf0QmHCRC1n8sfWVwXF2Frvo= +github.com/jeffchao/backoff v0.0.0-20140404060208-9d7fd7aa17f2 h1:mex1izRBCD+7WjieGgRdy7e651vD/lvB1bD9vNE/3K4= +github.com/jeffchao/backoff v0.0.0-20140404060208-9d7fd7aa17f2/go.mod h1:xkfESuHriIekR+4RoV+fu91j/CfnYM29Zi2tMFw5iD4= +github.com/jefferai/jsonx v0.0.0-20160721235117-9cc31c3135ee/go.mod h1:N0t2vlmpe8nyZB5ouIbJQPDSR+mH6oe7xHB9VZHSUzM= +github.com/jefferai/jsonx v1.0.0 h1:Xoz0ZbmkpBvED5W9W1B5B/zc3Oiq7oXqiW7iRV3B6EI= +github.com/jefferai/jsonx v1.0.0/go.mod h1:OGmqmi2tTeI/PS+qQfBDToLHHJIy/RMp24fPo8vFvoQ= +github.com/jellevandenhooff/dkim v0.0.0-20150330215556-f50fe3d243e1/go.mod h1:E0B/fFc00Y+Rasa88328GlI/XbtyysCtTHZS8h7IrBU= +github.com/jessevdk/go-flags v1.4.0/go.mod h1:4FA24M0QyGHXBuZZK/XkWh8h0e1EYbRYJSGM75WSRxI= +github.com/jmespath/go-jmespath v0.0.0-20160202185014-0b12d6b521d8 h1:12VvqtR6Aowv3l/EQUlocDHW2Cp4G9WJVH7uyH8QFJE= +github.com/jmespath/go-jmespath v0.0.0-20160202185014-0b12d6b521d8/go.mod h1:Nht3zPeWKUH0NzdCt2Blrr5ys8VGpn0CEB0cQHVjt7k= +github.com/jmespath/go-jmespath v0.0.0-20180206201540-c2b33e8439af h1:pmfjZENx5imkbgOkpRUYLnmbU7UEFbjtDA2hxJ1ichM= +github.com/jmespath/go-jmespath v0.0.0-20180206201540-c2b33e8439af/go.mod h1:Nht3zPeWKUH0NzdCt2Blrr5ys8VGpn0CEB0cQHVjt7k= +github.com/jonboulle/clockwork v0.1.0 h1:VKV+ZcuP6l3yW9doeqz6ziZGgcynBVQO+obU0+0hcPo= +github.com/jonboulle/clockwork v0.1.0/go.mod h1:Ii8DK3G1RaLaWxj9trq07+26W01tbo22gdxWY5EU2bo= +github.com/joyent/triton-go v0.0.0-20180628001255-830d2b111e62 h1:JHCT6xuyPUrbbgAPE/3dqlvUKzRHMNuTBKKUb6OeR/k= +github.com/joyent/triton-go v0.0.0-20180628001255-830d2b111e62/go.mod h1:U+RSyWxWd04xTqnuOQxnai7XGS2PrPY2cfGoDKtMHjA= +github.com/json-iterator/go v1.1.5 h1:gL2yXlmiIo4+t+y32d4WGwOjKGYcGOuyrg46vadswDE= +github.com/json-iterator/go v1.1.5/go.mod h1:+SdeFBvtyEkXs7REEP0seUULqWtbJapLOCVDaaPEHmU= +github.com/jsternberg/zap-logfmt v1.2.0/go.mod h1:kz+1CUmCutPWABnNkOu9hOHKdT2q3TDYCcsFy9hpqb0= +github.com/jtolds/gls v4.2.1+incompatible h1:fSuqC+Gmlu6l/ZYAoZzx2pyucC8Xza35fpRVWLVmUEE= +github.com/jtolds/gls v4.2.1+incompatible/go.mod h1:QJZ7F/aHp+rZTRtaJ1ow/lLfFfVYBRgL+9YlvaHOwJU= +github.com/julienschmidt/httprouter v1.2.0/go.mod h1:SYymIcj16QtmaHHD7aYtjjsJG7VTCxuUUipMqKk8s4w= +github.com/jwilder/encoding v0.0.0-20170811194829-b4e1701a28ef/go.mod h1:Ct9fl0F6iIOGgxJ5npU/IUOhOhqlVrGjyIZc8/MagT0= +github.com/k0kubun/colorstring v0.0.0-20150214042306-9440f1994b88/go.mod h1:3w7q1U84EfirKl04SVQ/s7nPm1ZPhiXd34z40TNz36k= +github.com/kevinburke/go-bindata v3.11.0+incompatible/go.mod h1:/pEEZ72flUW2p0yi30bslSp9YqD9pysLxunQDdb2CPM= +github.com/kevinburke/ssh_config v0.0.0-20180830205328-81db2a75821e/go.mod h1:CT57kijsi8u/K/BOFA39wgDQJ9CxiF4nAY/ojJ6r6mM= +github.com/keybase/go-crypto v0.0.0-20181031135447-f919bfda4fc1/go.mod h1:ghbZscTyKdM07+Fw3KSi0hcJm+AlEUWj8QLlPtijN/M= +github.com/keybase/go-crypto v0.0.0-20190312101036-b475f2ecc1fe h1:1uflwka8xAWVB2vfZgn+EzemfgGi7WA/XHDnECEeSCM= +github.com/keybase/go-crypto v0.0.0-20190312101036-b475f2ecc1fe/go.mod h1:ghbZscTyKdM07+Fw3KSi0hcJm+AlEUWj8QLlPtijN/M= +github.com/kisielk/errcheck v1.1.0/go.mod h1:EZBBE59ingxPouuu3KfxchcWSUPOHkagtvWXihfKN4Q= +github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck= +github.com/konsorten/go-windows-terminal-sequences v1.0.1 h1:mweAR1A6xJ3oS2pRaGiHgQ4OO8tzTaLawm8vnODuwDk= +github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= +github.com/kr/logfmt v0.0.0-20140226030751-b84e30acd515/go.mod h1:+0opPa2QZZtGFBFZlji/RkVcI2GknAs/DXo4wKdlNEc= +github.com/kr/pretty v0.1.0 h1:L/CwN0zerZDmRFUapSPitk6f+Q3+0za1rQkzVuMiMFI= +github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo= +github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= +github.com/kr/pty v1.1.3/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= +github.com/kr/text v0.1.0 h1:45sCR5RtlFHMR4UwH9sdQ5TC8v0qDQCHnXt+kaKSTVE= +github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= +github.com/lib/pq v1.0.0 h1:X5PMW56eZitiTeO7tKzZxFCSpbFZJtkMMooicw2us9A= +github.com/lib/pq v1.0.0/go.mod h1:5WUZQaWbwv1U+lTReE5YruASi9Al49XbQIvNi/34Woo= +github.com/lyft/protoc-gen-validate v0.0.14 h1:xbdDVIHd0Xq5Bfzu+8JR9s7mFmJPMvNLmfGhgcHJdFU= +github.com/lyft/protoc-gen-validate v0.0.14/go.mod h1:XbGvPuh87YZc5TdIa2/I4pLk0QoUACkjt2znoq26NVQ= +github.com/magiconair/properties v1.8.0/go.mod h1:PppfXfuXeibc/6YijjN8zIbojt8czPbwD3XqdrwzmxQ= +github.com/mattbaird/elastigo v0.0.0-20170123220020-2fe47fd29e4b h1:v29yPGHhOqw7VHEnTeQFAth3SsBrmwc8JfuhNY0G34k= +github.com/mattbaird/elastigo v0.0.0-20170123220020-2fe47fd29e4b/go.mod h1:5MWrJXKRQyhQdUCF+vu6U5c4nQpg70vW3eHaU0/AYbU= github.com/mattn/go-colorable v0.0.9/go.mod h1:9vuHe8Xs5qXnSaW/c/ABM9alt+Vo+STaOChaDxuIBZU= github.com/mattn/go-colorable v0.1.0/go.mod h1:9vuHe8Xs5qXnSaW/c/ABM9alt+Vo+STaOChaDxuIBZU= +github.com/mattn/go-colorable v0.1.1 h1:G1f5SKeVxmagw/IyvzvtZE4Gybcc4Tr1tf7I8z0XgOg= github.com/mattn/go-colorable v0.1.1/go.mod h1:FuOcm+DKB9mbwrcAfNl7/TZVBZ6rcnceauSikq3lYCQ= github.com/mattn/go-isatty v0.0.3/go.mod h1:M+lRXTBqGeGNdLjl/ufCoiOlB5xdOkqRJdNxMWT7Zi4= github.com/mattn/go-isatty v0.0.4/go.mod h1:M+lRXTBqGeGNdLjl/ufCoiOlB5xdOkqRJdNxMWT7Zi4= github.com/mattn/go-isatty v0.0.5/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hdxcsrc5s= +github.com/mattn/go-isatty v0.0.7 h1:UvyT9uN+3r7yLEYSlJsbQGdsaB/a0DlgWP3pql6iwOc= +github.com/mattn/go-isatty v0.0.7/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hdxcsrc5s= +github.com/mattn/go-runewidth v0.0.3/go.mod h1:LwmH8dsx7+W8Uxz3IHJYH5QSwggIsqBzpuz5H//U1FU= +github.com/mattn/go-tty v0.0.0-20180907095812-13ff1204f104/go.mod h1:XPvLUNfbS4fJH25nqRHfWLMa1ONC8Amw+mIA639KxkE= +github.com/mattn/go-zglob v0.0.0-20171230104132-4959821b4817/go.mod h1:9fxibJccNxU2cnpIKLRRFA7zX7qhkJIQWBb449FYHOo= +github.com/mattn/go-zglob v0.0.0-20180803001819-2ea3427bfa53/go.mod h1:9fxibJccNxU2cnpIKLRRFA7zX7qhkJIQWBb449FYHOo= +github.com/matttproud/golang_protobuf_extensions v1.0.1 h1:4hp9jkHxhMHkqkrB3Ix0jegS5sx/RkqARlsWZ6pIwiU= +github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0= +github.com/michaelklishin/rabbit-hole v1.5.0 h1:Bex27BiFDsijCM9D0ezSHqyy0kehpYHuNKaPqq/a4RM= +github.com/michaelklishin/rabbit-hole v1.5.0/go.mod h1:vvI1uOitYZi0O5HEGXhaWC1XT80Gy+HvFheJ+5Krlhk= github.com/micro/cli v0.0.0-20181223203424-1b0c9793c300/go.mod h1:x9x6qy+tXv17jzYWQup462+j3SIUgDa6vVTzU4IXy/w= github.com/micro/cli v0.1.0 h1:5DT+QdbAPPQvB3gYTgwze7tFO1m+7DU1sz9XfQczbsc= github.com/micro/cli v0.1.0/go.mod h1:jRT9gmfVKWSS6pkKcXQ8YhUyj6bzwxK8Fp5b0Y7qNnk= @@ -59,11 +488,14 @@ github.com/micro/go-log v0.1.0/go.mod h1:qaFBF6d6Jk01Gz4cbMkCA2vVuLk3FSaLLjmEGrM github.com/micro/go-micro v0.23.0/go.mod h1:3z3lfMkNU9Sr1L/CxL++8pVJmQapRo0N6kNjwYDtOVs= github.com/micro/go-micro v0.26.0/go.mod h1:CweCFO/pq8dCSIOdzVZ4ooIpUrKlyJ0AcFB269M7PgU= github.com/micro/go-micro v0.26.1/go.mod h1:Jgc5gPEmDiG1TWE5Qnzzx5qyXnU9VTXKT1FkXkfvt8g= +github.com/micro/go-micro v1.0.0/go.mod h1:DnwIb4pb7podyAgAF8HYMlDkV5sjtcIj9wW4Iq+JyIk= github.com/micro/go-rcache v0.1.0 h1:YTIgANVHgBe1XOQ/yLICL+s2gbZCAdW+c2ckhekjkuc= github.com/micro/go-rcache v0.1.0/go.mod h1:INzyZjXO5M+PmN2A33YxD4TaOY61xjFIM4CfSHv+At8= github.com/micro/go-rcache v0.2.0/go.mod h1:EoiTwbY2ubQ6lc3ScV+SnmKbelDzeFezDxPDvF8XDxw= github.com/micro/go-rcache v0.2.1 h1:hx24BZuhW4UVCyLE8p6fDrUetXrYDlOYSn5DSmqcjms= github.com/micro/go-rcache v0.2.1/go.mod h1:aPCNY3RbjBdyd6ShLENl4MDSgpAiWIU4LyNLE9+TOEo= +github.com/micro/go-rcache v0.3.0 h1:KmJI80XnLNOB11U+hahQMMHBZLnZjf/oA4DB6FdEbSU= +github.com/micro/go-rcache v0.3.0/go.mod h1:M5zEP6UW8YfsaHHyFdcgTzgIshTPNqMKw38Mwc+ht4g= github.com/micro/h2c v1.0.0/go.mod h1:54sOOQW/GRlHhH43vKwOhUb+kHaXhVxR0d3CJhn9alE= github.com/micro/mdns v0.0.0-20181201230301-9c3770d4057a/go.mod h1:SQG6o/94RinohLuB5noHSevg2Iqg2wXLDUn4lj2LWWo= github.com/micro/mdns v0.1.0 h1:fuLybUsfynbigJmCot/54i+gwe0hpc/vtCMvWt2WfDI= @@ -72,65 +504,430 @@ github.com/micro/util v0.1.0 h1:ghhF5KKRNlKMexzK+cWo6W6uRAZdKy1UKG/9O74NCYc= github.com/micro/util v0.1.0/go.mod h1:MZgOs0nwxzv9k4xQo4fpF9IwZGF2O96F5/phP9X4/Sw= github.com/micro/util v0.2.0 h1:6u0cPj1TeixEk5cAR9jbcVRUWDQsmCaZvDBiM3zFZuA= github.com/micro/util v0.2.0/go.mod h1:SgRDkxJJluC2ZNiPfINY42ObEaCAFjL3jP5a+u+qRLU= +github.com/microcosm-cc/bluemonday v1.0.1/go.mod h1:hsXNsILzKxV+sX77C5b8FSuKF00vh2OMYv+xgHpAMF4= github.com/miekg/dns v1.0.14/go.mod h1:W1PPwlIAgtquWBMBEV9nkV9Cazfe8ScdGz/Lj7v3Nrg= +github.com/miekg/dns v1.1.1/go.mod h1:W1PPwlIAgtquWBMBEV9nkV9Cazfe8ScdGz/Lj7v3Nrg= github.com/miekg/dns v1.1.3/go.mod h1:W1PPwlIAgtquWBMBEV9nkV9Cazfe8ScdGz/Lj7v3Nrg= github.com/miekg/dns v1.1.4 h1:rCMZsU2ScVSYcAsOXgmC6+AKOK+6pmQTOcw03nfwYV0= github.com/miekg/dns v1.1.4/go.mod h1:W1PPwlIAgtquWBMBEV9nkV9Cazfe8ScdGz/Lj7v3Nrg= +github.com/miekg/dns v1.1.6 h1:jVwb4GDwD65q/gtItR/lIZHjNH93QfeGxZUkzJcW9mc= +github.com/miekg/dns v1.1.6/go.mod h1:W1PPwlIAgtquWBMBEV9nkV9Cazfe8ScdGz/Lj7v3Nrg= +github.com/mitchellh/cli v1.0.0 h1:iGBIsUe3+HZ/AD/Vd7DErOt5sU9fa8Uj7A2s1aggv1Y= github.com/mitchellh/cli v1.0.0/go.mod h1:hNIlj7HEI86fIcpObd7a0FcrxTWetlwJDGcceTlRvqc= +github.com/mitchellh/copystructure v1.0.0 h1:Laisrj+bAB6b/yJwB5Bt3ITZhGJdqmxquMKeZ+mmkFQ= +github.com/mitchellh/copystructure v1.0.0/go.mod h1:SNtv71yrdKgLRyLFxmLdkAbkKEFWgYaq1OVrnRcwhnw= github.com/mitchellh/go-homedir v1.0.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0= +github.com/mitchellh/go-homedir v1.1.0 h1:lukF9ziXFxDFPkA1vsr5zpc1XuPDn/wFntq5mG+4E0Y= github.com/mitchellh/go-homedir v1.1.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0= +github.com/mitchellh/go-testing-interface v0.0.0-20171004221916-a61a99592b77/go.mod h1:kRemZodwjscx+RGhAo8eIhFbs2+BFgRtFPeD/KE+zxI= +github.com/mitchellh/go-testing-interface v1.0.0 h1:fzU/JVNcaqHQEcVFAKeR41fkiLdIPrefOvVG1VZ96U0= +github.com/mitchellh/go-testing-interface v1.0.0/go.mod h1:kRemZodwjscx+RGhAo8eIhFbs2+BFgRtFPeD/KE+zxI= github.com/mitchellh/go-wordwrap v1.0.0/go.mod h1:ZXFpozHsX6DPmq2I0TCekCxypsnAUbP2oI0UX1GXzOo= github.com/mitchellh/gox v0.4.0/go.mod h1:Sd9lOJ0+aimLBi73mGofS1ycjY8lL3uZM3JPS42BGNg= github.com/mitchellh/hashstructure v1.0.0 h1:ZkRJX1CyOoTkar7p/mLS5TZU4nJ1Rn/F8u9dGS02Q3Y= github.com/mitchellh/hashstructure v1.0.0/go.mod h1:QjSHrPWS+BGUVBYkbTZWEnOh3G1DutKwClXU/ABz6AQ= github.com/mitchellh/iochan v1.0.0/go.mod h1:JwYml1nuB7xOzsp52dPpHFffvOCDupsG0QubkSMEySY= github.com/mitchellh/mapstructure v0.0.0-20160808181253-ca63d7c062ee/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y= +github.com/mitchellh/mapstructure v1.0.0/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y= github.com/mitchellh/mapstructure v1.1.2 h1:fmNYVwqnSfB9mZU6OS2O6GsXM+wcskZDuKQzvN1EDeE= github.com/mitchellh/mapstructure v1.1.2/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y= +github.com/mitchellh/pointerstructure v0.0.0-20190323210102-2db4bb651397 h1:GwYLdFxg/9bWW+e6YMWDNrKZ43gbKKkgC9mtmxai4o0= +github.com/mitchellh/pointerstructure v0.0.0-20190323210102-2db4bb651397/go.mod h1:k4XwG94++jLVsSiTxo7qdIfXA9pj9EAeo0QsNNJOLZ8= +github.com/mitchellh/reflectwalk v1.0.0 h1:9D+8oIskB4VJBN5SFlmc27fSlIBZaov1Wpk/IfikLNY= +github.com/mitchellh/reflectwalk v1.0.0/go.mod h1:mSTlrgnPZtwu0c4WaC2kGObEpuNDbx0jmZXqmk4esnw= +github.com/mna/pigeon v1.0.1-0.20180808201053-bb0192cfc2ae/go.mod h1:Iym28+kJVnC1hfQvv5MUtI6AiFFzvQjHcvI4RFTG/04= +github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd h1:TRLaZ9cD/w8PVh93nsPXa1VrQ6jlwL5oN8l14QlcNfg= +github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= +github.com/modern-go/reflect2 v1.0.1 h1:9f412s+6RmYXLWZSEzVVgPGK7C2PphHj5RJrvfx9AWI= +github.com/modern-go/reflect2 v1.0.1/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0= +github.com/mschoch/smat v0.0.0-20160514031455-90eadee771ae/go.mod h1:qAyveg+e4CE+eKJXWVjKXM4ck2QobLqTDytGJbLLhJg= +github.com/mwitkow/go-conntrack v0.0.0-20161129095857-cc309e4a2223/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U= +github.com/nats-io/gnatsd v1.3.0/go.mod h1:nqco77VO78hLCJpIcVfygDP2rPGfsEHkGTUk94uh5DQ= +github.com/nats-io/go-nats v1.6.0/go.mod h1:+t7RHT5ApZebkrQdnn6AhQJmhJJiKAvJUio1PiiCtj0= +github.com/nats-io/go-nats-streaming v0.4.0/go.mod h1:gfq4R3c9sKAINOpelo0gn/b9QDMBZnmrttcsNF+lqyo= +github.com/nats-io/nats-streaming-server v0.11.2/go.mod h1:RyqtDJZvMZO66YmyjIYdIvS69zu/wDAkyNWa8PIUa5c= +github.com/nats-io/nuid v1.0.0/go.mod h1:19wcPz3Ph3q0Jbyiqsd0kePYG7A95tJPxeL+1OSON2c= +github.com/neelance/astrewrite v0.0.0-20160511093645-99348263ae86/go.mod h1:kHJEU3ofeGjhHklVoIGuVj85JJwZ6kWPaJwCIxgnFmo= +github.com/neelance/sourcemap v0.0.0-20151028013722-8c68805598ab/go.mod h1:Qr6/a/Q4r9LP1IltGz7tA7iOK1WonHEYhu1HRBA7ZiM= +github.com/nicolai86/scaleway-sdk v1.10.2-0.20180628010248-798f60e20bb2 h1:BQ1HW7hr4IVovMwWg0E0PYcyW8CzqDcVmaew9cujU4s= +github.com/nicolai86/scaleway-sdk v1.10.2-0.20180628010248-798f60e20bb2/go.mod h1:TLb2Sg7HQcgGdloNxkrmtgDNR9uVYF3lfdFIN4Ro6Sk= +github.com/oklog/run v1.0.0 h1:Ru7dDtJNOyC66gQ5dQmaCa0qIsAUFY3sFpK1Xk8igrw= +github.com/oklog/run v1.0.0/go.mod h1:dlhp/R75TPv97u0XWUtDeV/lRKWPKSdTuV0TZvrmrQA= +github.com/onsi/ginkgo v1.6.0 h1:Ix8l273rp3QzYgXSR+c8d1fTG7UPgYkOSELPhiY/YGw= +github.com/onsi/ginkgo v1.6.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= +github.com/onsi/ginkgo v1.7.0 h1:WSHQ+IS43OoUrWtD1/bbclrwK8TTH5hzp+umCiuxHgs= +github.com/onsi/ginkgo v1.7.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= +github.com/onsi/gomega v1.4.1 h1:PZSj/UFNaVp3KxrzHOcS7oyuWA7LoOY/77yCTEFu21U= +github.com/onsi/gomega v1.4.1/go.mod h1:C1qb7wdrVGGVU+Z6iS04AVkA3Q65CEZX59MT0QO5uiA= +github.com/onsi/gomega v1.4.3 h1:RE1xgDvH7imwFD45h+u2SgIfERHlS2yNG4DObb5BSKU= +github.com/onsi/gomega v1.4.3/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1CpauHY= +github.com/opencontainers/go-digest v1.0.0-rc1 h1:WzifXhOVOEOuFYOJAW6aQqW0TooG2iki3E3Ii+WN7gQ= +github.com/opencontainers/go-digest v1.0.0-rc1/go.mod h1:cMLVZDEM3+U2I4VmLI6N8jQYUd2OVphdqWwCJHrFt2s= +github.com/opencontainers/image-spec v1.0.1 h1:JMemWkRwHx4Zj+fVxWoMCFm/8sYGGrUVojFA6h/TRcI= +github.com/opencontainers/image-spec v1.0.1/go.mod h1:BtxoFyWECRxE4U/7sNtV5W15zMzWCbyJoFRP3s7yZA0= +github.com/opencontainers/runc v0.1.1 h1:GlxAyO6x8rfZYN9Tt0Kti5a/cP41iuiO2yYT0IJGY8Y= +github.com/opencontainers/runc v0.1.1/go.mod h1:qT5XzbpPznkRYVz/mWwUaVBUv2rmF59PVA73FjuZG0U= +github.com/opentracing/opentracing-go v1.0.2 h1:3jA2P6O1F9UOrWVpwrIo17pu01KWvNWg4X946/Y5Zwg= +github.com/opentracing/opentracing-go v1.0.2/go.mod h1:UkNAQd3GIcIGf0SeVgPpRdFStlNbqXla1AfSYxPUl2o= +github.com/openzipkin/zipkin-go v0.1.1/go.mod h1:NtoC/o8u3JlF1lSlyPNswIbeQH9bJTmOf0Erfk+hxe8= +github.com/openzipkin/zipkin-go v0.1.3/go.mod h1:NtoC/o8u3JlF1lSlyPNswIbeQH9bJTmOf0Erfk+hxe8= +github.com/openzipkin/zipkin-go v0.1.6/go.mod h1:QgAqvLzwWbR/WpD4A3cGpPtJrZXNIiJc5AZX7/PBEpw= +github.com/ory-am/common v0.4.0 h1:edGPoxYX4hno0IJHXh9TCMUPR6ZcJp+y6aClFYxeuUE= +github.com/ory-am/common v0.4.0/go.mod h1:oCYGuwwM8FyYMKqh9vrhBaeUoyz/edx0bgJN6uS6/+k= +github.com/ory/dockertest v3.3.2+incompatible/go.mod h1:1vX4m9wsvi00u5bseYwXaSnhNrne+V0E6LAcBILJdPs= +github.com/ory/dockertest v3.3.4+incompatible h1:VrpM6Gqg7CrPm3bL4Wm1skO+zFWLbh7/Xb5kGEbJRh8= +github.com/ory/dockertest v3.3.4+incompatible/go.mod h1:1vX4m9wsvi00u5bseYwXaSnhNrne+V0E6LAcBILJdPs= +github.com/packethost/packngo v0.1.1-0.20180711074735-b9cb5096f54c h1:vwpFWvAO8DeIZfFeqASzZfsxuWPno9ncAebBEP0N3uE= +github.com/packethost/packngo v0.1.1-0.20180711074735-b9cb5096f54c/go.mod h1:otzZQXgoO96RTzDB/Hycg0qZcXZsWJGJRSXbmEIJ+4M= github.com/pascaldekloe/goe v0.0.0-20180627143212-57f6aae5913c/go.mod h1:lzWF7FIEvWOWxwDKqyGYQf6ZUaNfKdP144TG7ZOy1lc= +github.com/pascaldekloe/goe v0.1.0 h1:cBOtyMzM9HTpWjXfbbunk26uA6nG3a8n06Wieeh0MwY= +github.com/pascaldekloe/goe v0.1.0/go.mod h1:lzWF7FIEvWOWxwDKqyGYQf6ZUaNfKdP144TG7ZOy1lc= +github.com/patrickmn/go-cache v2.1.0+incompatible h1:HRMgzkcYKYpi3C8ajMPV8OFXaaRUnok+kx1WdO15EQc= +github.com/patrickmn/go-cache v2.1.0+incompatible/go.mod h1:3Qf8kWWT7OJRJbdiICTKqZju1ZixQ/KpMGzzAfe6+WQ= +github.com/pborman/uuid v1.2.0 h1:J7Q5mO4ysT1dv8hyrUGHb9+ooztCXu1D8MY8DZYsu3g= +github.com/pborman/uuid v1.2.0/go.mod h1:X/NO0urCmaxf9VXbdlT7C2Yzkj2IKimNn4k+gtPdI/k= +github.com/pelletier/go-buffruneio v0.2.0/go.mod h1:JkE26KsDizTr40EUHkXVtNPvgGtbSNq5BcowyYOWdKo= +github.com/pelletier/go-toml v1.2.0/go.mod h1:5z9KED0ma1S8pY6P1sdut58dfprrGBbd/94hg7ilaic= +github.com/peterbourgon/diskv v2.0.1+incompatible h1:UBdAOUP5p4RWqPBg048CAvpKN+vxiaj6gdUUzhl4XmI= +github.com/peterbourgon/diskv v2.0.1+incompatible/go.mod h1:uqqh8zWWbv1HBMNONnaR/tNboyR3/BZd58JJSHlUSCU= +github.com/philhofer/fwd v1.0.0/go.mod h1:gk3iGcWd9+svBvR0sR+KPcfE+RNWozjowpeBVG3ZVNU= +github.com/pierrec/lz4 v2.0.5+incompatible h1:2xWsjqPFWcplujydGg4WmhC/6fZqK42wMM8aXeqhl0I= +github.com/pierrec/lz4 v2.0.5+incompatible/go.mod h1:pdkljMzZIN41W+lC3N2tnIh5sFi+IEE17M5jbnwPHcY= +github.com/pkg/errors v0.8.0/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= github.com/pkg/errors v0.8.1 h1:iURUrRGxPUNPdy5/HRSm+Yj6okJ6UtLINN0Q9M4+h3I= github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= +github.com/pkg/term v0.0.0-20180730021639-bffc007b7fd5/go.mod h1:eCbImbZ95eXtAUIbLAuAVnBnwf83mjf6QIVH8SHYwqQ= +github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= github.com/posener/complete v1.1.1/go.mod h1:em0nMJCgc9GFtwrmVmEMR/ZL6WyhyjMBndrE9hABlRI= +github.com/posener/complete v1.2.1 h1:LrvDIY//XNo65Lq84G/akBuMGlawHvGBABv8f/ZN6DI= github.com/posener/complete v1.2.1/go.mod h1:6gapUrK/U1TAN7ciCoNRIdVC5sbdBTUh1DKN0g6uH7E= +github.com/pquerna/cachecontrol v0.0.0-20180517163645-1555304b9b35 h1:J9b7z+QKAmPf4YLrFg6oQUotqHQeUNWwkvo7jZp1GLU= +github.com/pquerna/cachecontrol v0.0.0-20180517163645-1555304b9b35/go.mod h1:prYjPmNq4d1NPVmpShWobRqXY3q7Vp+80DqgxxUrUIA= +github.com/pquerna/otp v1.1.0 h1:q2gMsMuMl3JzneUaAX1MRGxLvOG6bzXV51hivBaStf0= +github.com/pquerna/otp v1.1.0/go.mod h1:Zad1CMQfSQZI5KLpahDiSUX4tMMREnXw98IvL1nhgMk= +github.com/prometheus/client_golang v0.0.0-20171201122222-661e31bf844d/go.mod h1:7SWBe2y4D6OKWSNQJUaRYU/AaXPKyh/dDVn+NZz0KFw= +github.com/prometheus/client_golang v0.8.0/go.mod h1:7SWBe2y4D6OKWSNQJUaRYU/AaXPKyh/dDVn+NZz0KFw= +github.com/prometheus/client_golang v0.9.0/go.mod h1:7SWBe2y4D6OKWSNQJUaRYU/AaXPKyh/dDVn+NZz0KFw= +github.com/prometheus/client_golang v0.9.1/go.mod h1:7SWBe2y4D6OKWSNQJUaRYU/AaXPKyh/dDVn+NZz0KFw= +github.com/prometheus/client_golang v0.9.3-0.20190127221311-3c4408c8b829 h1:D+CiwcpGTW6pL6bv6KI3KbyEyCKyS+1JWS2h8PNDnGA= +github.com/prometheus/client_golang v0.9.3-0.20190127221311-3c4408c8b829/go.mod h1:p2iRAGwDERtqlqzRXnrOVns+ignqQo//hLXqYxZYVNs= +github.com/prometheus/client_model v0.0.0-20180712105110-5c3871d89910 h1:idejC8f05m9MGOsuEi1ATq9shN03HrxNkD/luQvxCv8= +github.com/prometheus/client_model v0.0.0-20180712105110-5c3871d89910/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo= +github.com/prometheus/client_model v0.0.0-20190115171406-56726106282f h1:BVwpUVJDADN2ufcGik7W992pyps0wZ888b/y9GXcLTU= +github.com/prometheus/client_model v0.0.0-20190115171406-56726106282f/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo= +github.com/prometheus/common v0.0.0-20180801064454-c7de2306084e/go.mod h1:daVV7qP5qjZbuso7PdcryaAu0sAZbrN9i7WWcTMWvro= +github.com/prometheus/common v0.0.0-20181020173914-7e9e6cabbd39/go.mod h1:daVV7qP5qjZbuso7PdcryaAu0sAZbrN9i7WWcTMWvro= +github.com/prometheus/common v0.2.0 h1:kUZDBDTdBVBYBj5Tmh2NZLlF60mfjA27rM34b+cVwNU= +github.com/prometheus/common v0.2.0/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y86RQel1bk4= +github.com/prometheus/procfs v0.0.0-20180725123919-05ee40e3a273/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk= +github.com/prometheus/procfs v0.0.0-20181005140218-185b4288413d/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk= +github.com/prometheus/procfs v0.0.0-20190117184657-bf6a532e95b1 h1:/K3IL0Z1quvmJ7X0A1AwNEK7CRkVK3YwfOU/QAL4WGg= +github.com/prometheus/procfs v0.0.0-20190117184657-bf6a532e95b1/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk= +github.com/rcrowley/go-metrics v0.0.0-20181016184325-3113b8401b8a/go.mod h1:bCqnVzQkZxMG4s8nGwiZ5l3QUCyqpo9Y+/ZMZ9VjZe4= +github.com/renier/xmlrpc v0.0.0-20170708154548-ce4a1a486c03 h1:Wdi9nwnhFNAlseAOekn6B5G/+GMtks9UKbvRU/CMM/o= +github.com/renier/xmlrpc v0.0.0-20170708154548-ce4a1a486c03/go.mod h1:gRAiPF5C5Nd0eyyRdqIu9qTiFSoZzpTq727b5B8fkkU= +github.com/rogpeppe/fastuuid v0.0.0-20150106093220-6724a57986af/go.mod h1:XWv6SoW27p1b0cqNHllgS5HIMJraePCO15w5zCzIWYg= +github.com/russross/blackfriday v1.5.2/go.mod h1:JO/DiYxRf+HjHt06OyowR9PTA263kcR/rfWxYHBV53g= github.com/ryanuber/columnize v0.0.0-20160712163229-9b3edd62028f/go.mod h1:sm1tb6uqfes/u+d4ooFouqFdy9/2g9QGwK3SQygK0Ts= github.com/ryanuber/columnize v2.1.0+incompatible/go.mod h1:sm1tb6uqfes/u+d4ooFouqFdy9/2g9QGwK3SQygK0Ts= +github.com/ryanuber/go-glob v0.0.0-20170128012129-256dc444b735/go.mod h1:807d1WSdnB0XRJzKNil9Om6lcp/3a0v4qIHxIXzX/Yc= +github.com/ryanuber/go-glob v1.0.0 h1:iQh3xXAumdQ+4Ufa5b25cRpC5TYKlno6hsv6Cb3pkBk= +github.com/ryanuber/go-glob v1.0.0/go.mod h1:807d1WSdnB0XRJzKNil9Om6lcp/3a0v4qIHxIXzX/Yc= +github.com/samuel/go-zookeeper v0.0.0-20180130194729-c4fab1ac1bec h1:6ncX5ko6B9LntYM0YBRXkiSaZMmLYeZ/NWcmeB43mMY= +github.com/samuel/go-zookeeper v0.0.0-20180130194729-c4fab1ac1bec/go.mod h1:gi+0XIa01GRL2eRQVjQkKGqKF3SF9vZR/HnPullcV2E= +github.com/satori/go.uuid v1.2.0 h1:0uYX9dsZ2yD7q2RtLRtPSdGDWzjeM3TbMJP9utgA0ww= +github.com/satori/go.uuid v1.2.0/go.mod h1:dA0hQrYB0VpLJoorglMZABFdXlWrHn1NEOzdhQKdks0= github.com/sean-/seed v0.0.0-20170313163322-e2103e2c3529 h1:nn5Wsu0esKSJiIVhscUtVbo7ada43DJhG55ua/hjS5I= github.com/sean-/seed v0.0.0-20170313163322-e2103e2c3529/go.mod h1:DxrIzT+xaE7yg65j358z/aeFdxmN0P9QXhEzd20vsDc= +github.com/segmentio/kafka-go v0.1.0/go.mod h1:X6itGqS9L4jDletMsxZ7Dz+JFWxM6JHfPOCvTvk+EJo= +github.com/sergi/go-diff v1.0.0/go.mod h1:0CfEIISq7TuYL3j771MWULgwwjU+GofnZX9QAmXWZgo= +github.com/shirou/gopsutil v2.18.12+incompatible h1:1eaJvGomDnH74/5cF4CTmTbLHAriGFsTZppLXDX93OM= +github.com/shirou/gopsutil v2.18.12+incompatible/go.mod h1:5b4v6he4MtMOwMlS0TUMTu2PcXUg8+E1lC7eC3UO/RA= +github.com/shirou/w32 v0.0.0-20160930032740-bb4de0191aa4 h1:udFKJ0aHUL60LboW/A+DfgoHVedieIzIXE8uylPue0U= +github.com/shirou/w32 v0.0.0-20160930032740-bb4de0191aa4/go.mod h1:qsXQc7+bwAM3Q1u/4XEfrquwF8Lw7D7y5cD8CuHnfIc= +github.com/shurcooL/component v0.0.0-20170202220835-f88ec8f54cc4/go.mod h1:XhFIlyj5a1fBNx5aJTbKoIq0mNaPvOagO+HjB3EtxrY= +github.com/shurcooL/events v0.0.0-20181021180414-410e4ca65f48/go.mod h1:5u70Mqkb5O5cxEA8nxTsgrgLehJeAw6Oc4Ab1c/P1HM= +github.com/shurcooL/github_flavored_markdown v0.0.0-20181002035957-2122de532470/go.mod h1:2dOwnU2uBioM+SGy2aZoq1f/Sd1l9OkAeAUvjSyvgU0= +github.com/shurcooL/go v0.0.0-20180423040247-9e1955d9fb6e/go.mod h1:TDJrrUr11Vxrven61rcy3hJMUqaf/CLWYhHNPmT14Lk= +github.com/shurcooL/go-goon v0.0.0-20170922171312-37c2f522c041/go.mod h1:N5mDOmsrJOB+vfqUK+7DmDyjhSLIIBnXo9lvZJj3MWQ= +github.com/shurcooL/gofontwoff v0.0.0-20180329035133-29b52fc0a18d/go.mod h1:05UtEgK5zq39gLST6uB0cf3NEHjETfB4Fgr3Gx5R9Vw= +github.com/shurcooL/gopherjslib v0.0.0-20160914041154-feb6d3990c2c/go.mod h1:8d3azKNyqcHP1GaQE/c6dDgjkgSx2BZ4IoEi4F1reUI= +github.com/shurcooL/highlight_diff v0.0.0-20170515013008-09bb4053de1b/go.mod h1:ZpfEhSmds4ytuByIcDnOLkTHGUI6KNqRNPDLHDk+mUU= +github.com/shurcooL/highlight_go v0.0.0-20181028180052-98c3abbbae20/go.mod h1:UDKB5a1T23gOMUJrI+uSuH0VRDStOiUVSjBTRDVBVag= +github.com/shurcooL/home v0.0.0-20181020052607-80b7ffcb30f9/go.mod h1:+rgNQw2P9ARFAs37qieuu7ohDNQ3gds9msbT2yn85sg= +github.com/shurcooL/htmlg v0.0.0-20170918183704-d01228ac9e50/go.mod h1:zPn1wHpTIePGnXSHpsVPWEktKXHr6+SS6x/IKRb7cpw= +github.com/shurcooL/httperror v0.0.0-20170206035902-86b7830d14cc/go.mod h1:aYMfkZ6DWSJPJ6c4Wwz3QtW22G7mf/PEgaB9k/ik5+Y= +github.com/shurcooL/httpfs v0.0.0-20171119174359-809beceb2371/go.mod h1:ZY1cvUeJuFPAdZ/B6v7RHavJWZn2YPVFQ1OSXhCGOkg= +github.com/shurcooL/httpgzip v0.0.0-20180522190206-b1c53ac65af9/go.mod h1:919LwcH0M7/W4fcZ0/jy0qGght1GIhqyS/EgWGH2j5Q= +github.com/shurcooL/issues v0.0.0-20181008053335-6292fdc1e191/go.mod h1:e2qWDig5bLteJ4fwvDAc2NHzqFEthkqn7aOZAOpj+PQ= +github.com/shurcooL/issuesapp v0.0.0-20180602232740-048589ce2241/go.mod h1:NPpHK2TI7iSaM0buivtFUc9offApnI0Alt/K8hcHy0I= +github.com/shurcooL/notifications v0.0.0-20181007000457-627ab5aea122/go.mod h1:b5uSkrEVM1jQUspwbixRBhaIjIzL2xazXp6kntxYle0= +github.com/shurcooL/octicon v0.0.0-20181028054416-fa4f57f9efb2/go.mod h1:eWdoE5JD4R5UVWDucdOPg1g2fqQRq78IQa9zlOV1vpQ= +github.com/shurcooL/reactions v0.0.0-20181006231557-f2e0b4ca5b82/go.mod h1:TCR1lToEk4d2s07G3XGfz2QrgHXg4RJBvjrOozvoWfk= +github.com/shurcooL/sanitized_anchor_name v0.0.0-20170918181015-86672fcb3f95/go.mod h1:1NzhyTcUVG4SuEtjjoZeVRXNmyL/1OwPU0+IJeTBvfc= +github.com/shurcooL/users v0.0.0-20180125191416-49c67e49c537/go.mod h1:QJTqeLYEDaXHZDBsXlPCDqdhQuJkuw4NOtaxYe3xii4= +github.com/shurcooL/webdavfs v0.0.0-20170829043945-18c3829fa133/go.mod h1:hKmq5kWdCj2z2KEozexVbfEZIWiTjhE0+UjmZgPqehw= +github.com/sirupsen/logrus v1.0.6 h1:hcP1GmhGigz/O7h1WVUM5KklBp1JoNS9FggWKdj/j3s= +github.com/sirupsen/logrus v1.0.6/go.mod h1:pMByvHTf9Beacp5x1UXfOR9xyW/9antXMhjMPG0dEzc= +github.com/sirupsen/logrus v1.2.0 h1:juTguoYk5qI21pwyTXY3B3Y5cOTH3ZUyZCg1v/mihuo= +github.com/sirupsen/logrus v1.2.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPxbbu5VWo= +github.com/smartystreets/assertions v0.0.0-20180820201707-7c9eb446e3cf h1:6V1qxN6Usn4jy8unvggSJz/NC790tefw8Zdy6OZS5co= +github.com/smartystreets/assertions v0.0.0-20180820201707-7c9eb446e3cf/go.mod h1:OnSkiWE9lh6wB0YB77sQom3nweQdgAjqCqsofrRNTgc= +github.com/smartystreets/assertions v0.0.0-20180927180507-b2de0cb4f26d h1:zE9ykElWQ6/NYmHa3jpm/yHnI4xSofP+UP6SpjHcSeM= +github.com/smartystreets/assertions v0.0.0-20180927180507-b2de0cb4f26d/go.mod h1:OnSkiWE9lh6wB0YB77sQom3nweQdgAjqCqsofrRNTgc= +github.com/smartystreets/goconvey v0.0.0-20180222194500-ef6db91d284a h1:JSvGDIbmil4Ui/dDdFBExb7/cmkNjyX5F97oglmvCDo= +github.com/smartystreets/goconvey v0.0.0-20180222194500-ef6db91d284a/go.mod h1:XDJAKZRPZ1CvBcN2aX5YOUTYGHki24fSF0Iv48Ibg0s= +github.com/softlayer/softlayer-go v0.0.0-20180806151055-260589d94c7d h1:bVQRCxQvfjNUeRqaY/uT0tFuvuFY0ulgnczuR684Xic= +github.com/softlayer/softlayer-go v0.0.0-20180806151055-260589d94c7d/go.mod h1:Cw4GTlQccdRGSEf6KiMju767x0NEHE0YIVPJSaXjlsw= +github.com/soheilhy/cmux v0.1.4 h1:0HKaf1o97UwFjHH9o5XsHUOF+tqmdA7KEzXLpiyaw0E= +github.com/soheilhy/cmux v0.1.4/go.mod h1:IM3LyeVVIOuxMH7sFAkER9+bJ4dT7Ms6E4xg4kGIyLM= +github.com/sourcegraph/annotate v0.0.0-20160123013949-f4cad6c6324d/go.mod h1:UdhH50NIW0fCiwBSr0co2m7BnFLdv4fQTgdqdJTHFeE= +github.com/sourcegraph/syntaxhighlight v0.0.0-20170531221838-bd320f5d308e/go.mod h1:HuIsMU8RRBOtsCgI77wP899iHVBQpCmg4ErYMZB+2IA= +github.com/spaolacci/murmur3 v0.0.0-20180118202830-f09979ecbc72/go.mod h1:JwIasOWyU6f++ZhiEuf87xNszmSA2myDM2Kzu9HwQUA= +github.com/spf13/afero v1.1.2/go.mod h1:j4pytiNVoe2o6bmDsKpLACNPDBIoEAkihy7loJ1B0CQ= +github.com/spf13/cast v1.2.0/go.mod h1:r2rcYCSwa1IExKTDiTfzaxqT2FNHs8hODu4LnUfgKEg= +github.com/spf13/cobra v0.0.3/go.mod h1:1l0Ry5zgKvJasoi3XT1TypsSe7PqH0Sj9dhYf7v3XqQ= +github.com/spf13/jwalterweatherman v1.0.0/go.mod h1:cQK4TGJAtQXfYWX+Ddv3mKDzgVb68N+wFjFa4jdeBTo= +github.com/spf13/pflag v1.0.2 h1:Fy0orTDgHdbnzHcsOgfCN4LtHf0ec3wwtiwJqwvf3Gc= +github.com/spf13/pflag v1.0.2/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4= +github.com/spf13/pflag v1.0.3 h1:zPAT6CGy6wXeQ7NtTnaTerfKOsV6V6F8agHXFiazDkg= +github.com/spf13/pflag v1.0.3/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4= +github.com/spf13/viper v1.2.1/go.mod h1:P4AexN0a+C9tGAnUFNwDMYYZv3pjFuvmeiMyKRaNVlI= +github.com/src-d/gcfg v1.4.0/go.mod h1:p/UMsR43ujA89BJY9duynAwIpvqEujIH/jFlfL7jWoI= +github.com/stevvooe/resumable v0.0.0-20180830230917-22b14a53ba50/go.mod h1:1pdIZTAHUz+HDKDVZ++5xg/duPlhKAIzw9qy42CWYp4= +github.com/streadway/amqp v0.0.0-20190312223743-14f78b41ce6d h1:ToACqFOOYVdz7PswtVcAawttvtdGlLhoAsXdhYFQeEI= +github.com/streadway/amqp v0.0.0-20190312223743-14f78b41ce6d/go.mod h1:AZpEONHx3DKn8O/DFsRAY58/XVQiIPMTMB1SddzLXVw= github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= +github.com/stretchr/objx v0.1.1 h1:2vfRuCMp5sSVIDSqO8oNnWJq7mPa6KVP3iPIwFBuy8A= github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= +github.com/stretchr/testify v1.2.0/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= +github.com/stretchr/testify v1.2.1/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= +github.com/stretchr/testify v1.3.0 h1:TivCn/peBQ7UY8ooIcPgZFpTNSz0Q2U6UrFlUfqbe0Q= github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= +github.com/tarm/serial v0.0.0-20180830185346-98f6abe2eb07/go.mod h1:kDXzergiv9cbyO7IOYJZWg1U88JhDg3PB6klq9Hg2pA= +github.com/tcnksm/go-input v0.0.0-20180404061846-548a7d7a8ee8/go.mod h1:IlWNj9v/13q7xFbaK4mbyzMNwrZLaWSHx/aibKIZuIg= +github.com/tent/http-link-go v0.0.0-20130702225549-ac974c61c2f9 h1:/Bsw4C+DEdqPjt8vAqaC9LAqpAQnaCQQqmolqq3S1T4= +github.com/tent/http-link-go v0.0.0-20130702225549-ac974c61c2f9/go.mod h1:RHkNRtSLfOK7qBTHaeSX1D6BNpI3qw7NTxsmNr4RvN8= +github.com/testcontainers/testcontainer-go v0.0.0-20181115231424-8e868ca12c0f/go.mod h1:SrG3IY071gtmZJjGbKO+POJ57a/MMESerYNWt6ZRtKs= +github.com/tinylib/msgp v1.0.2/go.mod h1:+d+yLhGm8mzTaHzB+wgMYrodPfmZrzkirds8fDWklFE= +github.com/tmc/grpc-websocket-proxy v0.0.0-20190109142713-0ad062ec5ee5 h1:LnC5Kc/wtumK+WB441p7ynQJzVuNRJiqddSIE3IlSEQ= +github.com/tmc/grpc-websocket-proxy v0.0.0-20190109142713-0ad062ec5ee5/go.mod h1:ncp9v5uamzpCO7NfCPTXjqaC+bZgJeR0sMTm6dMHP7U= +github.com/tv42/httpunix v0.0.0-20150427012821-b75d8614f926 h1:G3dpKMzFDjgEh2q1Z7zUUtKa8ViPtH+ocF0bE0g00O8= +github.com/tv42/httpunix v0.0.0-20150427012821-b75d8614f926/go.mod h1:9ESjWnEqriFuLhtthL60Sar/7RFoluCcXsuvEwTV5KM= +github.com/tylerb/graceful v1.2.15/go.mod h1:LPYTbOYmUTdabwRt0TGhLllQ0MUNbs0Y5q1WXJOI9II= +github.com/ugorji/go v1.1.2 h1:JON3E2/GPW2iDNGoSAusl1KDf5TRQ8k8q7Tp097pZGs= +github.com/ugorji/go v1.1.2/go.mod h1:hnLbHMwcvSihnDhEfx2/BzKp2xb0Y+ErdfYcrs9tkJQ= +github.com/ugorji/go/codec v0.0.0-20190320090025-2dc34c0b8780 h1:vG/gY/PxA3v3l04qxe3tDjXyu3bozii8ulSlIPOYKhI= +github.com/ugorji/go/codec v0.0.0-20190320090025-2dc34c0b8780/go.mod h1:iT03XoTwV7xq/+UGwKO3UbC1nNNlopQiY61beSdrtOA= +github.com/vmware/govmomi v0.18.0 h1:f7QxSmP7meCtoAmiKZogvVbLInT+CZx6Px6K5rYsJZo= +github.com/vmware/govmomi v0.18.0/go.mod h1:URlwyTFZX72RmxtxuaFL2Uj3fD1JTvZdx59bHWk6aFU= +github.com/vmware/vic v1.4.1 h1:Cbvv5y2h1YlYebIYGuVp1Xk5imxPSDUF6c0O5oLdQ00= +github.com/vmware/vic v1.4.1/go.mod h1:AiTDrZuV13NkqRzseA5ZmF2QqLpTydaaGN75xgV6Ork= +github.com/willf/bitset v1.1.9/go.mod h1:RjeCKbqT1RxIR/KWY6phxZiaY1IyutSBfGjNPySAYV4= +github.com/xanzy/ssh-agent v0.2.0/go.mod h1:0NyE30eGUDliuLEHJgYte/zncp2zdTStcOnWhgSqHD8= +github.com/xiang90/probing v0.0.0-20190116061207-43a291ad63a2 h1:eY9dn8+vbi4tKz5Qo6v2eYzo7kUS51QINcR5jNpbZS8= +github.com/xiang90/probing v0.0.0-20190116061207-43a291ad63a2/go.mod h1:UETIi67q53MR2AWcXfiuqkDkRtnGDLqkBTpCHuJHxtU= +github.com/yudai/gojsondiff v1.0.0/go.mod h1:AY32+k2cwILAkW1fbgxQ5mUmMiZFgLIV+FBNExI05xg= +github.com/yudai/golcs v0.0.0-20170316035057-ecda9a501e82/go.mod h1:lgjkn3NuSvDfVJdfcVVdX+jpBxNmX4rDAzaS45IcYoM= +github.com/yudai/pp v2.0.1+incompatible/go.mod h1:PuxR/8QJ7cyCkFp/aUDS+JY727OFEZkTdatxwunjIkc= +go.opencensus.io v0.18.0/go.mod h1:vKdFvxhtzZ9onBp9VKHK8z/sRpBMnKAsufL7wlDrCOA= +go.opencensus.io v0.19.1/go.mod h1:gug0GbSHa8Pafr0d2urOSgoXHZ6x/RUlaiT0d9pqb4A= +go.opencensus.io v0.19.2 h1:ZZpq6xI6kv/LuE/5s5UQvBU5vMjvRnPb8PvJrIntAnc= +go.opencensus.io v0.19.2/go.mod h1:NO/8qkisMZLZ1FCsKNqtJPwc8/TaclWyY0B6wcYNg9M= +go.uber.org/atomic v1.3.2 h1:2Oa65PReHzfn29GpvgsYwloV9AVFHPDk8tYxt2c2tr4= +go.uber.org/atomic v1.3.2/go.mod h1:gD2HeocX3+yG+ygLZcrzQJaqmWj9AIm7n08wl/qW/PE= +go.uber.org/multierr v1.1.0 h1:HoEmRHQPVSqub6w2z2d2EOVs2fjyFRGyofhKuyDq0QI= +go.uber.org/multierr v1.1.0/go.mod h1:wR5kodmAFQ0UK8QlbwjlSNy0Z68gJhDJUG5sjR94q/0= +go.uber.org/zap v1.9.1 h1:XCJQEf3W6eZaVwhRBof6ImoYGJSITeKWsyeh3HFu/5o= +go.uber.org/zap v1.9.1/go.mod h1:vwi/ZaCAaUcBkycHslxD9B2zi4UTXhF60s6SWpuDF0Q= +go4.org v0.0.0-20180809161055-417644f6feb5/go.mod h1:MkTOUMDaeVYJUOUsaDXIhWPZYa1yOyC1qaOBpL57BhE= +golang.org/x/build v0.0.0-20190111050920-041ab4dc3f9d/go.mod h1:OWs+y06UdEOHN4y+MfF/py+xQ/tYqIWW03b70/CG9Rw= +golang.org/x/crypto v0.0.0-20180505025534-4ec37c66abab/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= +golang.org/x/crypto v0.0.0-20180820150726-614d502a4dac/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= +golang.org/x/crypto v0.0.0-20180904163835-0709b304e793/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= golang.org/x/crypto v0.0.0-20181029021203-45a5f77698d3/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= +golang.org/x/crypto v0.0.0-20181030102418-4d3f4d9ffa16/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= +golang.org/x/crypto v0.0.0-20181203042331-505ab145d0a9/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= golang.org/x/crypto v0.0.0-20190130090550-b01c7a725664/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= -golang.org/x/crypto v0.0.0-20190131182504-b8fe1690c613 h1:MQ/ZZiDsUapFFiMS+vzwXkCTeEKaum+Do5rINYJDmxc= -golang.org/x/crypto v0.0.0-20190131182504-b8fe1690c613/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= golang.org/x/crypto v0.0.0-20190211182817-74369b46fc67 h1:ng3VDlRp5/DHpSWl02R4rM9I+8M2rhmsuLwAMmkLQWE= golang.org/x/crypto v0.0.0-20190211182817-74369b46fc67/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= golang.org/x/crypto v0.0.0-20190222235706-ffb98f73852f h1:qWFY9ZxP3tfI37wYIs/MnIAqK0vlXp1xnYEa5HxFSSY= golang.org/x/crypto v0.0.0-20190222235706-ffb98f73852f/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= +golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= +golang.org/x/crypto v0.0.0-20190325154230-a5d413f7728c h1:Vj5n4GlwjmQteupaxJ9+0FNOmBrHfq7vN4btdGoDZgI= +golang.org/x/crypto v0.0.0-20190325154230-a5d413f7728c/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= +golang.org/x/exp v0.0.0-20180321215751-8460e604b9de/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= +golang.org/x/exp v0.0.0-20181112044915-a3060d491354/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= +golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= +golang.org/x/lint v0.0.0-20180702182130-06c8688daad7/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE= +golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE= +golang.org/x/lint v0.0.0-20181217174547-8f45f776aaf1/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE= +golang.org/x/lint v0.0.0-20190227174305-5b3e6a55c961/go.mod h1:wehouNa3lNwaWXcvxsM5YxQ5yQlVC4a0KAMCusXpPoU= +golang.org/x/lint v0.0.0-20190301231843-5614ed5bae6f/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE= +golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20181023162649-9b4f9f5ad519/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/net v0.0.0-20181029044818-c44066c5c816/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/net v0.0.0-20181106065722-10aee1819953/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/net v0.0.0-20181114220301-adae6a3d119a/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20181201002055-351d144fa1fc/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/net v0.0.0-20181220203305-927f97764cc3/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/net v0.0.0-20190108225652-1e06a53dbb7e/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20190125091013-d26f9f9a57f3/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= -golang.org/x/net v0.0.0-20190206173232-65e2d4e15006 h1:bfLnR+k0tq5Lqt6dflRLcZiz6UaXCMt3vhYJ1l4FQ80= -golang.org/x/net v0.0.0-20190206173232-65e2d4e15006/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20190213061140-3a22650c66bd h1:HuTn7WObtcDo9uEEU7rEqL0jYthdXAmZ6PP+meazmaU= golang.org/x/net v0.0.0-20190213061140-3a22650c66bd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= +golang.org/x/net v0.0.0-20190327214358-63eda1eb0650 h1:XCbwcsP09zrBt1aYht0fASw+ynbEpYr8NnCkIN9nMM0= +golang.org/x/net v0.0.0-20190327214358-63eda1eb0650/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= +golang.org/x/oauth2 v0.0.0-20170807180024-9a379c6b3e95/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= +golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be h1:vEDujvNQGv4jgYKudGeI/+DAX4Jffq6hpD55MmoEvKs= +golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= +golang.org/x/oauth2 v0.0.0-20181017192945-9dcd33a902f4/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= +golang.org/x/oauth2 v0.0.0-20181203162652-d668ce993890/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= +golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= +golang.org/x/oauth2 v0.0.0-20190319182350-c85d3e98c914 h1:jIOcLT9BZzyJ9ce+IwwZ+aF9yeCqzrR+NrD68a/SHKw= +golang.org/x/oauth2 v0.0.0-20190319182350-c85d3e98c914/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= +golang.org/x/perf v0.0.0-20180704124530-6e6d33e29852/go.mod h1:JLpeXjPJfIyPr5TlbXLkXWLhP8nz10XfvxElABhCtcw= +golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20190227155943-e225da77a7e6 h1:bjcUS9ztw9kFmmIxJInhon/0Is3p+EHBKNgquIzo1OI= +golang.org/x/sync v0.0.0-20190227155943-e225da77a7e6/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sys v0.0.0-20180823144017-11551d06cbcc/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20180828065106-d99a578cf41b/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20180903190138-2b024373dcd9/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20180906133057-8cf3aee42992/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20180909124046-d0be0721c37e/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20181026203630-95b1ffbd15a5/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20181029174526-d69651ed3497/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20181030150119-7e31e0c00fa0/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20181107165924-66b7b1311ac8/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20181116152217-5ac8a444bdc5/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20181122145206-62eef0e2fa9b/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20181205085412-a5c9d58dba9a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20181218192612-074acd46bca6/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190129075346-302c3dd5f1cc/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= -golang.org/x/sys v0.0.0-20190204203706-41f3e6584952 h1:FDfvYgoVsA7TTZSbgiqjAbfPbK47CNHdWl3h/PJtii0= -golang.org/x/sys v0.0.0-20190204203706-41f3e6584952/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= -golang.org/x/sys v0.0.0-20190209173611-3b5209105503 h1:5SvYFrOM3W8Mexn9/oA44Ji7vhXAZQ9hiP+1Q/DMrWg= -golang.org/x/sys v0.0.0-20190209173611-3b5209105503/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190213121743-983097b1a8a3 h1:+KlxhGbYkFs8lMfwKn+2ojry1ID5eBSMXprS2u/wqCE= golang.org/x/sys v0.0.0-20190213121743-983097b1a8a3/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190222072716-a9d3bda3a223/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190222171317-cd391775e71e h1:oF7qaQxUH6KzFdKN4ww7NpPdo53SZi4UlcksLrb2y/o= golang.org/x/sys v0.0.0-20190222171317-cd391775e71e/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20190322080309-f49334f85ddc h1:4gbWbmmPFp4ySWICouJl6emP0MyS31yy9SrTlAGFT+g= +golang.org/x/sys v0.0.0-20190322080309-f49334f85ddc/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/text v0.3.0 h1:g61tztE5qeGQ89tm6NTjjM9VPIm088od1l6aSorWRWg= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= +golang.org/x/text v0.3.1-0.20180807135948-17ff2d5776d2 h1:z99zHgr7hKfrUcX/KsoJk5FJfjTceCKIp96+biqP4To= +golang.org/x/text v0.3.1-0.20180807135948-17ff2d5776d2/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= +golang.org/x/time v0.0.0-20180412165947-fbb02b2291d2/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= +golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= +golang.org/x/time v0.0.0-20190308202827-9d24e82272b4 h1:SvFZT6jyqRaOeXpc5h/JSfZenJ2O330aBsf7JfSUXmQ= +golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= +golang.org/x/tools v0.0.0-20180221164845-07fd8470d635/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= +golang.org/x/tools v0.0.0-20180525024113-a5b4c53f6e8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= +golang.org/x/tools v0.0.0-20180828015842-6cd1fcedba52/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= +golang.org/x/tools v0.0.0-20181030000716-a0a13e073c7b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= +golang.org/x/tools v0.0.0-20181219222714-6e267b5cc78e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= +golang.org/x/tools v0.0.0-20181221154417-3ad2d988d5e2/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= +golang.org/x/tools v0.0.0-20190114222345-bf090417da8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= +golang.org/x/tools v0.0.0-20190226205152-f727befe758c/go.mod h1:9Yl7xja0Znq3iFh3HoIrodX9oNMXvdceNzlUR8zjMvY= +golang.org/x/tools v0.0.0-20190312170243-e65039ee4138/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= +gonum.org/v1/gonum v0.0.0-20181121035319-3f7ecaa7e8ca/go.mod h1:Y+Yx5eoAFn32cQvJDxZx5Dpnq+c3wtXuadVZAcxbbBo= +gonum.org/v1/netlib v0.0.0-20181029234149-ec6d1f5cefe6/go.mod h1:wa6Ws7BG/ESfp6dHfk7C6KdzKA7wR7u/rKwOGE66zvw= +google.golang.org/api v0.0.0-20180829000535-087779f1d2c9 h1:z1TeLUmxf9ws9KLICfmX+KGXTs+rjm+aGWzfsv7MZ9w= +google.golang.org/api v0.0.0-20180829000535-087779f1d2c9/go.mod h1:4mhQ8q/RsB7i+udVvVy5NUi08OU8ZlA0gRVgrF7VFY0= +google.golang.org/api v0.0.0-20180910000450-7ca32eb868bf/go.mod h1:4mhQ8q/RsB7i+udVvVy5NUi08OU8ZlA0gRVgrF7VFY0= +google.golang.org/api v0.0.0-20181021000519-a2651947f503/go.mod h1:4mhQ8q/RsB7i+udVvVy5NUi08OU8ZlA0gRVgrF7VFY0= +google.golang.org/api v0.0.0-20181030000543-1d582fd0359e/go.mod h1:4mhQ8q/RsB7i+udVvVy5NUi08OU8ZlA0gRVgrF7VFY0= +google.golang.org/api v0.0.0-20181220000619-583d854617af/go.mod h1:4mhQ8q/RsB7i+udVvVy5NUi08OU8ZlA0gRVgrF7VFY0= +google.golang.org/api v0.1.0/go.mod h1:UGEZY7KEX120AnNLIHFMKIo4obdJhkp2tPbaPlQx13Y= +google.golang.org/api v0.2.0/go.mod h1:IfRCZScioGtypHNTlz3gFk67J8uePVW7uDTBzXuIkhU= +google.golang.org/api v0.3.0 h1:UIJY20OEo3+tK5MBlcdx37kmdH6EnRjGkW78mc6+EeA= +google.golang.org/api v0.3.0/go.mod h1:IuvZyQh8jgscv8qWfQ4ABd8m7hEudgBFM/EdhA3BnXw= +google.golang.org/appengine v1.1.0 h1:igQkv0AAhEIvTEpD5LIpAfav2eeVO9HBTjvKHVJPRSs= +google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM= +google.golang.org/appengine v1.2.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= +google.golang.org/appengine v1.3.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= +google.golang.org/appengine v1.4.0 h1:/wp5JvzpHIxhs/dumFmF7BXTf3Z+dd4uXta4kVyO508= +google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= +google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8 h1:Nw54tB0rB7hY/N0NQvRW8DG4Yk3Q6T9cu9RcFQDu1tc= +google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc= +google.golang.org/genproto v0.0.0-20180831171423-11092d34479b/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc= +google.golang.org/genproto v0.0.0-20181016170114-94acd270e44e/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc= +google.golang.org/genproto v0.0.0-20181029155118-b69ba1387ce2/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc= +google.golang.org/genproto v0.0.0-20181202183823-bd91e49a0898/go.mod h1:7Ep/1NZk928CDR8SjdVbjWNpdIf6nzjE3BTgJDr2Atg= +google.golang.org/genproto v0.0.0-20181219182458-5a97ab628bfb/go.mod h1:7Ep/1NZk928CDR8SjdVbjWNpdIf6nzjE3BTgJDr2Atg= +google.golang.org/genproto v0.0.0-20190201180003-4b09977fb922/go.mod h1:L3J43x8/uS+qIUoksaLKe6OS3nUKxOKuIFz1sl2/jx4= +google.golang.org/genproto v0.0.0-20190307195333-5fe7a883aa19 h1:Lj2SnHtxkRGJDqnGaSjo+CCdIieEnwVazbOXILwQemk= +google.golang.org/genproto v0.0.0-20190307195333-5fe7a883aa19/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= +google.golang.org/grpc v1.14.0/go.mod h1:yo6s7OP7yaDglbqo1J04qKzAhqBH6lvTonzMVmEdcZw= +google.golang.org/grpc v1.15.0/go.mod h1:0JHn/cJsOMiMfNA9+DeHDlAU7KAAB5GDlYFpa9MZMio= +google.golang.org/grpc v1.16.0/go.mod h1:0JHn/cJsOMiMfNA9+DeHDlAU7KAAB5GDlYFpa9MZMio= +google.golang.org/grpc v1.17.0/go.mod h1:6QZJwpn2B+Zp71q/5VxRsJ6NXXVCE5NRUHRo+f3cWCs= +google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c= +google.golang.org/grpc v1.19.1 h1:TrBcJ1yqAl1G++wO39nD/qtgpsW9/1+QGrluyMGEYgM= +google.golang.org/grpc v1.19.1/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c= +gopkg.in/airbrake/gobrake.v2 v2.0.9 h1:7z2uVWwn7oVeeugY1DtlPAy5H+KYgB1KeKTnqjNatLo= +gopkg.in/airbrake/gobrake.v2 v2.0.9/go.mod h1:/h5ZAUhDkGaJfjzjKLSjv6zCL6O0LLBxU4K+aSYdM/U= +gopkg.in/alecthomas/kingpin.v2 v2.2.6/go.mod h1:FMv+mEhP44yOT+4EoQTLFTRgOQ1FBLkstjWtayDeSgw= +gopkg.in/asn1-ber.v1 v1.0.0-20170511165959-379148ca0225/go.mod h1:cuepJuh7vyXfUyUwEgHQXw849cJrilpS5NeIjOWESAw= +gopkg.in/asn1-ber.v1 v1.0.0-20181015200546-f715ec2f112d h1:TxyelI5cVkbREznMhfzycHdkp5cLA7DpE+GKjSslYhM= +gopkg.in/asn1-ber.v1 v1.0.0-20181015200546-f715ec2f112d/go.mod h1:cuepJuh7vyXfUyUwEgHQXw849cJrilpS5NeIjOWESAw= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127 h1:qIbj1fsPNlZgppZ+VLlY7N33q108Sa+fhmuc+sWQYwY= gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/fatih/pool.v2 v2.0.0 h1:xIFeWtxifuQJGk/IEPKsTduEKcKvPmhoiVDGpC40nKg= +gopkg.in/fatih/pool.v2 v2.0.0/go.mod h1:8xVGeu1/2jr2wm5V9SPuMht2H5AEmf5aFMGSQixtjTY= +gopkg.in/fsnotify.v1 v1.4.7 h1:xOHLXZwVvI9hhs+cLKq5+I5onOuwQLhQwiu63xxlHs4= +gopkg.in/fsnotify.v1 v1.4.7/go.mod h1:Tz8NjZHkW78fSQdbUxIjBTcgA1z1m8ZHf0WmKUhAMys= +gopkg.in/gemnasium/logrus-airbrake-hook.v2 v2.1.2 h1:OAj3g0cR6Dx/R07QgQe8wkA9RNjB2u4i700xBkIT4e0= +gopkg.in/gemnasium/logrus-airbrake-hook.v2 v2.1.2/go.mod h1:Xk6kEKp8OKb+X14hQBKWaSkCsqBpgog8nAV2xsGOxlo= +gopkg.in/gorethink/gorethink.v4 v4.1.0 h1:xoE9qJ9Ae9KdKEsiQGCF44u2JdnjyohrMBRDtts3Gjw= +gopkg.in/gorethink/gorethink.v4 v4.1.0/go.mod h1:M7JgwrUAmshJ3iUbEK0Pt049MPyPK+CYDGGaEjdZb/c= +gopkg.in/inf.v0 v0.9.1 h1:73M5CoZyi3ZLMOyDlQh031Cx6N9NDJ2Vvfl76EDAgDc= +gopkg.in/inf.v0 v0.9.1/go.mod h1:cWUDdTG/fYaXco+Dcufb5Vnc6Gp2YChqWtbxRZE0mXw= +gopkg.in/ini.v1 v1.42.0 h1:7N3gPTt50s8GuLortA00n8AqRTk75qOP98+mTPpgzRk= +gopkg.in/ini.v1 v1.42.0/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k= +gopkg.in/ldap.v2 v2.5.1/go.mod h1:oI0cpe/D7HRtBQl8aTg+ZmzFUAvu4lsv3eLXMLGFxWk= +gopkg.in/mgo.v2 v2.0.0-20180705113604-9856a29383ce h1:xcEWjVhvbDy+nHP67nPDDpbYrY+ILlfndk4bRioVHaU= +gopkg.in/mgo.v2 v2.0.0-20180705113604-9856a29383ce/go.mod h1:yeKp02qBN3iKW1OzL3MGk2IdtZzaj7SFntXj72NppTA= +gopkg.in/ory-am/dockertest.v2 v2.2.3 h1:vSYvP7tvyfAm9merq0gHmcI4yk5nkPpfXmoBCnSP3/4= +gopkg.in/ory-am/dockertest.v2 v2.2.3/go.mod h1:kDHEsan1UcKFYH1c28sDmqnmeqIpB4Nj682gSNhYDYM= +gopkg.in/resty.v1 v1.12.0/go.mod h1:mDo4pnntr5jdWRML875a/NmxYqAlA73dVijT2AXvQQo= +gopkg.in/robfig/cron.v2 v2.0.0-20150107220207-be2e0b0deed5/go.mod h1:hiOFpYm0ZJbusNj2ywpbrXowU3G8U6GIQzqn2mw1UIE= +gopkg.in/square/go-jose.v2 v2.3.0 h1:nLzhkFyl5bkblqYBoiWJUt5JkWOzmiaBtCxdJAqJd3U= +gopkg.in/square/go-jose.v2 v2.3.0/go.mod h1:M9dMgbHiYLoDGQrXy7OpJDJWiKiU//h+vD76mk0e1AI= +gopkg.in/src-d/go-billy.v4 v4.2.1/go.mod h1:tm33zBoOwxjYHZIE+OV8bxTWFMJLrconzFMd38aARFk= +gopkg.in/src-d/go-git-fixtures.v3 v3.1.1/go.mod h1:dLBcvytrw/TYZsNTWCnkNF2DSIlzWYqTe3rJR56Ac7g= +gopkg.in/src-d/go-git.v4 v4.8.1/go.mod h1:Vtut8izDyrM8BUVQnzJ+YvmNcem2J89EmfZYCkLokZk= +gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7 h1:uRGJdciOHaEIrze2W8Q3AKkepLTh2hOroT7a+7czfdQ= +gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7/go.mod h1:dt/ZhP58zS4L8KSrWDmTeBkI65Dw0HsyUHuEVlX15mw= +gopkg.in/vmihailenco/msgpack.v2 v2.9.1/go.mod h1:/3Dn1Npt9+MYyLpYYXjInO/5jvMLamn+AEGwNEOatn8= +gopkg.in/warnings.v0 v0.1.2/go.mod h1:jksf8JmL6Qr/oQM2OXTHunEvvTAsrWBLb6OOjuVWRNI= +gopkg.in/yaml.v2 v2.0.0-20170812160011-eb3733d160e7/go.mod h1:JAlM8MvJe8wmxCU4Bli9HhUf9+ttbYbLASfIpnQbh74= +gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= +gopkg.in/yaml.v2 v2.2.2 h1:ZCJp+EgiOT7lHqUV2J862kp8Qj64Jo6az82+3Td9dZw= gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= +gotest.tools v2.2.0+incompatible h1:VsBPFP1AI068pPrMxtb/S8Zkgf9xEmTLJjfM+P5UIEo= +gotest.tools v2.2.0+incompatible/go.mod h1:DsYFclhRJ6vuDpmuTbkuFWG+y2sxOXAzmJt81HFBacw= +grpc.go4.org v0.0.0-20170609214715-11d0a25b4919/go.mod h1:77eQGdRu53HpSqPFJFmuJdjuHRquDANNeA4x7B8WQ9o= +honnef.co/go/tools v0.0.0-20180728063816-88497007e858/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= +honnef.co/go/tools v0.0.0-20180920025451-e3ad64cb4ed3/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= +honnef.co/go/tools v0.0.0-20181108184350-ae8f1f9103cc/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= +honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= +honnef.co/go/tools v0.0.0-20190106161140-3f1c8253044a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= +k8s.io/api v0.0.0-20180806132203-61b11ee65332 h1:+ED/2NBbOoeWB9QrGTHxZI7UnE7rnHPKKumOl0WXphs= +k8s.io/api v0.0.0-20180806132203-61b11ee65332/go.mod h1:iuAfoD4hCxJ8Onx9kaTIt30j7jUFS00AXQi6QMi99vA= +k8s.io/apimachinery v0.0.0-20180821005732-488889b0007f h1:V0PkbgaYp5JqCmzLyRmssDtzim0NShXM8gYi4fcX230= +k8s.io/apimachinery v0.0.0-20180821005732-488889b0007f/go.mod h1:ccL7Eh7zubPUSh9A3USN90/OzHNSVN6zxzde07TDCL0= +k8s.io/client-go v8.0.0+incompatible h1:tTI4hRmb1DRMl4fG6Vclfdi6nTM82oIrTT7HfitmxC4= +k8s.io/client-go v8.0.0+incompatible/go.mod h1:7vJpHMYJwNQCWgzmNV+VYUl1zCObLyodBc8nIyt8L5s= +layeh.com/radius v0.0.0-20190322222518-890bc1058917 h1:BDXFaFzUt5EIqe/4wrTc4AcYZWP6iC6Ult+jQWLh5eU= +layeh.com/radius v0.0.0-20190322222518-890bc1058917/go.mod h1:fywZKyu//X7iRzaxLgPWsvc0L26IUpVvE/aeIL2JtIQ= +sourcegraph.com/sourcegraph/go-diff v0.5.0/go.mod h1:kuch7UrkMzY0X+p9CRK03kfuPQ2zzQcaEFbx8wA8rck= +sourcegraph.com/sqs/pbtypes v0.0.0-20180604144634-d3ebe8f20ae4/go.mod h1:ketZ/q3QxT9HOBeFhu6RdvsftgpsbFHBF5Cas6cDKZ0= From f824ba07797d93fc8877b7dd31bb0ef913524e02 Mon Sep 17 00:00:00 2001 From: Asim Aslam Date: Thu, 18 Apr 2019 09:05:22 +0000 Subject: [PATCH 178/196] non-blocking call chan when retries are 0 --- client/rpc_client.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/client/rpc_client.go b/client/rpc_client.go index 0e05dae9..e02744e2 100644 --- a/client/rpc_client.go +++ b/client/rpc_client.go @@ -382,7 +382,7 @@ func (r *rpcClient) Call(ctx context.Context, request Request, response interfac return err } - ch := make(chan error, callOpts.Retries) + ch := make(chan error, callOpts.Retries+1) var gerr error for i := 0; i <= callOpts.Retries; i++ { @@ -463,7 +463,7 @@ func (r *rpcClient) Stream(ctx context.Context, request Request, opts ...CallOpt err error } - ch := make(chan response, callOpts.Retries) + ch := make(chan response, callOpts.Retries+1) var grr error for i := 0; i <= callOpts.Retries; i++ { From fd2ca3a13a7707accf0c9be353676e4f9762a188 Mon Sep 17 00:00:00 2001 From: tongjichao <784172931@qq.com> Date: Fri, 19 Apr 2019 00:05:02 +0800 Subject: [PATCH 179/196] fix: client retries will be 0 when not set fix: client retries will be 0 when not set --- cmd/cmd.go | 1 + 1 file changed, 1 insertion(+) diff --git a/cmd/cmd.go b/cmd/cmd.go index f1e80a4a..c4987dbf 100644 --- a/cmd/cmd.go +++ b/cmd/cmd.go @@ -71,6 +71,7 @@ var ( cli.IntFlag{ Name: "client_retries", EnvVar: "MICRO_CLIENT_RETRIES", + Value: client.DefaultRetries, Usage: "Sets the client retries. Default: 1", }, cli.IntFlag{ From c43d7137cf3d35ea3b6e0f0e3b61f9fd77156a05 Mon Sep 17 00:00:00 2001 From: lixiaohui Date: Mon, 22 Apr 2019 21:39:02 +0800 Subject: [PATCH 180/196] cleanup deps --- go.mod | 126 ++++++--------- go.sum | 500 +++++++++++++++++++++++---------------------------------- 2 files changed, 254 insertions(+), 372 deletions(-) diff --git a/go.mod b/go.mod index bf225bbf..ecd63681 100644 --- a/go.mod +++ b/go.mod @@ -1,94 +1,73 @@ module github.com/micro/go-micro require ( - cloud.google.com/go v0.36.0 // indirect - github.com/DataDog/datadog-go v0.0.0-20190323183505-07c7c350327b // indirect + github.com/Azure/go-ansiterm v0.0.0-20170929234023-d6e3b3328b78 // indirect + github.com/DataDog/datadog-go v2.2.0+incompatible // indirect github.com/Microsoft/go-winio v0.4.12 // indirect github.com/NYTimes/gziphandler v1.1.1 // indirect + github.com/Nvveen/Gotty v0.0.0-20120604004816-cd527374f1e5 // indirect github.com/SAP/go-hdb v0.14.1 // indirect github.com/StackExchange/wmi v0.0.0-20181212234831-e0a55b97c705 // indirect - github.com/aliyun/alibaba-cloud-sdk-go v0.0.0-20190328075325-5887fb5d0027 // indirect github.com/araddon/gou v0.0.0-20190110011759-c797efecbb61 // indirect - github.com/aws/aws-sdk-go v1.17.5 // indirect + github.com/asaskevich/govalidator v0.0.0-20180720115003-f9ffefc3facf // indirect + github.com/bitly/go-hostpool v0.0.0-20171023180738-a3a6125de932 // indirect + github.com/bmizerany/assert v0.0.0-20160611221934-b7ed37b82869 // indirect + github.com/boltdb/bolt v1.3.1 // indirect github.com/boombuler/barcode v1.0.0 // indirect - github.com/briankassouf/jose v0.9.1 // indirect github.com/cenkalti/backoff v2.1.1+incompatible // indirect - github.com/centrify/cloud-golang-sdk v0.0.0-20190214225812-119110094d0f // indirect github.com/chrismalek/oktasdk-go v0.0.0-20181212195951-3430665dfaa0 // indirect - github.com/circonus-labs/circonus-gometrics v2.2.6+incompatible // indirect + github.com/circonus-labs/circonus-gometrics v2.3.1+incompatible // indirect + github.com/circonus-labs/circonusllhist v0.1.3 // indirect github.com/containerd/continuity v0.0.0-20181203112020-004b46473808 // indirect - github.com/coredns/coredns v1.4.0 // indirect - github.com/coreos/etcd v3.3.12+incompatible // indirect - github.com/coreos/go-oidc v2.0.0+incompatible // indirect - github.com/coreos/go-semver v0.2.0 // indirect - github.com/coreos/pkg v0.0.0-20180928190104-399ea9e2e55f // indirect + github.com/coredns/coredns v1.5.0 // indirect github.com/dancannon/gorethink v4.0.0+incompatible // indirect - github.com/denisenkom/go-mssqldb v0.0.0-20190328043727-2183450503ad // indirect - github.com/dimchansky/utfbom v1.1.0 // indirect + github.com/denisenkom/go-mssqldb v0.0.0-20190418034912-35416408c946 // indirect + github.com/dnaeon/go-vcr v1.0.1 // indirect + github.com/docker/go-connections v0.4.0 // indirect github.com/duosecurity/duo_api_golang v0.0.0-20190308151101-6c680f768e74 // indirect - github.com/envoyproxy/go-control-plane v0.6.9 // indirect - github.com/fullsailor/pkcs7 v0.0.0-20180613152042-8306686428a5 // indirect - github.com/gammazero/deque v0.0.0-20190130191400-2afb3858e9c7 // indirect - github.com/gammazero/workerpool v0.0.0-20181230203049-86a96b5d5d92 // indirect + github.com/elazarl/go-bindata-assetfs v1.0.0 // indirect + github.com/envoyproxy/go-control-plane v0.7.1 // indirect + github.com/envoyproxy/protoc-gen-validate v0.0.14 // indirect + github.com/fullsailor/pkcs7 v0.0.0-20190404230743-d7302db945fa // indirect github.com/garyburd/redigo v1.6.0 // indirect - github.com/go-errors/errors v1.0.1 // indirect - github.com/go-ldap/ldap v3.0.2+incompatible // indirect github.com/go-log/log v0.1.0 github.com/go-ole/go-ole v1.2.4 // indirect github.com/go-sql-driver/mysql v1.4.1 // indirect github.com/go-stomp/stomp v2.0.2+incompatible // indirect - github.com/gocql/gocql v0.0.0-20190325140904-fc3925ac2cbd // indirect - github.com/gogo/googleapis v1.1.0 // indirect - github.com/gogo/protobuf v1.2.1 // indirect - github.com/golang/groupcache v0.0.0-20190129154638-5b532d6fd5ef // indirect + github.com/gocql/gocql v0.0.0-20190418090649-59a610c947c5 // indirect + github.com/gogo/googleapis v1.2.0 // indirect github.com/golang/protobuf v1.3.1 - github.com/golang/snappy v0.0.1 // indirect - github.com/google/btree v1.0.0 // indirect + github.com/google/go-github v17.0.0+incompatible // indirect + github.com/google/gofuzz v1.0.0 // indirect github.com/google/uuid v1.1.1 - github.com/gorhill/cronexpr v0.0.0-20180427100037-88b0669f7d75 // indirect - github.com/gorilla/websocket v1.4.0 // indirect - github.com/grpc-ecosystem/go-grpc-middleware v1.0.0 // indirect - github.com/grpc-ecosystem/go-grpc-prometheus v1.2.0 // indirect - github.com/grpc-ecosystem/grpc-gateway v1.8.5 // indirect + github.com/gotestyourself/gotestyourself v2.2.0+incompatible // indirect github.com/hashicorp/consul v1.4.4 - github.com/hashicorp/go-discover v0.0.0-20190319153616-61771d82ff54 // indirect - github.com/hashicorp/go-gcp-common v0.5.0 // indirect - github.com/hashicorp/go-hclog v0.8.0 // indirect - github.com/hashicorp/go-memdb v1.0.0 // indirect - github.com/hashicorp/go-plugin v1.0.0 // indirect - github.com/hashicorp/go-retryablehttp v0.5.3 // indirect - github.com/hashicorp/go-rootcerts v1.0.0 // indirect - github.com/hashicorp/go-sockaddr v1.0.2 // indirect - github.com/hashicorp/go-version v1.1.0 // indirect - github.com/hashicorp/golang-lru v0.5.1 // indirect + github.com/hashicorp/go-discover v0.0.0-20190408185603-6ccdb67f9b84 // indirect + github.com/hashicorp/go-memdb v1.0.1 // indirect github.com/hashicorp/hil v0.0.0-20190212132231-97b3a9cdfa93 // indirect github.com/hashicorp/memberlist v0.1.3 github.com/hashicorp/net-rpc-msgpackrpc v0.0.0-20151116020338-a14192a58a69 // indirect - github.com/hashicorp/nomad v0.8.7 // indirect + github.com/hashicorp/nomad/api v0.0.0-20190419150859-8a0df4034dc4 // indirect + github.com/hashicorp/raft v1.0.1 // indirect github.com/hashicorp/raft-boltdb v0.0.0-20171010151810-6e5ba93211ea // indirect github.com/hashicorp/serf v0.8.2 // indirect - github.com/hashicorp/vault v1.1.0 // indirect - github.com/hashicorp/vault-plugin-auth-alicloud v0.0.0-20190320211238-36e70c54375f // indirect - github.com/hashicorp/vault-plugin-auth-azure v0.0.0-20190320211138-f34b96803f04 // indirect - github.com/hashicorp/vault-plugin-auth-centrify v0.0.0-20190320211357-44eb061bdfd8 // indirect - github.com/hashicorp/vault-plugin-auth-gcp v0.0.0-20190320214413-e8308b5e41c9 // indirect - github.com/hashicorp/vault-plugin-auth-jwt v0.0.0-20190321042813-9474f90fb1df // indirect - github.com/hashicorp/vault-plugin-auth-kubernetes v0.0.0-20190328163920-79931ee7aad5 // indirect - github.com/hashicorp/vault-plugin-secrets-ad v0.0.0-20190327182327-ed2c3d4c3d95 // indirect - github.com/hashicorp/vault-plugin-secrets-alicloud v0.0.0-20190320213517-3307bdf683cb // indirect - github.com/hashicorp/vault-plugin-secrets-azure v0.0.0-20190320211922-2dc8a8a5e490 // indirect - github.com/hashicorp/vault-plugin-secrets-gcp v0.0.0-20190320211452-71903323ecb4 // indirect - github.com/hashicorp/vault-plugin-secrets-gcpkms v0.0.0-20190320213325-9e326a9e802d // indirect - github.com/hashicorp/vault-plugin-secrets-kv v0.0.0-20190320211621-3ccc8684cf25 // indirect - github.com/influxdata/influxdb v1.7.5 // indirect - github.com/influxdata/platform v0.0.0-20190117200541-d500d3cf5589 // indirect - github.com/jeffchao/backoff v0.0.0-20140404060208-9d7fd7aa17f2 // indirect + github.com/hashicorp/vault v1.1.2 // indirect + github.com/hashicorp/vault-plugin-auth-alicloud v0.5.1 // indirect + github.com/hashicorp/vault-plugin-auth-azure v0.5.1 // indirect + github.com/hashicorp/vault-plugin-auth-centrify v0.5.1 // indirect + github.com/hashicorp/vault-plugin-auth-jwt v0.5.1 // indirect + github.com/hashicorp/vault-plugin-auth-kubernetes v0.5.1 // indirect + github.com/hashicorp/vault-plugin-secrets-ad v0.5.1 // indirect + github.com/hashicorp/vault-plugin-secrets-alicloud v0.5.1 // indirect + github.com/hashicorp/vault-plugin-secrets-azure v0.5.1 // indirect + github.com/hashicorp/vault-plugin-secrets-gcp v0.5.2 // indirect + github.com/hashicorp/vault-plugin-secrets-gcpkms v0.5.1 // indirect + github.com/hashicorp/vault-plugin-secrets-kv v0.5.1 // indirect + github.com/influxdata/influxdb v1.7.6 // indirect github.com/jefferai/jsonx v1.0.0 // indirect - github.com/jonboulle/clockwork v0.1.0 // indirect - github.com/keybase/go-crypto v0.0.0-20190312101036-b475f2ecc1fe // indirect - github.com/lyft/protoc-gen-validate v0.0.14 // indirect + github.com/keybase/go-crypto v0.0.0-20190416182011-b785b22cc757 // indirect + github.com/lib/pq v1.1.0 // indirect github.com/mattbaird/elastigo v0.0.0-20170123220020-2fe47fd29e4b // indirect - github.com/mattn/go-isatty v0.0.7 // indirect github.com/michaelklishin/rabbit-hole v1.5.0 // indirect github.com/micro/cli v0.1.0 github.com/micro/go-log v0.1.0 @@ -96,29 +75,24 @@ require ( github.com/micro/mdns v0.1.0 github.com/micro/util v0.2.0 github.com/mitchellh/hashstructure v1.0.0 - github.com/mitchellh/pointerstructure v0.0.0-20190323210102-2db4bb651397 // indirect + github.com/opencontainers/go-digest v1.0.0-rc1 // indirect + github.com/opencontainers/image-spec v1.0.1 // indirect + github.com/opencontainers/runc v0.1.1 // indirect github.com/ory-am/common v0.4.0 // indirect github.com/ory/dockertest v3.3.4+incompatible // indirect - github.com/pascaldekloe/goe v0.1.0 // indirect github.com/pborman/uuid v1.2.0 // indirect github.com/pkg/errors v0.8.1 - github.com/pquerna/cachecontrol v0.0.0-20180517163645-1555304b9b35 // indirect github.com/pquerna/otp v1.1.0 // indirect - github.com/ryanuber/go-glob v1.0.0 // indirect github.com/samuel/go-zookeeper v0.0.0-20180130194729-c4fab1ac1bec // indirect github.com/shirou/gopsutil v2.18.12+incompatible // indirect github.com/shirou/w32 v0.0.0-20160930032740-bb4de0191aa4 // indirect - github.com/soheilhy/cmux v0.1.4 // indirect - github.com/streadway/amqp v0.0.0-20190312223743-14f78b41ce6d // indirect - github.com/tmc/grpc-websocket-proxy v0.0.0-20190109142713-0ad062ec5ee5 // indirect - github.com/ugorji/go/codec v0.0.0-20190320090025-2dc34c0b8780 // indirect - github.com/xiang90/probing v0.0.0-20190116061207-43a291ad63a2 // indirect - golang.org/x/net v0.0.0-20190327214358-63eda1eb0650 - golang.org/x/time v0.0.0-20190308202827-9d24e82272b4 // indirect - google.golang.org/grpc v1.19.1 // indirect - gopkg.in/asn1-ber.v1 v1.0.0-20181015200546-f715ec2f112d // indirect + github.com/streadway/amqp v0.0.0-20190404075320-75d898a42a94 // indirect + github.com/tv42/httpunix v0.0.0-20150427012821-b75d8614f926 // indirect + golang.org/x/net v0.0.0-20190420063019-afa5a82059c6 + google.golang.org/grpc v1.20.1 // indirect gopkg.in/gorethink/gorethink.v4 v4.1.0 // indirect - gopkg.in/ini.v1 v1.42.0 // indirect + gopkg.in/mgo.v2 v2.0.0-20180705113604-9856a29383ce // indirect gopkg.in/ory-am/dockertest.v2 v2.2.3 // indirect + gotest.tools v2.2.0+incompatible // indirect layeh.com/radius v0.0.0-20190322222518-890bc1058917 // indirect ) diff --git a/go.sum b/go.sum index 6fa13c8c..4b08c70c 100644 --- a/go.sum +++ b/go.sum @@ -1,65 +1,50 @@ cloud.google.com/go v0.26.0 h1:e0WKqKTd5BnrG8aKH3J3h+QvEIQtSUcf2n5UZ5ZgLtQ= cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= -cloud.google.com/go v0.31.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= +cloud.google.com/go v0.28.0 h1:KZ/88LWSw8NxMkjdQyX7LQSGR9PkHr4PaVuNm8zgFq0= +cloud.google.com/go v0.28.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= cloud.google.com/go v0.34.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= -cloud.google.com/go v0.36.0 h1:+aCSj7tOo2LODWVEuZDZeGCckdt6MlSF+X/rB3wUiS8= -cloud.google.com/go v0.36.0/go.mod h1:RUoy9p/M4ge0HzT8L+SDZ8jg+Q6fth0CiBuhFJpSV40= -dmitri.shuralyov.com/app/changes v0.0.0-20180602232624-0a106ad413e3/go.mod h1:Yl+fi1br7+Rr3LqpNJf1/uxUdtRUV+Tnj0o93V2B9MU= -dmitri.shuralyov.com/html/belt v0.0.0-20180602232347-f7d459c86be0/go.mod h1:JLBrvjyP0v+ecvNYvCpyZgu5/xkfAUhi6wJj28eUfSU= -dmitri.shuralyov.com/service/change v0.0.0-20181023043359-a85b471d5412/go.mod h1:a1inKt/atXimZ4Mv927x+r7UpyzRUf4emIoiiSC2TN4= -dmitri.shuralyov.com/state v0.0.0-20180228185332-28bcc343414c/go.mod h1:0PRwlb0D6DFvNNtx+9ybjezNCa8XF0xaYcETyp6rHWU= -git.apache.org/thrift.git v0.0.0-20180902110319-2566ecd5d999/go.mod h1:fPE2ZNJGynbRyZ4dJvy6G277gSllfV2HJqblrnkyeyg= +cloud.google.com/go v0.37.4 h1:glPeL3BQJsbF6aIIYfZizMwc5LTYz250bDMjttbBGAU= +cloud.google.com/go v0.37.4/go.mod h1:NHPJ89PdicEuT9hdPXMROBD91xc5uRDxsMtSB16k7hw= +contrib.go.opencensus.io/exporter/ocagent v0.4.12 h1:jGFvw3l57ViIVEPKKEUXPcLYIXJmQxLUh6ey1eJhwyc= +contrib.go.opencensus.io/exporter/ocagent v0.4.12/go.mod h1:450APlNTSR6FrvC3CTRqYosuDstRB9un7SOx2k/9ckA= git.apache.org/thrift.git v0.12.0/go.mod h1:fPE2ZNJGynbRyZ4dJvy6G277gSllfV2HJqblrnkyeyg= github.com/Azure/azure-sdk-for-go v16.0.0+incompatible h1:gr1qKY/Ll72VjFTZmaBwRK1yQHAxCnV25ekOKroc9ws= github.com/Azure/azure-sdk-for-go v16.0.0+incompatible/go.mod h1:9XXNKU+eRnpl9moKnB4QOLf1HestfXbmab5FXxiDBjc= +github.com/Azure/azure-sdk-for-go v27.1.0+incompatible h1:/aGULErVaJsMdtew1p9OhEo8FeBzfRKRzJbc8NWJv/w= +github.com/Azure/azure-sdk-for-go v27.1.0+incompatible/go.mod h1:9XXNKU+eRnpl9moKnB4QOLf1HestfXbmab5FXxiDBjc= github.com/Azure/go-ansiterm v0.0.0-20170929234023-d6e3b3328b78 h1:w+iIsaOQNcT7OZ575w+acHgRric5iCyQh+xv+KJ4HB8= github.com/Azure/go-ansiterm v0.0.0-20170929234023-d6e3b3328b78/go.mod h1:LmzpDX56iTiv29bbRTIsUNlaFfuhWRQBWjQdVyAevI8= github.com/Azure/go-autorest v10.7.0+incompatible h1:dB+dKSLGdJLEhU/FoZTSNSPMZuE5H4M5p5zgSct7qwM= github.com/Azure/go-autorest v10.7.0+incompatible/go.mod h1:r+4oMnoxhatjLLJ6zxSWATqVooLgysK6ZNox3g/xq24= +github.com/Azure/go-autorest v11.7.1+incompatible h1:M2YZIajBBVekV86x0rr1443Lc1F/Ylxb9w+5EtSyX3Q= +github.com/Azure/go-autorest v11.7.1+incompatible/go.mod h1:r+4oMnoxhatjLLJ6zxSWATqVooLgysK6ZNox3g/xq24= github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= -github.com/DataDog/datadog-go v0.0.0-20180822151419-281ae9f2d895/go.mod h1:LButxg5PwREeZtORoXG3tL4fMGNddJ+vMq1mwgfaqoQ= -github.com/DataDog/datadog-go v0.0.0-20190323183505-07c7c350327b h1:s9I3AGSgN6M/40RePnvZnpDvHVvdpovl/TitcxZ6ExQ= -github.com/DataDog/datadog-go v0.0.0-20190323183505-07c7c350327b/go.mod h1:LButxg5PwREeZtORoXG3tL4fMGNddJ+vMq1mwgfaqoQ= +github.com/DataDog/datadog-go v2.2.0+incompatible h1:V5BKkxACZLjzHjSgBbr2gvLA2Ae49yhc6CSY7MLy5k4= +github.com/DataDog/datadog-go v2.2.0+incompatible/go.mod h1:LButxg5PwREeZtORoXG3tL4fMGNddJ+vMq1mwgfaqoQ= +github.com/DataDog/dd-trace-go v0.6.1/go.mod h1:SmQTTcC37XMyEm75HV0AWiZIYxDiaNhRi49zorIpW+o= +github.com/DataDog/zstd v1.3.5/go.mod h1:1jcaCB/ufaK+sKp1NBhlGmpz41jOoPQ35bpF36t7BBo= github.com/Jeffail/gabs v1.1.1 h1:V0uzR08Hj22EX8+8QMhyI9sX2hwRu+/RJhJUmnwda/E= github.com/Jeffail/gabs v1.1.1/go.mod h1:6xMvQMK4k33lb7GUUpaAPh6nKMmemQeg5d4gn7/bOXc= -github.com/Masterminds/semver v1.4.2/go.mod h1:MB6lktGJrhw8PrUyiEoblNEGEQ+RzHPF078ddwwvV3Y= -github.com/Masterminds/sprig v2.16.0+incompatible/go.mod h1:y6hNFY5UBTIWBxnzTeuNhlNS5hqE0NB0E6fgfo2Br3o= -github.com/Microsoft/go-winio v0.4.11/go.mod h1:VhR8bwka0BXejwEJY73c50VrPtXAaKcyvVC4A4RozmA= github.com/Microsoft/go-winio v0.4.12 h1:xAfWHN1IrQ0NJ9TBC0KBZoqLjzDTr1ML+4MywiUOryc= github.com/Microsoft/go-winio v0.4.12/go.mod h1:VhR8bwka0BXejwEJY73c50VrPtXAaKcyvVC4A4RozmA= -github.com/NYTimes/gziphandler v1.0.1/go.mod h1:3wb06e3pkSAbeQ52E9H9iFoQsEEwGN64994WTCIhntQ= github.com/NYTimes/gziphandler v1.1.1 h1:ZUDjpQae29j0ryrS0u/B8HZfJBtBQHjqw2rQ2cqUQ3I= github.com/NYTimes/gziphandler v1.1.1/go.mod h1:n/CVRwUEOgIxrgPvAQhUUr9oeUtvrhMomdKFjzJNB0c= github.com/Nvveen/Gotty v0.0.0-20120604004816-cd527374f1e5 h1:TngWCqHvy9oXAN6lEVMRuU21PR1EtLVZJmdB18Gu3Rw= github.com/Nvveen/Gotty v0.0.0-20120604004816-cd527374f1e5/go.mod h1:lmUJ/7eu/Q8D7ML55dXQrVaamCz2vxCfdQBasLZfHKk= -github.com/OneOfOne/xxhash v1.2.2/go.mod h1:HSdplMjZKSmBqAxg5vPj2TmRDmfkzw+cTzAElWljhcU= -github.com/RoaringBitmap/roaring v0.4.16/go.mod h1:8khRDP4HmeXns4xIj9oGrKSz7XTQiJx2zgh7AcNke4w= -github.com/SAP/go-hdb v0.13.1/go.mod h1:etBT+FAi1t5k3K3tf5vQTnosgYmhDkRi8jEnQqCnxF0= github.com/SAP/go-hdb v0.14.1 h1:hkw4ozGZ/i4eak7ZuGkY5e0hxiXFdNUBNhr4AvZVNFE= github.com/SAP/go-hdb v0.14.1/go.mod h1:7fdQLVC2lER3urZLjZCm0AuMQfApof92n3aylBPEkMo= -github.com/SermoDigital/jose v0.9.1 h1:atYaHPD3lPICcbK1owly3aPm0iaJGSGPi0WD4vLznv8= -github.com/SermoDigital/jose v0.9.1/go.mod h1:ARgCUhI1MHQH+ONky/PAtmVHQrP5JlGY0F3poXOp/fA= github.com/Shopify/sarama v1.19.0/go.mod h1:FVkBWblsNy7DGZRfXLU0O9RCGt5g3g3yEuWXgklEdEo= +github.com/Shopify/sarama v1.21.0/go.mod h1:yuqtN/pe8cXRWG5zPaO7hCfNJp5MwmkoJEoLjkm5tCQ= github.com/Shopify/toxiproxy v2.1.4+incompatible/go.mod h1:OXgGpZ6Cli1/URJOF1DMxUHB2q5Ap20/P/eIdh4G0pI= -github.com/Sirupsen/logrus v1.0.6 h1:HCAGQRk48dRVPA5Y+Yh0qdCSTzPOyU1tBJ7Q9YzotII= -github.com/Sirupsen/logrus v1.0.6/go.mod h1:rmk17hk6i8ZSAJkSDa7nOxamrG+SP4P0mm+DAvExv4U= github.com/StackExchange/wmi v0.0.0-20181212234831-e0a55b97c705 h1:UUppSQnhf4Yc6xGxSkoQpPhb7RVzuv5Nb1mwJ5VId9s= github.com/StackExchange/wmi v0.0.0-20181212234831-e0a55b97c705/go.mod h1:3eOhrUMpNV+6aFIbp5/iudMxNCF27Vw2OZgy4xEx0Fg= github.com/abdullin/seq v0.0.0-20160510034733-d5467c17e7af h1:DBNMBMuMiWYu0b+8KMJuWmfCkcxl09JwdlqwDZZ6U14= github.com/abdullin/seq v0.0.0-20160510034733-d5467c17e7af/go.mod h1:5Jv4cbFiHJMsVxt52+i0Ha45fjshj6wxYr1r19tB9bw= -github.com/alcortesm/tgz v0.0.0-20161220082320-9c5fe88206d7/go.mod h1:6zEj6s6u/ghQa61ZWa/C2Aw3RkjiTBOix7dkqa1VLIs= -github.com/alecthomas/kingpin v2.2.6+incompatible/go.mod h1:59OFYbFVLKQKq+mqrL6Rw5bR0c3ACQaawgXx0QYndlE= github.com/alecthomas/template v0.0.0-20160405071501-a0175ee3bccc/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc= github.com/alecthomas/units v0.0.0-20151022065526-2efee857e7cf/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0= -github.com/aliyun/alibaba-cloud-sdk-go v0.0.0-20190328075325-5887fb5d0027 h1:fRCXvr84WHoAnmRZa2GDzBfxH+8B+4j7ewXCUVHRGKk= -github.com/aliyun/alibaba-cloud-sdk-go v0.0.0-20190328075325-5887fb5d0027/go.mod h1:T9M45xf79ahXVelWoOBmH0y4aC1t5kXO5BxwyakgIGA= -github.com/andreyvit/diff v0.0.0-20170406064948-c7f18ee00883/go.mod h1:rCTlJbsFo29Kk6CurOXKm700vrz8f0KW0JNfpkRJY/8= -github.com/anmitsu/go-shlex v0.0.0-20161002113705-648efa622239/go.mod h1:2FmKhYUyUczH0OGQWaF5ceTx0UBShxjsH6f8oGKYe2c= -github.com/aokoli/goutils v1.0.1/go.mod h1:SijmP0QR8LtwsmDs8Yii5Z/S4trXFGFC2oO5g9DP+DQ= -github.com/apache/arrow/go/arrow v0.0.0-20181031164735-a56c009257a7/go.mod h1:GjvccvtI06FGFvRU1In/maF7tKp3h7GBV9Sexo5rNPM= -github.com/apache/arrow/go/arrow v0.0.0-20181217213538-e9ed591db9cb/go.mod h1:GjvccvtI06FGFvRU1In/maF7tKp3h7GBV9Sexo5rNPM= +github.com/aliyun/alibaba-cloud-sdk-go v0.0.0-20190412020505-60e2075261b6 h1:5RwdKFlGKokYBbq4M2ZZ0LzfxdK4e1L4rwQH+76wPkE= +github.com/aliyun/alibaba-cloud-sdk-go v0.0.0-20190412020505-60e2075261b6/go.mod h1:T9M45xf79ahXVelWoOBmH0y4aC1t5kXO5BxwyakgIGA= github.com/apache/thrift v0.12.0/go.mod h1:cp2SuWMxlEZw2r+iP2GNCdIi4C1qmUzdZFSVb+bacwQ= -github.com/apex/log v1.1.0/go.mod h1:yA770aXIDQrhVOIGurT/pVdfCpSq1GQV/auzMN5fzvY= github.com/araddon/gou v0.0.0-20190110011759-c797efecbb61 h1:Xz25cuW4REGC5W5UtpMU3QItMIImag615HiQcRbxqKQ= github.com/araddon/gou v0.0.0-20190110011759-c797efecbb61/go.mod h1:ikc1XA58M+Rx7SEbf0bLJCfBkwayZ8T5jBo5FXK8Uz8= github.com/armon/circbuf v0.0.0-20150827004946-bbbad097214e/go.mod h1:3U/XgcO3hCbHZ8TKRvWD2dDTCfh9M9ya+I9JpbB7O8o= @@ -72,62 +57,51 @@ github.com/armon/go-radix v1.0.0 h1:F4z6KzEeeQIMeLFa97iZU6vupzoecKdU5TX24SNppXI= github.com/armon/go-radix v1.0.0/go.mod h1:ufUuZ+zHj4x4TnLV4JWEpy2hxWSpsRywHrMgIH9cCH8= github.com/asaskevich/govalidator v0.0.0-20180720115003-f9ffefc3facf h1:eg0MeVzsP1G42dRafH3vf+al2vQIJU0YHX+1Tw87oco= github.com/asaskevich/govalidator v0.0.0-20180720115003-f9ffefc3facf/go.mod h1:lB+ZfQJz7igIIfQNfa7Ml4HSf2uFQQRzpGGRXenZAgY= +github.com/aws/aws-sdk-go v1.14.17/go.mod h1:ZRmQr0FajVIyZ4ZzBYKG5P3ZqPz9IHG41ZoMu1ADI3k= github.com/aws/aws-sdk-go v1.15.24 h1:xLAdTA/ore6xdPAljzZRed7IGqQgC+nY+ERS5vaj4Ro= github.com/aws/aws-sdk-go v1.15.24/go.mod h1:mFuSZ37Z9YOHbQEwBWztmVzqXrEkub65tZoCYDt7FT0= -github.com/aws/aws-sdk-go v1.15.59/go.mod h1:E3/ieXAlvM0XWO57iftYVDLLvQ824smPP3ATZkfNZeM= -github.com/aws/aws-sdk-go v1.15.64/go.mod h1:E3/ieXAlvM0XWO57iftYVDLLvQ824smPP3ATZkfNZeM= -github.com/aws/aws-sdk-go v1.17.5 h1:WW9Hm3KYo48iZHpmBc+b7sgyS0h32zgCvya28SLW4BU= -github.com/aws/aws-sdk-go v1.17.5/go.mod h1:KmX6BPdI08NWTb3/sm4ZGu5ShLoqVDhKgpiN924inxo= -github.com/benbjohnson/tmpl v1.0.0/go.mod h1:igT620JFIi44B6awvU9IsDhR77IXWtFigTLil/RPdps= github.com/beorn7/perks v0.0.0-20180321164747-3a771d992973 h1:xJ4a3vCFaGF/jqvzLMYoU8P317H5OQ+Via4RmuPwCS0= github.com/beorn7/perks v0.0.0-20180321164747-3a771d992973/go.mod h1:Dwedo/Wpr24TaqPxmxbtue+5NUziq4I4S80YR8gNf3Q= github.com/bgentry/speakeasy v0.1.0 h1:ByYyxL9InA1OWqxJqqp2A5pYHUrCiAL6K3J+LKSsQkY= github.com/bgentry/speakeasy v0.1.0/go.mod h1:+zsyZBPWlz7T6j88CTgSN5bM796AkVf0kBD4zp0CCIs= github.com/bitly/go-hostpool v0.0.0-20171023180738-a3a6125de932 h1:mXoPYz/Ul5HYEDvkta6I8/rnYM5gSdSV2tJ6XbZuEtY= github.com/bitly/go-hostpool v0.0.0-20171023180738-a3a6125de932/go.mod h1:NOuUCSz6Q9T7+igc/hlvDOUdtWKryOrtFyIVABv/p7k= -github.com/blakesmith/ar v0.0.0-20150311145944-8bd4349a67f2/go.mod h1:PkYb9DJNAwrSvRx5DYA+gUcOIgTGVMNkfSCbZM8cWpI= github.com/bmizerany/assert v0.0.0-20160611221934-b7ed37b82869 h1:DDGfHa7BWjL4YnC6+E63dPcxHo2sUxDIu8g3QgEJdRY= github.com/bmizerany/assert v0.0.0-20160611221934-b7ed37b82869/go.mod h1:Ekp36dRnpXw/yCqJaO+ZrUyxD+3VXMFFr56k5XYrpB4= github.com/boltdb/bolt v1.3.1 h1:JQmyP4ZBrce+ZQu0dY660FMfatumYDLun9hBCUVIkF4= github.com/boltdb/bolt v1.3.1/go.mod h1:clJnj/oiGkjum5o1McbSZDSLxVThjynRyGBgiAx27Ps= github.com/boombuler/barcode v1.0.0 h1:s1TvRnXwL2xJRaccrdcBQMZxq6X7DvsMogtmJeHDdrc= github.com/boombuler/barcode v1.0.0/go.mod h1:paBWMcWSl3LHKBqUq+rly7CNSldXjb2rDl3JlRe0mD8= -github.com/bouk/httprouter v0.0.0-20160817010721-ee8b3818a7f5/go.mod h1:CDReaxg1cmLrtcasZy43l4EYPAknXLiQSrb7tLw5zXM= -github.com/bradfitz/go-smtpd v0.0.0-20170404230938-deb6d6237625/go.mod h1:HYsPBTaaSFSlLx/70C2HPIMNZpVV8+vt/A+FMnYP11g= -github.com/briankassouf/jose v0.9.1 h1:HMeR+qpz2PBP7RgR+64nJPA9qcZI74tdkBv5NyD0Mzk= -github.com/briankassouf/jose v0.9.1/go.mod h1:HQhVmdUf7dBNwIIdBTivnCDxcf6IZY3/zrb+uKSJz6Y= -github.com/c-bata/go-prompt v0.2.2/go.mod h1:VzqtzE2ksDBcdln8G7mk2RX9QyGjH+OVqOCSiVIqS34= -github.com/caarlos0/ctrlc v1.0.0/go.mod h1:CdXpj4rmq0q/1Eb44M9zi2nKB0QraNKuRGYGrrHhcQw= -github.com/campoy/unique v0.0.0-20180121183637-88950e537e7e/go.mod h1:9IOqJGCPMSc6E5ydlp5NIonxObaeu/Iub/X03EKPVYo= +github.com/briankassouf/jose v0.9.2-0.20180619214549-d2569464773f h1:ZMEzE7R0WNqgbHplzSBaYJhJi5AZWTCK9baU0ebzG6g= +github.com/briankassouf/jose v0.9.2-0.20180619214549-d2569464773f/go.mod h1:HQhVmdUf7dBNwIIdBTivnCDxcf6IZY3/zrb+uKSJz6Y= github.com/cenkalti/backoff v2.0.0+incompatible/go.mod h1:90ReRw6GdpyfrHakVjL/QHaoyV4aDUVVkXQJJJ3NXXM= github.com/cenkalti/backoff v2.1.1+incompatible h1:tKJnvO2kl0zmb/jA5UKAt4VoEVw1qxKWjE/Bpp46npY= github.com/cenkalti/backoff v2.1.1+incompatible/go.mod h1:90ReRw6GdpyfrHakVjL/QHaoyV4aDUVVkXQJJJ3NXXM= +github.com/census-instrumentation/opencensus-proto v0.2.0 h1:LzQXZOgg4CQfE6bFvXGM30YZL1WW/M337pXml+GrcZ4= +github.com/census-instrumentation/opencensus-proto v0.2.0/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU= github.com/centrify/cloud-golang-sdk v0.0.0-20190214225812-119110094d0f h1:gJzxrodnNd/CtPXjO3WYiakyNzHg3rtAi7rO74ejHYU= github.com/centrify/cloud-golang-sdk v0.0.0-20190214225812-119110094d0f/go.mod h1:C0rtzmGXgN78pYR0tGJFhtHgkbAs0lIbHwkB81VxDQE= -github.com/cespare/xxhash v1.1.0/go.mod h1:XrSqR1VqqWfGrhpAt58auRo0WTKS1nRRg3ghfAqPWnc= github.com/chrismalek/oktasdk-go v0.0.0-20181212195951-3430665dfaa0 h1:CWU8piLyqoi9qXEUwzOh5KFKGgmSU5ZhktJyYcq6ryQ= github.com/chrismalek/oktasdk-go v0.0.0-20181212195951-3430665dfaa0/go.mod h1:5d8DqS60xkj9k3aXfL3+mXBH0DPYO0FQjcKosxl+b/Q= -github.com/circonus-labs/circonus-gometrics v2.2.5+incompatible/go.mod h1:nmEj6Dob7S7YxXgwXpfOuvO54S+tGdZdw9fuRZt25Ag= -github.com/circonus-labs/circonus-gometrics v2.2.6+incompatible h1:NoaznmtBvXxBwKGS+lQBGJSNqJQAtCTPE5ekztSSQfs= -github.com/circonus-labs/circonus-gometrics v2.2.6+incompatible/go.mod h1:nmEj6Dob7S7YxXgwXpfOuvO54S+tGdZdw9fuRZt25Ag= +github.com/circonus-labs/circonus-gometrics v2.3.1+incompatible h1:C29Ae4G5GtYyYMm1aztcyj/J5ckgJm2zwdDajFbx1NY= +github.com/circonus-labs/circonus-gometrics v2.3.1+incompatible/go.mod h1:nmEj6Dob7S7YxXgwXpfOuvO54S+tGdZdw9fuRZt25Ag= github.com/circonus-labs/circonusllhist v0.1.3 h1:TJH+oke8D16535+jHExHj4nQvzlZrj7ug5D7I/orNUA= github.com/circonus-labs/circonusllhist v0.1.3/go.mod h1:kMXHVDlOchFAehlya5ePtbp5jckzBHf4XRpQvBOLI+I= github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw= -github.com/containerd/continuity v0.0.0-20181027224239-bea7585dbfac/go.mod h1:GL3xCUCBDV3CZiTSEKksMWbLE66hEyuu9qyDOOqM47Y= github.com/containerd/continuity v0.0.0-20181203112020-004b46473808 h1:4BX8f882bXEDKfWIf0wa8HRvpnBoPszJJXL+TVbBw4M= github.com/containerd/continuity v0.0.0-20181203112020-004b46473808/go.mod h1:GL3xCUCBDV3CZiTSEKksMWbLE66hEyuu9qyDOOqM47Y= -github.com/coredns/coredns v1.4.0 h1:RubBkYmkByUqZWWkjRHvNLnUHgkRVqAWgSMmRFvpE1A= -github.com/coredns/coredns v1.4.0/go.mod h1:zASH/MVDgR6XZTbxvOnsZfffS+31vg6Ackf/wo1+AM0= -github.com/coreos/bbolt v1.3.1-coreos.6 h1:uTXKg9gY70s9jMAKdfljFQcuh4e/BXOM+V+d00KFj3A= -github.com/coreos/bbolt v1.3.1-coreos.6/go.mod h1:iRUV2dpdMOn7Bo10OQBFzIJO9kkE559Wcmn+qkEiiKk= -github.com/coreos/etcd v3.3.12+incompatible h1:pAWNwdf7QiT1zfaWyqCtNZQWCLByQyA3JrSQyuYAqnQ= -github.com/coreos/etcd v3.3.12+incompatible/go.mod h1:uF7uidLiAD3TWHmW31ZFd/JWoc32PjwdhPthX9715RE= +github.com/coredns/coredns v1.5.0 h1:SJ0xqULsNLGNSBE+G678tM/v1cJ5o5s/FcTC1qPTQkI= +github.com/coredns/coredns v1.5.0/go.mod h1:He0NCGwdo32s+0TFFuiB9ccnFZRAsjdrW5Q3Vv5Ne6g= +github.com/coreos/bbolt v1.3.2 h1:wZwiHHUieZCquLkDL0B8UhzreNWsPHooDAG3q34zk0s= +github.com/coreos/bbolt v1.3.2/go.mod h1:iRUV2dpdMOn7Bo10OQBFzIJO9kkE559Wcmn+qkEiiKk= +github.com/coreos/etcd v3.3.11+incompatible h1:0gCnqKsq7XxMi69JsnbmMc1o+RJH3XH64sV9aiTTYko= +github.com/coreos/etcd v3.3.11+incompatible/go.mod h1:uF7uidLiAD3TWHmW31ZFd/JWoc32PjwdhPthX9715RE= github.com/coreos/go-oidc v2.0.0+incompatible h1:+RStIopZ8wooMx+Vs5Bt8zMXxV1ABl5LbakNExNmZIg= github.com/coreos/go-oidc v2.0.0+incompatible/go.mod h1:CgnwVTmzoESiwO9qyAFEMiHoZ1nMCKZlZ9V6mm3/LKc= github.com/coreos/go-semver v0.2.0 h1:3Jm3tLmsgAYcjC+4Up7hJrFBPr+n7rAqYeSw/SZazuY= github.com/coreos/go-semver v0.2.0/go.mod h1:nnelYz7RCh+5ahJtPPxZlU+153eP4D4r3EedlOD2RNk= -github.com/coreos/go-systemd v0.0.0-20181012123002-c6f51f82210d h1:t5Wuyh53qYyg9eqn4BbnlIT+vmhyww0TatL+zT3uWgI= -github.com/coreos/go-systemd v0.0.0-20181012123002-c6f51f82210d/go.mod h1:F5haX7vjVVG0kc13fIWeqUViNPyEJxv/OmvnBo0Yme4= +github.com/coreos/go-systemd v0.0.0-20190212144455-93d5ec2c7f76 h1:FE783w8WFh+Rvg+7bZ5g8p7gP4SeVS4AoNwkvazlsBg= +github.com/coreos/go-systemd v0.0.0-20190212144455-93d5ec2c7f76/go.mod h1:F5haX7vjVVG0kc13fIWeqUViNPyEJxv/OmvnBo0Yme4= github.com/coreos/pkg v0.0.0-20180928190104-399ea9e2e55f h1:lBNOc5arjvs8E5mO2tbpBpLoyyu8B6e44T7hJy6potg= github.com/coreos/pkg v0.0.0-20180928190104-399ea9e2e55f/go.mod h1:E3G3o1h8I7cfcXa63jLwjI0eiQQMgzzUDFVpN/nH/eA= github.com/dancannon/gorethink v4.0.0+incompatible h1:KFV7Gha3AuqT+gr0B/eKvGhbjmUv0qGF43aKCIKVE9A= @@ -135,36 +109,42 @@ github.com/dancannon/gorethink v4.0.0+incompatible/go.mod h1:BLvkat9KmZc1efyYwhz github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= -github.com/denisenkom/go-mssqldb v0.0.0-20181014144952-4e0d7dc8888f/go.mod h1:xN/JuLBIz4bjkxNmByTiV1IbhfnYb6oo99phBn4Eqhc= -github.com/denisenkom/go-mssqldb v0.0.0-20190328043727-2183450503ad h1:pU720selZEfSLwzto57D7pucjcjMsrGRKq5xFjyruj8= -github.com/denisenkom/go-mssqldb v0.0.0-20190328043727-2183450503ad/go.mod h1:xN/JuLBIz4bjkxNmByTiV1IbhfnYb6oo99phBn4Eqhc= +github.com/denisenkom/go-mssqldb v0.0.0-20190418034912-35416408c946 h1:xn+jBHAqNYs6CnHhJwfWZQspPHMEL+LzUk0vpqWj6eo= +github.com/denisenkom/go-mssqldb v0.0.0-20190418034912-35416408c946/go.mod h1:zAg7JM8CkOJ43xKXIj7eRO9kmWm/TW578qo+oDO6tuM= github.com/denverdino/aliyungo v0.0.0-20170926055100-d3308649c661 h1:lrWnAyy/F72MbxIxFUzKmcMCdt9Oi8RzpAxzTNQHD7o= github.com/denverdino/aliyungo v0.0.0-20170926055100-d3308649c661/go.mod h1:dV8lFg6daOBZbT6/BDGIz6Y3WFGn8juu6G+CQ6LHtl0= github.com/dgrijalva/jwt-go v3.2.0+incompatible h1:7qlOGliEKZXTDg6OTjfoBKDXWrumCAMpl/TFQ4/5kLM= github.com/dgrijalva/jwt-go v3.2.0+incompatible/go.mod h1:E3ru+11k8xSBh+hMPgOLZmtrrCbhqsmaPHjLKYnJCaQ= -github.com/dgryski/go-bitstream v0.0.0-20180413035011-3522498ce2c8/go.mod h1:VMaSuZ+SZcx/wljOQKvp5srsbCiKDEb6K2wC4+PiBmQ= github.com/digitalocean/godo v1.1.1 h1:v0A7yF3xmKLjjdJGIeBbINfMufcrrRhqZsxuVQMoT+U= github.com/digitalocean/godo v1.1.1/go.mod h1:h6faOIcZ8lWIwNQ+DN7b3CgX4Kwby5T+nbpNqkUIozU= github.com/dimchansky/utfbom v1.1.0 h1:FcM3g+nofKgUteL8dm/UpdRXNC9KmADgTpLKsu0TRo4= github.com/dimchansky/utfbom v1.1.0/go.mod h1:rO41eb7gLfo8SF1jd9F8HplJm1Fewwi4mQvIirEdv+8= -github.com/docker/distribution v2.6.2+incompatible/go.mod h1:J2gT2udsDAN96Uj4KfcMRqY0/ypR+oyYUYmja8H+y+w= -github.com/docker/docker v0.0.0-20180422163414-57142e89befe/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk= +github.com/dnaeon/go-vcr v1.0.1 h1:r8L/HqC0Hje5AXMu1ooW8oyQyOFv4GxqpL0nRP7SLLY= +github.com/dnaeon/go-vcr v1.0.1/go.mod h1:aBB1+wY4s93YsC3HHjMBMrwTj2R9FHDzUr9KyGc8n1E= +github.com/dnstap/golang-dnstap v0.0.0-20170829151710-2cf77a2b5e11/go.mod h1:s1PfVYYVmTMgCSPtho4LKBDecEHJWtiVDPNv78Z985U= github.com/docker/go-connections v0.4.0 h1:El9xVISelRB7BuFusrZozjnkIM5YnzCViNKohAFqRJQ= github.com/docker/go-connections v0.4.0/go.mod h1:Gbd7IOopHjR8Iph03tsViu4nIes5XhDvyHbTtUxmeec= github.com/docker/go-units v0.3.3 h1:Xk8S3Xj5sLGlG5g67hJmYMmUgXv5N4PhkjJHHqrwnTk= github.com/docker/go-units v0.3.3/go.mod h1:fgPhTUdO+D/Jk86RDLlptpiXQzgHJF7gydDDbaIK4Dk= -github.com/duosecurity/duo_api_golang v0.0.0-20181024123116-92fea9203dbc/go.mod h1:UqXY1lYT/ERa4OEAywUqdok1T4RCRdArkhic1Opuavo= +github.com/docker/spdystream v0.0.0-20160310174837-449fdfce4d96/go.mod h1:Qh8CwZgvJUkLughtfhJv5dyTYa91l1fOUCrgjqmcifM= github.com/duosecurity/duo_api_golang v0.0.0-20190308151101-6c680f768e74 h1:2MIhn2R6oXQbgW5yHfS+d6YqyMfXiu2L55rFZC4UD/M= github.com/duosecurity/duo_api_golang v0.0.0-20190308151101-6c680f768e74/go.mod h1:UqXY1lYT/ERa4OEAywUqdok1T4RCRdArkhic1Opuavo= -github.com/dustin/go-humanize v1.0.0/go.mod h1:HtrtbFcZ19U5GC7JDqmcUSB87Iq5E25KnS6fMYU6eOk= github.com/eapache/go-resiliency v1.1.0/go.mod h1:kFI+JgMyC7bLPUVY133qvEBtVayf5mFgVsvEsIPBvNs= github.com/eapache/go-xerial-snappy v0.0.0-20180814174437-776d5712da21/go.mod h1:+020luEh2TKB4/GOp8oxxtq0Daoen/Cii55CzbTV6DU= github.com/eapache/queue v1.1.0/go.mod h1:6eCeP0CKFpHLu8blIFXhExK/dRa7WDZfr6jVFPTqq+I= github.com/elazarl/go-bindata-assetfs v1.0.0 h1:G/bYguwHIzWq9ZoyUQqrjTmJbbYn3j3CKKpKinvZLFk= github.com/elazarl/go-bindata-assetfs v1.0.0/go.mod h1:v+YaWX3bdea5J/mo8dSETolEo7R71Vk1u8bnjau5yw4= -github.com/emirpasic/gods v1.9.0/go.mod h1:YfzfFFoVP/catgzJb4IKIqXjX78Ha8FMSDh3ymbK86o= +github.com/elazarl/goproxy v0.0.0-20170405201442-c4fc26588b6e/go.mod h1:/Zj4wYkgs4iZTTu3o/KG3Itv/qCCa8VVMlb3i9OVuzc= github.com/envoyproxy/go-control-plane v0.6.9 h1:deEH9W8ZAUGNbCdX+9iNzBOGrAOrnpJGoy0PcTqk/tE= github.com/envoyproxy/go-control-plane v0.6.9/go.mod h1:SBwIajubJHhxtWwsL9s8ss4safvEdbitLhGGK48rN6g= +github.com/envoyproxy/go-control-plane v0.7.1 h1:CwDZ3n/znIaqNalgauCWLZ6Wl7NCe6v9yjiY4kslaMk= +github.com/envoyproxy/go-control-plane v0.7.1/go.mod h1:SBwIajubJHhxtWwsL9s8ss4safvEdbitLhGGK48rN6g= +github.com/envoyproxy/protoc-gen-validate v0.0.14 h1:YBW6/cKy9prEGRYLnaGa4IDhzxZhRCtKsax8srGKDnM= +github.com/envoyproxy/protoc-gen-validate v0.0.14/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c= +github.com/estesp/manifest-tool v0.9.0/go.mod h1:w/oandYlJC/m8nkP8UaJVxsm/LwjurJQHXR27njws74= +github.com/evanphx/json-patch v0.0.0-20190203023257-5858425f7550/go.mod h1:50XU6AFN0ol/bzJsmQLiYLvXMP4fmwYFNcr97nuDLSk= +github.com/evanphx/json-patch v4.1.0+incompatible/go.mod h1:50XU6AFN0ol/bzJsmQLiYLvXMP4fmwYFNcr97nuDLSk= +github.com/farsightsec/golang-framestream v0.0.0-20181102145529-8a0cb8ba8710/go.mod h1:eNde4IQyEiA5br02AouhEHCu3p3UzrCdFR4LuQHklMI= github.com/fatih/color v1.7.0 h1:DkWD4oS2D8LGGgTQ6IvwJJXSL5Vp2ffcQg58nFV38Ys= github.com/fatih/color v1.7.0/go.mod h1:Zm6kSWBoL9eyXnKyktHP6abPY2pDugNf5KwzbycvMj4= github.com/fatih/structs v1.1.0 h1:Q7juDM0QtcnhCpeyLGQKyg4TOIghuNXrkL32pHAUMxo= @@ -172,34 +152,31 @@ github.com/fatih/structs v1.1.0/go.mod h1:9NiDSp5zOcgEDl+j00MP/WkGVPOlPRLejGD8Ga github.com/flynn/go-shlex v0.0.0-20150515145356-3f9db97f8568/go.mod h1:xEzjJPgXI435gkrCt3MPfRiAkVrwSbHsst4LCFVfpJc= github.com/fsnotify/fsnotify v1.4.7 h1:IXs+QLmnXW2CcXuY+8Mzv/fWEsPGWxqefPtCP5CnV9I= github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo= -github.com/fullsailor/pkcs7 v0.0.0-20180613152042-8306686428a5 h1:v+vxrd9XS8uWIXG2RK0BHCnXc30qLVQXVqbK+IOmpXk= -github.com/fullsailor/pkcs7 v0.0.0-20180613152042-8306686428a5/go.mod h1:KnogPXtdwXqoenmZCw6S+25EAm2MkxbG0deNDu4cbSA= +github.com/fullsailor/pkcs7 v0.0.0-20190404230743-d7302db945fa h1:RDBNVkRviHZtvDvId8XSGPu3rmpmSe+wKRcEWNgsfWU= +github.com/fullsailor/pkcs7 v0.0.0-20190404230743-d7302db945fa/go.mod h1:KnogPXtdwXqoenmZCw6S+25EAm2MkxbG0deNDu4cbSA= github.com/gammazero/deque v0.0.0-20190130191400-2afb3858e9c7 h1:D2LrfOPgGHQprIxmsTpxtzhpmF66HoM6rXSmcqaX7h8= github.com/gammazero/deque v0.0.0-20190130191400-2afb3858e9c7/go.mod h1:GeIq9qoE43YdGnDXURnmKTnGg15pQz4mYkXSTChbneI= -github.com/gammazero/workerpool v0.0.0-20181230203049-86a96b5d5d92 h1:EipXK6U05IQ2wtuFRn4k3h0+2lXypzItoXGVyf4r9Io= -github.com/gammazero/workerpool v0.0.0-20181230203049-86a96b5d5d92/go.mod h1:w9RqFVO2BM3xwWEcAB8Fwp0OviTBBEiRmSBDfbXnd3w= +github.com/gammazero/workerpool v0.0.0-20190406235159-88d534f22b56 h1:VzbudKn/nvxYKOdzgkEBS6SSreRjAgoJ+ZeS4wPFkgc= +github.com/gammazero/workerpool v0.0.0-20190406235159-88d534f22b56/go.mod h1:w9RqFVO2BM3xwWEcAB8Fwp0OviTBBEiRmSBDfbXnd3w= github.com/garyburd/redigo v1.6.0 h1:0VruCpn7yAIIu7pWVClQC8wxCJEcG3nyzpMSHKi1PQc= github.com/garyburd/redigo v1.6.0/go.mod h1:NR3MbYisc3/PwhQ00EMzDiPmrwpPxAn5GI05/YaO1SY= -github.com/getkin/kin-openapi v0.1.0/go.mod h1:+0ZtELZf+SlWH8ZdA/IeFb3L/PKOKJx8eGxAlUZ/sOU= github.com/ghodss/yaml v1.0.0 h1:wQHKEahhL6wmXdzwWG11gIVCkOv05bNOh+Rxn0yngAk= github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04= -github.com/gliderlabs/ssh v0.1.1/go.mod h1:U7qILu1NlMHj9FlMhZLlkCdDnU1DBEAqr0aevW3Awn0= -github.com/glycerine/go-unsnap-stream v0.0.0-20180323001048-9f0cb55181dd/go.mod h1:/20jfyN9Y5QPEAprSgKAUr+glWDY39ZiUEAYOEv5dsE= -github.com/glycerine/goconvey v0.0.0-20180728074245-46e3a41ad493/go.mod h1:Ogl1Tioa0aV7gstGFO7KhffUsb9M4ydbEbbxpcEDc24= github.com/go-errors/errors v1.0.1 h1:LUHzmkK3GUKUrL/1gfBUxAHzcev3apQlezX/+O7ma6w= github.com/go-errors/errors v1.0.1/go.mod h1:f4zRHt4oKfwPJE5k8C9vpYG+aDHdBFUsgrm6/TyX73Q= github.com/go-ini/ini v1.25.4 h1:Mujh4R/dH6YL8bxuISne3xX2+qcQ9p0IxKAP6ExWoUo= github.com/go-ini/ini v1.25.4/go.mod h1:ByCAeIL28uOIIG0E3PJtZPDL8WnHpFKFOtgjp+3Ies8= +github.com/go-ini/ini v1.42.0 h1:TWr1wGj35+UiWHlBA8er89seFXxzwFn11spilrrj+38= +github.com/go-ini/ini v1.42.0/go.mod h1:ByCAeIL28uOIIG0E3PJtZPDL8WnHpFKFOtgjp+3Ies8= github.com/go-kit/kit v0.8.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as= -github.com/go-ldap/ldap v2.5.1+incompatible/go.mod h1:qfd9rJvER9Q0/D/Sqn1DfHRoBp40uXYvFoEVrNEPqRc= github.com/go-ldap/ldap v3.0.2+incompatible h1:kD5HQcAzlQ7yrhfn+h+MSABeAy/jAJhvIJ/QDllP44g= github.com/go-ldap/ldap v3.0.2+incompatible/go.mod h1:qfd9rJvER9Q0/D/Sqn1DfHRoBp40uXYvFoEVrNEPqRc= github.com/go-log/log v0.1.0 h1:wudGTNsiGzrD5ZjgIkVZ517ugi2XRe9Q/xRCzwEO4/U= github.com/go-log/log v0.1.0/go.mod h1:4mBwpdRMFLiuXZDCwU2lKQFsoSCo72j3HqBK9d81N2M= github.com/go-logfmt/logfmt v0.3.0/go.mod h1:Qt1PoO58o5twSAckw1HlFXLmHsOX5/0LbT9GBnD5lWE= +github.com/go-logfmt/logfmt v0.4.0/go.mod h1:3RMwSq7FuexP4Kalkev3ejPJsZTpXXBr9+V4qmtdjCk= github.com/go-ole/go-ole v1.2.4 h1:nNBDSCOigTSiarFpYE9J/KtEA1IOW4CNeqT9TQDqCxI= github.com/go-ole/go-ole v1.2.4/go.mod h1:XCwSNxSkXRo4vlyPy93sltvi/qJq0jqQhjqQNIwKuxM= -github.com/go-sql-driver/mysql v1.4.0/go.mod h1:zAC/RDZ24gD3HViQzih4MyKcchzm+sOG5ZlKdlhCg5w= github.com/go-sql-driver/mysql v1.4.1 h1:g24URVg0OFbNUTx9qqY1IRZ9D9z3iPyi5zKhQZpNwpA= github.com/go-sql-driver/mysql v1.4.1/go.mod h1:zAC/RDZ24gD3HViQzih4MyKcchzm+sOG5ZlKdlhCg5w= github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY= @@ -207,18 +184,19 @@ github.com/go-stomp/stomp v2.0.2+incompatible h1:0yPknMJh32lE2xiCFGW5t/KgamhUC4O github.com/go-stomp/stomp v2.0.2+incompatible/go.mod h1:VqCtqNZv1226A1/79yh+rMiFUcfY3R109np+7ke4n0c= github.com/go-test/deep v1.0.1 h1:UQhStjbkDClarlmv0am7OXXO4/GaPdCGiUiMTvi28sg= github.com/go-test/deep v1.0.1/go.mod h1:wGDj63lr65AM2AQyKZd/NYHGb0R+1RLqB8NKt3aSFNA= -github.com/gocql/gocql v0.0.0-20181117210152-33c0e89ca93a/go.mod h1:4Fw1eo5iaEhDUs8XyuhSVCVy52Jq3L+/3GJgYkwc+/0= -github.com/gocql/gocql v0.0.0-20190325140904-fc3925ac2cbd h1:yub0WC7grIFfQgGPDyfOdrqoFqfRbRiwKQXbSOOHjoQ= -github.com/gocql/gocql v0.0.0-20190325140904-fc3925ac2cbd/go.mod h1:4Fw1eo5iaEhDUs8XyuhSVCVy52Jq3L+/3GJgYkwc+/0= +github.com/gocql/gocql v0.0.0-20190418090649-59a610c947c5 h1:ja4omKSx9OiML8GnnDG13qOX58UAcSJfOmce21YXALk= +github.com/gocql/gocql v0.0.0-20190418090649-59a610c947c5/go.mod h1:4Fw1eo5iaEhDUs8XyuhSVCVy52Jq3L+/3GJgYkwc+/0= github.com/gogo/googleapis v1.1.0 h1:kFkMAZBNAn4j7K0GiZr8cRYzejq68VbheufiV3YuyFI= github.com/gogo/googleapis v1.1.0/go.mod h1:gf4bu3Q80BeJ6H1S1vYPm8/ELATdvryBaNFGgqEef3s= +github.com/gogo/googleapis v1.2.0 h1:Z0v3OJDotX9ZBpdz2V+AI7F4fITSZhVE5mg6GQppwMM= +github.com/gogo/googleapis v1.2.0/go.mod h1:Njal3psf3qN6dwBtQfUmBZh2ybovJ0tlu3o/AC7HYjU= github.com/gogo/protobuf v1.1.1/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ= github.com/gogo/protobuf v1.2.0/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ= github.com/gogo/protobuf v1.2.1 h1:/s5zKNz0uPFCZ5hddgPdo2TK2TVrUNMn0OOX8/aZMTE= github.com/gogo/protobuf v1.2.1/go.mod h1:hp+jE20tsWTFYpLwKvXlhS1hjn+gTNwPg2I6zVXpSg4= -github.com/golang/gddo v0.0.0-20181116215533-9bd4a3295021/go.mod h1:xEhNfoBDX1hzLm2Nf80qUvZ2sVwoMZ8d6IE2SrsQfh4= github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b h1:VKtxabqXZkF25pY9ekfRL6a582T4P37/31XEstQ5p58= github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q= +github.com/golang/groupcache v0.0.0-20160516000752-02826c3e7903/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= github.com/golang/groupcache v0.0.0-20190129154638-5b532d6fd5ef h1:veQD95Isof8w9/WXiA+pa3tz3fJXkt5B7QaRBrM62gk= github.com/golang/groupcache v0.0.0-20190129154638-5b532d6fd5ef/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= github.com/golang/lint v0.0.0-20180702182130-06c8688daad7/go.mod h1:tluoj9z5200jBnyusfRPU2LqT6J+DAorxEvtC7LHB+E= @@ -234,18 +212,16 @@ github.com/golang/snappy v0.0.1 h1:Qgr9rKW7uDUkrbSmQeiDsGa8SjGyCOGtuasMWwvp2P4= github.com/golang/snappy v0.0.1/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= github.com/google/btree v0.0.0-20180813153112-4030bb1f1f0c h1:964Od4U6p2jUkFxvCydnIczKteheJEzHRToSGK3Bnlw= github.com/google/btree v0.0.0-20180813153112-4030bb1f1f0c/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ= -github.com/google/btree v1.0.0 h1:0udJVsspx3VBr5FwtLhQQtuAsVc79tTq0ocGIPAU6qo= -github.com/google/btree v1.0.0/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ= github.com/google/go-cmp v0.2.0 h1:+dTQ8DZQJz0Mb/HjFlkptS1FeQ4cWSnN941F8aEG4SQ= github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M= github.com/google/go-github v17.0.0+incompatible h1:N0LgJ1j65A7kfXrZnUDaYCs/Sf4rEjNlfyDHW9dolSY= github.com/google/go-github v17.0.0+incompatible/go.mod h1:zLgOLi98H3fifZn+44m+umXrS52loVEgC2AApnigrVQ= github.com/google/go-querystring v0.0.0-20170111101155-53e6ce116135 h1:zLTLjkaOFEFIOxY5BWLFLwh+cL8vOBW4XJ2aqLE/Tf0= github.com/google/go-querystring v0.0.0-20170111101155-53e6ce116135/go.mod h1:odCYkC5MyYFN7vkCjXpyrEuKhc/BUO6wN/zVPAxq5ck= -github.com/google/go-querystring v1.0.0 h1:Xkwi/a1rcvNg1PPYe5vI8GbeBY/jrVuDX5ASuANWTrk= -github.com/google/go-querystring v1.0.0/go.mod h1:odCYkC5MyYFN7vkCjXpyrEuKhc/BUO6wN/zVPAxq5ck= github.com/google/gofuzz v0.0.0-20170612174753-24818f796faf h1:+RRA9JqSOZFfKrOeqr2z77+8R2RKyh8PG66dcu1V0ck= github.com/google/gofuzz v0.0.0-20170612174753-24818f796faf/go.mod h1:HP5RmnzzSNb993RKQDq4+1A4ia9nllfqcQFTQJedwGI= +github.com/google/gofuzz v1.0.0 h1:A8PeW59pxE9IoFRqBp37U+mSNaQoZ46F1f0f863XSXw= +github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= github.com/google/martian v2.1.0+incompatible/go.mod h1:9I4somxYTbIHy5NJKHRl3wXiIaQGbYVAs8BPL6v8lEs= github.com/google/pprof v0.0.0-20181206194817-3ea8567a2e57/go.mod h1:zfwlbNMJ+OItoe0UupaVj+oy1omPYYDuagoSzA8v9mc= github.com/google/uuid v1.0.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= @@ -253,20 +229,19 @@ github.com/google/uuid v1.1.0 h1:Jf4mxPC/ziBnoPIdpQdPJ9OeiomAUHLvxmPRSPH9m4s= github.com/google/uuid v1.1.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/google/uuid v1.1.1 h1:Gkbcsh/GbpXz7lPftLA3P6TYMwjCLYm83jiFQZF/3gY= github.com/google/uuid v1.1.1/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= -github.com/googleapis/gax-go v2.0.0+incompatible h1:j0GKcs05QVmm7yesiZq2+9cxHkNK9YM6zKx4D2qucQU= -github.com/googleapis/gax-go v2.0.0+incompatible/go.mod h1:SFVmujtThgffbyetf+mdk2eWhX2bMyUtNHzFKcPA9HY= -github.com/googleapis/gax-go/v2 v2.0.3 h1:siORttZ36U2R/WjiJuDz8znElWBiAlO9rVt+mqJt0Cc= -github.com/googleapis/gax-go/v2 v2.0.3/go.mod h1:LLvjysVCY1JZeum8Z6l8qUty8fiNwE08qbEPm1M08qg= +github.com/googleapis/gax-go/v2 v2.0.4 h1:hU4mGcQI4DaAYW+IbTun+2qEZVFxK0ySjQLTbS0VQKc= +github.com/googleapis/gax-go/v2 v2.0.4/go.mod h1:0Wqv26UfaUD9n4G6kQubkQ+KchISgw+vpHVxEJEs9eg= +github.com/googleapis/gnostic v0.0.0-20170729233727-0c5108395e2d/go.mod h1:sJBsCZ4ayReDTBIg8b9dl28c5xFWyhBTVRp3pOg5EKY= github.com/googleapis/gnostic v0.2.0 h1:l6N3VoaVzTncYYW+9yOz2LJJammFZGBO13sqgEhpy9g= github.com/googleapis/gnostic v0.2.0/go.mod h1:sJBsCZ4ayReDTBIg8b9dl28c5xFWyhBTVRp3pOg5EKY= github.com/gophercloud/gophercloud v0.0.0-20180828235145-f29afc2cceca h1:wobTb8SE189AuxzEKClyYxiI4nUGWlpVtl13eLiFlOE= github.com/gophercloud/gophercloud v0.0.0-20180828235145-f29afc2cceca/go.mod h1:3WdhXV3rUYy9p6AUW8d94kr+HS62Y4VL9mBnFxsD8q4= +github.com/gophercloud/gophercloud v0.0.0-20190307220656-fe1ba5ce12dd h1:tkA3C/XTk8iACLOlTez37pL+0iGSYkkRGKdXgJ6ZylM= +github.com/gophercloud/gophercloud v0.0.0-20190307220656-fe1ba5ce12dd/go.mod h1:vxM41WHh5uqHVBMZHzuwNOHh8XEoIEcSTewFxm1c5g8= github.com/gopherjs/gopherjs v0.0.0-20180825215210-0210a2f0f73c h1:16eHWuMGvCjSfgRJKqIzapE78onvvTbdi1rMkU00lZw= github.com/gopherjs/gopherjs v0.0.0-20180825215210-0210a2f0f73c/go.mod h1:wJfORRmW1u3UXTncJ5qlYoELFm8eSnnEO6hX4iZ3EWY= github.com/gopherjs/gopherjs v0.0.0-20181017120253-0766667cb4d1 h1:EGx4pi6eqNxGaHF6qqu48+N2wcFQ5qg5FXgOdqsJ5d8= github.com/gopherjs/gopherjs v0.0.0-20181017120253-0766667cb4d1/go.mod h1:wJfORRmW1u3UXTncJ5qlYoELFm8eSnnEO6hX4iZ3EWY= -github.com/goreleaser/goreleaser v0.94.0/go.mod h1:OjbYR2NhOI6AEUWCowMSBzo9nP1aRif3sYtx+rhp+Zo= -github.com/goreleaser/nfpm v0.9.7/go.mod h1:F2yzin6cBAL9gb+mSiReuXdsfTrOQwDMsuSpULof+y4= github.com/gorhill/cronexpr v0.0.0-20180427100037-88b0669f7d75 h1:f0n1xnMSmBLzVfsMMvriDyA75NB/oBgILX2GcHXIQzY= github.com/gorhill/cronexpr v0.0.0-20180427100037-88b0669f7d75/go.mod h1:g2644b03hfBX9Ov0ZBDgXXens4rxSxmqFBbhvKv2yVA= github.com/gorilla/context v1.1.1/go.mod h1:kBGZzfjB9CEq2AlWe17Uuf7NDRt0dE0s8S51q0aT7Yg= @@ -277,17 +252,19 @@ github.com/gotestyourself/gotestyourself v2.2.0+incompatible h1:AQwinXlbQR2HvPjQ github.com/gotestyourself/gotestyourself v2.2.0+incompatible/go.mod h1:zZKM6oeNM8k+FRljX1mnzVYeS8wiGgQyvST1/GafPbY= github.com/gregjones/httpcache v0.0.0-20180305231024-9cad4c3443a7 h1:pdN6V1QBWetyv/0+wjACpqVH+eVULgEjkurDLq3goeM= github.com/gregjones/httpcache v0.0.0-20180305231024-9cad4c3443a7/go.mod h1:FecbI9+v66THATjSRHfNgh1IVFe/9kFxbXtjV0ctIMA= +github.com/gregjones/httpcache v0.0.0-20190212212710-3befbb6ad0cc h1:f8eY6cV/x1x+HLjOp4r72s/31/V2aTUtg5oKRRPf8/Q= +github.com/gregjones/httpcache v0.0.0-20190212212710-3befbb6ad0cc/go.mod h1:FecbI9+v66THATjSRHfNgh1IVFe/9kFxbXtjV0ctIMA= github.com/grpc-ecosystem/go-grpc-middleware v1.0.0 h1:Iju5GlWwrvL6UBg4zJJt3btmonfrMlCDdsejg4CZE7c= github.com/grpc-ecosystem/go-grpc-middleware v1.0.0/go.mod h1:FiyG127CGDf3tlThmgyCl78X/SZQqEOJBCDaAfeWzPs= github.com/grpc-ecosystem/go-grpc-prometheus v1.2.0 h1:Ovs26xHkKqVztRpIrF/92BcuyuQ/YW4NSIpoGtfXNho= github.com/grpc-ecosystem/go-grpc-prometheus v1.2.0/go.mod h1:8NvIoxWQoOIhqOTXgfV/d3M/q6VIi02HzZEHgUlZvzk= -github.com/grpc-ecosystem/grpc-gateway v1.5.0/go.mod h1:RSKVYQBd5MCa4OVpNdGskqpgL2+G+NZTnrVHpWWfpdw= github.com/grpc-ecosystem/grpc-gateway v1.6.2/go.mod h1:RSKVYQBd5MCa4OVpNdGskqpgL2+G+NZTnrVHpWWfpdw= +github.com/grpc-ecosystem/grpc-gateway v1.8.3/go.mod h1:vNeuVxBJEsws4ogUvrchl83t/GYV9WGTSLVdBhOQFDY= github.com/grpc-ecosystem/grpc-gateway v1.8.5 h1:2+KSC78XiO6Qy0hIjfc1OD9H+hsaJdJlb8Kqsd41CTE= github.com/grpc-ecosystem/grpc-gateway v1.8.5/go.mod h1:vNeuVxBJEsws4ogUvrchl83t/GYV9WGTSLVdBhOQFDY= +github.com/grpc-ecosystem/grpc-opentracing v0.0.0-20180507213350-8e809c8a8645/go.mod h1:6iZfnjpejD4L/4DwD7NryNaJyCQdzwWwH2MWhCA90Kw= github.com/hailocab/go-hostpool v0.0.0-20160125115350-e80d13ce29ed h1:5upAirOpQc1Q53c0bnx2ufif5kANL7bfZWcc6VJWJd8= github.com/hailocab/go-hostpool v0.0.0-20160125115350-e80d13ce29ed/go.mod h1:tMWxXQ9wFIaZeTI9F+hmhFiGpFmhOHzyShyFUhRm0H4= -github.com/hashicorp/consul v1.4.0/go.mod h1:mFrjN1mfidgJfYP1xrJCF+AfRhr6Eaqhb2+sfyn/OOI= github.com/hashicorp/consul v1.4.2 h1:D9iJoJb8Ehe/Zmr+UEE3U3FjOLZ4LUxqFMl4O43BM1U= github.com/hashicorp/consul v1.4.2/go.mod h1:mFrjN1mfidgJfYP1xrJCF+AfRhr6Eaqhb2+sfyn/OOI= github.com/hashicorp/consul v1.4.4 h1:DR1+5EGgnPsd/LIsK3c9RDvajcsV5GOkGQBSNd3dpn8= @@ -298,34 +275,27 @@ github.com/hashicorp/go-cleanhttp v0.5.0 h1:wvCrVc9TjDls6+YGAF2hAifE1E5U1+b4tH6K github.com/hashicorp/go-cleanhttp v0.5.0/go.mod h1:JpRdi6/HCYpAwUzNwuwqhbovhLtngrth3wmdIIUrZ80= github.com/hashicorp/go-cleanhttp v0.5.1 h1:dH3aiDG9Jvb5r5+bYHsikaOUIpcM0xvgMXVoDkXMzJM= github.com/hashicorp/go-cleanhttp v0.5.1/go.mod h1:JpRdi6/HCYpAwUzNwuwqhbovhLtngrth3wmdIIUrZ80= -github.com/hashicorp/go-discover v0.0.0-20190319153616-61771d82ff54 h1:TfczkKkpOH9xfR0vZaSpW2FNP6hh2qm51n9yo20owBE= -github.com/hashicorp/go-discover v0.0.0-20190319153616-61771d82ff54/go.mod h1:CImRKBstQOB5m5fNKXFT/CCp5WyWCLvcYydd0kb2EaA= +github.com/hashicorp/go-discover v0.0.0-20190408185603-6ccdb67f9b84 h1:ImeFWg0F3G8xtba0MrlDXgw8lmR4dDgwqZrrWOowelY= +github.com/hashicorp/go-discover v0.0.0-20190408185603-6ccdb67f9b84/go.mod h1:FTV98wIi2RF5iDl1iLR/cB+no+B//ODP6133EcC9djw= github.com/hashicorp/go-gcp-common v0.5.0 h1:kkIQTjNTopn4eXQ1+lCiHYZXUtgIZvbc6YtAQkMnTos= github.com/hashicorp/go-gcp-common v0.5.0/go.mod h1:IDGUI2N/OS3PiU4qZcXJeWKPI6O/9Y8hOrbSiMcqyYw= github.com/hashicorp/go-hclog v0.0.0-20180709165350-ff2cf002a8dd/go.mod h1:9bjs9uLqI8l75knNv3lV1kA55veR+WUPSiKIWcQHudI= -github.com/hashicorp/go-hclog v0.0.0-20181001195459-61d530d6c27f/go.mod h1:5CU+agLiy3J7N7QjHK5d05KxGsuXiQLrjA0H7acj2lQ= github.com/hashicorp/go-hclog v0.8.0 h1:z3ollgGRg8RjfJH6UVBaG54R70GFd++QOkvnJH3VSBY= github.com/hashicorp/go-hclog v0.8.0/go.mod h1:5CU+agLiy3J7N7QjHK5d05KxGsuXiQLrjA0H7acj2lQ= github.com/hashicorp/go-immutable-radix v1.0.0 h1:AKDB1HM5PWEA7i4nhcpwOrO2byshxBjXVn/J/3+z5/0= github.com/hashicorp/go-immutable-radix v1.0.0/go.mod h1:0y9vanUI8NX6FsYoO3zeMjhV/C5i9g4Q3DwcSNZ4P60= -github.com/hashicorp/go-memdb v0.0.0-20181108192425-032f93b25bec/go.mod h1:kbfItVoBJwCfKXDXN4YoAXjxcFVZ7MRrJzyTX6H4giE= -github.com/hashicorp/go-memdb v1.0.0 h1:K1O4N2VPndZiTrdH3lmmf5bemr9Xw81KjVwhReIUjTQ= -github.com/hashicorp/go-memdb v1.0.0/go.mod h1:I6dKdmYhZqU0RJSheVEWgTNWdVQH5QvTgIUQ0t/t32M= -github.com/hashicorp/go-msgpack v0.0.0-20150518234257-fa3f63826f7c/go.mod h1:ahLV/dePpqEmjfWmKiqvPkv/twdG7iPBM1vqhUKIvfM= +github.com/hashicorp/go-memdb v1.0.1 h1:QR2h3O60I0DSvCsogh77kZUPzZBkbDSfeUjzhrK8p04= +github.com/hashicorp/go-memdb v1.0.1/go.mod h1:I6dKdmYhZqU0RJSheVEWgTNWdVQH5QvTgIUQ0t/t32M= github.com/hashicorp/go-msgpack v0.5.3 h1:zKjpN5BK/P5lMYrLmBHdBULWbJ0XpYR+7NGzqkZzoD4= github.com/hashicorp/go-msgpack v0.5.3/go.mod h1:ahLV/dePpqEmjfWmKiqvPkv/twdG7iPBM1vqhUKIvfM= github.com/hashicorp/go-multierror v1.0.0 h1:iVjPR7a6H0tWELX5NxNe7bYopibicUzc7uPribsnS6o= github.com/hashicorp/go-multierror v1.0.0/go.mod h1:dHtQlpGsu+cZNNAkkCN/P3hoUDHhCYQXV3UM06sGGrk= -github.com/hashicorp/go-plugin v0.0.0-20181030172320-54b6ff97d818/go.mod h1:Ft7ju2vWzhO0ETMKUVo12XmXmII6eSUS4rsPTkY/siA= github.com/hashicorp/go-plugin v1.0.0 h1:/gQ1sNR8/LHpoxKRQq4PmLBuacfZb4tC93e9B30o/7c= github.com/hashicorp/go-plugin v1.0.0/go.mod h1:++UyYGoz3o5w9ZzAdZxtQKrWWP+iqPBn3cQptSMzBuY= -github.com/hashicorp/go-retryablehttp v0.5.0/go.mod h1:9B5zBasrRhHXnJnui7y6sL7es7NDiJgTc6Er0maI1Xs= github.com/hashicorp/go-retryablehttp v0.5.3 h1:QlWt0KvWT0lq8MFppF9tsJGF+ynG7ztc2KIPhzRGk7s= github.com/hashicorp/go-retryablehttp v0.5.3/go.mod h1:9B5zBasrRhHXnJnui7y6sL7es7NDiJgTc6Er0maI1Xs= -github.com/hashicorp/go-rootcerts v0.0.0-20160503143440-6bb64b370b90/go.mod h1:o4zcYY1e0GEZI6eSEr+43QDYmuGglw1qSO6qdHUHCgg= github.com/hashicorp/go-rootcerts v1.0.0 h1:Rqb66Oo1X/eSV1x66xbDccZjhJigjg0+e82kpwzSwCI= github.com/hashicorp/go-rootcerts v1.0.0/go.mod h1:K6zTfqpRlCUIjkwsN4Z+hiSfzSTQa6eBIzfwKfwNnHU= -github.com/hashicorp/go-sockaddr v0.0.0-20180320115054-6d291a969b86/go.mod h1:7Xibr9yA9JjQq1JpNB2Vw7kxv8xerXegt+ozgdvDeDU= github.com/hashicorp/go-sockaddr v1.0.0/go.mod h1:7Xibr9yA9JjQq1JpNB2Vw7kxv8xerXegt+ozgdvDeDU= github.com/hashicorp/go-sockaddr v1.0.1 h1:eCkkJ5KOOktDvwbsE9KPyiBWaOfp1ZNy2gLHgL8PSBM= github.com/hashicorp/go-sockaddr v1.0.1/go.mod h1:rB4wwRAUzs07qva3c5SdrY/NEtAUjGlgmH/UkBUC97A= @@ -336,7 +306,6 @@ github.com/hashicorp/go-syslog v1.0.0/go.mod h1:qPfqrKkXGihmCqbJM2mZgkZGvKG1dFdv github.com/hashicorp/go-uuid v1.0.0/go.mod h1:6SBZvOh/SIDV7/2o3Jml5SYk/TvGqwFJ/bN7x4byOro= github.com/hashicorp/go-uuid v1.0.1 h1:fv1ep09latC32wFoVwnqcnKJGnMSdBanPczbHAYm1BE= github.com/hashicorp/go-uuid v1.0.1/go.mod h1:6SBZvOh/SIDV7/2o3Jml5SYk/TvGqwFJ/bN7x4byOro= -github.com/hashicorp/go-version v1.0.0/go.mod h1:fltr4n8CU8Ke44wwGCBoEymUuxUHl09ZGVZPK5anwXA= github.com/hashicorp/go-version v1.1.0 h1:bPIoEKD27tNdebFGGxxYwcL4nepeY4j1QP23PFRGzg0= github.com/hashicorp/go-version v1.1.0/go.mod h1:fltr4n8CU8Ke44wwGCBoEymUuxUHl09ZGVZPK5anwXA= github.com/hashicorp/go.net v0.0.1 h1:sNCoNyDEvN1xa+X0baata4RdcpKwcMS6DH+xwfqPgjw= @@ -353,77 +322,67 @@ github.com/hashicorp/logutils v1.0.0 h1:dLEQVugN8vlakKOUE3ihGLTZJRB4j+M2cdTm/ORI github.com/hashicorp/logutils v1.0.0/go.mod h1:QIAnNjmIWmVIIkWDTG1z5v++HQmx9WQRO+LraFDTW64= github.com/hashicorp/mdns v1.0.0 h1:WhIgCr5a7AaVH6jPUwjtRuuE7/RDufnUvzIr48smyxs= github.com/hashicorp/mdns v1.0.0/go.mod h1:tL+uN++7HEJ6SQLQ2/p+z2pH24WQKWjBPkE0mNTz8vQ= -github.com/hashicorp/memberlist v0.1.0/go.mod h1:ncdBp14cuox2iFOq3kDiquKU6fqsTBc3W6JvZwjxxsE= github.com/hashicorp/memberlist v0.1.3 h1:EmmoJme1matNzb+hMpDuR/0sbJSUisxyqBGG676r31M= github.com/hashicorp/memberlist v0.1.3/go.mod h1:ajVTdAv/9Im8oMAAj5G31PhhMCZJV2pPBoIllUwCN7I= github.com/hashicorp/net-rpc-msgpackrpc v0.0.0-20151116020338-a14192a58a69 h1:lc3c72qGlIMDqQpQH82Y4vaglRMMFdJbziYWriR4UcE= github.com/hashicorp/net-rpc-msgpackrpc v0.0.0-20151116020338-a14192a58a69/go.mod h1:/z+jUGRBlwVpUZfjute9jWaF6/HuhjuFQuL1YXzVD1Q= -github.com/hashicorp/nomad v0.8.7 h1:jOrmJdAoWcyhKgoG4OxHQhG5SU6RniXFjfwKg6a492U= -github.com/hashicorp/nomad v0.8.7/go.mod h1:WRaKjdO1G2iqi86TvTjIYtKTyxg4pl7NLr9InxtWaI0= -github.com/hashicorp/raft v1.0.0 h1:htBVktAOtGs4Le5Z7K8SF5H2+oWsQFYVmOgH5loro7Y= -github.com/hashicorp/raft v1.0.0/go.mod h1:DVSAWItjLjTOkVbSpWQ0j0kUADIvDaCtBxIcbNAQLkI= +github.com/hashicorp/nomad/api v0.0.0-20190419150859-8a0df4034dc4 h1:AI83pe3zptMoaIt8dQ7qN/FeSmWmXgvhSzr3tjUJXx0= +github.com/hashicorp/nomad/api v0.0.0-20190419150859-8a0df4034dc4/go.mod h1:BDngVi1f4UA6aJq9WYTgxhfWSE1+42xshvstLU2fRGk= +github.com/hashicorp/raft v1.0.1 h1:94uRdS11oEneUkxmXq6Vg9shNhBILh2UTb9crQjJWl0= +github.com/hashicorp/raft v1.0.1/go.mod h1:DVSAWItjLjTOkVbSpWQ0j0kUADIvDaCtBxIcbNAQLkI= github.com/hashicorp/raft-boltdb v0.0.0-20171010151810-6e5ba93211ea h1:xykPFhrBAS2J0VBzVa5e80b5ZtYuNQtgXjN40qBZlD4= github.com/hashicorp/raft-boltdb v0.0.0-20171010151810-6e5ba93211ea/go.mod h1:pNv7Wc3ycL6F5oOWn+tPGo2gWD4a5X+yp/ntwdKLjRk= -github.com/hashicorp/serf v0.8.1/go.mod h1:h/Ru6tmZazX7WO/GDmwdpS975F019L4t5ng5IgwbNrE= github.com/hashicorp/serf v0.8.2 h1:YZ7UKsJv+hKjqGVUUbtE3HNj79Eln2oQ75tniF6iPt0= github.com/hashicorp/serf v0.8.2/go.mod h1:6hOLApaqBFA1NXqRQAsxw9QxuDEvNxSQRwA/JwenrHc= -github.com/hashicorp/vault v0.11.5/go.mod h1:KfSyffbKxoVyspOdlaGVjIuwLobi07qD1bAbosPMpP0= -github.com/hashicorp/vault v1.1.0 h1:v79NUgO5xCZnXVzUkIqFOXtP8YhpnHAi1fk3eo9cuOE= -github.com/hashicorp/vault v1.1.0/go.mod h1:KfSyffbKxoVyspOdlaGVjIuwLobi07qD1bAbosPMpP0= -github.com/hashicorp/vault-plugin-auth-alicloud v0.0.0-20190320211238-36e70c54375f h1:yGxKygXLLfXKXYMBWDVja7dxxnTNYlYz81lpx2GRh4c= -github.com/hashicorp/vault-plugin-auth-alicloud v0.0.0-20190320211238-36e70c54375f/go.mod h1:o3i5QQWgV5+SYouIn++L9D0kbhLYB3FjxNRHNf6KS+Q= -github.com/hashicorp/vault-plugin-auth-azure v0.0.0-20190320211138-f34b96803f04 h1:MzPikhU6lh/tzbS5/+aj876HM+NkPOSe6C9cP/zudlU= -github.com/hashicorp/vault-plugin-auth-azure v0.0.0-20190320211138-f34b96803f04/go.mod h1:f+VmjSQIxxO+YTeO3FbPWRPCPbd3f3lwpP6jaO/YduQ= -github.com/hashicorp/vault-plugin-auth-centrify v0.0.0-20190320211357-44eb061bdfd8 h1:t3v3tm2pkxu7fgoBrrXcv3DTsiJCZCkgwGXFpm0+be8= -github.com/hashicorp/vault-plugin-auth-centrify v0.0.0-20190320211357-44eb061bdfd8/go.mod h1:IIz+CMBKBEFyjeBeFUlpoUuMOyFb7mybOUNP6GX1xuk= -github.com/hashicorp/vault-plugin-auth-gcp v0.0.0-20190320214413-e8308b5e41c9 h1:8dbhVmPoLPBzYFXkLHl1Gp4lkO1mFwFyyXHanINstHw= -github.com/hashicorp/vault-plugin-auth-gcp v0.0.0-20190320214413-e8308b5e41c9/go.mod h1:E/E+5CuQCjOn/YGCmZ/tA7GwLey/lN1PwwJOOa9Iqy0= -github.com/hashicorp/vault-plugin-auth-jwt v0.0.0-20190321042813-9474f90fb1df h1:K1dfrdfHKd6IcOGCwmGF1/UTqI0psKnRJ1G49WKn0Zw= -github.com/hashicorp/vault-plugin-auth-jwt v0.0.0-20190321042813-9474f90fb1df/go.mod h1:j6Xmkj3dzuC63mivquwVVTlxjwDndwNxi4cJUku40J8= -github.com/hashicorp/vault-plugin-auth-kubernetes v0.0.0-20190328163920-79931ee7aad5 h1:wJzxQBOoas0YkjEpDKas+wWoDbpKBtsFYcNK3tNUP5Y= -github.com/hashicorp/vault-plugin-auth-kubernetes v0.0.0-20190328163920-79931ee7aad5/go.mod h1:PqRUU5TaQ6FwVTsHPLrJs1F+T5IjbSzlfTy9cTyGeHM= -github.com/hashicorp/vault-plugin-secrets-ad v0.0.0-20190327182327-ed2c3d4c3d95 h1:8cIHbCsHHPn85gdoslbiw5A6j3Hbh0ezCbOG9bYeI3I= -github.com/hashicorp/vault-plugin-secrets-ad v0.0.0-20190327182327-ed2c3d4c3d95/go.mod h1:4vRQzvp3JI+g4oUqzcklIEj2UKyhQnpIo+BDbh2uzYM= -github.com/hashicorp/vault-plugin-secrets-alicloud v0.0.0-20190320213517-3307bdf683cb h1:pY6UDWcA1ZBNLDHt0Q/bzXr/HwbqPV/l6UgM2P+PFt4= -github.com/hashicorp/vault-plugin-secrets-alicloud v0.0.0-20190320213517-3307bdf683cb/go.mod h1:rl8WzY7++fZMLXd6Z/k/o9wUmMbOqpTLhbtKs1loMU0= -github.com/hashicorp/vault-plugin-secrets-azure v0.0.0-20190320211922-2dc8a8a5e490 h1:JfNEC8hCXOqQ8f6ISAtLa/1Ugk0mMrOjOkt8vYtZVGU= -github.com/hashicorp/vault-plugin-secrets-azure v0.0.0-20190320211922-2dc8a8a5e490/go.mod h1:/DhLpYuRP2o00gkj6S0Gy7NvKk5AaAtP6p3f+OmxDUI= -github.com/hashicorp/vault-plugin-secrets-gcp v0.0.0-20190320211452-71903323ecb4 h1:wGqUiCrjncbZnJYmlq14wMibhDn/wwrrtvNSdUvJiQE= -github.com/hashicorp/vault-plugin-secrets-gcp v0.0.0-20190320211452-71903323ecb4/go.mod h1:IV2OZZZ9FCtSYeKDLsnO5JipMdjwachVISz9pNuQjhs= -github.com/hashicorp/vault-plugin-secrets-gcpkms v0.0.0-20190320213325-9e326a9e802d h1:MFmc9Bkmh4AF1ZgEFnOPHPmqeQu8Yebq+6VlidUWjn4= -github.com/hashicorp/vault-plugin-secrets-gcpkms v0.0.0-20190320213325-9e326a9e802d/go.mod h1:2n62quNV4DvfMY5Lxx82NJmx+9pYtv4RltLIFKxEO4E= -github.com/hashicorp/vault-plugin-secrets-kv v0.0.0-20181106190520-2236f141171e/go.mod h1:VJHHT2SC1tAPrfENQeBhLlb5FbZoKZM+oC/ROmEftz0= -github.com/hashicorp/vault-plugin-secrets-kv v0.0.0-20190320211621-3ccc8684cf25 h1:7rGkIXt39f/+4N/RnDbZVV3vEskY7Dh7vmtJew4GuyA= -github.com/hashicorp/vault-plugin-secrets-kv v0.0.0-20190320211621-3ccc8684cf25/go.mod h1:VJHHT2SC1tAPrfENQeBhLlb5FbZoKZM+oC/ROmEftz0= +github.com/hashicorp/vault v1.1.2 h1:NDaWEwrTwjg3VKrKQmQykuiq4UqMUlbqloRvIX5fhns= +github.com/hashicorp/vault v1.1.2/go.mod h1:KfSyffbKxoVyspOdlaGVjIuwLobi07qD1bAbosPMpP0= +github.com/hashicorp/vault-plugin-auth-alicloud v0.5.1 h1:CldlLfMGlcXy+5CvnNsOWJjE9/C1i+Nho4ClSJe+63k= +github.com/hashicorp/vault-plugin-auth-alicloud v0.5.1/go.mod h1:v0d6/ft2ESFHG/PB2pqcwDPlvtAWWfOmfsY0nfbIMy0= +github.com/hashicorp/vault-plugin-auth-azure v0.5.1 h1:1CTmC68zYhp/cKuHW8K0QbnWEetFK7UUu5jaWhmzbHw= +github.com/hashicorp/vault-plugin-auth-azure v0.5.1/go.mod h1:D/slkpcqcZMqslj1X9jfU9aIOrC41LVkfDQ9lFhYg0o= +github.com/hashicorp/vault-plugin-auth-centrify v0.5.1 h1:kHWphxtASUJVYgqvfr6KjCN74qWLJeLhSRE5kBQ4iiQ= +github.com/hashicorp/vault-plugin-auth-centrify v0.5.1/go.mod h1:GHplZPj7NfPWdeCkgTRnNzbjVP5IW5MNm7+MMsjobpQ= +github.com/hashicorp/vault-plugin-auth-gcp v0.5.1 h1:8DR00s+Wmc21i3sfzvsqW88VMdf6NI2ue+onGoHshww= +github.com/hashicorp/vault-plugin-auth-gcp v0.5.1/go.mod h1:eLj92eX8MPI4vY1jaazVLF2sVbSAJ3LRHLRhF/pUmlI= +github.com/hashicorp/vault-plugin-auth-jwt v0.5.1 h1:d9WLI7oF6VMtwBZwS5bbChc4kW+UwNZUKIGXH6wnnTc= +github.com/hashicorp/vault-plugin-auth-jwt v0.5.1/go.mod h1:5VU7gc6/BEEFQW/viqMs3LBxI1D1cxJmKqKQEP3JUP4= +github.com/hashicorp/vault-plugin-auth-kubernetes v0.5.1 h1:q6DGb12Vw/CpZ9xDWAmpzxVRKeClFqRFgbIZ3fZcvuY= +github.com/hashicorp/vault-plugin-auth-kubernetes v0.5.1/go.mod h1:qCDsm0njdfUrnN5sFKMLjxGjZKjQf2qB6dReQ4gr4YI= +github.com/hashicorp/vault-plugin-secrets-ad v0.5.1 h1:BdiASUZLOvOUs317EnaUNjGxTSw0PYGQA7zJZhDKLC4= +github.com/hashicorp/vault-plugin-secrets-ad v0.5.1/go.mod h1:EH9CI8+0aWRBz8eIgGth0QjttmHWlGvn+8ZmX/ZUetE= +github.com/hashicorp/vault-plugin-secrets-alicloud v0.5.1 h1:72K91p4uLhT/jgtBq2zV5Wn8ocvny4sAN56XOcTxK1w= +github.com/hashicorp/vault-plugin-secrets-alicloud v0.5.1/go.mod h1:MspbyD2pPrYgBnYIawkBsFinaDb9lx9PA6uBYOG+d8I= +github.com/hashicorp/vault-plugin-secrets-azure v0.5.1 h1:6XFAkvpQl4zrXpZLSW9TCfF2z0mb2vwbrNmX2nzn480= +github.com/hashicorp/vault-plugin-secrets-azure v0.5.1/go.mod h1:9D3lbhWkN7kTCIrQl8yxMU4IkisAY3SYZaRvseih6ZE= +github.com/hashicorp/vault-plugin-secrets-gcp v0.5.2 h1:oH5EVMJCOHb81Ib9E7/ps1WrN3zkS6SnkbCW4tlk6Ro= +github.com/hashicorp/vault-plugin-secrets-gcp v0.5.2/go.mod h1:2VjVlKHTwqvcVCkZBhYks+HASDzQ4/bIsJoOpO2YJFY= +github.com/hashicorp/vault-plugin-secrets-gcpkms v0.5.1 h1:v25YWb7eMPe9DjGsUexRRuWwPlFNh+lbEGOeNrZalf8= +github.com/hashicorp/vault-plugin-secrets-gcpkms v0.5.1/go.mod h1:seBkt6x33ZT20koMcUwV/viMomnXDipsLgK5KUKz2ik= +github.com/hashicorp/vault-plugin-secrets-kv v0.5.1 h1:awaZ/UoeiDD0j3xF1E0kmXWJvAZw8ULayQu46mB6Un4= +github.com/hashicorp/vault-plugin-secrets-kv v0.5.1/go.mod h1:PIjaafaRr2QlkGl2SNhIywxlejeW0iMUtmx8u9u/a6c= +github.com/hashicorp/vault/api v1.0.1 h1:YQI4SgOlkmbEKZI8ZClo6fm9oXlBHJUlrbEtFiRPrng= +github.com/hashicorp/vault/api v1.0.1/go.mod h1:AV/+M5VPDpB90arloVX0rVDUIHkONiwz5Uza9HRtpUE= +github.com/hashicorp/vault/sdk v0.1.8 h1:pfF3KwA1yPlfpmcumNsFM4uo91WMasX5gTuIkItu9r0= +github.com/hashicorp/vault/sdk v0.1.8/go.mod h1:tHZfc6St71twLizWNHvnnbiGFo1aq0eD2jGPLtP8kAU= +github.com/hashicorp/vic v1.5.1-0.20190403131502-bbfe86ec9443 h1:O/pT5C1Q3mVXMyuqg7yuAWUg/jMZR1/0QTzTRdNR6Uw= +github.com/hashicorp/vic v1.5.1-0.20190403131502-bbfe86ec9443/go.mod h1:bEpDU35nTu0ey1EXjwNwPjI9xErAsoOCmcMb9GKvyxo= github.com/hashicorp/yamux v0.0.0-20180604194846-3520598351bb/go.mod h1:+NfK9FKeTrX5uv1uIXGdwYDTeHna2qgaIlx54MXqjAM= github.com/hashicorp/yamux v0.0.0-20181012175058-2f1d1f20f75d h1:kJCB4vdITiW1eC1vq2e6IsrXKrZit1bv/TDYFGMp4BQ= github.com/hashicorp/yamux v0.0.0-20181012175058-2f1d1f20f75d/go.mod h1:+NfK9FKeTrX5uv1uIXGdwYDTeHna2qgaIlx54MXqjAM= github.com/hpcloud/tail v1.0.0 h1:nfCOvKYfkgYP8hkirhJocXT2+zOD8yUNjXaWfTlyFKI= github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU= -github.com/huandu/xstrings v1.0.0/go.mod h1:4qWG/gcEcfX4z/mBDHJ++3ReCw9ibxbsNJbcucJdbSo= -github.com/imdario/mergo v0.3.4/go.mod h1:2EnlNZ0deacrJVfApfmtdGgDfMuh/nq6Ok1EcJh5FfA= github.com/imdario/mergo v0.3.6 h1:xTNEAn+kxVO7dTZGu0CegyqKZmoWFI0rF8UxjlB2d28= github.com/imdario/mergo v0.3.6/go.mod h1:2EnlNZ0deacrJVfApfmtdGgDfMuh/nq6Ok1EcJh5FfA= -github.com/inconshreveable/mousetrap v1.0.0/go.mod h1:PxqpIevigyE2G7u3NXJIT2ANytuPF1OarO4DADm73n8= -github.com/influxdata/flux v0.13.0/go.mod h1:81jeDcHVn1rN5uj9aQ81S72Q8ol8If7N0zM0G8TnxTE= -github.com/influxdata/influxdb v1.7.5 h1:qEgSrvIRxsIqNQTTeI1Bv6MPh8sOODEsL3GTi9nqtTk= -github.com/influxdata/influxdb v1.7.5/go.mod h1:qZna6X/4elxqT3yI9iZYdZrWWdeFOOprn86kgg4+IzY= -github.com/influxdata/influxql v0.0.0-20180925231337-1cbfca8e56b6/go.mod h1:KpVI7okXjK6PRi3Z5B+mtKZli+R1DnZgb3N+tzevNgo= -github.com/influxdata/line-protocol v0.0.0-20180522152040-32c6aa80de5e/go.mod h1:4kt73NQhadE3daL3WhR5EJ/J2ocX0PZzwxQ0gXJ7oFE= -github.com/influxdata/platform v0.0.0-20190117200541-d500d3cf5589 h1:oN2MMxbnMD/XIlyXbSczQqN5vcrCMFuRsiQafSt2c1E= -github.com/influxdata/platform v0.0.0-20190117200541-d500d3cf5589/go.mod h1:YVhys+JOY4wmXtJvdtkzLhS2K/r/px/vPc+EAddK+pg= -github.com/influxdata/tdigest v0.0.0-20181121200506-bf2b5ad3c0a9/go.mod h1:Js0mqiSBE6Ffsg94weZZ2c+v/ciT8QRHFOap7EKDrR0= -github.com/influxdata/usage-client v0.0.0-20160829180054-6d3895376368/go.mod h1:Wbbw6tYNvwa5dlB6304Sd+82Z3f7PmVZHVKU637d4po= +github.com/imdario/mergo v0.3.7 h1:Y+UAYTZ7gDEuOfhxKWy+dvb5dRQ6rJjFSdX2HZY1/gI= +github.com/imdario/mergo v0.3.7/go.mod h1:2EnlNZ0deacrJVfApfmtdGgDfMuh/nq6Ok1EcJh5FfA= +github.com/influxdata/influxdb v1.7.6 h1:8mQ7A/V+3noMGCt/P9pD09ISaiz9XvgCk303UYA3gcs= +github.com/influxdata/influxdb v1.7.6/go.mod h1:qZna6X/4elxqT3yI9iZYdZrWWdeFOOprn86kgg4+IzY= github.com/jarcoal/httpmock v0.0.0-20180424175123-9c70cfe4a1da h1:FjHUJJ7oBW4G/9j1KzlHaXL09LyMVM9rupS39lncbXk= github.com/jarcoal/httpmock v0.0.0-20180424175123-9c70cfe4a1da/go.mod h1:ks+b9deReOc7jgqp+e7LuFiCBH6Rm5hL32cLcEAArb4= -github.com/jbenet/go-context v0.0.0-20150711004518-d14ea06fba99/go.mod h1:1lJo3i6rXxKeerYnT8Nvf0QmHCRC1n8sfWVwXF2Frvo= github.com/jeffchao/backoff v0.0.0-20140404060208-9d7fd7aa17f2 h1:mex1izRBCD+7WjieGgRdy7e651vD/lvB1bD9vNE/3K4= github.com/jeffchao/backoff v0.0.0-20140404060208-9d7fd7aa17f2/go.mod h1:xkfESuHriIekR+4RoV+fu91j/CfnYM29Zi2tMFw5iD4= -github.com/jefferai/jsonx v0.0.0-20160721235117-9cc31c3135ee/go.mod h1:N0t2vlmpe8nyZB5ouIbJQPDSR+mH6oe7xHB9VZHSUzM= github.com/jefferai/jsonx v1.0.0 h1:Xoz0ZbmkpBvED5W9W1B5B/zc3Oiq7oXqiW7iRV3B6EI= github.com/jefferai/jsonx v1.0.0/go.mod h1:OGmqmi2tTeI/PS+qQfBDToLHHJIy/RMp24fPo8vFvoQ= -github.com/jellevandenhooff/dkim v0.0.0-20150330215556-f50fe3d243e1/go.mod h1:E0B/fFc00Y+Rasa88328GlI/XbtyysCtTHZS8h7IrBU= -github.com/jessevdk/go-flags v1.4.0/go.mod h1:4FA24M0QyGHXBuZZK/XkWh8h0e1EYbRYJSGM75WSRxI= github.com/jmespath/go-jmespath v0.0.0-20160202185014-0b12d6b521d8 h1:12VvqtR6Aowv3l/EQUlocDHW2Cp4G9WJVH7uyH8QFJE= github.com/jmespath/go-jmespath v0.0.0-20160202185014-0b12d6b521d8/go.mod h1:Nht3zPeWKUH0NzdCt2Blrr5ys8VGpn0CEB0cQHVjt7k= github.com/jmespath/go-jmespath v0.0.0-20180206201540-c2b33e8439af h1:pmfjZENx5imkbgOkpRUYLnmbU7UEFbjtDA2hxJ1ichM= @@ -432,19 +391,19 @@ github.com/jonboulle/clockwork v0.1.0 h1:VKV+ZcuP6l3yW9doeqz6ziZGgcynBVQO+obU0+0 github.com/jonboulle/clockwork v0.1.0/go.mod h1:Ii8DK3G1RaLaWxj9trq07+26W01tbo22gdxWY5EU2bo= github.com/joyent/triton-go v0.0.0-20180628001255-830d2b111e62 h1:JHCT6xuyPUrbbgAPE/3dqlvUKzRHMNuTBKKUb6OeR/k= github.com/joyent/triton-go v0.0.0-20180628001255-830d2b111e62/go.mod h1:U+RSyWxWd04xTqnuOQxnai7XGS2PrPY2cfGoDKtMHjA= +github.com/json-iterator/go v0.0.0-20180701071628-ab8a2e0c74be/go.mod h1:+SdeFBvtyEkXs7REEP0seUULqWtbJapLOCVDaaPEHmU= github.com/json-iterator/go v1.1.5 h1:gL2yXlmiIo4+t+y32d4WGwOjKGYcGOuyrg46vadswDE= github.com/json-iterator/go v1.1.5/go.mod h1:+SdeFBvtyEkXs7REEP0seUULqWtbJapLOCVDaaPEHmU= -github.com/jsternberg/zap-logfmt v1.2.0/go.mod h1:kz+1CUmCutPWABnNkOu9hOHKdT2q3TDYCcsFy9hpqb0= +github.com/json-iterator/go v1.1.6 h1:MrUvLMLTMxbqFJ9kzlvat/rYZqZnW3u4wkLzWTaFwKs= +github.com/json-iterator/go v1.1.6/go.mod h1:+SdeFBvtyEkXs7REEP0seUULqWtbJapLOCVDaaPEHmU= +github.com/jstemmer/go-junit-report v0.0.0-20190106144839-af01ea7f8024/go.mod h1:6v2b51hI/fHJwM22ozAgKL4VKDeJcHhJFhtBdhmNjmU= github.com/jtolds/gls v4.2.1+incompatible h1:fSuqC+Gmlu6l/ZYAoZzx2pyucC8Xza35fpRVWLVmUEE= github.com/jtolds/gls v4.2.1+incompatible/go.mod h1:QJZ7F/aHp+rZTRtaJ1ow/lLfFfVYBRgL+9YlvaHOwJU= +github.com/jtolds/gls v4.20.0+incompatible h1:xdiiI2gbIgH/gLH7ADydsJ1uDOEzR8yvV7C0MuV77Wo= +github.com/jtolds/gls v4.20.0+incompatible/go.mod h1:QJZ7F/aHp+rZTRtaJ1ow/lLfFfVYBRgL+9YlvaHOwJU= github.com/julienschmidt/httprouter v1.2.0/go.mod h1:SYymIcj16QtmaHHD7aYtjjsJG7VTCxuUUipMqKk8s4w= -github.com/jwilder/encoding v0.0.0-20170811194829-b4e1701a28ef/go.mod h1:Ct9fl0F6iIOGgxJ5npU/IUOhOhqlVrGjyIZc8/MagT0= -github.com/k0kubun/colorstring v0.0.0-20150214042306-9440f1994b88/go.mod h1:3w7q1U84EfirKl04SVQ/s7nPm1ZPhiXd34z40TNz36k= -github.com/kevinburke/go-bindata v3.11.0+incompatible/go.mod h1:/pEEZ72flUW2p0yi30bslSp9YqD9pysLxunQDdb2CPM= -github.com/kevinburke/ssh_config v0.0.0-20180830205328-81db2a75821e/go.mod h1:CT57kijsi8u/K/BOFA39wgDQJ9CxiF4nAY/ojJ6r6mM= -github.com/keybase/go-crypto v0.0.0-20181031135447-f919bfda4fc1/go.mod h1:ghbZscTyKdM07+Fw3KSi0hcJm+AlEUWj8QLlPtijN/M= -github.com/keybase/go-crypto v0.0.0-20190312101036-b475f2ecc1fe h1:1uflwka8xAWVB2vfZgn+EzemfgGi7WA/XHDnECEeSCM= -github.com/keybase/go-crypto v0.0.0-20190312101036-b475f2ecc1fe/go.mod h1:ghbZscTyKdM07+Fw3KSi0hcJm+AlEUWj8QLlPtijN/M= +github.com/keybase/go-crypto v0.0.0-20190416182011-b785b22cc757 h1:rHXu79NFmin5AvIe4JsnfCBGb1qAIlMTX0vnpVnDn7s= +github.com/keybase/go-crypto v0.0.0-20190416182011-b785b22cc757/go.mod h1:ghbZscTyKdM07+Fw3KSi0hcJm+AlEUWj8QLlPtijN/M= github.com/kisielk/errcheck v1.1.0/go.mod h1:EZBBE59ingxPouuu3KfxchcWSUPOHkagtvWXihfKN4Q= github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck= github.com/konsorten/go-windows-terminal-sequences v1.0.1 h1:mweAR1A6xJ3oS2pRaGiHgQ4OO8tzTaLawm8vnODuwDk= @@ -453,14 +412,13 @@ github.com/kr/logfmt v0.0.0-20140226030751-b84e30acd515/go.mod h1:+0opPa2QZZtGFB github.com/kr/pretty v0.1.0 h1:L/CwN0zerZDmRFUapSPitk6f+Q3+0za1rQkzVuMiMFI= github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo= github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= -github.com/kr/pty v1.1.3/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= github.com/kr/text v0.1.0 h1:45sCR5RtlFHMR4UwH9sdQ5TC8v0qDQCHnXt+kaKSTVE= github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= -github.com/lib/pq v1.0.0 h1:X5PMW56eZitiTeO7tKzZxFCSpbFZJtkMMooicw2us9A= -github.com/lib/pq v1.0.0/go.mod h1:5WUZQaWbwv1U+lTReE5YruASi9Al49XbQIvNi/34Woo= -github.com/lyft/protoc-gen-validate v0.0.14 h1:xbdDVIHd0Xq5Bfzu+8JR9s7mFmJPMvNLmfGhgcHJdFU= -github.com/lyft/protoc-gen-validate v0.0.14/go.mod h1:XbGvPuh87YZc5TdIa2/I4pLk0QoUACkjt2znoq26NVQ= -github.com/magiconair/properties v1.8.0/go.mod h1:PppfXfuXeibc/6YijjN8zIbojt8czPbwD3XqdrwzmxQ= +github.com/lib/pq v1.1.0 h1:/5u4a+KGJptBRqGzPvYQL9p0d/tPR4S31+Tnzj9lEO4= +github.com/lib/pq v1.1.0/go.mod h1:5WUZQaWbwv1U+lTReE5YruASi9Al49XbQIvNi/34Woo= +github.com/linode/linodego v0.7.1 h1:4WZmMpSA2NRwlPZcc0+4Gyn7rr99Evk9bnr0B3gXRKE= +github.com/linode/linodego v0.7.1/go.mod h1:ga11n3ivecUrPCHN0rANxKmfWBJVkOXfLMZinAbj2sY= +github.com/lyft/protoc-gen-validate v0.0.13/go.mod h1:XbGvPuh87YZc5TdIa2/I4pLk0QoUACkjt2znoq26NVQ= github.com/mattbaird/elastigo v0.0.0-20170123220020-2fe47fd29e4b h1:v29yPGHhOqw7VHEnTeQFAth3SsBrmwc8JfuhNY0G34k= github.com/mattbaird/elastigo v0.0.0-20170123220020-2fe47fd29e4b/go.mod h1:5MWrJXKRQyhQdUCF+vu6U5c4nQpg70vW3eHaU0/AYbU= github.com/mattn/go-colorable v0.0.9/go.mod h1:9vuHe8Xs5qXnSaW/c/ABM9alt+Vo+STaOChaDxuIBZU= @@ -469,15 +427,11 @@ github.com/mattn/go-colorable v0.1.1 h1:G1f5SKeVxmagw/IyvzvtZE4Gybcc4Tr1tf7I8z0X github.com/mattn/go-colorable v0.1.1/go.mod h1:FuOcm+DKB9mbwrcAfNl7/TZVBZ6rcnceauSikq3lYCQ= github.com/mattn/go-isatty v0.0.3/go.mod h1:M+lRXTBqGeGNdLjl/ufCoiOlB5xdOkqRJdNxMWT7Zi4= github.com/mattn/go-isatty v0.0.4/go.mod h1:M+lRXTBqGeGNdLjl/ufCoiOlB5xdOkqRJdNxMWT7Zi4= +github.com/mattn/go-isatty v0.0.5 h1:tHXDdz1cpzGaovsTB+TVB8q90WEokoVmfMqoVcrLUgw= github.com/mattn/go-isatty v0.0.5/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hdxcsrc5s= -github.com/mattn/go-isatty v0.0.7 h1:UvyT9uN+3r7yLEYSlJsbQGdsaB/a0DlgWP3pql6iwOc= -github.com/mattn/go-isatty v0.0.7/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hdxcsrc5s= -github.com/mattn/go-runewidth v0.0.3/go.mod h1:LwmH8dsx7+W8Uxz3IHJYH5QSwggIsqBzpuz5H//U1FU= -github.com/mattn/go-tty v0.0.0-20180907095812-13ff1204f104/go.mod h1:XPvLUNfbS4fJH25nqRHfWLMa1ONC8Amw+mIA639KxkE= -github.com/mattn/go-zglob v0.0.0-20171230104132-4959821b4817/go.mod h1:9fxibJccNxU2cnpIKLRRFA7zX7qhkJIQWBb449FYHOo= -github.com/mattn/go-zglob v0.0.0-20180803001819-2ea3427bfa53/go.mod h1:9fxibJccNxU2cnpIKLRRFA7zX7qhkJIQWBb449FYHOo= github.com/matttproud/golang_protobuf_extensions v1.0.1 h1:4hp9jkHxhMHkqkrB3Ix0jegS5sx/RkqARlsWZ6pIwiU= github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0= +github.com/mholt/caddy v0.11.5/go.mod h1:Wb1PlT4DAYSqOEd03MsqkdkXnTxA8v9pKjdpxbqM1kY= github.com/michaelklishin/rabbit-hole v1.5.0 h1:Bex27BiFDsijCM9D0ezSHqyy0kehpYHuNKaPqq/a4RM= github.com/michaelklishin/rabbit-hole v1.5.0/go.mod h1:vvI1uOitYZi0O5HEGXhaWC1XT80Gy+HvFheJ+5Krlhk= github.com/micro/cli v0.0.0-20181223203424-1b0c9793c300/go.mod h1:x9x6qy+tXv17jzYWQup462+j3SIUgDa6vVTzU4IXy/w= @@ -504,9 +458,7 @@ github.com/micro/util v0.1.0 h1:ghhF5KKRNlKMexzK+cWo6W6uRAZdKy1UKG/9O74NCYc= github.com/micro/util v0.1.0/go.mod h1:MZgOs0nwxzv9k4xQo4fpF9IwZGF2O96F5/phP9X4/Sw= github.com/micro/util v0.2.0 h1:6u0cPj1TeixEk5cAR9jbcVRUWDQsmCaZvDBiM3zFZuA= github.com/micro/util v0.2.0/go.mod h1:SgRDkxJJluC2ZNiPfINY42ObEaCAFjL3jP5a+u+qRLU= -github.com/microcosm-cc/bluemonday v1.0.1/go.mod h1:hsXNsILzKxV+sX77C5b8FSuKF00vh2OMYv+xgHpAMF4= github.com/miekg/dns v1.0.14/go.mod h1:W1PPwlIAgtquWBMBEV9nkV9Cazfe8ScdGz/Lj7v3Nrg= -github.com/miekg/dns v1.1.1/go.mod h1:W1PPwlIAgtquWBMBEV9nkV9Cazfe8ScdGz/Lj7v3Nrg= github.com/miekg/dns v1.1.3/go.mod h1:W1PPwlIAgtquWBMBEV9nkV9Cazfe8ScdGz/Lj7v3Nrg= github.com/miekg/dns v1.1.4 h1:rCMZsU2ScVSYcAsOXgmC6+AKOK+6pmQTOcw03nfwYV0= github.com/miekg/dns v1.1.4/go.mod h1:W1PPwlIAgtquWBMBEV9nkV9Cazfe8ScdGz/Lj7v3Nrg= @@ -528,27 +480,18 @@ github.com/mitchellh/hashstructure v1.0.0 h1:ZkRJX1CyOoTkar7p/mLS5TZU4nJ1Rn/F8u9 github.com/mitchellh/hashstructure v1.0.0/go.mod h1:QjSHrPWS+BGUVBYkbTZWEnOh3G1DutKwClXU/ABz6AQ= github.com/mitchellh/iochan v1.0.0/go.mod h1:JwYml1nuB7xOzsp52dPpHFffvOCDupsG0QubkSMEySY= github.com/mitchellh/mapstructure v0.0.0-20160808181253-ca63d7c062ee/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y= -github.com/mitchellh/mapstructure v1.0.0/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y= github.com/mitchellh/mapstructure v1.1.2 h1:fmNYVwqnSfB9mZU6OS2O6GsXM+wcskZDuKQzvN1EDeE= github.com/mitchellh/mapstructure v1.1.2/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y= github.com/mitchellh/pointerstructure v0.0.0-20190323210102-2db4bb651397 h1:GwYLdFxg/9bWW+e6YMWDNrKZ43gbKKkgC9mtmxai4o0= github.com/mitchellh/pointerstructure v0.0.0-20190323210102-2db4bb651397/go.mod h1:k4XwG94++jLVsSiTxo7qdIfXA9pj9EAeo0QsNNJOLZ8= github.com/mitchellh/reflectwalk v1.0.0 h1:9D+8oIskB4VJBN5SFlmc27fSlIBZaov1Wpk/IfikLNY= github.com/mitchellh/reflectwalk v1.0.0/go.mod h1:mSTlrgnPZtwu0c4WaC2kGObEpuNDbx0jmZXqmk4esnw= -github.com/mna/pigeon v1.0.1-0.20180808201053-bb0192cfc2ae/go.mod h1:Iym28+kJVnC1hfQvv5MUtI6AiFFzvQjHcvI4RFTG/04= github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd h1:TRLaZ9cD/w8PVh93nsPXa1VrQ6jlwL5oN8l14QlcNfg= github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= github.com/modern-go/reflect2 v1.0.1 h1:9f412s+6RmYXLWZSEzVVgPGK7C2PphHj5RJrvfx9AWI= github.com/modern-go/reflect2 v1.0.1/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0= -github.com/mschoch/smat v0.0.0-20160514031455-90eadee771ae/go.mod h1:qAyveg+e4CE+eKJXWVjKXM4ck2QobLqTDytGJbLLhJg= github.com/mwitkow/go-conntrack v0.0.0-20161129095857-cc309e4a2223/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U= -github.com/nats-io/gnatsd v1.3.0/go.mod h1:nqco77VO78hLCJpIcVfygDP2rPGfsEHkGTUk94uh5DQ= -github.com/nats-io/go-nats v1.6.0/go.mod h1:+t7RHT5ApZebkrQdnn6AhQJmhJJiKAvJUio1PiiCtj0= -github.com/nats-io/go-nats-streaming v0.4.0/go.mod h1:gfq4R3c9sKAINOpelo0gn/b9QDMBZnmrttcsNF+lqyo= -github.com/nats-io/nats-streaming-server v0.11.2/go.mod h1:RyqtDJZvMZO66YmyjIYdIvS69zu/wDAkyNWa8PIUa5c= -github.com/nats-io/nuid v1.0.0/go.mod h1:19wcPz3Ph3q0Jbyiqsd0kePYG7A95tJPxeL+1OSON2c= -github.com/neelance/astrewrite v0.0.0-20160511093645-99348263ae86/go.mod h1:kHJEU3ofeGjhHklVoIGuVj85JJwZ6kWPaJwCIxgnFmo= -github.com/neelance/sourcemap v0.0.0-20151028013722-8c68805598ab/go.mod h1:Qr6/a/Q4r9LP1IltGz7tA7iOK1WonHEYhu1HRBA7ZiM= +github.com/mxk/go-flowrate v0.0.0-20140419014527-cca7078d478f/go.mod h1:ZdcZmHo+o7JKHSa8/e818NopupXU1YMK5fe1lsApnBw= github.com/nicolai86/scaleway-sdk v1.10.2-0.20180628010248-798f60e20bb2 h1:BQ1HW7hr4IVovMwWg0E0PYcyW8CzqDcVmaew9cujU4s= github.com/nicolai86/scaleway-sdk v1.10.2-0.20180628010248-798f60e20bb2/go.mod h1:TLb2Sg7HQcgGdloNxkrmtgDNR9uVYF3lfdFIN4Ro6Sk= github.com/oklog/run v1.0.0 h1:Ru7dDtJNOyC66gQ5dQmaCa0qIsAUFY3sFpK1Xk8igrw= @@ -557,6 +500,9 @@ github.com/onsi/ginkgo v1.6.0 h1:Ix8l273rp3QzYgXSR+c8d1fTG7UPgYkOSELPhiY/YGw= github.com/onsi/ginkgo v1.6.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= github.com/onsi/ginkgo v1.7.0 h1:WSHQ+IS43OoUrWtD1/bbclrwK8TTH5hzp+umCiuxHgs= github.com/onsi/ginkgo v1.7.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= +github.com/onsi/ginkgo v1.8.0 h1:VkHVNpR4iVnU8XQR6DBm8BqYjN7CRzw+xKUbVVbbW9w= +github.com/onsi/ginkgo v1.8.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= +github.com/onsi/gomega v0.0.0-20190113212917-5533ce8a0da3/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1CpauHY= github.com/onsi/gomega v1.4.1 h1:PZSj/UFNaVp3KxrzHOcS7oyuWA7LoOY/77yCTEFu21U= github.com/onsi/gomega v1.4.1/go.mod h1:C1qb7wdrVGGVU+Z6iS04AVkA3Q65CEZX59MT0QO5uiA= github.com/onsi/gomega v1.4.3 h1:RE1xgDvH7imwFD45h+u2SgIfERHlS2yNG4DObb5BSKU= @@ -567,18 +513,19 @@ github.com/opencontainers/image-spec v1.0.1 h1:JMemWkRwHx4Zj+fVxWoMCFm/8sYGGrUVo github.com/opencontainers/image-spec v1.0.1/go.mod h1:BtxoFyWECRxE4U/7sNtV5W15zMzWCbyJoFRP3s7yZA0= github.com/opencontainers/runc v0.1.1 h1:GlxAyO6x8rfZYN9Tt0Kti5a/cP41iuiO2yYT0IJGY8Y= github.com/opencontainers/runc v0.1.1/go.mod h1:qT5XzbpPznkRYVz/mWwUaVBUv2rmF59PVA73FjuZG0U= +github.com/opentracing-contrib/go-observer v0.0.0-20170622124052-a52f23424492/go.mod h1:Ngi6UdF0k5OKD5t5wlmGhe/EDKPoUM3BXZSSfIuJbis= github.com/opentracing/opentracing-go v1.0.2 h1:3jA2P6O1F9UOrWVpwrIo17pu01KWvNWg4X946/Y5Zwg= github.com/opentracing/opentracing-go v1.0.2/go.mod h1:UkNAQd3GIcIGf0SeVgPpRdFStlNbqXla1AfSYxPUl2o= -github.com/openzipkin/zipkin-go v0.1.1/go.mod h1:NtoC/o8u3JlF1lSlyPNswIbeQH9bJTmOf0Erfk+hxe8= github.com/openzipkin/zipkin-go v0.1.3/go.mod h1:NtoC/o8u3JlF1lSlyPNswIbeQH9bJTmOf0Erfk+hxe8= github.com/openzipkin/zipkin-go v0.1.6/go.mod h1:QgAqvLzwWbR/WpD4A3cGpPtJrZXNIiJc5AZX7/PBEpw= +github.com/openzipkin/zipkin-go-opentracing v0.3.4/go.mod h1:js2AbwmHW0YD9DwIw2JhQWmbfFi/UnWyYwdVhqbCDOE= github.com/ory-am/common v0.4.0 h1:edGPoxYX4hno0IJHXh9TCMUPR6ZcJp+y6aClFYxeuUE= github.com/ory-am/common v0.4.0/go.mod h1:oCYGuwwM8FyYMKqh9vrhBaeUoyz/edx0bgJN6uS6/+k= -github.com/ory/dockertest v3.3.2+incompatible/go.mod h1:1vX4m9wsvi00u5bseYwXaSnhNrne+V0E6LAcBILJdPs= github.com/ory/dockertest v3.3.4+incompatible h1:VrpM6Gqg7CrPm3bL4Wm1skO+zFWLbh7/Xb5kGEbJRh8= github.com/ory/dockertest v3.3.4+incompatible/go.mod h1:1vX4m9wsvi00u5bseYwXaSnhNrne+V0E6LAcBILJdPs= github.com/packethost/packngo v0.1.1-0.20180711074735-b9cb5096f54c h1:vwpFWvAO8DeIZfFeqASzZfsxuWPno9ncAebBEP0N3uE= github.com/packethost/packngo v0.1.1-0.20180711074735-b9cb5096f54c/go.mod h1:otzZQXgoO96RTzDB/Hycg0qZcXZsWJGJRSXbmEIJ+4M= +github.com/pascaldekloe/goe v0.0.0-20180627143212-57f6aae5913c h1:Lgl0gzECD8GnQ5QCWA8o6BtfL6mDH5rQgM4/fX3avOs= github.com/pascaldekloe/goe v0.0.0-20180627143212-57f6aae5913c/go.mod h1:lzWF7FIEvWOWxwDKqyGYQf6ZUaNfKdP144TG7ZOy1lc= github.com/pascaldekloe/goe v0.1.0 h1:cBOtyMzM9HTpWjXfbbunk26uA6nG3a8n06Wieeh0MwY= github.com/pascaldekloe/goe v0.1.0/go.mod h1:lzWF7FIEvWOWxwDKqyGYQf6ZUaNfKdP144TG7ZOy1lc= @@ -586,17 +533,13 @@ github.com/patrickmn/go-cache v2.1.0+incompatible h1:HRMgzkcYKYpi3C8ajMPV8OFXaaR github.com/patrickmn/go-cache v2.1.0+incompatible/go.mod h1:3Qf8kWWT7OJRJbdiICTKqZju1ZixQ/KpMGzzAfe6+WQ= github.com/pborman/uuid v1.2.0 h1:J7Q5mO4ysT1dv8hyrUGHb9+ooztCXu1D8MY8DZYsu3g= github.com/pborman/uuid v1.2.0/go.mod h1:X/NO0urCmaxf9VXbdlT7C2Yzkj2IKimNn4k+gtPdI/k= -github.com/pelletier/go-buffruneio v0.2.0/go.mod h1:JkE26KsDizTr40EUHkXVtNPvgGtbSNq5BcowyYOWdKo= -github.com/pelletier/go-toml v1.2.0/go.mod h1:5z9KED0ma1S8pY6P1sdut58dfprrGBbd/94hg7ilaic= github.com/peterbourgon/diskv v2.0.1+incompatible h1:UBdAOUP5p4RWqPBg048CAvpKN+vxiaj6gdUUzhl4XmI= github.com/peterbourgon/diskv v2.0.1+incompatible/go.mod h1:uqqh8zWWbv1HBMNONnaR/tNboyR3/BZd58JJSHlUSCU= -github.com/philhofer/fwd v1.0.0/go.mod h1:gk3iGcWd9+svBvR0sR+KPcfE+RNWozjowpeBVG3ZVNU= github.com/pierrec/lz4 v2.0.5+incompatible h1:2xWsjqPFWcplujydGg4WmhC/6fZqK42wMM8aXeqhl0I= github.com/pierrec/lz4 v2.0.5+incompatible/go.mod h1:pdkljMzZIN41W+lC3N2tnIh5sFi+IEE17M5jbnwPHcY= github.com/pkg/errors v0.8.0/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= github.com/pkg/errors v0.8.1 h1:iURUrRGxPUNPdy5/HRSm+Yj6okJ6UtLINN0Q9M4+h3I= github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= -github.com/pkg/term v0.0.0-20180730021639-bffc007b7fd5/go.mod h1:eCbImbZ95eXtAUIbLAuAVnBnwf83mjf6QIVH8SHYwqQ= github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= github.com/posener/complete v1.1.1/go.mod h1:em0nMJCgc9GFtwrmVmEMR/ZL6WyhyjMBndrE9hABlRI= @@ -606,32 +549,30 @@ github.com/pquerna/cachecontrol v0.0.0-20180517163645-1555304b9b35 h1:J9b7z+QKAm github.com/pquerna/cachecontrol v0.0.0-20180517163645-1555304b9b35/go.mod h1:prYjPmNq4d1NPVmpShWobRqXY3q7Vp+80DqgxxUrUIA= github.com/pquerna/otp v1.1.0 h1:q2gMsMuMl3JzneUaAX1MRGxLvOG6bzXV51hivBaStf0= github.com/pquerna/otp v1.1.0/go.mod h1:Zad1CMQfSQZI5KLpahDiSUX4tMMREnXw98IvL1nhgMk= -github.com/prometheus/client_golang v0.0.0-20171201122222-661e31bf844d/go.mod h1:7SWBe2y4D6OKWSNQJUaRYU/AaXPKyh/dDVn+NZz0KFw= -github.com/prometheus/client_golang v0.8.0/go.mod h1:7SWBe2y4D6OKWSNQJUaRYU/AaXPKyh/dDVn+NZz0KFw= -github.com/prometheus/client_golang v0.9.0/go.mod h1:7SWBe2y4D6OKWSNQJUaRYU/AaXPKyh/dDVn+NZz0KFw= github.com/prometheus/client_golang v0.9.1/go.mod h1:7SWBe2y4D6OKWSNQJUaRYU/AaXPKyh/dDVn+NZz0KFw= +github.com/prometheus/client_golang v0.9.2 h1:awm861/B8OKDd2I/6o1dy3ra4BamzKhYOiGItCeZ740= +github.com/prometheus/client_golang v0.9.2/go.mod h1:OsXs2jCmiKlQ1lTBmv21f2mNfw4xf/QclQDMrYNZzcM= github.com/prometheus/client_golang v0.9.3-0.20190127221311-3c4408c8b829 h1:D+CiwcpGTW6pL6bv6KI3KbyEyCKyS+1JWS2h8PNDnGA= github.com/prometheus/client_golang v0.9.3-0.20190127221311-3c4408c8b829/go.mod h1:p2iRAGwDERtqlqzRXnrOVns+ignqQo//hLXqYxZYVNs= github.com/prometheus/client_model v0.0.0-20180712105110-5c3871d89910 h1:idejC8f05m9MGOsuEi1ATq9shN03HrxNkD/luQvxCv8= github.com/prometheus/client_model v0.0.0-20180712105110-5c3871d89910/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo= github.com/prometheus/client_model v0.0.0-20190115171406-56726106282f h1:BVwpUVJDADN2ufcGik7W992pyps0wZ888b/y9GXcLTU= github.com/prometheus/client_model v0.0.0-20190115171406-56726106282f/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo= -github.com/prometheus/common v0.0.0-20180801064454-c7de2306084e/go.mod h1:daVV7qP5qjZbuso7PdcryaAu0sAZbrN9i7WWcTMWvro= -github.com/prometheus/common v0.0.0-20181020173914-7e9e6cabbd39/go.mod h1:daVV7qP5qjZbuso7PdcryaAu0sAZbrN9i7WWcTMWvro= +github.com/prometheus/common v0.0.0-20181126121408-4724e9255275 h1:PnBWHBf+6L0jOqq0gIVUe6Yk0/QMZ640k6NvkxcBf+8= +github.com/prometheus/common v0.0.0-20181126121408-4724e9255275/go.mod h1:daVV7qP5qjZbuso7PdcryaAu0sAZbrN9i7WWcTMWvro= github.com/prometheus/common v0.2.0 h1:kUZDBDTdBVBYBj5Tmh2NZLlF60mfjA27rM34b+cVwNU= github.com/prometheus/common v0.2.0/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y86RQel1bk4= -github.com/prometheus/procfs v0.0.0-20180725123919-05ee40e3a273/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk= github.com/prometheus/procfs v0.0.0-20181005140218-185b4288413d/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk= +github.com/prometheus/procfs v0.0.0-20181204211112-1dc9a6cbc91a h1:9a8MnZMP0X2nLJdBg+pBmGgkJlSaKC2KaQmTCk1XDtE= +github.com/prometheus/procfs v0.0.0-20181204211112-1dc9a6cbc91a/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk= github.com/prometheus/procfs v0.0.0-20190117184657-bf6a532e95b1 h1:/K3IL0Z1quvmJ7X0A1AwNEK7CRkVK3YwfOU/QAL4WGg= github.com/prometheus/procfs v0.0.0-20190117184657-bf6a532e95b1/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk= github.com/rcrowley/go-metrics v0.0.0-20181016184325-3113b8401b8a/go.mod h1:bCqnVzQkZxMG4s8nGwiZ5l3QUCyqpo9Y+/ZMZ9VjZe4= github.com/renier/xmlrpc v0.0.0-20170708154548-ce4a1a486c03 h1:Wdi9nwnhFNAlseAOekn6B5G/+GMtks9UKbvRU/CMM/o= github.com/renier/xmlrpc v0.0.0-20170708154548-ce4a1a486c03/go.mod h1:gRAiPF5C5Nd0eyyRdqIu9qTiFSoZzpTq727b5B8fkkU= github.com/rogpeppe/fastuuid v0.0.0-20150106093220-6724a57986af/go.mod h1:XWv6SoW27p1b0cqNHllgS5HIMJraePCO15w5zCzIWYg= -github.com/russross/blackfriday v1.5.2/go.mod h1:JO/DiYxRf+HjHt06OyowR9PTA263kcR/rfWxYHBV53g= github.com/ryanuber/columnize v0.0.0-20160712163229-9b3edd62028f/go.mod h1:sm1tb6uqfes/u+d4ooFouqFdy9/2g9QGwK3SQygK0Ts= github.com/ryanuber/columnize v2.1.0+incompatible/go.mod h1:sm1tb6uqfes/u+d4ooFouqFdy9/2g9QGwK3SQygK0Ts= -github.com/ryanuber/go-glob v0.0.0-20170128012129-256dc444b735/go.mod h1:807d1WSdnB0XRJzKNil9Om6lcp/3a0v4qIHxIXzX/Yc= github.com/ryanuber/go-glob v1.0.0 h1:iQh3xXAumdQ+4Ufa5b25cRpC5TYKlno6hsv6Cb3pkBk= github.com/ryanuber/go-glob v1.0.0/go.mod h1:807d1WSdnB0XRJzKNil9Om6lcp/3a0v4qIHxIXzX/Yc= github.com/samuel/go-zookeeper v0.0.0-20180130194729-c4fab1ac1bec h1:6ncX5ko6B9LntYM0YBRXkiSaZMmLYeZ/NWcmeB43mMY= @@ -640,34 +581,10 @@ github.com/satori/go.uuid v1.2.0 h1:0uYX9dsZ2yD7q2RtLRtPSdGDWzjeM3TbMJP9utgA0ww= github.com/satori/go.uuid v1.2.0/go.mod h1:dA0hQrYB0VpLJoorglMZABFdXlWrHn1NEOzdhQKdks0= github.com/sean-/seed v0.0.0-20170313163322-e2103e2c3529 h1:nn5Wsu0esKSJiIVhscUtVbo7ada43DJhG55ua/hjS5I= github.com/sean-/seed v0.0.0-20170313163322-e2103e2c3529/go.mod h1:DxrIzT+xaE7yg65j358z/aeFdxmN0P9QXhEzd20vsDc= -github.com/segmentio/kafka-go v0.1.0/go.mod h1:X6itGqS9L4jDletMsxZ7Dz+JFWxM6JHfPOCvTvk+EJo= -github.com/sergi/go-diff v1.0.0/go.mod h1:0CfEIISq7TuYL3j771MWULgwwjU+GofnZX9QAmXWZgo= github.com/shirou/gopsutil v2.18.12+incompatible h1:1eaJvGomDnH74/5cF4CTmTbLHAriGFsTZppLXDX93OM= github.com/shirou/gopsutil v2.18.12+incompatible/go.mod h1:5b4v6he4MtMOwMlS0TUMTu2PcXUg8+E1lC7eC3UO/RA= github.com/shirou/w32 v0.0.0-20160930032740-bb4de0191aa4 h1:udFKJ0aHUL60LboW/A+DfgoHVedieIzIXE8uylPue0U= github.com/shirou/w32 v0.0.0-20160930032740-bb4de0191aa4/go.mod h1:qsXQc7+bwAM3Q1u/4XEfrquwF8Lw7D7y5cD8CuHnfIc= -github.com/shurcooL/component v0.0.0-20170202220835-f88ec8f54cc4/go.mod h1:XhFIlyj5a1fBNx5aJTbKoIq0mNaPvOagO+HjB3EtxrY= -github.com/shurcooL/events v0.0.0-20181021180414-410e4ca65f48/go.mod h1:5u70Mqkb5O5cxEA8nxTsgrgLehJeAw6Oc4Ab1c/P1HM= -github.com/shurcooL/github_flavored_markdown v0.0.0-20181002035957-2122de532470/go.mod h1:2dOwnU2uBioM+SGy2aZoq1f/Sd1l9OkAeAUvjSyvgU0= -github.com/shurcooL/go v0.0.0-20180423040247-9e1955d9fb6e/go.mod h1:TDJrrUr11Vxrven61rcy3hJMUqaf/CLWYhHNPmT14Lk= -github.com/shurcooL/go-goon v0.0.0-20170922171312-37c2f522c041/go.mod h1:N5mDOmsrJOB+vfqUK+7DmDyjhSLIIBnXo9lvZJj3MWQ= -github.com/shurcooL/gofontwoff v0.0.0-20180329035133-29b52fc0a18d/go.mod h1:05UtEgK5zq39gLST6uB0cf3NEHjETfB4Fgr3Gx5R9Vw= -github.com/shurcooL/gopherjslib v0.0.0-20160914041154-feb6d3990c2c/go.mod h1:8d3azKNyqcHP1GaQE/c6dDgjkgSx2BZ4IoEi4F1reUI= -github.com/shurcooL/highlight_diff v0.0.0-20170515013008-09bb4053de1b/go.mod h1:ZpfEhSmds4ytuByIcDnOLkTHGUI6KNqRNPDLHDk+mUU= -github.com/shurcooL/highlight_go v0.0.0-20181028180052-98c3abbbae20/go.mod h1:UDKB5a1T23gOMUJrI+uSuH0VRDStOiUVSjBTRDVBVag= -github.com/shurcooL/home v0.0.0-20181020052607-80b7ffcb30f9/go.mod h1:+rgNQw2P9ARFAs37qieuu7ohDNQ3gds9msbT2yn85sg= -github.com/shurcooL/htmlg v0.0.0-20170918183704-d01228ac9e50/go.mod h1:zPn1wHpTIePGnXSHpsVPWEktKXHr6+SS6x/IKRb7cpw= -github.com/shurcooL/httperror v0.0.0-20170206035902-86b7830d14cc/go.mod h1:aYMfkZ6DWSJPJ6c4Wwz3QtW22G7mf/PEgaB9k/ik5+Y= -github.com/shurcooL/httpfs v0.0.0-20171119174359-809beceb2371/go.mod h1:ZY1cvUeJuFPAdZ/B6v7RHavJWZn2YPVFQ1OSXhCGOkg= -github.com/shurcooL/httpgzip v0.0.0-20180522190206-b1c53ac65af9/go.mod h1:919LwcH0M7/W4fcZ0/jy0qGght1GIhqyS/EgWGH2j5Q= -github.com/shurcooL/issues v0.0.0-20181008053335-6292fdc1e191/go.mod h1:e2qWDig5bLteJ4fwvDAc2NHzqFEthkqn7aOZAOpj+PQ= -github.com/shurcooL/issuesapp v0.0.0-20180602232740-048589ce2241/go.mod h1:NPpHK2TI7iSaM0buivtFUc9offApnI0Alt/K8hcHy0I= -github.com/shurcooL/notifications v0.0.0-20181007000457-627ab5aea122/go.mod h1:b5uSkrEVM1jQUspwbixRBhaIjIzL2xazXp6kntxYle0= -github.com/shurcooL/octicon v0.0.0-20181028054416-fa4f57f9efb2/go.mod h1:eWdoE5JD4R5UVWDucdOPg1g2fqQRq78IQa9zlOV1vpQ= -github.com/shurcooL/reactions v0.0.0-20181006231557-f2e0b4ca5b82/go.mod h1:TCR1lToEk4d2s07G3XGfz2QrgHXg4RJBvjrOozvoWfk= -github.com/shurcooL/sanitized_anchor_name v0.0.0-20170918181015-86672fcb3f95/go.mod h1:1NzhyTcUVG4SuEtjjoZeVRXNmyL/1OwPU0+IJeTBvfc= -github.com/shurcooL/users v0.0.0-20180125191416-49c67e49c537/go.mod h1:QJTqeLYEDaXHZDBsXlPCDqdhQuJkuw4NOtaxYe3xii4= -github.com/shurcooL/webdavfs v0.0.0-20170829043945-18c3829fa133/go.mod h1:hKmq5kWdCj2z2KEozexVbfEZIWiTjhE0+UjmZgPqehw= github.com/sirupsen/logrus v1.0.6 h1:hcP1GmhGigz/O7h1WVUM5KklBp1JoNS9FggWKdj/j3s= github.com/sirupsen/logrus v1.0.6/go.mod h1:pMByvHTf9Beacp5x1UXfOR9xyW/9antXMhjMPG0dEzc= github.com/sirupsen/logrus v1.2.0 h1:juTguoYk5qI21pwyTXY3B3Y5cOTH3ZUyZCg1v/mihuo= @@ -678,119 +595,102 @@ github.com/smartystreets/assertions v0.0.0-20180927180507-b2de0cb4f26d h1:zE9ykE github.com/smartystreets/assertions v0.0.0-20180927180507-b2de0cb4f26d/go.mod h1:OnSkiWE9lh6wB0YB77sQom3nweQdgAjqCqsofrRNTgc= github.com/smartystreets/goconvey v0.0.0-20180222194500-ef6db91d284a h1:JSvGDIbmil4Ui/dDdFBExb7/cmkNjyX5F97oglmvCDo= github.com/smartystreets/goconvey v0.0.0-20180222194500-ef6db91d284a/go.mod h1:XDJAKZRPZ1CvBcN2aX5YOUTYGHki24fSF0Iv48Ibg0s= +github.com/smartystreets/goconvey v0.0.0-20190306220146-200a235640ff h1:86HlEv0yBCry9syNuylzqznKXDK11p6D0DT596yNMys= +github.com/smartystreets/goconvey v0.0.0-20190306220146-200a235640ff/go.mod h1:KSQcGKpxUMHk3nbYzs/tIBAM2iDooCn0BmttHOJEbLs= +github.com/smartystreets/goconvey v0.0.0-20190330032615-68dc04aab96a h1:pa8hGb/2YqsZKovtsgrwcDH1RZhVbTKCjLp47XpqCDs= +github.com/smartystreets/goconvey v0.0.0-20190330032615-68dc04aab96a/go.mod h1:syvi0/a8iFYH4r/RixwvyeAJjdLS9QV7WQ/tjFTllLA= github.com/softlayer/softlayer-go v0.0.0-20180806151055-260589d94c7d h1:bVQRCxQvfjNUeRqaY/uT0tFuvuFY0ulgnczuR684Xic= github.com/softlayer/softlayer-go v0.0.0-20180806151055-260589d94c7d/go.mod h1:Cw4GTlQccdRGSEf6KiMju767x0NEHE0YIVPJSaXjlsw= github.com/soheilhy/cmux v0.1.4 h1:0HKaf1o97UwFjHH9o5XsHUOF+tqmdA7KEzXLpiyaw0E= github.com/soheilhy/cmux v0.1.4/go.mod h1:IM3LyeVVIOuxMH7sFAkER9+bJ4dT7Ms6E4xg4kGIyLM= -github.com/sourcegraph/annotate v0.0.0-20160123013949-f4cad6c6324d/go.mod h1:UdhH50NIW0fCiwBSr0co2m7BnFLdv4fQTgdqdJTHFeE= -github.com/sourcegraph/syntaxhighlight v0.0.0-20170531221838-bd320f5d308e/go.mod h1:HuIsMU8RRBOtsCgI77wP899iHVBQpCmg4ErYMZB+2IA= -github.com/spaolacci/murmur3 v0.0.0-20180118202830-f09979ecbc72/go.mod h1:JwIasOWyU6f++ZhiEuf87xNszmSA2myDM2Kzu9HwQUA= -github.com/spf13/afero v1.1.2/go.mod h1:j4pytiNVoe2o6bmDsKpLACNPDBIoEAkihy7loJ1B0CQ= -github.com/spf13/cast v1.2.0/go.mod h1:r2rcYCSwa1IExKTDiTfzaxqT2FNHs8hODu4LnUfgKEg= -github.com/spf13/cobra v0.0.3/go.mod h1:1l0Ry5zgKvJasoi3XT1TypsSe7PqH0Sj9dhYf7v3XqQ= -github.com/spf13/jwalterweatherman v1.0.0/go.mod h1:cQK4TGJAtQXfYWX+Ddv3mKDzgVb68N+wFjFa4jdeBTo= +github.com/spf13/pflag v1.0.1/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4= github.com/spf13/pflag v1.0.2 h1:Fy0orTDgHdbnzHcsOgfCN4LtHf0ec3wwtiwJqwvf3Gc= github.com/spf13/pflag v1.0.2/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4= github.com/spf13/pflag v1.0.3 h1:zPAT6CGy6wXeQ7NtTnaTerfKOsV6V6F8agHXFiazDkg= github.com/spf13/pflag v1.0.3/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4= -github.com/spf13/viper v1.2.1/go.mod h1:P4AexN0a+C9tGAnUFNwDMYYZv3pjFuvmeiMyKRaNVlI= -github.com/src-d/gcfg v1.4.0/go.mod h1:p/UMsR43ujA89BJY9duynAwIpvqEujIH/jFlfL7jWoI= -github.com/stevvooe/resumable v0.0.0-20180830230917-22b14a53ba50/go.mod h1:1pdIZTAHUz+HDKDVZ++5xg/duPlhKAIzw9qy42CWYp4= -github.com/streadway/amqp v0.0.0-20190312223743-14f78b41ce6d h1:ToACqFOOYVdz7PswtVcAawttvtdGlLhoAsXdhYFQeEI= -github.com/streadway/amqp v0.0.0-20190312223743-14f78b41ce6d/go.mod h1:AZpEONHx3DKn8O/DFsRAY58/XVQiIPMTMB1SddzLXVw= +github.com/streadway/amqp v0.0.0-20190404075320-75d898a42a94 h1:0ngsPmuP6XIjiFRNFYlvKwSr5zff2v+uPHaffZ6/M4k= +github.com/streadway/amqp v0.0.0-20190404075320-75d898a42a94/go.mod h1:AZpEONHx3DKn8O/DFsRAY58/XVQiIPMTMB1SddzLXVw= github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/objx v0.1.1 h1:2vfRuCMp5sSVIDSqO8oNnWJq7mPa6KVP3iPIwFBuy8A= github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= -github.com/stretchr/testify v1.2.0/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= -github.com/stretchr/testify v1.2.1/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= github.com/stretchr/testify v1.3.0 h1:TivCn/peBQ7UY8ooIcPgZFpTNSz0Q2U6UrFlUfqbe0Q= github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= -github.com/tarm/serial v0.0.0-20180830185346-98f6abe2eb07/go.mod h1:kDXzergiv9cbyO7IOYJZWg1U88JhDg3PB6klq9Hg2pA= -github.com/tcnksm/go-input v0.0.0-20180404061846-548a7d7a8ee8/go.mod h1:IlWNj9v/13q7xFbaK4mbyzMNwrZLaWSHx/aibKIZuIg= github.com/tent/http-link-go v0.0.0-20130702225549-ac974c61c2f9 h1:/Bsw4C+DEdqPjt8vAqaC9LAqpAQnaCQQqmolqq3S1T4= github.com/tent/http-link-go v0.0.0-20130702225549-ac974c61c2f9/go.mod h1:RHkNRtSLfOK7qBTHaeSX1D6BNpI3qw7NTxsmNr4RvN8= -github.com/testcontainers/testcontainer-go v0.0.0-20181115231424-8e868ca12c0f/go.mod h1:SrG3IY071gtmZJjGbKO+POJ57a/MMESerYNWt6ZRtKs= -github.com/tinylib/msgp v1.0.2/go.mod h1:+d+yLhGm8mzTaHzB+wgMYrodPfmZrzkirds8fDWklFE= github.com/tmc/grpc-websocket-proxy v0.0.0-20190109142713-0ad062ec5ee5 h1:LnC5Kc/wtumK+WB441p7ynQJzVuNRJiqddSIE3IlSEQ= github.com/tmc/grpc-websocket-proxy v0.0.0-20190109142713-0ad062ec5ee5/go.mod h1:ncp9v5uamzpCO7NfCPTXjqaC+bZgJeR0sMTm6dMHP7U= github.com/tv42/httpunix v0.0.0-20150427012821-b75d8614f926 h1:G3dpKMzFDjgEh2q1Z7zUUtKa8ViPtH+ocF0bE0g00O8= github.com/tv42/httpunix v0.0.0-20150427012821-b75d8614f926/go.mod h1:9ESjWnEqriFuLhtthL60Sar/7RFoluCcXsuvEwTV5KM= -github.com/tylerb/graceful v1.2.15/go.mod h1:LPYTbOYmUTdabwRt0TGhLllQ0MUNbs0Y5q1WXJOI9II= github.com/ugorji/go v1.1.2 h1:JON3E2/GPW2iDNGoSAusl1KDf5TRQ8k8q7Tp097pZGs= github.com/ugorji/go v1.1.2/go.mod h1:hnLbHMwcvSihnDhEfx2/BzKp2xb0Y+ErdfYcrs9tkJQ= -github.com/ugorji/go/codec v0.0.0-20190320090025-2dc34c0b8780 h1:vG/gY/PxA3v3l04qxe3tDjXyu3bozii8ulSlIPOYKhI= -github.com/ugorji/go/codec v0.0.0-20190320090025-2dc34c0b8780/go.mod h1:iT03XoTwV7xq/+UGwKO3UbC1nNNlopQiY61beSdrtOA= +github.com/ugorji/go/codec v0.0.0-20190309163734-c4a1c341dc93 h1:JnDJ9gMf6CfErtoOXnghtY5hhMuDtW4tUBaWSBrqvKs= +github.com/ugorji/go/codec v0.0.0-20190309163734-c4a1c341dc93/go.mod h1:iT03XoTwV7xq/+UGwKO3UbC1nNNlopQiY61beSdrtOA= github.com/vmware/govmomi v0.18.0 h1:f7QxSmP7meCtoAmiKZogvVbLInT+CZx6Px6K5rYsJZo= github.com/vmware/govmomi v0.18.0/go.mod h1:URlwyTFZX72RmxtxuaFL2Uj3fD1JTvZdx59bHWk6aFU= -github.com/vmware/vic v1.4.1 h1:Cbvv5y2h1YlYebIYGuVp1Xk5imxPSDUF6c0O5oLdQ00= -github.com/vmware/vic v1.4.1/go.mod h1:AiTDrZuV13NkqRzseA5ZmF2QqLpTydaaGN75xgV6Ork= -github.com/willf/bitset v1.1.9/go.mod h1:RjeCKbqT1RxIR/KWY6phxZiaY1IyutSBfGjNPySAYV4= -github.com/xanzy/ssh-agent v0.2.0/go.mod h1:0NyE30eGUDliuLEHJgYte/zncp2zdTStcOnWhgSqHD8= github.com/xiang90/probing v0.0.0-20190116061207-43a291ad63a2 h1:eY9dn8+vbi4tKz5Qo6v2eYzo7kUS51QINcR5jNpbZS8= github.com/xiang90/probing v0.0.0-20190116061207-43a291ad63a2/go.mod h1:UETIi67q53MR2AWcXfiuqkDkRtnGDLqkBTpCHuJHxtU= -github.com/yudai/gojsondiff v1.0.0/go.mod h1:AY32+k2cwILAkW1fbgxQ5mUmMiZFgLIV+FBNExI05xg= -github.com/yudai/golcs v0.0.0-20170316035057-ecda9a501e82/go.mod h1:lgjkn3NuSvDfVJdfcVVdX+jpBxNmX4rDAzaS45IcYoM= -github.com/yudai/pp v2.0.1+incompatible/go.mod h1:PuxR/8QJ7cyCkFp/aUDS+JY727OFEZkTdatxwunjIkc= -go.opencensus.io v0.18.0/go.mod h1:vKdFvxhtzZ9onBp9VKHK8z/sRpBMnKAsufL7wlDrCOA= +go.etcd.io/bbolt v1.3.2 h1:Z/90sZLPOeCy2PwprqkFa25PdkusRzaj9P8zm/KNyvk= +go.etcd.io/bbolt v1.3.2/go.mod h1:IbVyRI1SCnLcuJnV2u8VeU0CEYM7e686BmAb1XKL+uU= go.opencensus.io v0.19.1/go.mod h1:gug0GbSHa8Pafr0d2urOSgoXHZ6x/RUlaiT0d9pqb4A= go.opencensus.io v0.19.2 h1:ZZpq6xI6kv/LuE/5s5UQvBU5vMjvRnPb8PvJrIntAnc= go.opencensus.io v0.19.2/go.mod h1:NO/8qkisMZLZ1FCsKNqtJPwc8/TaclWyY0B6wcYNg9M= +go.opencensus.io v0.20.1/go.mod h1:6WKK9ahsWS3RSO+PY9ZHZUfv2irvY6gN279GOPZjmmk= +go.opencensus.io v0.20.2 h1:NAfh7zF0/3/HqtMvJNZ/RFrSlCE6ZTlHmKfhL/Dm1Jk= +go.opencensus.io v0.20.2/go.mod h1:6WKK9ahsWS3RSO+PY9ZHZUfv2irvY6gN279GOPZjmmk= go.uber.org/atomic v1.3.2 h1:2Oa65PReHzfn29GpvgsYwloV9AVFHPDk8tYxt2c2tr4= go.uber.org/atomic v1.3.2/go.mod h1:gD2HeocX3+yG+ygLZcrzQJaqmWj9AIm7n08wl/qW/PE= go.uber.org/multierr v1.1.0 h1:HoEmRHQPVSqub6w2z2d2EOVs2fjyFRGyofhKuyDq0QI= go.uber.org/multierr v1.1.0/go.mod h1:wR5kodmAFQ0UK8QlbwjlSNy0Z68gJhDJUG5sjR94q/0= go.uber.org/zap v1.9.1 h1:XCJQEf3W6eZaVwhRBof6ImoYGJSITeKWsyeh3HFu/5o= go.uber.org/zap v1.9.1/go.mod h1:vwi/ZaCAaUcBkycHslxD9B2zi4UTXhF60s6SWpuDF0Q= -go4.org v0.0.0-20180809161055-417644f6feb5/go.mod h1:MkTOUMDaeVYJUOUsaDXIhWPZYa1yOyC1qaOBpL57BhE= -golang.org/x/build v0.0.0-20190111050920-041ab4dc3f9d/go.mod h1:OWs+y06UdEOHN4y+MfF/py+xQ/tYqIWW03b70/CG9Rw= -golang.org/x/crypto v0.0.0-20180505025534-4ec37c66abab/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= golang.org/x/crypto v0.0.0-20180820150726-614d502a4dac/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= golang.org/x/crypto v0.0.0-20180904163835-0709b304e793/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= golang.org/x/crypto v0.0.0-20181029021203-45a5f77698d3/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= -golang.org/x/crypto v0.0.0-20181030102418-4d3f4d9ffa16/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= -golang.org/x/crypto v0.0.0-20181203042331-505ab145d0a9/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= golang.org/x/crypto v0.0.0-20190130090550-b01c7a725664/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= golang.org/x/crypto v0.0.0-20190211182817-74369b46fc67 h1:ng3VDlRp5/DHpSWl02R4rM9I+8M2rhmsuLwAMmkLQWE= golang.org/x/crypto v0.0.0-20190211182817-74369b46fc67/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= golang.org/x/crypto v0.0.0-20190222235706-ffb98f73852f h1:qWFY9ZxP3tfI37wYIs/MnIAqK0vlXp1xnYEa5HxFSSY= golang.org/x/crypto v0.0.0-20190222235706-ffb98f73852f/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= +golang.org/x/crypto v0.0.0-20190228161510-8dd112bcdc25/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= golang.org/x/crypto v0.0.0-20190325154230-a5d413f7728c h1:Vj5n4GlwjmQteupaxJ9+0FNOmBrHfq7vN4btdGoDZgI= golang.org/x/crypto v0.0.0-20190325154230-a5d413f7728c/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= -golang.org/x/exp v0.0.0-20180321215751-8460e604b9de/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= -golang.org/x/exp v0.0.0-20181112044915-a3060d491354/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= golang.org/x/lint v0.0.0-20180702182130-06c8688daad7/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE= golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE= golang.org/x/lint v0.0.0-20181217174547-8f45f776aaf1/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE= golang.org/x/lint v0.0.0-20190227174305-5b3e6a55c961/go.mod h1:wehouNa3lNwaWXcvxsM5YxQ5yQlVC4a0KAMCusXpPoU= golang.org/x/lint v0.0.0-20190301231843-5614ed5bae6f/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE= +golang.org/x/lint v0.0.0-20190313153728-d0100b6bd8b3/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20181023162649-9b4f9f5ad519/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= -golang.org/x/net v0.0.0-20181029044818-c44066c5c816/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20181106065722-10aee1819953/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20181114220301-adae6a3d119a/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20181201002055-351d144fa1fc/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20181220203305-927f97764cc3/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20190108225652-1e06a53dbb7e/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20190125091013-d26f9f9a57f3/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/net v0.0.0-20190206173232-65e2d4e15006/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20190213061140-3a22650c66bd h1:HuTn7WObtcDo9uEEU7rEqL0jYthdXAmZ6PP+meazmaU= golang.org/x/net v0.0.0-20190213061140-3a22650c66bd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= golang.org/x/net v0.0.0-20190327214358-63eda1eb0650 h1:XCbwcsP09zrBt1aYht0fASw+ynbEpYr8NnCkIN9nMM0= golang.org/x/net v0.0.0-20190327214358-63eda1eb0650/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= +golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= +golang.org/x/net v0.0.0-20190420063019-afa5a82059c6 h1:HdqqaWmYAUI7/dmByKKEw+yxDksGSo+9GjkUc9Zp34E= +golang.org/x/net v0.0.0-20190420063019-afa5a82059c6/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= golang.org/x/oauth2 v0.0.0-20170807180024-9a379c6b3e95/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be h1:vEDujvNQGv4jgYKudGeI/+DAX4Jffq6hpD55MmoEvKs= golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= -golang.org/x/oauth2 v0.0.0-20181017192945-9dcd33a902f4/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= golang.org/x/oauth2 v0.0.0-20181203162652-d668ce993890/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= golang.org/x/oauth2 v0.0.0-20190319182350-c85d3e98c914 h1:jIOcLT9BZzyJ9ce+IwwZ+aF9yeCqzrR+NrD68a/SHKw= golang.org/x/oauth2 v0.0.0-20190319182350-c85d3e98c914/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= -golang.org/x/perf v0.0.0-20180704124530-6e6d33e29852/go.mod h1:JLpeXjPJfIyPr5TlbXLkXWLhP8nz10XfvxElABhCtcw= +golang.org/x/oauth2 v0.0.0-20190402181905-9f3314589c9a h1:tImsplftrFpALCYumobsd0K86vlAs/eXGFms2txfJfA= +golang.org/x/oauth2 v0.0.0-20190402181905-9f3314589c9a/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= @@ -799,56 +699,54 @@ golang.org/x/sync v0.0.0-20190227155943-e225da77a7e6/go.mod h1:RxMgew5VJxzue5/jJ golang.org/x/sys v0.0.0-20180823144017-11551d06cbcc/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20180828065106-d99a578cf41b/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= -golang.org/x/sys v0.0.0-20180903190138-2b024373dcd9/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= -golang.org/x/sys v0.0.0-20180906133057-8cf3aee42992/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20180909124046-d0be0721c37e/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20181026203630-95b1ffbd15a5/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= -golang.org/x/sys v0.0.0-20181029174526-d69651ed3497/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= -golang.org/x/sys v0.0.0-20181030150119-7e31e0c00fa0/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20181107165924-66b7b1311ac8/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20181116152217-5ac8a444bdc5/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20181122145206-62eef0e2fa9b/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= -golang.org/x/sys v0.0.0-20181205085412-a5c9d58dba9a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20181218192612-074acd46bca6/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190129075346-302c3dd5f1cc/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20190209173611-3b5209105503/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190213121743-983097b1a8a3 h1:+KlxhGbYkFs8lMfwKn+2ojry1ID5eBSMXprS2u/wqCE= golang.org/x/sys v0.0.0-20190213121743-983097b1a8a3/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190222072716-a9d3bda3a223/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190222171317-cd391775e71e h1:oF7qaQxUH6KzFdKN4ww7NpPdo53SZi4UlcksLrb2y/o= golang.org/x/sys v0.0.0-20190222171317-cd391775e71e/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20190312061237-fead79001313/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190322080309-f49334f85ddc h1:4gbWbmmPFp4ySWICouJl6emP0MyS31yy9SrTlAGFT+g= golang.org/x/sys v0.0.0-20190322080309-f49334f85ddc/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190403152447-81d4e9dc473e h1:nFYrTHrdrAOpShe27kaFHjsqYSEQ0KWqdWLu3xuZJts= +golang.org/x/sys v0.0.0-20190403152447-81d4e9dc473e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/text v0.3.0 h1:g61tztE5qeGQ89tm6NTjjM9VPIm088od1l6aSorWRWg= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.1-0.20180807135948-17ff2d5776d2 h1:z99zHgr7hKfrUcX/KsoJk5FJfjTceCKIp96+biqP4To= golang.org/x/text v0.3.1-0.20180807135948-17ff2d5776d2/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= +golang.org/x/text v0.3.1-0.20181227161524-e6919f6577db h1:6/JqlYfC1CCaLnGceQTI+sDGhC9UBSPAsBqI0Gun6kU= +golang.org/x/text v0.3.1-0.20181227161524-e6919f6577db/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk= golang.org/x/time v0.0.0-20180412165947-fbb02b2291d2/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.0.0-20190308202827-9d24e82272b4 h1:SvFZT6jyqRaOeXpc5h/JSfZenJ2O330aBsf7JfSUXmQ= golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/tools v0.0.0-20180221164845-07fd8470d635/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= -golang.org/x/tools v0.0.0-20180525024113-a5b4c53f6e8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20180828015842-6cd1fcedba52/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= -golang.org/x/tools v0.0.0-20181030000716-a0a13e073c7b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= +golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20181219222714-6e267b5cc78e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= -golang.org/x/tools v0.0.0-20181221154417-3ad2d988d5e2/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20190114222345-bf090417da8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20190226205152-f727befe758c/go.mod h1:9Yl7xja0Znq3iFh3HoIrodX9oNMXvdceNzlUR8zjMvY= +golang.org/x/tools v0.0.0-20190311212946-11955173bddd/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= golang.org/x/tools v0.0.0-20190312170243-e65039ee4138/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= -gonum.org/v1/gonum v0.0.0-20181121035319-3f7ecaa7e8ca/go.mod h1:Y+Yx5eoAFn32cQvJDxZx5Dpnq+c3wtXuadVZAcxbbBo= -gonum.org/v1/netlib v0.0.0-20181029234149-ec6d1f5cefe6/go.mod h1:wa6Ws7BG/ESfp6dHfk7C6KdzKA7wR7u/rKwOGE66zvw= +golang.org/x/tools v0.0.0-20190328211700-ab21143f2384/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= google.golang.org/api v0.0.0-20180829000535-087779f1d2c9 h1:z1TeLUmxf9ws9KLICfmX+KGXTs+rjm+aGWzfsv7MZ9w= google.golang.org/api v0.0.0-20180829000535-087779f1d2c9/go.mod h1:4mhQ8q/RsB7i+udVvVy5NUi08OU8ZlA0gRVgrF7VFY0= -google.golang.org/api v0.0.0-20180910000450-7ca32eb868bf/go.mod h1:4mhQ8q/RsB7i+udVvVy5NUi08OU8ZlA0gRVgrF7VFY0= -google.golang.org/api v0.0.0-20181021000519-a2651947f503/go.mod h1:4mhQ8q/RsB7i+udVvVy5NUi08OU8ZlA0gRVgrF7VFY0= -google.golang.org/api v0.0.0-20181030000543-1d582fd0359e/go.mod h1:4mhQ8q/RsB7i+udVvVy5NUi08OU8ZlA0gRVgrF7VFY0= google.golang.org/api v0.0.0-20181220000619-583d854617af/go.mod h1:4mhQ8q/RsB7i+udVvVy5NUi08OU8ZlA0gRVgrF7VFY0= -google.golang.org/api v0.1.0/go.mod h1:UGEZY7KEX120AnNLIHFMKIo4obdJhkp2tPbaPlQx13Y= google.golang.org/api v0.2.0/go.mod h1:IfRCZScioGtypHNTlz3gFk67J8uePVW7uDTBzXuIkhU= google.golang.org/api v0.3.0 h1:UIJY20OEo3+tK5MBlcdx37kmdH6EnRjGkW78mc6+EeA= google.golang.org/api v0.3.0/go.mod h1:IuvZyQh8jgscv8qWfQ4ABd8m7hEudgBFM/EdhA3BnXw= +google.golang.org/api v0.3.1/go.mod h1:6wY9I6uQWHQ8EM57III9mq/AjF+i8G65rmVagqKMtkk= +google.golang.org/api v0.3.2 h1:iTp+3yyl/KOtxa/d1/JUE0GGSoR6FuW5udver22iwpw= +google.golang.org/api v0.3.2/go.mod h1:6wY9I6uQWHQ8EM57III9mq/AjF+i8G65rmVagqKMtkk= google.golang.org/appengine v1.1.0 h1:igQkv0AAhEIvTEpD5LIpAfav2eeVO9HBTjvKHVJPRSs= google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM= google.golang.org/appengine v1.2.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= @@ -857,25 +755,24 @@ google.golang.org/appengine v1.4.0 h1:/wp5JvzpHIxhs/dumFmF7BXTf3Z+dd4uXta4kVyO50 google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8 h1:Nw54tB0rB7hY/N0NQvRW8DG4Yk3Q6T9cu9RcFQDu1tc= google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc= -google.golang.org/genproto v0.0.0-20180831171423-11092d34479b/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc= -google.golang.org/genproto v0.0.0-20181016170114-94acd270e44e/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc= -google.golang.org/genproto v0.0.0-20181029155118-b69ba1387ce2/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc= -google.golang.org/genproto v0.0.0-20181202183823-bd91e49a0898/go.mod h1:7Ep/1NZk928CDR8SjdVbjWNpdIf6nzjE3BTgJDr2Atg= google.golang.org/genproto v0.0.0-20181219182458-5a97ab628bfb/go.mod h1:7Ep/1NZk928CDR8SjdVbjWNpdIf6nzjE3BTgJDr2Atg= -google.golang.org/genproto v0.0.0-20190201180003-4b09977fb922/go.mod h1:L3J43x8/uS+qIUoksaLKe6OS3nUKxOKuIFz1sl2/jx4= google.golang.org/genproto v0.0.0-20190307195333-5fe7a883aa19 h1:Lj2SnHtxkRGJDqnGaSjo+CCdIieEnwVazbOXILwQemk= google.golang.org/genproto v0.0.0-20190307195333-5fe7a883aa19/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= +google.golang.org/genproto v0.0.0-20190404172233-64821d5d2107 h1:xtNn7qFlagY2mQNFHMSRPjT2RkOV4OXM7P5TVy9xATo= +google.golang.org/genproto v0.0.0-20190404172233-64821d5d2107/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= google.golang.org/grpc v1.14.0/go.mod h1:yo6s7OP7yaDglbqo1J04qKzAhqBH6lvTonzMVmEdcZw= -google.golang.org/grpc v1.15.0/go.mod h1:0JHn/cJsOMiMfNA9+DeHDlAU7KAAB5GDlYFpa9MZMio= google.golang.org/grpc v1.16.0/go.mod h1:0JHn/cJsOMiMfNA9+DeHDlAU7KAAB5GDlYFpa9MZMio= google.golang.org/grpc v1.17.0/go.mod h1:6QZJwpn2B+Zp71q/5VxRsJ6NXXVCE5NRUHRo+f3cWCs= google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c= google.golang.org/grpc v1.19.1 h1:TrBcJ1yqAl1G++wO39nD/qtgpsW9/1+QGrluyMGEYgM= google.golang.org/grpc v1.19.1/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c= +google.golang.org/grpc v1.20.0/go.mod h1:chYK+tFQF0nDUGJgXMSgLCQk3phJEuONr2DCgLDdAQM= +google.golang.org/grpc v1.20.1 h1:Hz2g2wirWK7H0qIIhGIqRGTuMwTE8HEKFnDZZ7lm9NU= +google.golang.org/grpc v1.20.1/go.mod h1:10oTOabMzJvdu6/UiuZezV6QK5dSlG84ov/aaiqXj38= +gopkg.in/DataDog/dd-trace-go.v0 v0.6.1/go.mod h1:uxRvUTC61u1w+PTfyHNOzLPTCHYt6CJyGZvZSAzGvZA= gopkg.in/airbrake/gobrake.v2 v2.0.9 h1:7z2uVWwn7oVeeugY1DtlPAy5H+KYgB1KeKTnqjNatLo= gopkg.in/airbrake/gobrake.v2 v2.0.9/go.mod h1:/h5ZAUhDkGaJfjzjKLSjv6zCL6O0LLBxU4K+aSYdM/U= gopkg.in/alecthomas/kingpin.v2 v2.2.6/go.mod h1:FMv+mEhP44yOT+4EoQTLFTRgOQ1FBLkstjWtayDeSgw= -gopkg.in/asn1-ber.v1 v1.0.0-20170511165959-379148ca0225/go.mod h1:cuepJuh7vyXfUyUwEgHQXw849cJrilpS5NeIjOWESAw= gopkg.in/asn1-ber.v1 v1.0.0-20181015200546-f715ec2f112d h1:TxyelI5cVkbREznMhfzycHdkp5cLA7DpE+GKjSslYhM= gopkg.in/asn1-ber.v1 v1.0.0-20181015200546-f715ec2f112d/go.mod h1:cuepJuh7vyXfUyUwEgHQXw849cJrilpS5NeIjOWESAw= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= @@ -889,45 +786,56 @@ gopkg.in/gemnasium/logrus-airbrake-hook.v2 v2.1.2 h1:OAj3g0cR6Dx/R07QgQe8wkA9RNj gopkg.in/gemnasium/logrus-airbrake-hook.v2 v2.1.2/go.mod h1:Xk6kEKp8OKb+X14hQBKWaSkCsqBpgog8nAV2xsGOxlo= gopkg.in/gorethink/gorethink.v4 v4.1.0 h1:xoE9qJ9Ae9KdKEsiQGCF44u2JdnjyohrMBRDtts3Gjw= gopkg.in/gorethink/gorethink.v4 v4.1.0/go.mod h1:M7JgwrUAmshJ3iUbEK0Pt049MPyPK+CYDGGaEjdZb/c= +gopkg.in/inf.v0 v0.9.0/go.mod h1:cWUDdTG/fYaXco+Dcufb5Vnc6Gp2YChqWtbxRZE0mXw= gopkg.in/inf.v0 v0.9.1 h1:73M5CoZyi3ZLMOyDlQh031Cx6N9NDJ2Vvfl76EDAgDc= gopkg.in/inf.v0 v0.9.1/go.mod h1:cWUDdTG/fYaXco+Dcufb5Vnc6Gp2YChqWtbxRZE0mXw= gopkg.in/ini.v1 v1.42.0 h1:7N3gPTt50s8GuLortA00n8AqRTk75qOP98+mTPpgzRk= gopkg.in/ini.v1 v1.42.0/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k= -gopkg.in/ldap.v2 v2.5.1/go.mod h1:oI0cpe/D7HRtBQl8aTg+ZmzFUAvu4lsv3eLXMLGFxWk= gopkg.in/mgo.v2 v2.0.0-20180705113604-9856a29383ce h1:xcEWjVhvbDy+nHP67nPDDpbYrY+ILlfndk4bRioVHaU= gopkg.in/mgo.v2 v2.0.0-20180705113604-9856a29383ce/go.mod h1:yeKp02qBN3iKW1OzL3MGk2IdtZzaj7SFntXj72NppTA= gopkg.in/ory-am/dockertest.v2 v2.2.3 h1:vSYvP7tvyfAm9merq0gHmcI4yk5nkPpfXmoBCnSP3/4= gopkg.in/ory-am/dockertest.v2 v2.2.3/go.mod h1:kDHEsan1UcKFYH1c28sDmqnmeqIpB4Nj682gSNhYDYM= +gopkg.in/resty.v1 v1.12.0 h1:CuXP0Pjfw9rOuY6EP+UvtNvt5DSqHpIxILZKT/quCZI= gopkg.in/resty.v1 v1.12.0/go.mod h1:mDo4pnntr5jdWRML875a/NmxYqAlA73dVijT2AXvQQo= -gopkg.in/robfig/cron.v2 v2.0.0-20150107220207-be2e0b0deed5/go.mod h1:hiOFpYm0ZJbusNj2ywpbrXowU3G8U6GIQzqn2mw1UIE= gopkg.in/square/go-jose.v2 v2.3.0 h1:nLzhkFyl5bkblqYBoiWJUt5JkWOzmiaBtCxdJAqJd3U= gopkg.in/square/go-jose.v2 v2.3.0/go.mod h1:M9dMgbHiYLoDGQrXy7OpJDJWiKiU//h+vD76mk0e1AI= -gopkg.in/src-d/go-billy.v4 v4.2.1/go.mod h1:tm33zBoOwxjYHZIE+OV8bxTWFMJLrconzFMd38aARFk= -gopkg.in/src-d/go-git-fixtures.v3 v3.1.1/go.mod h1:dLBcvytrw/TYZsNTWCnkNF2DSIlzWYqTe3rJR56Ac7g= -gopkg.in/src-d/go-git.v4 v4.8.1/go.mod h1:Vtut8izDyrM8BUVQnzJ+YvmNcem2J89EmfZYCkLokZk= +gopkg.in/square/go-jose.v2 v2.3.1 h1:SK5KegNXmKmqE342YYN2qPHEnUYeoMiXXl1poUlI+o4= +gopkg.in/square/go-jose.v2 v2.3.1/go.mod h1:M9dMgbHiYLoDGQrXy7OpJDJWiKiU//h+vD76mk0e1AI= gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7 h1:uRGJdciOHaEIrze2W8Q3AKkepLTh2hOroT7a+7czfdQ= gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7/go.mod h1:dt/ZhP58zS4L8KSrWDmTeBkI65Dw0HsyUHuEVlX15mw= -gopkg.in/vmihailenco/msgpack.v2 v2.9.1/go.mod h1:/3Dn1Npt9+MYyLpYYXjInO/5jvMLamn+AEGwNEOatn8= -gopkg.in/warnings.v0 v0.1.2/go.mod h1:jksf8JmL6Qr/oQM2OXTHunEvvTAsrWBLb6OOjuVWRNI= gopkg.in/yaml.v2 v2.0.0-20170812160011-eb3733d160e7/go.mod h1:JAlM8MvJe8wmxCU4Bli9HhUf9+ttbYbLASfIpnQbh74= gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.2.2 h1:ZCJp+EgiOT7lHqUV2J862kp8Qj64Jo6az82+3Td9dZw= gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gotest.tools v2.2.0+incompatible h1:VsBPFP1AI068pPrMxtb/S8Zkgf9xEmTLJjfM+P5UIEo= gotest.tools v2.2.0+incompatible/go.mod h1:DsYFclhRJ6vuDpmuTbkuFWG+y2sxOXAzmJt81HFBacw= -grpc.go4.org v0.0.0-20170609214715-11d0a25b4919/go.mod h1:77eQGdRu53HpSqPFJFmuJdjuHRquDANNeA4x7B8WQ9o= honnef.co/go/tools v0.0.0-20180728063816-88497007e858/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= honnef.co/go/tools v0.0.0-20180920025451-e3ad64cb4ed3/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= -honnef.co/go/tools v0.0.0-20181108184350-ae8f1f9103cc/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= honnef.co/go/tools v0.0.0-20190106161140-3f1c8253044a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= k8s.io/api v0.0.0-20180806132203-61b11ee65332 h1:+ED/2NBbOoeWB9QrGTHxZI7UnE7rnHPKKumOl0WXphs= k8s.io/api v0.0.0-20180806132203-61b11ee65332/go.mod h1:iuAfoD4hCxJ8Onx9kaTIt30j7jUFS00AXQi6QMi99vA= +k8s.io/api v0.0.0-20181204000039-89a74a8d264d h1:HQoGWsWUe/FmRcX9BU440AAMnzBFEf+DBo4nbkQlNzs= +k8s.io/api v0.0.0-20181204000039-89a74a8d264d/go.mod h1:iuAfoD4hCxJ8Onx9kaTIt30j7jUFS00AXQi6QMi99vA= +k8s.io/api v0.0.0-20190409092523-d687e77c8ae9 h1:c9UEl5z8gk1DGh/g3snETZ+a52YeR9VdbX/3BQ4PHas= +k8s.io/api v0.0.0-20190409092523-d687e77c8ae9/go.mod h1:FQEUn50aaytlU65qqBn/w+5ugllHwrBzKm7DzbnXdzE= k8s.io/apimachinery v0.0.0-20180821005732-488889b0007f h1:V0PkbgaYp5JqCmzLyRmssDtzim0NShXM8gYi4fcX230= k8s.io/apimachinery v0.0.0-20180821005732-488889b0007f/go.mod h1:ccL7Eh7zubPUSh9A3USN90/OzHNSVN6zxzde07TDCL0= +k8s.io/apimachinery v0.0.0-20181127025237-2b1284ed4c93 h1:tT6oQBi0qwLbbZSfDkdIsb23EwaLY85hoAV4SpXfdao= +k8s.io/apimachinery v0.0.0-20181127025237-2b1284ed4c93/go.mod h1:ccL7Eh7zubPUSh9A3USN90/OzHNSVN6zxzde07TDCL0= +k8s.io/apimachinery v0.0.0-20190409092423-760d1845f48b h1:fVkKJL9FIpA8LSJyHVM00MP45q1WJ7+af77vcxmQP4g= +k8s.io/apimachinery v0.0.0-20190409092423-760d1845f48b/go.mod h1:FW86P8YXVLsbuplGMZeb20J3jYHscrDqw4jELaFJvRU= k8s.io/client-go v8.0.0+incompatible h1:tTI4hRmb1DRMl4fG6Vclfdi6nTM82oIrTT7HfitmxC4= k8s.io/client-go v8.0.0+incompatible/go.mod h1:7vJpHMYJwNQCWgzmNV+VYUl1zCObLyodBc8nIyt8L5s= +k8s.io/client-go v10.0.0+incompatible h1:F1IqCqw7oMBzDkqlcBymRq1450wD0eNqLE9jzUrIi34= +k8s.io/client-go v10.0.0+incompatible/go.mod h1:7vJpHMYJwNQCWgzmNV+VYUl1zCObLyodBc8nIyt8L5s= +k8s.io/klog v0.0.0-20181108234604-8139d8cb77af h1:s6rm8OxBbyDNSRkpyAd5OL4icUdBICVw9+mFADa+t5E= +k8s.io/klog v0.0.0-20181108234604-8139d8cb77af/go.mod h1:Gq+BEi5rUBO/HRz0bTSXDUcqjScdoY3a9IHpCEIOOfk= +k8s.io/klog v0.0.0-20190306015804-8e90cee79f82 h1:SHucoAy7lRb+w5oC/hbXyZg+zX+Wftn6hD4tGzHCVqA= +k8s.io/klog v0.0.0-20190306015804-8e90cee79f82/go.mod h1:Gq+BEi5rUBO/HRz0bTSXDUcqjScdoY3a9IHpCEIOOfk= +k8s.io/kube-openapi v0.0.0-20190228160746-b3a7cee44a30/go.mod h1:BXM9ceUBTj2QnfH2MK1odQs778ajze1RxcmP6S8RVVc= +k8s.io/kube-openapi v0.0.0-20190306001800-15615b16d372/go.mod h1:BXM9ceUBTj2QnfH2MK1odQs778ajze1RxcmP6S8RVVc= layeh.com/radius v0.0.0-20190322222518-890bc1058917 h1:BDXFaFzUt5EIqe/4wrTc4AcYZWP6iC6Ult+jQWLh5eU= layeh.com/radius v0.0.0-20190322222518-890bc1058917/go.mod h1:fywZKyu//X7iRzaxLgPWsvc0L26IUpVvE/aeIL2JtIQ= -sourcegraph.com/sourcegraph/go-diff v0.5.0/go.mod h1:kuch7UrkMzY0X+p9CRK03kfuPQ2zzQcaEFbx8wA8rck= -sourcegraph.com/sqs/pbtypes v0.0.0-20180604144634-d3ebe8f20ae4/go.mod h1:ketZ/q3QxT9HOBeFhu6RdvsftgpsbFHBF5Cas6cDKZ0= +sigs.k8s.io/yaml v1.1.0 h1:4A07+ZFc2wgJwo8YNlQpr1rVlgUDlxXHhPJciaPY5gs= +sigs.k8s.io/yaml v1.1.0/go.mod h1:UJmg0vDUVViEyp3mgSv9WPwZCDxu4rQW1olrI1uml+o= From df6561165aff77581ea95000da8cf8e04510cd5f Mon Sep 17 00:00:00 2001 From: Asim Aslam Date: Tue, 23 Apr 2019 07:13:21 +0000 Subject: [PATCH 181/196] gofmt --- registry/consul/consul.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/registry/consul/consul.go b/registry/consul/consul.go index 52b8b2cd..89f0a2d0 100644 --- a/registry/consul/consul.go +++ b/registry/consul/consul.go @@ -111,7 +111,7 @@ func configure(c *consulRegistry, opts ...registry.Option) { // requires secure connection? if c.opts.Secure || c.opts.TLSConfig != nil { - + config.Scheme = "https" // We're going to support InsecureSkipVerify config.HttpClient.Transport = newTransport(c.opts.TLSConfig) From 46f44fd8f8a93707849603e64e9fd05608233f20 Mon Sep 17 00:00:00 2001 From: Asim Aslam Date: Tue, 23 Apr 2019 07:15:03 +0000 Subject: [PATCH 182/196] update go mod --- go.mod | 50 +++++++++++++++++++++++++++-- go.sum | 100 +++++++++++++++++++++++++++++++++++++++++++++++++++++++-- 2 files changed, 146 insertions(+), 4 deletions(-) diff --git a/go.mod b/go.mod index ecd63681..0ea0caa7 100644 --- a/go.mod +++ b/go.mod @@ -1,15 +1,21 @@ module github.com/micro/go-micro require ( + github.com/Azure/azure-sdk-for-go v27.3.0+incompatible // indirect github.com/Azure/go-ansiterm v0.0.0-20170929234023-d6e3b3328b78 // indirect + github.com/Azure/go-autorest v12.0.0+incompatible // indirect github.com/DataDog/datadog-go v2.2.0+incompatible // indirect + github.com/Jeffail/gabs v1.2.0 // indirect github.com/Microsoft/go-winio v0.4.12 // indirect github.com/NYTimes/gziphandler v1.1.1 // indirect github.com/Nvveen/Gotty v0.0.0-20120604004816-cd527374f1e5 // indirect github.com/SAP/go-hdb v0.14.1 // indirect github.com/StackExchange/wmi v0.0.0-20181212234831-e0a55b97c705 // indirect + github.com/aliyun/alibaba-cloud-sdk-go v0.0.0-20190423023524-6ff5e74c25e8 // indirect github.com/araddon/gou v0.0.0-20190110011759-c797efecbb61 // indirect github.com/asaskevich/govalidator v0.0.0-20180720115003-f9ffefc3facf // indirect + github.com/aws/aws-sdk-go v1.19.15 // indirect + github.com/beorn7/perks v1.0.0 // indirect github.com/bitly/go-hostpool v0.0.0-20171023180738-a3a6125de932 // indirect github.com/bmizerany/assert v0.0.0-20160611221934-b7ed37b82869 // indirect github.com/boltdb/bolt v1.3.1 // indirect @@ -20,8 +26,13 @@ require ( github.com/circonus-labs/circonusllhist v0.1.3 // indirect github.com/containerd/continuity v0.0.0-20181203112020-004b46473808 // indirect github.com/coredns/coredns v1.5.0 // indirect + github.com/coreos/etcd v3.3.12+incompatible // indirect + github.com/coreos/go-semver v0.3.0 // indirect + github.com/coreos/go-systemd v0.0.0-20190321100706-95778dfbb74e // indirect github.com/dancannon/gorethink v4.0.0+incompatible // indirect github.com/denisenkom/go-mssqldb v0.0.0-20190418034912-35416408c946 // indirect + github.com/denverdino/aliyungo v0.0.0-20190410085603-611ead8a6fed // indirect + github.com/digitalocean/godo v1.13.0 // indirect github.com/dnaeon/go-vcr v1.0.1 // indirect github.com/docker/go-connections v0.4.0 // indirect github.com/duosecurity/duo_api_golang v0.0.0-20190308151101-6c680f768e74 // indirect @@ -30,6 +41,7 @@ require ( github.com/envoyproxy/protoc-gen-validate v0.0.14 // indirect github.com/fullsailor/pkcs7 v0.0.0-20190404230743-d7302db945fa // indirect github.com/garyburd/redigo v1.6.0 // indirect + github.com/go-ldap/ldap v3.0.3+incompatible // indirect github.com/go-log/log v0.1.0 github.com/go-ole/go-ole v1.2.4 // indirect github.com/go-sql-driver/mysql v1.4.1 // indirect @@ -37,20 +49,27 @@ require ( github.com/gocql/gocql v0.0.0-20190418090649-59a610c947c5 // indirect github.com/gogo/googleapis v1.2.0 // indirect github.com/golang/protobuf v1.3.1 + github.com/google/btree v1.0.0 // indirect github.com/google/go-github v17.0.0+incompatible // indirect + github.com/google/go-querystring v1.0.0 // indirect github.com/google/gofuzz v1.0.0 // indirect github.com/google/uuid v1.1.1 + github.com/gophercloud/gophercloud v0.0.0-20190422143055-fe6299556848 // indirect + github.com/gopherjs/gopherjs v0.0.0-20190411002643-bd77b112433e // indirect github.com/gotestyourself/gotestyourself v2.2.0+incompatible // indirect github.com/hashicorp/consul v1.4.4 github.com/hashicorp/go-discover v0.0.0-20190408185603-6ccdb67f9b84 // indirect github.com/hashicorp/go-memdb v1.0.1 // indirect + github.com/hashicorp/go-msgpack v0.5.4 // indirect + github.com/hashicorp/go-version v1.2.0 // indirect github.com/hashicorp/hil v0.0.0-20190212132231-97b3a9cdfa93 // indirect + github.com/hashicorp/mdns v1.0.1 // indirect github.com/hashicorp/memberlist v0.1.3 github.com/hashicorp/net-rpc-msgpackrpc v0.0.0-20151116020338-a14192a58a69 // indirect - github.com/hashicorp/nomad/api v0.0.0-20190419150859-8a0df4034dc4 // indirect + github.com/hashicorp/nomad/api v0.0.0-20190422193122-09c998a4a160 // indirect github.com/hashicorp/raft v1.0.1 // indirect github.com/hashicorp/raft-boltdb v0.0.0-20171010151810-6e5ba93211ea // indirect - github.com/hashicorp/serf v0.8.2 // indirect + github.com/hashicorp/serf v0.8.3 // indirect github.com/hashicorp/vault v1.1.2 // indirect github.com/hashicorp/vault-plugin-auth-alicloud v0.5.1 // indirect github.com/hashicorp/vault-plugin-auth-azure v0.5.1 // indirect @@ -63,36 +82,63 @@ require ( github.com/hashicorp/vault-plugin-secrets-gcp v0.5.2 // indirect github.com/hashicorp/vault-plugin-secrets-gcpkms v0.5.1 // indirect github.com/hashicorp/vault-plugin-secrets-kv v0.5.1 // indirect + github.com/hashicorp/vault/sdk v0.1.9 // indirect github.com/influxdata/influxdb v1.7.6 // indirect + github.com/jarcoal/httpmock v1.0.3 // indirect github.com/jefferai/jsonx v1.0.0 // indirect + github.com/joyent/triton-go v0.0.0-20190112182421-51ffac552869 // indirect github.com/keybase/go-crypto v0.0.0-20190416182011-b785b22cc757 // indirect + github.com/konsorten/go-windows-terminal-sequences v1.0.2 // indirect github.com/lib/pq v1.1.0 // indirect github.com/mattbaird/elastigo v0.0.0-20170123220020-2fe47fd29e4b // indirect + github.com/mattn/go-isatty v0.0.7 // indirect github.com/michaelklishin/rabbit-hole v1.5.0 // indirect github.com/micro/cli v0.1.0 github.com/micro/go-log v0.1.0 github.com/micro/go-rcache v0.3.0 github.com/micro/mdns v0.1.0 github.com/micro/util v0.2.0 + github.com/miekg/dns v1.1.8 // indirect github.com/mitchellh/hashstructure v1.0.0 + github.com/onsi/gomega v1.5.0 // indirect github.com/opencontainers/go-digest v1.0.0-rc1 // indirect github.com/opencontainers/image-spec v1.0.1 // indirect github.com/opencontainers/runc v0.1.1 // indirect + github.com/opentracing/opentracing-go v1.1.0 // indirect github.com/ory-am/common v0.4.0 // indirect github.com/ory/dockertest v3.3.4+incompatible // indirect github.com/pborman/uuid v1.2.0 // indirect github.com/pkg/errors v0.8.1 github.com/pquerna/otp v1.1.0 // indirect + github.com/prometheus/client_model v0.0.0-20190129233127-fd36f4220a90 // indirect + github.com/prometheus/common v0.3.0 // indirect + github.com/prometheus/procfs v0.0.0-20190416084830-8368d24ba045 // indirect github.com/samuel/go-zookeeper v0.0.0-20180130194729-c4fab1ac1bec // indirect github.com/shirou/gopsutil v2.18.12+incompatible // indirect github.com/shirou/w32 v0.0.0-20160930032740-bb4de0191aa4 // indirect + github.com/sirupsen/logrus v1.4.1 // indirect + github.com/smartystreets/assertions v0.0.0-20190401211740-f487f9de1cd3 // indirect + github.com/softlayer/softlayer-go v0.0.0-20190415014515-aa510384a41b // indirect github.com/streadway/amqp v0.0.0-20190404075320-75d898a42a94 // indirect + github.com/stretchr/objx v0.2.0 // indirect github.com/tv42/httpunix v0.0.0-20150427012821-b75d8614f926 // indirect + github.com/vmware/govmomi v0.20.0 // indirect + golang.org/x/crypto v0.0.0-20190422183909-d864b10871cd // indirect golang.org/x/net v0.0.0-20190420063019-afa5a82059c6 + golang.org/x/sync v0.0.0-20190423024810-112230192c58 // indirect + golang.org/x/sys v0.0.0-20190422165155-953cdadca894 // indirect + google.golang.org/appengine v1.5.0 // indirect + google.golang.org/genproto v0.0.0-20190418145605-e7d98fc518a7 // indirect google.golang.org/grpc v1.20.1 // indirect gopkg.in/gorethink/gorethink.v4 v4.1.0 // indirect gopkg.in/mgo.v2 v2.0.0-20180705113604-9856a29383ce // indirect gopkg.in/ory-am/dockertest.v2 v2.2.3 // indirect gotest.tools v2.2.0+incompatible // indirect + k8s.io/api v0.0.0-20190419092548-c5cad27821f6 // indirect + k8s.io/apimachinery v0.0.0-20190419212445-b874eabb9a4e // indirect + k8s.io/client-go v11.0.0+incompatible // indirect + k8s.io/utils v0.0.0-20190308190857-21c4ce38f2a7 // indirect layeh.com/radius v0.0.0-20190322222518-890bc1058917 // indirect ) + +replace github.com/golang/lint => github.com/golang/lint v0.0.0-20190227174305-8f45f776aaf1 diff --git a/go.sum b/go.sum index 4b08c70c..a60eadbc 100644 --- a/go.sum +++ b/go.sum @@ -12,12 +12,16 @@ github.com/Azure/azure-sdk-for-go v16.0.0+incompatible h1:gr1qKY/Ll72VjFTZmaBwRK github.com/Azure/azure-sdk-for-go v16.0.0+incompatible/go.mod h1:9XXNKU+eRnpl9moKnB4QOLf1HestfXbmab5FXxiDBjc= github.com/Azure/azure-sdk-for-go v27.1.0+incompatible h1:/aGULErVaJsMdtew1p9OhEo8FeBzfRKRzJbc8NWJv/w= github.com/Azure/azure-sdk-for-go v27.1.0+incompatible/go.mod h1:9XXNKU+eRnpl9moKnB4QOLf1HestfXbmab5FXxiDBjc= +github.com/Azure/azure-sdk-for-go v27.3.0+incompatible h1:i+ROfG3CsZUPoVAnhK06T3R6PmBzKB9ds+lHBpN7Mzo= +github.com/Azure/azure-sdk-for-go v27.3.0+incompatible/go.mod h1:9XXNKU+eRnpl9moKnB4QOLf1HestfXbmab5FXxiDBjc= github.com/Azure/go-ansiterm v0.0.0-20170929234023-d6e3b3328b78 h1:w+iIsaOQNcT7OZ575w+acHgRric5iCyQh+xv+KJ4HB8= github.com/Azure/go-ansiterm v0.0.0-20170929234023-d6e3b3328b78/go.mod h1:LmzpDX56iTiv29bbRTIsUNlaFfuhWRQBWjQdVyAevI8= github.com/Azure/go-autorest v10.7.0+incompatible h1:dB+dKSLGdJLEhU/FoZTSNSPMZuE5H4M5p5zgSct7qwM= github.com/Azure/go-autorest v10.7.0+incompatible/go.mod h1:r+4oMnoxhatjLLJ6zxSWATqVooLgysK6ZNox3g/xq24= github.com/Azure/go-autorest v11.7.1+incompatible h1:M2YZIajBBVekV86x0rr1443Lc1F/Ylxb9w+5EtSyX3Q= github.com/Azure/go-autorest v11.7.1+incompatible/go.mod h1:r+4oMnoxhatjLLJ6zxSWATqVooLgysK6ZNox3g/xq24= +github.com/Azure/go-autorest v12.0.0+incompatible h1:N+VqClcomLGD/sHb3smbSYYtNMgKpVV3Cd5r5i8z6bQ= +github.com/Azure/go-autorest v12.0.0+incompatible/go.mod h1:r+4oMnoxhatjLLJ6zxSWATqVooLgysK6ZNox3g/xq24= github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= github.com/DataDog/datadog-go v2.2.0+incompatible h1:V5BKkxACZLjzHjSgBbr2gvLA2Ae49yhc6CSY7MLy5k4= github.com/DataDog/datadog-go v2.2.0+incompatible/go.mod h1:LButxg5PwREeZtORoXG3tL4fMGNddJ+vMq1mwgfaqoQ= @@ -25,6 +29,8 @@ github.com/DataDog/dd-trace-go v0.6.1/go.mod h1:SmQTTcC37XMyEm75HV0AWiZIYxDiaNhR github.com/DataDog/zstd v1.3.5/go.mod h1:1jcaCB/ufaK+sKp1NBhlGmpz41jOoPQ35bpF36t7BBo= github.com/Jeffail/gabs v1.1.1 h1:V0uzR08Hj22EX8+8QMhyI9sX2hwRu+/RJhJUmnwda/E= github.com/Jeffail/gabs v1.1.1/go.mod h1:6xMvQMK4k33lb7GUUpaAPh6nKMmemQeg5d4gn7/bOXc= +github.com/Jeffail/gabs v1.2.0 h1:uFhoIVTtsX7hV2RxNgWad8gMU+8OJdzFbOathJdhD3o= +github.com/Jeffail/gabs v1.2.0/go.mod h1:6xMvQMK4k33lb7GUUpaAPh6nKMmemQeg5d4gn7/bOXc= github.com/Microsoft/go-winio v0.4.12 h1:xAfWHN1IrQ0NJ9TBC0KBZoqLjzDTr1ML+4MywiUOryc= github.com/Microsoft/go-winio v0.4.12/go.mod h1:VhR8bwka0BXejwEJY73c50VrPtXAaKcyvVC4A4RozmA= github.com/NYTimes/gziphandler v1.1.1 h1:ZUDjpQae29j0ryrS0u/B8HZfJBtBQHjqw2rQ2cqUQ3I= @@ -44,6 +50,8 @@ github.com/alecthomas/template v0.0.0-20160405071501-a0175ee3bccc/go.mod h1:LOuy github.com/alecthomas/units v0.0.0-20151022065526-2efee857e7cf/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0= github.com/aliyun/alibaba-cloud-sdk-go v0.0.0-20190412020505-60e2075261b6 h1:5RwdKFlGKokYBbq4M2ZZ0LzfxdK4e1L4rwQH+76wPkE= github.com/aliyun/alibaba-cloud-sdk-go v0.0.0-20190412020505-60e2075261b6/go.mod h1:T9M45xf79ahXVelWoOBmH0y4aC1t5kXO5BxwyakgIGA= +github.com/aliyun/alibaba-cloud-sdk-go v0.0.0-20190423023524-6ff5e74c25e8 h1:n3yJ9NAD5JfC5aTyO6yoJm5wbQ8LozPHrj2qJnAAHlI= +github.com/aliyun/alibaba-cloud-sdk-go v0.0.0-20190423023524-6ff5e74c25e8/go.mod h1:T9M45xf79ahXVelWoOBmH0y4aC1t5kXO5BxwyakgIGA= github.com/apache/thrift v0.12.0/go.mod h1:cp2SuWMxlEZw2r+iP2GNCdIi4C1qmUzdZFSVb+bacwQ= github.com/araddon/gou v0.0.0-20190110011759-c797efecbb61 h1:Xz25cuW4REGC5W5UtpMU3QItMIImag615HiQcRbxqKQ= github.com/araddon/gou v0.0.0-20190110011759-c797efecbb61/go.mod h1:ikc1XA58M+Rx7SEbf0bLJCfBkwayZ8T5jBo5FXK8Uz8= @@ -60,8 +68,12 @@ github.com/asaskevich/govalidator v0.0.0-20180720115003-f9ffefc3facf/go.mod h1:l github.com/aws/aws-sdk-go v1.14.17/go.mod h1:ZRmQr0FajVIyZ4ZzBYKG5P3ZqPz9IHG41ZoMu1ADI3k= github.com/aws/aws-sdk-go v1.15.24 h1:xLAdTA/ore6xdPAljzZRed7IGqQgC+nY+ERS5vaj4Ro= github.com/aws/aws-sdk-go v1.15.24/go.mod h1:mFuSZ37Z9YOHbQEwBWztmVzqXrEkub65tZoCYDt7FT0= +github.com/aws/aws-sdk-go v1.19.15 h1:Ov8zxPunHxZFxrXBarqzkZBSZugJRzPgb4mfq/SyVgA= +github.com/aws/aws-sdk-go v1.19.15/go.mod h1:KmX6BPdI08NWTb3/sm4ZGu5ShLoqVDhKgpiN924inxo= github.com/beorn7/perks v0.0.0-20180321164747-3a771d992973 h1:xJ4a3vCFaGF/jqvzLMYoU8P317H5OQ+Via4RmuPwCS0= github.com/beorn7/perks v0.0.0-20180321164747-3a771d992973/go.mod h1:Dwedo/Wpr24TaqPxmxbtue+5NUziq4I4S80YR8gNf3Q= +github.com/beorn7/perks v1.0.0 h1:HWo1m869IqiPhD389kmkxeTalrjNbbJTC8LXupb+sl0= +github.com/beorn7/perks v1.0.0/go.mod h1:KWe93zE9D1o94FZ5RNwFwVgaQK1VOXiVxmqh+CedLV8= github.com/bgentry/speakeasy v0.1.0 h1:ByYyxL9InA1OWqxJqqp2A5pYHUrCiAL6K3J+LKSsQkY= github.com/bgentry/speakeasy v0.1.0/go.mod h1:+zsyZBPWlz7T6j88CTgSN5bM796AkVf0kBD4zp0CCIs= github.com/bitly/go-hostpool v0.0.0-20171023180738-a3a6125de932 h1:mXoPYz/Ul5HYEDvkta6I8/rnYM5gSdSV2tJ6XbZuEtY= @@ -96,12 +108,18 @@ github.com/coreos/bbolt v1.3.2 h1:wZwiHHUieZCquLkDL0B8UhzreNWsPHooDAG3q34zk0s= github.com/coreos/bbolt v1.3.2/go.mod h1:iRUV2dpdMOn7Bo10OQBFzIJO9kkE559Wcmn+qkEiiKk= github.com/coreos/etcd v3.3.11+incompatible h1:0gCnqKsq7XxMi69JsnbmMc1o+RJH3XH64sV9aiTTYko= github.com/coreos/etcd v3.3.11+incompatible/go.mod h1:uF7uidLiAD3TWHmW31ZFd/JWoc32PjwdhPthX9715RE= +github.com/coreos/etcd v3.3.12+incompatible h1:pAWNwdf7QiT1zfaWyqCtNZQWCLByQyA3JrSQyuYAqnQ= +github.com/coreos/etcd v3.3.12+incompatible/go.mod h1:uF7uidLiAD3TWHmW31ZFd/JWoc32PjwdhPthX9715RE= github.com/coreos/go-oidc v2.0.0+incompatible h1:+RStIopZ8wooMx+Vs5Bt8zMXxV1ABl5LbakNExNmZIg= github.com/coreos/go-oidc v2.0.0+incompatible/go.mod h1:CgnwVTmzoESiwO9qyAFEMiHoZ1nMCKZlZ9V6mm3/LKc= github.com/coreos/go-semver v0.2.0 h1:3Jm3tLmsgAYcjC+4Up7hJrFBPr+n7rAqYeSw/SZazuY= github.com/coreos/go-semver v0.2.0/go.mod h1:nnelYz7RCh+5ahJtPPxZlU+153eP4D4r3EedlOD2RNk= +github.com/coreos/go-semver v0.3.0 h1:wkHLiw0WNATZnSG7epLsujiMCgPAc9xhjJ4tgnAxmfM= +github.com/coreos/go-semver v0.3.0/go.mod h1:nnelYz7RCh+5ahJtPPxZlU+153eP4D4r3EedlOD2RNk= github.com/coreos/go-systemd v0.0.0-20190212144455-93d5ec2c7f76 h1:FE783w8WFh+Rvg+7bZ5g8p7gP4SeVS4AoNwkvazlsBg= github.com/coreos/go-systemd v0.0.0-20190212144455-93d5ec2c7f76/go.mod h1:F5haX7vjVVG0kc13fIWeqUViNPyEJxv/OmvnBo0Yme4= +github.com/coreos/go-systemd v0.0.0-20190321100706-95778dfbb74e h1:Wf6HqHfScWJN9/ZjdUKyjop4mf3Qdd+1TvvltAvM3m8= +github.com/coreos/go-systemd v0.0.0-20190321100706-95778dfbb74e/go.mod h1:F5haX7vjVVG0kc13fIWeqUViNPyEJxv/OmvnBo0Yme4= github.com/coreos/pkg v0.0.0-20180928190104-399ea9e2e55f h1:lBNOc5arjvs8E5mO2tbpBpLoyyu8B6e44T7hJy6potg= github.com/coreos/pkg v0.0.0-20180928190104-399ea9e2e55f/go.mod h1:E3G3o1h8I7cfcXa63jLwjI0eiQQMgzzUDFVpN/nH/eA= github.com/dancannon/gorethink v4.0.0+incompatible h1:KFV7Gha3AuqT+gr0B/eKvGhbjmUv0qGF43aKCIKVE9A= @@ -113,10 +131,14 @@ github.com/denisenkom/go-mssqldb v0.0.0-20190418034912-35416408c946 h1:xn+jBHAqN github.com/denisenkom/go-mssqldb v0.0.0-20190418034912-35416408c946/go.mod h1:zAg7JM8CkOJ43xKXIj7eRO9kmWm/TW578qo+oDO6tuM= github.com/denverdino/aliyungo v0.0.0-20170926055100-d3308649c661 h1:lrWnAyy/F72MbxIxFUzKmcMCdt9Oi8RzpAxzTNQHD7o= github.com/denverdino/aliyungo v0.0.0-20170926055100-d3308649c661/go.mod h1:dV8lFg6daOBZbT6/BDGIz6Y3WFGn8juu6G+CQ6LHtl0= +github.com/denverdino/aliyungo v0.0.0-20190410085603-611ead8a6fed h1:WtFFp2kd7j/ATD3dT5tdjyoXuynxHu6D0AJVG9Be1q4= +github.com/denverdino/aliyungo v0.0.0-20190410085603-611ead8a6fed/go.mod h1:dV8lFg6daOBZbT6/BDGIz6Y3WFGn8juu6G+CQ6LHtl0= github.com/dgrijalva/jwt-go v3.2.0+incompatible h1:7qlOGliEKZXTDg6OTjfoBKDXWrumCAMpl/TFQ4/5kLM= github.com/dgrijalva/jwt-go v3.2.0+incompatible/go.mod h1:E3ru+11k8xSBh+hMPgOLZmtrrCbhqsmaPHjLKYnJCaQ= github.com/digitalocean/godo v1.1.1 h1:v0A7yF3xmKLjjdJGIeBbINfMufcrrRhqZsxuVQMoT+U= github.com/digitalocean/godo v1.1.1/go.mod h1:h6faOIcZ8lWIwNQ+DN7b3CgX4Kwby5T+nbpNqkUIozU= +github.com/digitalocean/godo v1.13.0 h1:+0rQUl0AkTmhKDeqP8Y1Z60cJzhC/1jPI6jWpWnLUr8= +github.com/digitalocean/godo v1.13.0/go.mod h1:h6faOIcZ8lWIwNQ+DN7b3CgX4Kwby5T+nbpNqkUIozU= github.com/dimchansky/utfbom v1.1.0 h1:FcM3g+nofKgUteL8dm/UpdRXNC9KmADgTpLKsu0TRo4= github.com/dimchansky/utfbom v1.1.0/go.mod h1:rO41eb7gLfo8SF1jd9F8HplJm1Fewwi4mQvIirEdv+8= github.com/dnaeon/go-vcr v1.0.1 h1:r8L/HqC0Hje5AXMu1ooW8oyQyOFv4GxqpL0nRP7SLLY= @@ -171,6 +193,8 @@ github.com/go-ini/ini v1.42.0/go.mod h1:ByCAeIL28uOIIG0E3PJtZPDL8WnHpFKFOtgjp+3I github.com/go-kit/kit v0.8.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as= github.com/go-ldap/ldap v3.0.2+incompatible h1:kD5HQcAzlQ7yrhfn+h+MSABeAy/jAJhvIJ/QDllP44g= github.com/go-ldap/ldap v3.0.2+incompatible/go.mod h1:qfd9rJvER9Q0/D/Sqn1DfHRoBp40uXYvFoEVrNEPqRc= +github.com/go-ldap/ldap v3.0.3+incompatible h1:HTeSZO8hWMS1Rgb2Ziku6b8a7qRIZZMHjsvuZyatzwk= +github.com/go-ldap/ldap v3.0.3+incompatible/go.mod h1:qfd9rJvER9Q0/D/Sqn1DfHRoBp40uXYvFoEVrNEPqRc= github.com/go-log/log v0.1.0 h1:wudGTNsiGzrD5ZjgIkVZ517ugi2XRe9Q/xRCzwEO4/U= github.com/go-log/log v0.1.0/go.mod h1:4mBwpdRMFLiuXZDCwU2lKQFsoSCo72j3HqBK9d81N2M= github.com/go-logfmt/logfmt v0.3.0/go.mod h1:Qt1PoO58o5twSAckw1HlFXLmHsOX5/0LbT9GBnD5lWE= @@ -190,6 +214,7 @@ github.com/gogo/googleapis v1.1.0 h1:kFkMAZBNAn4j7K0GiZr8cRYzejq68VbheufiV3YuyFI github.com/gogo/googleapis v1.1.0/go.mod h1:gf4bu3Q80BeJ6H1S1vYPm8/ELATdvryBaNFGgqEef3s= github.com/gogo/googleapis v1.2.0 h1:Z0v3OJDotX9ZBpdz2V+AI7F4fITSZhVE5mg6GQppwMM= github.com/gogo/googleapis v1.2.0/go.mod h1:Njal3psf3qN6dwBtQfUmBZh2ybovJ0tlu3o/AC7HYjU= +github.com/gogo/protobuf v0.0.0-20171007142547-342cbe0a0415/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ= github.com/gogo/protobuf v1.1.1/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ= github.com/gogo/protobuf v1.2.0/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ= github.com/gogo/protobuf v1.2.1 h1:/s5zKNz0uPFCZ5hddgPdo2TK2TVrUNMn0OOX8/aZMTE= @@ -200,6 +225,7 @@ github.com/golang/groupcache v0.0.0-20160516000752-02826c3e7903/go.mod h1:cIg4er github.com/golang/groupcache v0.0.0-20190129154638-5b532d6fd5ef h1:veQD95Isof8w9/WXiA+pa3tz3fJXkt5B7QaRBrM62gk= github.com/golang/groupcache v0.0.0-20190129154638-5b532d6fd5ef/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= github.com/golang/lint v0.0.0-20180702182130-06c8688daad7/go.mod h1:tluoj9z5200jBnyusfRPU2LqT6J+DAorxEvtC7LHB+E= +github.com/golang/lint v0.0.0-20190227174305-8f45f776aaf1/go.mod h1:tluoj9z5200jBnyusfRPU2LqT6J+DAorxEvtC7LHB+E= github.com/golang/mock v1.1.1/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A= github.com/golang/mock v1.2.0/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A= github.com/golang/protobuf v1.2.0 h1:P3YflyNX/ehuJFLhxviNdFxQPkGK5cDcApsge1SqnvM= @@ -212,12 +238,16 @@ github.com/golang/snappy v0.0.1 h1:Qgr9rKW7uDUkrbSmQeiDsGa8SjGyCOGtuasMWwvp2P4= github.com/golang/snappy v0.0.1/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= github.com/google/btree v0.0.0-20180813153112-4030bb1f1f0c h1:964Od4U6p2jUkFxvCydnIczKteheJEzHRToSGK3Bnlw= github.com/google/btree v0.0.0-20180813153112-4030bb1f1f0c/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ= +github.com/google/btree v1.0.0 h1:0udJVsspx3VBr5FwtLhQQtuAsVc79tTq0ocGIPAU6qo= +github.com/google/btree v1.0.0/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ= github.com/google/go-cmp v0.2.0 h1:+dTQ8DZQJz0Mb/HjFlkptS1FeQ4cWSnN941F8aEG4SQ= github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M= github.com/google/go-github v17.0.0+incompatible h1:N0LgJ1j65A7kfXrZnUDaYCs/Sf4rEjNlfyDHW9dolSY= github.com/google/go-github v17.0.0+incompatible/go.mod h1:zLgOLi98H3fifZn+44m+umXrS52loVEgC2AApnigrVQ= github.com/google/go-querystring v0.0.0-20170111101155-53e6ce116135 h1:zLTLjkaOFEFIOxY5BWLFLwh+cL8vOBW4XJ2aqLE/Tf0= github.com/google/go-querystring v0.0.0-20170111101155-53e6ce116135/go.mod h1:odCYkC5MyYFN7vkCjXpyrEuKhc/BUO6wN/zVPAxq5ck= +github.com/google/go-querystring v1.0.0 h1:Xkwi/a1rcvNg1PPYe5vI8GbeBY/jrVuDX5ASuANWTrk= +github.com/google/go-querystring v1.0.0/go.mod h1:odCYkC5MyYFN7vkCjXpyrEuKhc/BUO6wN/zVPAxq5ck= github.com/google/gofuzz v0.0.0-20170612174753-24818f796faf h1:+RRA9JqSOZFfKrOeqr2z77+8R2RKyh8PG66dcu1V0ck= github.com/google/gofuzz v0.0.0-20170612174753-24818f796faf/go.mod h1:HP5RmnzzSNb993RKQDq4+1A4ia9nllfqcQFTQJedwGI= github.com/google/gofuzz v1.0.0 h1:A8PeW59pxE9IoFRqBp37U+mSNaQoZ46F1f0f863XSXw= @@ -238,10 +268,14 @@ github.com/gophercloud/gophercloud v0.0.0-20180828235145-f29afc2cceca h1:wobTb8S github.com/gophercloud/gophercloud v0.0.0-20180828235145-f29afc2cceca/go.mod h1:3WdhXV3rUYy9p6AUW8d94kr+HS62Y4VL9mBnFxsD8q4= github.com/gophercloud/gophercloud v0.0.0-20190307220656-fe1ba5ce12dd h1:tkA3C/XTk8iACLOlTez37pL+0iGSYkkRGKdXgJ6ZylM= github.com/gophercloud/gophercloud v0.0.0-20190307220656-fe1ba5ce12dd/go.mod h1:vxM41WHh5uqHVBMZHzuwNOHh8XEoIEcSTewFxm1c5g8= +github.com/gophercloud/gophercloud v0.0.0-20190422143055-fe6299556848 h1:3C19GoTlj2BtSe+APK65YeFikcZVacnXncVEPGuqOQU= +github.com/gophercloud/gophercloud v0.0.0-20190422143055-fe6299556848/go.mod h1:vxM41WHh5uqHVBMZHzuwNOHh8XEoIEcSTewFxm1c5g8= github.com/gopherjs/gopherjs v0.0.0-20180825215210-0210a2f0f73c h1:16eHWuMGvCjSfgRJKqIzapE78onvvTbdi1rMkU00lZw= github.com/gopherjs/gopherjs v0.0.0-20180825215210-0210a2f0f73c/go.mod h1:wJfORRmW1u3UXTncJ5qlYoELFm8eSnnEO6hX4iZ3EWY= github.com/gopherjs/gopherjs v0.0.0-20181017120253-0766667cb4d1 h1:EGx4pi6eqNxGaHF6qqu48+N2wcFQ5qg5FXgOdqsJ5d8= github.com/gopherjs/gopherjs v0.0.0-20181017120253-0766667cb4d1/go.mod h1:wJfORRmW1u3UXTncJ5qlYoELFm8eSnnEO6hX4iZ3EWY= +github.com/gopherjs/gopherjs v0.0.0-20190411002643-bd77b112433e h1:XWcjeEtTFTOVA9Fs1w7n2XBftk5ib4oZrhzWk0B+3eA= +github.com/gopherjs/gopherjs v0.0.0-20190411002643-bd77b112433e/go.mod h1:wJfORRmW1u3UXTncJ5qlYoELFm8eSnnEO6hX4iZ3EWY= github.com/gorhill/cronexpr v0.0.0-20180427100037-88b0669f7d75 h1:f0n1xnMSmBLzVfsMMvriDyA75NB/oBgILX2GcHXIQzY= github.com/gorhill/cronexpr v0.0.0-20180427100037-88b0669f7d75/go.mod h1:g2644b03hfBX9Ov0ZBDgXXens4rxSxmqFBbhvKv2yVA= github.com/gorilla/context v1.1.1/go.mod h1:kBGZzfjB9CEq2AlWe17Uuf7NDRt0dE0s8S51q0aT7Yg= @@ -288,6 +322,8 @@ github.com/hashicorp/go-memdb v1.0.1 h1:QR2h3O60I0DSvCsogh77kZUPzZBkbDSfeUjzhrK8 github.com/hashicorp/go-memdb v1.0.1/go.mod h1:I6dKdmYhZqU0RJSheVEWgTNWdVQH5QvTgIUQ0t/t32M= github.com/hashicorp/go-msgpack v0.5.3 h1:zKjpN5BK/P5lMYrLmBHdBULWbJ0XpYR+7NGzqkZzoD4= github.com/hashicorp/go-msgpack v0.5.3/go.mod h1:ahLV/dePpqEmjfWmKiqvPkv/twdG7iPBM1vqhUKIvfM= +github.com/hashicorp/go-msgpack v0.5.4 h1:SFT72YqIkOcLdWJUYcriVX7hbrZpwc/f7h8aW2NUqrA= +github.com/hashicorp/go-msgpack v0.5.4/go.mod h1:ahLV/dePpqEmjfWmKiqvPkv/twdG7iPBM1vqhUKIvfM= github.com/hashicorp/go-multierror v1.0.0 h1:iVjPR7a6H0tWELX5NxNe7bYopibicUzc7uPribsnS6o= github.com/hashicorp/go-multierror v1.0.0/go.mod h1:dHtQlpGsu+cZNNAkkCN/P3hoUDHhCYQXV3UM06sGGrk= github.com/hashicorp/go-plugin v1.0.0 h1:/gQ1sNR8/LHpoxKRQq4PmLBuacfZb4tC93e9B30o/7c= @@ -308,6 +344,8 @@ github.com/hashicorp/go-uuid v1.0.1 h1:fv1ep09latC32wFoVwnqcnKJGnMSdBanPczbHAYm1 github.com/hashicorp/go-uuid v1.0.1/go.mod h1:6SBZvOh/SIDV7/2o3Jml5SYk/TvGqwFJ/bN7x4byOro= github.com/hashicorp/go-version v1.1.0 h1:bPIoEKD27tNdebFGGxxYwcL4nepeY4j1QP23PFRGzg0= github.com/hashicorp/go-version v1.1.0/go.mod h1:fltr4n8CU8Ke44wwGCBoEymUuxUHl09ZGVZPK5anwXA= +github.com/hashicorp/go-version v1.2.0 h1:3vNe/fWF5CBgRIguda1meWhsZHy3m8gCJ5wx+dIzX/E= +github.com/hashicorp/go-version v1.2.0/go.mod h1:fltr4n8CU8Ke44wwGCBoEymUuxUHl09ZGVZPK5anwXA= github.com/hashicorp/go.net v0.0.1 h1:sNCoNyDEvN1xa+X0baata4RdcpKwcMS6DH+xwfqPgjw= github.com/hashicorp/go.net v0.0.1/go.mod h1:hjKkEWcCURg++eb33jQU7oqQcI9XDCnUzHA0oac0k90= github.com/hashicorp/golang-lru v0.5.0 h1:CL2msUPvZTLb5O648aiLNJw3hnBxN2+1Jq8rCOH9wdo= @@ -322,18 +360,22 @@ github.com/hashicorp/logutils v1.0.0 h1:dLEQVugN8vlakKOUE3ihGLTZJRB4j+M2cdTm/ORI github.com/hashicorp/logutils v1.0.0/go.mod h1:QIAnNjmIWmVIIkWDTG1z5v++HQmx9WQRO+LraFDTW64= github.com/hashicorp/mdns v1.0.0 h1:WhIgCr5a7AaVH6jPUwjtRuuE7/RDufnUvzIr48smyxs= github.com/hashicorp/mdns v1.0.0/go.mod h1:tL+uN++7HEJ6SQLQ2/p+z2pH24WQKWjBPkE0mNTz8vQ= +github.com/hashicorp/mdns v1.0.1 h1:XFSOubp8KWB+Jd2PDyaX5xUd5bhSP/+pTDZVDMzZJM8= +github.com/hashicorp/mdns v1.0.1/go.mod h1:4gW7WsVCke5TE7EPeYliwHlRUyBtfCwuFwuMg2DmyNY= github.com/hashicorp/memberlist v0.1.3 h1:EmmoJme1matNzb+hMpDuR/0sbJSUisxyqBGG676r31M= github.com/hashicorp/memberlist v0.1.3/go.mod h1:ajVTdAv/9Im8oMAAj5G31PhhMCZJV2pPBoIllUwCN7I= github.com/hashicorp/net-rpc-msgpackrpc v0.0.0-20151116020338-a14192a58a69 h1:lc3c72qGlIMDqQpQH82Y4vaglRMMFdJbziYWriR4UcE= github.com/hashicorp/net-rpc-msgpackrpc v0.0.0-20151116020338-a14192a58a69/go.mod h1:/z+jUGRBlwVpUZfjute9jWaF6/HuhjuFQuL1YXzVD1Q= -github.com/hashicorp/nomad/api v0.0.0-20190419150859-8a0df4034dc4 h1:AI83pe3zptMoaIt8dQ7qN/FeSmWmXgvhSzr3tjUJXx0= -github.com/hashicorp/nomad/api v0.0.0-20190419150859-8a0df4034dc4/go.mod h1:BDngVi1f4UA6aJq9WYTgxhfWSE1+42xshvstLU2fRGk= +github.com/hashicorp/nomad/api v0.0.0-20190422193122-09c998a4a160 h1:3a/eASHSEdXV9ghYxoZj8DJ52/9Wp22Ers70lxB/vnU= +github.com/hashicorp/nomad/api v0.0.0-20190422193122-09c998a4a160/go.mod h1:BDngVi1f4UA6aJq9WYTgxhfWSE1+42xshvstLU2fRGk= github.com/hashicorp/raft v1.0.1 h1:94uRdS11oEneUkxmXq6Vg9shNhBILh2UTb9crQjJWl0= github.com/hashicorp/raft v1.0.1/go.mod h1:DVSAWItjLjTOkVbSpWQ0j0kUADIvDaCtBxIcbNAQLkI= github.com/hashicorp/raft-boltdb v0.0.0-20171010151810-6e5ba93211ea h1:xykPFhrBAS2J0VBzVa5e80b5ZtYuNQtgXjN40qBZlD4= github.com/hashicorp/raft-boltdb v0.0.0-20171010151810-6e5ba93211ea/go.mod h1:pNv7Wc3ycL6F5oOWn+tPGo2gWD4a5X+yp/ntwdKLjRk= github.com/hashicorp/serf v0.8.2 h1:YZ7UKsJv+hKjqGVUUbtE3HNj79Eln2oQ75tniF6iPt0= github.com/hashicorp/serf v0.8.2/go.mod h1:6hOLApaqBFA1NXqRQAsxw9QxuDEvNxSQRwA/JwenrHc= +github.com/hashicorp/serf v0.8.3 h1:MWYcmct5EtKz0efYooPcL0yNkem+7kWxqXDi/UIh+8k= +github.com/hashicorp/serf v0.8.3/go.mod h1:UpNcs7fFbpKIyZaUuSW6EPiH+eZC7OuyFD+wc1oal+k= github.com/hashicorp/vault v1.1.2 h1:NDaWEwrTwjg3VKrKQmQykuiq4UqMUlbqloRvIX5fhns= github.com/hashicorp/vault v1.1.2/go.mod h1:KfSyffbKxoVyspOdlaGVjIuwLobi07qD1bAbosPMpP0= github.com/hashicorp/vault-plugin-auth-alicloud v0.5.1 h1:CldlLfMGlcXy+5CvnNsOWJjE9/C1i+Nho4ClSJe+63k= @@ -364,6 +406,8 @@ github.com/hashicorp/vault/api v1.0.1 h1:YQI4SgOlkmbEKZI8ZClo6fm9oXlBHJUlrbEtFiR github.com/hashicorp/vault/api v1.0.1/go.mod h1:AV/+M5VPDpB90arloVX0rVDUIHkONiwz5Uza9HRtpUE= github.com/hashicorp/vault/sdk v0.1.8 h1:pfF3KwA1yPlfpmcumNsFM4uo91WMasX5gTuIkItu9r0= github.com/hashicorp/vault/sdk v0.1.8/go.mod h1:tHZfc6St71twLizWNHvnnbiGFo1aq0eD2jGPLtP8kAU= +github.com/hashicorp/vault/sdk v0.1.9 h1:GkHLrt3ZU8j/ATmbLqW5P/frBCxPhCRC6nLD0kDP/yc= +github.com/hashicorp/vault/sdk v0.1.9/go.mod h1:tHZfc6St71twLizWNHvnnbiGFo1aq0eD2jGPLtP8kAU= github.com/hashicorp/vic v1.5.1-0.20190403131502-bbfe86ec9443 h1:O/pT5C1Q3mVXMyuqg7yuAWUg/jMZR1/0QTzTRdNR6Uw= github.com/hashicorp/vic v1.5.1-0.20190403131502-bbfe86ec9443/go.mod h1:bEpDU35nTu0ey1EXjwNwPjI9xErAsoOCmcMb9GKvyxo= github.com/hashicorp/yamux v0.0.0-20180604194846-3520598351bb/go.mod h1:+NfK9FKeTrX5uv1uIXGdwYDTeHna2qgaIlx54MXqjAM= @@ -379,6 +423,8 @@ github.com/influxdata/influxdb v1.7.6 h1:8mQ7A/V+3noMGCt/P9pD09ISaiz9XvgCk303UYA github.com/influxdata/influxdb v1.7.6/go.mod h1:qZna6X/4elxqT3yI9iZYdZrWWdeFOOprn86kgg4+IzY= github.com/jarcoal/httpmock v0.0.0-20180424175123-9c70cfe4a1da h1:FjHUJJ7oBW4G/9j1KzlHaXL09LyMVM9rupS39lncbXk= github.com/jarcoal/httpmock v0.0.0-20180424175123-9c70cfe4a1da/go.mod h1:ks+b9deReOc7jgqp+e7LuFiCBH6Rm5hL32cLcEAArb4= +github.com/jarcoal/httpmock v1.0.3 h1:Qgv39cyHvgEguAofjb5GomnBCm10Dq71K+k1Aq0h7/o= +github.com/jarcoal/httpmock v1.0.3/go.mod h1:ATjnClrvW/3tijVmpL/va5Z3aAyGvqU3gCT8nX0Txik= github.com/jeffchao/backoff v0.0.0-20140404060208-9d7fd7aa17f2 h1:mex1izRBCD+7WjieGgRdy7e651vD/lvB1bD9vNE/3K4= github.com/jeffchao/backoff v0.0.0-20140404060208-9d7fd7aa17f2/go.mod h1:xkfESuHriIekR+4RoV+fu91j/CfnYM29Zi2tMFw5iD4= github.com/jefferai/jsonx v1.0.0 h1:Xoz0ZbmkpBvED5W9W1B5B/zc3Oiq7oXqiW7iRV3B6EI= @@ -391,6 +437,8 @@ github.com/jonboulle/clockwork v0.1.0 h1:VKV+ZcuP6l3yW9doeqz6ziZGgcynBVQO+obU0+0 github.com/jonboulle/clockwork v0.1.0/go.mod h1:Ii8DK3G1RaLaWxj9trq07+26W01tbo22gdxWY5EU2bo= github.com/joyent/triton-go v0.0.0-20180628001255-830d2b111e62 h1:JHCT6xuyPUrbbgAPE/3dqlvUKzRHMNuTBKKUb6OeR/k= github.com/joyent/triton-go v0.0.0-20180628001255-830d2b111e62/go.mod h1:U+RSyWxWd04xTqnuOQxnai7XGS2PrPY2cfGoDKtMHjA= +github.com/joyent/triton-go v0.0.0-20190112182421-51ffac552869 h1:BvV6PYcRz0yGnWXNZrd5wginNT1GfFfPvvWpPbjfFL8= +github.com/joyent/triton-go v0.0.0-20190112182421-51ffac552869/go.mod h1:U+RSyWxWd04xTqnuOQxnai7XGS2PrPY2cfGoDKtMHjA= github.com/json-iterator/go v0.0.0-20180701071628-ab8a2e0c74be/go.mod h1:+SdeFBvtyEkXs7REEP0seUULqWtbJapLOCVDaaPEHmU= github.com/json-iterator/go v1.1.5 h1:gL2yXlmiIo4+t+y32d4WGwOjKGYcGOuyrg46vadswDE= github.com/json-iterator/go v1.1.5/go.mod h1:+SdeFBvtyEkXs7REEP0seUULqWtbJapLOCVDaaPEHmU= @@ -408,6 +456,8 @@ github.com/kisielk/errcheck v1.1.0/go.mod h1:EZBBE59ingxPouuu3KfxchcWSUPOHkagtvW github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck= github.com/konsorten/go-windows-terminal-sequences v1.0.1 h1:mweAR1A6xJ3oS2pRaGiHgQ4OO8tzTaLawm8vnODuwDk= github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= +github.com/konsorten/go-windows-terminal-sequences v1.0.2 h1:DB17ag19krx9CFsz4o3enTrPXyIXCl+2iCXH/aMAp9s= +github.com/konsorten/go-windows-terminal-sequences v1.0.2/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= github.com/kr/logfmt v0.0.0-20140226030751-b84e30acd515/go.mod h1:+0opPa2QZZtGFBFZlji/RkVcI2GknAs/DXo4wKdlNEc= github.com/kr/pretty v0.1.0 h1:L/CwN0zerZDmRFUapSPitk6f+Q3+0za1rQkzVuMiMFI= github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo= @@ -429,6 +479,8 @@ github.com/mattn/go-isatty v0.0.3/go.mod h1:M+lRXTBqGeGNdLjl/ufCoiOlB5xdOkqRJdNx github.com/mattn/go-isatty v0.0.4/go.mod h1:M+lRXTBqGeGNdLjl/ufCoiOlB5xdOkqRJdNxMWT7Zi4= github.com/mattn/go-isatty v0.0.5 h1:tHXDdz1cpzGaovsTB+TVB8q90WEokoVmfMqoVcrLUgw= github.com/mattn/go-isatty v0.0.5/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hdxcsrc5s= +github.com/mattn/go-isatty v0.0.7 h1:UvyT9uN+3r7yLEYSlJsbQGdsaB/a0DlgWP3pql6iwOc= +github.com/mattn/go-isatty v0.0.7/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hdxcsrc5s= github.com/matttproud/golang_protobuf_extensions v1.0.1 h1:4hp9jkHxhMHkqkrB3Ix0jegS5sx/RkqARlsWZ6pIwiU= github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0= github.com/mholt/caddy v0.11.5/go.mod h1:Wb1PlT4DAYSqOEd03MsqkdkXnTxA8v9pKjdpxbqM1kY= @@ -464,6 +516,8 @@ github.com/miekg/dns v1.1.4 h1:rCMZsU2ScVSYcAsOXgmC6+AKOK+6pmQTOcw03nfwYV0= github.com/miekg/dns v1.1.4/go.mod h1:W1PPwlIAgtquWBMBEV9nkV9Cazfe8ScdGz/Lj7v3Nrg= github.com/miekg/dns v1.1.6 h1:jVwb4GDwD65q/gtItR/lIZHjNH93QfeGxZUkzJcW9mc= github.com/miekg/dns v1.1.6/go.mod h1:W1PPwlIAgtquWBMBEV9nkV9Cazfe8ScdGz/Lj7v3Nrg= +github.com/miekg/dns v1.1.8 h1:1QYRAKU3lN5cRfLCkPU08hwvLJFhvjP6MqNMmQz6ZVI= +github.com/miekg/dns v1.1.8/go.mod h1:W1PPwlIAgtquWBMBEV9nkV9Cazfe8ScdGz/Lj7v3Nrg= github.com/mitchellh/cli v1.0.0 h1:iGBIsUe3+HZ/AD/Vd7DErOt5sU9fa8Uj7A2s1aggv1Y= github.com/mitchellh/cli v1.0.0/go.mod h1:hNIlj7HEI86fIcpObd7a0FcrxTWetlwJDGcceTlRvqc= github.com/mitchellh/copystructure v1.0.0 h1:Laisrj+bAB6b/yJwB5Bt3ITZhGJdqmxquMKeZ+mmkFQ= @@ -507,6 +561,8 @@ github.com/onsi/gomega v1.4.1 h1:PZSj/UFNaVp3KxrzHOcS7oyuWA7LoOY/77yCTEFu21U= github.com/onsi/gomega v1.4.1/go.mod h1:C1qb7wdrVGGVU+Z6iS04AVkA3Q65CEZX59MT0QO5uiA= github.com/onsi/gomega v1.4.3 h1:RE1xgDvH7imwFD45h+u2SgIfERHlS2yNG4DObb5BSKU= github.com/onsi/gomega v1.4.3/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1CpauHY= +github.com/onsi/gomega v1.5.0 h1:izbySO9zDPmjJ8rDjLvkA2zJHIo+HkYXHnf7eN7SSyo= +github.com/onsi/gomega v1.5.0/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1CpauHY= github.com/opencontainers/go-digest v1.0.0-rc1 h1:WzifXhOVOEOuFYOJAW6aQqW0TooG2iki3E3Ii+WN7gQ= github.com/opencontainers/go-digest v1.0.0-rc1/go.mod h1:cMLVZDEM3+U2I4VmLI6N8jQYUd2OVphdqWwCJHrFt2s= github.com/opencontainers/image-spec v1.0.1 h1:JMemWkRwHx4Zj+fVxWoMCFm/8sYGGrUVojFA6h/TRcI= @@ -516,6 +572,8 @@ github.com/opencontainers/runc v0.1.1/go.mod h1:qT5XzbpPznkRYVz/mWwUaVBUv2rmF59P github.com/opentracing-contrib/go-observer v0.0.0-20170622124052-a52f23424492/go.mod h1:Ngi6UdF0k5OKD5t5wlmGhe/EDKPoUM3BXZSSfIuJbis= github.com/opentracing/opentracing-go v1.0.2 h1:3jA2P6O1F9UOrWVpwrIo17pu01KWvNWg4X946/Y5Zwg= github.com/opentracing/opentracing-go v1.0.2/go.mod h1:UkNAQd3GIcIGf0SeVgPpRdFStlNbqXla1AfSYxPUl2o= +github.com/opentracing/opentracing-go v1.1.0 h1:pWlfV3Bxv7k65HYwkikxat0+s3pV4bsqf19k25Ur8rU= +github.com/opentracing/opentracing-go v1.1.0/go.mod h1:UkNAQd3GIcIGf0SeVgPpRdFStlNbqXla1AfSYxPUl2o= github.com/openzipkin/zipkin-go v0.1.3/go.mod h1:NtoC/o8u3JlF1lSlyPNswIbeQH9bJTmOf0Erfk+hxe8= github.com/openzipkin/zipkin-go v0.1.6/go.mod h1:QgAqvLzwWbR/WpD4A3cGpPtJrZXNIiJc5AZX7/PBEpw= github.com/openzipkin/zipkin-go-opentracing v0.3.4/go.mod h1:js2AbwmHW0YD9DwIw2JhQWmbfFi/UnWyYwdVhqbCDOE= @@ -558,15 +616,21 @@ github.com/prometheus/client_model v0.0.0-20180712105110-5c3871d89910 h1:idejC8f github.com/prometheus/client_model v0.0.0-20180712105110-5c3871d89910/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo= github.com/prometheus/client_model v0.0.0-20190115171406-56726106282f h1:BVwpUVJDADN2ufcGik7W992pyps0wZ888b/y9GXcLTU= github.com/prometheus/client_model v0.0.0-20190115171406-56726106282f/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo= +github.com/prometheus/client_model v0.0.0-20190129233127-fd36f4220a90 h1:S/YWwWx/RA8rT8tKFRuGUZhuA90OyIBpPCXkcbwU8DE= +github.com/prometheus/client_model v0.0.0-20190129233127-fd36f4220a90/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= github.com/prometheus/common v0.0.0-20181126121408-4724e9255275 h1:PnBWHBf+6L0jOqq0gIVUe6Yk0/QMZ640k6NvkxcBf+8= github.com/prometheus/common v0.0.0-20181126121408-4724e9255275/go.mod h1:daVV7qP5qjZbuso7PdcryaAu0sAZbrN9i7WWcTMWvro= github.com/prometheus/common v0.2.0 h1:kUZDBDTdBVBYBj5Tmh2NZLlF60mfjA27rM34b+cVwNU= github.com/prometheus/common v0.2.0/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y86RQel1bk4= +github.com/prometheus/common v0.3.0 h1:taZ4h8Tkxv2kNyoSctBvfXEHmBmxrwmIidZTIaHons4= +github.com/prometheus/common v0.3.0/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y86RQel1bk4= github.com/prometheus/procfs v0.0.0-20181005140218-185b4288413d/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk= github.com/prometheus/procfs v0.0.0-20181204211112-1dc9a6cbc91a h1:9a8MnZMP0X2nLJdBg+pBmGgkJlSaKC2KaQmTCk1XDtE= github.com/prometheus/procfs v0.0.0-20181204211112-1dc9a6cbc91a/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk= github.com/prometheus/procfs v0.0.0-20190117184657-bf6a532e95b1 h1:/K3IL0Z1quvmJ7X0A1AwNEK7CRkVK3YwfOU/QAL4WGg= github.com/prometheus/procfs v0.0.0-20190117184657-bf6a532e95b1/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk= +github.com/prometheus/procfs v0.0.0-20190416084830-8368d24ba045 h1:Raos9GP+3BlCBicScEQ+SjTLpYYac34fZMoeqj9McSM= +github.com/prometheus/procfs v0.0.0-20190416084830-8368d24ba045/go.mod h1:TjEm7ze935MbeOT/UhFTIMYKhuLP4wbCsTZCD3I8kEA= github.com/rcrowley/go-metrics v0.0.0-20181016184325-3113b8401b8a/go.mod h1:bCqnVzQkZxMG4s8nGwiZ5l3QUCyqpo9Y+/ZMZ9VjZe4= github.com/renier/xmlrpc v0.0.0-20170708154548-ce4a1a486c03 h1:Wdi9nwnhFNAlseAOekn6B5G/+GMtks9UKbvRU/CMM/o= github.com/renier/xmlrpc v0.0.0-20170708154548-ce4a1a486c03/go.mod h1:gRAiPF5C5Nd0eyyRdqIu9qTiFSoZzpTq727b5B8fkkU= @@ -589,10 +653,14 @@ github.com/sirupsen/logrus v1.0.6 h1:hcP1GmhGigz/O7h1WVUM5KklBp1JoNS9FggWKdj/j3s github.com/sirupsen/logrus v1.0.6/go.mod h1:pMByvHTf9Beacp5x1UXfOR9xyW/9antXMhjMPG0dEzc= github.com/sirupsen/logrus v1.2.0 h1:juTguoYk5qI21pwyTXY3B3Y5cOTH3ZUyZCg1v/mihuo= github.com/sirupsen/logrus v1.2.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPxbbu5VWo= +github.com/sirupsen/logrus v1.4.1 h1:GL2rEmy6nsikmW0r8opw9JIRScdMF5hA8cOYLH7In1k= +github.com/sirupsen/logrus v1.4.1/go.mod h1:ni0Sbl8bgC9z8RoU9G6nDWqqs/fq4eDPysMBDgk/93Q= github.com/smartystreets/assertions v0.0.0-20180820201707-7c9eb446e3cf h1:6V1qxN6Usn4jy8unvggSJz/NC790tefw8Zdy6OZS5co= github.com/smartystreets/assertions v0.0.0-20180820201707-7c9eb446e3cf/go.mod h1:OnSkiWE9lh6wB0YB77sQom3nweQdgAjqCqsofrRNTgc= github.com/smartystreets/assertions v0.0.0-20180927180507-b2de0cb4f26d h1:zE9ykElWQ6/NYmHa3jpm/yHnI4xSofP+UP6SpjHcSeM= github.com/smartystreets/assertions v0.0.0-20180927180507-b2de0cb4f26d/go.mod h1:OnSkiWE9lh6wB0YB77sQom3nweQdgAjqCqsofrRNTgc= +github.com/smartystreets/assertions v0.0.0-20190401211740-f487f9de1cd3 h1:hBSHahWMEgzwRyS6dRpxY0XyjZsHyQ61s084wo5PJe0= +github.com/smartystreets/assertions v0.0.0-20190401211740-f487f9de1cd3/go.mod h1:OnSkiWE9lh6wB0YB77sQom3nweQdgAjqCqsofrRNTgc= github.com/smartystreets/goconvey v0.0.0-20180222194500-ef6db91d284a h1:JSvGDIbmil4Ui/dDdFBExb7/cmkNjyX5F97oglmvCDo= github.com/smartystreets/goconvey v0.0.0-20180222194500-ef6db91d284a/go.mod h1:XDJAKZRPZ1CvBcN2aX5YOUTYGHki24fSF0Iv48Ibg0s= github.com/smartystreets/goconvey v0.0.0-20190306220146-200a235640ff h1:86HlEv0yBCry9syNuylzqznKXDK11p6D0DT596yNMys= @@ -601,6 +669,8 @@ github.com/smartystreets/goconvey v0.0.0-20190330032615-68dc04aab96a h1:pa8hGb/2 github.com/smartystreets/goconvey v0.0.0-20190330032615-68dc04aab96a/go.mod h1:syvi0/a8iFYH4r/RixwvyeAJjdLS9QV7WQ/tjFTllLA= github.com/softlayer/softlayer-go v0.0.0-20180806151055-260589d94c7d h1:bVQRCxQvfjNUeRqaY/uT0tFuvuFY0ulgnczuR684Xic= github.com/softlayer/softlayer-go v0.0.0-20180806151055-260589d94c7d/go.mod h1:Cw4GTlQccdRGSEf6KiMju767x0NEHE0YIVPJSaXjlsw= +github.com/softlayer/softlayer-go v0.0.0-20190415014515-aa510384a41b h1:88dDriC8WlKTaGOzhMKZVqczu9Pp/n4a3dV3SN7RyQA= +github.com/softlayer/softlayer-go v0.0.0-20190415014515-aa510384a41b/go.mod h1:Cw4GTlQccdRGSEf6KiMju767x0NEHE0YIVPJSaXjlsw= github.com/soheilhy/cmux v0.1.4 h1:0HKaf1o97UwFjHH9o5XsHUOF+tqmdA7KEzXLpiyaw0E= github.com/soheilhy/cmux v0.1.4/go.mod h1:IM3LyeVVIOuxMH7sFAkER9+bJ4dT7Ms6E4xg4kGIyLM= github.com/spf13/pflag v1.0.1/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4= @@ -613,6 +683,8 @@ github.com/streadway/amqp v0.0.0-20190404075320-75d898a42a94/go.mod h1:AZpEONHx3 github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/objx v0.1.1 h1:2vfRuCMp5sSVIDSqO8oNnWJq7mPa6KVP3iPIwFBuy8A= github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= +github.com/stretchr/objx v0.2.0 h1:Hbg2NidpLE8veEBkEZTL3CvlkUIVzuU9jDplZO54c48= +github.com/stretchr/objx v0.2.0/go.mod h1:qt09Ya8vawLte6SNmTgCsAVtYtaKzEcn8ATUoHMkEqE= github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= github.com/stretchr/testify v1.3.0 h1:TivCn/peBQ7UY8ooIcPgZFpTNSz0Q2U6UrFlUfqbe0Q= github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= @@ -628,6 +700,8 @@ github.com/ugorji/go/codec v0.0.0-20190309163734-c4a1c341dc93 h1:JnDJ9gMf6CfErto github.com/ugorji/go/codec v0.0.0-20190309163734-c4a1c341dc93/go.mod h1:iT03XoTwV7xq/+UGwKO3UbC1nNNlopQiY61beSdrtOA= github.com/vmware/govmomi v0.18.0 h1:f7QxSmP7meCtoAmiKZogvVbLInT+CZx6Px6K5rYsJZo= github.com/vmware/govmomi v0.18.0/go.mod h1:URlwyTFZX72RmxtxuaFL2Uj3fD1JTvZdx59bHWk6aFU= +github.com/vmware/govmomi v0.20.0 h1:+1IyhvoVb5JET2Wvgw9J3ZDv6CK4sxzUunpH8LhQqm4= +github.com/vmware/govmomi v0.20.0/go.mod h1:URlwyTFZX72RmxtxuaFL2Uj3fD1JTvZdx59bHWk6aFU= github.com/xiang90/probing v0.0.0-20190116061207-43a291ad63a2 h1:eY9dn8+vbi4tKz5Qo6v2eYzo7kUS51QINcR5jNpbZS8= github.com/xiang90/probing v0.0.0-20190116061207-43a291ad63a2/go.mod h1:UETIi67q53MR2AWcXfiuqkDkRtnGDLqkBTpCHuJHxtU= go.etcd.io/bbolt v1.3.2 h1:Z/90sZLPOeCy2PwprqkFa25PdkusRzaj9P8zm/KNyvk= @@ -656,6 +730,8 @@ golang.org/x/crypto v0.0.0-20190228161510-8dd112bcdc25/go.mod h1:djNgcEr1/C05ACk golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= golang.org/x/crypto v0.0.0-20190325154230-a5d413f7728c h1:Vj5n4GlwjmQteupaxJ9+0FNOmBrHfq7vN4btdGoDZgI= golang.org/x/crypto v0.0.0-20190325154230-a5d413f7728c/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= +golang.org/x/crypto v0.0.0-20190422183909-d864b10871cd h1:sMHc2rZHuzQmrbVoSpt9HgerkXPyIeCSO6k0zUMGfFk= +golang.org/x/crypto v0.0.0-20190422183909-d864b10871cd/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= golang.org/x/lint v0.0.0-20180702182130-06c8688daad7/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE= golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE= @@ -696,6 +772,8 @@ golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJ golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20190227155943-e225da77a7e6 h1:bjcUS9ztw9kFmmIxJInhon/0Is3p+EHBKNgquIzo1OI= golang.org/x/sync v0.0.0-20190227155943-e225da77a7e6/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20190423024810-112230192c58 h1:8gQV6CLnAEikrhgkHFbMAEhagSSnXWGV915qUMm9mrU= +golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sys v0.0.0-20180823144017-11551d06cbcc/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20180828065106-d99a578cf41b/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= @@ -719,6 +797,9 @@ golang.org/x/sys v0.0.0-20190322080309-f49334f85ddc h1:4gbWbmmPFp4ySWICouJl6emP0 golang.org/x/sys v0.0.0-20190322080309-f49334f85ddc/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190403152447-81d4e9dc473e h1:nFYrTHrdrAOpShe27kaFHjsqYSEQ0KWqdWLu3xuZJts= golang.org/x/sys v0.0.0-20190403152447-81d4e9dc473e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190422165155-953cdadca894 h1:Cz4ceDQGXuKRnVBDTS23GTn/pU5OE2C0WrNTOYK1Uuc= +golang.org/x/sys v0.0.0-20190422165155-953cdadca894/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/text v0.3.0 h1:g61tztE5qeGQ89tm6NTjjM9VPIm088od1l6aSorWRWg= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.1-0.20180807135948-17ff2d5776d2 h1:z99zHgr7hKfrUcX/KsoJk5FJfjTceCKIp96+biqP4To= @@ -753,6 +834,8 @@ google.golang.org/appengine v1.2.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7 google.golang.org/appengine v1.3.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= google.golang.org/appengine v1.4.0 h1:/wp5JvzpHIxhs/dumFmF7BXTf3Z+dd4uXta4kVyO508= google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= +google.golang.org/appengine v1.5.0 h1:KxkO13IPW4Lslp2bz+KHP2E3gtFlrIGNThxkZQ3g+4c= +google.golang.org/appengine v1.5.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8 h1:Nw54tB0rB7hY/N0NQvRW8DG4Yk3Q6T9cu9RcFQDu1tc= google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc= google.golang.org/genproto v0.0.0-20181219182458-5a97ab628bfb/go.mod h1:7Ep/1NZk928CDR8SjdVbjWNpdIf6nzjE3BTgJDr2Atg= @@ -760,6 +843,8 @@ google.golang.org/genproto v0.0.0-20190307195333-5fe7a883aa19 h1:Lj2SnHtxkRGJDqn google.golang.org/genproto v0.0.0-20190307195333-5fe7a883aa19/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= google.golang.org/genproto v0.0.0-20190404172233-64821d5d2107 h1:xtNn7qFlagY2mQNFHMSRPjT2RkOV4OXM7P5TVy9xATo= google.golang.org/genproto v0.0.0-20190404172233-64821d5d2107/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= +google.golang.org/genproto v0.0.0-20190418145605-e7d98fc518a7 h1:ZUjXAXmrAyrmmCPHgCA/vChHcpsX27MZ3yBonD/z1KE= +google.golang.org/genproto v0.0.0-20190418145605-e7d98fc518a7/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= google.golang.org/grpc v1.14.0/go.mod h1:yo6s7OP7yaDglbqo1J04qKzAhqBH6lvTonzMVmEdcZw= google.golang.org/grpc v1.16.0/go.mod h1:0JHn/cJsOMiMfNA9+DeHDlAU7KAAB5GDlYFpa9MZMio= google.golang.org/grpc v1.17.0/go.mod h1:6QZJwpn2B+Zp71q/5VxRsJ6NXXVCE5NRUHRo+f3cWCs= @@ -819,22 +904,33 @@ k8s.io/api v0.0.0-20181204000039-89a74a8d264d h1:HQoGWsWUe/FmRcX9BU440AAMnzBFEf+ k8s.io/api v0.0.0-20181204000039-89a74a8d264d/go.mod h1:iuAfoD4hCxJ8Onx9kaTIt30j7jUFS00AXQi6QMi99vA= k8s.io/api v0.0.0-20190409092523-d687e77c8ae9 h1:c9UEl5z8gk1DGh/g3snETZ+a52YeR9VdbX/3BQ4PHas= k8s.io/api v0.0.0-20190409092523-d687e77c8ae9/go.mod h1:FQEUn50aaytlU65qqBn/w+5ugllHwrBzKm7DzbnXdzE= +k8s.io/api v0.0.0-20190419092548-c5cad27821f6 h1:S/8tIFYavaVbM3nFX0yqkw4X0BooJqRO+TrDANFX1Uo= +k8s.io/api v0.0.0-20190419092548-c5cad27821f6/go.mod h1:B0cvvXrD9UkqARVdlFhdZB9SNL0TzJ13UB/p410skE4= k8s.io/apimachinery v0.0.0-20180821005732-488889b0007f h1:V0PkbgaYp5JqCmzLyRmssDtzim0NShXM8gYi4fcX230= k8s.io/apimachinery v0.0.0-20180821005732-488889b0007f/go.mod h1:ccL7Eh7zubPUSh9A3USN90/OzHNSVN6zxzde07TDCL0= k8s.io/apimachinery v0.0.0-20181127025237-2b1284ed4c93 h1:tT6oQBi0qwLbbZSfDkdIsb23EwaLY85hoAV4SpXfdao= k8s.io/apimachinery v0.0.0-20181127025237-2b1284ed4c93/go.mod h1:ccL7Eh7zubPUSh9A3USN90/OzHNSVN6zxzde07TDCL0= k8s.io/apimachinery v0.0.0-20190409092423-760d1845f48b h1:fVkKJL9FIpA8LSJyHVM00MP45q1WJ7+af77vcxmQP4g= k8s.io/apimachinery v0.0.0-20190409092423-760d1845f48b/go.mod h1:FW86P8YXVLsbuplGMZeb20J3jYHscrDqw4jELaFJvRU= +k8s.io/apimachinery v0.0.0-20190418212431-b3683fe6b520/go.mod h1:tXkZEnPhecLuffcJcEuO/iNpM8w0n42dM5fNrr9OVVE= +k8s.io/apimachinery v0.0.0-20190419212445-b874eabb9a4e h1:h2UL1ppdZDnaCKNvEFzbRIscOymKZznckYlXgZ3iQME= +k8s.io/apimachinery v0.0.0-20190419212445-b874eabb9a4e/go.mod h1:tXkZEnPhecLuffcJcEuO/iNpM8w0n42dM5fNrr9OVVE= k8s.io/client-go v8.0.0+incompatible h1:tTI4hRmb1DRMl4fG6Vclfdi6nTM82oIrTT7HfitmxC4= k8s.io/client-go v8.0.0+incompatible/go.mod h1:7vJpHMYJwNQCWgzmNV+VYUl1zCObLyodBc8nIyt8L5s= k8s.io/client-go v10.0.0+incompatible h1:F1IqCqw7oMBzDkqlcBymRq1450wD0eNqLE9jzUrIi34= k8s.io/client-go v10.0.0+incompatible/go.mod h1:7vJpHMYJwNQCWgzmNV+VYUl1zCObLyodBc8nIyt8L5s= +k8s.io/client-go v11.0.0+incompatible h1:LBbX2+lOwY9flffWlJM7f1Ct8V2SRNiMRDFeiwnJo9o= +k8s.io/client-go v11.0.0+incompatible/go.mod h1:7vJpHMYJwNQCWgzmNV+VYUl1zCObLyodBc8nIyt8L5s= k8s.io/klog v0.0.0-20181108234604-8139d8cb77af h1:s6rm8OxBbyDNSRkpyAd5OL4icUdBICVw9+mFADa+t5E= k8s.io/klog v0.0.0-20181108234604-8139d8cb77af/go.mod h1:Gq+BEi5rUBO/HRz0bTSXDUcqjScdoY3a9IHpCEIOOfk= k8s.io/klog v0.0.0-20190306015804-8e90cee79f82 h1:SHucoAy7lRb+w5oC/hbXyZg+zX+Wftn6hD4tGzHCVqA= k8s.io/klog v0.0.0-20190306015804-8e90cee79f82/go.mod h1:Gq+BEi5rUBO/HRz0bTSXDUcqjScdoY3a9IHpCEIOOfk= +k8s.io/klog v0.3.0 h1:0VPpR+sizsiivjIfIAQH/rl8tan6jvWkS7lU+0di3lE= +k8s.io/klog v0.3.0/go.mod h1:Gq+BEi5rUBO/HRz0bTSXDUcqjScdoY3a9IHpCEIOOfk= k8s.io/kube-openapi v0.0.0-20190228160746-b3a7cee44a30/go.mod h1:BXM9ceUBTj2QnfH2MK1odQs778ajze1RxcmP6S8RVVc= k8s.io/kube-openapi v0.0.0-20190306001800-15615b16d372/go.mod h1:BXM9ceUBTj2QnfH2MK1odQs778ajze1RxcmP6S8RVVc= +k8s.io/utils v0.0.0-20190308190857-21c4ce38f2a7 h1:8r+l4bNWjRlsFYlQJnKJ2p7s1YQPj4XyXiJVqDHRx7c= +k8s.io/utils v0.0.0-20190308190857-21c4ce38f2a7/go.mod h1:8k8uAuAQ0rXslZKaEWd0c3oVhZz7sSzSiPnVZayjIX0= layeh.com/radius v0.0.0-20190322222518-890bc1058917 h1:BDXFaFzUt5EIqe/4wrTc4AcYZWP6iC6Ult+jQWLh5eU= layeh.com/radius v0.0.0-20190322222518-890bc1058917/go.mod h1:fywZKyu//X7iRzaxLgPWsvc0L26IUpVvE/aeIL2JtIQ= sigs.k8s.io/yaml v1.1.0 h1:4A07+ZFc2wgJwo8YNlQpr1rVlgUDlxXHhPJciaPY5gs= From afd1f9f50ff72b257228b34076f4e9e2eceb3ede Mon Sep 17 00:00:00 2001 From: Patrick Moore Date: Fri, 26 Apr 2019 10:40:10 -0700 Subject: [PATCH 183/196] Update consul/watch import The watch package was moved from github.com/hashicorp/consul/watch to github.com/hashicorp/consul/api/watch to live in the API module. Per: https://github.com/hashicorp/consul/commit/6c885d383a7f303cc6c625108d3e7fc1a35d715d --- registry/consul/watcher.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/registry/consul/watcher.go b/registry/consul/watcher.go index 60957bb1..a3d894a7 100644 --- a/registry/consul/watcher.go +++ b/registry/consul/watcher.go @@ -5,7 +5,7 @@ import ( "sync" "github.com/hashicorp/consul/api" - "github.com/hashicorp/consul/watch" + "github.com/hashicorp/consul/api/watch" "github.com/micro/go-micro/registry" ) From c1c0a8fb30e02579e7a0eaf04ad444a1232ecb33 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Hunyadv=C3=A1ri=20P=C3=A9ter?= Date: Thu, 2 May 2019 17:14:41 +0200 Subject: [PATCH 184/196] send requestBody to mock function if it can handle it --- client/mock/mock.go | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/client/mock/mock.go b/client/mock/mock.go index e9022c71..27317391 100644 --- a/client/mock/mock.go +++ b/client/mock/mock.go @@ -83,7 +83,11 @@ func (m *MockClient) Call(ctx context.Context, req client.Request, rsp interface } response := r.Response if t := reflect.TypeOf(r.Response); t.Kind() == reflect.Func { - response = reflect.ValueOf(r.Response).Call([]reflect.Value{})[0].Interface() + var reqBody []reflect.Value + if t.NumIn() == 0 { + reqBody = append(reqBody, reflect.ValueOf(req.Body())) + } + response = reflect.ValueOf(r.Response).Call(reqBody)[0].Interface() } v.Set(reflect.ValueOf(response)) From 08d70c9d0a8b8e47e3ba757567737a4dc6356bb6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Hunyadv=C3=A1ri=20P=C3=A9ter?= Date: Thu, 2 May 2019 18:02:24 +0200 Subject: [PATCH 185/196] fix and add tests --- client/mock/mock.go | 2 +- client/mock/mock_test.go | 22 +++++++++++++++++++++- 2 files changed, 22 insertions(+), 2 deletions(-) diff --git a/client/mock/mock.go b/client/mock/mock.go index 27317391..f10b3f9a 100644 --- a/client/mock/mock.go +++ b/client/mock/mock.go @@ -84,7 +84,7 @@ func (m *MockClient) Call(ctx context.Context, req client.Request, rsp interface response := r.Response if t := reflect.TypeOf(r.Response); t.Kind() == reflect.Func { var reqBody []reflect.Value - if t.NumIn() == 0 { + if t.NumIn() == 1 { reqBody = append(reqBody, reflect.ValueOf(req.Body())) } response = reflect.ValueOf(r.Response).Call(reqBody)[0].Interface() diff --git a/client/mock/mock_test.go b/client/mock/mock_test.go index 5dc5de1b..4f00f8a9 100644 --- a/client/mock/mock_test.go +++ b/client/mock/mock_test.go @@ -18,12 +18,18 @@ func TestClient(t *testing.T) { {Endpoint: "Foo.Fail", Error: errors.InternalServerError("go.mock", "failed")}, {Endpoint: "Foo.Func", Response: func() string { return "string" }}, {Endpoint: "Foo.FuncStruct", Response: func() *TestResponse { return &TestResponse{Param: "aparam"} }}, + {Endpoint: "Foo.FuncWithReqBody", Response: func(req interface{}) string { + if req.(map[string]string)["foo"] == "bar" { + return "string" + } + return "wrong" + }}, } c := NewClient(Response("go.mock", response)) for _, r := range response { - req := c.NewRequest("go.mock", r.Endpoint, map[string]interface{}{"foo": "bar"}) + req := c.NewRequest("go.mock", r.Endpoint, map[string]string{"foo": "bar"}) var rsp interface{} err := c.Call(context.TODO(), req, &rsp) @@ -33,6 +39,20 @@ func TestClient(t *testing.T) { } t.Log(rsp) + if r.Endpoint == "Foo.FuncWithReqBody" { + req := c.NewRequest("go.mock", r.Endpoint, map[string]string{"foo": "wrong"}) + var rsp interface{} + + err := c.Call(context.TODO(), req, &rsp) + + if err != r.Error { + t.Fatalf("Expecter error %v got %v", r.Error, err) + } + if rsp.(string) != "wrong" { + t.Fatalf("Expecter response 'wrong' got %v", rsp) + } + t.Log(rsp) + } } } From aaf4a5c51a77e8d35bcc59b4c26094be80b98b4b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Hunyadv=C3=A1ri=20P=C3=A9ter?= Date: Thu, 2 May 2019 18:06:43 +0200 Subject: [PATCH 186/196] rename reqBody variable to request --- client/mock/mock.go | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/client/mock/mock.go b/client/mock/mock.go index f10b3f9a..6ee8f1f8 100644 --- a/client/mock/mock.go +++ b/client/mock/mock.go @@ -83,11 +83,11 @@ func (m *MockClient) Call(ctx context.Context, req client.Request, rsp interface } response := r.Response if t := reflect.TypeOf(r.Response); t.Kind() == reflect.Func { - var reqBody []reflect.Value + var request []reflect.Value if t.NumIn() == 1 { - reqBody = append(reqBody, reflect.ValueOf(req.Body())) + request = append(request, reflect.ValueOf(req.Body())) } - response = reflect.ValueOf(r.Response).Call(reqBody)[0].Interface() + response = reflect.ValueOf(r.Response).Call(request)[0].Interface() } v.Set(reflect.ValueOf(response)) From 1a151a3348f74a3f14716d562888ee6f426b8643 Mon Sep 17 00:00:00 2001 From: Vasiliy Tolstov Date: Thu, 9 May 2019 22:32:21 +0300 Subject: [PATCH 187/196] fix data races in gossip registry Signed-off-by: Vasiliy Tolstov --- registry/gossip/gossip.go | 23 +++++++++++++++-------- 1 file changed, 15 insertions(+), 8 deletions(-) diff --git a/registry/gossip/gossip.go b/registry/gossip/gossip.go index 78fb5cdb..ca654568 100644 --- a/registry/gossip/gossip.go +++ b/registry/gossip/gossip.go @@ -159,6 +159,10 @@ func configure(g *gossipRegistry, opts ...registry.Option) error { // shutdown old member g.Stop() + + // lock internals + g.Lock() + // new done chan g.done = make(chan bool) @@ -250,16 +254,12 @@ func configure(g *gossipRegistry, opts ...registry.Option) error { events: g.events, } } - // create the memberlist m, err := memberlist.Create(c) if err != nil { return err } - // set internals - g.Lock() - if len(curAddrs) > 0 { for _, addr := range curAddrs { g.members[addr] = nodeActionUnknown @@ -547,9 +547,13 @@ func (g *gossipRegistry) expiryLoop(updates *updates) { ticker := time.NewTicker(ExpiryTick) defer ticker.Stop() + g.RLock() + done := g.done + g.RUnlock() + for { select { - case <-g.done: + case <-done: return case <-ticker.C: now := uint64(time.Now().UnixNano()) @@ -576,10 +580,13 @@ func (g *gossipRegistry) expiryLoop(updates *updates) { // process member events func (g *gossipRegistry) eventLoop() { + g.RLock() + done := g.done + g.RUnlock() for { select { // return when done - case <-g.done: + case <-done: return case ev := <-g.events: // TODO: nonblocking update @@ -603,10 +610,12 @@ func (g *gossipRegistry) run() { // event loop go g.eventLoop() + g.RLock() // connect loop if g.connectRetry { go g.connectLoop() } + g.RUnlock() // process the updates for u := range g.updates { @@ -808,7 +817,6 @@ func NewRegistry(opts ...registry.Option) registry.Registry { watchers: make(map[string]chan *registry.Result), members: make(map[string]int32), } - // run the updater go g.run() @@ -816,7 +824,6 @@ func NewRegistry(opts ...registry.Option) registry.Registry { if err := configure(g, opts...); err != nil { log.Fatalf("[gossip] Error configuring registry: %v", err) } - // wait for setup <-time.After(g.interval * 2) From 58775249c5e4ecd8f6fecb5a9643e3c5d1d46fe2 Mon Sep 17 00:00:00 2001 From: Vasiliy Tolstov Date: Thu, 9 May 2019 23:01:58 +0300 Subject: [PATCH 188/196] fix race with rcache Signed-off-by: Vasiliy Tolstov --- registry/gossip/watcher.go | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/registry/gossip/watcher.go b/registry/gossip/watcher.go index a43d875e..57b35521 100644 --- a/registry/gossip/watcher.go +++ b/registry/gossip/watcher.go @@ -34,7 +34,9 @@ func (m *gossipWatcher) Next() (*registry.Result, error) { if len(m.wo.Service) > 0 && r.Service.Name != m.wo.Service { continue } - return r, nil + nr := ®istry.Result{} + *nr = *r + return nr, nil case <-m.stop: return nil, registry.ErrWatcherStopped } From a13cdfcc3408926ab5c5402be587e971511717c1 Mon Sep 17 00:00:00 2001 From: Vasiliy Tolstov Date: Mon, 13 May 2019 01:39:42 +0300 Subject: [PATCH 189/196] add RegisterCheck server option for internal health checks Signed-off-by: Vasiliy Tolstov --- server/options.go | 13 +++++++++++++ server/rpc_server.go | 28 ++++++++++++++++++++++------ server/server.go | 15 ++++++++------- 3 files changed, 43 insertions(+), 13 deletions(-) diff --git a/server/options.go b/server/options.go index 6acb5960..b0bae35a 100644 --- a/server/options.go +++ b/server/options.go @@ -25,6 +25,8 @@ type Options struct { HdlrWrappers []HandlerWrapper SubWrappers []SubscriberWrapper + // RegisterCheck runs a check function before registering the service + RegisterCheck func(context.Context) error // The register expiry time RegisterTTL time.Duration // The interval on which to register @@ -67,6 +69,10 @@ func newOptions(opt ...Option) Options { opts.DebugHandler = debug.DefaultDebugHandler } + if opts.RegisterCheck == nil { + opts.RegisterCheck = DefaultRegisterCheck + } + if len(opts.Address) == 0 { opts.Address = DefaultAddress } @@ -163,6 +169,13 @@ func Metadata(md map[string]string) Option { } } +// RegisterCheck run func before registry service +func RegisterCheck(fn func(context.Context) error) Option { + return func(o *Options) { + o.RegisterCheck = fn + } +} + // Register the service with a TTL func RegisterTTL(t time.Duration) Option { return func(o *Options) { diff --git a/server/rpc_server.go b/server/rpc_server.go index 57fd0685..4f1049c1 100644 --- a/server/rpc_server.go +++ b/server/rpc_server.go @@ -468,9 +468,14 @@ func (s *rpcServer) Start() error { log.Logf("Broker [%s] Connected to %s", config.Broker.String(), config.Broker.Address()) - // announce self to the world - if err := s.Register(); err != nil { - log.Log("Server register error: ", err) + // use RegisterCheck func before register + if err = s.opts.RegisterCheck(s.opts.Context); err != nil { + log.Logf("Server %s-%s register check error: %s", config.Name, config.Id, err) + } else { + // announce self to the world + if err = s.Register(); err != nil { + log.Log("Server %s-%s register error: %s", config.Name, config.Id, err) + } } exit := make(chan bool) @@ -518,8 +523,19 @@ func (s *rpcServer) Start() error { select { // register self on interval case <-t.C: - if err := s.Register(); err != nil { - log.Log("Server register error: ", err) + s.RLock() + registered := s.registered + s.RUnlock() + if err = s.opts.RegisterCheck(s.opts.Context); err != nil && registered { + log.Logf("Server %s-%s register check error: %s, deregister it", config.Name, config.Id, err) + // deregister self in case of error + if err := s.Deregister(); err != nil { + log.Logf("Server %s-%s deregister error: %s", config.Name, config.Id, err) + } + } else { + if err := s.Register(); err != nil { + log.Logf("Server %s-%s register error: %s", config.Name, config.Id, err) + } } // wait for exit case ch = <-s.exit: @@ -531,7 +547,7 @@ func (s *rpcServer) Start() error { // deregister self if err := s.Deregister(); err != nil { - log.Log("Server deregister error: ", err) + log.Logf("Server %s-%s deregister error: %s", config.Name, config.Id, err) } // wait for requests to finish diff --git a/server/server.go b/server/server.go index 2810f253..706e6b7e 100644 --- a/server/server.go +++ b/server/server.go @@ -8,7 +8,7 @@ import ( "syscall" "github.com/google/uuid" - "github.com/micro/go-log" + log "github.com/micro/go-log" "github.com/micro/go-micro/codec" "github.com/micro/go-micro/registry" ) @@ -115,12 +115,13 @@ type Subscriber interface { type Option func(*Options) var ( - DefaultAddress = ":0" - DefaultName = "server" - DefaultVersion = "latest" - DefaultId = uuid.New().String() - DefaultServer Server = newRpcServer() - DefaultRouter = newRpcRouter() + DefaultAddress = ":0" + DefaultName = "server" + DefaultVersion = "latest" + DefaultId = uuid.New().String() + DefaultServer Server = newRpcServer() + DefaultRouter = newRpcRouter() + DefaultRegisterCheck = func(context.Context) error { return nil } ) // DefaultOptions returns config options for the default service From 389d141c5a61283dbbd06c1270fd860c54948d34 Mon Sep 17 00:00:00 2001 From: Blair McMillan Date: Thu, 16 May 2019 12:37:48 +1000 Subject: [PATCH 190/196] Use existing consul client for watcher --- registry/consul/watcher.go | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/registry/consul/watcher.go b/registry/consul/watcher.go index a3d894a7..2fc81886 100644 --- a/registry/consul/watcher.go +++ b/registry/consul/watcher.go @@ -2,6 +2,8 @@ package consul import ( "errors" + "log" + "os" "sync" "github.com/hashicorp/consul/api" @@ -43,7 +45,7 @@ func newConsulWatcher(cr *consulRegistry, opts ...registry.WatchOption) (registr } wp.Handler = cw.handle - go wp.Run(cr.Address) + go wp.RunWithClientAndLogger(cr.Client, log.New(os.Stderr, "", log.LstdFlags)) cw.wp = wp return cw, nil @@ -208,7 +210,7 @@ func (cw *consulWatcher) handle(idx uint64, data interface{}) { }) if err == nil { wp.Handler = cw.serviceHandler - go wp.Run(cw.r.Address) + go wp.RunWithClientAndLogger(cw.r.Client, log.New(os.Stderr, "", log.LstdFlags)) cw.watchers[service] = wp cw.next <- ®istry.Result{Action: "create", Service: ®istry.Service{Name: service}} } From 92ab8141389a695a9221f21c9ddec30e7e22f3f8 Mon Sep 17 00:00:00 2001 From: Asim Aslam Date: Sun, 19 May 2019 15:38:49 +0000 Subject: [PATCH 191/196] remove sponsors --- README.md | 5 ----- README.zh-cn.md | 5 ----- 2 files changed, 10 deletions(-) diff --git a/README.md b/README.md index 0f17836c..708ae895 100644 --- a/README.md +++ b/README.md @@ -47,8 +47,3 @@ are pluggable and allows Go Micro to be runtime agnostic. You can plugin any und See the [docs](https://micro.mu/docs/go-micro.html) for detailed information on the architecture, installation and use of go-micro. -## Sponsors - -Sixt is an Enterprise Sponsor of Micro - - diff --git a/README.zh-cn.md b/README.zh-cn.md index 9e80fbaa..b5599821 100644 --- a/README.zh-cn.md +++ b/README.zh-cn.md @@ -34,8 +34,3 @@ Go Micro把分布式系统的各种细节抽象出来。下面是它的主要特 更多关于架构、安装的资料可以查看[文档](https://micro.mu/docs/go-micro_cn.html)。 -## 赞助商 - -Sixt是我们的赞助商。 - - From 0016752fc1fb2e668aacfd4d50d31696647f6c5c Mon Sep 17 00:00:00 2001 From: Asim Aslam Date: Tue, 21 May 2019 07:49:30 +0000 Subject: [PATCH 192/196] accept publisher options --- publisher.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/publisher.go b/publisher.go index ca81469c..c3bfbff3 100644 --- a/publisher.go +++ b/publisher.go @@ -12,5 +12,5 @@ type publisher struct { } func (p *publisher) Publish(ctx context.Context, msg interface{}, opts ...client.PublishOption) error { - return p.c.Publish(ctx, p.c.NewMessage(p.topic, msg)) + return p.c.Publish(ctx, p.c.NewMessage(p.topic, msg), opts...) } From 6de3d9eb245ff536f4eeaa81a39ec26b938d0847 Mon Sep 17 00:00:00 2001 From: Asim Aslam Date: Wed, 22 May 2019 16:11:06 +0000 Subject: [PATCH 193/196] Update go mod --- go.mod | 166 ++++++++++++++++++++-------------- go.sum | 275 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 374 insertions(+), 67 deletions(-) diff --git a/go.mod b/go.mod index 0ea0caa7..5a0adffb 100644 --- a/go.mod +++ b/go.mod @@ -1,72 +1,84 @@ module github.com/micro/go-micro require ( - github.com/Azure/azure-sdk-for-go v27.3.0+incompatible // indirect - github.com/Azure/go-ansiterm v0.0.0-20170929234023-d6e3b3328b78 // indirect - github.com/Azure/go-autorest v12.0.0+incompatible // indirect - github.com/DataDog/datadog-go v2.2.0+incompatible // indirect - github.com/Jeffail/gabs v1.2.0 // indirect + cloud.google.com/go v0.39.0 // indirect + contrib.go.opencensus.io/exporter/ocagent v0.5.0 // indirect + github.com/Azure/azure-sdk-for-go v29.0.0+incompatible // indirect + github.com/Azure/go-autorest v12.1.0+incompatible // indirect + github.com/DataDog/dd-trace-go v1.14.0 // indirect + github.com/DataDog/zstd v1.4.0 // indirect + github.com/Jeffail/gabs v1.4.0 // indirect github.com/Microsoft/go-winio v0.4.12 // indirect github.com/NYTimes/gziphandler v1.1.1 // indirect - github.com/Nvveen/Gotty v0.0.0-20120604004816-cd527374f1e5 // indirect + github.com/OneOfOne/xxhash v1.2.5 // indirect + github.com/PuerkitoBio/purell v1.1.1 // indirect github.com/SAP/go-hdb v0.14.1 // indirect + github.com/Shopify/sarama v1.22.1 // indirect github.com/StackExchange/wmi v0.0.0-20181212234831-e0a55b97c705 // indirect - github.com/aliyun/alibaba-cloud-sdk-go v0.0.0-20190423023524-6ff5e74c25e8 // indirect + github.com/aliyun/alibaba-cloud-sdk-go v0.0.0-20190522081930-582d16a078d0 // indirect + github.com/aliyun/aliyun-oss-go-sdk v1.9.6 // indirect github.com/araddon/gou v0.0.0-20190110011759-c797efecbb61 // indirect - github.com/asaskevich/govalidator v0.0.0-20180720115003-f9ffefc3facf // indirect - github.com/aws/aws-sdk-go v1.19.15 // indirect - github.com/beorn7/perks v1.0.0 // indirect - github.com/bitly/go-hostpool v0.0.0-20171023180738-a3a6125de932 // indirect - github.com/bmizerany/assert v0.0.0-20160611221934-b7ed37b82869 // indirect - github.com/boltdb/bolt v1.3.1 // indirect + github.com/armon/go-metrics v0.0.0-20190430140413-ec5e00d3c878 // indirect + github.com/asaskevich/govalidator v0.0.0-20190424111038-f61b66f89f4a // indirect + github.com/aws/aws-sdk-go v1.19.35 // indirect github.com/boombuler/barcode v1.0.0 // indirect - github.com/cenkalti/backoff v2.1.1+incompatible // indirect github.com/chrismalek/oktasdk-go v0.0.0-20181212195951-3430665dfaa0 // indirect - github.com/circonus-labs/circonus-gometrics v2.3.1+incompatible // indirect - github.com/circonus-labs/circonusllhist v0.1.3 // indirect - github.com/containerd/continuity v0.0.0-20181203112020-004b46473808 // indirect + github.com/containerd/continuity v0.0.0-20190426062206-aaeac12a7ffc // indirect github.com/coredns/coredns v1.5.0 // indirect - github.com/coreos/etcd v3.3.12+incompatible // indirect + github.com/coreos/etcd v3.3.13+incompatible // indirect github.com/coreos/go-semver v0.3.0 // indirect github.com/coreos/go-systemd v0.0.0-20190321100706-95778dfbb74e // indirect github.com/dancannon/gorethink v4.0.0+incompatible // indirect - github.com/denisenkom/go-mssqldb v0.0.0-20190418034912-35416408c946 // indirect + github.com/denisenkom/go-mssqldb v0.0.0-20190515213511-eb9f6a1743f3 // indirect github.com/denverdino/aliyungo v0.0.0-20190410085603-611ead8a6fed // indirect - github.com/digitalocean/godo v1.13.0 // indirect + github.com/dgryski/go-sip13 v0.0.0-20190329191031-25c5027a8c7b // indirect + github.com/digitalocean/godo v1.15.0 // indirect github.com/dnaeon/go-vcr v1.0.1 // indirect + github.com/dnstap/golang-dnstap v0.0.0-20190521061535-1a0dab85b926 // indirect github.com/docker/go-connections v0.4.0 // indirect - github.com/duosecurity/duo_api_golang v0.0.0-20190308151101-6c680f768e74 // indirect + github.com/docker/go-units v0.4.0 // indirect + github.com/docker/spdystream v0.0.0-20181023171402-6480d4af844c // indirect github.com/elazarl/go-bindata-assetfs v1.0.0 // indirect - github.com/envoyproxy/go-control-plane v0.7.1 // indirect - github.com/envoyproxy/protoc-gen-validate v0.0.14 // indirect + github.com/elazarl/goproxy v0.0.0-20190421051319-9d40249d3c2f // indirect + github.com/emicklei/go-restful v2.9.5+incompatible // indirect + github.com/envoyproxy/go-control-plane v0.8.0 // indirect + github.com/evanphx/json-patch v4.2.0+incompatible // indirect + github.com/farsightsec/golang-framestream v0.0.0-20190425193708-fa4b164d59b8 // indirect github.com/fullsailor/pkcs7 v0.0.0-20190404230743-d7302db945fa // indirect + github.com/gammazero/workerpool v0.0.0-20190521015540-3b91a70bc0a1 // indirect github.com/garyburd/redigo v1.6.0 // indirect github.com/go-ldap/ldap v3.0.3+incompatible // indirect github.com/go-log/log v0.1.0 github.com/go-ole/go-ole v1.2.4 // indirect + github.com/go-openapi/jsonpointer v0.19.0 // indirect + github.com/go-openapi/jsonreference v0.19.0 // indirect + github.com/go-openapi/spec v0.19.0 // indirect + github.com/go-openapi/swag v0.19.0 // indirect github.com/go-sql-driver/mysql v1.4.1 // indirect - github.com/go-stomp/stomp v2.0.2+incompatible // indirect - github.com/gocql/gocql v0.0.0-20190418090649-59a610c947c5 // indirect + github.com/go-stomp/stomp v2.0.3+incompatible // indirect + github.com/gocql/gocql v0.0.0-20190423091413-b99afaf3b163 // indirect github.com/gogo/googleapis v1.2.0 // indirect + github.com/golang/mock v1.3.1 // indirect github.com/golang/protobuf v1.3.1 github.com/google/btree v1.0.0 // indirect - github.com/google/go-github v17.0.0+incompatible // indirect - github.com/google/go-querystring v1.0.0 // indirect github.com/google/gofuzz v1.0.0 // indirect + github.com/google/pprof v0.0.0-20190515194954-54271f7e092f // indirect github.com/google/uuid v1.1.1 - github.com/gophercloud/gophercloud v0.0.0-20190422143055-fe6299556848 // indirect - github.com/gopherjs/gopherjs v0.0.0-20190411002643-bd77b112433e // indirect - github.com/gotestyourself/gotestyourself v2.2.0+incompatible // indirect - github.com/hashicorp/consul v1.4.4 - github.com/hashicorp/go-discover v0.0.0-20190408185603-6ccdb67f9b84 // indirect - github.com/hashicorp/go-memdb v1.0.1 // indirect - github.com/hashicorp/go-msgpack v0.5.4 // indirect + github.com/gophercloud/gophercloud v0.0.0-20190520235722-e87e5f90e7e6 // indirect + github.com/gopherjs/gopherjs v0.0.0-20190430165422-3e4dfb77656c // indirect + github.com/gorilla/mux v1.7.2 // indirect + github.com/grpc-ecosystem/grpc-gateway v1.9.0 // indirect + github.com/hashicorp/consul v1.5.0 + github.com/hashicorp/consul/api v1.1.0 + github.com/hashicorp/go-checkpoint v0.5.0 // indirect + github.com/hashicorp/go-discover v0.0.0-20190522154730-8aba54d36e17 // indirect + github.com/hashicorp/go-hclog v0.9.2 // indirect + github.com/hashicorp/go-memdb v1.0.2 // indirect + github.com/hashicorp/go-msgpack v0.5.5 // indirect github.com/hashicorp/go-version v1.2.0 // indirect github.com/hashicorp/hil v0.0.0-20190212132231-97b3a9cdfa93 // indirect - github.com/hashicorp/mdns v1.0.1 // indirect - github.com/hashicorp/memberlist v0.1.3 - github.com/hashicorp/net-rpc-msgpackrpc v0.0.0-20151116020338-a14192a58a69 // indirect - github.com/hashicorp/nomad/api v0.0.0-20190422193122-09c998a4a160 // indirect + github.com/hashicorp/memberlist v0.1.4 + github.com/hashicorp/nomad/api v0.0.0-20190522160243-df84e07c1a46 // indirect github.com/hashicorp/raft v1.0.1 // indirect github.com/hashicorp/raft-boltdb v0.0.0-20171010151810-6e5ba93211ea // indirect github.com/hashicorp/serf v0.8.3 // indirect @@ -82,63 +94,83 @@ require ( github.com/hashicorp/vault-plugin-secrets-gcp v0.5.2 // indirect github.com/hashicorp/vault-plugin-secrets-gcpkms v0.5.1 // indirect github.com/hashicorp/vault-plugin-secrets-kv v0.5.1 // indirect - github.com/hashicorp/vault/sdk v0.1.9 // indirect + github.com/hashicorp/vault/api v1.0.2 // indirect + github.com/hashicorp/vault/sdk v0.1.11 // indirect github.com/influxdata/influxdb v1.7.6 // indirect - github.com/jarcoal/httpmock v1.0.3 // indirect + github.com/jarcoal/httpmock v1.0.4 // indirect github.com/jefferai/jsonx v1.0.0 // indirect github.com/joyent/triton-go v0.0.0-20190112182421-51ffac552869 // indirect github.com/keybase/go-crypto v0.0.0-20190416182011-b785b22cc757 // indirect + github.com/kisielk/errcheck v1.2.0 // indirect + github.com/klauspost/cpuid v1.2.1 // indirect github.com/konsorten/go-windows-terminal-sequences v1.0.2 // indirect - github.com/lib/pq v1.1.0 // indirect + github.com/kr/pty v1.1.4 // indirect + github.com/kylelemons/godebug v1.1.0 // indirect + github.com/lib/pq v1.1.1 // indirect + github.com/linode/linodego v0.8.1 // indirect + github.com/lucas-clemente/quic-go v0.11.1 // indirect + github.com/lyft/protoc-gen-validate v0.0.14 // indirect + github.com/mailru/easyjson v0.0.0-20190403194419-1ea4449da983 // indirect github.com/mattbaird/elastigo v0.0.0-20170123220020-2fe47fd29e4b // indirect - github.com/mattn/go-isatty v0.0.7 // indirect + github.com/mattn/go-isatty v0.0.8 // indirect + github.com/mholt/caddy v1.0.0 // indirect + github.com/mholt/certmagic v0.5.1 // indirect github.com/michaelklishin/rabbit-hole v1.5.0 // indirect github.com/micro/cli v0.1.0 github.com/micro/go-log v0.1.0 github.com/micro/go-rcache v0.3.0 github.com/micro/mdns v0.1.0 github.com/micro/util v0.2.0 - github.com/miekg/dns v1.1.8 // indirect + github.com/miekg/dns v1.1.12 // indirect github.com/mitchellh/hashstructure v1.0.0 - github.com/onsi/gomega v1.5.0 // indirect - github.com/opencontainers/go-digest v1.0.0-rc1 // indirect - github.com/opencontainers/image-spec v1.0.1 // indirect - github.com/opencontainers/runc v0.1.1 // indirect + github.com/mitchellh/pointerstructure v0.0.0-20190430161007-f252a8fd71c8 // indirect + github.com/munnerz/goautoneg v0.0.0-20190414153302-2ae31c8b6b30 // indirect github.com/opentracing/opentracing-go v1.1.0 // indirect + github.com/openzipkin/zipkin-go-opentracing v0.3.5 // indirect github.com/ory-am/common v0.4.0 // indirect - github.com/ory/dockertest v3.3.4+incompatible // indirect github.com/pborman/uuid v1.2.0 // indirect github.com/pkg/errors v0.8.1 github.com/pquerna/otp v1.1.0 // indirect - github.com/prometheus/client_model v0.0.0-20190129233127-fd36f4220a90 // indirect - github.com/prometheus/common v0.3.0 // indirect - github.com/prometheus/procfs v0.0.0-20190416084830-8368d24ba045 // indirect + github.com/prometheus/client_golang v0.9.3 // indirect + github.com/prometheus/common v0.4.1 // indirect + github.com/prometheus/procfs v0.0.0-20190522114515-bc1a522cf7b1 // indirect + github.com/prometheus/tsdb v0.8.0 // indirect + github.com/rogpeppe/fastuuid v1.1.0 // indirect + github.com/russross/blackfriday v2.0.0+incompatible // indirect github.com/samuel/go-zookeeper v0.0.0-20180130194729-c4fab1ac1bec // indirect github.com/shirou/gopsutil v2.18.12+incompatible // indirect - github.com/shirou/w32 v0.0.0-20160930032740-bb4de0191aa4 // indirect - github.com/sirupsen/logrus v1.4.1 // indirect + github.com/sirupsen/logrus v1.4.2 // indirect github.com/smartystreets/assertions v0.0.0-20190401211740-f487f9de1cd3 // indirect - github.com/softlayer/softlayer-go v0.0.0-20190415014515-aa510384a41b // indirect + github.com/softlayer/softlayer-go v0.0.0-20190508182157-7c592eb2559c // indirect + github.com/spaolacci/murmur3 v1.1.0 // indirect github.com/streadway/amqp v0.0.0-20190404075320-75d898a42a94 // indirect github.com/stretchr/objx v0.2.0 // indirect - github.com/tv42/httpunix v0.0.0-20150427012821-b75d8614f926 // indirect - github.com/vmware/govmomi v0.20.0 // indirect - golang.org/x/crypto v0.0.0-20190422183909-d864b10871cd // indirect - golang.org/x/net v0.0.0-20190420063019-afa5a82059c6 - golang.org/x/sync v0.0.0-20190423024810-112230192c58 // indirect - golang.org/x/sys v0.0.0-20190422165155-953cdadca894 // indirect - google.golang.org/appengine v1.5.0 // indirect - google.golang.org/genproto v0.0.0-20190418145605-e7d98fc518a7 // indirect - google.golang.org/grpc v1.20.1 // indirect + github.com/ugorji/go v1.1.4 // indirect + github.com/vmware/govmomi v0.20.1 // indirect + go.uber.org/atomic v1.4.0 // indirect + go.uber.org/zap v1.10.0 // indirect + golang.org/x/crypto v0.0.0-20190513172903-22d7a77e9e5f // indirect + golang.org/x/exp v0.0.0-20190510132918-efd6b22b2522 // indirect + golang.org/x/image v0.0.0-20190516052701-61b8692d9a5c // indirect + golang.org/x/lint v0.0.0-20190409202823-959b441ac422 // indirect + golang.org/x/mobile v0.0.0-20190509164839-32b2708ab171 // indirect + golang.org/x/net v0.0.0-20190522155817-f3200d17e092 + golang.org/x/oauth2 v0.0.0-20190517181255-950ef44c6e07 // indirect + golang.org/x/sys v0.0.0-20190522044717-8097e1b27ff5 // indirect + golang.org/x/tools v0.0.0-20190521203540-521d6ed310dd // indirect + google.golang.org/appengine v1.6.0 // indirect + google.golang.org/genproto v0.0.0-20190516172635-bb713bdc0e52 // indirect gopkg.in/gorethink/gorethink.v4 v4.1.0 // indirect gopkg.in/mgo.v2 v2.0.0-20180705113604-9856a29383ce // indirect gopkg.in/ory-am/dockertest.v2 v2.2.3 // indirect - gotest.tools v2.2.0+incompatible // indirect - k8s.io/api v0.0.0-20190419092548-c5cad27821f6 // indirect - k8s.io/apimachinery v0.0.0-20190419212445-b874eabb9a4e // indirect + honnef.co/go/tools v0.0.0-20190522022531-bad1bd262ba8 // indirect + k8s.io/api v0.0.0-20190515023547-db5a9d1c40eb // indirect k8s.io/client-go v11.0.0+incompatible // indirect - k8s.io/utils v0.0.0-20190308190857-21c4ce38f2a7 // indirect + k8s.io/gengo v0.0.0-20190327210449-e17681d19d3a // indirect + k8s.io/kube-openapi v0.0.0-20190510232812-a01b7d5d6c22 // indirect + k8s.io/utils v0.0.0-20190520173318-324c5df7d3f0 // indirect layeh.com/radius v0.0.0-20190322222518-890bc1058917 // indirect + sigs.k8s.io/structured-merge-diff v0.0.0-20190521201008-1c46bef2e9c8 // indirect ) replace github.com/golang/lint => github.com/golang/lint v0.0.0-20190227174305-8f45f776aaf1 diff --git a/go.sum b/go.sum index a60eadbc..19443b70 100644 --- a/go.sum +++ b/go.sum @@ -5,8 +5,10 @@ cloud.google.com/go v0.28.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMT cloud.google.com/go v0.34.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= cloud.google.com/go v0.37.4 h1:glPeL3BQJsbF6aIIYfZizMwc5LTYz250bDMjttbBGAU= cloud.google.com/go v0.37.4/go.mod h1:NHPJ89PdicEuT9hdPXMROBD91xc5uRDxsMtSB16k7hw= +cloud.google.com/go v0.39.0/go.mod h1:rVLT6fkc8chs9sfPtFc1SBH6em7n+ZoXaG+87tDISts= contrib.go.opencensus.io/exporter/ocagent v0.4.12 h1:jGFvw3l57ViIVEPKKEUXPcLYIXJmQxLUh6ey1eJhwyc= contrib.go.opencensus.io/exporter/ocagent v0.4.12/go.mod h1:450APlNTSR6FrvC3CTRqYosuDstRB9un7SOx2k/9ckA= +contrib.go.opencensus.io/exporter/ocagent v0.5.0/go.mod h1:ImxhfLRpxoYiSq891pBrLVhN+qmP8BTVvdH2YLs7Gl0= git.apache.org/thrift.git v0.12.0/go.mod h1:fPE2ZNJGynbRyZ4dJvy6G277gSllfV2HJqblrnkyeyg= github.com/Azure/azure-sdk-for-go v16.0.0+incompatible h1:gr1qKY/Ll72VjFTZmaBwRK1yQHAxCnV25ekOKroc9ws= github.com/Azure/azure-sdk-for-go v16.0.0+incompatible/go.mod h1:9XXNKU+eRnpl9moKnB4QOLf1HestfXbmab5FXxiDBjc= @@ -14,34 +16,58 @@ github.com/Azure/azure-sdk-for-go v27.1.0+incompatible h1:/aGULErVaJsMdtew1p9OhE github.com/Azure/azure-sdk-for-go v27.1.0+incompatible/go.mod h1:9XXNKU+eRnpl9moKnB4QOLf1HestfXbmab5FXxiDBjc= github.com/Azure/azure-sdk-for-go v27.3.0+incompatible h1:i+ROfG3CsZUPoVAnhK06T3R6PmBzKB9ds+lHBpN7Mzo= github.com/Azure/azure-sdk-for-go v27.3.0+incompatible/go.mod h1:9XXNKU+eRnpl9moKnB4QOLf1HestfXbmab5FXxiDBjc= +github.com/Azure/azure-sdk-for-go v29.0.0+incompatible/go.mod h1:9XXNKU+eRnpl9moKnB4QOLf1HestfXbmab5FXxiDBjc= github.com/Azure/go-ansiterm v0.0.0-20170929234023-d6e3b3328b78 h1:w+iIsaOQNcT7OZ575w+acHgRric5iCyQh+xv+KJ4HB8= github.com/Azure/go-ansiterm v0.0.0-20170929234023-d6e3b3328b78/go.mod h1:LmzpDX56iTiv29bbRTIsUNlaFfuhWRQBWjQdVyAevI8= github.com/Azure/go-autorest v10.7.0+incompatible h1:dB+dKSLGdJLEhU/FoZTSNSPMZuE5H4M5p5zgSct7qwM= github.com/Azure/go-autorest v10.7.0+incompatible/go.mod h1:r+4oMnoxhatjLLJ6zxSWATqVooLgysK6ZNox3g/xq24= +github.com/Azure/go-autorest v10.15.3+incompatible/go.mod h1:r+4oMnoxhatjLLJ6zxSWATqVooLgysK6ZNox3g/xq24= github.com/Azure/go-autorest v11.7.1+incompatible h1:M2YZIajBBVekV86x0rr1443Lc1F/Ylxb9w+5EtSyX3Q= github.com/Azure/go-autorest v11.7.1+incompatible/go.mod h1:r+4oMnoxhatjLLJ6zxSWATqVooLgysK6ZNox3g/xq24= github.com/Azure/go-autorest v12.0.0+incompatible h1:N+VqClcomLGD/sHb3smbSYYtNMgKpVV3Cd5r5i8z6bQ= github.com/Azure/go-autorest v12.0.0+incompatible/go.mod h1:r+4oMnoxhatjLLJ6zxSWATqVooLgysK6ZNox3g/xq24= +github.com/Azure/go-autorest v12.1.0+incompatible/go.mod h1:r+4oMnoxhatjLLJ6zxSWATqVooLgysK6ZNox3g/xq24= github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= +github.com/BurntSushi/xgb v0.0.0-20160522181843-27f122750802/go.mod h1:IVnqGOEym/WlBOVXweHU+Q+/VP0lqqI8lqeDx9IjBqo= +github.com/DataDog/datadog-go v0.0.0-20160329135253-cc2f4770f4d6/go.mod h1:LButxg5PwREeZtORoXG3tL4fMGNddJ+vMq1mwgfaqoQ= github.com/DataDog/datadog-go v2.2.0+incompatible h1:V5BKkxACZLjzHjSgBbr2gvLA2Ae49yhc6CSY7MLy5k4= github.com/DataDog/datadog-go v2.2.0+incompatible/go.mod h1:LButxg5PwREeZtORoXG3tL4fMGNddJ+vMq1mwgfaqoQ= github.com/DataDog/dd-trace-go v0.6.1/go.mod h1:SmQTTcC37XMyEm75HV0AWiZIYxDiaNhRi49zorIpW+o= +github.com/DataDog/dd-trace-go v1.14.0/go.mod h1:SmQTTcC37XMyEm75HV0AWiZIYxDiaNhRi49zorIpW+o= github.com/DataDog/zstd v1.3.5/go.mod h1:1jcaCB/ufaK+sKp1NBhlGmpz41jOoPQ35bpF36t7BBo= +github.com/DataDog/zstd v1.3.6-0.20190409195224-796139022798/go.mod h1:1jcaCB/ufaK+sKp1NBhlGmpz41jOoPQ35bpF36t7BBo= +github.com/DataDog/zstd v1.4.0/go.mod h1:1jcaCB/ufaK+sKp1NBhlGmpz41jOoPQ35bpF36t7BBo= +github.com/Jeffail/gabs v1.1.0/go.mod h1:6xMvQMK4k33lb7GUUpaAPh6nKMmemQeg5d4gn7/bOXc= github.com/Jeffail/gabs v1.1.1 h1:V0uzR08Hj22EX8+8QMhyI9sX2hwRu+/RJhJUmnwda/E= github.com/Jeffail/gabs v1.1.1/go.mod h1:6xMvQMK4k33lb7GUUpaAPh6nKMmemQeg5d4gn7/bOXc= github.com/Jeffail/gabs v1.2.0 h1:uFhoIVTtsX7hV2RxNgWad8gMU+8OJdzFbOathJdhD3o= github.com/Jeffail/gabs v1.2.0/go.mod h1:6xMvQMK4k33lb7GUUpaAPh6nKMmemQeg5d4gn7/bOXc= +github.com/Jeffail/gabs v1.4.0/go.mod h1:6xMvQMK4k33lb7GUUpaAPh6nKMmemQeg5d4gn7/bOXc= +github.com/Microsoft/go-winio v0.4.3/go.mod h1:VhR8bwka0BXejwEJY73c50VrPtXAaKcyvVC4A4RozmA= github.com/Microsoft/go-winio v0.4.12 h1:xAfWHN1IrQ0NJ9TBC0KBZoqLjzDTr1ML+4MywiUOryc= github.com/Microsoft/go-winio v0.4.12/go.mod h1:VhR8bwka0BXejwEJY73c50VrPtXAaKcyvVC4A4RozmA= +github.com/NYTimes/gziphandler v0.0.0-20170623195520-56545f4a5d46/go.mod h1:3wb06e3pkSAbeQ52E9H9iFoQsEEwGN64994WTCIhntQ= +github.com/NYTimes/gziphandler v1.0.1/go.mod h1:3wb06e3pkSAbeQ52E9H9iFoQsEEwGN64994WTCIhntQ= github.com/NYTimes/gziphandler v1.1.1 h1:ZUDjpQae29j0ryrS0u/B8HZfJBtBQHjqw2rQ2cqUQ3I= github.com/NYTimes/gziphandler v1.1.1/go.mod h1:n/CVRwUEOgIxrgPvAQhUUr9oeUtvrhMomdKFjzJNB0c= github.com/Nvveen/Gotty v0.0.0-20120604004816-cd527374f1e5 h1:TngWCqHvy9oXAN6lEVMRuU21PR1EtLVZJmdB18Gu3Rw= github.com/Nvveen/Gotty v0.0.0-20120604004816-cd527374f1e5/go.mod h1:lmUJ/7eu/Q8D7ML55dXQrVaamCz2vxCfdQBasLZfHKk= +github.com/OneOfOne/xxhash v1.2.2/go.mod h1:HSdplMjZKSmBqAxg5vPj2TmRDmfkzw+cTzAElWljhcU= +github.com/OneOfOne/xxhash v1.2.5/go.mod h1:eZbhyaAYD41SGSSsnmcpxVoRiQ/MPUTjUdIIOT9Um7Q= +github.com/PuerkitoBio/purell v1.0.0/go.mod h1:c11w/QuzBsJSee3cPx9rAFu61PvFxuPbtSwDGJws/X0= +github.com/PuerkitoBio/purell v1.1.0/go.mod h1:c11w/QuzBsJSee3cPx9rAFu61PvFxuPbtSwDGJws/X0= +github.com/PuerkitoBio/purell v1.1.1/go.mod h1:c11w/QuzBsJSee3cPx9rAFu61PvFxuPbtSwDGJws/X0= +github.com/PuerkitoBio/urlesc v0.0.0-20160726150825-5bd2802263f2/go.mod h1:uGdkoq3SwY9Y+13GIhn11/XLaGBb4BfwItxLd5jeuXE= +github.com/PuerkitoBio/urlesc v0.0.0-20170810143723-de5bf2ad4578/go.mod h1:uGdkoq3SwY9Y+13GIhn11/XLaGBb4BfwItxLd5jeuXE= +github.com/SAP/go-hdb v0.12.0/go.mod h1:etBT+FAi1t5k3K3tf5vQTnosgYmhDkRi8jEnQqCnxF0= github.com/SAP/go-hdb v0.14.1 h1:hkw4ozGZ/i4eak7ZuGkY5e0hxiXFdNUBNhr4AvZVNFE= github.com/SAP/go-hdb v0.14.1/go.mod h1:7fdQLVC2lER3urZLjZCm0AuMQfApof92n3aylBPEkMo= +github.com/SermoDigital/jose v0.0.0-20180104203859-803625baeddc/go.mod h1:ARgCUhI1MHQH+ONky/PAtmVHQrP5JlGY0F3poXOp/fA= github.com/Shopify/sarama v1.19.0/go.mod h1:FVkBWblsNy7DGZRfXLU0O9RCGt5g3g3yEuWXgklEdEo= github.com/Shopify/sarama v1.21.0/go.mod h1:yuqtN/pe8cXRWG5zPaO7hCfNJp5MwmkoJEoLjkm5tCQ= +github.com/Shopify/sarama v1.22.1/go.mod h1:FRzlvRpMFO/639zY1SDxUxkqH97Y0ndM5CbGj6oG3As= github.com/Shopify/toxiproxy v2.1.4+incompatible/go.mod h1:OXgGpZ6Cli1/URJOF1DMxUHB2q5Ap20/P/eIdh4G0pI= +github.com/StackExchange/wmi v0.0.0-20180116203802-5d049714c4a6/go.mod h1:3eOhrUMpNV+6aFIbp5/iudMxNCF27Vw2OZgy4xEx0Fg= github.com/StackExchange/wmi v0.0.0-20181212234831-e0a55b97c705 h1:UUppSQnhf4Yc6xGxSkoQpPhb7RVzuv5Nb1mwJ5VId9s= github.com/StackExchange/wmi v0.0.0-20181212234831-e0a55b97c705/go.mod h1:3eOhrUMpNV+6aFIbp5/iudMxNCF27Vw2OZgy4xEx0Fg= github.com/abdullin/seq v0.0.0-20160510034733-d5467c17e7af h1:DBNMBMuMiWYu0b+8KMJuWmfCkcxl09JwdlqwDZZ6U14= @@ -52,6 +78,9 @@ github.com/aliyun/alibaba-cloud-sdk-go v0.0.0-20190412020505-60e2075261b6 h1:5Rw github.com/aliyun/alibaba-cloud-sdk-go v0.0.0-20190412020505-60e2075261b6/go.mod h1:T9M45xf79ahXVelWoOBmH0y4aC1t5kXO5BxwyakgIGA= github.com/aliyun/alibaba-cloud-sdk-go v0.0.0-20190423023524-6ff5e74c25e8 h1:n3yJ9NAD5JfC5aTyO6yoJm5wbQ8LozPHrj2qJnAAHlI= github.com/aliyun/alibaba-cloud-sdk-go v0.0.0-20190423023524-6ff5e74c25e8/go.mod h1:T9M45xf79ahXVelWoOBmH0y4aC1t5kXO5BxwyakgIGA= +github.com/aliyun/alibaba-cloud-sdk-go v0.0.0-20190522081930-582d16a078d0/go.mod h1:0nPXeXAsIm3YH7imFCamfa0u+PueDefehKCQ8dicxmc= +github.com/aliyun/aliyun-oss-go-sdk v0.0.0-20190307165228-86c17b95fcd5/go.mod h1:T/Aws4fEfogEE9v+HPhhw+CntffsBHJ8nXQCwKr0/g8= +github.com/aliyun/aliyun-oss-go-sdk v1.9.6/go.mod h1:T/Aws4fEfogEE9v+HPhhw+CntffsBHJ8nXQCwKr0/g8= github.com/apache/thrift v0.12.0/go.mod h1:cp2SuWMxlEZw2r+iP2GNCdIi4C1qmUzdZFSVb+bacwQ= github.com/araddon/gou v0.0.0-20190110011759-c797efecbb61 h1:Xz25cuW4REGC5W5UtpMU3QItMIImag615HiQcRbxqKQ= github.com/araddon/gou v0.0.0-20190110011759-c797efecbb61/go.mod h1:ikc1XA58M+Rx7SEbf0bLJCfBkwayZ8T5jBo5FXK8Uz8= @@ -60,22 +89,30 @@ github.com/armon/circbuf v0.0.0-20190214190532-5111143e8da2 h1:7Ip0wMmLHLRJdrloD github.com/armon/circbuf v0.0.0-20190214190532-5111143e8da2/go.mod h1:3U/XgcO3hCbHZ8TKRvWD2dDTCfh9M9ya+I9JpbB7O8o= github.com/armon/go-metrics v0.0.0-20180917152333-f0300d1749da h1:8GUt8eRujhVEGZFFEjBj46YV4rDjvGrNxb0KMWYkL2I= github.com/armon/go-metrics v0.0.0-20180917152333-f0300d1749da/go.mod h1:Q73ZrmVTwzkszR9V5SSuryQ31EELlFMUz1kKyl939pY= +github.com/armon/go-metrics v0.0.0-20190430140413-ec5e00d3c878 h1:EFSB7Zo9Eg91v7MJPVsifUysc/wPdN+NOnVe6bWbdBM= +github.com/armon/go-metrics v0.0.0-20190430140413-ec5e00d3c878/go.mod h1:3AMJUQhVx52RsWOnlkpikZr01T/yAVN2gn0861vByNg= github.com/armon/go-radix v0.0.0-20180808171621-7fddfc383310/go.mod h1:ufUuZ+zHj4x4TnLV4JWEpy2hxWSpsRywHrMgIH9cCH8= github.com/armon/go-radix v1.0.0 h1:F4z6KzEeeQIMeLFa97iZU6vupzoecKdU5TX24SNppXI= github.com/armon/go-radix v1.0.0/go.mod h1:ufUuZ+zHj4x4TnLV4JWEpy2hxWSpsRywHrMgIH9cCH8= +github.com/asaskevich/govalidator v0.0.0-20180319081651-7d2e70ef918f/go.mod h1:lB+ZfQJz7igIIfQNfa7Ml4HSf2uFQQRzpGGRXenZAgY= github.com/asaskevich/govalidator v0.0.0-20180720115003-f9ffefc3facf h1:eg0MeVzsP1G42dRafH3vf+al2vQIJU0YHX+1Tw87oco= github.com/asaskevich/govalidator v0.0.0-20180720115003-f9ffefc3facf/go.mod h1:lB+ZfQJz7igIIfQNfa7Ml4HSf2uFQQRzpGGRXenZAgY= +github.com/asaskevich/govalidator v0.0.0-20190424111038-f61b66f89f4a/go.mod h1:lB+ZfQJz7igIIfQNfa7Ml4HSf2uFQQRzpGGRXenZAgY= github.com/aws/aws-sdk-go v1.14.17/go.mod h1:ZRmQr0FajVIyZ4ZzBYKG5P3ZqPz9IHG41ZoMu1ADI3k= github.com/aws/aws-sdk-go v1.15.24 h1:xLAdTA/ore6xdPAljzZRed7IGqQgC+nY+ERS5vaj4Ro= github.com/aws/aws-sdk-go v1.15.24/go.mod h1:mFuSZ37Z9YOHbQEwBWztmVzqXrEkub65tZoCYDt7FT0= github.com/aws/aws-sdk-go v1.19.15 h1:Ov8zxPunHxZFxrXBarqzkZBSZugJRzPgb4mfq/SyVgA= github.com/aws/aws-sdk-go v1.19.15/go.mod h1:KmX6BPdI08NWTb3/sm4ZGu5ShLoqVDhKgpiN924inxo= +github.com/aws/aws-sdk-go v1.19.35/go.mod h1:KmX6BPdI08NWTb3/sm4ZGu5ShLoqVDhKgpiN924inxo= +github.com/baiyubin/aliyun-sts-go-sdk v0.0.0-20180326062324-cfa1a18b161f/go.mod h1:AuiFmCCPBSrqvVMvuqFuk0qogytodnVFVSN5CeJB8Gc= github.com/beorn7/perks v0.0.0-20180321164747-3a771d992973 h1:xJ4a3vCFaGF/jqvzLMYoU8P317H5OQ+Via4RmuPwCS0= github.com/beorn7/perks v0.0.0-20180321164747-3a771d992973/go.mod h1:Dwedo/Wpr24TaqPxmxbtue+5NUziq4I4S80YR8gNf3Q= github.com/beorn7/perks v1.0.0 h1:HWo1m869IqiPhD389kmkxeTalrjNbbJTC8LXupb+sl0= github.com/beorn7/perks v1.0.0/go.mod h1:KWe93zE9D1o94FZ5RNwFwVgaQK1VOXiVxmqh+CedLV8= github.com/bgentry/speakeasy v0.1.0 h1:ByYyxL9InA1OWqxJqqp2A5pYHUrCiAL6K3J+LKSsQkY= github.com/bgentry/speakeasy v0.1.0/go.mod h1:+zsyZBPWlz7T6j88CTgSN5bM796AkVf0kBD4zp0CCIs= +github.com/bifurcation/mint v0.0.0-20180715133206-93c51c6ce115/go.mod h1:zVt7zX3K/aDCk9Tj+VM7YymsX66ERvzCJzw8rFCX2JU= +github.com/bifurcation/mint v0.0.0-20190129141059-83ba9bc2ead9/go.mod h1:zVt7zX3K/aDCk9Tj+VM7YymsX66ERvzCJzw8rFCX2JU= github.com/bitly/go-hostpool v0.0.0-20171023180738-a3a6125de932 h1:mXoPYz/Ul5HYEDvkta6I8/rnYM5gSdSV2tJ6XbZuEtY= github.com/bitly/go-hostpool v0.0.0-20171023180738-a3a6125de932/go.mod h1:NOuUCSz6Q9T7+igc/hlvDOUdtWKryOrtFyIVABv/p7k= github.com/bmizerany/assert v0.0.0-20160611221934-b7ed37b82869 h1:DDGfHa7BWjL4YnC6+E63dPcxHo2sUxDIu8g3QgEJdRY= @@ -93,15 +130,22 @@ github.com/census-instrumentation/opencensus-proto v0.2.0 h1:LzQXZOgg4CQfE6bFvXG github.com/census-instrumentation/opencensus-proto v0.2.0/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU= github.com/centrify/cloud-golang-sdk v0.0.0-20190214225812-119110094d0f h1:gJzxrodnNd/CtPXjO3WYiakyNzHg3rtAi7rO74ejHYU= github.com/centrify/cloud-golang-sdk v0.0.0-20190214225812-119110094d0f/go.mod h1:C0rtzmGXgN78pYR0tGJFhtHgkbAs0lIbHwkB81VxDQE= +github.com/cespare/xxhash v1.1.0/go.mod h1:XrSqR1VqqWfGrhpAt58auRo0WTKS1nRRg3ghfAqPWnc= +github.com/cheekybits/genny v0.0.0-20170328200008-9127e812e1e9/go.mod h1:+tQajlRqAUrPI7DOSpB0XAqZYtQakVtB7wXkRAgjxjQ= +github.com/cheekybits/genny v1.0.0/go.mod h1:+tQajlRqAUrPI7DOSpB0XAqZYtQakVtB7wXkRAgjxjQ= github.com/chrismalek/oktasdk-go v0.0.0-20181212195951-3430665dfaa0 h1:CWU8piLyqoi9qXEUwzOh5KFKGgmSU5ZhktJyYcq6ryQ= github.com/chrismalek/oktasdk-go v0.0.0-20181212195951-3430665dfaa0/go.mod h1:5d8DqS60xkj9k3aXfL3+mXBH0DPYO0FQjcKosxl+b/Q= +github.com/circonus-labs/circonus-gometrics v0.0.0-20161109192337-d17a8420c36e/go.mod h1:nmEj6Dob7S7YxXgwXpfOuvO54S+tGdZdw9fuRZt25Ag= github.com/circonus-labs/circonus-gometrics v2.3.1+incompatible h1:C29Ae4G5GtYyYMm1aztcyj/J5ckgJm2zwdDajFbx1NY= github.com/circonus-labs/circonus-gometrics v2.3.1+incompatible/go.mod h1:nmEj6Dob7S7YxXgwXpfOuvO54S+tGdZdw9fuRZt25Ag= +github.com/circonus-labs/circonusllhist v0.0.0-20161110002650-365d370cc145/go.mod h1:kMXHVDlOchFAehlya5ePtbp5jckzBHf4XRpQvBOLI+I= github.com/circonus-labs/circonusllhist v0.1.3 h1:TJH+oke8D16535+jHExHj4nQvzlZrj7ug5D7I/orNUA= github.com/circonus-labs/circonusllhist v0.1.3/go.mod h1:kMXHVDlOchFAehlya5ePtbp5jckzBHf4XRpQvBOLI+I= github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw= github.com/containerd/continuity v0.0.0-20181203112020-004b46473808 h1:4BX8f882bXEDKfWIf0wa8HRvpnBoPszJJXL+TVbBw4M= github.com/containerd/continuity v0.0.0-20181203112020-004b46473808/go.mod h1:GL3xCUCBDV3CZiTSEKksMWbLE66hEyuu9qyDOOqM47Y= +github.com/containerd/continuity v0.0.0-20190426062206-aaeac12a7ffc/go.mod h1:GL3xCUCBDV3CZiTSEKksMWbLE66hEyuu9qyDOOqM47Y= +github.com/coredns/coredns v1.1.2/go.mod h1:zASH/MVDgR6XZTbxvOnsZfffS+31vg6Ackf/wo1+AM0= github.com/coredns/coredns v1.5.0 h1:SJ0xqULsNLGNSBE+G678tM/v1cJ5o5s/FcTC1qPTQkI= github.com/coredns/coredns v1.5.0/go.mod h1:He0NCGwdo32s+0TFFuiB9ccnFZRAsjdrW5Q3Vv5Ne6g= github.com/coreos/bbolt v1.3.2 h1:wZwiHHUieZCquLkDL0B8UhzreNWsPHooDAG3q34zk0s= @@ -110,6 +154,7 @@ github.com/coreos/etcd v3.3.11+incompatible h1:0gCnqKsq7XxMi69JsnbmMc1o+RJH3XH64 github.com/coreos/etcd v3.3.11+incompatible/go.mod h1:uF7uidLiAD3TWHmW31ZFd/JWoc32PjwdhPthX9715RE= github.com/coreos/etcd v3.3.12+incompatible h1:pAWNwdf7QiT1zfaWyqCtNZQWCLByQyA3JrSQyuYAqnQ= github.com/coreos/etcd v3.3.12+incompatible/go.mod h1:uF7uidLiAD3TWHmW31ZFd/JWoc32PjwdhPthX9715RE= +github.com/coreos/etcd v3.3.13+incompatible/go.mod h1:uF7uidLiAD3TWHmW31ZFd/JWoc32PjwdhPthX9715RE= github.com/coreos/go-oidc v2.0.0+incompatible h1:+RStIopZ8wooMx+Vs5Bt8zMXxV1ABl5LbakNExNmZIg= github.com/coreos/go-oidc v2.0.0+incompatible/go.mod h1:CgnwVTmzoESiwO9qyAFEMiHoZ1nMCKZlZ9V6mm3/LKc= github.com/coreos/go-semver v0.2.0 h1:3Jm3tLmsgAYcjC+4Up7hJrFBPr+n7rAqYeSw/SZazuY= @@ -124,51 +169,73 @@ github.com/coreos/pkg v0.0.0-20180928190104-399ea9e2e55f h1:lBNOc5arjvs8E5mO2tbp github.com/coreos/pkg v0.0.0-20180928190104-399ea9e2e55f/go.mod h1:E3G3o1h8I7cfcXa63jLwjI0eiQQMgzzUDFVpN/nH/eA= github.com/dancannon/gorethink v4.0.0+incompatible h1:KFV7Gha3AuqT+gr0B/eKvGhbjmUv0qGF43aKCIKVE9A= github.com/dancannon/gorethink v4.0.0+incompatible/go.mod h1:BLvkat9KmZc1efyYwhz3WnybhRZtgF1K929FD8z1avU= +github.com/davecgh/go-spew v0.0.0-20151105211317-5215b55f46b2/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/denisenkom/go-mssqldb v0.0.0-20180620032804-94c9c97e8c9f/go.mod h1:xN/JuLBIz4bjkxNmByTiV1IbhfnYb6oo99phBn4Eqhc= github.com/denisenkom/go-mssqldb v0.0.0-20190418034912-35416408c946 h1:xn+jBHAqNYs6CnHhJwfWZQspPHMEL+LzUk0vpqWj6eo= github.com/denisenkom/go-mssqldb v0.0.0-20190418034912-35416408c946/go.mod h1:zAg7JM8CkOJ43xKXIj7eRO9kmWm/TW578qo+oDO6tuM= +github.com/denisenkom/go-mssqldb v0.0.0-20190515213511-eb9f6a1743f3/go.mod h1:zAg7JM8CkOJ43xKXIj7eRO9kmWm/TW578qo+oDO6tuM= github.com/denverdino/aliyungo v0.0.0-20170926055100-d3308649c661 h1:lrWnAyy/F72MbxIxFUzKmcMCdt9Oi8RzpAxzTNQHD7o= github.com/denverdino/aliyungo v0.0.0-20170926055100-d3308649c661/go.mod h1:dV8lFg6daOBZbT6/BDGIz6Y3WFGn8juu6G+CQ6LHtl0= github.com/denverdino/aliyungo v0.0.0-20190410085603-611ead8a6fed h1:WtFFp2kd7j/ATD3dT5tdjyoXuynxHu6D0AJVG9Be1q4= github.com/denverdino/aliyungo v0.0.0-20190410085603-611ead8a6fed/go.mod h1:dV8lFg6daOBZbT6/BDGIz6Y3WFGn8juu6G+CQ6LHtl0= github.com/dgrijalva/jwt-go v3.2.0+incompatible h1:7qlOGliEKZXTDg6OTjfoBKDXWrumCAMpl/TFQ4/5kLM= github.com/dgrijalva/jwt-go v3.2.0+incompatible/go.mod h1:E3ru+11k8xSBh+hMPgOLZmtrrCbhqsmaPHjLKYnJCaQ= +github.com/dgryski/go-sip13 v0.0.0-20181026042036-e10d5fee7954/go.mod h1:vAd38F8PWV+bWy6jNmig1y/TA+kYO4g3RSRF0IAv0no= +github.com/dgryski/go-sip13 v0.0.0-20190329191031-25c5027a8c7b/go.mod h1:vAd38F8PWV+bWy6jNmig1y/TA+kYO4g3RSRF0IAv0no= github.com/digitalocean/godo v1.1.1 h1:v0A7yF3xmKLjjdJGIeBbINfMufcrrRhqZsxuVQMoT+U= github.com/digitalocean/godo v1.1.1/go.mod h1:h6faOIcZ8lWIwNQ+DN7b3CgX4Kwby5T+nbpNqkUIozU= +github.com/digitalocean/godo v1.10.0/go.mod h1:h6faOIcZ8lWIwNQ+DN7b3CgX4Kwby5T+nbpNqkUIozU= github.com/digitalocean/godo v1.13.0 h1:+0rQUl0AkTmhKDeqP8Y1Z60cJzhC/1jPI6jWpWnLUr8= github.com/digitalocean/godo v1.13.0/go.mod h1:h6faOIcZ8lWIwNQ+DN7b3CgX4Kwby5T+nbpNqkUIozU= +github.com/digitalocean/godo v1.15.0/go.mod h1:AAPQ+tiM4st79QHlEBTg8LM7JQNre4SAQCbn56wEyKY= github.com/dimchansky/utfbom v1.1.0 h1:FcM3g+nofKgUteL8dm/UpdRXNC9KmADgTpLKsu0TRo4= github.com/dimchansky/utfbom v1.1.0/go.mod h1:rO41eb7gLfo8SF1jd9F8HplJm1Fewwi4mQvIirEdv+8= +github.com/dnaeon/go-vcr v0.0.0-20180814043457-aafff18a5cc2/go.mod h1:aBB1+wY4s93YsC3HHjMBMrwTj2R9FHDzUr9KyGc8n1E= github.com/dnaeon/go-vcr v1.0.1 h1:r8L/HqC0Hje5AXMu1ooW8oyQyOFv4GxqpL0nRP7SLLY= github.com/dnaeon/go-vcr v1.0.1/go.mod h1:aBB1+wY4s93YsC3HHjMBMrwTj2R9FHDzUr9KyGc8n1E= github.com/dnstap/golang-dnstap v0.0.0-20170829151710-2cf77a2b5e11/go.mod h1:s1PfVYYVmTMgCSPtho4LKBDecEHJWtiVDPNv78Z985U= +github.com/dnstap/golang-dnstap v0.0.0-20190521061535-1a0dab85b926/go.mod h1:s1PfVYYVmTMgCSPtho4LKBDecEHJWtiVDPNv78Z985U= +github.com/docker/go-connections v0.3.0/go.mod h1:Gbd7IOopHjR8Iph03tsViu4nIes5XhDvyHbTtUxmeec= github.com/docker/go-connections v0.4.0 h1:El9xVISelRB7BuFusrZozjnkIM5YnzCViNKohAFqRJQ= github.com/docker/go-connections v0.4.0/go.mod h1:Gbd7IOopHjR8Iph03tsViu4nIes5XhDvyHbTtUxmeec= github.com/docker/go-units v0.3.3 h1:Xk8S3Xj5sLGlG5g67hJmYMmUgXv5N4PhkjJHHqrwnTk= github.com/docker/go-units v0.3.3/go.mod h1:fgPhTUdO+D/Jk86RDLlptpiXQzgHJF7gydDDbaIK4Dk= +github.com/docker/go-units v0.4.0/go.mod h1:fgPhTUdO+D/Jk86RDLlptpiXQzgHJF7gydDDbaIK4Dk= github.com/docker/spdystream v0.0.0-20160310174837-449fdfce4d96/go.mod h1:Qh8CwZgvJUkLughtfhJv5dyTYa91l1fOUCrgjqmcifM= +github.com/docker/spdystream v0.0.0-20181023171402-6480d4af844c/go.mod h1:Qh8CwZgvJUkLughtfhJv5dyTYa91l1fOUCrgjqmcifM= github.com/duosecurity/duo_api_golang v0.0.0-20190308151101-6c680f768e74 h1:2MIhn2R6oXQbgW5yHfS+d6YqyMfXiu2L55rFZC4UD/M= github.com/duosecurity/duo_api_golang v0.0.0-20190308151101-6c680f768e74/go.mod h1:UqXY1lYT/ERa4OEAywUqdok1T4RCRdArkhic1Opuavo= +github.com/dustin/go-humanize v1.0.0/go.mod h1:HtrtbFcZ19U5GC7JDqmcUSB87Iq5E25KnS6fMYU6eOk= github.com/eapache/go-resiliency v1.1.0/go.mod h1:kFI+JgMyC7bLPUVY133qvEBtVayf5mFgVsvEsIPBvNs= github.com/eapache/go-xerial-snappy v0.0.0-20180814174437-776d5712da21/go.mod h1:+020luEh2TKB4/GOp8oxxtq0Daoen/Cii55CzbTV6DU= github.com/eapache/queue v1.1.0/go.mod h1:6eCeP0CKFpHLu8blIFXhExK/dRa7WDZfr6jVFPTqq+I= +github.com/elazarl/go-bindata-assetfs v0.0.0-20160803192304-e1a2a7ec64b0/go.mod h1:v+YaWX3bdea5J/mo8dSETolEo7R71Vk1u8bnjau5yw4= github.com/elazarl/go-bindata-assetfs v1.0.0 h1:G/bYguwHIzWq9ZoyUQqrjTmJbbYn3j3CKKpKinvZLFk= github.com/elazarl/go-bindata-assetfs v1.0.0/go.mod h1:v+YaWX3bdea5J/mo8dSETolEo7R71Vk1u8bnjau5yw4= github.com/elazarl/goproxy v0.0.0-20170405201442-c4fc26588b6e/go.mod h1:/Zj4wYkgs4iZTTu3o/KG3Itv/qCCa8VVMlb3i9OVuzc= +github.com/elazarl/goproxy v0.0.0-20190421051319-9d40249d3c2f/go.mod h1:/Zj4wYkgs4iZTTu3o/KG3Itv/qCCa8VVMlb3i9OVuzc= +github.com/emicklei/go-restful v0.0.0-20170410110728-ff4f55a20633/go.mod h1:otzb+WCGbkyDHkqmQmT5YD2WR4BBwUdeQoFo8l/7tVs= +github.com/emicklei/go-restful v2.9.5+incompatible/go.mod h1:otzb+WCGbkyDHkqmQmT5YD2WR4BBwUdeQoFo8l/7tVs= +github.com/envoyproxy/go-control-plane v0.0.0-20180919002855-2137d9196328/go.mod h1:SBwIajubJHhxtWwsL9s8ss4safvEdbitLhGGK48rN6g= github.com/envoyproxy/go-control-plane v0.6.9 h1:deEH9W8ZAUGNbCdX+9iNzBOGrAOrnpJGoy0PcTqk/tE= github.com/envoyproxy/go-control-plane v0.6.9/go.mod h1:SBwIajubJHhxtWwsL9s8ss4safvEdbitLhGGK48rN6g= github.com/envoyproxy/go-control-plane v0.7.1 h1:CwDZ3n/znIaqNalgauCWLZ6Wl7NCe6v9yjiY4kslaMk= github.com/envoyproxy/go-control-plane v0.7.1/go.mod h1:SBwIajubJHhxtWwsL9s8ss4safvEdbitLhGGK48rN6g= +github.com/envoyproxy/go-control-plane v0.8.0/go.mod h1:GSSbY9P1neVhdY7G4wu+IK1rk/dqhiCC/4ExuWJZVuk= github.com/envoyproxy/protoc-gen-validate v0.0.14 h1:YBW6/cKy9prEGRYLnaGa4IDhzxZhRCtKsax8srGKDnM= github.com/envoyproxy/protoc-gen-validate v0.0.14/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c= github.com/estesp/manifest-tool v0.9.0/go.mod h1:w/oandYlJC/m8nkP8UaJVxsm/LwjurJQHXR27njws74= github.com/evanphx/json-patch v0.0.0-20190203023257-5858425f7550/go.mod h1:50XU6AFN0ol/bzJsmQLiYLvXMP4fmwYFNcr97nuDLSk= github.com/evanphx/json-patch v4.1.0+incompatible/go.mod h1:50XU6AFN0ol/bzJsmQLiYLvXMP4fmwYFNcr97nuDLSk= +github.com/evanphx/json-patch v4.2.0+incompatible/go.mod h1:50XU6AFN0ol/bzJsmQLiYLvXMP4fmwYFNcr97nuDLSk= github.com/farsightsec/golang-framestream v0.0.0-20181102145529-8a0cb8ba8710/go.mod h1:eNde4IQyEiA5br02AouhEHCu3p3UzrCdFR4LuQHklMI= +github.com/farsightsec/golang-framestream v0.0.0-20190425193708-fa4b164d59b8/go.mod h1:eNde4IQyEiA5br02AouhEHCu3p3UzrCdFR4LuQHklMI= github.com/fatih/color v1.7.0 h1:DkWD4oS2D8LGGgTQ6IvwJJXSL5Vp2ffcQg58nFV38Ys= github.com/fatih/color v1.7.0/go.mod h1:Zm6kSWBoL9eyXnKyktHP6abPY2pDugNf5KwzbycvMj4= +github.com/fatih/structs v0.0.0-20180123065059-ebf56d35bba7/go.mod h1:9NiDSp5zOcgEDl+j00MP/WkGVPOlPRLejGD8Ga6PJ7M= github.com/fatih/structs v1.1.0 h1:Q7juDM0QtcnhCpeyLGQKyg4TOIghuNXrkL32pHAUMxo= github.com/fatih/structs v1.1.0/go.mod h1:9NiDSp5zOcgEDl+j00MP/WkGVPOlPRLejGD8Ga6PJ7M= github.com/flynn/go-shlex v0.0.0-20150515145356-3f9db97f8568/go.mod h1:xEzjJPgXI435gkrCt3MPfRiAkVrwSbHsst4LCFVfpJc= @@ -178,12 +245,16 @@ github.com/fullsailor/pkcs7 v0.0.0-20190404230743-d7302db945fa h1:RDBNVkRviHZtvD github.com/fullsailor/pkcs7 v0.0.0-20190404230743-d7302db945fa/go.mod h1:KnogPXtdwXqoenmZCw6S+25EAm2MkxbG0deNDu4cbSA= github.com/gammazero/deque v0.0.0-20190130191400-2afb3858e9c7 h1:D2LrfOPgGHQprIxmsTpxtzhpmF66HoM6rXSmcqaX7h8= github.com/gammazero/deque v0.0.0-20190130191400-2afb3858e9c7/go.mod h1:GeIq9qoE43YdGnDXURnmKTnGg15pQz4mYkXSTChbneI= +github.com/gammazero/deque v0.0.0-20190521012701-46e4ffb7a622/go.mod h1:D90+MBHVc9Sk1lJAbEVgws0eYEurY4mv2TDso3Nxh3w= github.com/gammazero/workerpool v0.0.0-20190406235159-88d534f22b56 h1:VzbudKn/nvxYKOdzgkEBS6SSreRjAgoJ+ZeS4wPFkgc= github.com/gammazero/workerpool v0.0.0-20190406235159-88d534f22b56/go.mod h1:w9RqFVO2BM3xwWEcAB8Fwp0OviTBBEiRmSBDfbXnd3w= +github.com/gammazero/workerpool v0.0.0-20190521015540-3b91a70bc0a1/go.mod h1:avlwxCMavNtjwf7NrfnzdIGU3OZYI5D1NFQ2Rn3nHKg= github.com/garyburd/redigo v1.6.0 h1:0VruCpn7yAIIu7pWVClQC8wxCJEcG3nyzpMSHKi1PQc= github.com/garyburd/redigo v1.6.0/go.mod h1:NR3MbYisc3/PwhQ00EMzDiPmrwpPxAn5GI05/YaO1SY= +github.com/ghodss/yaml v0.0.0-20150909031657-73d445a93680/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04= github.com/ghodss/yaml v1.0.0 h1:wQHKEahhL6wmXdzwWG11gIVCkOv05bNOh+Rxn0yngAk= github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04= +github.com/go-acme/lego v2.5.0+incompatible/go.mod h1:yzMNe9CasVUhkquNvti5nAtPmG94USbYxYrZfTkIn0M= github.com/go-errors/errors v1.0.1 h1:LUHzmkK3GUKUrL/1gfBUxAHzcev3apQlezX/+O7ma6w= github.com/go-errors/errors v1.0.1/go.mod h1:f4zRHt4oKfwPJE5k8C9vpYG+aDHdBFUsgrm6/TyX73Q= github.com/go-ini/ini v1.25.4 h1:Mujh4R/dH6YL8bxuISne3xX2+qcQ9p0IxKAP6ExWoUo= @@ -199,17 +270,34 @@ github.com/go-log/log v0.1.0 h1:wudGTNsiGzrD5ZjgIkVZ517ugi2XRe9Q/xRCzwEO4/U= github.com/go-log/log v0.1.0/go.mod h1:4mBwpdRMFLiuXZDCwU2lKQFsoSCo72j3HqBK9d81N2M= github.com/go-logfmt/logfmt v0.3.0/go.mod h1:Qt1PoO58o5twSAckw1HlFXLmHsOX5/0LbT9GBnD5lWE= github.com/go-logfmt/logfmt v0.4.0/go.mod h1:3RMwSq7FuexP4Kalkev3ejPJsZTpXXBr9+V4qmtdjCk= +github.com/go-ole/go-ole v1.2.1/go.mod h1:7FAglXiTm7HKlQRDeOQ6ZNUHidzCWXuZWq/1dTyBNF8= github.com/go-ole/go-ole v1.2.4 h1:nNBDSCOigTSiarFpYE9J/KtEA1IOW4CNeqT9TQDqCxI= github.com/go-ole/go-ole v1.2.4/go.mod h1:XCwSNxSkXRo4vlyPy93sltvi/qJq0jqQhjqQNIwKuxM= +github.com/go-openapi/jsonpointer v0.0.0-20160704185906-46af16f9f7b1/go.mod h1:+35s3my2LFTysnkMfxsJBAMHj/DoqoB9knIWoYG/Vk0= +github.com/go-openapi/jsonpointer v0.17.0/go.mod h1:cOnomiV+CVVwFLk0A/MExoFMjwdsUdVpsRhURCKh+3M= +github.com/go-openapi/jsonpointer v0.19.0/go.mod h1:cOnomiV+CVVwFLk0A/MExoFMjwdsUdVpsRhURCKh+3M= +github.com/go-openapi/jsonreference v0.0.0-20160704190145-13c6e3589ad9/go.mod h1:W3Z9FmVs9qj+KR4zFKmDPGiLdk1D9Rlm7cyMvf57TTg= +github.com/go-openapi/jsonreference v0.17.0/go.mod h1:g4xxGn04lDIRh0GJb5QlpE3HfopLOL6uZrK/VgnsK9I= +github.com/go-openapi/jsonreference v0.19.0/go.mod h1:g4xxGn04lDIRh0GJb5QlpE3HfopLOL6uZrK/VgnsK9I= +github.com/go-openapi/spec v0.0.0-20160808142527-6aced65f8501/go.mod h1:J8+jY1nAiCcj+friV/PDoE1/3eeccG9LYBs0tYvLOWc= +github.com/go-openapi/spec v0.19.0/go.mod h1:XkF/MOi14NmjsfZ8VtAKf8pIlbZzyoTvZsdfssdxcBI= +github.com/go-openapi/swag v0.0.0-20160704191624-1d0bd113de87/go.mod h1:DXUve3Dpr1UfpPtxFw+EFuQ41HhCWZfha5jSVRG7C7I= +github.com/go-openapi/swag v0.17.0/go.mod h1:AByQ+nYG6gQg71GINrmuDXCPWdL640yX49/kXLo40Tg= +github.com/go-openapi/swag v0.19.0/go.mod h1:AByQ+nYG6gQg71GINrmuDXCPWdL640yX49/kXLo40Tg= +github.com/go-sql-driver/mysql v0.0.0-20180618115901-749ddf1598b4/go.mod h1:zAC/RDZ24gD3HViQzih4MyKcchzm+sOG5ZlKdlhCg5w= github.com/go-sql-driver/mysql v1.4.1 h1:g24URVg0OFbNUTx9qqY1IRZ9D9z3iPyi5zKhQZpNwpA= github.com/go-sql-driver/mysql v1.4.1/go.mod h1:zAC/RDZ24gD3HViQzih4MyKcchzm+sOG5ZlKdlhCg5w= github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY= github.com/go-stomp/stomp v2.0.2+incompatible h1:0yPknMJh32lE2xiCFGW5t/KgamhUC4OgCv10wIjx5aw= github.com/go-stomp/stomp v2.0.2+incompatible/go.mod h1:VqCtqNZv1226A1/79yh+rMiFUcfY3R109np+7ke4n0c= +github.com/go-stomp/stomp v2.0.3+incompatible/go.mod h1:VqCtqNZv1226A1/79yh+rMiFUcfY3R109np+7ke4n0c= github.com/go-test/deep v1.0.1 h1:UQhStjbkDClarlmv0am7OXXO4/GaPdCGiUiMTvi28sg= github.com/go-test/deep v1.0.1/go.mod h1:wGDj63lr65AM2AQyKZd/NYHGb0R+1RLqB8NKt3aSFNA= +github.com/go-test/deep v1.0.2-0.20181118220953-042da051cf31/go.mod h1:wGDj63lr65AM2AQyKZd/NYHGb0R+1RLqB8NKt3aSFNA= +github.com/gocql/gocql v0.0.0-20180617115710-e06f8c1bcd78/go.mod h1:4Fw1eo5iaEhDUs8XyuhSVCVy52Jq3L+/3GJgYkwc+/0= github.com/gocql/gocql v0.0.0-20190418090649-59a610c947c5 h1:ja4omKSx9OiML8GnnDG13qOX58UAcSJfOmce21YXALk= github.com/gocql/gocql v0.0.0-20190418090649-59a610c947c5/go.mod h1:4Fw1eo5iaEhDUs8XyuhSVCVy52Jq3L+/3GJgYkwc+/0= +github.com/gocql/gocql v0.0.0-20190423091413-b99afaf3b163/go.mod h1:4Fw1eo5iaEhDUs8XyuhSVCVy52Jq3L+/3GJgYkwc+/0= github.com/gogo/googleapis v1.1.0 h1:kFkMAZBNAn4j7K0GiZr8cRYzejq68VbheufiV3YuyFI= github.com/gogo/googleapis v1.1.0/go.mod h1:gf4bu3Q80BeJ6H1S1vYPm8/ELATdvryBaNFGgqEef3s= github.com/gogo/googleapis v1.2.0 h1:Z0v3OJDotX9ZBpdz2V+AI7F4fITSZhVE5mg6GQppwMM= @@ -219,6 +307,7 @@ github.com/gogo/protobuf v1.1.1/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7a github.com/gogo/protobuf v1.2.0/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ= github.com/gogo/protobuf v1.2.1 h1:/s5zKNz0uPFCZ5hddgPdo2TK2TVrUNMn0OOX8/aZMTE= github.com/gogo/protobuf v1.2.1/go.mod h1:hp+jE20tsWTFYpLwKvXlhS1hjn+gTNwPg2I6zVXpSg4= +github.com/goji/httpauth v0.0.0-20160601135302-2da839ab0f4d/go.mod h1:nnjvkQ9ptGaCkuDUx6wNykzzlUixGxvkme+H/lnzb+A= github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b h1:VKtxabqXZkF25pY9ekfRL6a582T4P37/31XEstQ5p58= github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q= github.com/golang/groupcache v0.0.0-20160516000752-02826c3e7903/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= @@ -228,6 +317,8 @@ github.com/golang/lint v0.0.0-20180702182130-06c8688daad7/go.mod h1:tluoj9z5200j github.com/golang/lint v0.0.0-20190227174305-8f45f776aaf1/go.mod h1:tluoj9z5200jBnyusfRPU2LqT6J+DAorxEvtC7LHB+E= github.com/golang/mock v1.1.1/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A= github.com/golang/mock v1.2.0/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A= +github.com/golang/mock v1.3.1/go.mod h1:sBzyDLLjw3U8JLTeZvSv8jJB+tU5PVekmnlKIyFUx0Y= +github.com/golang/protobuf v0.0.0-20161109072736-4bd1920723d7/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= github.com/golang/protobuf v1.2.0 h1:P3YflyNX/ehuJFLhxviNdFxQPkGK5cDcApsge1SqnvM= github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= github.com/golang/protobuf v1.3.1 h1:YF8+flBXS5eO826T4nzqPrxfhQThhXl0YzfuUPu4SBg= @@ -242,18 +333,21 @@ github.com/google/btree v1.0.0 h1:0udJVsspx3VBr5FwtLhQQtuAsVc79tTq0ocGIPAU6qo= github.com/google/btree v1.0.0/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ= github.com/google/go-cmp v0.2.0 h1:+dTQ8DZQJz0Mb/HjFlkptS1FeQ4cWSnN941F8aEG4SQ= github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M= +github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= github.com/google/go-github v17.0.0+incompatible h1:N0LgJ1j65A7kfXrZnUDaYCs/Sf4rEjNlfyDHW9dolSY= github.com/google/go-github v17.0.0+incompatible/go.mod h1:zLgOLi98H3fifZn+44m+umXrS52loVEgC2AApnigrVQ= github.com/google/go-querystring v0.0.0-20170111101155-53e6ce116135 h1:zLTLjkaOFEFIOxY5BWLFLwh+cL8vOBW4XJ2aqLE/Tf0= github.com/google/go-querystring v0.0.0-20170111101155-53e6ce116135/go.mod h1:odCYkC5MyYFN7vkCjXpyrEuKhc/BUO6wN/zVPAxq5ck= github.com/google/go-querystring v1.0.0 h1:Xkwi/a1rcvNg1PPYe5vI8GbeBY/jrVuDX5ASuANWTrk= github.com/google/go-querystring v1.0.0/go.mod h1:odCYkC5MyYFN7vkCjXpyrEuKhc/BUO6wN/zVPAxq5ck= +github.com/google/gofuzz v0.0.0-20161122191042-44d81051d367/go.mod h1:HP5RmnzzSNb993RKQDq4+1A4ia9nllfqcQFTQJedwGI= github.com/google/gofuzz v0.0.0-20170612174753-24818f796faf h1:+RRA9JqSOZFfKrOeqr2z77+8R2RKyh8PG66dcu1V0ck= github.com/google/gofuzz v0.0.0-20170612174753-24818f796faf/go.mod h1:HP5RmnzzSNb993RKQDq4+1A4ia9nllfqcQFTQJedwGI= github.com/google/gofuzz v1.0.0 h1:A8PeW59pxE9IoFRqBp37U+mSNaQoZ46F1f0f863XSXw= github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= github.com/google/martian v2.1.0+incompatible/go.mod h1:9I4somxYTbIHy5NJKHRl3wXiIaQGbYVAs8BPL6v8lEs= github.com/google/pprof v0.0.0-20181206194817-3ea8567a2e57/go.mod h1:zfwlbNMJ+OItoe0UupaVj+oy1omPYYDuagoSzA8v9mc= +github.com/google/pprof v0.0.0-20190515194954-54271f7e092f/go.mod h1:zfwlbNMJ+OItoe0UupaVj+oy1omPYYDuagoSzA8v9mc= github.com/google/uuid v1.0.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/google/uuid v1.1.0 h1:Jf4mxPC/ziBnoPIdpQdPJ9OeiomAUHLvxmPRSPH9m4s= github.com/google/uuid v1.1.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= @@ -261,6 +355,7 @@ github.com/google/uuid v1.1.1 h1:Gkbcsh/GbpXz7lPftLA3P6TYMwjCLYm83jiFQZF/3gY= github.com/google/uuid v1.1.1/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/googleapis/gax-go/v2 v2.0.4 h1:hU4mGcQI4DaAYW+IbTun+2qEZVFxK0ySjQLTbS0VQKc= github.com/googleapis/gax-go/v2 v2.0.4/go.mod h1:0Wqv26UfaUD9n4G6kQubkQ+KchISgw+vpHVxEJEs9eg= +github.com/googleapis/gnostic v0.0.0-20170426233943-68f4ded48ba9/go.mod h1:sJBsCZ4ayReDTBIg8b9dl28c5xFWyhBTVRp3pOg5EKY= github.com/googleapis/gnostic v0.0.0-20170729233727-0c5108395e2d/go.mod h1:sJBsCZ4ayReDTBIg8b9dl28c5xFWyhBTVRp3pOg5EKY= github.com/googleapis/gnostic v0.2.0 h1:l6N3VoaVzTncYYW+9yOz2LJJammFZGBO13sqgEhpy9g= github.com/googleapis/gnostic v0.2.0/go.mod h1:sJBsCZ4ayReDTBIg8b9dl28c5xFWyhBTVRp3pOg5EKY= @@ -270,16 +365,19 @@ github.com/gophercloud/gophercloud v0.0.0-20190307220656-fe1ba5ce12dd h1:tkA3C/X github.com/gophercloud/gophercloud v0.0.0-20190307220656-fe1ba5ce12dd/go.mod h1:vxM41WHh5uqHVBMZHzuwNOHh8XEoIEcSTewFxm1c5g8= github.com/gophercloud/gophercloud v0.0.0-20190422143055-fe6299556848 h1:3C19GoTlj2BtSe+APK65YeFikcZVacnXncVEPGuqOQU= github.com/gophercloud/gophercloud v0.0.0-20190422143055-fe6299556848/go.mod h1:vxM41WHh5uqHVBMZHzuwNOHh8XEoIEcSTewFxm1c5g8= +github.com/gophercloud/gophercloud v0.0.0-20190520235722-e87e5f90e7e6/go.mod h1:vxM41WHh5uqHVBMZHzuwNOHh8XEoIEcSTewFxm1c5g8= github.com/gopherjs/gopherjs v0.0.0-20180825215210-0210a2f0f73c h1:16eHWuMGvCjSfgRJKqIzapE78onvvTbdi1rMkU00lZw= github.com/gopherjs/gopherjs v0.0.0-20180825215210-0210a2f0f73c/go.mod h1:wJfORRmW1u3UXTncJ5qlYoELFm8eSnnEO6hX4iZ3EWY= github.com/gopherjs/gopherjs v0.0.0-20181017120253-0766667cb4d1 h1:EGx4pi6eqNxGaHF6qqu48+N2wcFQ5qg5FXgOdqsJ5d8= github.com/gopherjs/gopherjs v0.0.0-20181017120253-0766667cb4d1/go.mod h1:wJfORRmW1u3UXTncJ5qlYoELFm8eSnnEO6hX4iZ3EWY= github.com/gopherjs/gopherjs v0.0.0-20190411002643-bd77b112433e h1:XWcjeEtTFTOVA9Fs1w7n2XBftk5ib4oZrhzWk0B+3eA= github.com/gopherjs/gopherjs v0.0.0-20190411002643-bd77b112433e/go.mod h1:wJfORRmW1u3UXTncJ5qlYoELFm8eSnnEO6hX4iZ3EWY= +github.com/gopherjs/gopherjs v0.0.0-20190430165422-3e4dfb77656c/go.mod h1:wJfORRmW1u3UXTncJ5qlYoELFm8eSnnEO6hX4iZ3EWY= github.com/gorhill/cronexpr v0.0.0-20180427100037-88b0669f7d75 h1:f0n1xnMSmBLzVfsMMvriDyA75NB/oBgILX2GcHXIQzY= github.com/gorhill/cronexpr v0.0.0-20180427100037-88b0669f7d75/go.mod h1:g2644b03hfBX9Ov0ZBDgXXens4rxSxmqFBbhvKv2yVA= github.com/gorilla/context v1.1.1/go.mod h1:kBGZzfjB9CEq2AlWe17Uuf7NDRt0dE0s8S51q0aT7Yg= github.com/gorilla/mux v1.6.2/go.mod h1:1lud6UwP+6orDFRuTfBEV8e9/aOM/c4fVVCaMa2zaAs= +github.com/gorilla/mux v1.7.2/go.mod h1:1lud6UwP+6orDFRuTfBEV8e9/aOM/c4fVVCaMa2zaAs= github.com/gorilla/websocket v1.4.0 h1:WDFjx/TMzVgy9VdMMQi2K2Emtwi2QcUQsztZ/zLaH/Q= github.com/gorilla/websocket v1.4.0/go.mod h1:E7qHFY5m1UJ88s3WnNqhKjPHQ0heANvMoAMk2YaljkQ= github.com/gotestyourself/gotestyourself v2.2.0+incompatible h1:AQwinXlbQR2HvPjQZOmDhRqsv5mZf+Jb1RnSLxcqZcI= @@ -296,6 +394,7 @@ github.com/grpc-ecosystem/grpc-gateway v1.6.2/go.mod h1:RSKVYQBd5MCa4OVpNdGskqpg github.com/grpc-ecosystem/grpc-gateway v1.8.3/go.mod h1:vNeuVxBJEsws4ogUvrchl83t/GYV9WGTSLVdBhOQFDY= github.com/grpc-ecosystem/grpc-gateway v1.8.5 h1:2+KSC78XiO6Qy0hIjfc1OD9H+hsaJdJlb8Kqsd41CTE= github.com/grpc-ecosystem/grpc-gateway v1.8.5/go.mod h1:vNeuVxBJEsws4ogUvrchl83t/GYV9WGTSLVdBhOQFDY= +github.com/grpc-ecosystem/grpc-gateway v1.9.0/go.mod h1:vNeuVxBJEsws4ogUvrchl83t/GYV9WGTSLVdBhOQFDY= github.com/grpc-ecosystem/grpc-opentracing v0.0.0-20180507213350-8e809c8a8645/go.mod h1:6iZfnjpejD4L/4DwD7NryNaJyCQdzwWwH2MWhCA90Kw= github.com/hailocab/go-hostpool v0.0.0-20160125115350-e80d13ce29ed h1:5upAirOpQc1Q53c0bnx2ufif5kANL7bfZWcc6VJWJd8= github.com/hailocab/go-hostpool v0.0.0-20160125115350-e80d13ce29ed/go.mod h1:tMWxXQ9wFIaZeTI9F+hmhFiGpFmhOHzyShyFUhRm0H4= @@ -303,31 +402,49 @@ github.com/hashicorp/consul v1.4.2 h1:D9iJoJb8Ehe/Zmr+UEE3U3FjOLZ4LUxqFMl4O43BM1 github.com/hashicorp/consul v1.4.2/go.mod h1:mFrjN1mfidgJfYP1xrJCF+AfRhr6Eaqhb2+sfyn/OOI= github.com/hashicorp/consul v1.4.4 h1:DR1+5EGgnPsd/LIsK3c9RDvajcsV5GOkGQBSNd3dpn8= github.com/hashicorp/consul v1.4.4/go.mod h1:mFrjN1mfidgJfYP1xrJCF+AfRhr6Eaqhb2+sfyn/OOI= +github.com/hashicorp/consul v1.5.0 h1:GPtcwUGw5kjoSIF7NpDHmwHEM17ufGn1ezKQSutBMhI= +github.com/hashicorp/consul v1.5.0/go.mod h1:7rvUESOLul7V9uCo5TNZ64jzf9W5Fcy/xf/TxtOT0xQ= +github.com/hashicorp/consul/api v1.1.0 h1:BNQPM9ytxj6jbjjdRPioQ94T6YXriSopn0i8COv6SRA= +github.com/hashicorp/consul/api v1.1.0/go.mod h1:VmuI/Lkw1nC05EYQWNKwWGbkg+FbDBtguAZLlVdkD9Q= +github.com/hashicorp/consul/sdk v0.1.1/go.mod h1:VKf9jXwCTEY1QZP2MOLRhb5i/I/ssyNV1vwHyQBF0x8= github.com/hashicorp/errwrap v1.0.0 h1:hLrqtEDnRye3+sgx6z4qVLNuviH3MR5aQ0ykNJa/UYA= github.com/hashicorp/errwrap v1.0.0/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4= +github.com/hashicorp/go-bexpr v0.1.0/go.mod h1:ANbpTX1oAql27TZkKVeW8p1w8NTdnyzPe/0qqPCKohU= +github.com/hashicorp/go-checkpoint v0.0.0-20171009173528-1545e56e46de/go.mod h1:xIwEieBHERyEvaeKF/TcHh1Hu+lxPM+n2vT1+g9I4m4= +github.com/hashicorp/go-checkpoint v0.5.0/go.mod h1:7nfLNL10NsxqO4iWuW6tWW0HjZuDrwkBuEQsVcpCOgg= github.com/hashicorp/go-cleanhttp v0.5.0 h1:wvCrVc9TjDls6+YGAF2hAifE1E5U1+b4tH6KdvN3Gig= github.com/hashicorp/go-cleanhttp v0.5.0/go.mod h1:JpRdi6/HCYpAwUzNwuwqhbovhLtngrth3wmdIIUrZ80= github.com/hashicorp/go-cleanhttp v0.5.1 h1:dH3aiDG9Jvb5r5+bYHsikaOUIpcM0xvgMXVoDkXMzJM= github.com/hashicorp/go-cleanhttp v0.5.1/go.mod h1:JpRdi6/HCYpAwUzNwuwqhbovhLtngrth3wmdIIUrZ80= +github.com/hashicorp/go-discover v0.0.0-20190403160810-22221edb15cd/go.mod h1:ueUgD9BeIocT7QNuvxSyJyPAM9dfifBcaWmeybb67OY= github.com/hashicorp/go-discover v0.0.0-20190408185603-6ccdb67f9b84 h1:ImeFWg0F3G8xtba0MrlDXgw8lmR4dDgwqZrrWOowelY= github.com/hashicorp/go-discover v0.0.0-20190408185603-6ccdb67f9b84/go.mod h1:FTV98wIi2RF5iDl1iLR/cB+no+B//ODP6133EcC9djw= +github.com/hashicorp/go-discover v0.0.0-20190522154730-8aba54d36e17/go.mod h1:FTV98wIi2RF5iDl1iLR/cB+no+B//ODP6133EcC9djw= github.com/hashicorp/go-gcp-common v0.5.0 h1:kkIQTjNTopn4eXQ1+lCiHYZXUtgIZvbc6YtAQkMnTos= github.com/hashicorp/go-gcp-common v0.5.0/go.mod h1:IDGUI2N/OS3PiU4qZcXJeWKPI6O/9Y8hOrbSiMcqyYw= +github.com/hashicorp/go-hclog v0.0.0-20180402200405-69ff559dc25f/go.mod h1:9bjs9uLqI8l75knNv3lV1kA55veR+WUPSiKIWcQHudI= github.com/hashicorp/go-hclog v0.0.0-20180709165350-ff2cf002a8dd/go.mod h1:9bjs9uLqI8l75knNv3lV1kA55veR+WUPSiKIWcQHudI= github.com/hashicorp/go-hclog v0.8.0 h1:z3ollgGRg8RjfJH6UVBaG54R70GFd++QOkvnJH3VSBY= github.com/hashicorp/go-hclog v0.8.0/go.mod h1:5CU+agLiy3J7N7QjHK5d05KxGsuXiQLrjA0H7acj2lQ= +github.com/hashicorp/go-hclog v0.9.2/go.mod h1:5CU+agLiy3J7N7QjHK5d05KxGsuXiQLrjA0H7acj2lQ= github.com/hashicorp/go-immutable-radix v1.0.0 h1:AKDB1HM5PWEA7i4nhcpwOrO2byshxBjXVn/J/3+z5/0= github.com/hashicorp/go-immutable-radix v1.0.0/go.mod h1:0y9vanUI8NX6FsYoO3zeMjhV/C5i9g4Q3DwcSNZ4P60= +github.com/hashicorp/go-memdb v0.0.0-20180223233045-1289e7fffe71/go.mod h1:kbfItVoBJwCfKXDXN4YoAXjxcFVZ7MRrJzyTX6H4giE= github.com/hashicorp/go-memdb v1.0.1 h1:QR2h3O60I0DSvCsogh77kZUPzZBkbDSfeUjzhrK8p04= github.com/hashicorp/go-memdb v1.0.1/go.mod h1:I6dKdmYhZqU0RJSheVEWgTNWdVQH5QvTgIUQ0t/t32M= +github.com/hashicorp/go-memdb v1.0.2/go.mod h1:I6dKdmYhZqU0RJSheVEWgTNWdVQH5QvTgIUQ0t/t32M= github.com/hashicorp/go-msgpack v0.5.3 h1:zKjpN5BK/P5lMYrLmBHdBULWbJ0XpYR+7NGzqkZzoD4= github.com/hashicorp/go-msgpack v0.5.3/go.mod h1:ahLV/dePpqEmjfWmKiqvPkv/twdG7iPBM1vqhUKIvfM= github.com/hashicorp/go-msgpack v0.5.4 h1:SFT72YqIkOcLdWJUYcriVX7hbrZpwc/f7h8aW2NUqrA= github.com/hashicorp/go-msgpack v0.5.4/go.mod h1:ahLV/dePpqEmjfWmKiqvPkv/twdG7iPBM1vqhUKIvfM= +github.com/hashicorp/go-msgpack v0.5.5 h1:i9R9JSrqIz0QVLz3sz+i3YJdT7TTSLcfLLzJi9aZTuI= +github.com/hashicorp/go-msgpack v0.5.5/go.mod h1:ahLV/dePpqEmjfWmKiqvPkv/twdG7iPBM1vqhUKIvfM= github.com/hashicorp/go-multierror v1.0.0 h1:iVjPR7a6H0tWELX5NxNe7bYopibicUzc7uPribsnS6o= github.com/hashicorp/go-multierror v1.0.0/go.mod h1:dHtQlpGsu+cZNNAkkCN/P3hoUDHhCYQXV3UM06sGGrk= +github.com/hashicorp/go-plugin v0.0.0-20180331002553-e8d22c780116/go.mod h1:JSqWYsict+jzcj0+xElxyrBQRPNoiWQuddnxArJ7XHQ= github.com/hashicorp/go-plugin v1.0.0 h1:/gQ1sNR8/LHpoxKRQq4PmLBuacfZb4tC93e9B30o/7c= github.com/hashicorp/go-plugin v1.0.0/go.mod h1:++UyYGoz3o5w9ZzAdZxtQKrWWP+iqPBn3cQptSMzBuY= +github.com/hashicorp/go-retryablehttp v0.0.0-20180531211321-3b087ef2d313/go.mod h1:fXcdFsQoipQa7mwORhKad5jmDCeSy/RCGzWA08PO0lM= github.com/hashicorp/go-retryablehttp v0.5.3 h1:QlWt0KvWT0lq8MFppF9tsJGF+ynG7ztc2KIPhzRGk7s= github.com/hashicorp/go-retryablehttp v0.5.3/go.mod h1:9B5zBasrRhHXnJnui7y6sL7es7NDiJgTc6Er0maI1Xs= github.com/hashicorp/go-rootcerts v1.0.0 h1:Rqb66Oo1X/eSV1x66xbDccZjhJigjg0+e82kpwzSwCI= @@ -342,18 +459,23 @@ github.com/hashicorp/go-syslog v1.0.0/go.mod h1:qPfqrKkXGihmCqbJM2mZgkZGvKG1dFdv github.com/hashicorp/go-uuid v1.0.0/go.mod h1:6SBZvOh/SIDV7/2o3Jml5SYk/TvGqwFJ/bN7x4byOro= github.com/hashicorp/go-uuid v1.0.1 h1:fv1ep09latC32wFoVwnqcnKJGnMSdBanPczbHAYm1BE= github.com/hashicorp/go-uuid v1.0.1/go.mod h1:6SBZvOh/SIDV7/2o3Jml5SYk/TvGqwFJ/bN7x4byOro= +github.com/hashicorp/go-version v0.0.0-20170202080759-03c5bf6be031/go.mod h1:fltr4n8CU8Ke44wwGCBoEymUuxUHl09ZGVZPK5anwXA= +github.com/hashicorp/go-version v1.0.0/go.mod h1:fltr4n8CU8Ke44wwGCBoEymUuxUHl09ZGVZPK5anwXA= github.com/hashicorp/go-version v1.1.0 h1:bPIoEKD27tNdebFGGxxYwcL4nepeY4j1QP23PFRGzg0= github.com/hashicorp/go-version v1.1.0/go.mod h1:fltr4n8CU8Ke44wwGCBoEymUuxUHl09ZGVZPK5anwXA= github.com/hashicorp/go-version v1.2.0 h1:3vNe/fWF5CBgRIguda1meWhsZHy3m8gCJ5wx+dIzX/E= github.com/hashicorp/go-version v1.2.0/go.mod h1:fltr4n8CU8Ke44wwGCBoEymUuxUHl09ZGVZPK5anwXA= github.com/hashicorp/go.net v0.0.1 h1:sNCoNyDEvN1xa+X0baata4RdcpKwcMS6DH+xwfqPgjw= github.com/hashicorp/go.net v0.0.1/go.mod h1:hjKkEWcCURg++eb33jQU7oqQcI9XDCnUzHA0oac0k90= +github.com/hashicorp/golang-lru v0.0.0-20180201235237-0fb14efe8c47/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8= github.com/hashicorp/golang-lru v0.5.0 h1:CL2msUPvZTLb5O648aiLNJw3hnBxN2+1Jq8rCOH9wdo= github.com/hashicorp/golang-lru v0.5.0/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8= github.com/hashicorp/golang-lru v0.5.1 h1:0hERBMJE1eitiLkihrMvRVBYAkpHzc/J3QdDN+dAcgU= github.com/hashicorp/golang-lru v0.5.1/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8= +github.com/hashicorp/hcl v0.0.0-20180906183839-65a6292f0157/go.mod h1:E5yfLk+7swimpb2L/Alb/PJmXilQ/rhwaUYs4T20WEQ= github.com/hashicorp/hcl v1.0.0 h1:0Anlzjpi4vEasTeNFn2mLJgTSwt0+6sfsiTG8qcWGx4= github.com/hashicorp/hcl v1.0.0/go.mod h1:E5yfLk+7swimpb2L/Alb/PJmXilQ/rhwaUYs4T20WEQ= +github.com/hashicorp/hil v0.0.0-20160711231837-1e86c6b523c5/go.mod h1:KHvg/R2/dPtaePb16oW4qIyzkMxXOL38xjRN64adsts= github.com/hashicorp/hil v0.0.0-20190212132231-97b3a9cdfa93 h1:T1Q6ag9tCwun16AW+XK3tAql24P4uTGUMIn1/92WsQQ= github.com/hashicorp/hil v0.0.0-20190212132231-97b3a9cdfa93/go.mod h1:n2TSygSNwsLJ76m8qFXTSc7beTb+auJxYdqrnoqwZWE= github.com/hashicorp/logutils v1.0.0 h1:dLEQVugN8vlakKOUE3ihGLTZJRB4j+M2cdTm/ORI65Y= @@ -364,18 +486,24 @@ github.com/hashicorp/mdns v1.0.1 h1:XFSOubp8KWB+Jd2PDyaX5xUd5bhSP/+pTDZVDMzZJM8= github.com/hashicorp/mdns v1.0.1/go.mod h1:4gW7WsVCke5TE7EPeYliwHlRUyBtfCwuFwuMg2DmyNY= github.com/hashicorp/memberlist v0.1.3 h1:EmmoJme1matNzb+hMpDuR/0sbJSUisxyqBGG676r31M= github.com/hashicorp/memberlist v0.1.3/go.mod h1:ajVTdAv/9Im8oMAAj5G31PhhMCZJV2pPBoIllUwCN7I= +github.com/hashicorp/memberlist v0.1.4 h1:gkyML/r71w3FL8gUi74Vk76avkj/9lYAY9lvg0OcoGs= +github.com/hashicorp/memberlist v0.1.4/go.mod h1:ajVTdAv/9Im8oMAAj5G31PhhMCZJV2pPBoIllUwCN7I= github.com/hashicorp/net-rpc-msgpackrpc v0.0.0-20151116020338-a14192a58a69 h1:lc3c72qGlIMDqQpQH82Y4vaglRMMFdJbziYWriR4UcE= github.com/hashicorp/net-rpc-msgpackrpc v0.0.0-20151116020338-a14192a58a69/go.mod h1:/z+jUGRBlwVpUZfjute9jWaF6/HuhjuFQuL1YXzVD1Q= github.com/hashicorp/nomad/api v0.0.0-20190422193122-09c998a4a160 h1:3a/eASHSEdXV9ghYxoZj8DJ52/9Wp22Ers70lxB/vnU= github.com/hashicorp/nomad/api v0.0.0-20190422193122-09c998a4a160/go.mod h1:BDngVi1f4UA6aJq9WYTgxhfWSE1+42xshvstLU2fRGk= +github.com/hashicorp/nomad/api v0.0.0-20190522160243-df84e07c1a46/go.mod h1:BDngVi1f4UA6aJq9WYTgxhfWSE1+42xshvstLU2fRGk= +github.com/hashicorp/raft v1.0.1-0.20190409200437-d9fe23f7d472/go.mod h1:DVSAWItjLjTOkVbSpWQ0j0kUADIvDaCtBxIcbNAQLkI= github.com/hashicorp/raft v1.0.1 h1:94uRdS11oEneUkxmXq6Vg9shNhBILh2UTb9crQjJWl0= github.com/hashicorp/raft v1.0.1/go.mod h1:DVSAWItjLjTOkVbSpWQ0j0kUADIvDaCtBxIcbNAQLkI= +github.com/hashicorp/raft-boltdb v0.0.0-20150201200839-d1e82c1ec3f1/go.mod h1:pNv7Wc3ycL6F5oOWn+tPGo2gWD4a5X+yp/ntwdKLjRk= github.com/hashicorp/raft-boltdb v0.0.0-20171010151810-6e5ba93211ea h1:xykPFhrBAS2J0VBzVa5e80b5ZtYuNQtgXjN40qBZlD4= github.com/hashicorp/raft-boltdb v0.0.0-20171010151810-6e5ba93211ea/go.mod h1:pNv7Wc3ycL6F5oOWn+tPGo2gWD4a5X+yp/ntwdKLjRk= github.com/hashicorp/serf v0.8.2 h1:YZ7UKsJv+hKjqGVUUbtE3HNj79Eln2oQ75tniF6iPt0= github.com/hashicorp/serf v0.8.2/go.mod h1:6hOLApaqBFA1NXqRQAsxw9QxuDEvNxSQRwA/JwenrHc= github.com/hashicorp/serf v0.8.3 h1:MWYcmct5EtKz0efYooPcL0yNkem+7kWxqXDi/UIh+8k= github.com/hashicorp/serf v0.8.3/go.mod h1:UpNcs7fFbpKIyZaUuSW6EPiH+eZC7OuyFD+wc1oal+k= +github.com/hashicorp/vault v0.10.3/go.mod h1:KfSyffbKxoVyspOdlaGVjIuwLobi07qD1bAbosPMpP0= github.com/hashicorp/vault v1.1.2 h1:NDaWEwrTwjg3VKrKQmQykuiq4UqMUlbqloRvIX5fhns= github.com/hashicorp/vault v1.1.2/go.mod h1:KfSyffbKxoVyspOdlaGVjIuwLobi07qD1bAbosPMpP0= github.com/hashicorp/vault-plugin-auth-alicloud v0.5.1 h1:CldlLfMGlcXy+5CvnNsOWJjE9/C1i+Nho4ClSJe+63k= @@ -400,14 +528,17 @@ github.com/hashicorp/vault-plugin-secrets-gcp v0.5.2 h1:oH5EVMJCOHb81Ib9E7/ps1Wr github.com/hashicorp/vault-plugin-secrets-gcp v0.5.2/go.mod h1:2VjVlKHTwqvcVCkZBhYks+HASDzQ4/bIsJoOpO2YJFY= github.com/hashicorp/vault-plugin-secrets-gcpkms v0.5.1 h1:v25YWb7eMPe9DjGsUexRRuWwPlFNh+lbEGOeNrZalf8= github.com/hashicorp/vault-plugin-secrets-gcpkms v0.5.1/go.mod h1:seBkt6x33ZT20koMcUwV/viMomnXDipsLgK5KUKz2ik= +github.com/hashicorp/vault-plugin-secrets-kv v0.0.0-20190318174639-195e0e9d07f1/go.mod h1:VJHHT2SC1tAPrfENQeBhLlb5FbZoKZM+oC/ROmEftz0= github.com/hashicorp/vault-plugin-secrets-kv v0.5.1 h1:awaZ/UoeiDD0j3xF1E0kmXWJvAZw8ULayQu46mB6Un4= github.com/hashicorp/vault-plugin-secrets-kv v0.5.1/go.mod h1:PIjaafaRr2QlkGl2SNhIywxlejeW0iMUtmx8u9u/a6c= github.com/hashicorp/vault/api v1.0.1 h1:YQI4SgOlkmbEKZI8ZClo6fm9oXlBHJUlrbEtFiRPrng= github.com/hashicorp/vault/api v1.0.1/go.mod h1:AV/+M5VPDpB90arloVX0rVDUIHkONiwz5Uza9HRtpUE= +github.com/hashicorp/vault/api v1.0.2/go.mod h1:AV/+M5VPDpB90arloVX0rVDUIHkONiwz5Uza9HRtpUE= github.com/hashicorp/vault/sdk v0.1.8 h1:pfF3KwA1yPlfpmcumNsFM4uo91WMasX5gTuIkItu9r0= github.com/hashicorp/vault/sdk v0.1.8/go.mod h1:tHZfc6St71twLizWNHvnnbiGFo1aq0eD2jGPLtP8kAU= github.com/hashicorp/vault/sdk v0.1.9 h1:GkHLrt3ZU8j/ATmbLqW5P/frBCxPhCRC6nLD0kDP/yc= github.com/hashicorp/vault/sdk v0.1.9/go.mod h1:tHZfc6St71twLizWNHvnnbiGFo1aq0eD2jGPLtP8kAU= +github.com/hashicorp/vault/sdk v0.1.11/go.mod h1:XF2Bod+ahPWGARnyFq5LfkOZwWwvveR5ptYwJLqK0ZI= github.com/hashicorp/vic v1.5.1-0.20190403131502-bbfe86ec9443 h1:O/pT5C1Q3mVXMyuqg7yuAWUg/jMZR1/0QTzTRdNR6Uw= github.com/hashicorp/vic v1.5.1-0.20190403131502-bbfe86ec9443/go.mod h1:bEpDU35nTu0ey1EXjwNwPjI9xErAsoOCmcMb9GKvyxo= github.com/hashicorp/yamux v0.0.0-20180604194846-3520598351bb/go.mod h1:+NfK9FKeTrX5uv1uIXGdwYDTeHna2qgaIlx54MXqjAM= @@ -425,10 +556,14 @@ github.com/jarcoal/httpmock v0.0.0-20180424175123-9c70cfe4a1da h1:FjHUJJ7oBW4G/9 github.com/jarcoal/httpmock v0.0.0-20180424175123-9c70cfe4a1da/go.mod h1:ks+b9deReOc7jgqp+e7LuFiCBH6Rm5hL32cLcEAArb4= github.com/jarcoal/httpmock v1.0.3 h1:Qgv39cyHvgEguAofjb5GomnBCm10Dq71K+k1Aq0h7/o= github.com/jarcoal/httpmock v1.0.3/go.mod h1:ATjnClrvW/3tijVmpL/va5Z3aAyGvqU3gCT8nX0Txik= +github.com/jarcoal/httpmock v1.0.4/go.mod h1:ATjnClrvW/3tijVmpL/va5Z3aAyGvqU3gCT8nX0Txik= github.com/jeffchao/backoff v0.0.0-20140404060208-9d7fd7aa17f2 h1:mex1izRBCD+7WjieGgRdy7e651vD/lvB1bD9vNE/3K4= github.com/jeffchao/backoff v0.0.0-20140404060208-9d7fd7aa17f2/go.mod h1:xkfESuHriIekR+4RoV+fu91j/CfnYM29Zi2tMFw5iD4= +github.com/jefferai/jsonx v0.0.0-20160721235117-9cc31c3135ee/go.mod h1:N0t2vlmpe8nyZB5ouIbJQPDSR+mH6oe7xHB9VZHSUzM= github.com/jefferai/jsonx v1.0.0 h1:Xoz0ZbmkpBvED5W9W1B5B/zc3Oiq7oXqiW7iRV3B6EI= github.com/jefferai/jsonx v1.0.0/go.mod h1:OGmqmi2tTeI/PS+qQfBDToLHHJIy/RMp24fPo8vFvoQ= +github.com/jimstudt/http-authentication v0.0.0-20140401203705-3eca13d6893a/go.mod h1:wK6yTYYcgjHE1Z1QtXACPDjcFJyBskHEdagmnq3vsP8= +github.com/jmespath/go-jmespath v0.0.0-20151117175822-3433f3ea46d9/go.mod h1:Nht3zPeWKUH0NzdCt2Blrr5ys8VGpn0CEB0cQHVjt7k= github.com/jmespath/go-jmespath v0.0.0-20160202185014-0b12d6b521d8 h1:12VvqtR6Aowv3l/EQUlocDHW2Cp4G9WJVH7uyH8QFJE= github.com/jmespath/go-jmespath v0.0.0-20160202185014-0b12d6b521d8/go.mod h1:Nht3zPeWKUH0NzdCt2Blrr5ys8VGpn0CEB0cQHVjt7k= github.com/jmespath/go-jmespath v0.0.0-20180206201540-c2b33e8439af h1:pmfjZENx5imkbgOkpRUYLnmbU7UEFbjtDA2hxJ1ichM= @@ -439,6 +574,7 @@ github.com/joyent/triton-go v0.0.0-20180628001255-830d2b111e62 h1:JHCT6xuyPUrbbg github.com/joyent/triton-go v0.0.0-20180628001255-830d2b111e62/go.mod h1:U+RSyWxWd04xTqnuOQxnai7XGS2PrPY2cfGoDKtMHjA= github.com/joyent/triton-go v0.0.0-20190112182421-51ffac552869 h1:BvV6PYcRz0yGnWXNZrd5wginNT1GfFfPvvWpPbjfFL8= github.com/joyent/triton-go v0.0.0-20190112182421-51ffac552869/go.mod h1:U+RSyWxWd04xTqnuOQxnai7XGS2PrPY2cfGoDKtMHjA= +github.com/json-iterator/go v0.0.0-20180612202835-f2b4162afba3/go.mod h1:+SdeFBvtyEkXs7REEP0seUULqWtbJapLOCVDaaPEHmU= github.com/json-iterator/go v0.0.0-20180701071628-ab8a2e0c74be/go.mod h1:+SdeFBvtyEkXs7REEP0seUULqWtbJapLOCVDaaPEHmU= github.com/json-iterator/go v1.1.5 h1:gL2yXlmiIo4+t+y32d4WGwOjKGYcGOuyrg46vadswDE= github.com/json-iterator/go v1.1.5/go.mod h1:+SdeFBvtyEkXs7REEP0seUULqWtbJapLOCVDaaPEHmU= @@ -450,10 +586,14 @@ github.com/jtolds/gls v4.2.1+incompatible/go.mod h1:QJZ7F/aHp+rZTRtaJ1ow/lLfFfVY github.com/jtolds/gls v4.20.0+incompatible h1:xdiiI2gbIgH/gLH7ADydsJ1uDOEzR8yvV7C0MuV77Wo= github.com/jtolds/gls v4.20.0+incompatible/go.mod h1:QJZ7F/aHp+rZTRtaJ1ow/lLfFfVYBRgL+9YlvaHOwJU= github.com/julienschmidt/httprouter v1.2.0/go.mod h1:SYymIcj16QtmaHHD7aYtjjsJG7VTCxuUUipMqKk8s4w= +github.com/keybase/go-crypto v0.0.0-20180614160407-5114a9a81e1b/go.mod h1:ghbZscTyKdM07+Fw3KSi0hcJm+AlEUWj8QLlPtijN/M= github.com/keybase/go-crypto v0.0.0-20190416182011-b785b22cc757 h1:rHXu79NFmin5AvIe4JsnfCBGb1qAIlMTX0vnpVnDn7s= github.com/keybase/go-crypto v0.0.0-20190416182011-b785b22cc757/go.mod h1:ghbZscTyKdM07+Fw3KSi0hcJm+AlEUWj8QLlPtijN/M= github.com/kisielk/errcheck v1.1.0/go.mod h1:EZBBE59ingxPouuu3KfxchcWSUPOHkagtvWXihfKN4Q= +github.com/kisielk/errcheck v1.2.0/go.mod h1:/BMXB+zMLi60iA8Vv6Ksmxu/1UDYcXs4uQLJ+jE2L00= github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck= +github.com/klauspost/cpuid v1.2.0/go.mod h1:Pj4uuM528wm8OyEC2QMXAi2YiTZ96dNQPGgoMS4s3ek= +github.com/klauspost/cpuid v1.2.1/go.mod h1:Pj4uuM528wm8OyEC2QMXAi2YiTZ96dNQPGgoMS4s3ek= github.com/konsorten/go-windows-terminal-sequences v1.0.1 h1:mweAR1A6xJ3oS2pRaGiHgQ4OO8tzTaLawm8vnODuwDk= github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= github.com/konsorten/go-windows-terminal-sequences v1.0.2 h1:DB17ag19krx9CFsz4o3enTrPXyIXCl+2iCXH/aMAp9s= @@ -462,13 +602,30 @@ github.com/kr/logfmt v0.0.0-20140226030751-b84e30acd515/go.mod h1:+0opPa2QZZtGFB github.com/kr/pretty v0.1.0 h1:L/CwN0zerZDmRFUapSPitk6f+Q3+0za1rQkzVuMiMFI= github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo= github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= +github.com/kr/pty v1.1.4/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= github.com/kr/text v0.1.0 h1:45sCR5RtlFHMR4UwH9sdQ5TC8v0qDQCHnXt+kaKSTVE= github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= +github.com/kylelemons/godebug v0.0.0-20170820004349-d65d576e9348/go.mod h1:B69LEHPfb2qLo0BaaOLcbitczOKLWTsrBG9LczfCD4k= +github.com/kylelemons/godebug v1.1.0/go.mod h1:9/0rRGxNHcop5bhtWyNeEfOS8JIWk580+fNqagV/RAw= +github.com/lib/pq v0.0.0-20180523175426-90697d60dd84/go.mod h1:5WUZQaWbwv1U+lTReE5YruASi9Al49XbQIvNi/34Woo= github.com/lib/pq v1.1.0 h1:/5u4a+KGJptBRqGzPvYQL9p0d/tPR4S31+Tnzj9lEO4= github.com/lib/pq v1.1.0/go.mod h1:5WUZQaWbwv1U+lTReE5YruASi9Al49XbQIvNi/34Woo= +github.com/lib/pq v1.1.1/go.mod h1:5WUZQaWbwv1U+lTReE5YruASi9Al49XbQIvNi/34Woo= github.com/linode/linodego v0.7.1 h1:4WZmMpSA2NRwlPZcc0+4Gyn7rr99Evk9bnr0B3gXRKE= github.com/linode/linodego v0.7.1/go.mod h1:ga11n3ivecUrPCHN0rANxKmfWBJVkOXfLMZinAbj2sY= +github.com/linode/linodego v0.8.1/go.mod h1:cziNP7pbvE3mXIPneHj0oRY8L1WtGEIKlZ8LANE4eXA= +github.com/lucas-clemente/aes12 v0.0.0-20171027163421-cd47fb39b79f/go.mod h1:JpH9J1c9oX6otFSgdUHwUBUizmKlrMjxWnIAjff4m04= +github.com/lucas-clemente/quic-clients v0.1.0/go.mod h1:y5xVIEoObKqULIKivu+gD/LU90pL73bTdtQjPBvtCBk= +github.com/lucas-clemente/quic-go v0.10.2/go.mod h1:hvaRS9IHjFLMq76puFJeWNfmn+H70QZ/CXoxqw9bzao= +github.com/lucas-clemente/quic-go v0.11.1/go.mod h1:PpMmPfPKO9nKJ/psF49ESTAGQSdfXxlg1otPbEB2nOw= +github.com/lucas-clemente/quic-go-certificates v0.0.0-20160823095156-d2f86524cced/go.mod h1:NCcRLrOTZbzhZvixZLlERbJtDtYsmMw8Jc4vS8Z0g58= +github.com/lyft/protoc-gen-validate v0.0.0-20180911180927-64fcb82c878e/go.mod h1:XbGvPuh87YZc5TdIa2/I4pLk0QoUACkjt2znoq26NVQ= github.com/lyft/protoc-gen-validate v0.0.13/go.mod h1:XbGvPuh87YZc5TdIa2/I4pLk0QoUACkjt2znoq26NVQ= +github.com/lyft/protoc-gen-validate v0.0.14/go.mod h1:XbGvPuh87YZc5TdIa2/I4pLk0QoUACkjt2znoq26NVQ= +github.com/mailru/easyjson v0.0.0-20160728113105-d5b7844b561a/go.mod h1:C1wdFJiN94OJF2b5HbByQZoLdCWB1Yqtg26g4irojpc= +github.com/mailru/easyjson v0.0.0-20180823135443-60711f1a8329/go.mod h1:C1wdFJiN94OJF2b5HbByQZoLdCWB1Yqtg26g4irojpc= +github.com/mailru/easyjson v0.0.0-20190403194419-1ea4449da983/go.mod h1:C1wdFJiN94OJF2b5HbByQZoLdCWB1Yqtg26g4irojpc= +github.com/marten-seemann/qtls v0.2.3/go.mod h1:xzjG7avBwGGbdZ8dTGxlBnLArsVKLvwmjgmPuiQEcYk= github.com/mattbaird/elastigo v0.0.0-20170123220020-2fe47fd29e4b h1:v29yPGHhOqw7VHEnTeQFAth3SsBrmwc8JfuhNY0G34k= github.com/mattbaird/elastigo v0.0.0-20170123220020-2fe47fd29e4b/go.mod h1:5MWrJXKRQyhQdUCF+vu6U5c4nQpg70vW3eHaU0/AYbU= github.com/mattn/go-colorable v0.0.9/go.mod h1:9vuHe8Xs5qXnSaW/c/ABM9alt+Vo+STaOChaDxuIBZU= @@ -481,9 +638,13 @@ github.com/mattn/go-isatty v0.0.5 h1:tHXDdz1cpzGaovsTB+TVB8q90WEokoVmfMqoVcrLUgw github.com/mattn/go-isatty v0.0.5/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hdxcsrc5s= github.com/mattn/go-isatty v0.0.7 h1:UvyT9uN+3r7yLEYSlJsbQGdsaB/a0DlgWP3pql6iwOc= github.com/mattn/go-isatty v0.0.7/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hdxcsrc5s= +github.com/mattn/go-isatty v0.0.8/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hdxcsrc5s= github.com/matttproud/golang_protobuf_extensions v1.0.1 h1:4hp9jkHxhMHkqkrB3Ix0jegS5sx/RkqARlsWZ6pIwiU= github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0= github.com/mholt/caddy v0.11.5/go.mod h1:Wb1PlT4DAYSqOEd03MsqkdkXnTxA8v9pKjdpxbqM1kY= +github.com/mholt/caddy v1.0.0/go.mod h1:PzUpQ3yGCTuEuy0KSxEeB4TZOi3zBZ8BR/zY0RBP414= +github.com/mholt/certmagic v0.5.0/go.mod h1:g4cOPxcjV0oFq3qwpjSA30LReKD8AoIfwAY9VvG35NY= +github.com/mholt/certmagic v0.5.1/go.mod h1:g4cOPxcjV0oFq3qwpjSA30LReKD8AoIfwAY9VvG35NY= github.com/michaelklishin/rabbit-hole v1.5.0 h1:Bex27BiFDsijCM9D0ezSHqyy0kehpYHuNKaPqq/a4RM= github.com/michaelklishin/rabbit-hole v1.5.0/go.mod h1:vvI1uOitYZi0O5HEGXhaWC1XT80Gy+HvFheJ+5Krlhk= github.com/micro/cli v0.0.0-20181223203424-1b0c9793c300/go.mod h1:x9x6qy+tXv17jzYWQup462+j3SIUgDa6vVTzU4IXy/w= @@ -518,8 +679,11 @@ github.com/miekg/dns v1.1.6 h1:jVwb4GDwD65q/gtItR/lIZHjNH93QfeGxZUkzJcW9mc= github.com/miekg/dns v1.1.6/go.mod h1:W1PPwlIAgtquWBMBEV9nkV9Cazfe8ScdGz/Lj7v3Nrg= github.com/miekg/dns v1.1.8 h1:1QYRAKU3lN5cRfLCkPU08hwvLJFhvjP6MqNMmQz6ZVI= github.com/miekg/dns v1.1.8/go.mod h1:W1PPwlIAgtquWBMBEV9nkV9Cazfe8ScdGz/Lj7v3Nrg= +github.com/miekg/dns v1.1.12 h1:WMhc1ik4LNkTg8U9l3hI1LvxKmIL+f1+WV/SZtCbDDA= +github.com/miekg/dns v1.1.12/go.mod h1:W1PPwlIAgtquWBMBEV9nkV9Cazfe8ScdGz/Lj7v3Nrg= github.com/mitchellh/cli v1.0.0 h1:iGBIsUe3+HZ/AD/Vd7DErOt5sU9fa8Uj7A2s1aggv1Y= github.com/mitchellh/cli v1.0.0/go.mod h1:hNIlj7HEI86fIcpObd7a0FcrxTWetlwJDGcceTlRvqc= +github.com/mitchellh/copystructure v0.0.0-20160804032330-cdac8253d00f/go.mod h1:eOsF2yLPlBBJPvD+nhl5QMTBSOBbOph6N7j/IDUw7PY= github.com/mitchellh/copystructure v1.0.0 h1:Laisrj+bAB6b/yJwB5Bt3ITZhGJdqmxquMKeZ+mmkFQ= github.com/mitchellh/copystructure v1.0.0/go.mod h1:SNtv71yrdKgLRyLFxmLdkAbkKEFWgYaq1OVrnRcwhnw= github.com/mitchellh/go-homedir v1.0.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0= @@ -530,6 +694,8 @@ github.com/mitchellh/go-testing-interface v1.0.0 h1:fzU/JVNcaqHQEcVFAKeR41fkiLdI github.com/mitchellh/go-testing-interface v1.0.0/go.mod h1:kRemZodwjscx+RGhAo8eIhFbs2+BFgRtFPeD/KE+zxI= github.com/mitchellh/go-wordwrap v1.0.0/go.mod h1:ZXFpozHsX6DPmq2I0TCekCxypsnAUbP2oI0UX1GXzOo= github.com/mitchellh/gox v0.4.0/go.mod h1:Sd9lOJ0+aimLBi73mGofS1ycjY8lL3uZM3JPS42BGNg= +github.com/mitchellh/gox v1.0.1/go.mod h1:ED6BioOGXMswlXa2zxfh/xdd5QhwYliBFn9V18Ap4z4= +github.com/mitchellh/hashstructure v0.0.0-20170609045927-2bca23e0e452/go.mod h1:QjSHrPWS+BGUVBYkbTZWEnOh3G1DutKwClXU/ABz6AQ= github.com/mitchellh/hashstructure v1.0.0 h1:ZkRJX1CyOoTkar7p/mLS5TZU4nJ1Rn/F8u9dGS02Q3Y= github.com/mitchellh/hashstructure v1.0.0/go.mod h1:QjSHrPWS+BGUVBYkbTZWEnOh3G1DutKwClXU/ABz6AQ= github.com/mitchellh/iochan v1.0.0/go.mod h1:JwYml1nuB7xOzsp52dPpHFffvOCDupsG0QubkSMEySY= @@ -538,27 +704,40 @@ github.com/mitchellh/mapstructure v1.1.2 h1:fmNYVwqnSfB9mZU6OS2O6GsXM+wcskZDuKQz github.com/mitchellh/mapstructure v1.1.2/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y= github.com/mitchellh/pointerstructure v0.0.0-20190323210102-2db4bb651397 h1:GwYLdFxg/9bWW+e6YMWDNrKZ43gbKKkgC9mtmxai4o0= github.com/mitchellh/pointerstructure v0.0.0-20190323210102-2db4bb651397/go.mod h1:k4XwG94++jLVsSiTxo7qdIfXA9pj9EAeo0QsNNJOLZ8= +github.com/mitchellh/pointerstructure v0.0.0-20190430161007-f252a8fd71c8/go.mod h1:k4XwG94++jLVsSiTxo7qdIfXA9pj9EAeo0QsNNJOLZ8= github.com/mitchellh/reflectwalk v1.0.0 h1:9D+8oIskB4VJBN5SFlmc27fSlIBZaov1Wpk/IfikLNY= github.com/mitchellh/reflectwalk v1.0.0/go.mod h1:mSTlrgnPZtwu0c4WaC2kGObEpuNDbx0jmZXqmk4esnw= +github.com/mitchellh/reflectwalk v1.0.1/go.mod h1:mSTlrgnPZtwu0c4WaC2kGObEpuNDbx0jmZXqmk4esnw= github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd h1:TRLaZ9cD/w8PVh93nsPXa1VrQ6jlwL5oN8l14QlcNfg= github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= +github.com/modern-go/reflect2 v0.0.0-20180320133207-05fbef0ca5da/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0= +github.com/modern-go/reflect2 v0.0.0-20180701023420-4b7aa43c6742/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0= github.com/modern-go/reflect2 v1.0.1 h1:9f412s+6RmYXLWZSEzVVgPGK7C2PphHj5RJrvfx9AWI= github.com/modern-go/reflect2 v1.0.1/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0= +github.com/munnerz/goautoneg v0.0.0-20120707110453-a547fc61f48d/go.mod h1:+n7T8mK8HuQTcFwEeznm/DIxMOiR9yIdICNftLE1DvQ= +github.com/munnerz/goautoneg v0.0.0-20190414153302-2ae31c8b6b30/go.mod h1:+n7T8mK8HuQTcFwEeznm/DIxMOiR9yIdICNftLE1DvQ= github.com/mwitkow/go-conntrack v0.0.0-20161129095857-cc309e4a2223/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U= github.com/mxk/go-flowrate v0.0.0-20140419014527-cca7078d478f/go.mod h1:ZdcZmHo+o7JKHSa8/e818NopupXU1YMK5fe1lsApnBw= +github.com/naoina/go-stringutil v0.1.0/go.mod h1:XJ2SJL9jCtBh+P9q5btrd/Ylo8XwT/h1USek5+NqSA0= +github.com/naoina/toml v0.1.1/go.mod h1:NBIhNtsFMo3G2szEBne+bO4gS192HuIYRqfvOWb4i1E= github.com/nicolai86/scaleway-sdk v1.10.2-0.20180628010248-798f60e20bb2 h1:BQ1HW7hr4IVovMwWg0E0PYcyW8CzqDcVmaew9cujU4s= github.com/nicolai86/scaleway-sdk v1.10.2-0.20180628010248-798f60e20bb2/go.mod h1:TLb2Sg7HQcgGdloNxkrmtgDNR9uVYF3lfdFIN4Ro6Sk= +github.com/oklog/run v0.0.0-20180308005104-6934b124db28/go.mod h1:dlhp/R75TPv97u0XWUtDeV/lRKWPKSdTuV0TZvrmrQA= github.com/oklog/run v1.0.0 h1:Ru7dDtJNOyC66gQ5dQmaCa0qIsAUFY3sFpK1Xk8igrw= github.com/oklog/run v1.0.0/go.mod h1:dlhp/R75TPv97u0XWUtDeV/lRKWPKSdTuV0TZvrmrQA= +github.com/oklog/ulid v1.3.1/go.mod h1:CirwcVhetQ6Lv90oh/F+FBtV6XMibvdAFo93nm5qn4U= +github.com/onsi/ginkgo v0.0.0-20170829012221-11459a886d9c/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= github.com/onsi/ginkgo v1.6.0 h1:Ix8l273rp3QzYgXSR+c8d1fTG7UPgYkOSELPhiY/YGw= github.com/onsi/ginkgo v1.6.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= github.com/onsi/ginkgo v1.7.0 h1:WSHQ+IS43OoUrWtD1/bbclrwK8TTH5hzp+umCiuxHgs= github.com/onsi/ginkgo v1.7.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= github.com/onsi/ginkgo v1.8.0 h1:VkHVNpR4iVnU8XQR6DBm8BqYjN7CRzw+xKUbVVbbW9w= github.com/onsi/ginkgo v1.8.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= +github.com/onsi/gomega v0.0.0-20170829124025-dcabb60a477c/go.mod h1:C1qb7wdrVGGVU+Z6iS04AVkA3Q65CEZX59MT0QO5uiA= github.com/onsi/gomega v0.0.0-20190113212917-5533ce8a0da3/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1CpauHY= github.com/onsi/gomega v1.4.1 h1:PZSj/UFNaVp3KxrzHOcS7oyuWA7LoOY/77yCTEFu21U= github.com/onsi/gomega v1.4.1/go.mod h1:C1qb7wdrVGGVU+Z6iS04AVkA3Q65CEZX59MT0QO5uiA= +github.com/onsi/gomega v1.4.2/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1CpauHY= github.com/onsi/gomega v1.4.3 h1:RE1xgDvH7imwFD45h+u2SgIfERHlS2yNG4DObb5BSKU= github.com/onsi/gomega v1.4.3/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1CpauHY= github.com/onsi/gomega v1.5.0 h1:izbySO9zDPmjJ8rDjLvkA2zJHIo+HkYXHnf7eN7SSyo= @@ -577,6 +756,7 @@ github.com/opentracing/opentracing-go v1.1.0/go.mod h1:UkNAQd3GIcIGf0SeVgPpRdFSt github.com/openzipkin/zipkin-go v0.1.3/go.mod h1:NtoC/o8u3JlF1lSlyPNswIbeQH9bJTmOf0Erfk+hxe8= github.com/openzipkin/zipkin-go v0.1.6/go.mod h1:QgAqvLzwWbR/WpD4A3cGpPtJrZXNIiJc5AZX7/PBEpw= github.com/openzipkin/zipkin-go-opentracing v0.3.4/go.mod h1:js2AbwmHW0YD9DwIw2JhQWmbfFi/UnWyYwdVhqbCDOE= +github.com/openzipkin/zipkin-go-opentracing v0.3.5/go.mod h1:js2AbwmHW0YD9DwIw2JhQWmbfFi/UnWyYwdVhqbCDOE= github.com/ory-am/common v0.4.0 h1:edGPoxYX4hno0IJHXh9TCMUPR6ZcJp+y6aClFYxeuUE= github.com/ory-am/common v0.4.0/go.mod h1:oCYGuwwM8FyYMKqh9vrhBaeUoyz/edx0bgJN6uS6/+k= github.com/ory/dockertest v3.3.4+incompatible h1:VrpM6Gqg7CrPm3bL4Wm1skO+zFWLbh7/Xb5kGEbJRh8= @@ -587,17 +767,22 @@ github.com/pascaldekloe/goe v0.0.0-20180627143212-57f6aae5913c h1:Lgl0gzECD8GnQ5 github.com/pascaldekloe/goe v0.0.0-20180627143212-57f6aae5913c/go.mod h1:lzWF7FIEvWOWxwDKqyGYQf6ZUaNfKdP144TG7ZOy1lc= github.com/pascaldekloe/goe v0.1.0 h1:cBOtyMzM9HTpWjXfbbunk26uA6nG3a8n06Wieeh0MwY= github.com/pascaldekloe/goe v0.1.0/go.mod h1:lzWF7FIEvWOWxwDKqyGYQf6ZUaNfKdP144TG7ZOy1lc= +github.com/patrickmn/go-cache v0.0.0-20180527043350-9f6ff22cfff8/go.mod h1:3Qf8kWWT7OJRJbdiICTKqZju1ZixQ/KpMGzzAfe6+WQ= github.com/patrickmn/go-cache v2.1.0+incompatible h1:HRMgzkcYKYpi3C8ajMPV8OFXaaRUnok+kx1WdO15EQc= github.com/patrickmn/go-cache v2.1.0+incompatible/go.mod h1:3Qf8kWWT7OJRJbdiICTKqZju1ZixQ/KpMGzzAfe6+WQ= github.com/pborman/uuid v1.2.0 h1:J7Q5mO4ysT1dv8hyrUGHb9+ooztCXu1D8MY8DZYsu3g= github.com/pborman/uuid v1.2.0/go.mod h1:X/NO0urCmaxf9VXbdlT7C2Yzkj2IKimNn4k+gtPdI/k= github.com/peterbourgon/diskv v2.0.1+incompatible h1:UBdAOUP5p4RWqPBg048CAvpKN+vxiaj6gdUUzhl4XmI= github.com/peterbourgon/diskv v2.0.1+incompatible/go.mod h1:uqqh8zWWbv1HBMNONnaR/tNboyR3/BZd58JJSHlUSCU= +github.com/pierrec/lz4 v0.0.0-20190327172049-315a67e90e41/go.mod h1:3/3N9NVKO0jef7pBehbT1qWhCMrIgbYNnFAZCqQ5LRc= github.com/pierrec/lz4 v2.0.5+incompatible h1:2xWsjqPFWcplujydGg4WmhC/6fZqK42wMM8aXeqhl0I= github.com/pierrec/lz4 v2.0.5+incompatible/go.mod h1:pdkljMzZIN41W+lC3N2tnIh5sFi+IEE17M5jbnwPHcY= github.com/pkg/errors v0.8.0/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= github.com/pkg/errors v0.8.1 h1:iURUrRGxPUNPdy5/HRSm+Yj6okJ6UtLINN0Q9M4+h3I= github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= +github.com/pkg/profile v1.2.1/go.mod h1:hJw3o1OdXxsrSjjVksARp5W95eeEaEfptyVZyv6JUPA= +github.com/pkg/profile v1.3.0/go.mod h1:hJw3o1OdXxsrSjjVksARp5W95eeEaEfptyVZyv6JUPA= +github.com/pmezard/go-difflib v0.0.0-20151028094244-d8ed2627bdf0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= github.com/posener/complete v1.1.1/go.mod h1:em0nMJCgc9GFtwrmVmEMR/ZL6WyhyjMBndrE9hABlRI= @@ -607,23 +792,31 @@ github.com/pquerna/cachecontrol v0.0.0-20180517163645-1555304b9b35 h1:J9b7z+QKAm github.com/pquerna/cachecontrol v0.0.0-20180517163645-1555304b9b35/go.mod h1:prYjPmNq4d1NPVmpShWobRqXY3q7Vp+80DqgxxUrUIA= github.com/pquerna/otp v1.1.0 h1:q2gMsMuMl3JzneUaAX1MRGxLvOG6bzXV51hivBaStf0= github.com/pquerna/otp v1.1.0/go.mod h1:Zad1CMQfSQZI5KLpahDiSUX4tMMREnXw98IvL1nhgMk= +github.com/prometheus/client_golang v0.0.0-20180328130430-f504d69affe1/go.mod h1:7SWBe2y4D6OKWSNQJUaRYU/AaXPKyh/dDVn+NZz0KFw= github.com/prometheus/client_golang v0.9.1/go.mod h1:7SWBe2y4D6OKWSNQJUaRYU/AaXPKyh/dDVn+NZz0KFw= github.com/prometheus/client_golang v0.9.2 h1:awm861/B8OKDd2I/6o1dy3ra4BamzKhYOiGItCeZ740= github.com/prometheus/client_golang v0.9.2/go.mod h1:OsXs2jCmiKlQ1lTBmv21f2mNfw4xf/QclQDMrYNZzcM= github.com/prometheus/client_golang v0.9.3-0.20190127221311-3c4408c8b829 h1:D+CiwcpGTW6pL6bv6KI3KbyEyCKyS+1JWS2h8PNDnGA= github.com/prometheus/client_golang v0.9.3-0.20190127221311-3c4408c8b829/go.mod h1:p2iRAGwDERtqlqzRXnrOVns+ignqQo//hLXqYxZYVNs= +github.com/prometheus/client_golang v0.9.3/go.mod h1:/TN21ttK/J9q6uSwhBd54HahCDft0ttaMvbicHlPoso= +github.com/prometheus/client_model v0.0.0-20171117100541-99fa1f4be8e5/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo= github.com/prometheus/client_model v0.0.0-20180712105110-5c3871d89910 h1:idejC8f05m9MGOsuEi1ATq9shN03HrxNkD/luQvxCv8= github.com/prometheus/client_model v0.0.0-20180712105110-5c3871d89910/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo= github.com/prometheus/client_model v0.0.0-20190115171406-56726106282f h1:BVwpUVJDADN2ufcGik7W992pyps0wZ888b/y9GXcLTU= github.com/prometheus/client_model v0.0.0-20190115171406-56726106282f/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo= github.com/prometheus/client_model v0.0.0-20190129233127-fd36f4220a90 h1:S/YWwWx/RA8rT8tKFRuGUZhuA90OyIBpPCXkcbwU8DE= github.com/prometheus/client_model v0.0.0-20190129233127-fd36f4220a90/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= +github.com/prometheus/common v0.0.0-20180326160409-38c53a9f4bfc/go.mod h1:daVV7qP5qjZbuso7PdcryaAu0sAZbrN9i7WWcTMWvro= +github.com/prometheus/common v0.0.0-20181113130724-41aa239b4cce/go.mod h1:daVV7qP5qjZbuso7PdcryaAu0sAZbrN9i7WWcTMWvro= github.com/prometheus/common v0.0.0-20181126121408-4724e9255275 h1:PnBWHBf+6L0jOqq0gIVUe6Yk0/QMZ640k6NvkxcBf+8= github.com/prometheus/common v0.0.0-20181126121408-4724e9255275/go.mod h1:daVV7qP5qjZbuso7PdcryaAu0sAZbrN9i7WWcTMWvro= github.com/prometheus/common v0.2.0 h1:kUZDBDTdBVBYBj5Tmh2NZLlF60mfjA27rM34b+cVwNU= github.com/prometheus/common v0.2.0/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y86RQel1bk4= github.com/prometheus/common v0.3.0 h1:taZ4h8Tkxv2kNyoSctBvfXEHmBmxrwmIidZTIaHons4= github.com/prometheus/common v0.3.0/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y86RQel1bk4= +github.com/prometheus/common v0.4.0/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y86RQel1bk4= +github.com/prometheus/common v0.4.1/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y86RQel1bk4= +github.com/prometheus/procfs v0.0.0-20180408092902-8b1c2da0d56d/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk= github.com/prometheus/procfs v0.0.0-20181005140218-185b4288413d/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk= github.com/prometheus/procfs v0.0.0-20181204211112-1dc9a6cbc91a h1:9a8MnZMP0X2nLJdBg+pBmGgkJlSaKC2KaQmTCk1XDtE= github.com/prometheus/procfs v0.0.0-20181204211112-1dc9a6cbc91a/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk= @@ -631,12 +824,20 @@ github.com/prometheus/procfs v0.0.0-20190117184657-bf6a532e95b1 h1:/K3IL0Z1quvmJ github.com/prometheus/procfs v0.0.0-20190117184657-bf6a532e95b1/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk= github.com/prometheus/procfs v0.0.0-20190416084830-8368d24ba045 h1:Raos9GP+3BlCBicScEQ+SjTLpYYac34fZMoeqj9McSM= github.com/prometheus/procfs v0.0.0-20190416084830-8368d24ba045/go.mod h1:TjEm7ze935MbeOT/UhFTIMYKhuLP4wbCsTZCD3I8kEA= +github.com/prometheus/procfs v0.0.0-20190507164030-5867b95ac084/go.mod h1:TjEm7ze935MbeOT/UhFTIMYKhuLP4wbCsTZCD3I8kEA= +github.com/prometheus/procfs v0.0.0-20190522114515-bc1a522cf7b1/go.mod h1:TjEm7ze935MbeOT/UhFTIMYKhuLP4wbCsTZCD3I8kEA= +github.com/prometheus/tsdb v0.7.1/go.mod h1:qhTCs0VvXwvX/y3TZrWD7rabWM+ijKTux40TwIPHuXU= +github.com/prometheus/tsdb v0.8.0/go.mod h1:fSI0j+IUQrDd7+ZtR9WKIGtoYAYAJUKcKhYLG25tN4g= github.com/rcrowley/go-metrics v0.0.0-20181016184325-3113b8401b8a/go.mod h1:bCqnVzQkZxMG4s8nGwiZ5l3QUCyqpo9Y+/ZMZ9VjZe4= github.com/renier/xmlrpc v0.0.0-20170708154548-ce4a1a486c03 h1:Wdi9nwnhFNAlseAOekn6B5G/+GMtks9UKbvRU/CMM/o= github.com/renier/xmlrpc v0.0.0-20170708154548-ce4a1a486c03/go.mod h1:gRAiPF5C5Nd0eyyRdqIu9qTiFSoZzpTq727b5B8fkkU= github.com/rogpeppe/fastuuid v0.0.0-20150106093220-6724a57986af/go.mod h1:XWv6SoW27p1b0cqNHllgS5HIMJraePCO15w5zCzIWYg= +github.com/rogpeppe/fastuuid v1.1.0/go.mod h1:jVj6XXZzXRy/MSR5jhDC/2q6DgLz+nrA6LYCDYWNEvQ= +github.com/russross/blackfriday v0.0.0-20170610170232-067529f716f4/go.mod h1:JO/DiYxRf+HjHt06OyowR9PTA263kcR/rfWxYHBV53g= +github.com/russross/blackfriday v2.0.0+incompatible/go.mod h1:JO/DiYxRf+HjHt06OyowR9PTA263kcR/rfWxYHBV53g= github.com/ryanuber/columnize v0.0.0-20160712163229-9b3edd62028f/go.mod h1:sm1tb6uqfes/u+d4ooFouqFdy9/2g9QGwK3SQygK0Ts= github.com/ryanuber/columnize v2.1.0+incompatible/go.mod h1:sm1tb6uqfes/u+d4ooFouqFdy9/2g9QGwK3SQygK0Ts= +github.com/ryanuber/go-glob v0.0.0-20170128012129-256dc444b735/go.mod h1:807d1WSdnB0XRJzKNil9Om6lcp/3a0v4qIHxIXzX/Yc= github.com/ryanuber/go-glob v1.0.0 h1:iQh3xXAumdQ+4Ufa5b25cRpC5TYKlno6hsv6Cb3pkBk= github.com/ryanuber/go-glob v1.0.0/go.mod h1:807d1WSdnB0XRJzKNil9Om6lcp/3a0v4qIHxIXzX/Yc= github.com/samuel/go-zookeeper v0.0.0-20180130194729-c4fab1ac1bec h1:6ncX5ko6B9LntYM0YBRXkiSaZMmLYeZ/NWcmeB43mMY= @@ -645,6 +846,7 @@ github.com/satori/go.uuid v1.2.0 h1:0uYX9dsZ2yD7q2RtLRtPSdGDWzjeM3TbMJP9utgA0ww= github.com/satori/go.uuid v1.2.0/go.mod h1:dA0hQrYB0VpLJoorglMZABFdXlWrHn1NEOzdhQKdks0= github.com/sean-/seed v0.0.0-20170313163322-e2103e2c3529 h1:nn5Wsu0esKSJiIVhscUtVbo7ada43DJhG55ua/hjS5I= github.com/sean-/seed v0.0.0-20170313163322-e2103e2c3529/go.mod h1:DxrIzT+xaE7yg65j358z/aeFdxmN0P9QXhEzd20vsDc= +github.com/shirou/gopsutil v0.0.0-20181107111621-48177ef5f880/go.mod h1:5b4v6he4MtMOwMlS0TUMTu2PcXUg8+E1lC7eC3UO/RA= github.com/shirou/gopsutil v2.18.12+incompatible h1:1eaJvGomDnH74/5cF4CTmTbLHAriGFsTZppLXDX93OM= github.com/shirou/gopsutil v2.18.12+incompatible/go.mod h1:5b4v6he4MtMOwMlS0TUMTu2PcXUg8+E1lC7eC3UO/RA= github.com/shirou/w32 v0.0.0-20160930032740-bb4de0191aa4 h1:udFKJ0aHUL60LboW/A+DfgoHVedieIzIXE8uylPue0U= @@ -655,6 +857,7 @@ github.com/sirupsen/logrus v1.2.0 h1:juTguoYk5qI21pwyTXY3B3Y5cOTH3ZUyZCg1v/mihuo github.com/sirupsen/logrus v1.2.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPxbbu5VWo= github.com/sirupsen/logrus v1.4.1 h1:GL2rEmy6nsikmW0r8opw9JIRScdMF5hA8cOYLH7In1k= github.com/sirupsen/logrus v1.4.1/go.mod h1:ni0Sbl8bgC9z8RoU9G6nDWqqs/fq4eDPysMBDgk/93Q= +github.com/sirupsen/logrus v1.4.2/go.mod h1:tLMulIdttU9McNUspp0xgXVQah82FyeX6MwdIuYE2rE= github.com/smartystreets/assertions v0.0.0-20180820201707-7c9eb446e3cf h1:6V1qxN6Usn4jy8unvggSJz/NC790tefw8Zdy6OZS5co= github.com/smartystreets/assertions v0.0.0-20180820201707-7c9eb446e3cf/go.mod h1:OnSkiWE9lh6wB0YB77sQom3nweQdgAjqCqsofrRNTgc= github.com/smartystreets/assertions v0.0.0-20180927180507-b2de0cb4f26d h1:zE9ykElWQ6/NYmHa3jpm/yHnI4xSofP+UP6SpjHcSeM= @@ -671,8 +874,13 @@ github.com/softlayer/softlayer-go v0.0.0-20180806151055-260589d94c7d h1:bVQRCxQv github.com/softlayer/softlayer-go v0.0.0-20180806151055-260589d94c7d/go.mod h1:Cw4GTlQccdRGSEf6KiMju767x0NEHE0YIVPJSaXjlsw= github.com/softlayer/softlayer-go v0.0.0-20190415014515-aa510384a41b h1:88dDriC8WlKTaGOzhMKZVqczu9Pp/n4a3dV3SN7RyQA= github.com/softlayer/softlayer-go v0.0.0-20190415014515-aa510384a41b/go.mod h1:Cw4GTlQccdRGSEf6KiMju767x0NEHE0YIVPJSaXjlsw= +github.com/softlayer/softlayer-go v0.0.0-20190508182157-7c592eb2559c/go.mod h1:Cw4GTlQccdRGSEf6KiMju767x0NEHE0YIVPJSaXjlsw= github.com/soheilhy/cmux v0.1.4 h1:0HKaf1o97UwFjHH9o5XsHUOF+tqmdA7KEzXLpiyaw0E= github.com/soheilhy/cmux v0.1.4/go.mod h1:IM3LyeVVIOuxMH7sFAkER9+bJ4dT7Ms6E4xg4kGIyLM= +github.com/spaolacci/murmur3 v0.0.0-20180118202830-f09979ecbc72/go.mod h1:JwIasOWyU6f++ZhiEuf87xNszmSA2myDM2Kzu9HwQUA= +github.com/spaolacci/murmur3 v1.1.0/go.mod h1:JwIasOWyU6f++ZhiEuf87xNszmSA2myDM2Kzu9HwQUA= +github.com/spf13/afero v1.2.2/go.mod h1:9ZxEEn6pIJ8Rxe320qSDBk6AsU0r9pR7Q4OcevTdifk= +github.com/spf13/pflag v0.0.0-20170130214245-9ff6c6923cff/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4= github.com/spf13/pflag v1.0.1/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4= github.com/spf13/pflag v1.0.2 h1:Fy0orTDgHdbnzHcsOgfCN4LtHf0ec3wwtiwJqwvf3Gc= github.com/spf13/pflag v1.0.2/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4= @@ -685,6 +893,7 @@ github.com/stretchr/objx v0.1.1 h1:2vfRuCMp5sSVIDSqO8oNnWJq7mPa6KVP3iPIwFBuy8A= github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/objx v0.2.0 h1:Hbg2NidpLE8veEBkEZTL3CvlkUIVzuU9jDplZO54c48= github.com/stretchr/objx v0.2.0/go.mod h1:qt09Ya8vawLte6SNmTgCsAVtYtaKzEcn8ATUoHMkEqE= +github.com/stretchr/testify v0.0.0-20151208002404-e3a8ff8ce365/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= github.com/stretchr/testify v1.3.0 h1:TivCn/peBQ7UY8ooIcPgZFpTNSz0Q2U6UrFlUfqbe0Q= github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= @@ -696,12 +905,16 @@ github.com/tv42/httpunix v0.0.0-20150427012821-b75d8614f926 h1:G3dpKMzFDjgEh2q1Z github.com/tv42/httpunix v0.0.0-20150427012821-b75d8614f926/go.mod h1:9ESjWnEqriFuLhtthL60Sar/7RFoluCcXsuvEwTV5KM= github.com/ugorji/go v1.1.2 h1:JON3E2/GPW2iDNGoSAusl1KDf5TRQ8k8q7Tp097pZGs= github.com/ugorji/go v1.1.2/go.mod h1:hnLbHMwcvSihnDhEfx2/BzKp2xb0Y+ErdfYcrs9tkJQ= +github.com/ugorji/go v1.1.4/go.mod h1:uQMGLiO92mf5W77hV/PUCpI3pbzQx3CRekS0kk+RGrc= github.com/ugorji/go/codec v0.0.0-20190309163734-c4a1c341dc93 h1:JnDJ9gMf6CfErtoOXnghtY5hhMuDtW4tUBaWSBrqvKs= github.com/ugorji/go/codec v0.0.0-20190309163734-c4a1c341dc93/go.mod h1:iT03XoTwV7xq/+UGwKO3UbC1nNNlopQiY61beSdrtOA= github.com/vmware/govmomi v0.18.0 h1:f7QxSmP7meCtoAmiKZogvVbLInT+CZx6Px6K5rYsJZo= github.com/vmware/govmomi v0.18.0/go.mod h1:URlwyTFZX72RmxtxuaFL2Uj3fD1JTvZdx59bHWk6aFU= github.com/vmware/govmomi v0.20.0 h1:+1IyhvoVb5JET2Wvgw9J3ZDv6CK4sxzUunpH8LhQqm4= github.com/vmware/govmomi v0.20.0/go.mod h1:URlwyTFZX72RmxtxuaFL2Uj3fD1JTvZdx59bHWk6aFU= +github.com/vmware/govmomi v0.20.1/go.mod h1:URlwyTFZX72RmxtxuaFL2Uj3fD1JTvZdx59bHWk6aFU= +github.com/xdg/scram v0.0.0-20180814205039-7eeb5667e42c/go.mod h1:lB8K/P019DLNhemzwFU4jHLhdvlE6uDZjXFejJXr49I= +github.com/xdg/stringprep v1.0.0/go.mod h1:Jhud4/sHMO4oL310DaZAKk9ZaJ08SJfe+sJh0HrGL1Y= github.com/xiang90/probing v0.0.0-20190116061207-43a291ad63a2 h1:eY9dn8+vbi4tKz5Qo6v2eYzo7kUS51QINcR5jNpbZS8= github.com/xiang90/probing v0.0.0-20190116061207-43a291ad63a2/go.mod h1:UETIi67q53MR2AWcXfiuqkDkRtnGDLqkBTpCHuJHxtU= go.etcd.io/bbolt v1.3.2 h1:Z/90sZLPOeCy2PwprqkFa25PdkusRzaj9P8zm/KNyvk= @@ -712,15 +925,19 @@ go.opencensus.io v0.19.2/go.mod h1:NO/8qkisMZLZ1FCsKNqtJPwc8/TaclWyY0B6wcYNg9M= go.opencensus.io v0.20.1/go.mod h1:6WKK9ahsWS3RSO+PY9ZHZUfv2irvY6gN279GOPZjmmk= go.opencensus.io v0.20.2 h1:NAfh7zF0/3/HqtMvJNZ/RFrSlCE6ZTlHmKfhL/Dm1Jk= go.opencensus.io v0.20.2/go.mod h1:6WKK9ahsWS3RSO+PY9ZHZUfv2irvY6gN279GOPZjmmk= +go.opencensus.io v0.21.0/go.mod h1:mSImk1erAIZhrmZN+AvHh14ztQfjbGwt4TtuofqLduU= go.uber.org/atomic v1.3.2 h1:2Oa65PReHzfn29GpvgsYwloV9AVFHPDk8tYxt2c2tr4= go.uber.org/atomic v1.3.2/go.mod h1:gD2HeocX3+yG+ygLZcrzQJaqmWj9AIm7n08wl/qW/PE= +go.uber.org/atomic v1.4.0/go.mod h1:gD2HeocX3+yG+ygLZcrzQJaqmWj9AIm7n08wl/qW/PE= go.uber.org/multierr v1.1.0 h1:HoEmRHQPVSqub6w2z2d2EOVs2fjyFRGyofhKuyDq0QI= go.uber.org/multierr v1.1.0/go.mod h1:wR5kodmAFQ0UK8QlbwjlSNy0Z68gJhDJUG5sjR94q/0= go.uber.org/zap v1.9.1 h1:XCJQEf3W6eZaVwhRBof6ImoYGJSITeKWsyeh3HFu/5o= go.uber.org/zap v1.9.1/go.mod h1:vwi/ZaCAaUcBkycHslxD9B2zi4UTXhF60s6SWpuDF0Q= +go.uber.org/zap v1.10.0/go.mod h1:vwi/ZaCAaUcBkycHslxD9B2zi4UTXhF60s6SWpuDF0Q= golang.org/x/crypto v0.0.0-20180820150726-614d502a4dac/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= golang.org/x/crypto v0.0.0-20180904163835-0709b304e793/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= golang.org/x/crypto v0.0.0-20181029021203-45a5f77698d3/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= +golang.org/x/crypto v0.0.0-20190123085648-057139ce5d2b/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= golang.org/x/crypto v0.0.0-20190130090550-b01c7a725664/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= golang.org/x/crypto v0.0.0-20190211182817-74369b46fc67 h1:ng3VDlRp5/DHpSWl02R4rM9I+8M2rhmsuLwAMmkLQWE= golang.org/x/crypto v0.0.0-20190211182817-74369b46fc67/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= @@ -730,18 +947,31 @@ golang.org/x/crypto v0.0.0-20190228161510-8dd112bcdc25/go.mod h1:djNgcEr1/C05ACk golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= golang.org/x/crypto v0.0.0-20190325154230-a5d413f7728c h1:Vj5n4GlwjmQteupaxJ9+0FNOmBrHfq7vN4btdGoDZgI= golang.org/x/crypto v0.0.0-20190325154230-a5d413f7728c/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= +golang.org/x/crypto v0.0.0-20190404164418-38d8ce5564a5/go.mod h1:WFFai1msRO1wXaEeE5yQxYXgSfI8pQAWXbQop6sCtWE= golang.org/x/crypto v0.0.0-20190422183909-d864b10871cd h1:sMHc2rZHuzQmrbVoSpt9HgerkXPyIeCSO6k0zUMGfFk= golang.org/x/crypto v0.0.0-20190422183909-d864b10871cd/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= +golang.org/x/crypto v0.0.0-20190513172903-22d7a77e9e5f h1:R423Cnkcp5JABoeemiGEPlt9tHXFfw5kvc0yqlxRPWo= +golang.org/x/crypto v0.0.0-20190513172903-22d7a77e9e5f/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= +golang.org/x/exp v0.0.0-20190306152737-a1d7652674e8/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= +golang.org/x/exp v0.0.0-20190510132918-efd6b22b2522/go.mod h1:ZjyILWgesfNpC6sMxTJOJm9Kp84zZh5NQWvqDGG3Qr8= +golang.org/x/image v0.0.0-20190227222117-0694c2d4d067/go.mod h1:kZ7UVZpmo3dzQBMxlp+ypCbDeSB+sBbTgSJuh5dn5js= +golang.org/x/image v0.0.0-20190516052701-61b8692d9a5c/go.mod h1:kZ7UVZpmo3dzQBMxlp+ypCbDeSB+sBbTgSJuh5dn5js= golang.org/x/lint v0.0.0-20180702182130-06c8688daad7/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE= golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE= golang.org/x/lint v0.0.0-20181217174547-8f45f776aaf1/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE= golang.org/x/lint v0.0.0-20190227174305-5b3e6a55c961/go.mod h1:wehouNa3lNwaWXcvxsM5YxQ5yQlVC4a0KAMCusXpPoU= golang.org/x/lint v0.0.0-20190301231843-5614ed5bae6f/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE= golang.org/x/lint v0.0.0-20190313153728-d0100b6bd8b3/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= +golang.org/x/lint v0.0.0-20190409202823-959b441ac422/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= +golang.org/x/mobile v0.0.0-20190312151609-d3739f865fa6/go.mod h1:z+o9i4GpDbdi3rU15maQ/Ox0txvL9dWGYEHz965HBQE= +golang.org/x/mobile v0.0.0-20190509164839-32b2708ab171/go.mod h1:E/iHnbuqvinMTCcRqshq8CkpyQDoeVncDDYHnLhea+o= +golang.org/x/net v0.0.0-20170114055629-f2499483f923/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/net v0.0.0-20180611182652-db08ff08e862/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/net v0.0.0-20181005035420-146acd28ed58/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20181023162649-9b4f9f5ad519/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20181106065722-10aee1819953/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20181114220301-adae6a3d119a/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= @@ -755,9 +985,14 @@ golang.org/x/net v0.0.0-20190213061140-3a22650c66bd/go.mod h1:mL1N/T3taQHkDXs73r golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= golang.org/x/net v0.0.0-20190327214358-63eda1eb0650 h1:XCbwcsP09zrBt1aYht0fASw+ynbEpYr8NnCkIN9nMM0= golang.org/x/net v0.0.0-20190327214358-63eda1eb0650/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= +golang.org/x/net v0.0.0-20190328230028-74de082e2cca/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= +golang.org/x/net v0.0.0-20190403144856-b630fd6fe46b/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= golang.org/x/net v0.0.0-20190420063019-afa5a82059c6 h1:HdqqaWmYAUI7/dmByKKEw+yxDksGSo+9GjkUc9Zp34E= golang.org/x/net v0.0.0-20190420063019-afa5a82059c6/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= +golang.org/x/net v0.0.0-20190503192946-f4e77d36d62c/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= +golang.org/x/net v0.0.0-20190522155817-f3200d17e092 h1:4QSRKanuywn15aTZvI/mIDEgPQpswuFndXpOj3rKEco= +golang.org/x/net v0.0.0-20190522155817-f3200d17e092/go.mod h1:HSz+uSET+XFnRR8LxR5pz3Of3rY3CfYBVs4xY44aLks= golang.org/x/oauth2 v0.0.0-20170807180024-9a379c6b3e95/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be h1:vEDujvNQGv4jgYKudGeI/+DAX4Jffq6hpD55MmoEvKs= golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= @@ -767,6 +1002,7 @@ golang.org/x/oauth2 v0.0.0-20190319182350-c85d3e98c914 h1:jIOcLT9BZzyJ9ce+IwwZ+a golang.org/x/oauth2 v0.0.0-20190319182350-c85d3e98c914/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= golang.org/x/oauth2 v0.0.0-20190402181905-9f3314589c9a h1:tImsplftrFpALCYumobsd0K86vlAs/eXGFms2txfJfA= golang.org/x/oauth2 v0.0.0-20190402181905-9f3314589c9a/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= +golang.org/x/oauth2 v0.0.0-20190517181255-950ef44c6e07/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= @@ -774,6 +1010,7 @@ golang.org/x/sync v0.0.0-20190227155943-e225da77a7e6 h1:bjcUS9ztw9kFmmIxJInhon/0 golang.org/x/sync v0.0.0-20190227155943-e225da77a7e6/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20190423024810-112230192c58 h1:8gQV6CLnAEikrhgkHFbMAEhagSSnXWGV915qUMm9mrU= golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sys v0.0.0-20170830134202-bb24a47a89ea/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20180823144017-11551d06cbcc/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20180828065106-d99a578cf41b/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= @@ -784,6 +1021,7 @@ golang.org/x/sys v0.0.0-20181107165924-66b7b1311ac8/go.mod h1:STP8DvDyc/dI5b8T5h golang.org/x/sys v0.0.0-20181116152217-5ac8a444bdc5/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20181122145206-62eef0e2fa9b/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20181218192612-074acd46bca6/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20190124100055-b90733256f2e/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190129075346-302c3dd5f1cc/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190209173611-3b5209105503/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190213121743-983097b1a8a3 h1:+KlxhGbYkFs8lMfwKn+2ojry1ID5eBSMXprS2u/wqCE= @@ -792,6 +1030,7 @@ golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5h golang.org/x/sys v0.0.0-20190222072716-a9d3bda3a223/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190222171317-cd391775e71e h1:oF7qaQxUH6KzFdKN4ww7NpPdo53SZi4UlcksLrb2y/o= golang.org/x/sys v0.0.0-20190222171317-cd391775e71e/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20190228124157-a34e9553db1e/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190312061237-fead79001313/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190322080309-f49334f85ddc h1:4gbWbmmPFp4ySWICouJl6emP0MyS31yy9SrTlAGFT+g= golang.org/x/sys v0.0.0-20190322080309-f49334f85ddc/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= @@ -800,12 +1039,18 @@ golang.org/x/sys v0.0.0-20190403152447-81d4e9dc473e/go.mod h1:h1NjWce9XRLGQEsW7w golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190422165155-953cdadca894 h1:Cz4ceDQGXuKRnVBDTS23GTn/pU5OE2C0WrNTOYK1Uuc= golang.org/x/sys v0.0.0-20190422165155-953cdadca894/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190508220229-2d0786266e9c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190522044717-8097e1b27ff5 h1:f005F/Jl5JLP036x7QIvUVhNTqxvSYwFIiyOh2q12iU= +golang.org/x/sys v0.0.0-20190522044717-8097e1b27ff5/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/text v0.0.0-20160726164857-2910a502d2bf/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.0 h1:g61tztE5qeGQ89tm6NTjjM9VPIm088od1l6aSorWRWg= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.1-0.20180807135948-17ff2d5776d2 h1:z99zHgr7hKfrUcX/KsoJk5FJfjTceCKIp96+biqP4To= golang.org/x/text v0.3.1-0.20180807135948-17ff2d5776d2/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.1-0.20181227161524-e6919f6577db h1:6/JqlYfC1CCaLnGceQTI+sDGhC9UBSPAsBqI0Gun6kU= golang.org/x/text v0.3.1-0.20181227161524-e6919f6577db/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk= +golang.org/x/text v0.3.2 h1:tW2bmiBqwgJj/UpqtC8EpXEZVYOwU0yG4iWbprSVAcs= +golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk= golang.org/x/time v0.0.0-20180412165947-fbb02b2291d2/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.0.0-20190308202827-9d24e82272b4 h1:SvFZT6jyqRaOeXpc5h/JSfZenJ2O330aBsf7JfSUXmQ= @@ -813,12 +1058,17 @@ golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxb golang.org/x/tools v0.0.0-20180221164845-07fd8470d635/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20180828015842-6cd1fcedba52/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= +golang.org/x/tools v0.0.0-20181011042414-1f849cf54d09/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= +golang.org/x/tools v0.0.0-20181030221726-6c7e314b6563/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20181219222714-6e267b5cc78e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20190114222345-bf090417da8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20190226205152-f727befe758c/go.mod h1:9Yl7xja0Znq3iFh3HoIrodX9oNMXvdceNzlUR8zjMvY= golang.org/x/tools v0.0.0-20190311212946-11955173bddd/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= +golang.org/x/tools v0.0.0-20190312151545-0bb0c0a6e846/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= golang.org/x/tools v0.0.0-20190312170243-e65039ee4138/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= golang.org/x/tools v0.0.0-20190328211700-ab21143f2384/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= +golang.org/x/tools v0.0.0-20190425150028-36563e24a262/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q= +golang.org/x/tools v0.0.0-20190521203540-521d6ed310dd/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q= google.golang.org/api v0.0.0-20180829000535-087779f1d2c9 h1:z1TeLUmxf9ws9KLICfmX+KGXTs+rjm+aGWzfsv7MZ9w= google.golang.org/api v0.0.0-20180829000535-087779f1d2c9/go.mod h1:4mhQ8q/RsB7i+udVvVy5NUi08OU8ZlA0gRVgrF7VFY0= google.golang.org/api v0.0.0-20181220000619-583d854617af/go.mod h1:4mhQ8q/RsB7i+udVvVy5NUi08OU8ZlA0gRVgrF7VFY0= @@ -828,6 +1078,8 @@ google.golang.org/api v0.3.0/go.mod h1:IuvZyQh8jgscv8qWfQ4ABd8m7hEudgBFM/EdhA3Bn google.golang.org/api v0.3.1/go.mod h1:6wY9I6uQWHQ8EM57III9mq/AjF+i8G65rmVagqKMtkk= google.golang.org/api v0.3.2 h1:iTp+3yyl/KOtxa/d1/JUE0GGSoR6FuW5udver22iwpw= google.golang.org/api v0.3.2/go.mod h1:6wY9I6uQWHQ8EM57III9mq/AjF+i8G65rmVagqKMtkk= +google.golang.org/api v0.4.0/go.mod h1:8k5glujaEP+g9n7WNsDg8QP6cUVNI86fCNMcbazEtwE= +google.golang.org/api v0.5.0/go.mod h1:8k5glujaEP+g9n7WNsDg8QP6cUVNI86fCNMcbazEtwE= google.golang.org/appengine v1.1.0 h1:igQkv0AAhEIvTEpD5LIpAfav2eeVO9HBTjvKHVJPRSs= google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM= google.golang.org/appengine v1.2.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= @@ -836,6 +1088,7 @@ google.golang.org/appengine v1.4.0 h1:/wp5JvzpHIxhs/dumFmF7BXTf3Z+dd4uXta4kVyO50 google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= google.golang.org/appengine v1.5.0 h1:KxkO13IPW4Lslp2bz+KHP2E3gtFlrIGNThxkZQ3g+4c= google.golang.org/appengine v1.5.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= +google.golang.org/appengine v1.6.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8 h1:Nw54tB0rB7hY/N0NQvRW8DG4Yk3Q6T9cu9RcFQDu1tc= google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc= google.golang.org/genproto v0.0.0-20181219182458-5a97ab628bfb/go.mod h1:7Ep/1NZk928CDR8SjdVbjWNpdIf6nzjE3BTgJDr2Atg= @@ -845,6 +1098,9 @@ google.golang.org/genproto v0.0.0-20190404172233-64821d5d2107 h1:xtNn7qFlagY2mQN google.golang.org/genproto v0.0.0-20190404172233-64821d5d2107/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= google.golang.org/genproto v0.0.0-20190418145605-e7d98fc518a7 h1:ZUjXAXmrAyrmmCPHgCA/vChHcpsX27MZ3yBonD/z1KE= google.golang.org/genproto v0.0.0-20190418145605-e7d98fc518a7/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= +google.golang.org/genproto v0.0.0-20190508193815-b515fa19cec8/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= +google.golang.org/genproto v0.0.0-20190516172635-bb713bdc0e52/go.mod h1:z3L6/3dTEVtUr6QSP8miRzeRqwQOioJ9I66odjN4I7s= +google.golang.org/grpc v0.0.0-20180920234847-8997b5fa0873/go.mod h1:0JHn/cJsOMiMfNA9+DeHDlAU7KAAB5GDlYFpa9MZMio= google.golang.org/grpc v1.14.0/go.mod h1:yo6s7OP7yaDglbqo1J04qKzAhqBH6lvTonzMVmEdcZw= google.golang.org/grpc v1.16.0/go.mod h1:0JHn/cJsOMiMfNA9+DeHDlAU7KAAB5GDlYFpa9MZMio= google.golang.org/grpc v1.17.0/go.mod h1:6QZJwpn2B+Zp71q/5VxRsJ6NXXVCE5NRUHRo+f3cWCs= @@ -876,12 +1132,18 @@ gopkg.in/inf.v0 v0.9.1 h1:73M5CoZyi3ZLMOyDlQh031Cx6N9NDJ2Vvfl76EDAgDc= gopkg.in/inf.v0 v0.9.1/go.mod h1:cWUDdTG/fYaXco+Dcufb5Vnc6Gp2YChqWtbxRZE0mXw= gopkg.in/ini.v1 v1.42.0 h1:7N3gPTt50s8GuLortA00n8AqRTk75qOP98+mTPpgzRk= gopkg.in/ini.v1 v1.42.0/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k= +gopkg.in/mcuadros/go-syslog.v2 v2.2.1/go.mod h1:l5LPIyOOyIdQquNg+oU6Z3524YwrcqEm0aKH+5zpt2U= +gopkg.in/mgo.v2 v2.0.0-20160818020120-3f83fa500528/go.mod h1:yeKp02qBN3iKW1OzL3MGk2IdtZzaj7SFntXj72NppTA= gopkg.in/mgo.v2 v2.0.0-20180705113604-9856a29383ce h1:xcEWjVhvbDy+nHP67nPDDpbYrY+ILlfndk4bRioVHaU= gopkg.in/mgo.v2 v2.0.0-20180705113604-9856a29383ce/go.mod h1:yeKp02qBN3iKW1OzL3MGk2IdtZzaj7SFntXj72NppTA= +gopkg.in/natefinch/lumberjack.v2 v2.0.0/go.mod h1:l0ndWWf7gzL7RNwBG7wST/UCcT4T24xpD6X8LsfU/+k= gopkg.in/ory-am/dockertest.v2 v2.2.3 h1:vSYvP7tvyfAm9merq0gHmcI4yk5nkPpfXmoBCnSP3/4= gopkg.in/ory-am/dockertest.v2 v2.2.3/go.mod h1:kDHEsan1UcKFYH1c28sDmqnmeqIpB4Nj682gSNhYDYM= +gopkg.in/ory-am/dockertest.v3 v3.3.4/go.mod h1:s9mmoLkaGeAh97qygnNj4xWkiN7e1SKekYC6CovU+ek= +gopkg.in/resty.v1 v1.9.1/go.mod h1:vo52Hzryw9PnPHcJfPsBiFW62XhNx5OczbV9y+IMpgc= gopkg.in/resty.v1 v1.12.0 h1:CuXP0Pjfw9rOuY6EP+UvtNvt5DSqHpIxILZKT/quCZI= gopkg.in/resty.v1 v1.12.0/go.mod h1:mDo4pnntr5jdWRML875a/NmxYqAlA73dVijT2AXvQQo= +gopkg.in/square/go-jose.v2 v2.2.2/go.mod h1:M9dMgbHiYLoDGQrXy7OpJDJWiKiU//h+vD76mk0e1AI= gopkg.in/square/go-jose.v2 v2.3.0 h1:nLzhkFyl5bkblqYBoiWJUt5JkWOzmiaBtCxdJAqJd3U= gopkg.in/square/go-jose.v2 v2.3.0/go.mod h1:M9dMgbHiYLoDGQrXy7OpJDJWiKiU//h+vD76mk0e1AI= gopkg.in/square/go-jose.v2 v2.3.1 h1:SK5KegNXmKmqE342YYN2qPHEnUYeoMiXXl1poUlI+o4= @@ -898,29 +1160,38 @@ honnef.co/go/tools v0.0.0-20180728063816-88497007e858/go.mod h1:rf3lG4BRIbNafJWh honnef.co/go/tools v0.0.0-20180920025451-e3ad64cb4ed3/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= honnef.co/go/tools v0.0.0-20190106161140-3f1c8253044a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= +honnef.co/go/tools v0.0.0-20190522022531-bad1bd262ba8/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= +istio.io/gogo-genproto v0.0.0-20190124151557-6d926a6e6feb/go.mod h1:eIDJ6jNk/IeJz6ODSksHl5Aiczy5JUq6vFhJWI5OtiI= k8s.io/api v0.0.0-20180806132203-61b11ee65332 h1:+ED/2NBbOoeWB9QrGTHxZI7UnE7rnHPKKumOl0WXphs= k8s.io/api v0.0.0-20180806132203-61b11ee65332/go.mod h1:iuAfoD4hCxJ8Onx9kaTIt30j7jUFS00AXQi6QMi99vA= k8s.io/api v0.0.0-20181204000039-89a74a8d264d h1:HQoGWsWUe/FmRcX9BU440AAMnzBFEf+DBo4nbkQlNzs= k8s.io/api v0.0.0-20181204000039-89a74a8d264d/go.mod h1:iuAfoD4hCxJ8Onx9kaTIt30j7jUFS00AXQi6QMi99vA= +k8s.io/api v0.0.0-20190325185214-7544f9db76f6/go.mod h1:iuAfoD4hCxJ8Onx9kaTIt30j7jUFS00AXQi6QMi99vA= k8s.io/api v0.0.0-20190409092523-d687e77c8ae9 h1:c9UEl5z8gk1DGh/g3snETZ+a52YeR9VdbX/3BQ4PHas= k8s.io/api v0.0.0-20190409092523-d687e77c8ae9/go.mod h1:FQEUn50aaytlU65qqBn/w+5ugllHwrBzKm7DzbnXdzE= k8s.io/api v0.0.0-20190419092548-c5cad27821f6 h1:S/8tIFYavaVbM3nFX0yqkw4X0BooJqRO+TrDANFX1Uo= k8s.io/api v0.0.0-20190419092548-c5cad27821f6/go.mod h1:B0cvvXrD9UkqARVdlFhdZB9SNL0TzJ13UB/p410skE4= +k8s.io/api v0.0.0-20190515023547-db5a9d1c40eb/go.mod h1:fbdFiGtx7GQ3+vkBAYto3QsSImiYIJdpH3YfaclST/U= k8s.io/apimachinery v0.0.0-20180821005732-488889b0007f h1:V0PkbgaYp5JqCmzLyRmssDtzim0NShXM8gYi4fcX230= k8s.io/apimachinery v0.0.0-20180821005732-488889b0007f/go.mod h1:ccL7Eh7zubPUSh9A3USN90/OzHNSVN6zxzde07TDCL0= k8s.io/apimachinery v0.0.0-20181127025237-2b1284ed4c93 h1:tT6oQBi0qwLbbZSfDkdIsb23EwaLY85hoAV4SpXfdao= k8s.io/apimachinery v0.0.0-20181127025237-2b1284ed4c93/go.mod h1:ccL7Eh7zubPUSh9A3USN90/OzHNSVN6zxzde07TDCL0= +k8s.io/apimachinery v0.0.0-20190223001710-c182ff3b9841/go.mod h1:ccL7Eh7zubPUSh9A3USN90/OzHNSVN6zxzde07TDCL0= k8s.io/apimachinery v0.0.0-20190409092423-760d1845f48b h1:fVkKJL9FIpA8LSJyHVM00MP45q1WJ7+af77vcxmQP4g= k8s.io/apimachinery v0.0.0-20190409092423-760d1845f48b/go.mod h1:FW86P8YXVLsbuplGMZeb20J3jYHscrDqw4jELaFJvRU= k8s.io/apimachinery v0.0.0-20190418212431-b3683fe6b520/go.mod h1:tXkZEnPhecLuffcJcEuO/iNpM8w0n42dM5fNrr9OVVE= k8s.io/apimachinery v0.0.0-20190419212445-b874eabb9a4e h1:h2UL1ppdZDnaCKNvEFzbRIscOymKZznckYlXgZ3iQME= k8s.io/apimachinery v0.0.0-20190419212445-b874eabb9a4e/go.mod h1:tXkZEnPhecLuffcJcEuO/iNpM8w0n42dM5fNrr9OVVE= +k8s.io/apimachinery v0.0.0-20190515023456-b74e4c97951f/go.mod h1:Ew3b/24/JSgJdn4RsnrLskv3LvMZDlZ1Fl1xopsJftY= k8s.io/client-go v8.0.0+incompatible h1:tTI4hRmb1DRMl4fG6Vclfdi6nTM82oIrTT7HfitmxC4= k8s.io/client-go v8.0.0+incompatible/go.mod h1:7vJpHMYJwNQCWgzmNV+VYUl1zCObLyodBc8nIyt8L5s= k8s.io/client-go v10.0.0+incompatible h1:F1IqCqw7oMBzDkqlcBymRq1450wD0eNqLE9jzUrIi34= k8s.io/client-go v10.0.0+incompatible/go.mod h1:7vJpHMYJwNQCWgzmNV+VYUl1zCObLyodBc8nIyt8L5s= k8s.io/client-go v11.0.0+incompatible h1:LBbX2+lOwY9flffWlJM7f1Ct8V2SRNiMRDFeiwnJo9o= k8s.io/client-go v11.0.0+incompatible/go.mod h1:7vJpHMYJwNQCWgzmNV+VYUl1zCObLyodBc8nIyt8L5s= +k8s.io/gengo v0.0.0-20190128074634-0689ccc1d7d6/go.mod h1:ezvh/TsK7cY6rbqRK0oQQ8IAqLxYwwyPxAX1Pzy0ii0= +k8s.io/gengo v0.0.0-20190327210449-e17681d19d3a/go.mod h1:ezvh/TsK7cY6rbqRK0oQQ8IAqLxYwwyPxAX1Pzy0ii0= +k8s.io/klog v0.0.0-20181102134211-b9b56d5dfc92/go.mod h1:Gq+BEi5rUBO/HRz0bTSXDUcqjScdoY3a9IHpCEIOOfk= k8s.io/klog v0.0.0-20181108234604-8139d8cb77af h1:s6rm8OxBbyDNSRkpyAd5OL4icUdBICVw9+mFADa+t5E= k8s.io/klog v0.0.0-20181108234604-8139d8cb77af/go.mod h1:Gq+BEi5rUBO/HRz0bTSXDUcqjScdoY3a9IHpCEIOOfk= k8s.io/klog v0.0.0-20190306015804-8e90cee79f82 h1:SHucoAy7lRb+w5oC/hbXyZg+zX+Wftn6hD4tGzHCVqA= @@ -929,9 +1200,13 @@ k8s.io/klog v0.3.0 h1:0VPpR+sizsiivjIfIAQH/rl8tan6jvWkS7lU+0di3lE= k8s.io/klog v0.3.0/go.mod h1:Gq+BEi5rUBO/HRz0bTSXDUcqjScdoY3a9IHpCEIOOfk= k8s.io/kube-openapi v0.0.0-20190228160746-b3a7cee44a30/go.mod h1:BXM9ceUBTj2QnfH2MK1odQs778ajze1RxcmP6S8RVVc= k8s.io/kube-openapi v0.0.0-20190306001800-15615b16d372/go.mod h1:BXM9ceUBTj2QnfH2MK1odQs778ajze1RxcmP6S8RVVc= +k8s.io/kube-openapi v0.0.0-20190510232812-a01b7d5d6c22/go.mod h1:iU+ZGYsNlvU9XKUSso6SQfKTCCw7lFduMZy26Mgr2Fw= k8s.io/utils v0.0.0-20190308190857-21c4ce38f2a7 h1:8r+l4bNWjRlsFYlQJnKJ2p7s1YQPj4XyXiJVqDHRx7c= k8s.io/utils v0.0.0-20190308190857-21c4ce38f2a7/go.mod h1:8k8uAuAQ0rXslZKaEWd0c3oVhZz7sSzSiPnVZayjIX0= +k8s.io/utils v0.0.0-20190520173318-324c5df7d3f0/go.mod h1:sZAwmy6armz5eXlNoLmJcl4F1QuKu7sr+mFQ0byX7Ew= layeh.com/radius v0.0.0-20190322222518-890bc1058917 h1:BDXFaFzUt5EIqe/4wrTc4AcYZWP6iC6Ult+jQWLh5eU= layeh.com/radius v0.0.0-20190322222518-890bc1058917/go.mod h1:fywZKyu//X7iRzaxLgPWsvc0L26IUpVvE/aeIL2JtIQ= +sigs.k8s.io/structured-merge-diff v0.0.0-20190426204423-ea680f03cc65/go.mod h1:wWxsB5ozmmv/SG7nM11ayaAW51xMvak/t1r0CSlcokI= +sigs.k8s.io/structured-merge-diff v0.0.0-20190521201008-1c46bef2e9c8/go.mod h1:wWxsB5ozmmv/SG7nM11ayaAW51xMvak/t1r0CSlcokI= sigs.k8s.io/yaml v1.1.0 h1:4A07+ZFc2wgJwo8YNlQpr1rVlgUDlxXHhPJciaPY5gs= sigs.k8s.io/yaml v1.1.0/go.mod h1:UJmg0vDUVViEyp3mgSv9WPwZCDxu4rQW1olrI1uml+o= From 0a3df1b2f325bc43336b3b00d89c75ee027721ca Mon Sep 17 00:00:00 2001 From: Asim Aslam Date: Thu, 23 May 2019 00:35:02 +0100 Subject: [PATCH 194/196] Update README.md --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 708ae895..1c689389 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,6 @@ # Go Micro [![License](https://img.shields.io/:license-apache-blue.svg)](https://opensource.org/licenses/Apache-2.0) [![GoDoc](https://godoc.org/github.com/micro/go-micro?status.svg)](https://godoc.org/github.com/micro/go-micro) [![Travis CI](https://api.travis-ci.org/micro/go-micro.svg?branch=master)](https://travis-ci.org/micro/go-micro) [![Go Report Card](https://goreportcard.com/badge/micro/go-micro)](https://goreportcard.com/report/github.com/micro/go-micro) -Go Micro is a framework for micro service development. +Go Micro is a framework for microservice development. ## Overview From fac42bc1a91492eb9e4ddf0a5344a667d3e76b72 Mon Sep 17 00:00:00 2001 From: shu xian Date: Fri, 24 May 2019 20:06:27 +0800 Subject: [PATCH 195/196] add AutoAck support for Server --- server/handler.go | 12 ++++++++++++ server/rpc_server.go | 6 ++++++ server/subscriber.go | 5 ++++- 3 files changed, 22 insertions(+), 1 deletion(-) diff --git a/server/handler.go b/server/handler.go index ffa0865d..8236c355 100644 --- a/server/handler.go +++ b/server/handler.go @@ -12,6 +12,9 @@ type HandlerOptions struct { type SubscriberOption func(*SubscriberOptions) type SubscriberOptions struct { + // AutoAck defaults to true. When a handler returns + // with a nil error the message is acked. + AutoAck bool Queue string Internal bool Context context.Context @@ -43,6 +46,7 @@ func InternalSubscriber(b bool) SubscriberOption { } func NewSubscriberOptions(opts ...SubscriberOption) SubscriberOptions { opt := SubscriberOptions{ + AutoAck: true, Context: context.Background(), } @@ -53,6 +57,14 @@ func NewSubscriberOptions(opts ...SubscriberOption) SubscriberOptions { return opt } +// DisableAutoAck will disable auto acking of messages +// after they have been handled. +func DisableAutoAck() SubscriberOption { + return func(o *SubscriberOptions) { + o.AutoAck = false + } +} + // Shared queue name distributed messages across subscribers func SubscriberQueue(n string) SubscriberOption { return func(o *SubscriberOptions) { diff --git a/server/rpc_server.go b/server/rpc_server.go index 4f1049c1..b4924846 100644 --- a/server/rpc_server.go +++ b/server/rpc_server.go @@ -365,9 +365,15 @@ func (s *rpcServer) Register() error { if queue := sb.Options().Queue; len(queue) > 0 { opts = append(opts, broker.Queue(queue)) } + if cx := sb.Options().Context; cx != nil { opts = append(opts, broker.SubscribeContext(cx)) } + + if !sb.Options().AutoAck { + opts = append(opts, broker.DisableAutoAck()) + } + sub, err := config.Broker.Subscribe(sb.Topic(), handler, opts...) if err != nil { return err diff --git a/server/subscriber.go b/server/subscriber.go index a02bc222..b9a50a7b 100644 --- a/server/subscriber.go +++ b/server/subscriber.go @@ -34,7 +34,10 @@ type subscriber struct { } func newSubscriber(topic string, sub interface{}, opts ...SubscriberOption) Subscriber { - var options SubscriberOptions + options := SubscriberOptions{ + AutoAck: true, + } + for _, o := range opts { o(&options) } From f5d37d92af5512a2d567293c14055106da925d59 Mon Sep 17 00:00:00 2001 From: Asim Aslam Date: Fri, 24 May 2019 17:05:31 +0100 Subject: [PATCH 196/196] set nextprotos --- transport/http_transport.go | 1 + 1 file changed, 1 insertion(+) diff --git a/transport/http_transport.go b/transport/http_transport.go index 3aed66be..f72ed8cd 100644 --- a/transport/http_transport.go +++ b/transport/http_transport.go @@ -444,6 +444,7 @@ func (h *httpTransport) Dial(addr string, opts ...DialOption) (Client, error) { InsecureSkipVerify: true, } } + config.NextProtos = []string{"http/1.1"} conn, err = newConn(func(addr string) (net.Conn, error) { return tls.DialWithDialer(&net.Dialer{Timeout: dopts.Timeout}, "tcp", addr, config) })(addr)